Skip to content

Commit

Permalink
feat: Add slot for custom controls in absolute range date picker (#531)
Browse files Browse the repository at this point in the history
  • Loading branch information
just-boris authored and taheramr committed Dec 1, 2022
1 parent c483bae commit 5f68a82
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 80 deletions.
17 changes: 12 additions & 5 deletions pages/date-range-picker/calendar-permutations.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,26 @@ const intervals = [
['2021-05-10', '2021-05-30'],
];

const permutations = createPermutations<DateRangePickerCalendarProps>(
intervals.map(([startDate, endDate]) => ({
const permutations = createPermutations<DateRangePickerCalendarProps>([
...intervals.map(([startDate, endDate]) => ({
value: [{ start: { date: startDate, time: '' }, end: { date: endDate, time: '' } }],
setValue: [() => {}],
locale: ['en-GB'],
startOfWeek: [1],
isDateEnabled: [() => true],
onChange: [() => {}],
timeInputFormat: ['hh:mm:ss'],
timeInputFormat: ['hh:mm:ss'] as const,
i18nStrings: [i18nStrings],
dateOnly: [false, true],
}))
);
customAbsoluteRangeControl: [undefined],
})),
{
value: [{ start: { date: '', time: '' }, end: { date: '', time: '' } }],
setValue: [() => {}],
i18nStrings: [i18nStrings],
customAbsoluteRangeControl: [() => 'Custom control'],
},
]);

export default function DateRangePickerCalendarPage() {
let i = -1;
Expand Down
86 changes: 86 additions & 0 deletions pages/date-range-picker/custom-control.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useState } from 'react';
import startOfWeek from 'date-fns/startOfWeek';
import endOfWeek from 'date-fns/endOfWeek';
import startOfMonth from 'date-fns/startOfMonth';
import endOfMonth from 'date-fns/endOfMonth';
import enLocale from 'date-fns/locale/en-GB';
import { Box, DateRangePicker, DateRangePickerProps, Link, FormField } from '~components';
import { i18nStrings, isValid } from './common';
import { formatDate } from '~components/internal/utils/date-time';

export default function DatePickerScenario() {
const [value, setValue] = useState<DateRangePickerProps['value']>(null);

return (
<Box padding="s">
<h1>Date range picker with custom control</h1>
<FormField label="Date Range Picker field">
<DateRangePicker
value={value}
onChange={e => setValue(e.detail.value)}
locale={enLocale.code}
i18nStrings={i18nStrings}
relativeOptions={[]}
placeholder="Filter by a date and time range"
isValidRange={isValid}
rangeSelectorMode="absolute-only"
customAbsoluteRangeControl={(selectedDate, setSelectedDate) => (
<>
Auto-select:{' '}
<Link
onFollow={() => {
const today = formatDate(new Date());
return setSelectedDate({
start: { date: today, time: '' },
end: { date: today, time: '' },
});
}}
>
1D
</Link>{' '}
<Link
variant="secondary"
onFollow={() =>
setSelectedDate({
start: {
date: formatDate(startOfWeek(new Date(), { locale: enLocale })),
time: '',
},
end: {
date: formatDate(endOfWeek(new Date(), { locale: enLocale })),
time: '',
},
})
}
>
7D
</Link>{' '}
<Link
onFollow={() =>
setSelectedDate({
start: { date: formatDate(startOfMonth(new Date())), time: '' },
end: { date: formatDate(endOfMonth(new Date())), time: '' },
})
}
>
1M
</Link>{' '}
<Link
onFollow={() =>
setSelectedDate({
start: { date: '', time: '' },
end: { date: '', time: '' },
})
}
>
None
</Link>
</>
)}
/>
</FormField>
</Box>
);
}
1 change: 1 addition & 0 deletions pages/date-range-picker/range-calendar.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function RangeCalendarScenario() {
dateOnly={dateOnly}
timeInputFormat="hh:mm"
isDateEnabled={date => date.getDate() !== 15}
customAbsoluteRangeControl={undefined}
/>

<Link id="focusable-after">Focusable element after the range calendar</Link>
Expand Down
21 changes: 21 additions & 0 deletions src/__tests__/__snapshots__/documenter.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4843,6 +4843,27 @@ is provided by its parent form field component.
"optional": true,
"type": "string",
},
Object {
"description": "Specifies an additional control displayed in the dropdown, located below the range calendar.",
"inlineType": Object {
"name": "DateRangePickerProps.AbsoluteRangeControl",
"parameters": Array [
Object {
"name": "selectedRange",
"type": "DateRangePickerProps.PendingAbsoluteValue",
},
Object {
"name": "setSelectedRange",
"type": "React.Dispatch<React.SetStateAction<DateRangePickerProps.PendingAbsoluteValue>>",
},
],
"returnType": "React.ReactNode",
"type": "function",
},
"name": "customAbsoluteRangeControl",
"optional": true,
"type": "DateRangePickerProps.AbsoluteRangeControl",
},
Object {
"defaultValue": "false",
"description": "Hides time inputs and changes the input format to date-only, e.g. 2021-04-06.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,5 +469,72 @@ describe('Date range picker', () => {
);
});
});

