diff --git a/docs/prop-types.json b/docs/prop-types.json index d9106f8c9..c8e28b65c 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -320,7 +320,7 @@ }, "onError": { "defaultValue": null, - "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\nThis can be used to render appropriate form error.\n\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", + "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\r\nThis can be used to render appropriate form error.\r\n\r\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", "name": "onError", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/hooks/useValidation.ts", @@ -1292,7 +1292,7 @@ }, "onError": { "defaultValue": null, - "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\nThis can be used to render appropriate form error.\n\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", + "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\r\nThis can be used to render appropriate form error.\r\n\r\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", "name": "onError", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/hooks/useValidation.ts", @@ -1974,7 +1974,7 @@ }, "onError": { "defaultValue": null, - "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\nThis can be used to render appropriate form error.\n\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", + "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\r\nThis can be used to render appropriate form error.\r\n\r\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", "name": "onError", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/hooks/useValidation.ts", @@ -3472,7 +3472,7 @@ }, "onError": { "defaultValue": null, - "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\nThis can be used to render appropriate form error.\n\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", + "description": "Callback that fired when input value or new `value` prop validation returns **new** validation error (or value is valid after error).\nIn case of validation error detected `reason` prop return non-null value and `TextField` must be displayed in `error` state.\r\nThis can be used to render appropriate form error.\r\n\r\n[Read the guide](https://next.material-ui-pickers.dev/guides/forms) about form integration and error displaying.\n@DateIOType", "name": "onError", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/hooks/useValidation.ts", @@ -4110,6 +4110,21 @@ "type": { "name": "boolean" } + }, + "allowSameDateSelection": { + "defaultValue": { + "value": false + }, + "description": "Allow selecting the same date (fire onChange even if same date is selected).", + "name": "allowSameDateSelection", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } } }, "ClockView": { diff --git a/lib/src/DateRangePicker/DateRangePickerDay.tsx b/lib/src/DateRangePicker/DateRangePickerDay.tsx index 1e62ebad4..f4bdabf6e 100644 --- a/lib/src/DateRangePicker/DateRangePickerDay.tsx +++ b/lib/src/DateRangePicker/DateRangePickerDay.tsx @@ -141,6 +141,7 @@ export const PureDateRangeDay = ({ {...other} day={day} selected={selected} + allowSameDateSelection={true} inCurrentMonth={inCurrentMonth} data-mui-test="DateRangeDay" className={clsx( diff --git a/lib/src/__tests__/DatePickerTestingLib.test.tsx b/lib/src/__tests__/DatePickerTestingLib.test.tsx index a5a8370da..bc8489487 100644 --- a/lib/src/__tests__/DatePickerTestingLib.test.tsx +++ b/lib/src/__tests__/DatePickerTestingLib.test.tsx @@ -78,4 +78,23 @@ describe('', () => { expect(screen.queryByRole('dialog')).toBeInTheDocument(); }); + + it('does not call onChange if same date selected', async () => { + const onChangeMock = jest.fn(); + + render( + } + /> + ); + + fireEvent.click(screen.getByLabelText('Choose date, selected date is Jan 1, 2018')); + await waitFor(() => screen.getByRole('dialog')); + + fireEvent.click(screen.getByLabelText('Jan 1, 2018')); + expect(onChangeMock).not.toHaveBeenCalled(); + }); }); diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 27184c90c..0734212cb 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -104,7 +104,6 @@ export function usePickerState( selectionState: PickerSelectionState = 'partial' ) => { setPickerDate(newDate); - if (selectionState === 'partial') { acceptDate(newDate, false); } diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 7e108b0d2..72e9c50c1 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -124,12 +124,18 @@ export interface DayProps extends ExtendMui { * @default false */ disableHighlightToday?: boolean; + /** + * Allow selecting the same date (fire onChange even if same date is selected). + * @default false + */ + allowSameDateSelection?: boolean; onDayFocus: (day: unknown) => void; onDaySelect: (day: unknown, isFinish: PickerSelectionState) => void; } const PureDay: React.FC = ({ allowKeyboardControl, + allowSameDateSelection = false, className, day, disabled, @@ -180,6 +186,8 @@ const PureDay: React.FC = ({ }; const handleClick = (event: React.MouseEvent) => { + if (!allowSameDateSelection && selected) return; + if (!disabled) { onDaySelect(day, 'finish'); }