Skip to content

Commit

Permalink
(feat): Enhancements to the OpenmrsDatePicker (#1062)
Browse files Browse the repository at this point in the history
Co-authored-by: Ian <[email protected]>
  • Loading branch information
NethmiRodrigo and ibacher authored Jul 5, 2024
1 parent d98a188 commit e450bab
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 56 deletions.
4 changes: 2 additions & 2 deletions packages/framework/esm-framework/docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ A type for any of the acceptable date formats

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:48](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L48)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:56](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L56)

___

Expand Down Expand Up @@ -1571,7 +1571,7 @@ A date picker component to select a single date. Based on React Aria, but styled

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:260](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L260)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:247](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L247)

___

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Properties for the OpenmrsDatePicker
- [hideTimeZone](OpenmrsDatePickerProps.md#hidetimezone)
- [hourCycle](OpenmrsDatePickerProps.md#hourcycle)
- [id](OpenmrsDatePickerProps.md#id)
- [invalid](OpenmrsDatePickerProps.md#invalid)
- [invalidText](OpenmrsDatePickerProps.md#invalidtext)
- [isDisabled](OpenmrsDatePickerProps.md#isdisabled)
- [isInvalid](OpenmrsDatePickerProps.md#isinvalid)
- [isOpen](OpenmrsDatePickerProps.md#isopen)
Expand Down Expand Up @@ -169,7 +171,7 @@ Any CSS classes to add to the outer div of the date picker

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:68](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L68)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:74](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L74)

___

Expand Down Expand Up @@ -197,7 +199,7 @@ The default value (uncontrolled)

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:72](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L72)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:76](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L76)

___

Expand Down Expand Up @@ -267,6 +269,30 @@ node_modules/@react-types/shared/src/dom.d.ts:62

___

### invalid

`Optional` **invalid**: `boolean`

Whether the input value is invalid.

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:78](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L78)

___

### invalidText

`Optional` **invalidText**: `string`

Text to show if the input is invalid e.g. an error message

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:80](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L80)

___

### isDisabled

`Optional` **isDisabled**: `boolean`
Expand Down Expand Up @@ -357,19 +383,19 @@ The label for this DatePicker element

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:77](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L77)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:85](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L85)

___

### labelText

`Optional` **labelText**: `string` \| `ReactElement`<`any`, `string` \| `JSXElementConstructor`<`any`\>\>

The label for this DatePicker element
The label for this DatePicker element.

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:81](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L81)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:87](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L87)

___

Expand All @@ -381,7 +407,7 @@ ___

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:85](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L85)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:89](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L89)

___

Expand All @@ -393,7 +419,7 @@ The latest date it is possible to select

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:89](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L89)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:91](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L91)

___

Expand Down Expand Up @@ -499,7 +525,7 @@ ___

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:101](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L101)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:97](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L97)

___

Expand Down Expand Up @@ -542,11 +568,11 @@ ___

`Optional` **size**: ``"sm"`` \| ``"md"`` \| ``"lg"``

Specifies the size of the input. Currently supports either `sm`, `md`, or `lg` as an option.
Specifies the size of the input. Currently supports either `sm`, `md`, or `lg` as an option

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:97](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L97)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:95](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L95)

___

Expand Down Expand Up @@ -611,7 +637,7 @@ The value (controlled)

#### Defined in

