diff --git a/docs/data/date-pickers/custom-field/PickerWithBrowserField.js b/docs/data/date-pickers/custom-field/PickerWithBrowserField.js index 64b20beedc61..bc8e2e00cc5a 100644 --- a/docs/data/date-pickers/custom-field/PickerWithBrowserField.js +++ b/docs/data/date-pickers/custom-field/PickerWithBrowserField.js @@ -5,6 +5,7 @@ import { useSlotProps } from '@mui/base/utils'; import Box from '@mui/material/Box'; import Stack from '@mui/material/Stack'; import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; import { DateRangeIcon } from '@mui/x-date-pickers/icons'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; @@ -15,6 +16,8 @@ import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } f import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; + const BrowserField = React.forwardRef((props, ref) => { const { disabled, @@ -26,6 +29,7 @@ const BrowserField = React.forwardRef((props, ref) => { error, focused, ownerState, + sx, ...other } = props; @@ -33,7 +37,7 @@ const BrowserField = React.forwardRef((props, ref) => { return ( @@ -48,33 +52,51 @@ const BrowserSingleInputDateRangeField = React.forwardRef((props, ref) => { const { slots, slotProps, onAdornmentClick, ...other } = props; const { inputRef: externalInputRef, ...textFieldProps } = useSlotProps({ - elementType: null, + elementType: 'input', externalSlotProps: slotProps?.textField, externalForwardedProps: other, ownerState: props, }); - const { ref: inputRef, ...response } = useSingleInputDateRangeField({ + const { + ref: inputRef, + onClear, + clearable, + ...fieldProps + } = useSingleInputDateRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField({ + onClear, + clearable, + fieldProps, + InputProps: { + ...fieldProps.InputProps, + endAdornment: ( + + + + + + ), + }, + slots, + slotProps, + }); + return ( - - - ), - }} + InputProps={{ ...ProcessedInputProps }} /> ); }); @@ -93,14 +115,18 @@ const BrowserSingleInputDateRangePicker = React.forwardRef((props, ref) => { return ( ); }); @@ -126,13 +152,13 @@ const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { } = props; const { inputRef: startInputRef, ...startTextFieldProps } = useSlotProps({ - elementType: null, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'start' }, }); const { inputRef: endInputRef, ...endTextFieldProps } = useSlotProps({ - elementType: null, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'end' }, }); @@ -176,8 +202,8 @@ const BrowserDateRangePicker = React.forwardRef((props, ref) => { return ( ); }); @@ -185,20 +211,42 @@ const BrowserDateRangePicker = React.forwardRef((props, ref) => { const BrowserDateField = React.forwardRef((props, ref) => { const { inputRef: externalInputRef, slots, slotProps, ...textFieldProps } = props; - const { ref: inputRef, ...other } = useDateField({ + const { + onClear, + clearable, + ref: inputRef, + ...fieldProps + } = useDateField({ props: textFieldProps, inputRef: externalInputRef, }); - return ; + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + }); + return ( + + ); }); const BrowserDatePicker = React.forwardRef((props, ref) => { return ( ); }); @@ -209,8 +257,16 @@ export default function PickerWithBrowserField() { - - + + diff --git a/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx b/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx index 263c232bf8b4..415a2cf5b5a6 100644 --- a/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx +++ b/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx @@ -5,6 +5,7 @@ import { useSlotProps } from '@mui/base/utils'; import Box from '@mui/material/Box'; import Stack from '@mui/material/Stack'; import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; import { DateRangeIcon } from '@mui/x-date-pickers/icons'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; @@ -23,6 +24,11 @@ import { unstable_useDateField as useDateField, UseDateFieldProps, } from '@mui/x-date-pickers/DateField'; +import { + DateFieldSlotsComponent, + DateFieldSlotsComponentsProps, +} from '@mui/x-date-pickers/DateField/DateField.types'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; import { BaseMultiInputFieldProps, DateRange, @@ -34,6 +40,10 @@ import { RangeFieldSection, FieldSection, } from '@mui/x-date-pickers-pro'; +import type { + SingleInputDateRangeFieldSlotsComponent, + SingleInputDateRangeFieldSlotsComponentsProps, +} from '@mui/x-date-pickers-pro/SingleInputDateRangeField/SingleInputDateRangeField.types'; interface BrowserFieldProps extends Omit, 'size'> { @@ -47,6 +57,7 @@ interface BrowserFieldProps error?: boolean; focused?: boolean; ownerState?: any; + sx?: any; } type BrowserFieldComponent = (( @@ -65,6 +76,7 @@ const BrowserField = React.forwardRef( error, focused, ownerState, + sx, ...other } = props; @@ -72,7 +84,7 @@ const BrowserField = React.forwardRef( return ( @@ -104,36 +116,56 @@ const BrowserSingleInputDateRangeField = React.forwardRef( inputRef: externalInputRef, ...textFieldProps }: SingleInputDateRangeFieldProps = useSlotProps({ - elementType: null as any, + elementType: 'input', externalSlotProps: slotProps?.textField, externalForwardedProps: other, ownerState: props as any, }); - const { ref: inputRef, ...response } = useSingleInputDateRangeField< - Dayjs, - typeof textFieldProps - >({ + const { + ref: inputRef, + onClear, + clearable, + ...fieldProps + } = useSingleInputDateRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField< + {}, + typeof textFieldProps.InputProps, + SingleInputDateRangeFieldSlotsComponent, + SingleInputDateRangeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: { + ...fieldProps.InputProps, + endAdornment: ( + + + + + + ), + }, + slots, + slotProps, + }); + return ( - - - ), - }} + InputProps={{ ...ProcessedInputProps }} /> ); }, @@ -154,14 +186,18 @@ const BrowserSingleInputDateRangePicker = React.forwardRef( return ( ); }, @@ -202,13 +238,13 @@ const BrowserMultiInputDateRangeField = React.forwardRef( } = props; const { inputRef: startInputRef, ...startTextFieldProps } = useSlotProps({ - elementType: null as any, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'start' }, }) as MultiInputFieldSlotTextFieldProps; const { inputRef: endInputRef, ...endTextFieldProps } = useSlotProps({ - elementType: null as any, + elementType: 'input', externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'end' }, }) as MultiInputFieldSlotTextFieldProps; @@ -254,8 +290,8 @@ const BrowserDateRangePicker = React.forwardRef( return ( ); }, @@ -279,12 +315,39 @@ const BrowserDateField = React.forwardRef( ...textFieldProps } = props; - const { ref: inputRef, ...other } = useDateField({ + const { + onClear, + clearable, + ref: inputRef, + ...fieldProps + } = useDateField({ props: textFieldProps, inputRef: externalInputRef, }); - return ; + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField< + {}, + typeof textFieldProps.InputProps, + DateFieldSlotsComponent, + DateFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + }); + return ( + + ); }, ); @@ -293,8 +356,8 @@ const BrowserDatePicker = React.forwardRef( return ( ); }, @@ -306,8 +369,16 @@ export default function PickerWithBrowserField() { - - + + diff --git a/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx.preview b/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx.preview index 4e96e10bc78a..6a6dd7638dae 100644 --- a/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx.preview +++ b/docs/data/date-pickers/custom-field/PickerWithBrowserField.tsx.preview @@ -1,3 +1,11 @@ - - + + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/PickerWithJoyField.js b/docs/data/date-pickers/custom-field/PickerWithJoyField.js index 3289e3e068c2..c753b81155d8 100644 --- a/docs/data/date-pickers/custom-field/PickerWithJoyField.js +++ b/docs/data/date-pickers/custom-field/PickerWithJoyField.js @@ -29,6 +29,8 @@ import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } f import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; + const joyTheme = extendJoyTheme(); const JoyField = React.forwardRef((props, ref) => { @@ -38,6 +40,8 @@ const JoyField = React.forwardRef((props, ref) => { label, InputProps: { ref: containerRef, startAdornment, endAdornment } = {}, formControlSx, + endDecorator, + startDecorator, slotProps, ...other } = props; @@ -56,13 +60,24 @@ const JoyField = React.forwardRef((props, ref) => { > {label} + {startAdornment} + {startDecorator} + + } + endDecorator={ + + {endAdornment} + {endDecorator} + + } slotProps={{ ...slotProps, root: { ...slotProps?.root, ref: containerRef }, }} - startDecorator={startAdornment} - endDecorator={endAdornment} {...other} /> @@ -73,20 +88,36 @@ const JoySingleInputDateRangeField = React.forwardRef((props, ref) => { const { slots, slotProps, onAdornmentClick, ...other } = props; const { inputRef: externalInputRef, ...textFieldProps } = useSlotProps({ - elementType: null, + elementType: FormControl, externalSlotProps: slotProps?.textField, externalForwardedProps: other, ownerState: props, }); - const { ref: inputRef, ...response } = useSingleInputDateRangeField({ + const { + onClear, + clearable, + ref: inputRef, + ...fieldProps + } = useSingleInputDateRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots: { ...slots, clearButton: IconButton }, + slotProps: { ...slotProps, clearIcon: { color: 'action' } }, + }); + return ( { }, }} endDecorator={ - + } + InputProps={{ ...ProcessedInputProps }} /> ); }); @@ -119,15 +156,19 @@ const JoySingleInputDateRangePicker = React.forwardRef((props, ref) => { return ( ); }); @@ -179,13 +220,13 @@ const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { } = props; const { inputRef: startInputRef, ...startTextFieldProps } = useSlotProps({ - elementType: null, + elementType: FormControl, externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'start' }, }); const { inputRef: endInputRef, ...endTextFieldProps } = useSlotProps({ - elementType: null, + elementType: FormControl, externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'end' }, }); @@ -243,8 +284,8 @@ const JoyDateRangePicker = React.forwardRef((props, ref) => { return ( ); }); @@ -252,11 +293,27 @@ const JoyDateRangePicker = React.forwardRef((props, ref) => { const JoyDateField = React.forwardRef((props, ref) => { const { inputRef: externalInputRef, slots, slotProps, ...textFieldProps } = props; - const { ref: inputRef, ...other } = useDateField({ + const { + onClear, + clearable, + ref: inputRef, + ...fieldProps + } = useDateField({ props: textFieldProps, inputRef: externalInputRef, }); + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + }); + return ( { ref: inputRef, }, }} - {...other} + {...processedFieldProps} + InputProps={ProcessedInputProps} /> ); }); @@ -277,7 +335,9 @@ const JoyDatePicker = React.forwardRef((props, ref) => { {...props} slots={{ field: JoyDateField, ...props.slots }} slotProps={{ + ...props.slotProps, field: { + ...props.slotProps?.field, formControlSx: { flexDirection: 'row', }, @@ -311,8 +371,16 @@ export default function PickerWithJoyField() { - - + + diff --git a/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx b/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx index 845d6e6aa7b7..2777e5fea381 100644 --- a/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx +++ b/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx @@ -37,6 +37,11 @@ import { unstable_useDateField as useDateField, UseDateFieldProps, } from '@mui/x-date-pickers/DateField'; +import { + DateFieldSlotsComponent, + DateFieldSlotsComponentsProps, +} from '@mui/x-date-pickers/DateField/DateField.types'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; import { BaseMultiInputFieldProps, DateRange, @@ -48,6 +53,10 @@ import { RangeFieldSection, FieldSection, } from '@mui/x-date-pickers-pro'; +import type { + SingleInputDateRangeFieldSlotsComponent, + SingleInputDateRangeFieldSlotsComponentsProps, +} from '@mui/x-date-pickers-pro/SingleInputDateRangeField/SingleInputDateRangeField.types'; const joyTheme = extendJoyTheme(); @@ -73,6 +82,8 @@ const JoyField = React.forwardRef( label, InputProps: { ref: containerRef, startAdornment, endAdornment } = {}, formControlSx, + endDecorator, + startDecorator, slotProps, ...other } = props; @@ -91,13 +102,24 @@ const JoyField = React.forwardRef( > {label} + {startAdornment} + {startDecorator} + + } + endDecorator={ + + {endAdornment} + {endDecorator} + + } slotProps={{ ...slotProps, root: { ...slotProps?.root, ref: containerRef }, }} - startDecorator={startAdornment} - endDecorator={endAdornment} {...other} /> @@ -125,23 +147,41 @@ const JoySingleInputDateRangeField = React.forwardRef( Dayjs, JoyFieldProps & { inputRef: React.Ref } > = useSlotProps({ - elementType: null as any, + elementType: FormControl, externalSlotProps: slotProps?.textField, externalForwardedProps: other, ownerState: props as any, }); - const { ref: inputRef, ...response } = useSingleInputDateRangeField< - Dayjs, - JoyFieldProps - >({ + const { + onClear, + clearable, + ref: inputRef, + ...fieldProps + } = useSingleInputDateRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField< + {}, + typeof textFieldProps.InputProps, + SingleInputDateRangeFieldSlotsComponent, + SingleInputDateRangeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots: { ...slots, clearButton: IconButton }, + slotProps: { ...slotProps, clearIcon: { color: 'action' } }, + }); + return ( + } + InputProps={{ ...ProcessedInputProps }} /> ); }, @@ -176,15 +222,19 @@ const JoySingleInputDateRangePicker = React.forwardRef( return ( ); }, @@ -251,13 +301,13 @@ const JoyMultiInputDateRangeField = React.forwardRef( } = props; const { inputRef: startInputRef, ...startTextFieldProps } = useSlotProps({ - elementType: null as any, + elementType: FormControl, externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'start' }, }) as MultiInputFieldSlotTextFieldProps; const { inputRef: endInputRef, ...endTextFieldProps } = useSlotProps({ - elementType: null as any, + elementType: FormControl, externalSlotProps: slotProps?.textField, ownerState: { ...props, position: 'end' }, }) as MultiInputFieldSlotTextFieldProps; @@ -317,8 +367,8 @@ const JoyDateRangePicker = React.forwardRef( return ( ); }, @@ -342,11 +392,32 @@ const JoyDateField = React.forwardRef( ...textFieldProps } = props; - const { ref: inputRef, ...other } = useDateField({ + const { + onClear, + clearable, + ref: inputRef, + ...fieldProps + } = useDateField({ props: textFieldProps, inputRef: externalInputRef, }); + /* If you don't need a clear button, you can skip the use of this hook */ + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = + useClearableField< + {}, + typeof textFieldProps.InputProps, + DateFieldSlotsComponent, + DateFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + }); + return ( ); }, @@ -369,7 +441,9 @@ const JoyDatePicker = React.forwardRef( {...props} slots={{ field: JoyDateField, ...props.slots }} slotProps={{ + ...props.slotProps, field: { + ...props.slotProps?.field, formControlSx: { flexDirection: 'row', }, @@ -404,8 +478,16 @@ export default function PickerWithJoyField() { - - + + diff --git a/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx.preview b/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx.preview deleted file mode 100644 index 1549f760fbea..000000000000 --- a/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx.preview +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/custom-field.md b/docs/data/date-pickers/custom-field/custom-field.md index f16a6f3ec7ae..5c1f7ffe9969 100644 --- a/docs/data/date-pickers/custom-field/custom-field.md +++ b/docs/data/date-pickers/custom-field/custom-field.md @@ -75,6 +75,10 @@ You can also use any other input: {{"demo": "PickerWithBrowserField.js", "defaultCodeOpen": false}} +:::warning +You will need to use a component that supports the `sx` prop as a wrapper for your input, in order to be able to benefit from the **hover** and **focus** behavior of the clear button. You will have access to the `clearable` and `onClear` props using native HTML elements, but the on **focus** and **hover** behavior depends on styles applied via the `sx` prop. +::: + ### Using an `Autocomplete` If your user can only select a value in a small list of available dates, diff --git a/docs/data/date-pickers/date-picker/ClearableProp.js b/docs/data/date-pickers/date-picker/ClearableProp.js new file mode 100644 index 000000000000..c5ecfc1beaf8 --- /dev/null +++ b/docs/data/date-pickers/date-picker/ClearableProp.js @@ -0,0 +1,54 @@ +import * as React from 'react'; +import { DemoItem } from '@mui/x-date-pickers/internals/demo'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import Box from '@mui/material/Box'; +import Alert from '@mui/material/Alert'; + +export default function ClearableProp() { + const [cleared, setCleared] = React.useState(false); + + React.useEffect(() => { + if (cleared) { + const timeout = setTimeout(() => { + setCleared(false); + }, 1500); + + return () => clearTimeout(timeout); + } + return () => {}; + }, [cleared]); + + return ( + + + + setCleared(true) }, + }} + /> + + + {cleared && ( + + Field cleared! + + )} + + + ); +} diff --git a/docs/data/date-pickers/date-picker/ClearableProp.tsx b/docs/data/date-pickers/date-picker/ClearableProp.tsx new file mode 100644 index 000000000000..d2d509261589 --- /dev/null +++ b/docs/data/date-pickers/date-picker/ClearableProp.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import { DemoItem } from '@mui/x-date-pickers/internals/demo'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import Box from '@mui/material/Box'; +import Alert from '@mui/material/Alert'; + +export default function ClearableProp() { + const [cleared, setCleared] = React.useState(false); + + React.useEffect(() => { + if (cleared) { + const timeout = setTimeout(() => { + setCleared(false); + }, 1500); + + return () => clearTimeout(timeout); + } + return () => {}; + }, [cleared]); + + return ( + + + + setCleared(true) }, + }} + /> + + + {cleared && ( + + Field cleared! + + )} + + + ); +} diff --git a/docs/data/date-pickers/date-picker/date-picker.md b/docs/data/date-pickers/date-picker/date-picker.md index c3aac1f06bc5..9ebc9fa0bc7b 100644 --- a/docs/data/date-pickers/date-picker/date-picker.md +++ b/docs/data/date-pickers/date-picker/date-picker.md @@ -106,6 +106,12 @@ You can show a helper text with the date format accepted: {{"demo": "HelperText.js"}} +## Clearing the value + +You can enable the clearable behavior: + +{{"demo": "ClearableProp.js"}} + ## Validation You can find the documentation in the [Validation page](/x/react-date-pickers/validation/). diff --git a/docs/data/date-pickers/fields/ClearableBehavior.js b/docs/data/date-pickers/fields/ClearableBehavior.js new file mode 100644 index 000000000000..c66c5e1538ba --- /dev/null +++ b/docs/data/date-pickers/fields/ClearableBehavior.js @@ -0,0 +1,56 @@ +import * as React from 'react'; + +import { DemoItem } from '@mui/x-date-pickers/internals/demo'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import Box from '@mui/material/Box'; +import Alert from '@mui/material/Alert'; + +export default function ClearableBehavior() { + const [value, setValue] = React.useState(null); + const [cleared, setCleared] = React.useState(false); + + React.useEffect(() => { + if (cleared) { + const timeout = setTimeout(() => { + setCleared(false); + }, 1500); + + return () => clearTimeout(timeout); + } + return () => {}; + }, [cleared]); + + return ( + + + + setValue(newValue)} + onClear={() => setCleared(true)} + clearable + /> + + {cleared && !value && ( + + Field cleared! + + )} + + + ); +} diff --git a/docs/data/date-pickers/fields/ClearableBehavior.tsx b/docs/data/date-pickers/fields/ClearableBehavior.tsx new file mode 100644 index 000000000000..0aeceeaf2950 --- /dev/null +++ b/docs/data/date-pickers/fields/ClearableBehavior.tsx @@ -0,0 +1,56 @@ +import * as React from 'react'; +import { Dayjs } from 'dayjs'; +import { DemoItem } from '@mui/x-date-pickers/internals/demo'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import Box from '@mui/material/Box'; +import Alert from '@mui/material/Alert'; + +export default function ClearableBehavior() { + const [value, setValue] = React.useState(null); + const [cleared, setCleared] = React.useState(false); + + React.useEffect(() => { + if (cleared) { + const timeout = setTimeout(() => { + setCleared(false); + }, 1500); + + return () => clearTimeout(timeout); + } + return () => {}; + }, [cleared]); + + return ( + + + + setValue(newValue)} + onClear={() => setCleared(true)} + clearable + /> + + {cleared && !value && ( + + Field cleared! + + )} + + + ); +} diff --git a/docs/data/date-pickers/fields/CustomizeClearIcon.js b/docs/data/date-pickers/fields/CustomizeClearIcon.js new file mode 100644 index 000000000000..416541f175a8 --- /dev/null +++ b/docs/data/date-pickers/fields/CustomizeClearIcon.js @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import BackspaceIcon from '@mui/icons-material/Backspace'; +import HighlightOffIcon from '@mui/icons-material/HighlightOff'; + +export default function CustomizeClearIcon() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/fields/CustomizeClearIcon.tsx b/docs/data/date-pickers/fields/CustomizeClearIcon.tsx new file mode 100644 index 000000000000..416541f175a8 --- /dev/null +++ b/docs/data/date-pickers/fields/CustomizeClearIcon.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import BackspaceIcon from '@mui/icons-material/Backspace'; +import HighlightOffIcon from '@mui/icons-material/HighlightOff'; + +export default function CustomizeClearIcon() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/fields/CustomizeClearIcon.tsx.preview b/docs/data/date-pickers/fields/CustomizeClearIcon.tsx.preview new file mode 100644 index 000000000000..bb0651a2a82b --- /dev/null +++ b/docs/data/date-pickers/fields/CustomizeClearIcon.tsx.preview @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/docs/data/date-pickers/fields/fields.md b/docs/data/date-pickers/fields/fields.md index f0821ea234f6..9bd7260fff46 100644 --- a/docs/data/date-pickers/fields/fields.md +++ b/docs/data/date-pickers/fields/fields.md @@ -74,3 +74,17 @@ Please only use it if needed. ::: {{"demo": "ControlledSelectedSectionsSingleInputRangeField.js", "defaultCodeOpen": false }} + +### Clearable behavior + +You can use the `clearable` prop to enable the clearing behavior on a field. You can also add an event handler using the `onClear` callback prop. + +:::info +For **multi-input** range fields the clearable behavior is not supported yet. +::: + +{{"demo": "ClearableBehavior.js"}} + +You can also customize the icon you want to be displayed inside the clear `IconButton`. + +{{"demo": "CustomizeClearIcon.js"}} diff --git a/docs/data/date-pickers/localization/data.json b/docs/data/date-pickers/localization/data.json index 0c8369ecba5e..e4f077b2a1f4 100644 --- a/docs/data/date-pickers/localization/data.json +++ b/docs/data/date-pickers/localization/data.json @@ -3,96 +3,96 @@ "languageTag": "be-BY", "importName": "beBY", "localeName": "Belarusian", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/beBY.ts" }, { "languageTag": "ca-ES", "importName": "caES", "localeName": "Catalan", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/caES.ts" }, { "languageTag": "zh-HK", "importName": "zhHK", "localeName": "Chinese (Hong Kong)", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/zhHK.ts" }, { "languageTag": "zh-CN", "importName": "zhCN", "localeName": "Chinese (Simplified)", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/zhCN.ts" }, { "languageTag": "cs-CZ", "importName": "csCZ", "localeName": "Czech", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/csCZ.ts" }, { "languageTag": "da-DK", "importName": "daDK", "localeName": "Danish", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/daDK.ts" }, { "languageTag": "nl-NL", "importName": "nlNL", "localeName": "Dutch", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/nlNL.ts" }, { "languageTag": "fi-FI", "importName": "fiFI", "localeName": "Finnish", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/fiFI.ts" }, { "languageTag": "fr-FR", "importName": "frFR", "localeName": "French", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/frFR.ts" }, { "languageTag": "de-DE", "importName": "deDE", "localeName": "German", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/deDE.ts" }, { "languageTag": "el-GR", "importName": "elGR", "localeName": "Greek", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/elGR.ts" }, { "languageTag": "he-IL", "importName": "heIL", "localeName": "Hebrew", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/heIL.ts" }, { @@ -100,79 +100,79 @@ "importName": "huHU", "localeName": "Hungarian", "missingKeysCount": 1, - "totalKeysCount": 36, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/huHU.ts" }, { "languageTag": "is-IS", "importName": "isIS", "localeName": "Icelandic", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/isIS.ts" }, { "languageTag": "it-IT", "importName": "itIT", "localeName": "Italian", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/itIT.ts" }, { "languageTag": "ja-JP", "importName": "jaJP", "localeName": "Japanese", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/jaJP.ts" }, { "languageTag": "kz-KZ", "importName": "kzKZ", "localeName": "Kazakh", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/kzKZ.ts" }, { "languageTag": "ko-KR", "importName": "koKR", "localeName": "Korean", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/koKR.ts" }, { "languageTag": "nb-NO", "importName": "nbNO", "localeName": "Norwegian (Bokmål)", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/nbNO.ts" }, { "languageTag": "fa-IR", "importName": "faIR", "localeName": "Persian", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/faIR.ts" }, { "languageTag": "pl-PL", "importName": "plPL", "localeName": "Polish", - "missingKeysCount": 8, - "totalKeysCount": 36, + "missingKeysCount": 9, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/plPL.ts" }, { "languageTag": "pt-BR", "importName": "ptBR", "localeName": "Portuguese (Brazil)", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/ptBR.ts" }, { @@ -180,71 +180,71 @@ "importName": "roRO", "localeName": "Romanian", "missingKeysCount": 1, - "totalKeysCount": 36, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/roRO.ts" }, { "languageTag": "ru-RU", "importName": "ruRU", "localeName": "Russian", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/ruRU.ts" }, { "languageTag": "sk-SK", "importName": "skSK", "localeName": "Slovak", - "missingKeysCount": 1, - "totalKeysCount": 36, + "missingKeysCount": 2, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/skSK.ts" }, { "languageTag": "es-ES", "importName": "esES", "localeName": "Spanish", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/esES.ts" }, { "languageTag": "sv-SE", "importName": "svSE", "localeName": "Swedish", - "missingKeysCount": 8, - "totalKeysCount": 36, + "missingKeysCount": 9, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/svSE.ts" }, { "languageTag": "tr-TR", "importName": "trTR", "localeName": "Turkish", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/trTR.ts" }, { "languageTag": "uk-UA", "importName": "ukUA", "localeName": "Ukrainian", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/ukUA.ts" }, { "languageTag": "ur-PK", "importName": "urPK", "localeName": "Urdu (Pakistan)", - "missingKeysCount": 8, - "totalKeysCount": 36, + "missingKeysCount": 9, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/urPK.ts" }, { "languageTag": "vi-VN", "importName": "viVN", "localeName": "Vietnamese", - "missingKeysCount": 0, - "totalKeysCount": 36, + "missingKeysCount": 1, + "totalKeysCount": 37, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/viVN.ts" } ] diff --git a/docs/pages/x/api/date-pickers/date-field.json b/docs/pages/x/api/date-pickers/date-field.json index 56d51b4e5976..89072397e7b2 100644 --- a/docs/pages/x/api/date-pickers/date-field.json +++ b/docs/pages/x/api/date-pickers/date-field.json @@ -1,6 +1,7 @@ { "props": { "autoFocus": { "type": { "name": "bool" } }, + "clearable": { "type": { "name": "bool" } }, "color": { "type": { "name": "enum", @@ -57,6 +58,7 @@ "describedArgs": ["value", "context"] } }, + "onClear": { "type": { "name": "func" } }, "onError": { "type": { "name": "func" }, "signature": { @@ -135,6 +137,18 @@ } }, "slots": [ + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "textField", diff --git a/docs/pages/x/api/date-pickers/date-picker.json b/docs/pages/x/api/date-pickers/date-picker.json index dfd25d49ff8d..1803d4f4b607 100644 --- a/docs/pages/x/api/date-pickers/date-picker.json +++ b/docs/pages/x/api/date-pickers/date-picker.json @@ -199,6 +199,18 @@ "description": "Custom component for calendar header. Check the PickersCalendarHeader component.", "default": "PickersCalendarHeader" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/date-range-picker.json b/docs/pages/x/api/date-pickers/date-range-picker.json index 57bfacbb15f3..f9e5c64271c7 100644 --- a/docs/pages/x/api/date-pickers/date-range-picker.json +++ b/docs/pages/x/api/date-pickers/date-range-picker.json @@ -160,6 +160,18 @@ "description": "Custom component for the action bar, it is placed below the picker views.", "default": "PickersActionBar" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/date-time-field.json b/docs/pages/x/api/date-pickers/date-time-field.json index 5572cc24adaf..968daaeb4cc3 100644 --- a/docs/pages/x/api/date-pickers/date-time-field.json +++ b/docs/pages/x/api/date-pickers/date-time-field.json @@ -2,6 +2,7 @@ "props": { "ampm": { "type": { "name": "bool" }, "default": "`utils.is12HourCycleInCurrentLocale()`" }, "autoFocus": { "type": { "name": "bool" } }, + "clearable": { "type": { "name": "bool" } }, "color": { "type": { "name": "enum", @@ -64,6 +65,7 @@ "describedArgs": ["value", "context"] } }, + "onClear": { "type": { "name": "func" } }, "onError": { "type": { "name": "func" }, "signature": { @@ -160,6 +162,18 @@ } }, "slots": [ + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "textField", diff --git a/docs/pages/x/api/date-pickers/date-time-picker.json b/docs/pages/x/api/date-pickers/date-time-picker.json index 9678e58a782f..bea6fc7b0cab 100644 --- a/docs/pages/x/api/date-pickers/date-time-picker.json +++ b/docs/pages/x/api/date-pickers/date-time-picker.json @@ -236,6 +236,18 @@ "description": "Custom component for calendar header. Check the PickersCalendarHeader component.", "default": "PickersCalendarHeader" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/desktop-date-picker.json b/docs/pages/x/api/date-pickers/desktop-date-picker.json index 7c13e56265cc..1b01288b20e1 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-picker.json @@ -195,6 +195,18 @@ "description": "Custom component for calendar header. Check the PickersCalendarHeader component.", "default": "PickersCalendarHeader" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/desktop-date-range-picker.json b/docs/pages/x/api/date-pickers/desktop-date-range-picker.json index 98d873b0b18f..d9c1416cc884 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-range-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-range-picker.json @@ -156,6 +156,18 @@ "description": "Custom component for the action bar, it is placed below the picker views.", "default": "PickersActionBar" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/desktop-date-time-picker.json b/docs/pages/x/api/date-pickers/desktop-date-time-picker.json index e58f80d0bb7f..1ef5df7fdcf0 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-time-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-time-picker.json @@ -232,6 +232,18 @@ "description": "Custom component for calendar header. Check the PickersCalendarHeader component.", "default": "PickersCalendarHeader" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/desktop-time-picker.json b/docs/pages/x/api/date-pickers/desktop-time-picker.json index c14f69525db2..4891f2b2098b 100644 --- a/docs/pages/x/api/date-pickers/desktop-time-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-time-picker.json @@ -159,6 +159,18 @@ "description": "Custom component for the action bar, it is placed below the picker views.", "default": "PickersActionBar" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "desktopPaper", diff --git a/docs/pages/x/api/date-pickers/mobile-date-range-picker.json b/docs/pages/x/api/date-pickers/mobile-date-range-picker.json index 31acd8d9789f..82e56dae97fe 100644 --- a/docs/pages/x/api/date-pickers/mobile-date-range-picker.json +++ b/docs/pages/x/api/date-pickers/mobile-date-range-picker.json @@ -156,6 +156,18 @@ "description": "Custom component for the action bar, it is placed below the picker views.", "default": "PickersActionBar" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "day", diff --git a/docs/pages/x/api/date-pickers/single-input-date-range-field.json b/docs/pages/x/api/date-pickers/single-input-date-range-field.json index 8bda7a1f2bcf..432c5d2a4df8 100644 --- a/docs/pages/x/api/date-pickers/single-input-date-range-field.json +++ b/docs/pages/x/api/date-pickers/single-input-date-range-field.json @@ -1,6 +1,7 @@ { "props": { "autoFocus": { "type": { "name": "bool" } }, + "clearable": { "type": { "name": "bool" } }, "color": { "type": { "name": "enum", @@ -57,6 +58,7 @@ "describedArgs": ["value", "context"] } }, + "onClear": { "type": { "name": "func" } }, "onError": { "type": { "name": "func" }, "signature": { @@ -119,6 +121,18 @@ } }, "slots": [ + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "textField", diff --git a/docs/pages/x/api/date-pickers/single-input-date-time-range-field.json b/docs/pages/x/api/date-pickers/single-input-date-time-range-field.json index 3fa7b79e206a..84b68c95fde3 100644 --- a/docs/pages/x/api/date-pickers/single-input-date-time-range-field.json +++ b/docs/pages/x/api/date-pickers/single-input-date-time-range-field.json @@ -2,6 +2,7 @@ "props": { "ampm": { "type": { "name": "bool" }, "default": "`utils.is12HourCycleInCurrentLocale()`" }, "autoFocus": { "type": { "name": "bool" } }, + "clearable": { "type": { "name": "bool" } }, "color": { "type": { "name": "enum", @@ -64,6 +65,7 @@ "describedArgs": ["value", "context"] } }, + "onClear": { "type": { "name": "func" } }, "onError": { "type": { "name": "func" }, "signature": { @@ -144,6 +146,18 @@ } }, "slots": [ + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "textField", diff --git a/docs/pages/x/api/date-pickers/single-input-time-range-field.json b/docs/pages/x/api/date-pickers/single-input-time-range-field.json index f40874c7ca8c..4e65b1db6c17 100644 --- a/docs/pages/x/api/date-pickers/single-input-time-range-field.json +++ b/docs/pages/x/api/date-pickers/single-input-time-range-field.json @@ -2,6 +2,7 @@ "props": { "ampm": { "type": { "name": "bool" }, "default": "`utils.is12HourCycleInCurrentLocale()`" }, "autoFocus": { "type": { "name": "bool" } }, + "clearable": { "type": { "name": "bool" } }, "color": { "type": { "name": "enum", @@ -60,6 +61,7 @@ "describedArgs": ["value", "context"] } }, + "onClear": { "type": { "name": "func" } }, "onError": { "type": { "name": "func" }, "signature": { @@ -132,6 +134,18 @@ } }, "slots": [ + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "textField", diff --git a/docs/pages/x/api/date-pickers/time-field.json b/docs/pages/x/api/date-pickers/time-field.json index 694e207ef527..3838c85b52b4 100644 --- a/docs/pages/x/api/date-pickers/time-field.json +++ b/docs/pages/x/api/date-pickers/time-field.json @@ -2,6 +2,7 @@ "props": { "ampm": { "type": { "name": "bool" }, "default": "`utils.is12HourCycleInCurrentLocale()`" }, "autoFocus": { "type": { "name": "bool" } }, + "clearable": { "type": { "name": "bool" } }, "color": { "type": { "name": "enum", @@ -60,6 +61,7 @@ "describedArgs": ["value", "context"] } }, + "onClear": { "type": { "name": "func" } }, "onError": { "type": { "name": "func" }, "signature": { @@ -132,6 +134,18 @@ } }, "slots": [ + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "textField", diff --git a/docs/pages/x/api/date-pickers/time-picker.json b/docs/pages/x/api/date-pickers/time-picker.json index 8f7a3476cf2d..42966d1b4838 100644 --- a/docs/pages/x/api/date-pickers/time-picker.json +++ b/docs/pages/x/api/date-pickers/time-picker.json @@ -163,6 +163,18 @@ "description": "Custom component for the action bar, it is placed below the picker views.", "default": "PickersActionBar" }, + { + "class": null, + "name": "clearButton", + "description": "Button to clear the value.", + "default": "IconButton" + }, + { + "class": null, + "name": "clearIcon", + "description": "Icon to display inside the clear button.", + "default": "ClearIcon" + }, { "class": null, "name": "desktopPaper", diff --git a/docs/translations/api-docs/date-pickers/date-field.json b/docs/translations/api-docs/date-pickers/date-field.json index 378955d48647..689457d6d5e3 100644 --- a/docs/translations/api-docs/date-pickers/date-field.json +++ b/docs/translations/api-docs/date-pickers/date-field.json @@ -6,6 +6,11 @@ "deprecated": "", "typeDescriptions": {} }, + "clearable": { + "description": "If true, a clear button will be shown in the field allowing value clearing.", + "deprecated": "", + "typeDescriptions": {} + }, "color": { "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide.", "deprecated": "", @@ -130,6 +135,11 @@ "context": "The context containing the validation result of the current value." } }, + "onClear": { + "description": "Callback fired when the clear button is clicked.", + "deprecated": "", + "typeDescriptions": {} + }, "onError": { "description": "Callback fired when the error associated to the current value changes.", "deprecated": "", @@ -231,6 +241,8 @@ }, "classDescriptions": { "root": { "description": "Styles applied to the root element." } }, "slotDescriptions": { + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "textField": "Form control with an input to render the value. Receives the same props as @mui/material/TextField." } } diff --git a/docs/translations/api-docs/date-pickers/date-picker.json b/docs/translations/api-docs/date-pickers/date-picker.json index fe129ddf55b1..409254939a30 100644 --- a/docs/translations/api-docs/date-pickers/date-picker.json +++ b/docs/translations/api-docs/date-pickers/date-picker.json @@ -286,6 +286,8 @@ "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", "calendarHeader": "Custom component for calendar header. Check the PickersCalendarHeader component.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day. Check the PickersDay component.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", diff --git a/docs/translations/api-docs/date-pickers/date-range-picker.json b/docs/translations/api-docs/date-pickers/date-range-picker.json index 3e87d04ff351..8524121c65e8 100644 --- a/docs/translations/api-docs/date-pickers/date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/date-range-picker.json @@ -273,6 +273,8 @@ "classDescriptions": {}, "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day in range pickers. Check the DateRangePickersDay component.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", diff --git a/docs/translations/api-docs/date-pickers/date-time-field.json b/docs/translations/api-docs/date-pickers/date-time-field.json index 4242bafaa32c..e95835ca1cca 100644 --- a/docs/translations/api-docs/date-pickers/date-time-field.json +++ b/docs/translations/api-docs/date-pickers/date-time-field.json @@ -11,6 +11,11 @@ "deprecated": "", "typeDescriptions": {} }, + "clearable": { + "description": "If true, a clear button will be shown in the field allowing value clearing.", + "deprecated": "", + "typeDescriptions": {} + }, "color": { "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide.", "deprecated": "", @@ -165,6 +170,11 @@ "context": "The context containing the validation result of the current value." } }, + "onClear": { + "description": "Callback fired when the clear button is clicked.", + "deprecated": "", + "typeDescriptions": {} + }, "onError": { "description": "Callback fired when the error associated to the current value changes.", "deprecated": "", @@ -284,6 +294,8 @@ }, "classDescriptions": { "root": { "description": "Styles applied to the root element." } }, "slotDescriptions": { + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "textField": "Form control with an input to render the value. Receives the same props as @mui/material/TextField." } } diff --git a/docs/translations/api-docs/date-pickers/date-time-picker.json b/docs/translations/api-docs/date-pickers/date-time-picker.json index 8c00d1add2d0..88ea1526810e 100644 --- a/docs/translations/api-docs/date-pickers/date-time-picker.json +++ b/docs/translations/api-docs/date-pickers/date-time-picker.json @@ -354,6 +354,8 @@ "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", "calendarHeader": "Custom component for calendar header. Check the PickersCalendarHeader component.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day. Check the PickersDay component.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", diff --git a/docs/translations/api-docs/date-pickers/desktop-date-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-picker.json index 17576497cc0d..74507aa919dd 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-picker.json @@ -281,6 +281,8 @@ "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", "calendarHeader": "Custom component for calendar header. Check the PickersCalendarHeader component.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day. Check the PickersDay component.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", diff --git a/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json index 12038cb01399..861bc30997ce 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-range-picker.json @@ -268,6 +268,8 @@ "classDescriptions": {}, "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day in range pickers. Check the DateRangePickersDay component.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", diff --git a/docs/translations/api-docs/date-pickers/desktop-date-time-picker.json b/docs/translations/api-docs/date-pickers/desktop-date-time-picker.json index c803b39fc837..96aa0d020322 100644 --- a/docs/translations/api-docs/date-pickers/desktop-date-time-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-date-time-picker.json @@ -349,6 +349,8 @@ "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", "calendarHeader": "Custom component for calendar header. Check the PickersCalendarHeader component.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day. Check the PickersDay component.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", diff --git a/docs/translations/api-docs/date-pickers/desktop-time-picker.json b/docs/translations/api-docs/date-pickers/desktop-time-picker.json index 06abd1fc1f5f..b6795623bb5a 100644 --- a/docs/translations/api-docs/date-pickers/desktop-time-picker.json +++ b/docs/translations/api-docs/date-pickers/desktop-time-picker.json @@ -246,6 +246,8 @@ "classDescriptions": {}, "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", "desktopTrapFocus": "Custom component for trapping the focus inside the views on desktop.", diff --git a/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json b/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json index 8bf59738d93c..3cc069eb98c0 100644 --- a/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json +++ b/docs/translations/api-docs/date-pickers/mobile-date-range-picker.json @@ -268,6 +268,8 @@ "classDescriptions": {}, "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "day": "Custom component for day in range pickers. Check the DateRangePickersDay component.", "dialog": "Custom component for the dialog inside which the views are rendered on mobile.", "field": "", diff --git a/docs/translations/api-docs/date-pickers/single-input-date-range-field.json b/docs/translations/api-docs/date-pickers/single-input-date-range-field.json index e4c730bfee33..f237391ebf78 100644 --- a/docs/translations/api-docs/date-pickers/single-input-date-range-field.json +++ b/docs/translations/api-docs/date-pickers/single-input-date-range-field.json @@ -6,6 +6,11 @@ "deprecated": "", "typeDescriptions": {} }, + "clearable": { + "description": "If true, a clear button will be shown in the field allowing value clearing.", + "deprecated": "", + "typeDescriptions": {} + }, "color": { "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide.", "deprecated": "", @@ -130,6 +135,11 @@ "context": "The context containing the validation result of the current value." } }, + "onClear": { + "description": "Callback fired when the clear button is clicked.", + "deprecated": "", + "typeDescriptions": {} + }, "onError": { "description": "Callback fired when the error associated to the current value changes.", "deprecated": "", @@ -216,6 +226,8 @@ }, "classDescriptions": { "root": { "description": "Styles applied to the root element." } }, "slotDescriptions": { + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "textField": "Form control with an input to render the value. Receives the same props as @mui/material/TextField." } } diff --git a/docs/translations/api-docs/date-pickers/single-input-date-time-range-field.json b/docs/translations/api-docs/date-pickers/single-input-date-time-range-field.json index a95d30e9fba2..c1651c037ab7 100644 --- a/docs/translations/api-docs/date-pickers/single-input-date-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/single-input-date-time-range-field.json @@ -11,6 +11,11 @@ "deprecated": "", "typeDescriptions": {} }, + "clearable": { + "description": "If true, a clear button will be shown in the field allowing value clearing.", + "deprecated": "", + "typeDescriptions": {} + }, "color": { "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide.", "deprecated": "", @@ -165,6 +170,11 @@ "context": "The context containing the validation result of the current value." } }, + "onClear": { + "description": "Callback fired when the clear button is clicked.", + "deprecated": "", + "typeDescriptions": {} + }, "onError": { "description": "Callback fired when the error associated to the current value changes.", "deprecated": "", @@ -269,6 +279,8 @@ }, "classDescriptions": { "root": { "description": "Styles applied to the root element." } }, "slotDescriptions": { + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "textField": "Form control with an input to render the value. Receives the same props as @mui/material/TextField." } } diff --git a/docs/translations/api-docs/date-pickers/single-input-time-range-field.json b/docs/translations/api-docs/date-pickers/single-input-time-range-field.json index 7feea9066577..f1099afa2497 100644 --- a/docs/translations/api-docs/date-pickers/single-input-time-range-field.json +++ b/docs/translations/api-docs/date-pickers/single-input-time-range-field.json @@ -11,6 +11,11 @@ "deprecated": "", "typeDescriptions": {} }, + "clearable": { + "description": "If true, a clear button will be shown in the field allowing value clearing.", + "deprecated": "", + "typeDescriptions": {} + }, "color": { "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide.", "deprecated": "", @@ -145,6 +150,11 @@ "context": "The context containing the validation result of the current value." } }, + "onClear": { + "description": "Callback fired when the clear button is clicked.", + "deprecated": "", + "typeDescriptions": {} + }, "onError": { "description": "Callback fired when the error associated to the current value changes.", "deprecated": "", @@ -240,6 +250,8 @@ }, "classDescriptions": { "root": { "description": "Styles applied to the root element." } }, "slotDescriptions": { + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "textField": "Form control with an input to render the value. Receives the same props as @mui/material/TextField." } } diff --git a/docs/translations/api-docs/date-pickers/time-field.json b/docs/translations/api-docs/date-pickers/time-field.json index 7feea9066577..f1099afa2497 100644 --- a/docs/translations/api-docs/date-pickers/time-field.json +++ b/docs/translations/api-docs/date-pickers/time-field.json @@ -11,6 +11,11 @@ "deprecated": "", "typeDescriptions": {} }, + "clearable": { + "description": "If true, a clear button will be shown in the field allowing value clearing.", + "deprecated": "", + "typeDescriptions": {} + }, "color": { "description": "The color of the component. It supports both default and custom theme colors, which can be added as shown in the palette customization guide.", "deprecated": "", @@ -145,6 +150,11 @@ "context": "The context containing the validation result of the current value." } }, + "onClear": { + "description": "Callback fired when the clear button is clicked.", + "deprecated": "", + "typeDescriptions": {} + }, "onError": { "description": "Callback fired when the error associated to the current value changes.", "deprecated": "", @@ -240,6 +250,8 @@ }, "classDescriptions": { "root": { "description": "Styles applied to the root element." } }, "slotDescriptions": { + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "textField": "Form control with an input to render the value. Receives the same props as @mui/material/TextField." } } diff --git a/docs/translations/api-docs/date-pickers/time-picker.json b/docs/translations/api-docs/date-pickers/time-picker.json index 823d14046c7e..2bdc0a8bec4f 100644 --- a/docs/translations/api-docs/date-pickers/time-picker.json +++ b/docs/translations/api-docs/date-pickers/time-picker.json @@ -251,6 +251,8 @@ "classDescriptions": {}, "slotDescriptions": { "actionBar": "Custom component for the action bar, it is placed below the picker views.", + "clearButton": "Button to clear the value.", + "clearIcon": "Icon to display inside the clear button.", "desktopPaper": "Custom component for the paper rendered inside the desktop picker's Popper.", "desktopTransition": "Custom component for the desktop popper Transition.", "desktopTrapFocus": "Custom component for trapping the focus inside the views on desktop.", diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 2f7cea805d30..82ae847ca3c0 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -75,7 +75,10 @@ const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeFi const { internalProps: dateFieldInternalProps, forwardedProps } = splitFieldInternalAndForwardedProps< typeof themeProps, - keyof Omit, 'unstableFieldRef' | 'disabled'> + keyof Omit< + UseDateRangeFieldProps, + 'unstableFieldRef' | 'disabled' | 'clearable' | 'onClear' + > >(themeProps, 'date'); const { diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts index b8c559a15def..49ed9d971f6f 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.types.ts @@ -17,7 +17,7 @@ export type UseMultiInputDateRangeFieldParams< > = UseMultiInputRangeFieldParams, TTextFieldSlotProps>; export interface UseMultiInputDateRangeFieldProps - extends Omit, 'unstableFieldRef'> { + extends Omit, 'unstableFieldRef' | 'clearable' | 'onClear'> { unstableStartFieldRef?: React.Ref>; unstableEndFieldRef?: React.Ref>; } diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index a270d8126041..1749d51761cd 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -73,7 +73,10 @@ const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTim const { internalProps: dateTimeFieldInternalProps, forwardedProps } = splitFieldInternalAndForwardedProps< typeof themeProps, - keyof Omit, 'unstableFieldRef' | 'disabled'> + keyof Omit< + UseDateTimeRangeFieldProps, + 'unstableFieldRef' | 'disabled' | 'clearable' | 'onClear' + > >(themeProps, 'date-time'); const { diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts index b2e96bd6e6a7..f41e7e1c6da6 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.types.ts @@ -20,7 +20,7 @@ export type UseMultiInputDateTimeRangeFieldParams< > = UseMultiInputRangeFieldParams, TTextFieldSlotProps>; export interface UseMultiInputDateTimeRangeFieldProps - extends Omit, 'unstableFieldRef'> { + extends Omit, 'unstableFieldRef' | 'clearable' | 'onClear'> { unstableStartFieldRef?: React.Ref>; unstableEndFieldRef?: React.Ref>; } diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index 350be349f524..3b6e252e5ff7 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -75,7 +75,10 @@ const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeFi const { internalProps: timeFieldInternalProps, forwardedProps } = splitFieldInternalAndForwardedProps< typeof themeProps, - keyof Omit, 'unstableFieldRef' | 'disabled'> + keyof Omit< + UseTimeRangeFieldProps, + 'unstableFieldRef' | 'disabled' | 'clearable' | 'onClear' + > >(themeProps, 'time'); const { diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts index 16530f7b418c..f665e1fd614a 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.types.ts @@ -20,7 +20,7 @@ export type UseMultiInputTimeRangeFieldParams< > = UseMultiInputRangeFieldParams, TTextFieldSlotProps>; export interface UseMultiInputTimeRangeFieldProps - extends Omit, 'unstableFieldRef'> { + extends Omit, 'unstableFieldRef' | 'clearable' | 'onClear'> { unstableStartFieldRef?: React.Ref>; unstableEndFieldRef?: React.Ref>; } diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx index fea8b8962395..940008ed2275 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.tsx @@ -3,8 +3,13 @@ import PropTypes from 'prop-types'; import MuiTextField from '@mui/material/TextField'; import { useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; import { refType } from '@mui/utils'; -import { SingleInputDateRangeFieldProps } from './SingleInputDateRangeField.types'; +import { + SingleInputDateRangeFieldProps, + SingleInputDateRangeFieldSlotsComponentsProps, + SingleInputDateRangeFieldSlotsComponent, +} from './SingleInputDateRangeField.types'; import { useSingleInputDateRangeField } from './useSingleInputDateRangeField'; type DateRangeFieldComponent = (( @@ -44,17 +49,35 @@ const SingleInputDateRangeField = React.forwardRef(function SingleInputDateRange onKeyDown, inputMode, readOnly, + clearable, + onClear, ...fieldProps } = useSingleInputDateRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = useClearableField< + typeof fieldProps, + typeof fieldProps.InputProps, + SingleInputDateRangeFieldSlotsComponent, + SingleInputDateRangeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + components, + componentsProps, + }); + return ( ); @@ -73,6 +96,11 @@ SingleInputDateRangeField.propTypes = { */ autoFocus: PropTypes.bool, className: PropTypes.string, + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable: PropTypes.bool, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -201,6 +229,10 @@ SingleInputDateRangeField.propTypes = { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange: PropTypes.func, + /** + * Callback fired when the clear button is clicked. + */ + onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts index 4ae01f645806..e2db02ad4e5e 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/SingleInputDateRangeField.types.ts @@ -1,7 +1,12 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/base/utils'; import TextField from '@mui/material/TextField'; -import { FieldsTextFieldProps, UncapitalizeObjectKeys } from '@mui/x-date-pickers/internals'; +import { + FieldsTextFieldProps, + UncapitalizeObjectKeys, + FieldSlotsComponents, + FieldSlotsComponentsProps, +} from '@mui/x-date-pickers/internals'; import { UseDateRangeFieldDefaultizedProps, UseDateRangeFieldProps } from '../internals/models'; export interface UseSingleInputDateRangeFieldParams { @@ -53,7 +58,7 @@ export type SingleInputDateRangeFieldProps< export type SingleInputDateRangeFieldOwnerState = SingleInputDateRangeFieldProps; -export interface SingleInputDateRangeFieldSlotsComponent { +export interface SingleInputDateRangeFieldSlotsComponent extends FieldSlotsComponents { /** * Form control with an input to render the value. * Receives the same props as `@mui/material/TextField`. @@ -62,6 +67,7 @@ export interface SingleInputDateRangeFieldSlotsComponent { TextField?: React.ElementType; } -export interface SingleInputDateRangeFieldSlotsComponentsProps { +export interface SingleInputDateRangeFieldSlotsComponentsProps + extends FieldSlotsComponentsProps { textField?: SlotComponentProps>; } diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx index bf7ef82c2b1b..9cc316ba7039 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.tsx @@ -3,8 +3,13 @@ import PropTypes from 'prop-types'; import MuiTextField from '@mui/material/TextField'; import { useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; import { refType } from '@mui/utils'; -import { SingleInputDateTimeRangeFieldProps } from './SingleInputDateTimeRangeField.types'; +import { + SingleInputDateTimeRangeFieldProps, + SingleInputDateTimeRangeFieldSlotsComponent, + SingleInputDateTimeRangeFieldSlotsComponentsProps, +} from './SingleInputDateTimeRangeField.types'; import { useSingleInputDateTimeRangeField } from './useSingleInputDateTimeRangeField'; type DateRangeFieldComponent = (( @@ -45,17 +50,35 @@ const SingleInputDateTimeRangeField = React.forwardRef(function SingleInputDateT onKeyDown, inputMode, readOnly, + clearable, + onClear, ...fieldProps } = useSingleInputDateTimeRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = useClearableField< + typeof fieldProps, + typeof fieldProps.InputProps, + SingleInputDateTimeRangeFieldSlotsComponent, + SingleInputDateTimeRangeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + components, + componentsProps, + }); + return ( ); @@ -79,6 +102,11 @@ SingleInputDateTimeRangeField.propTypes = { */ autoFocus: PropTypes.bool, className: PropTypes.string, + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable: PropTypes.bool, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -235,6 +263,10 @@ SingleInputDateTimeRangeField.propTypes = { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange: PropTypes.func, + /** + * Callback fired when the clear button is clicked. + */ + onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts index 0b72006f6fe9..27cf3cd66c6a 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/SingleInputDateTimeRangeField.types.ts @@ -2,7 +2,11 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/base/utils'; import TextField from '@mui/material/TextField'; import { FieldsTextFieldProps } from '@mui/x-date-pickers/internals/models/fields'; -import { UncapitalizeObjectKeys } from '@mui/x-date-pickers/internals'; +import { + UncapitalizeObjectKeys, + FieldSlotsComponents, + FieldSlotsComponentsProps, +} from '@mui/x-date-pickers/internals'; import { UseDateTimeRangeFieldDefaultizedProps, UseDateTimeRangeFieldProps, @@ -56,7 +60,7 @@ export interface SingleInputDateTimeRangeFieldProps export type SingleInputDateTimeRangeFieldOwnerState = SingleInputDateTimeRangeFieldProps; -export interface SingleInputDateTimeRangeFieldSlotsComponent { +export interface SingleInputDateTimeRangeFieldSlotsComponent extends FieldSlotsComponents { /** * Form control with an input to render the value. * Receives the same props as `@mui/material/TextField`. @@ -65,7 +69,8 @@ export interface SingleInputDateTimeRangeFieldSlotsComponent { TextField?: React.ElementType; } -export interface SingleInputDateTimeRangeFieldSlotsComponentsProps { +export interface SingleInputDateTimeRangeFieldSlotsComponentsProps + extends FieldSlotsComponentsProps { textField?: SlotComponentProps< typeof TextField, {}, diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx index d4d28798cc9d..117bda6e8b5c 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.tsx @@ -1,10 +1,15 @@ import * as React from 'react'; import PropTypes from 'prop-types'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; import MuiTextField from '@mui/material/TextField'; import { useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { refType } from '@mui/utils'; -import { SingleInputTimeRangeFieldProps } from './SingleInputTimeRangeField.types'; +import { + SingleInputTimeRangeFieldProps, + SingleInputTimeRangeFieldSlotsComponent, + SingleInputTimeRangeFieldSlotsComponentsProps, +} from './SingleInputTimeRangeField.types'; import { useSingleInputTimeRangeField } from './useSingleInputTimeRangeField'; type DateRangeFieldComponent = (( @@ -44,17 +49,35 @@ const SingleInputTimeRangeField = React.forwardRef(function SingleInputTimeRange onKeyDown, inputMode, readOnly, + clearable, + onClear, ...fieldProps } = useSingleInputTimeRangeField({ props: textFieldProps, inputRef: externalInputRef, }); + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = useClearableField< + typeof fieldProps, + typeof fieldProps.InputProps, + SingleInputTimeRangeFieldSlotsComponent, + SingleInputTimeRangeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + components, + componentsProps, + }); + return ( ); @@ -78,6 +101,11 @@ SingleInputTimeRangeField.propTypes = { */ autoFocus: PropTypes.bool, className: PropTypes.string, + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable: PropTypes.bool, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -218,6 +246,10 @@ SingleInputTimeRangeField.propTypes = { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange: PropTypes.func, + /** + * Callback fired when the clear button is clicked. + */ + onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts index 6ce1602f23a3..67cdbf1ac1c5 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/SingleInputTimeRangeField.types.ts @@ -2,7 +2,11 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/base/utils'; import TextField from '@mui/material/TextField'; import { FieldsTextFieldProps } from '@mui/x-date-pickers/internals/models/fields'; -import { UncapitalizeObjectKeys } from '@mui/x-date-pickers/internals'; +import { + UncapitalizeObjectKeys, + FieldSlotsComponents, + FieldSlotsComponentsProps, +} from '@mui/x-date-pickers/internals'; import { UseTimeRangeFieldDefaultizedProps, UseTimeRangeFieldProps } from '../internals/models'; export interface UseSingleInputTimeRangeFieldParams { @@ -51,7 +55,7 @@ export interface SingleInputTimeRangeFieldProps export type SingleInputTimeRangeFieldOwnerState = SingleInputTimeRangeFieldProps; -export interface SingleInputTimeRangeFieldSlotsComponent { +export interface SingleInputTimeRangeFieldSlotsComponent extends FieldSlotsComponents { /** * Form control with an input to render the value. * Receives the same props as `@mui/material/TextField`. @@ -60,6 +64,7 @@ export interface SingleInputTimeRangeFieldSlotsComponent { TextField?: React.ElementType; } -export interface SingleInputTimeRangeFieldSlotsComponentsProps { +export interface SingleInputTimeRangeFieldSlotsComponentsProps + extends FieldSlotsComponentsProps { textField?: SlotComponentProps>; } diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts index 0bb6dccd50e2..9629c2757a04 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts @@ -17,6 +17,8 @@ import { UncapitalizeObjectKeys, UsePickerProps, getActiveElement, + FieldSlotsComponents, + FieldSlotsComponentsProps, } from '@mui/x-date-pickers/internals'; import { BaseMultiInputFieldProps, @@ -29,7 +31,7 @@ import { } from '../models'; import { UseRangePositionResponse } from './useRangePosition'; -export interface RangePickerFieldSlotsComponent { +export interface RangePickerFieldSlotsComponent extends FieldSlotsComponents { Field: React.ElementType; /** * Element rendered at the root. @@ -50,7 +52,7 @@ export interface RangePickerFieldSlotsComponent { TextField?: React.ElementType; } -export interface RangePickerFieldSlotsComponentsProps { +export interface RangePickerFieldSlotsComponentsProps extends FieldSlotsComponentsProps { field?: SlotComponentProps< React.ElementType< BaseMultiInputFieldProps, TDate, RangeFieldSection, unknown> @@ -236,7 +238,14 @@ const useMultiInputFieldSlotProps = ( + props: TProps, + excludedProps: Array, +): TProps => { + return (Object.keys(props) as Array).reduce((acc, key) => { + if (!excludedProps.includes(key)) { + acc[key] = props[key]; + } + return acc; + }, {} as TProps); +}; diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts index a6c72af7cdb9..1f9dc7c1e521 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField.ts @@ -24,6 +24,7 @@ import { import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; import { DateRangeValidationError } from '../../../models'; +import { excludeProps } from './shared'; export const useMultiInputDateRangeField = ({ sharedProps: inSharedProps, @@ -151,5 +152,9 @@ export const useMultiInputDateRangeField = ; - return { startDate: startDateResponse, endDate: endDateResponse }; + /* TODO: Undo this change when a clearable behavior for multiple input range fields is implemented */ + return { + startDate: excludeProps(startDateResponse, ['clearable', 'onClear']), + endDate: excludeProps(endDateResponse, ['clearable', 'onClear']), + }; }; diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts index 5d9a6770c776..148ffed7e97d 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField.ts @@ -30,6 +30,7 @@ import { } from '../../utils/validation/validateDateTimeRange'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; +import { excludeProps } from './shared'; export const useDefaultizedDateTimeRangeFieldProps = ( props: UseMultiInputDateTimeRangeFieldProps, @@ -172,5 +173,9 @@ export const useMultiInputDateTimeRangeField = ; - return { startDate: startDateResponse, endDate: endDateResponse }; + /* TODO: Undo this change when a clearable behavior for multiple input range fields is implemented */ + return { + startDate: excludeProps(startDateResponse, ['clearable', 'onClear']), + endDate: excludeProps(endDateResponse, ['clearable', 'onClear']), + }; }; diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts index 092b9e8b121a..cab1dae97d7e 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField.ts @@ -28,6 +28,7 @@ import type { } from '../../../MultiInputTimeRangeField/MultiInputTimeRangeField.types'; import { rangeValueManager } from '../../utils/valueManagers'; import type { UseMultiInputRangeFieldResponse } from './useMultiInputRangeField.types'; +import { excludeProps } from './shared'; export const useDefaultizedTimeRangeFieldProps = ( props: UseMultiInputTimeRangeFieldProps, @@ -162,5 +163,9 @@ export const useMultiInputTimeRangeField = ; - return { startDate: startDateResponse, endDate: endDateResponse }; + /* TODO: Undo this change when a clearable behavior for multiple input range fields is implemented */ + return { + startDate: excludeProps(startDateResponse, ['clearable', 'onClear']), + endDate: excludeProps(endDateResponse, ['clearable', 'onClear']), + }; }; diff --git a/packages/x-date-pickers/src/DateField/DateField.tsx b/packages/x-date-pickers/src/DateField/DateField.tsx index 9ca2e103dc45..6d64df93608b 100644 --- a/packages/x-date-pickers/src/DateField/DateField.tsx +++ b/packages/x-date-pickers/src/DateField/DateField.tsx @@ -4,8 +4,13 @@ import MuiTextField from '@mui/material/TextField'; import { useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { refType } from '@mui/utils'; -import { DateFieldProps } from './DateField.types'; +import { + DateFieldProps, + DateFieldSlotsComponent, + DateFieldSlotsComponentsProps, +} from './DateField.types'; import { useDateField } from './useDateField'; +import { useClearableField } from '../hooks'; type DateFieldComponent = (( props: DateFieldProps & React.RefAttributes, @@ -43,17 +48,38 @@ const DateField = React.forwardRef(function DateField( onKeyDown, inputMode, readOnly, + clearable, + onClear, ...fieldProps } = useDateField({ props: textFieldProps, inputRef: externalInputRef, }); + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = useClearableField< + typeof fieldProps, + typeof fieldProps.InputProps, + DateFieldSlotsComponent, + DateFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + components, + componentsProps, + }); + return ( ); @@ -70,6 +96,11 @@ DateField.propTypes = { */ autoFocus: PropTypes.bool, className: PropTypes.string, + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable: PropTypes.bool, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -198,6 +229,10 @@ DateField.propTypes = { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange: PropTypes.func, + /** + * Callback fired when the clear button is clicked. + */ + onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. diff --git a/packages/x-date-pickers/src/DateField/DateField.types.ts b/packages/x-date-pickers/src/DateField/DateField.types.ts index 2664c54f8769..6b59ceee896c 100644 --- a/packages/x-date-pickers/src/DateField/DateField.types.ts +++ b/packages/x-date-pickers/src/DateField/DateField.types.ts @@ -1,6 +1,7 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/base/utils'; import TextField from '@mui/material/TextField'; +import { FieldSlotsComponents, FieldSlotsComponentsProps } from '../internals'; import { DateValidationError, FieldSection } from '../models'; import { UseFieldInternalProps } from '../internals/hooks/useField'; import { DefaultizedProps, MakeOptional } from '../internals/models/helpers'; @@ -45,7 +46,7 @@ export interface DateFieldProps export type DateFieldOwnerState = DateFieldProps; -export interface DateFieldSlotsComponent { +export interface DateFieldSlotsComponent extends FieldSlotsComponents { /** * Form control with an input to render the value. * Receives the same props as `@mui/material/TextField`. @@ -54,6 +55,6 @@ export interface DateFieldSlotsComponent { TextField?: React.ElementType; } -export interface DateFieldSlotsComponentsProps { +export interface DateFieldSlotsComponentsProps extends FieldSlotsComponentsProps { textField?: SlotComponentProps>; } diff --git a/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx b/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx index c36fd6ce82dc..a855ec96def9 100644 --- a/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx +++ b/packages/x-date-pickers/src/DateTimeField/DateTimeField.tsx @@ -4,8 +4,13 @@ import MuiTextField from '@mui/material/TextField'; import { useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { refType } from '@mui/utils'; -import { DateTimeFieldProps } from './DateTimeField.types'; +import { + DateTimeFieldProps, + DateTimeFieldSlotsComponent, + DateTimeFieldSlotsComponentsProps, +} from './DateTimeField.types'; import { useDateTimeField } from './useDateTimeField'; +import { useClearableField } from '../hooks'; type DateTimeFieldComponent = (( props: DateTimeFieldProps & React.RefAttributes, @@ -45,17 +50,34 @@ const DateTimeField = React.forwardRef(function DateTimeField( onKeyDown, inputMode, readOnly, + clearable, + onClear, ...fieldProps } = useDateTimeField({ props: textFieldProps, inputRef: externalInputRef, }); + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = useClearableField< + typeof fieldProps, + typeof fieldProps.InputProps, + DateTimeFieldSlotsComponent, + DateTimeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + components, + componentsProps, + }); return ( ); @@ -77,6 +99,11 @@ DateTimeField.propTypes = { */ autoFocus: PropTypes.bool, className: PropTypes.string, + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable: PropTypes.bool, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -233,6 +260,10 @@ DateTimeField.propTypes = { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange: PropTypes.func, + /** + * Callback fired when the clear button is clicked. + */ + onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. diff --git a/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts b/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts index 5b860c84e24b..cf9ce438e7b2 100644 --- a/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts +++ b/packages/x-date-pickers/src/DateTimeField/DateTimeField.types.ts @@ -15,6 +15,7 @@ import { } from '../internals/models/validation'; import { FieldsTextFieldProps } from '../internals/models/fields'; import { UncapitalizeObjectKeys } from '../internals/utils/slots-migration'; +import { FieldSlotsComponents, FieldSlotsComponentsProps } from '../internals'; export interface UseDateTimeFieldParams { props: UseDateTimeFieldComponentProps; @@ -79,7 +80,7 @@ export interface DateTimeFieldProps export type DateTimeFieldOwnerState = DateTimeFieldProps; -export interface DateTimeFieldSlotsComponent { +export interface DateTimeFieldSlotsComponent extends FieldSlotsComponents { /** * Form control with an input to render the value. * Receives the same props as `@mui/material/TextField`. @@ -88,6 +89,6 @@ export interface DateTimeFieldSlotsComponent { TextField?: React.ElementType; } -export interface DateTimeFieldSlotsComponentsProps { +export interface DateTimeFieldSlotsComponentsProps extends FieldSlotsComponentsProps { textField?: SlotComponentProps>; } diff --git a/packages/x-date-pickers/src/TimeField/TimeField.tsx b/packages/x-date-pickers/src/TimeField/TimeField.tsx index 0c0b602fe128..a60706c388f9 100644 --- a/packages/x-date-pickers/src/TimeField/TimeField.tsx +++ b/packages/x-date-pickers/src/TimeField/TimeField.tsx @@ -4,8 +4,13 @@ import MuiTextField from '@mui/material/TextField'; import { useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { refType } from '@mui/utils'; -import { TimeFieldProps } from './TimeField.types'; +import { + TimeFieldProps, + TimeFieldSlotsComponent, + TimeFieldSlotsComponentsProps, +} from './TimeField.types'; import { useTimeField } from './useTimeField'; +import { useClearableField } from '../hooks'; type TimeFieldComponent = (( props: TimeFieldProps & React.RefAttributes, @@ -43,17 +48,35 @@ const TimeField = React.forwardRef(function TimeField( onKeyDown, inputMode, readOnly, + clearable, + onClear, ...fieldProps } = useTimeField({ props: textFieldProps, inputRef: externalInputRef, }); + const { InputProps: ProcessedInputProps, fieldProps: processedFieldProps } = useClearableField< + typeof fieldProps, + typeof fieldProps.InputProps, + TimeFieldSlotsComponent, + TimeFieldSlotsComponentsProps + >({ + onClear, + clearable, + fieldProps, + InputProps: fieldProps.InputProps, + slots, + slotProps, + components, + componentsProps, + }); + return ( ); @@ -75,6 +98,11 @@ TimeField.propTypes = { */ autoFocus: PropTypes.bool, className: PropTypes.string, + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable: PropTypes.bool, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -215,6 +243,10 @@ TimeField.propTypes = { * @param {FieldChangeHandlerContext} context The context containing the validation result of the current value. */ onChange: PropTypes.func, + /** + * Callback fired when the clear button is clicked. + */ + onClear: PropTypes.func, /** * Callback fired when the error associated to the current value changes. * @template TValue The value type. Will be either the same type as `value` or `null`. Can be in `[start, end]` format in case of range value. diff --git a/packages/x-date-pickers/src/TimeField/TimeField.types.ts b/packages/x-date-pickers/src/TimeField/TimeField.types.ts index de566f65bd91..fc95372257e9 100644 --- a/packages/x-date-pickers/src/TimeField/TimeField.types.ts +++ b/packages/x-date-pickers/src/TimeField/TimeField.types.ts @@ -7,6 +7,7 @@ import { BaseTimeValidationProps, TimeValidationProps } from '../internals/model import { UncapitalizeObjectKeys } from '../internals/utils/slots-migration'; import { FieldsTextFieldProps } from '../internals/models/fields'; import { FieldSection, TimeValidationError } from '../models'; +import { FieldSlotsComponents, FieldSlotsComponentsProps } from '../internals'; export interface UseTimeFieldParams { props: UseTimeFieldComponentProps; @@ -66,7 +67,7 @@ export interface TimeFieldProps export type TimeFieldOwnerState = TimeFieldProps; -export interface TimeFieldSlotsComponent { +export interface TimeFieldSlotsComponent extends FieldSlotsComponents { /** * Form control with an input to render the value. * Receives the same props as `@mui/material/TextField`. @@ -75,6 +76,6 @@ export interface TimeFieldSlotsComponent { TextField?: React.ElementType; } -export interface TimeFieldSlotsComponentsProps { +export interface TimeFieldSlotsComponentsProps extends FieldSlotsComponentsProps { textField?: SlotComponentProps>; } diff --git a/packages/x-date-pickers/src/hooks/index.tsx b/packages/x-date-pickers/src/hooks/index.tsx new file mode 100644 index 000000000000..aa5038bf7570 --- /dev/null +++ b/packages/x-date-pickers/src/hooks/index.tsx @@ -0,0 +1 @@ +export { useClearableField } from './useClearableField'; diff --git a/packages/x-date-pickers/src/hooks/useClearableField.tsx b/packages/x-date-pickers/src/hooks/useClearableField.tsx new file mode 100644 index 000000000000..ee37ea49af38 --- /dev/null +++ b/packages/x-date-pickers/src/hooks/useClearableField.tsx @@ -0,0 +1,113 @@ +import * as React from 'react'; +import { useSlotProps } from '@mui/base/utils'; +import MuiIconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; +import { ClearIcon } from '../icons'; +import { + FieldSlotsComponents, + FieldSlotsComponentsProps, + FieldsTextFieldProps, + useLocaleText, +} from '../internals'; + +type UseClearableFieldProps< + TFieldProps extends FieldsTextFieldProps, + TInputProps extends { endAdornment?: React.ReactNode } | undefined, + TFieldSlots extends FieldSlotsComponents, + TFieldSlotsComponentsProps extends FieldSlotsComponentsProps, +> = { + clearable: boolean; + fieldProps: TFieldProps; + InputProps: TInputProps; + onClear: React.MouseEventHandler; + slots?: { [K in keyof TFieldSlots as Uncapitalize]: TFieldSlots[K] }; + slotProps?: TFieldSlotsComponentsProps; + components?: TFieldSlots; + componentsProps?: TFieldSlotsComponentsProps; +}; + +export const useClearableField = < + TFieldProps extends FieldsTextFieldProps, + TInputProps extends { endAdornment?: React.ReactNode } | undefined, + TFieldSlotsComponents extends FieldSlotsComponents, + TFieldSlotsComponentsProps extends FieldSlotsComponentsProps, +>({ + clearable, + fieldProps: forwardedFieldProps, + InputProps: ForwardedInputProps, + onClear, + slots, + slotProps, + components, + componentsProps, +}: UseClearableFieldProps< + TFieldProps, + TInputProps, + TFieldSlotsComponents, + TFieldSlotsComponentsProps +>) => { + const localeText = useLocaleText(); + + const IconButton = slots?.clearButton ?? components?.ClearButton ?? MuiIconButton; + // The spread is here to avoid this bug mui/material-ui#34056 + const { ownerState, ...iconButtonProps } = useSlotProps({ + elementType: IconButton, + externalSlotProps: slotProps?.clearButton ?? componentsProps?.clearButton, + ownerState: {}, + className: 'clearButton', + additionalProps: { + title: localeText.fieldClearLabel, + }, + }); + const EndClearIcon = slots?.clearIcon ?? components?.ClearIcon ?? ClearIcon; + const endClearIconProps = useSlotProps({ + elementType: EndClearIcon, + externalSlotProps: slotProps?.clearIcon ?? componentsProps?.clearIcon, + ownerState: {}, + }); + + const InputProps = { + ...ForwardedInputProps, + endAdornment: clearable ? ( + + + + + + + {ForwardedInputProps?.endAdornment} + + ) : ( + ForwardedInputProps?.endAdornment + ), + }; + + const fieldProps: TFieldProps = { + ...forwardedFieldProps, + sx: [ + { + '& .clearButton': { + opacity: 1, + }, + '@media (pointer: fine)': { + '& .clearButton': { + opacity: 0, + }, + '&:hover, &:focus-within': { + '.clearButton': { + opacity: 1, + }, + }, + }, + }, + ...(Array.isArray(forwardedFieldProps.sx) + ? forwardedFieldProps.sx + : [forwardedFieldProps.sx]), + ], + }; + + return { InputProps, fieldProps }; +}; diff --git a/packages/x-date-pickers/src/icons/index.tsx b/packages/x-date-pickers/src/icons/index.tsx index 74cf00414bb4..6ce0eb246190 100644 --- a/packages/x-date-pickers/src/icons/index.tsx +++ b/packages/x-date-pickers/src/icons/index.tsx @@ -59,3 +59,11 @@ export const TimeIcon = createSvgIcon( , 'Time', ); + +/** + * @ignore - internal component. + */ +export const ClearIcon = createSvgIcon( + , + 'Clear', +); diff --git a/packages/x-date-pickers/src/index.ts b/packages/x-date-pickers/src/index.ts index c7e082779e50..680bcd4736db 100644 --- a/packages/x-date-pickers/src/index.ts +++ b/packages/x-date-pickers/src/index.ts @@ -48,3 +48,5 @@ export { DEFAULT_DESKTOP_MODE_MEDIA_QUERY } from './internals/utils/utils'; export * from './models'; export * from './icons'; + +export * from './hooks'; diff --git a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx index 65f3168f21c1..738976af622f 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx @@ -142,6 +142,8 @@ export const useDesktopPicker = < unknown >['slots'] = { textField: slots.textField, + clearIcon: slots.clearIcon, + clearButton: slots.clearButton, ...fieldProps.slots, }; diff --git a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts index c6410882e820..9be1bece44bf 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts @@ -23,13 +23,15 @@ import { UsePickerValueNonStaticProps } from '../usePicker/usePickerValue.types' import { UsePickerViewsNonStaticProps, UsePickerViewsProps } from '../usePicker/usePickerViews'; import { UncapitalizeObjectKeys } from '../../utils/slots-migration'; import { DateOrTimeViewWithMeridiem } from '../../models'; +import { FieldSlotsComponents, FieldSlotsComponentsProps } from '../useField'; export interface UseDesktopPickerSlotsComponent extends Pick< PickersPopperSlotsComponent, 'DesktopPaper' | 'DesktopTransition' | 'DesktopTrapFocus' | 'Popper' >, - ExportedPickersLayoutSlotsComponent { + ExportedPickersLayoutSlotsComponent, + FieldSlotsComponents { /** * Component used to enter the date with the keyboard. */ @@ -66,7 +68,8 @@ export interface ExportedUseDesktopPickerSlotsComponentsProps< TDate, TView extends DateOrTimeViewWithMeridiem, > extends PickersPopperSlotsComponentsProps, - ExportedPickersLayoutSlotsComponentsProps { + ExportedPickersLayoutSlotsComponentsProps, + FieldSlotsComponentsProps { field?: SlotComponentProps< React.ElementType>, {}, diff --git a/packages/x-date-pickers/src/internals/hooks/useField/index.ts b/packages/x-date-pickers/src/internals/hooks/useField/index.ts index 955beab828fe..a4fc8fdccdbd 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/index.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/index.ts @@ -8,6 +8,8 @@ export type { FieldChangeHandler, FieldChangeHandlerContext, FieldRef, + FieldSlotsComponents, + FieldSlotsComponentsProps, } from './useField.types'; export { splitFormatIntoSections, diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts index f94b18ce9f97..c2a7b7d8a67a 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.ts @@ -55,6 +55,8 @@ export const useField = < onMouseUp, onPaste, error, + clearable, + onClear, ...otherForwardedProps }, fieldValueManager, @@ -100,12 +102,17 @@ export const useField = < ); } const sectionIndex = nextSectionIndex === -1 ? state.sections.length - 1 : nextSectionIndex - 1; - setSelectedSections(sectionIndex); }; - const handleInputClick = useEventCallback((...args) => { - onClick?.(...(args as [])); + const handleInputClick = useEventCallback((event: React.MouseEvent, ...args) => { + // The click event on the clear button would propagate to the input, trigger this handler and result in a wrong section selection. + // We avoid this by checking if the call of `handleInputClick` is actually intended, or a side effect. + if (event.isDefaultPrevented()) { + return; + } + + onClick?.(event, ...(args as [])); syncSelectionFromDOM(); }); @@ -476,8 +483,12 @@ export const useField = < }, [selectedSectionIndexes, state.sections]); const inputHasFocus = inputRef.current && inputRef.current === getActiveElement(document); - const shouldShowPlaceholder = - !inputHasFocus && valueManager.areValuesEqual(utils, state.value, valueManager.emptyValue); + const areAllSectionsEmpty = valueManager.areValuesEqual( + utils, + state.value, + valueManager.emptyValue, + ); + const shouldShowPlaceholder = !inputHasFocus && areAllSectionsEmpty; React.useImperativeHandle(unstableFieldRef, () => ({ getSections: () => state.sections, @@ -499,6 +510,14 @@ export const useField = < setSelectedSections: (activeSectionIndex) => setSelectedSections(activeSectionIndex), })); + const handleClearValue = useEventCallback((event: React.MouseEvent, ...args) => { + event.preventDefault(); + onClear?.(event, ...(args as [])); + clearValue(); + inputRef?.current?.focus(); + setSelectedSections(0); + }); + return { placeholder, autoComplete: 'off', @@ -513,7 +532,9 @@ export const useField = < onChange: handleInputChange, onKeyDown: handleInputKeyDown, onMouseUp: handleInputMouseUp, + onClear: handleClearValue, error: inputError, ref: handleRef, + clearable: Boolean(clearable && !areAllSectionsEmpty && !readOnly), }; }; diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts b/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts index c8eb121a0c51..dc29061c355b 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useField.types.ts @@ -1,4 +1,7 @@ import * as React from 'react'; +import { SlotComponentProps } from '@mui/base/utils'; +import IconButton from '@mui/material/IconButton'; +import { ClearIcon } from '../../../icons'; import { FieldSectionType, FieldSection, @@ -116,6 +119,15 @@ export interface UseFieldInternalProps>; + /** + * Callback fired when the clear button is clicked. + */ + onClear?: React.MouseEventHandler; + /** + * If `true`, a clear button will be shown in the field allowing value clearing. + * @default false + */ + clearable?: boolean; } export interface FieldRef { @@ -141,10 +153,12 @@ export interface UseFieldForwardedProps { onKeyDown?: React.KeyboardEventHandler; onMouseUp?: React.MouseEventHandler; onPaste?: React.ClipboardEventHandler; - onClick?: () => void; + onClick?: React.MouseEventHandler; onFocus?: () => void; onBlur?: () => void; error?: boolean; + onClear?: React.MouseEventHandler; + clearable?: boolean; } export type UseFieldResponse = Omit< @@ -371,3 +385,21 @@ export type SectionOrdering = { */ endIndex: number; }; + +export interface FieldSlotsComponents { + /** + * Icon to display inside the clear button. + * @default ClearIcon + */ + ClearIcon?: React.ElementType; + /** + * Button to clear the value. + * @default IconButton + */ + ClearButton?: React.ElementType; +} + +export interface FieldSlotsComponentsProps { + clearIcon?: SlotComponentProps; + clearButton?: SlotComponentProps; +} diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index be9a99358b3f..fdb7337873f1 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -66,6 +66,8 @@ export type { FieldValueManager, FieldChangeHandler, FieldChangeHandlerContext, + FieldSlotsComponents, + FieldSlotsComponentsProps, } from './hooks/useField'; export type { MobileOnlyPickerProps } from './hooks/useMobilePicker'; export { usePicker } from './hooks/usePicker'; diff --git a/packages/x-date-pickers/src/locales/beBY.ts b/packages/x-date-pickers/src/locales/beBY.ts index 76004e920f7a..ff290e09184b 100644 --- a/packages/x-date-pickers/src/locales/beBY.ts +++ b/packages/x-date-pickers/src/locales/beBY.ts @@ -66,6 +66,7 @@ const beBYPickers: Partial> = { value !== null && utils.isValid(value) ? `Абраць час, абрыны час ${utils.format(value, 'fullTime')}` : 'Абраць час', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'абраць час', diff --git a/packages/x-date-pickers/src/locales/caES.ts b/packages/x-date-pickers/src/locales/caES.ts index 4253843313b3..ad82c3f7c3ec 100644 --- a/packages/x-date-pickers/src/locales/caES.ts +++ b/packages/x-date-pickers/src/locales/caES.ts @@ -67,6 +67,7 @@ const caESPickers: Partial> = { value !== null && utils.isValid(value) ? `Tria l'hora, l'hora triada és ${utils.format(value, 'fullTime')}` : "Tria l'hora", + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'tria la data', diff --git a/packages/x-date-pickers/src/locales/csCZ.ts b/packages/x-date-pickers/src/locales/csCZ.ts index 9630ed8fd5be..baab53b389af 100644 --- a/packages/x-date-pickers/src/locales/csCZ.ts +++ b/packages/x-date-pickers/src/locales/csCZ.ts @@ -66,6 +66,7 @@ const csCZPickers: Partial> = { value !== null && utils.isValid(value) ? `Vyberte čas, vybraný čas je ${utils.format(value, 'fullTime')}` : 'Vyberte čas', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'vyberte čas', diff --git a/packages/x-date-pickers/src/locales/daDK.ts b/packages/x-date-pickers/src/locales/daDK.ts index f46f0b28a797..45be74c3579f 100644 --- a/packages/x-date-pickers/src/locales/daDK.ts +++ b/packages/x-date-pickers/src/locales/daDK.ts @@ -68,6 +68,7 @@ const daDKPickers: Partial> = { value !== null && utils.isValid(value) ? `Vælg tidspunkt, valgte tidspunkt er ${utils.format(value, 'fullTime')}` : 'Vælg tidspunkt', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'vælg tidspunkt', diff --git a/packages/x-date-pickers/src/locales/deDE.ts b/packages/x-date-pickers/src/locales/deDE.ts index 8319f063b1b8..01bee187797d 100644 --- a/packages/x-date-pickers/src/locales/deDE.ts +++ b/packages/x-date-pickers/src/locales/deDE.ts @@ -68,6 +68,7 @@ const deDEPickers: Partial> = { value !== null && utils.isValid(value) ? `Uhrzeit auswählen, gewählte Uhrzeit ist ${utils.format(value, 'fullTime')}` : 'Uhrzeit auswählen', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'Uhrzeit auswählen', diff --git a/packages/x-date-pickers/src/locales/elGR.ts b/packages/x-date-pickers/src/locales/elGR.ts index 7a15dc49987d..2c4ae628dc82 100644 --- a/packages/x-date-pickers/src/locales/elGR.ts +++ b/packages/x-date-pickers/src/locales/elGR.ts @@ -67,6 +67,7 @@ const elGRPickers: Partial> = { value !== null && utils.isValid(value) ? `Επιλέξτε ώρα, η επιλεγμένη ώρα είναι ${utils.format(value, 'fullTime')}` : 'Επιλέξτε ώρα', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'επιλέξτε ώρα', diff --git a/packages/x-date-pickers/src/locales/enUS.ts b/packages/x-date-pickers/src/locales/enUS.ts index 53fce05b2081..f46dde84fe5b 100644 --- a/packages/x-date-pickers/src/locales/enUS.ts +++ b/packages/x-date-pickers/src/locales/enUS.ts @@ -60,6 +60,8 @@ const enUSPickers: PickersLocaleText = { ? `Choose time, selected time is ${utils.format(value, 'fullTime')}` : 'Choose time', + fieldClearLabel: 'Clear value', + // Table labels timeTableLabel: 'pick time', dateTableLabel: 'pick date', diff --git a/packages/x-date-pickers/src/locales/esES.ts b/packages/x-date-pickers/src/locales/esES.ts index b5fec0ff00d6..273cf066ef20 100644 --- a/packages/x-date-pickers/src/locales/esES.ts +++ b/packages/x-date-pickers/src/locales/esES.ts @@ -67,6 +67,7 @@ const esESPickers: Partial> = { value !== null && utils.isValid(value) ? `Elige la hora, la hora elegido es ${utils.format(value, 'fullTime')}` : 'Elige la hora', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'elige la fecha', diff --git a/packages/x-date-pickers/src/locales/faIR.ts b/packages/x-date-pickers/src/locales/faIR.ts index 5a748c92810d..64545ebd2a26 100644 --- a/packages/x-date-pickers/src/locales/faIR.ts +++ b/packages/x-date-pickers/src/locales/faIR.ts @@ -67,6 +67,7 @@ const faIRPickers: Partial> = { value !== null && utils.isValid(value) ? `ساعت را انتخاب کنید، ساعت انتخاب شده ${utils.format(value, 'fullTime')} می باشد` : 'ساعت را انتخاب کنید', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'انتخاب تاریخ', diff --git a/packages/x-date-pickers/src/locales/fiFI.ts b/packages/x-date-pickers/src/locales/fiFI.ts index cef50d5f4072..9bcca993f08b 100644 --- a/packages/x-date-pickers/src/locales/fiFI.ts +++ b/packages/x-date-pickers/src/locales/fiFI.ts @@ -65,6 +65,7 @@ const fiFIPickers: Partial> = { value !== null && utils.isValid(value) ? `Valitse aika, valittu aika on ${utils.format(value, 'fullTime')}` : 'Valitse aika', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'valitse aika', diff --git a/packages/x-date-pickers/src/locales/frFR.ts b/packages/x-date-pickers/src/locales/frFR.ts index 14ac7e7d7dbc..6fdb39d1e9ba 100644 --- a/packages/x-date-pickers/src/locales/frFR.ts +++ b/packages/x-date-pickers/src/locales/frFR.ts @@ -67,6 +67,7 @@ const frFRPickers: Partial> = { value !== null && utils.isValid(value) ? `Choisir l'heure, l'heure sélectionnée est ${utils.format(value, 'fullTime')}` : "Choisir l'heure", + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: "choix de l'heure", diff --git a/packages/x-date-pickers/src/locales/heIL.ts b/packages/x-date-pickers/src/locales/heIL.ts index dceedbbff2b6..98f438249a0c 100644 --- a/packages/x-date-pickers/src/locales/heIL.ts +++ b/packages/x-date-pickers/src/locales/heIL.ts @@ -65,6 +65,7 @@ const heILPickers: Partial> = { value !== null && utils.isValid(value) ? `בחירת שעה, השעה שנבחרה היא ${utils.format(value, 'fullTime')}` : 'בחירת שעה', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'בחירת שעה', diff --git a/packages/x-date-pickers/src/locales/huHU.ts b/packages/x-date-pickers/src/locales/huHU.ts index 86fc0a23469c..3738aa46e1af 100644 --- a/packages/x-date-pickers/src/locales/huHU.ts +++ b/packages/x-date-pickers/src/locales/huHU.ts @@ -68,6 +68,7 @@ const huHUPickers: Partial> = { value !== null && utils.isValid(value) ? `Válasszon időt, a kiválasztott idő: ${utils.format(value, 'fullTime')}` : 'Válasszon időt', + fieldClearLabel: 'Tartalom ürítése', // Table labels timeTableLabel: 'válasszon időt', diff --git a/packages/x-date-pickers/src/locales/isIS.ts b/packages/x-date-pickers/src/locales/isIS.ts index cfdfa2124e29..e478eefdd3f3 100644 --- a/packages/x-date-pickers/src/locales/isIS.ts +++ b/packages/x-date-pickers/src/locales/isIS.ts @@ -65,6 +65,7 @@ const isISPickers: Partial> = { value !== null && utils.isValid(value) ? `Velja tíma, valinn tími er ${utils.format(value, 'fullTime')}` : 'Velja tíma', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'velja tíma', diff --git a/packages/x-date-pickers/src/locales/itIT.ts b/packages/x-date-pickers/src/locales/itIT.ts index feb675cc5fcc..e7ac7b62703b 100644 --- a/packages/x-date-pickers/src/locales/itIT.ts +++ b/packages/x-date-pickers/src/locales/itIT.ts @@ -67,6 +67,7 @@ const itITPickers: Partial> = { value !== null && utils.isValid(value) ? `Scegli l'ora, l'ora selezionata è ${utils.format(value, 'fullTime')}` : "Scegli l'ora", + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: "scegli un'ora", diff --git a/packages/x-date-pickers/src/locales/jaJP.ts b/packages/x-date-pickers/src/locales/jaJP.ts index 74aa23834109..0d822813e62d 100644 --- a/packages/x-date-pickers/src/locales/jaJP.ts +++ b/packages/x-date-pickers/src/locales/jaJP.ts @@ -68,6 +68,7 @@ const jaJPPickers: Partial> = { value !== null && utils.isValid(value) ? `時間を選択してください。選択した時間は ${utils.format(value, 'fullTime')} です` : '時間を選択してください', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: '時間を選択', diff --git a/packages/x-date-pickers/src/locales/koKR.ts b/packages/x-date-pickers/src/locales/koKR.ts index a44d3c218291..51c64f0c4bb4 100644 --- a/packages/x-date-pickers/src/locales/koKR.ts +++ b/packages/x-date-pickers/src/locales/koKR.ts @@ -67,6 +67,7 @@ const koKRPickers: Partial> = { value !== null && utils.isValid(value) ? `시간을 선택하세요. 현재 선택된 시간은 ${utils.format(value, 'fullTime')}입니다.` : '시간을 선택하세요', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: '선택한 시간', diff --git a/packages/x-date-pickers/src/locales/kzKZ.ts b/packages/x-date-pickers/src/locales/kzKZ.ts index bb43a39e2ae7..c27450d3df48 100644 --- a/packages/x-date-pickers/src/locales/kzKZ.ts +++ b/packages/x-date-pickers/src/locales/kzKZ.ts @@ -66,6 +66,7 @@ const kzKZPickers: Partial> = { value !== null && utils.isValid(value) ? `Уақытты таңдаңыз, таңдалған уақыт ${utils.format(value, 'fullTime')}` : 'Уақытты таңдаңыз', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'уақытты таңдау', diff --git a/packages/x-date-pickers/src/locales/nbNO.ts b/packages/x-date-pickers/src/locales/nbNO.ts index 8679592b861e..68b44e72e9c2 100644 --- a/packages/x-date-pickers/src/locales/nbNO.ts +++ b/packages/x-date-pickers/src/locales/nbNO.ts @@ -65,6 +65,7 @@ const nbNOPickers: Partial> = { value !== null && utils.isValid(value) ? `Velg tid, valgt tid er ${utils.format(value, 'fullTime')}` : 'Velg tid', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'velg tid', diff --git a/packages/x-date-pickers/src/locales/nlNL.ts b/packages/x-date-pickers/src/locales/nlNL.ts index 3d73af4c0595..56477a3234d5 100644 --- a/packages/x-date-pickers/src/locales/nlNL.ts +++ b/packages/x-date-pickers/src/locales/nlNL.ts @@ -67,6 +67,7 @@ const nlNLPickers: Partial> = { value !== null && utils.isValid(value) ? `Kies tijd, geselecteerde tijd is ${utils.format(value, 'fullTime')}` : 'Kies tijd', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'kies tijd', diff --git a/packages/x-date-pickers/src/locales/plPL.ts b/packages/x-date-pickers/src/locales/plPL.ts index 6b7720e969c3..dc2133f322d6 100644 --- a/packages/x-date-pickers/src/locales/plPL.ts +++ b/packages/x-date-pickers/src/locales/plPL.ts @@ -65,6 +65,7 @@ const plPLPickers: Partial> = { value !== null && utils.isValid(value) ? `Wybierz czas, obecnie wybrany czas to ${utils.format(value, 'fullTime')}` : 'Wybierz czas', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'wybierz czas', diff --git a/packages/x-date-pickers/src/locales/ptBR.ts b/packages/x-date-pickers/src/locales/ptBR.ts index 032c8ccfccf0..4b0d4ccfa96c 100644 --- a/packages/x-date-pickers/src/locales/ptBR.ts +++ b/packages/x-date-pickers/src/locales/ptBR.ts @@ -67,6 +67,7 @@ const ptBRPickers: Partial> = { value !== null && utils.isValid(value) ? `Escolha uma hora, hora selecionada ${utils.format(value, 'fullTime')}` : 'Escolha uma hora', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'escolha uma hora', diff --git a/packages/x-date-pickers/src/locales/roRO.ts b/packages/x-date-pickers/src/locales/roRO.ts index 7c24c4a6b680..2334197303ae 100644 --- a/packages/x-date-pickers/src/locales/roRO.ts +++ b/packages/x-date-pickers/src/locales/roRO.ts @@ -68,6 +68,7 @@ const roROPickers: Partial> = { value !== null && utils.isValid(value) ? `Selectați ora, ora selectată este ${utils.format(value, 'fullTime')}` : 'Selectați ora', + fieldClearLabel: 'Golire conținut', // Table labels timeTableLabel: 'Selectați ora', diff --git a/packages/x-date-pickers/src/locales/ruRU.ts b/packages/x-date-pickers/src/locales/ruRU.ts index d947bcd5b253..8f98d866c4c6 100644 --- a/packages/x-date-pickers/src/locales/ruRU.ts +++ b/packages/x-date-pickers/src/locales/ruRU.ts @@ -66,6 +66,7 @@ const ruRUPickers: Partial> = { value !== null && utils.isValid(value) ? `Выберите время, выбрано время ${utils.format(value, 'fullTime')}` : 'Выберите время', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'выбрать время', diff --git a/packages/x-date-pickers/src/locales/skSK.ts b/packages/x-date-pickers/src/locales/skSK.ts index 22ab6650219e..96cdfd13bde1 100644 --- a/packages/x-date-pickers/src/locales/skSK.ts +++ b/packages/x-date-pickers/src/locales/skSK.ts @@ -66,6 +66,7 @@ const skSKPickers: Partial> = { value !== null && utils.isValid(value) ? `Vyberte čas, vybraný čas je ${utils.format(value, 'fullTime')}` : 'Vyberte čas', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'vyberte čas', diff --git a/packages/x-date-pickers/src/locales/svSE.ts b/packages/x-date-pickers/src/locales/svSE.ts index b8296507ce94..498c02df0c2b 100644 --- a/packages/x-date-pickers/src/locales/svSE.ts +++ b/packages/x-date-pickers/src/locales/svSE.ts @@ -65,6 +65,7 @@ const svSEPickers: Partial> = { value !== null && utils.isValid(value) ? `Välj tid, vald tid är ${utils.format(value, 'fullTime')}` : 'Välj tid', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'välj tid', diff --git a/packages/x-date-pickers/src/locales/trTR.ts b/packages/x-date-pickers/src/locales/trTR.ts index a640746cadf6..948c0cc1e2b0 100644 --- a/packages/x-date-pickers/src/locales/trTR.ts +++ b/packages/x-date-pickers/src/locales/trTR.ts @@ -65,6 +65,7 @@ const trTRPickers: Partial> = { value !== null && utils.isValid(value) ? `Saat seçin, seçilen saat: ${utils.format(value, 'fullTime')}` : 'Saat seç', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'saat seç', diff --git a/packages/x-date-pickers/src/locales/ukUA.ts b/packages/x-date-pickers/src/locales/ukUA.ts index 45242cabee79..d9895177ac12 100644 --- a/packages/x-date-pickers/src/locales/ukUA.ts +++ b/packages/x-date-pickers/src/locales/ukUA.ts @@ -65,6 +65,7 @@ const ukUAPickers: Partial> = { value !== null && utils.isValid(value) ? `Оберіть час, обраний час ${utils.format(value, 'fullTime')}` : 'Оберіть час', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'оберіть час', diff --git a/packages/x-date-pickers/src/locales/urPK.ts b/packages/x-date-pickers/src/locales/urPK.ts index 1c73d41e999b..ab0043a0aef9 100644 --- a/packages/x-date-pickers/src/locales/urPK.ts +++ b/packages/x-date-pickers/src/locales/urPK.ts @@ -65,6 +65,7 @@ const urPKPickers: Partial> = { value !== null && utils.isValid(value) ? `وقت منتخب کریں، منتخب شدہ وقت ہے ${utils.format(value, 'fullTime')}` : 'وقت منتخب کریں', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'وقت منتخب کریں', diff --git a/packages/x-date-pickers/src/locales/utils/pickersLocaleTextApi.ts b/packages/x-date-pickers/src/locales/utils/pickersLocaleTextApi.ts index a2acb4fa27bf..e7a6e8e6e0e1 100644 --- a/packages/x-date-pickers/src/locales/utils/pickersLocaleTextApi.ts +++ b/packages/x-date-pickers/src/locales/utils/pickersLocaleTextApi.ts @@ -63,6 +63,9 @@ export interface PickersComponentAgnosticLocaleText { openDatePickerDialogue: (date: TDate | null, utils: MuiPickersAdapter) => string; openTimePickerDialogue: (date: TDate | null, utils: MuiPickersAdapter) => string; + // Clear button label + fieldClearLabel: string; + // Table labels timeTableLabel: string; dateTableLabel: string; diff --git a/packages/x-date-pickers/src/locales/viVN.ts b/packages/x-date-pickers/src/locales/viVN.ts index f238b31ea5f5..638f4c58fdf6 100644 --- a/packages/x-date-pickers/src/locales/viVN.ts +++ b/packages/x-date-pickers/src/locales/viVN.ts @@ -67,6 +67,7 @@ const viVNPickers: Partial> = { value !== null && utils.isValid(value) ? `Chọn giờ, giờ đã chọn là ${utils.format(value, 'fullTime')}` : 'Chọn giờ', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: 'chọn giờ', diff --git a/packages/x-date-pickers/src/locales/zhCN.ts b/packages/x-date-pickers/src/locales/zhCN.ts index 544b6d23c1bd..ec77887c5bed 100644 --- a/packages/x-date-pickers/src/locales/zhCN.ts +++ b/packages/x-date-pickers/src/locales/zhCN.ts @@ -63,6 +63,7 @@ const zhCNPickers: Partial> = { value !== null && utils.isValid(value) ? `选择时间,已选择${utils.format(value, 'fullTime')}` : '选择时间', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: '选择时间', diff --git a/packages/x-date-pickers/src/locales/zhHK.ts b/packages/x-date-pickers/src/locales/zhHK.ts index 8c454b92a8e3..c06008ad2916 100644 --- a/packages/x-date-pickers/src/locales/zhHK.ts +++ b/packages/x-date-pickers/src/locales/zhHK.ts @@ -63,6 +63,7 @@ const zhHKPickers: Partial> = { value !== null && utils.isValid(value) ? `選擇時間,已選擇${utils.format(value, 'fullTime')}` : '選擇時間', + // fieldClearLabel: 'Clear value', // Table labels timeTableLabel: '選擇時間', diff --git a/packages/x-date-pickers/src/models/fields.ts b/packages/x-date-pickers/src/models/fields.ts index 06b589a3a9d3..30e3410328e7 100644 --- a/packages/x-date-pickers/src/models/fields.ts +++ b/packages/x-date-pickers/src/models/fields.ts @@ -150,4 +150,6 @@ export interface BaseSingleInputFieldProps