Add date-only mode to DateTimePickerControl (#35066)

* Remove border from top of date picker
* Add isDateOnlyPicker, rename is12HourPicker
* Add tests for isDateOnlyPicker
* Add date only story
This commit is contained in:
Matt Sherman 2022-10-14 16:48:03 -04:00 committed by GitHub
parent 8747ea2995
commit e470c62650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 35 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add date-only mode to DateTimePickerControl.

View File

@ -4,4 +4,8 @@
.woocommerce-date-time-picker-control__input-control__suffix {
padding-right: 8px;
}
.components-datetime__date {
border-top: 0;
}
}

View File

@ -6,7 +6,6 @@ import {
useState,
useEffect,
useLayoutEffect,
useCallback,
useRef,
} from '@wordpress/element';
import { Icon, calendar } from '@wordpress/icons';
@ -16,12 +15,14 @@ import { sprintf, __ } from '@wordpress/i18n';
import { useDebounce, useInstanceId } from '@wordpress/compose';
import {
BaseControl,
Dropdown,
DatePicker,
DateTimePicker as WpDateTimePicker,
Dropdown,
// @ts-expect-error `__experimentalInputControl` does exist.
__experimentalInputControl as InputControl,
} from '@wordpress/components';
export const defaultDateFormat = 'MM/DD/YYYY';
export const default12HourDateTimeFormat = 'MM/DD/YYYY h:mm a';
export const default24HourDateTimeFormat = 'MM/DD/YYYY H:mm';
@ -34,7 +35,8 @@ export type DateTimePickerControlProps = {
currentDate?: string | null;
dateTimeFormat?: string;
disabled?: boolean;
is12Hour?: boolean;
isDateOnlyPicker?: boolean;
is12HourPicker?: boolean;
onChange?: DateTimePickerControlOnChangeHandler;
onBlur?: () => void;
label?: string;
@ -45,10 +47,9 @@ export type DateTimePickerControlProps = {
export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
currentDate,
is12Hour = true,
dateTimeFormat = is12Hour
? default12HourDateTimeFormat
: default24HourDateTimeFormat,
isDateOnlyPicker = false,
is12HourPicker = true,
dateTimeFormat,
disabled = false,
onChange,
onBlur,
@ -75,6 +76,22 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
null
);
const displayFormat = ( () => {
if ( dateTimeFormat ) {
return dateTimeFormat;
}
if ( isDateOnlyPicker ) {
return defaultDateFormat;
}
if ( is12HourPicker ) {
return default12HourDateTimeFormat;
}
return default24HourDateTimeFormat;
} )();
function parseMomentIso(
dateString?: string | null,
assumeLocalTime = false
@ -88,7 +105,7 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
function parseMoment( dateString?: string | null ): Moment {
// parse input date string as local time
return moment( dateString, dateTimeFormat );
return moment( dateString, displayFormat );
}
function formatMomentIso( momentDate: Moment ): string {
@ -96,7 +113,7 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
}
function formatMoment( momentDate: Moment ): string {
return momentDate.local().format( dateTimeFormat );
return momentDate.local().format( displayFormat );
}
function hasFocusLeftInputAndDropdownContent(
@ -211,7 +228,7 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
} else {
changeImmediate( currentDate || '', fireOnChange );
}
}, [ currentDate, dateTimeFormat ] );
}, [ currentDate, displayFormat ] );
return (
<Dropdown
@ -272,8 +289,11 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
/>
</BaseControl>
) }
renderContent={ () => (
<WpDateTimePicker
renderContent={ () => {
const Picker = isDateOnlyPicker ? DatePicker : WpDateTimePicker;
return (
<Picker
currentDate={
lastValidDate
? formatMomentIso( lastValidDate )
@ -286,9 +306,10 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
);
changeImmediate( formattedDate, true );
} }
is12Hour={ is12Hour }
is12Hour={ is12HourPicker }
/>
) }
);
} }
/>
);
};

View File

@ -90,3 +90,10 @@ Controlled.decorators = [
);
},
];
export const ControlledDateOnly = Template.bind( {} );
ControlledDateOnly.args = {
...Controlled.args,
isDateOnlyPicker: true,
};
ControlledDateOnly.decorators = Controlled.decorators;

View File

@ -96,7 +96,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render(
<DateTimePickerControl
currentDate={ dateTime.toISOString() }
is12Hour={ false }
is12HourPicker={ false }
/>
);
@ -112,7 +112,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render(
<DateTimePickerControl
currentDate={ ambiguousISODateTimeString }
is12Hour={ false }
is12HourPicker={ false }
/>
);
@ -132,7 +132,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render(
<DateTimePickerControl
currentDate={ unambiguousISODateTimeString }
is12Hour={ false }
is12HourPicker={ false }
/>
);
@ -152,7 +152,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render(
<DateTimePickerControl
currentDate={ dateTime.toISOString() }
is12Hour={ true }
is12HourPicker={ true }
/>
);
@ -184,14 +184,14 @@ describe( 'DateTimePickerControl', () => {
const { container, rerender } = render(
<DateTimePickerControl
currentDate={ originalDateTime.toISOString() }
is12Hour={ false }
is12HourPicker={ false }
/>
);
rerender(
<DateTimePickerControl
currentDate={ updatedDateTime.toISOString() }
is12Hour={ false }
is12HourPicker={ false }
/>
);
@ -229,9 +229,23 @@ describe( 'DateTimePickerControl', () => {
);
} );
it( 'should set the date time picker popup to 12 hour mode', async () => {
it( 'should set the picker popup to date and time by default', async () => {
const { container } = render( <DateTimePickerControl /> );
const input = container.querySelector( 'input' );
userEvent.click( input! );
await waitFor( () =>
expect(
container.querySelector( '.components-datetime' )
).toBeInTheDocument()
);
} );
it( 'should set the picker to 12 hour mode', async () => {
const { container } = render(
<DateTimePickerControl is12Hour={ true } />
<DateTimePickerControl is12HourPicker={ true } />
);
const input = container.querySelector( 'input' );
@ -247,6 +261,25 @@ describe( 'DateTimePickerControl', () => {
);
} );
it( 'should set the picker popup to date only', async () => {
const { container } = render(
<DateTimePickerControl isDateOnlyPicker={ true } />
);
const input = container.querySelector( 'input' );
userEvent.click( input! );
await waitFor( () => {
expect(
container.querySelector( '.components-datetime' )
).not.toBeInTheDocument();
expect(
container.querySelector( '.components-datetime__date' )
).toBeInTheDocument();
} );
} );
it( 'should call onBlur when losing focus', async () => {
const onBlurHandler = jest.fn();