Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat): Enhancements to the OpenmrsDatePicker #1062

Merged
merged 15 commits into from
Jul 5, 2024
Merged
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
Loading