import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import _extends from "@babel/runtime/helpers/esm/extends"; var _excluded = ["parentProps", "day", "focusableDay", "selectedDays", "isDateDisabled", "currentMonthNumber", "isViewFocused"], _excluded2 = ["ownerState"]; import * as React from 'react'; import useEventCallback from '@mui/utils/useEventCallback'; import Typography from '@mui/material/Typography'; import { useSlotProps } from '@mui/base/utils'; import { styled, useTheme, useThemeProps } from '@mui/material/styles'; import { unstable_composeClasses as composeClasses, unstable_useControlled as useControlled } from '@mui/utils'; import clsx from 'clsx'; import { PickersDay } from '../PickersDay/PickersDay'; import { useUtils, useNow, useLocaleText } from '../internals/hooks/useUtils'; import { DAY_SIZE, DAY_MARGIN } from '../internals/constants/dimensions'; import { PickersSlideTransition } from './PickersSlideTransition'; import { useIsDateDisabled } from './useIsDateDisabled'; import { findClosestEnabledDate, getWeekdays } from '../internals/utils/date-utils'; import { getDayCalendarUtilityClass } from './dayCalendarClasses'; import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; var useUtilityClasses = function useUtilityClasses(ownerState) { var classes = ownerState.classes; var slots = { root: ['root'], header: ['header'], weekDayLabel: ['weekDayLabel'], loadingContainer: ['loadingContainer'], slideTransition: ['slideTransition'], monthContainer: ['monthContainer'], weekContainer: ['weekContainer'], weekNumberLabel: ['weekNumberLabel'], weekNumber: ['weekNumber'] }; return composeClasses(slots, getDayCalendarUtilityClass, classes); }; var weeksContainerHeight = (DAY_SIZE + DAY_MARGIN * 2) * 6; var PickersCalendarDayRoot = styled('div', { name: 'MuiDayCalendar', slot: 'Root', overridesResolver: function overridesResolver(_, styles) { return styles.root; } })({}); var PickersCalendarDayHeader = styled('div', { name: 'MuiDayCalendar', slot: 'Header', overridesResolver: function overridesResolver(_, styles) { return styles.header; } })({ display: 'flex', justifyContent: 'center', alignItems: 'center' }); var PickersCalendarWeekDayLabel = styled(Typography, { name: 'MuiDayCalendar', slot: 'WeekDayLabel', overridesResolver: function overridesResolver(_, styles) { return styles.weekDayLabel; } })(function (_ref) { var theme = _ref.theme; return { width: 36, height: 40, margin: '0 2px', textAlign: 'center', display: 'flex', justifyContent: 'center', alignItems: 'center', color: (theme.vars || theme).palette.text.secondary }; }); var PickersCalendarWeekNumberLabel = styled(Typography, { name: 'MuiDayCalendar', slot: 'WeekNumberLabel', overridesResolver: function overridesResolver(_, styles) { return styles.weekNumberLabel; } })(function (_ref2) { var theme = _ref2.theme; return { width: 36, height: 40, margin: '0 2px', textAlign: 'center', display: 'flex', justifyContent: 'center', alignItems: 'center', color: theme.palette.text.disabled }; }); var PickersCalendarWeekNumber = styled(Typography, { name: 'MuiDayCalendar', slot: 'WeekNumber', overridesResolver: function overridesResolver(_, styles) { return styles.weekNumber; } })(function (_ref3) { var theme = _ref3.theme; return _extends({}, theme.typography.caption, { width: DAY_SIZE, height: DAY_SIZE, padding: 0, margin: "0 ".concat(DAY_MARGIN, "px"), color: theme.palette.text.disabled, fontSize: '0.75rem', alignItems: 'center', justifyContent: 'center', display: 'inline-flex' }); }); var PickersCalendarLoadingContainer = styled('div', { name: 'MuiDayCalendar', slot: 'LoadingContainer', overridesResolver: function overridesResolver(_, styles) { return styles.loadingContainer; } })({ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: weeksContainerHeight }); var PickersCalendarSlideTransition = styled(PickersSlideTransition, { name: 'MuiDayCalendar', slot: 'SlideTransition', overridesResolver: function overridesResolver(_, styles) { return styles.slideTransition; } })({ minHeight: weeksContainerHeight }); var PickersCalendarWeekContainer = styled('div', { name: 'MuiDayCalendar', slot: 'MonthContainer', overridesResolver: function overridesResolver(_, styles) { return styles.monthContainer; } })({ overflow: 'hidden' }); var PickersCalendarWeek = styled('div', { name: 'MuiDayCalendar', slot: 'WeekContainer', overridesResolver: function overridesResolver(_, styles) { return styles.weekContainer; } })({ margin: "".concat(DAY_MARGIN, "px 0"), display: 'flex', justifyContent: 'center' }); function WrappedDay(_ref4) { var _ref5, _slots$day, _slotProps$day; var parentProps = _ref4.parentProps, day = _ref4.day, focusableDay = _ref4.focusableDay, selectedDays = _ref4.selectedDays, isDateDisabled = _ref4.isDateDisabled, currentMonthNumber = _ref4.currentMonthNumber, isViewFocused = _ref4.isViewFocused, other = _objectWithoutProperties(_ref4, _excluded); var disabled = parentProps.disabled, disableHighlightToday = parentProps.disableHighlightToday, isMonthSwitchingAnimating = parentProps.isMonthSwitchingAnimating, showDaysOutsideCurrentMonth = parentProps.showDaysOutsideCurrentMonth, components = parentProps.components, componentsProps = parentProps.componentsProps, slots = parentProps.slots, slotProps = parentProps.slotProps, timezone = parentProps.timezone; var utils = useUtils(); var now = useNow(timezone); var isFocusableDay = focusableDay !== null && utils.isSameDay(day, focusableDay); var isSelected = selectedDays.some(function (selectedDay) { return utils.isSameDay(selectedDay, day); }); var isToday = utils.isSameDay(day, now); var Day = (_ref5 = (_slots$day = slots == null ? void 0 : slots.day) != null ? _slots$day : components == null ? void 0 : components.Day) != null ? _ref5 : PickersDay; // We don't want to pass to ownerState down, to avoid re-rendering all the day whenever a prop changes. var _useSlotProps = useSlotProps({ elementType: Day, externalSlotProps: (_slotProps$day = slotProps == null ? void 0 : slotProps.day) != null ? _slotProps$day : componentsProps == null ? void 0 : componentsProps.day, additionalProps: _extends({ disableHighlightToday: disableHighlightToday, showDaysOutsideCurrentMonth: showDaysOutsideCurrentMonth, role: 'gridcell', isAnimating: isMonthSwitchingAnimating, // it is used in date range dragging logic by accessing `dataset.timestamp` 'data-timestamp': utils.toJsDate(day).valueOf() }, other), ownerState: _extends({}, parentProps, { day: day, selected: isSelected }) }), dayOwnerState = _useSlotProps.ownerState, dayProps = _objectWithoutProperties(_useSlotProps, _excluded2); var isDisabled = React.useMemo(function () { return disabled || isDateDisabled(day); }, [disabled, isDateDisabled, day]); var outsideCurrentMonth = React.useMemo(function () { return utils.getMonth(day) !== currentMonthNumber; }, [utils, day, currentMonthNumber]); var isFirstVisibleCell = React.useMemo(function () { var startOfMonth = utils.startOfMonth(utils.setMonth(day, currentMonthNumber)); if (!showDaysOutsideCurrentMonth) { return utils.isSameDay(day, startOfMonth); } return utils.isSameDay(day, utils.startOfWeek(startOfMonth)); }, [currentMonthNumber, day, showDaysOutsideCurrentMonth, utils]); var isLastVisibleCell = React.useMemo(function () { var endOfMonth = utils.endOfMonth(utils.setMonth(day, currentMonthNumber)); if (!showDaysOutsideCurrentMonth) { return utils.isSameDay(day, endOfMonth); } return utils.isSameDay(day, utils.endOfWeek(endOfMonth)); }, [currentMonthNumber, day, showDaysOutsideCurrentMonth, utils]); return /*#__PURE__*/_jsx(Day, _extends({}, dayProps, { day: day, disabled: isDisabled, autoFocus: isViewFocused && isFocusableDay, today: isToday, outsideCurrentMonth: outsideCurrentMonth, isFirstVisibleCell: isFirstVisibleCell, isLastVisibleCell: isLastVisibleCell, selected: isSelected, tabIndex: isFocusableDay ? 0 : -1, "aria-selected": isSelected, "aria-current": isToday ? 'date' : undefined })); } /** * @ignore - do not document. */ export function DayCalendar(inProps) { var props = useThemeProps({ props: inProps, name: 'MuiDayCalendar' }); var onFocusedDayChange = props.onFocusedDayChange, className = props.className, currentMonth = props.currentMonth, selectedDays = props.selectedDays, focusedDay = props.focusedDay, loading = props.loading, onSelectedDaysChange = props.onSelectedDaysChange, onMonthSwitchingAnimationEnd = props.onMonthSwitchingAnimationEnd, readOnly = props.readOnly, reduceAnimations = props.reduceAnimations, _props$renderLoading = props.renderLoading, renderLoading = _props$renderLoading === void 0 ? function () { return /*#__PURE__*/_jsx("span", { children: "..." }); } : _props$renderLoading, slideDirection = props.slideDirection, TransitionProps = props.TransitionProps, disablePast = props.disablePast, disableFuture = props.disableFuture, minDate = props.minDate, maxDate = props.maxDate, shouldDisableDate = props.shouldDisableDate, shouldDisableMonth = props.shouldDisableMonth, shouldDisableYear = props.shouldDisableYear, dayOfWeekFormatterFromProps = props.dayOfWeekFormatter, hasFocus = props.hasFocus, onFocusedViewChange = props.onFocusedViewChange, gridLabelId = props.gridLabelId, displayWeekNumber = props.displayWeekNumber, fixedWeekNumber = props.fixedWeekNumber, autoFocus = props.autoFocus, timezone = props.timezone; var now = useNow(timezone); var utils = useUtils(); var classes = useUtilityClasses(props); var theme = useTheme(); var isRTL = theme.direction === 'rtl'; // before we could define this outside of the component scope, but now we need utils, which is only defined here var dayOfWeekFormatter = dayOfWeekFormatterFromProps || function (_day, date) { return utils.format(date, 'weekdayShort').charAt(0).toUpperCase(); }; var isDateDisabled = useIsDateDisabled({ shouldDisableDate: shouldDisableDate, shouldDisableMonth: shouldDisableMonth, shouldDisableYear: shouldDisableYear, minDate: minDate, maxDate: maxDate, disablePast: disablePast, disableFuture: disableFuture, timezone: timezone }); var localeText = useLocaleText(); var _useControlled = useControlled({ name: 'DayCalendar', state: 'hasFocus', controlled: hasFocus, default: autoFocus != null ? autoFocus : false }), _useControlled2 = _slicedToArray(_useControlled, 2), internalHasFocus = _useControlled2[0], setInternalHasFocus = _useControlled2[1]; var _React$useState = React.useState(function () { return focusedDay || now; }), _React$useState2 = _slicedToArray(_React$useState, 2), internalFocusedDay = _React$useState2[0], setInternalFocusedDay = _React$useState2[1]; var handleDaySelect = useEventCallback(function (day) { if (readOnly) { return; } onSelectedDaysChange(day); }); var focusDay = function focusDay(day) { if (!isDateDisabled(day)) { onFocusedDayChange(day); setInternalFocusedDay(day); onFocusedViewChange == null || onFocusedViewChange(true); setInternalHasFocus(true); } }; var handleKeyDown = useEventCallback(function (event, day) { switch (event.key) { case 'ArrowUp': focusDay(utils.addDays(day, -7)); event.preventDefault(); break; case 'ArrowDown': focusDay(utils.addDays(day, 7)); event.preventDefault(); break; case 'ArrowLeft': { var newFocusedDayDefault = utils.addDays(day, isRTL ? 1 : -1); var nextAvailableMonth = utils.addMonths(day, isRTL ? 1 : -1); var closestDayToFocus = findClosestEnabledDate({ utils: utils, date: newFocusedDayDefault, minDate: isRTL ? newFocusedDayDefault : utils.startOfMonth(nextAvailableMonth), maxDate: isRTL ? utils.endOfMonth(nextAvailableMonth) : newFocusedDayDefault, isDateDisabled: isDateDisabled, timezone: timezone }); focusDay(closestDayToFocus || newFocusedDayDefault); event.preventDefault(); break; } case 'ArrowRight': { var _newFocusedDayDefault = utils.addDays(day, isRTL ? -1 : 1); var _nextAvailableMonth = utils.addMonths(day, isRTL ? -1 : 1); var _closestDayToFocus = findClosestEnabledDate({ utils: utils, date: _newFocusedDayDefault, minDate: isRTL ? utils.startOfMonth(_nextAvailableMonth) : _newFocusedDayDefault, maxDate: isRTL ? _newFocusedDayDefault : utils.endOfMonth(_nextAvailableMonth), isDateDisabled: isDateDisabled, timezone: timezone }); focusDay(_closestDayToFocus || _newFocusedDayDefault); event.preventDefault(); break; } case 'Home': focusDay(utils.startOfWeek(day)); event.preventDefault(); break; case 'End': focusDay(utils.endOfWeek(day)); event.preventDefault(); break; case 'PageUp': focusDay(utils.addMonths(day, 1)); event.preventDefault(); break; case 'PageDown': focusDay(utils.addMonths(day, -1)); event.preventDefault(); break; default: break; } }); var handleFocus = useEventCallback(function (event, day) { return focusDay(day); }); var handleBlur = useEventCallback(function (event, day) { if (internalHasFocus && utils.isSameDay(internalFocusedDay, day)) { onFocusedViewChange == null || onFocusedViewChange(false); } }); var currentMonthNumber = utils.getMonth(currentMonth); var validSelectedDays = React.useMemo(function () { return selectedDays.filter(function (day) { return !!day; }).map(function (day) { return utils.startOfDay(day); }); }, [utils, selectedDays]); // need a new ref whenever the `key` of the transition changes: http://reactcommunity.org/react-transition-group/transition/#Transition-prop-nodeRef. var transitionKey = currentMonthNumber; // eslint-disable-next-line react-hooks/exhaustive-deps var slideNodeRef = React.useMemo(function () { return /*#__PURE__*/React.createRef(); }, [transitionKey]); var startOfCurrentWeek = utils.startOfWeek(now); var focusableDay = React.useMemo(function () { var startOfMonth = utils.startOfMonth(currentMonth); var endOfMonth = utils.endOfMonth(currentMonth); if (isDateDisabled(internalFocusedDay) || utils.isAfterDay(internalFocusedDay, endOfMonth) || utils.isBeforeDay(internalFocusedDay, startOfMonth)) { return findClosestEnabledDate({ utils: utils, date: internalFocusedDay, minDate: startOfMonth, maxDate: endOfMonth, disablePast: disablePast, disableFuture: disableFuture, isDateDisabled: isDateDisabled, timezone: timezone }); } return internalFocusedDay; }, [currentMonth, disableFuture, disablePast, internalFocusedDay, isDateDisabled, utils, timezone]); var weeksToDisplay = React.useMemo(function () { var currentMonthWithTimezone = utils.setTimezone(currentMonth, timezone); var toDisplay = utils.getWeekArray(currentMonthWithTimezone); var nextMonth = utils.addMonths(currentMonthWithTimezone, 1); while (fixedWeekNumber && toDisplay.length < fixedWeekNumber) { var additionalWeeks = utils.getWeekArray(nextMonth); var hasCommonWeek = utils.isSameDay(toDisplay[toDisplay.length - 1][0], additionalWeeks[0][0]); additionalWeeks.slice(hasCommonWeek ? 1 : 0).forEach(function (week) { if (toDisplay.length < fixedWeekNumber) { toDisplay.push(week); } }); nextMonth = utils.addMonths(nextMonth, 1); } return toDisplay; }, [currentMonth, fixedWeekNumber, utils, timezone]); return /*#__PURE__*/_jsxs(PickersCalendarDayRoot, { role: "grid", "aria-labelledby": gridLabelId, className: classes.root, children: [/*#__PURE__*/_jsxs(PickersCalendarDayHeader, { role: "row", className: classes.header, children: [displayWeekNumber && /*#__PURE__*/_jsx(PickersCalendarWeekNumberLabel, { variant: "caption", role: "columnheader", "aria-label": localeText.calendarWeekNumberHeaderLabel, className: classes.weekNumberLabel, children: localeText.calendarWeekNumberHeaderText }), getWeekdays(utils, now).map(function (weekday, i) { var _dayOfWeekFormatter; var day = utils.format(weekday, 'weekdayShort'); return /*#__PURE__*/_jsx(PickersCalendarWeekDayLabel, { variant: "caption", role: "columnheader", "aria-label": utils.format(utils.addDays(startOfCurrentWeek, i), 'weekday'), className: classes.weekDayLabel, children: (_dayOfWeekFormatter = dayOfWeekFormatter == null ? void 0 : dayOfWeekFormatter(day, weekday)) != null ? _dayOfWeekFormatter : day }, day + i.toString()); })] }), loading ? /*#__PURE__*/_jsx(PickersCalendarLoadingContainer, { className: classes.loadingContainer, children: renderLoading() }) : /*#__PURE__*/_jsx(PickersCalendarSlideTransition, _extends({ transKey: transitionKey, onExited: onMonthSwitchingAnimationEnd, reduceAnimations: reduceAnimations, slideDirection: slideDirection, className: clsx(className, classes.slideTransition) }, TransitionProps, { nodeRef: slideNodeRef, children: /*#__PURE__*/_jsx(PickersCalendarWeekContainer, { ref: slideNodeRef, role: "rowgroup", className: classes.monthContainer, children: weeksToDisplay.map(function (week, index) { return /*#__PURE__*/_jsxs(PickersCalendarWeek, { role: "row", className: classes.weekContainer // fix issue of announcing row 1 as row 2 // caused by week day labels row , "aria-rowindex": index + 1, children: [displayWeekNumber && /*#__PURE__*/_jsx(PickersCalendarWeekNumber, { className: classes.weekNumber, role: "rowheader", "aria-label": localeText.calendarWeekNumberAriaLabelText(utils.getWeekNumber(week[0])), children: localeText.calendarWeekNumberText(utils.getWeekNumber(week[0])) }), week.map(function (day, dayIndex) { return /*#__PURE__*/_jsx(WrappedDay, { parentProps: props, day: day, selectedDays: validSelectedDays, focusableDay: focusableDay, onKeyDown: handleKeyDown, onFocus: handleFocus, onBlur: handleBlur, onDaySelect: handleDaySelect, isDateDisabled: isDateDisabled, currentMonthNumber: currentMonthNumber, isViewFocused: internalHasFocus // fix issue of announcing column 1 as column 2 when `displayWeekNumber` is enabled , "aria-colindex": dayIndex + 1 }, day.toString()); })] }, "week-".concat(week[0])); }) }) }))] }); }