UNPKG

@mui/x-date-pickers

Version:

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

387 lines (385 loc) 14.1 kB
"use strict"; 'use client'; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.YearCalendar = void 0; var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _clsx = _interopRequireDefault(require("clsx")); var _RtlProvider = require("@mui/system/RtlProvider"); var _styles = require("@mui/material/styles"); var _utils = require("@mui/utils"); var _PickersYear = require("./PickersYear"); var _useUtils = require("../internals/hooks/useUtils"); var _yearCalendarClasses = require("./yearCalendarClasses"); var _dateUtils = require("../internals/utils/date-utils"); var _valueManagers = require("../internals/utils/valueManagers"); var _getDefaultReferenceDate = require("../internals/utils/getDefaultReferenceDate"); var _useValueWithTimezone = require("../internals/hooks/useValueWithTimezone"); var _dimensions = require("../internals/constants/dimensions"); var _jsxRuntime = require("react/jsx-runtime"); const _excluded = ["autoFocus", "className", "value", "defaultValue", "referenceDate", "disabled", "disableFuture", "disablePast", "maxDate", "minDate", "onChange", "readOnly", "shouldDisableYear", "disableHighlightToday", "onYearFocus", "hasFocus", "onFocusedViewChange", "yearsOrder", "yearsPerRow", "timezone", "gridLabelId", "slots", "slotProps"]; const useUtilityClasses = ownerState => { const { classes } = ownerState; const slots = { root: ['root'] }; return (0, _utils.unstable_composeClasses)(slots, _yearCalendarClasses.getYearCalendarUtilityClass, classes); }; function useYearCalendarDefaultizedProps(props, name) { const utils = (0, _useUtils.useUtils)(); const defaultDates = (0, _useUtils.useDefaultDates)(); const themeProps = (0, _styles.useThemeProps)({ props, name }); return (0, _extends2.default)({ disablePast: false, disableFuture: false }, themeProps, { yearsPerRow: themeProps.yearsPerRow ?? 3, minDate: (0, _dateUtils.applyDefaultDate)(utils, themeProps.minDate, defaultDates.minDate), maxDate: (0, _dateUtils.applyDefaultDate)(utils, themeProps.maxDate, defaultDates.maxDate) }); } const YearCalendarRoot = (0, _styles.styled)('div', { name: 'MuiYearCalendar', slot: 'Root', overridesResolver: (props, styles) => styles.root })({ display: 'flex', flexDirection: 'row', flexWrap: 'wrap', overflowY: 'auto', height: '100%', padding: '0 4px', width: _dimensions.DIALOG_WIDTH, maxHeight: _dimensions.MAX_CALENDAR_HEIGHT, // avoid padding increasing width over defined boxSizing: 'border-box', position: 'relative' }); /** * Demos: * * - [DateCalendar](https://mui.com/x/react-date-pickers/date-calendar/) * * API: * * - [YearCalendar API](https://mui.com/x/api/date-pickers/year-calendar/) */ const YearCalendar = exports.YearCalendar = /*#__PURE__*/React.forwardRef(function YearCalendar(inProps, ref) { const props = useYearCalendarDefaultizedProps(inProps, 'MuiYearCalendar'); const { autoFocus, className, value: valueProp, defaultValue, referenceDate: referenceDateProp, disabled, disableFuture, disablePast, maxDate, minDate, onChange, readOnly, shouldDisableYear, onYearFocus, hasFocus, onFocusedViewChange, yearsOrder = 'asc', yearsPerRow, timezone: timezoneProp, gridLabelId, slots, slotProps } = props, other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded); const { value, handleValueChange, timezone } = (0, _useValueWithTimezone.useControlledValueWithTimezone)({ name: 'YearCalendar', timezone: timezoneProp, value: valueProp, defaultValue, referenceDate: referenceDateProp, onChange, valueManager: _valueManagers.singleItemValueManager }); const now = (0, _useUtils.useNow)(timezone); const isRtl = (0, _RtlProvider.useRtl)(); const utils = (0, _useUtils.useUtils)(); const referenceDate = React.useMemo(() => _valueManagers.singleItemValueManager.getInitialReferenceValue({ value, utils, props, timezone, referenceDate: referenceDateProp, granularity: _getDefaultReferenceDate.SECTION_TYPE_GRANULARITY.year }), [] // eslint-disable-line react-hooks/exhaustive-deps ); const ownerState = props; const classes = useUtilityClasses(ownerState); const todayYear = React.useMemo(() => utils.getYear(now), [utils, now]); const selectedYear = React.useMemo(() => { if (value != null) { return utils.getYear(value); } return null; }, [value, utils]); const [focusedYear, setFocusedYear] = React.useState(() => selectedYear || utils.getYear(referenceDate)); const [internalHasFocus, setInternalHasFocus] = (0, _utils.unstable_useControlled)({ name: 'YearCalendar', state: 'hasFocus', controlled: hasFocus, default: autoFocus ?? false }); const changeHasFocus = (0, _utils.unstable_useEventCallback)(newHasFocus => { setInternalHasFocus(newHasFocus); if (onFocusedViewChange) { onFocusedViewChange(newHasFocus); } }); const isYearDisabled = React.useCallback(dateToValidate => { if (disablePast && utils.isBeforeYear(dateToValidate, now)) { return true; } if (disableFuture && utils.isAfterYear(dateToValidate, now)) { return true; } if (minDate && utils.isBeforeYear(dateToValidate, minDate)) { return true; } if (maxDate && utils.isAfterYear(dateToValidate, maxDate)) { return true; } if (!shouldDisableYear) { return false; } const yearToValidate = utils.startOfYear(dateToValidate); return shouldDisableYear(yearToValidate); }, [disableFuture, disablePast, maxDate, minDate, now, shouldDisableYear, utils]); const handleYearSelection = (0, _utils.unstable_useEventCallback)((event, year) => { if (readOnly) { return; } const newDate = utils.setYear(value ?? referenceDate, year); handleValueChange(newDate); }); const focusYear = (0, _utils.unstable_useEventCallback)(year => { if (!isYearDisabled(utils.setYear(value ?? referenceDate, year))) { setFocusedYear(year); changeHasFocus(true); onYearFocus?.(year); } }); React.useEffect(() => { setFocusedYear(prevFocusedYear => selectedYear !== null && prevFocusedYear !== selectedYear ? selectedYear : prevFocusedYear); }, [selectedYear]); const verticalDirection = yearsOrder !== 'desc' ? yearsPerRow * 1 : yearsPerRow * -1; const horizontalDirection = isRtl && yearsOrder === 'asc' || !isRtl && yearsOrder === 'desc' ? -1 : 1; const handleKeyDown = (0, _utils.unstable_useEventCallback)((event, year) => { switch (event.key) { case 'ArrowUp': focusYear(year - verticalDirection); event.preventDefault(); break; case 'ArrowDown': focusYear(year + verticalDirection); event.preventDefault(); break; case 'ArrowLeft': focusYear(year - horizontalDirection); event.preventDefault(); break; case 'ArrowRight': focusYear(year + horizontalDirection); event.preventDefault(); break; default: break; } }); const handleYearFocus = (0, _utils.unstable_useEventCallback)((event, year) => { focusYear(year); }); const handleYearBlur = (0, _utils.unstable_useEventCallback)((event, year) => { if (focusedYear === year) { changeHasFocus(false); } }); const scrollerRef = React.useRef(null); const handleRef = (0, _utils.unstable_useForkRef)(ref, scrollerRef); React.useEffect(() => { if (autoFocus || scrollerRef.current === null) { return; } const tabbableButton = scrollerRef.current.querySelector('[tabindex="0"]'); if (!tabbableButton) { return; } // Taken from useScroll in x-data-grid, but vertically centered const offsetHeight = tabbableButton.offsetHeight; const offsetTop = tabbableButton.offsetTop; const clientHeight = scrollerRef.current.clientHeight; const scrollTop = scrollerRef.current.scrollTop; const elementBottom = offsetTop + offsetHeight; if (offsetHeight > clientHeight || offsetTop < scrollTop) { // Button already visible return; } scrollerRef.current.scrollTop = elementBottom - clientHeight / 2 - offsetHeight / 2; }, [autoFocus]); const yearRange = utils.getYearRange([minDate, maxDate]); if (yearsOrder === 'desc') { yearRange.reverse(); } return /*#__PURE__*/(0, _jsxRuntime.jsx)(YearCalendarRoot, (0, _extends2.default)({ ref: handleRef, className: (0, _clsx.default)(classes.root, className), ownerState: ownerState, role: "radiogroup", "aria-labelledby": gridLabelId }, other, { children: yearRange.map(year => { const yearNumber = utils.getYear(year); const isSelected = yearNumber === selectedYear; const isDisabled = disabled || isYearDisabled(year); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_PickersYear.PickersYear, { selected: isSelected, value: yearNumber, onClick: handleYearSelection, onKeyDown: handleKeyDown, autoFocus: internalHasFocus && yearNumber === focusedYear, disabled: isDisabled, tabIndex: yearNumber === focusedYear && !isDisabled ? 0 : -1, onFocus: handleYearFocus, onBlur: handleYearBlur, "aria-current": todayYear === yearNumber ? 'date' : undefined, yearsPerRow: yearsPerRow, slots: slots, slotProps: slotProps, children: utils.format(year, 'year') }, utils.format(year, 'year')); }) })); }); process.env.NODE_ENV !== "production" ? YearCalendar.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- autoFocus: _propTypes.default.bool, /** * Override or extend the styles applied to the component. */ classes: _propTypes.default.object, className: _propTypes.default.string, /** * The default selected value. * Used when the component is not controlled. */ defaultValue: _propTypes.default.object, /** * If `true` picker is disabled */ disabled: _propTypes.default.bool, /** * If `true`, disable values after the current date for date components, time for time components and both for date time components. * @default false */ disableFuture: _propTypes.default.bool, /** * If `true`, today's date is rendering without highlighting with circle. * @default false */ disableHighlightToday: _propTypes.default.bool, /** * If `true`, disable values before the current date for date components, time for time components and both for date time components. * @default false */ disablePast: _propTypes.default.bool, gridLabelId: _propTypes.default.string, hasFocus: _propTypes.default.bool, /** * Maximal selectable date. * @default 2099-12-31 */ maxDate: _propTypes.default.object, /** * Minimal selectable date. * @default 1900-01-01 */ minDate: _propTypes.default.object, /** * Callback fired when the value changes. * @template TDate * @param {TDate} value The new value. */ onChange: _propTypes.default.func, onFocusedViewChange: _propTypes.default.func, onYearFocus: _propTypes.default.func, /** * If `true` picker is readonly */ readOnly: _propTypes.default.bool, /** * The date used to generate the new value when both `value` and `defaultValue` are empty. * @default The closest valid year using the validation props, except callbacks such as `shouldDisableYear`. */ referenceDate: _propTypes.default.object, /** * Disable specific year. * @template TDate * @param {TDate} year The year to test. * @returns {boolean} If `true`, the year will be disabled. */ shouldDisableYear: _propTypes.default.func, /** * The props used for each component slot. * @default {} */ slotProps: _propTypes.default.object, /** * Overridable component slots. * @default {} */ slots: _propTypes.default.object, /** * The system prop that allows defining system overrides as well as additional CSS styles. */ sx: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object, _propTypes.default.bool])), _propTypes.default.func, _propTypes.default.object]), /** * Choose which timezone to use for the value. * Example: "default", "system", "UTC", "America/New_York". * If you pass values from other timezones to some props, they will be converted to this timezone before being used. * @see See the {@link https://mui.com/x/react-date-pickers/timezone/ timezones documentation} for more details. * @default The timezone of the `value` or `defaultValue` prop is defined, 'default' otherwise. */ timezone: _propTypes.default.string, /** * The selected value. * Used when the component is controlled. */ value: _propTypes.default.object, /** * Years are displayed in ascending (chronological) order by default. * If `desc`, years are displayed in descending order. * @default 'asc' */ yearsOrder: _propTypes.default.oneOf(['asc', 'desc']), /** * Years rendered per row. * @default 3 */ yearsPerRow: _propTypes.default.oneOf([3, 4]) } : void 0;