describe('custom control', () => {
const customControl: DateRangePickerProps.AbsoluteRangeControl = (value, setValue) => (
<>
<div data-testid="display">{JSON.stringify(value)}</div>
<button
data-testid="set-date"
onClick={() =>
setValue({
start: { date: '2022-01-02', time: '00:00:00' },
end: { date: '2022-02-06', time: '12:34:56' },
})
}
></button>
<button
data-testid="clear-date"
onClick={() => setValue({ start: { date: '', time: '' }, end: { date: '', time: '' } })}
></button>
</>
);
test('renders current value from calendar', () => {
const { wrapper, getByTestId } = renderDateRangePicker({
...defaultProps,
value: { type: 'absolute', startDate: '2022-11-24T12:55:00', endDate: '2022-11-28T11:14:00' },
customAbsoluteRangeControl: customControl,
});
act(() => wrapper.findTrigger().click());
expect(getByTestId('display')).toHaveTextContent(
'{"start":{"date":"2022-11-24","time":"12:55:00"},"end":{"date":"2022-11-28","time":"11:14:00"}}'
);
});

test('can update value in calendar', () => {
const { wrapper, getByTestId } = renderDateRangePicker({
...defaultProps,
customAbsoluteRangeControl: customControl,
});
act(() => wrapper.findTrigger().click());
getByTestId('set-date').click();
expect(getByTestId('display')).toHaveTextContent(
'{"start":{"date":"2022-01-02","time":"00:00:00"},"end":{"date":"2022-02-06","time":"12:34:56"}}'
);
expect(wrapper.findDropdown()!.findSelectedStartDate()!.getElement()).toHaveTextContent('2');
expect(wrapper.findDropdown()!.findStartDateInput()!.findNativeInput().getElement()).toHaveValue('2022/01/02');
expect(wrapper.findDropdown()!.findStartTimeInput()!.findNativeInput().getElement()).toHaveValue('00:00:00');
expect(wrapper.findDropdown()!.findSelectedEndDate()!.getElement()).toHaveTextContent('6');
expect(wrapper.findDropdown()!.findEndDateInput()!.findNativeInput().getElement()).toHaveValue('2022/02/06');
expect(wrapper.findDropdown()!.findEndTimeInput()!.findNativeInput().getElement()).toHaveValue('12:34:56');
});

test('can clear value in calendar', () => {
const { wrapper, getByTestId } = renderDateRangePicker({
...defaultProps,
value: { type: 'absolute', startDate: '2022-11-24T12:55:00', endDate: '2022-11-28T11:14:00' },
customAbsoluteRangeControl: customControl,
});
act(() => wrapper.findTrigger().click());
getByTestId('clear-date').click();
expect(getByTestId('display')).toHaveTextContent('{"start":{"date":"","time":""},"end":{"date":"","time":""}}');
expect(wrapper.findDropdown()!.findSelectedStartDate()).toBeNull();
expect(wrapper.findDropdown()!.findStartDateInput()!.findNativeInput().getElement()).toHaveValue('');
expect(wrapper.findDropdown()!.findStartTimeInput()!.findNativeInput().getElement()).toHaveValue('');
expect(wrapper.findDropdown()!.findSelectedEndDate()).toBeNull();
expect(wrapper.findDropdown()!.findEndDateInput()!.findNativeInput().getElement()).toHaveValue('');
expect(wrapper.findDropdown()!.findEndTimeInput()!.findNativeInput().getElement()).toHaveValue('');
});
});
});
});
Loading

0 comments on commit 5f68a82

Please sign in to comment.