[packages/framework/esm-styleguide/src/datepicker/index.tsx:105](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L105)
[packages/framework/esm-styleguide/src/datepicker/index.tsx:99](https://github.com/openmrs/openmrs-esm-core/blob/main/packages/framework/esm-styleguide/src/datepicker/index.tsx#L99)

## Methods

Expand Down
2 changes: 1 addition & 1 deletion packages/framework/esm-styleguide/src/_overrides.scss
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,6 @@ html[dir='rtl'] {
color: #0f62fe;
}

svg.omrs-icon {
.omrs-icon {
fill: var(--omrs-icon-fill, 'currentColor');
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@use '@carbon/styles/scss/utilities/box-shadow';
@use '@carbon/styles/scss/utilities/component-reset';
@use '@carbon/styles/scss/utilities/focus-outline' as focus;
@use '@openmrs/esm-styleguide/src/vars' as *;

.calendarGrid {
width: 17rem;
Expand Down Expand Up @@ -34,10 +35,15 @@
outline: unset;
}

&:hover:not(:has([aria-disabled='true'])) {
&:hover:not(:has([aria-disabled], [data-selected])) {
background-color: theme.$layer-hover;
}

&:has([data-selected]) {
background-color: $color-blue-60-2;
color: $ui-background;
}

[aria-disabled] {
color: theme.$text-disabled;
cursor: default;
Expand Down Expand Up @@ -68,6 +74,10 @@
}
}

[data-invalid] > .flatButton > svg {
--omrs-icon-fill: #{theme.$support-error};
}

.flatButtonMd {
height: spacing.$spacing-08;
width: spacing.$spacing-08;
Expand Down Expand Up @@ -291,3 +301,39 @@
}
}
}

.invalidText {
color: theme.$text-error !important;
font-size: 0.75rem;
font-weight: 400 !important;
margin: spacing.$spacing-02 0 0;
overflow: hidden;
}

.today:not([data-selected]) {
position: relative;
color: $color-blue-60-2;
font-weight: 600;
font-size: var(--cds-body-compact-01-font-size, 0.875rem);
line-height: var(--cds-body-compact-01-line-height, 1.28572);
letter-spacing: var(--cds-body-compact-01-letter-spacing, 0.16px);
display: flex;
align-items: center;
justify-content: center;
block-size: 2.5rem;
cursor: pointer;
inline-size: 2.5rem;

&::after {
position: absolute;
display: block;
background-color: var(--cds-link-primary, #0f62fe);
block-size: 0.25rem;
content: '';
inline-size: 0.25rem;
inset-block-end: 0.4375rem;
inset-inline-start: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
}
81 changes: 41 additions & 40 deletions packages/framework/esm-styleguide/src/datepicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import React, {
useRef,
} from 'react';
import classNames, { type Argument } from 'classnames';
import { createCalendar, CalendarDate, CalendarDateTime, ZonedDateTime } from '@internationalized/date';
import {
createCalendar,
CalendarDate,
CalendarDateTime,
ZonedDateTime,
today,
getLocalTimeZone,
} from '@internationalized/date';
import { I18nProvider, type DateValue, useLocale, useDateField } from 'react-aria';
import { useDateFieldState } from 'react-stately';
import {
Expand All @@ -38,6 +45,7 @@ import {
InputContext,
Provider,
GroupContext,
FieldError,
} from 'react-aria-components';
import dayjs, { type Dayjs } from 'dayjs';
import { formatDate, getDefaultCalendar, getLocale } from '@openmrs/esm-utils';
Expand All @@ -62,46 +70,32 @@ export type DateInputValue =
export interface OpenmrsDatePickerProps
// omits here for features we have custom implementations of
extends Omit<DatePickerProps<CalendarDate>, 'className' | 'defaultValue' | 'value'> {
/**
* Any CSS classes to add to the outer div of the date picker
*/
/** Any CSS classes to add to the outer div of the date picker */
className?: Argument;
/**
* The default value (uncontrolled)
*/
/** The default value (uncontrolled) */
defaultValue?: DateInputValue;
/** Whether the input value is invalid. */
invalid?: boolean;
/** Text to show if the input is invalid e.g. an error message */
invalidText?: string;
/**
* The label for this DatePicker element
* @deprecated Use labelText instead
*/
label?: string | ReactElement;
/**
* The label for this DatePicker element
*/
/** The label for this DatePicker element. */
labelText?: string | ReactElement;
/**
* 'true' to use the light version.
*/
/** 'true' to use the light version. */
light?: boolean;
/**
* The latest date it is possible to select
*/
/** The latest date it is possible to select */
maxDate?: DateInputValue;
/**
* The earliest date it is possible to select
*/
/** The earliest date it is possible to select */
minDate?: DateInputValue;
/**
* Specifies the size of the input. Currently supports either `sm`, `md`, or `lg` as an option.
*/
/** Specifies the size of the input. Currently supports either `sm`, `md`, or `lg` as an option */
size?: 'sm' | 'md' | 'lg';
/**
* 'true' to use the short version.
*/
/** 'true' to use the short version. */
short?: boolean;
/**
* The value (controlled)
*/
/** The value (controlled) */
value?: DateInputValue;
}

Expand Down Expand Up @@ -196,13 +190,10 @@ const MonthYear = forwardRef<Element, PropsWithChildren<HTMLAttributes<HTMLSpanE
},
);

const DatePickerIcon = forwardRef<Element>(function DatePickerIcon(props, ref) {
const DatePickerIcon = forwardRef<SVGSVGElement>(function DatePickerIcon(props, ref) {
const state = useContext(DatePickerStateContext);
return state.isInvalid ? (
<WarningIcon className="cds--date-picker__icon--invalid" size={16} />
) : (
<CalendarIcon size={16} />
);

return state.isInvalid ? <WarningIcon ref={ref} size={16} /> : <CalendarIcon ref={ref} size={16} />;
});

// The main reason for this component is to allow us to click inside the date field and trigger the popover
Expand Down Expand Up @@ -247,11 +238,7 @@ function DatePickerLabel({ labelText }: Pick<OpenmrsDatePickerProps, 'labelText'
return null;
}

if (typeof labelText === 'string' || typeof labelText === 'number') {
return <Label className="cds--label">{labelText}</Label>;
}

return cloneElement(labelText, { className: classNames(labelText.props?.className, 'cds--label') });
return <Label className="cds--label">{labelText}</Label>;
}

/**
Expand All @@ -262,6 +249,9 @@ export const OpenmrsDatePicker = forwardRef<HTMLDivElement, OpenmrsDatePickerPro
const {
className,
defaultValue: rawDefaultValue,
invalid,
invalidText,
isInvalid: isInvalidRaw,
label,
labelText,
light,
Expand All @@ -277,8 +267,10 @@ export const OpenmrsDatePicker = forwardRef<HTMLDivElement, OpenmrsDatePickerPro
const value = useMemo(() => dateToInternationalizedDate(rawValue), [rawValue]);
const maxDate = useMemo(() => dateToInternationalizedDate(rawMaxDate), [rawMaxDate]);
const minDate = useMemo(() => dateToInternationalizedDate(rawMinDate), [rawMinDate]);
const isInvalid = useMemo(() => invalid ?? isInvalidRaw, [invalid, isInvalidRaw]);

const locale = getLocale();
const today_ = today(getLocalTimeZone());

const localeWithCalendar = useMemo(() => {
const calendar = getDefaultCalendar(locale);
Expand All @@ -298,6 +290,7 @@ export const OpenmrsDatePicker = forwardRef<HTMLDivElement, OpenmrsDatePickerPro
['cds--date-picker--light']: light,
})}
defaultValue={defaultValue}
isInvalid={isInvalid}
maxValue={maxDate}
minValue={minDate}
value={value}
Expand All @@ -324,6 +317,7 @@ export const OpenmrsDatePicker = forwardRef<HTMLDivElement, OpenmrsDatePickerPro
<DatePickerIcon />
</Button>
</Group>
{isInvalid && invalidText && <FieldError className={styles.invalidText}>{invalidText}</FieldError>}
</div>
<Popover className={styles.popover} placement="bottom" offset={1}>
<Dialog className={styles.dialog}>
Expand All @@ -338,7 +332,14 @@ export const OpenmrsDatePicker = forwardRef<HTMLDivElement, OpenmrsDatePickerPro
</Button>
</header>
<CalendarGrid className={styles.calendarGrid}>
{(date) => <CalendarCell className="cds--date-picker__day" date={date} />}
{(date) => (
<CalendarCell
className={classNames('cds--date-picker__day', {
[styles.today]: today_.compare(date) === 0,
})}
date={date}
/>
)}
</CalendarGrid>
</Calendar>
</Dialog>
Expand Down
Loading

0 comments on commit e450bab

Please sign in to comment.