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

[@mantine/dates] DateInput: Separate clearable and allowDeselect logic #4527

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/src/docs/dates/DateInput.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ and must return `Date` object:

<Demo data={DateInputDemos.parser} />

## Allow deselect
## Allow clear

Set `allowDeselect` prop to allow removing value from the input. Input will be cleared if
Set `clearable` prop to allow removing value from the input. Input will be cleared if
user selects the same date in dropdown or clears input value:

<Demo data={DateInputDemos.deselect} />
<Demo data={DateInputDemos.clearable} />

## Min and max date

Expand Down
90 changes: 84 additions & 6 deletions src/mantine-dates/src/components/DateInput/DateInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ describe('@mantine/dates/DateInput', () => {
expect(spy).toHaveBeenLastCalledWith(null);
});

it('allows to clear input value when allowDeselect is set (uncontrolled)', async () => {
it('allows to clear input value when clearable is set (uncontrolled)', async () => {
const { container } = render(
<DateInput {...defaultProps} allowDeselect defaultValue={new Date(2022, 3, 11)} />
<DateInput {...defaultProps} clearable defaultValue={new Date(2022, 3, 11)} />
);

expectValue(container, 'April 11, 2022');
Expand All @@ -223,9 +223,22 @@ describe('@mantine/dates/DateInput', () => {
expectValue(container, '');
});

it('does not allow to clear input value when allowDeselect is not set (uncontrolled)', async () => {
it('allows to clear input value when clearable is set (controlled)', async () => {
const spy = jest.fn();
const { container } = render(
<DateInput {...defaultProps} clearable value={new Date(2022, 3, 11)} onChange={spy} />
);

expectValue(container, 'April 11, 2022');
await userEvent.clear(getInput(container));
await userEvent.tab();
expectValue(container, 'April 11, 2022');
expect(spy).toHaveBeenLastCalledWith(null);
});

it('does not allow to clear input value when clearable is not set (uncontrolled)', async () => {
const { container } = render(
<DateInput {...defaultProps} allowDeselect={false} defaultValue={new Date(2022, 3, 11)} />
<DateInput {...defaultProps} clearable={false} defaultValue={new Date(2022, 3, 11)} />
);

expectValue(container, 'April 11, 2022');
Expand All @@ -234,19 +247,84 @@ describe('@mantine/dates/DateInput', () => {
expectValue(container, 'April 11, 2022');
});

it('allows to clear input value when allowDeselect is set (controlled)', async () => {
it('does not allow to clear input value when clearable is not set (controlled)', async () => {
const spy = jest.fn();
const { container } = render(
<DateInput {...defaultProps} allowDeselect value={new Date(2022, 3, 11)} onChange={spy} />
<DateInput {...defaultProps} clearable={false} value={new Date(2022, 3, 11)} onChange={spy} />
);

expectValue(container, 'April 11, 2022');
await userEvent.clear(getInput(container));
await userEvent.tab();
expectValue(container, 'April 11, 2022');
expect(spy).not.toHaveBeenCalled();
});

it('allows to clear input value by clicking the selected date when clearable and allowDeselect are set (uncontrolled)', async () => {
const { container } = render(
<DateInput {...defaultProps} clearable allowDeselect defaultValue={new Date(2022, 3, 1)} />
);

expectValue(container, 'April 1, 2022');
await userEvent.tab();
await clickControl(container, 4);
expectValue(container, '');
});

it('allows to clear input value by clicking the selected date when clearable and allowDeselect are set (controlled)', async () => {
const spy = jest.fn();
const { container } = render(
<DateInput
{...defaultProps}
clearable
allowDeselect
value={new Date(2022, 3, 1)}
onChange={spy}
/>
);

expectValue(container, 'April 1, 2022');
await userEvent.tab();
await clickControl(container, 4);
expectValue(container, 'April 1, 2022');
expect(spy).toHaveBeenLastCalledWith(null);
});

it('does not allow to clear input value by clicking the selected date when allowDeselect is not set (uncontrolled)', async () => {
const { container } = render(
<DateInput
{...defaultProps}
clearable
allowDeselect={false}
defaultValue={new Date(2022, 3, 1)}
/>
);

expectValue(container, 'April 1, 2022');
await userEvent.tab();
await clickControl(container, 4);
expectValue(container, 'April 1, 2022');
});

it('does not allow to clear input value by clicking the selected date when allowDeselect is not set (controlled)', async () => {
const spy = jest.fn();
const { container } = render(
<DateInput
{...defaultProps}
clearable
allowDeselect={false}
value={new Date(2022, 3, 1)}
onChange={spy}
/>
);

expectValue(container, 'April 1, 2022');
await userEvent.tab();
await clickControl(container, 4);
expectValue(container, 'April 1, 2022');
expect(spy).toHaveBeenLastCalledWith(new Date(2022, 3, 1));
});

it('calls onClick when input is clicked', async () => {
const spy = jest.fn();
const { container } = render(<DateInput {...defaultProps} onClick={spy} />);
Expand Down
17 changes: 9 additions & 8 deletions src/mantine-dates/src/components/DateInput/DateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export interface DateInputProps
/** Determines whether input value should be reverted to last known valid value on blur, true by default */
fixOnBlur?: boolean;

/** Determines whether value can be deselected when the user clicks on the selected date in the calendar or erases content of the input, true if clearable prop is set, false by default */
/** Determines whether value can be deselected when the user clicks on the selected date in the calendar (only when clearable prop is set), defaults to true if clearable prop is set, false otherwise */
allowDeselect?: boolean;

/** Determines whether time (hours, minutes, seconds and milliseconds) should be preserved when new date is picked, true by default */
Expand Down Expand Up @@ -130,7 +130,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, re
};

const _dateParser = dateParser || defaultDateParser;
const _allowDeselect = clearable || allowDeselect;
const _allowDeselect = allowDeselect !== undefined ? allowDeselect : clearable;

const formatValue = (val: Date) =>
val ? dayjs(val).locale(ctx.getLocale(locale)).format(valueFormat) : '';
Expand Down Expand Up @@ -167,7 +167,7 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, re
const val = event.currentTarget.value;
setInputValue(val);

if (val.trim() === '' && _allowDeselect) {
if (val.trim() === '' && clearable) {
setValue(null);
} else {
const dateValue = _dateParser(val);
Expand Down Expand Up @@ -199,11 +199,12 @@ export const DateInput = forwardRef<HTMLInputElement, DateInputProps>((props, re
selected: dayjs(_value).isSame(day, 'day'),
onClick: () => {
const valueWithTime = preserveTime ? assignTime(_value, day) : day;
const val = _allowDeselect
? dayjs(_value).isSame(day, 'day')
? null
: valueWithTime
: valueWithTime;
const val =
clearable && _allowDeselect
? dayjs(_value).isSame(day, 'day')
? null
: valueWithTime
: valueWithTime;
setValue(val);
!controlled && setInputValue(formatValue(val));
setDropdownOpened(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const code = `
import { DateInput } from '@mantine/dates';

function Demo() {
return <DateInput label="Date input" placeholder="Date input" maw={400} mx="auto" />;
return <DateInput clearable label="Date input" placeholder="Date input" maw={400} mx="auto" />;
}
`;

Expand Down