Skip to content

Commit

Permalink
[@mantine/core] Add range type to DateTimePicker
Browse files Browse the repository at this point in the history
  • Loading branch information
wuifdesign committed Oct 19, 2023
1 parent 77635df commit 20d11db
Show file tree
Hide file tree
Showing 9 changed files with 417 additions and 200 deletions.
6 changes: 6 additions & 0 deletions docs/pages/dates/date-time-picker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ read through [DatePicker](/dates/date-picker/) documentation to learn about all

<Demo data={DateTimePickerDemos.withSeconds} />

## Dates range

Set `type="range"` to allow user to pick dates range:

<Demo data={DateTimePickerDemos.range} />

## Value format

Use `valueFormat` prop to change [dayjs format](https://day.js.org/docs/en/display/format) of value label:
Expand Down
5 changes: 5 additions & 0 deletions src/mantine-dates/src/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export interface DatePickerBaseProps<Type extends DatePickerType = 'default'>
/** Current level displayed to the user (decade, year, month), used for controlled component */
level?: CalendarLevel;

/** Allow same day for range selects */
allowSameDay?: boolean;

/** Called when level changes */
onLevelChange?: (level: CalendarLevel) => void;
}
Expand Down Expand Up @@ -67,6 +70,7 @@ export const DatePicker: DatePickerComponent = factory<DatePickerFactory>((_prop
const {
classNames,
styles,
allowSameDay,
vars,
type,
defaultValue,
Expand All @@ -88,6 +92,7 @@ export const DatePicker: DatePickerComponent = factory<DatePickerFactory>((_prop
const { onDateChange, onRootMouseLeave, onHoveredDateChange, getControlProps } = useDatesState({
type: type as any,
level: 'day',
allowSameDay,
allowDeselect,
allowSingleDateInRange,
value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ export function WithSeconds() {
);
}

export function Range() {
return (
<div style={{ padding: 40, maxWidth: 400 }}>
<DateTimePicker placeholder="Date time picker" withSeconds type="range" />
</div>
);
}

export function MinDate() {
return (
<div style={{ padding: 40, maxWidth: 400 }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { DateTimePicker, DateTimePickerProps } from './DateTimePicker';
import { DatesProvider } from '../DatesProvider';

const defaultProps: DateTimePickerProps = {
const defaultProps = {
popoverProps: { withinPortal: false, transitionProps: { duration: 0 } },
modalProps: { withinPortal: false, transitionProps: { duration: 0 } },
timeInputProps: { 'aria-label': 'test-time-input' },
Expand All @@ -44,6 +44,7 @@ const defaultPropsWithInputProps: DateTimePickerProps = {
};

const getTimeInput = () => screen.getByLabelText('test-time-input');
const getTimeInputs = () => screen.getAllByLabelText('test-time-input');
const getSubmitButton = () => screen.getByLabelText('test-submit');
const getClearButton = () => screen.queryAllByLabelText('test-clear')[0];

Expand Down Expand Up @@ -182,6 +183,32 @@ describe('@mantine/dates/DateTimePicker', () => {
expectValue(container, '03/04/2022 14:45');
});

it('supports uncontrolled state with range', async () => {
const { container } = render(
<DateTimePicker
{...defaultProps}
defaultValue={[new Date(2022, 3, 11), new Date(2022, 3, 12)]}
type="range"
/>
);
expectValue(container, '11/04/2022 00:00 – 12/04/2022 00:00');

await clickInput(container);
await userEvent.click(container.querySelectorAll('table button')[6]);
expectValue(container, '03/04/2022 00:00 – ');

await userEvent.click(container.querySelectorAll('table button')[7]);
expectValue(container, '03/04/2022 00:00 – 04/04/2022 00:00');

await userEvent.clear(getTimeInputs()[0]);
await userEvent.type(getTimeInputs()[0], '14:45');
expectValue(container, '03/04/2022 14:45 – 04/04/2022 00:00');

await userEvent.clear(getTimeInputs()[1]);
await userEvent.type(getTimeInputs()[1], '12:35');
expectValue(container, '03/04/2022 14:45 – 04/04/2022 12:35');
});

it('supports uncontrolled state with timezone', async () => {
const { container } = render(
<DatesProvider settings={{ timezone: 'UTC' }}>
Expand Down Expand Up @@ -212,6 +239,24 @@ describe('@mantine/dates/DateTimePicker', () => {
expect(spy).toHaveBeenLastCalledWith(new Date(2022, 3, 3));
});

it('supports controlled state with range', async () => {
const spy = jest.fn();
const { container } = render(
<DateTimePicker
{...defaultProps}
value={[new Date(2022, 3, 11), new Date(2022, 3, 12)]}
onChange={spy}
type="range"
/>
);
expectValue(container, '11/04/2022 00:00 – 12/04/2022 00:00');

await clickInput(container);
await userEvent.click(container.querySelectorAll('table button')[6]);
expectValue(container, '11/04/2022 00:00 – 12/04/2022 00:00');
expect(spy).toHaveBeenLastCalledWith([new Date(2022, 3, 3), null]);
});

it('supports controlled state with timezone', async () => {
const spy = jest.fn();

Expand Down

0 comments on commit 20d11db

Please sign in to comment.