diff --git a/docs/data/date-pickers/calendar-systems/AdapterHijri.js b/docs/data/date-pickers/calendar-systems/AdapterHijri.js
index fa738ee1e6e3..f146aaa31ba3 100644
--- a/docs/data/date-pickers/calendar-systems/AdapterHijri.js
+++ b/docs/data/date-pickers/calendar-systems/AdapterHijri.js
@@ -46,14 +46,6 @@ function ButtonDateTimeField(props) {
props: internalProps,
});
- const handleTogglePicker = (event) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const valueStr = value == null ? parsedFormat : value.format(format);
return (
@@ -62,7 +54,7 @@ function ButtonDateTimeField(props) {
variant="outlined"
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${valueStr}` : valueStr}
diff --git a/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx b/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx
index aa9b24d67f79..319f93f591ac 100644
--- a/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx
+++ b/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx
@@ -50,14 +50,6 @@ function ButtonDateTimeField(props: DateTimePickerFieldProps) {
props: internalProps,
});
- const handleTogglePicker = (event: React.UIEvent) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const valueStr = value == null ? parsedFormat : value.format(format);
return (
@@ -66,7 +58,7 @@ function ButtonDateTimeField(props: DateTimePickerFieldProps) {
variant="outlined"
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${valueStr}` : valueStr}
diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js
index a86335cd7dd7..7adc0f2e453a 100644
--- a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js
+++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js
@@ -87,13 +87,6 @@ const BrowserSingleInputDateRangeField = React.forwardRef((props, ref) => {
const { slots, slotProps, ...other } = props;
const pickerContext = usePickerContext();
- const handleTogglePicker = (event) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
const textFieldProps = useSlotProps({
elementType: 'input',
@@ -106,7 +99,7 @@ const BrowserSingleInputDateRangeField = React.forwardRef((props, ref) => {
...textFieldProps.InputProps,
endAdornment: (
-
+
diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx
index 2c1c935104e7..e6e44e9656e4 100644
--- a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx
+++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx
@@ -115,13 +115,6 @@ const BrowserSingleInputDateRangeField = React.forwardRef(
const { slots, slotProps, ...other } = props;
const pickerContext = usePickerContext();
- const handleTogglePicker = (event: React.UIEvent) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
const textFieldProps: typeof props = useSlotProps({
elementType: 'input',
@@ -134,7 +127,7 @@ const BrowserSingleInputDateRangeField = React.forwardRef(
...textFieldProps.InputProps,
endAdornment: (
-
+
diff --git a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js
index dd5ee96d6f52..95be4b633756 100644
--- a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js
+++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js
@@ -72,13 +72,6 @@ const JoySingleInputDateRangeField = React.forwardRef((props, ref) => {
const { slots, slotProps, ...other } = props;
const pickerContext = usePickerContext();
- const handleTogglePicker = (event) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
const textFieldProps = useSlotProps({
elementType: FormControl,
@@ -105,7 +98,7 @@ const JoySingleInputDateRangeField = React.forwardRef((props, ref) => {
ref={ref}
endDecorator={
{
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
const textFieldProps: JoySingleInputDateRangeFieldProps = useSlotProps({
elementType: FormControl,
@@ -136,7 +129,7 @@ const JoySingleInputDateRangeField = React.forwardRef(
ref={ref}
endDecorator={
{
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const valueStr = value == null ? parsedFormat : value.format(format);
return (
@@ -50,7 +42,7 @@ function ButtonDateField(props) {
variant="outlined"
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${valueStr}` : valueStr}
diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx b/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx
index ac64ebd3a5f0..d19c72fb95b0 100644
--- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx
+++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx
@@ -38,14 +38,6 @@ function ButtonDateField(props: DatePickerFieldProps) {
props: internalProps,
});
- const handleTogglePicker = (event: React.UIEvent) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const valueStr = value == null ? parsedFormat : value.format(format);
return (
@@ -54,7 +46,7 @@ function ButtonDateField(props: DatePickerFieldProps) {
variant="outlined"
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${valueStr}` : valueStr}
diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js
index 7c56f7a2693a..d2e26d720904 100644
--- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js
+++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js
@@ -36,14 +36,6 @@ function ButtonDateRangeField(props) {
props: internalProps,
});
- const handleTogglePicker = (event) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const formattedValue = (value ?? [null, null])
.map((date) => (date == null ? parsedFormat : date.format(format)))
.join(' – ');
@@ -54,7 +46,7 @@ function ButtonDateRangeField(props) {
variant="outlined"
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${formattedValue}` : formattedValue}
diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx
index fbc0cd45c51e..b4a39597513e 100644
--- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx
+++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx
@@ -40,14 +40,6 @@ function ButtonDateRangeField(props: DateRangePickerFieldProps) {
props: internalProps,
});
- const handleTogglePicker = (event: React.UIEvent) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const formattedValue = (value ?? [null, null])
.map((date: Dayjs) => (date == null ? parsedFormat : date.format(format)))
.join(' – ');
@@ -58,7 +50,7 @@ function ButtonDateRangeField(props: DateRangePickerFieldProps) {
variant="outlined"
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${formattedValue}` : formattedValue}
diff --git a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js
index 1e7d773f6fdf..96e29f79763a 100644
--- a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js
+++ b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js
@@ -26,14 +26,6 @@ function ReadOnlyDateField(props) {
props: internalProps,
});
- const handleTogglePicker = (event) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
return (
);
}
diff --git a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx
index 1fd235a77819..cc2b1180fdf7 100644
--- a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx
+++ b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx
@@ -30,14 +30,6 @@ function ReadOnlyDateField(props: DatePickerFieldProps) {
props: internalProps,
});
- const handleTogglePicker = (event: React.UIEvent) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
return (
);
}
diff --git a/docs/src/modules/components/overview/mainDemo/PickerButton.tsx b/docs/src/modules/components/overview/mainDemo/PickerButton.tsx
index d47d045fb1c6..59043f6ea467 100644
--- a/docs/src/modules/components/overview/mainDemo/PickerButton.tsx
+++ b/docs/src/modules/components/overview/mainDemo/PickerButton.tsx
@@ -23,14 +23,6 @@ function ButtonDateField(props: DatePickerFieldProps) {
props: internalProps,
});
- const handleTogglePicker = (event: React.UIEvent) => {
- if (pickerContext.open) {
- pickerContext.onClose(event);
- } else {
- pickerContext.onOpen(event);
- }
- };
-
const valueStr = value == null ? parsedFormat : value.format(format);
return (
@@ -43,7 +35,7 @@ function ButtonDateField(props: DatePickerFieldProps) {
fullWidth
color={hasValidationError ? 'error' : 'primary'}
ref={InputProps?.ref}
- onClick={handleTogglePicker}
+ onClick={pickerContext.onToggleOpening}
>
{label ? `${label}: ${valueStr}` : valueStr}
diff --git a/packages/x-date-pickers/src/internals/components/PickerProvider.tsx b/packages/x-date-pickers/src/internals/components/PickerProvider.tsx
index 85eeaf1f04d8..4fa7eb07cbf1 100644
--- a/packages/x-date-pickers/src/internals/components/PickerProvider.tsx
+++ b/packages/x-date-pickers/src/internals/components/PickerProvider.tsx
@@ -54,6 +54,11 @@ export interface PickerContextValue {
* @param {React.UIEvent} event The DOM event that triggered the change.
*/
onClose: (event: React.UIEvent) => void;
+ /**
+ * Close the picker if it's open, open it if it's closed.
+ * @param {React.UIEvent} event The DOM event that triggered the change.
+ */
+ onToggleOpening: (event: React.UIEvent) => void;
/**
* `true` if the picker is open, `false` otherwise.
*/
diff --git a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts
index 92964972c29a..6c4746dbc8b7 100644
--- a/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts
+++ b/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerProvider.ts
@@ -1,5 +1,6 @@
import * as React from 'react';
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
+import useEventCallback from '@mui/utils/useEventCallback';
import { PickerOwnerState } from '../../../models';
import { PickerValueManager, UsePickerValueResponse } from './usePickerValue.types';
import {
@@ -67,6 +68,14 @@ export function usePickerProvider(
const utils = useUtils();
const orientation = usePickerOrientation(views, props.orientation);
+ const handleTogglePicker = useEventCallback((event: React.UIEvent) => {
+ if (pickerValueResponse.open) {
+ pickerValueResponse.actions.onClose(event);
+ } else {
+ pickerValueResponse.actions.onOpen(event);
+ }
+ });
+
const ownerState = React.useMemo(
() => ({
isPickerValueEmpty: valueManager.areValuesEqual(
@@ -96,6 +105,7 @@ export function usePickerProvider(
() => ({
onOpen: pickerValueResponse.actions.onOpen,
onClose: pickerValueResponse.actions.onClose,
+ onToggleOpening: handleTogglePicker,
open: pickerValueResponse.open,
disabled: props.disabled ?? false,
readOnly: props.readOnly ?? false,
@@ -105,6 +115,7 @@ export function usePickerProvider(
[
pickerValueResponse.actions.onOpen,
pickerValueResponse.actions.onClose,
+ handleTogglePicker,
pickerValueResponse.open,
variant,
orientation,