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 { .woocommerce-date-time-picker-control__input-control__suffix {
padding-right: 8px; padding-right: 8px;
} }
.components-datetime__date {
border-top: 0;
}
} }

View File

@ -6,7 +6,6 @@ import {
useState, useState,
useEffect, useEffect,
useLayoutEffect, useLayoutEffect,
useCallback,
useRef, useRef,
} from '@wordpress/element'; } from '@wordpress/element';
import { Icon, calendar } from '@wordpress/icons'; import { Icon, calendar } from '@wordpress/icons';
@ -16,12 +15,14 @@ import { sprintf, __ } from '@wordpress/i18n';
import { useDebounce, useInstanceId } from '@wordpress/compose'; import { useDebounce, useInstanceId } from '@wordpress/compose';
import { import {
BaseControl, BaseControl,
Dropdown, DatePicker,
DateTimePicker as WpDateTimePicker, DateTimePicker as WpDateTimePicker,
Dropdown,
// @ts-expect-error `__experimentalInputControl` does exist. // @ts-expect-error `__experimentalInputControl` does exist.
__experimentalInputControl as InputControl, __experimentalInputControl as InputControl,
} from '@wordpress/components'; } from '@wordpress/components';
export const defaultDateFormat = 'MM/DD/YYYY';
export const default12HourDateTimeFormat = 'MM/DD/YYYY h:mm a'; export const default12HourDateTimeFormat = 'MM/DD/YYYY h:mm a';
export const default24HourDateTimeFormat = 'MM/DD/YYYY H:mm'; export const default24HourDateTimeFormat = 'MM/DD/YYYY H:mm';
@ -34,7 +35,8 @@ export type DateTimePickerControlProps = {
currentDate?: string | null; currentDate?: string | null;
dateTimeFormat?: string; dateTimeFormat?: string;
disabled?: boolean; disabled?: boolean;
is12Hour?: boolean; isDateOnlyPicker?: boolean;
is12HourPicker?: boolean;
onChange?: DateTimePickerControlOnChangeHandler; onChange?: DateTimePickerControlOnChangeHandler;
onBlur?: () => void; onBlur?: () => void;
label?: string; label?: string;
@ -45,10 +47,9 @@ export type DateTimePickerControlProps = {
export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( { export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
currentDate, currentDate,
is12Hour = true, isDateOnlyPicker = false,
dateTimeFormat = is12Hour is12HourPicker = true,
? default12HourDateTimeFormat dateTimeFormat,
: default24HourDateTimeFormat,
disabled = false, disabled = false,
onChange, onChange,
onBlur, onBlur,
@ -75,6 +76,22 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
null null
); );
const displayFormat = ( () => {
if ( dateTimeFormat ) {
return dateTimeFormat;
}
if ( isDateOnlyPicker ) {
return defaultDateFormat;
}
if ( is12HourPicker ) {
return default12HourDateTimeFormat;
}
return default24HourDateTimeFormat;
} )();
function parseMomentIso( function parseMomentIso(
dateString?: string | null, dateString?: string | null,
assumeLocalTime = false assumeLocalTime = false
@ -88,7 +105,7 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
function parseMoment( dateString?: string | null ): Moment { function parseMoment( dateString?: string | null ): Moment {
// parse input date string as local time // parse input date string as local time
return moment( dateString, dateTimeFormat ); return moment( dateString, displayFormat );
} }
function formatMomentIso( momentDate: Moment ): string { function formatMomentIso( momentDate: Moment ): string {
@ -96,7 +113,7 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
} }
function formatMoment( momentDate: Moment ): string { function formatMoment( momentDate: Moment ): string {
return momentDate.local().format( dateTimeFormat ); return momentDate.local().format( displayFormat );
} }
function hasFocusLeftInputAndDropdownContent( function hasFocusLeftInputAndDropdownContent(
@ -211,7 +228,7 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
} else { } else {
changeImmediate( currentDate || '', fireOnChange ); changeImmediate( currentDate || '', fireOnChange );
} }
}, [ currentDate, dateTimeFormat ] ); }, [ currentDate, displayFormat ] );
return ( return (
<Dropdown <Dropdown
@ -272,23 +289,27 @@ export const DateTimePickerControl: React.FC< DateTimePickerControlProps > = ( {
/> />
</BaseControl> </BaseControl>
) } ) }
renderContent={ () => ( renderContent={ () => {
<WpDateTimePicker const Picker = isDateOnlyPicker ? DatePicker : WpDateTimePicker;
currentDate={
lastValidDate return (
? formatMomentIso( lastValidDate ) <Picker
: undefined currentDate={
} lastValidDate
onChange={ ( date: string ) => { ? formatMomentIso( lastValidDate )
// the picker returns the date in local time : undefined
const formattedDate = formatMoment( }
parseMomentIso( date, true ) onChange={ ( date: string ) => {
); // the picker returns the date in local time
changeImmediate( formattedDate, true ); const formattedDate = formatMoment(
} } parseMomentIso( date, true )
is12Hour={ is12Hour } );
/> changeImmediate( formattedDate, true );
) } } }
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( const { container } = render(
<DateTimePickerControl <DateTimePickerControl
currentDate={ dateTime.toISOString() } currentDate={ dateTime.toISOString() }
is12Hour={ false } is12HourPicker={ false }
/> />
); );
@ -112,7 +112,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render( const { container } = render(
<DateTimePickerControl <DateTimePickerControl
currentDate={ ambiguousISODateTimeString } currentDate={ ambiguousISODateTimeString }
is12Hour={ false } is12HourPicker={ false }
/> />
); );
@ -132,7 +132,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render( const { container } = render(
<DateTimePickerControl <DateTimePickerControl
currentDate={ unambiguousISODateTimeString } currentDate={ unambiguousISODateTimeString }
is12Hour={ false } is12HourPicker={ false }
/> />
); );
@ -152,7 +152,7 @@ describe( 'DateTimePickerControl', () => {
const { container } = render( const { container } = render(
<DateTimePickerControl <DateTimePickerControl
currentDate={ dateTime.toISOString() } currentDate={ dateTime.toISOString() }
is12Hour={ true } is12HourPicker={ true }
/> />
); );
@ -184,14 +184,14 @@ describe( 'DateTimePickerControl', () => {
const { container, rerender } = render( const { container, rerender } = render(
<DateTimePickerControl <DateTimePickerControl
currentDate={ originalDateTime.toISOString() } currentDate={ originalDateTime.toISOString() }
is12Hour={ false } is12HourPicker={ false }
/> />
); );
rerender( rerender(
<DateTimePickerControl <DateTimePickerControl
currentDate={ updatedDateTime.toISOString() } 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( const { container } = render(
<DateTimePickerControl is12Hour={ true } /> <DateTimePickerControl is12HourPicker={ true } />
); );
const input = container.querySelector( 'input' ); 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 () => { it( 'should call onBlur when losing focus', async () => {
const onBlurHandler = jest.fn(); const onBlurHandler = jest.fn();