UNPKG

@mui/x-date-pickers

Version:

The community edition of the Date and Time Picker components (MUI X).

321 lines (318 loc) 12.8 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; const _excluded = ["enableAccessibleFieldDOMStructure"], _excluded2 = ["InputProps", "readOnly", "onClear", "clearable", "clearButtonPosition", "openPickerButtonPosition", "openPickerAriaLabel"], _excluded3 = ["onPaste", "onKeyDown", "inputMode", "readOnly", "InputProps", "inputProps", "inputRef", "onClear", "clearable", "clearButtonPosition", "openPickerButtonPosition", "openPickerAriaLabel"], _excluded4 = ["ownerState"], _excluded5 = ["ownerState"], _excluded6 = ["ownerState"], _excluded7 = ["ownerState"], _excluded8 = ["InputProps", "inputProps"]; import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; import useForkRef from '@mui/utils/useForkRef'; import resolveComponentProps from '@mui/utils/resolveComponentProps'; import MuiTextField from '@mui/material/TextField'; import MuiIconButton from '@mui/material/IconButton'; import MuiInputAdornment from '@mui/material/InputAdornment'; import useSlotProps from '@mui/utils/useSlotProps'; import { useFieldOwnerState } from "../hooks/useFieldOwnerState.js"; import { usePickerTranslations } from "../../hooks/index.js"; import { ClearIcon as MuiClearIcon } from "../../icons/index.js"; import { useNullablePickerContext } from "../hooks/useNullablePickerContext.js"; import { PickersTextField } from "../../PickersTextField/index.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export const cleanFieldResponse = _ref => { let { enableAccessibleFieldDOMStructure } = _ref, fieldResponse = _objectWithoutPropertiesLoose(_ref, _excluded); if (enableAccessibleFieldDOMStructure) { const { InputProps, readOnly, onClear, clearable, clearButtonPosition, openPickerButtonPosition, openPickerAriaLabel } = fieldResponse, other = _objectWithoutPropertiesLoose(fieldResponse, _excluded2); return { clearable, onClear, clearButtonPosition, openPickerButtonPosition, openPickerAriaLabel, textFieldProps: _extends({}, other, { InputProps: _extends({}, InputProps ?? {}, { readOnly }) }) }; } const { onPaste, onKeyDown, inputMode, readOnly, InputProps, inputProps, inputRef, onClear, clearable, clearButtonPosition, openPickerButtonPosition, openPickerAriaLabel } = fieldResponse, other = _objectWithoutPropertiesLoose(fieldResponse, _excluded3); return { clearable, onClear, clearButtonPosition, openPickerButtonPosition, openPickerAriaLabel, textFieldProps: _extends({}, other, { InputProps: _extends({}, InputProps ?? {}, { readOnly }), inputProps: _extends({}, inputProps ?? {}, { inputMode, onPaste, onKeyDown, ref: inputRef }) }) }; }; export const PickerFieldUIContext = /*#__PURE__*/React.createContext({ slots: {}, slotProps: {}, inputRef: undefined }); /** * Adds the button to open the Picker and the button to clear the value of the field. * @ignore - internal component. */ export function PickerFieldUI(props) { const { slots, slotProps, fieldResponse, defaultOpenPickerIcon } = props; const translations = usePickerTranslations(); const pickerContext = useNullablePickerContext(); const pickerFieldUIContext = React.useContext(PickerFieldUIContext); const { textFieldProps, onClear, clearable, openPickerAriaLabel, clearButtonPosition: clearButtonPositionProp = 'end', openPickerButtonPosition: openPickerButtonPositionProp = 'end' } = cleanFieldResponse(fieldResponse); const ownerState = useFieldOwnerState(textFieldProps); const handleClickOpeningButton = useEventCallback(event => { event.preventDefault(); pickerContext?.setOpen(prev => !prev); }); const triggerStatus = pickerContext ? pickerContext.triggerStatus : 'hidden'; const clearButtonPosition = clearable ? clearButtonPositionProp : null; const openPickerButtonPosition = triggerStatus !== 'hidden' ? openPickerButtonPositionProp : null; const TextField = slots?.textField ?? pickerFieldUIContext.slots.textField ?? (fieldResponse.enableAccessibleFieldDOMStructure === false ? MuiTextField : PickersTextField); const InputAdornment = slots?.inputAdornment ?? pickerFieldUIContext.slots.inputAdornment ?? MuiInputAdornment; const _useSlotProps = useSlotProps({ elementType: InputAdornment, externalSlotProps: mergeSlotProps(pickerFieldUIContext.slotProps.inputAdornment, slotProps?.inputAdornment), additionalProps: { position: 'start' }, ownerState: _extends({}, ownerState, { position: 'start' }) }), startInputAdornmentProps = _objectWithoutPropertiesLoose(_useSlotProps, _excluded4); const _useSlotProps2 = useSlotProps({ elementType: InputAdornment, externalSlotProps: slotProps?.inputAdornment, additionalProps: { position: 'end' }, ownerState: _extends({}, ownerState, { position: 'end' }) }), endInputAdornmentProps = _objectWithoutPropertiesLoose(_useSlotProps2, _excluded5); const OpenPickerButton = pickerFieldUIContext.slots.openPickerButton ?? MuiIconButton; // We don't want to forward the `ownerState` to the `<IconButton />` component, see mui/material-ui#34056 const _useSlotProps3 = useSlotProps({ elementType: OpenPickerButton, externalSlotProps: pickerFieldUIContext.slotProps.openPickerButton, additionalProps: { disabled: triggerStatus === 'disabled', onClick: handleClickOpeningButton, 'aria-label': openPickerAriaLabel, edge: // open button is always rendered at the edge textFieldProps.variant !== 'standard' ? openPickerButtonPosition : false }, ownerState }), openPickerButtonProps = _objectWithoutPropertiesLoose(_useSlotProps3, _excluded6); const OpenPickerIcon = pickerFieldUIContext.slots.openPickerIcon ?? defaultOpenPickerIcon; const openPickerIconProps = useSlotProps({ elementType: OpenPickerIcon, externalSlotProps: pickerFieldUIContext.slotProps.openPickerIcon, ownerState }); const ClearButton = slots?.clearButton ?? pickerFieldUIContext.slots.clearButton ?? MuiIconButton; // We don't want to forward the `ownerState` to the `<IconButton />` component, see mui/material-ui#34056 const _useSlotProps4 = useSlotProps({ elementType: ClearButton, externalSlotProps: mergeSlotProps(pickerFieldUIContext.slotProps.clearButton, slotProps?.clearButton), className: 'clearButton', additionalProps: { title: translations.fieldClearLabel, tabIndex: -1, onClick: onClear, disabled: fieldResponse.disabled || fieldResponse.readOnly, edge: // clear button can only be at the edge if it's position differs from the open button textFieldProps.variant !== 'standard' && clearButtonPosition !== openPickerButtonPosition ? clearButtonPosition : false }, ownerState }), clearButtonProps = _objectWithoutPropertiesLoose(_useSlotProps4, _excluded7); const ClearIcon = slots?.clearIcon ?? pickerFieldUIContext.slots.clearIcon ?? MuiClearIcon; const clearIconProps = useSlotProps({ elementType: ClearIcon, externalSlotProps: mergeSlotProps(pickerFieldUIContext.slotProps.clearIcon, slotProps?.clearIcon), additionalProps: { fontSize: 'small' }, ownerState }); textFieldProps.ref = useForkRef(textFieldProps.ref, pickerContext?.rootRef); if (!textFieldProps.InputProps) { textFieldProps.InputProps = {}; } if (pickerContext) { textFieldProps.InputProps.ref = pickerContext.triggerRef; } if (!textFieldProps.InputProps?.startAdornment && (clearButtonPosition === 'start' || openPickerButtonPosition === 'start')) { textFieldProps.InputProps.startAdornment = /*#__PURE__*/_jsxs(InputAdornment, _extends({}, startInputAdornmentProps, { children: [openPickerButtonPosition === 'start' && /*#__PURE__*/_jsx(OpenPickerButton, _extends({}, openPickerButtonProps, { children: /*#__PURE__*/_jsx(OpenPickerIcon, _extends({}, openPickerIconProps)) })), clearButtonPosition === 'start' && /*#__PURE__*/_jsx(ClearButton, _extends({}, clearButtonProps, { children: /*#__PURE__*/_jsx(ClearIcon, _extends({}, clearIconProps)) }))] })); } if (!textFieldProps.InputProps?.endAdornment && (clearButtonPosition === 'end' || openPickerButtonPosition === 'end')) { textFieldProps.InputProps.endAdornment = /*#__PURE__*/_jsxs(InputAdornment, _extends({}, endInputAdornmentProps, { children: [clearButtonPosition === 'end' && /*#__PURE__*/_jsx(ClearButton, _extends({}, clearButtonProps, { children: /*#__PURE__*/_jsx(ClearIcon, _extends({}, clearIconProps)) })), openPickerButtonPosition === 'end' && /*#__PURE__*/_jsx(OpenPickerButton, _extends({}, openPickerButtonProps, { children: /*#__PURE__*/_jsx(OpenPickerIcon, _extends({}, openPickerIconProps)) }))] })); } if (clearButtonPosition != null) { textFieldProps.sx = [{ '& .clearButton': { opacity: 1 }, '@media (pointer: fine)': { '& .clearButton': { opacity: 0 }, '&:hover, &:focus-within': { '.clearButton': { opacity: 1 } } } }, ...(Array.isArray(textFieldProps.sx) ? textFieldProps.sx : [textFieldProps.sx])]; } return /*#__PURE__*/_jsx(TextField, _extends({}, textFieldProps)); } export function mergeSlotProps(slotPropsA, slotPropsB) { if (!slotPropsA) { return slotPropsB; } if (!slotPropsB) { return slotPropsA; } return ownerState => { return _extends({}, resolveComponentProps(slotPropsB, ownerState), resolveComponentProps(slotPropsA, ownerState)); }; } /** * The `textField` slot props cannot be handled inside `PickerFieldUI` because it would be a breaking change to not pass the enriched props to `useField`. * Once the non-accessible DOM structure will be removed, we will be able to remove the `textField` slot and clean this logic. */ export function useFieldTextFieldProps(parameters) { const { ref, externalForwardedProps, slotProps } = parameters; const pickerFieldUIContext = React.useContext(PickerFieldUIContext); const pickerContext = useNullablePickerContext(); const ownerState = useFieldOwnerState(externalForwardedProps); const { InputProps, inputProps } = externalForwardedProps, otherExternalForwardedProps = _objectWithoutPropertiesLoose(externalForwardedProps, _excluded8); const textFieldProps = useSlotProps({ elementType: PickersTextField, externalSlotProps: mergeSlotProps(pickerFieldUIContext.slotProps.textField, slotProps?.textField), externalForwardedProps: otherExternalForwardedProps, additionalProps: { ref, sx: pickerContext?.rootSx, label: pickerContext?.label, name: pickerContext?.name, className: pickerContext?.rootClassName, inputRef: pickerFieldUIContext.inputRef }, ownerState }); // TODO: Remove when mui/material-ui#35088 will be merged textFieldProps.inputProps = _extends({}, inputProps, textFieldProps.inputProps); textFieldProps.InputProps = _extends({}, InputProps, textFieldProps.InputProps); return textFieldProps; } export function PickerFieldUIContextProvider(props) { const { slots = {}, slotProps = {}, inputRef, children } = props; const contextValue = React.useMemo(() => ({ inputRef, slots: { openPickerButton: slots.openPickerButton, openPickerIcon: slots.openPickerIcon, textField: slots.textField, inputAdornment: slots.inputAdornment, clearIcon: slots.clearIcon, clearButton: slots.clearButton }, slotProps: { openPickerButton: slotProps.openPickerButton, openPickerIcon: slotProps.openPickerIcon, textField: slotProps.textField, inputAdornment: slotProps.inputAdornment, clearIcon: slotProps.clearIcon, clearButton: slotProps.clearButton } }), [inputRef, slots.openPickerButton, slots.openPickerIcon, slots.textField, slots.inputAdornment, slots.clearIcon, slots.clearButton, slotProps.openPickerButton, slotProps.openPickerIcon, slotProps.textField, slotProps.inputAdornment, slotProps.clearIcon, slotProps.clearButton]); return /*#__PURE__*/_jsx(PickerFieldUIContext.Provider, { value: contextValue, children: children }); }