UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

416 lines (415 loc) 14.9 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _push = _interopRequireDefault(require("core-js-pure/stable/instance/push.js")); var _react = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _dateFns = require("date-fns"); var _DatePickerCalc = require("./DatePickerCalc.js"); var _Button = _interopRequireDefault(require("../button/Button.js")); var _DatePickerContext = _interopRequireDefault(require("./DatePickerContext.js")); var _DatePickerCalendarNavigator = require("./DatePickerCalendarNavigator.js"); var _DateFormatUtils = require("../date-format/DateFormatUtils.js"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } const defaultProps = { hideNavigation: false, hideDays: false, onlyMonth: false, hideNextMonthWeek: false, rtl: false, resetDate: true }; const arrowKeys = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; const keysToHandle = ['Enter', 'Space', ...arrowKeys]; function DatePickerCalendar(restOfProps) { const props = { ...defaultProps, ...restOfProps }; const { updateDates, setHasClickedCalendarDay, startDate, endDate, maxDate, minDate, startMonth, endMonth, hoverDate, setHoverDate, setSubmittedDates, props: { onDaysRender, yearNavigation }, translation: { DatePicker: { firstDay: defaultFirstDayOfWeek, selectedMonth } } } = (0, _react.useContext)(_DatePickerContext.default); const { id, nr, rtl, month, isRange, firstDayOfWeek = defaultFirstDayOfWeek, hideNavigation, locale, hideDays, onSelect, onKeyDown, resetDate, hideNextMonthWeek, onlyMonth } = props; const tableRef = (0, _react.useRef)(); const days = (0, _react.useRef)({}); const cache = (0, _react.useRef)({}); (0, _react.useEffect)(() => { setSubmittedDates({ startDate, endDate }); }, []); const onMouseLeaveHandler = (0, _react.useCallback)(() => { setHoverDate(undefined); }, [setHoverDate]); const callOnSelect = (0, _react.useCallback)(event => { onSelect === null || onSelect === void 0 || onSelect(event); }, [onSelect]); const getDays = (0, _react.useCallback)(month => { let daysFromCalendar = (0, _DatePickerCalc.getCalendar)(month || new Date(), (0, _DatePickerCalc.dayOffset)(firstDayOfWeek), { onlyMonth, hideNextMonthWeek }).map(date => (0, _DatePickerCalc.makeDayObject)(date, { startDate, endDate, hoverDate, minDate, maxDate, month })); if (onDaysRender) { const changedDays = onDaysRender(daysFromCalendar, nr); if (Array.isArray(changedDays)) { daysFromCalendar = changedDays; } } days.current[(0, _dateFns.format)(month, 'yyyy-MM')] = daysFromCalendar; return daysFromCalendar; }, [endDate, firstDayOfWeek, hideNextMonthWeek, hoverDate, maxDate, minDate, nr, onDaysRender, onlyMonth, startDate]); const keyNavCalc = (0, _react.useCallback)((date, keyCode) => { if (!arrowKeys.includes(keyCode)) { return date; } const dateHandler = /(ArrowLeft|ArrowRight)/g.test(keyCode) ? _dateFns.addDays : _dateFns.addWeeks; const shiftAmount = /(ArrowLeft|ArrowUp)/g.test(keyCode) ? -1 : 1; return dateHandler(date, shiftAmount); }, []); const findValid = (0, _react.useCallback)((date, keyCode) => { if (!onDaysRender || !days.current) { return date; } const month = (0, _dateFns.format)(date, 'yyyy-MM'); if (!days.current[month]) { getDays(date); } if (Array.isArray(days.current[month])) { const foundDate = days.current[month].find(cur => (0, _dateFns.isSameDay)(cur.date, date)); if (foundDate !== null && foundDate !== void 0 && foundDate.date && (foundDate.isDisabled || foundDate.isSelectable === false || foundDate.isInactive)) { const nextDate = keyNavCalc(foundDate.date, keyCode); return findValid(nextDate, keyCode); } if (foundDate !== null && foundDate !== void 0 && foundDate.date) { return foundDate.date; } } return date; }, [onDaysRender, getDays, keyNavCalc]); const hasReachedEnd = (0, _react.useCallback)(date => (0, _DatePickerCalc.isDisabled)(date, minDate, maxDate), [minDate, maxDate]); const onKeyDownHandler = (0, _react.useCallback)(event => { const pressedKey = event.code; if (typeof onKeyDown === 'function') { return onKeyDown(event, tableRef, nr); } if (!keysToHandle.includes(pressedKey)) { return; } event.preventDefault(); event.persist(); const currentDates = { startDate, endDate, startMonth, endMonth }; const dateType = !isRange || nr === 0 ? 'start' : 'end'; const currentDate = currentDates[`${dateType}Date`]; let newDate = currentDate ? keyNavCalc(currentDate, pressedKey) : currentDates[`${dateType}Month`] || (isRange && nr === 1 ? (0, _dateFns.addMonths)(new Date(), 1) : new Date()); if (newDate === currentDate && (pressedKey === 'Enter' || pressedKey === 'Space')) { return callOnSelect({ event, nr, hidePicker: true }); } const dates = {}; const currentMonth = currentDates[`${dateType}Month`]; if (currentMonth && !currentDate || currentMonth && Math.abs((0, _dateFns.differenceInMonths)(newDate, currentMonth)) > 1) { newDate = !isRange ? currentMonth : nr === 0 ? (0, _dateFns.setDate)(currentMonth, 1) : (0, _dateFns.lastDayOfMonth)(currentMonth); } else if (currentMonth && !(0, _dateFns.isSameMonth)(currentDate, currentMonth)) { dates[`${dateType}Month`] = newDate; } newDate = findValid(newDate, pressedKey); if (hasReachedEnd(newDate)) { return; } dates[`${dateType}Date`] = newDate; if (!isRange) { dates.endDate = newDate; } else { if (!startDate) { dates.startDate = newDate; } if (!endDate) { dates.endDate = newDate; } } if (onlyMonth || hideNavigation) { if (!(0, _dateFns.isSameMonth)(dates.startDate, startDate) || !(0, _dateFns.isSameMonth)(dates.endDate, startDate)) { return; } } updateDates(dates, () => { callOnSelect({ event, nr, hidePicker: false, ...dates }); }); if (tableRef && tableRef.current) { tableRef.current.focus({ preventScroll: true }); } }, [callOnSelect, findValid, hasReachedEnd, onKeyDown, startDate, endDate, updateDates, hideNavigation, isRange, keyNavCalc, nr, onlyMonth, endMonth, startMonth]); const cacheKey = (0, _react.useMemo)(() => { return [nr, month, firstDayOfWeek, onlyMonth, hideNextMonthWeek, startDate, endDate, hoverDate, maxDate, minDate].join('|'); }, [nr, month, firstDayOfWeek, onlyMonth, hideNextMonthWeek, startDate, endDate, hoverDate, maxDate, minDate]); const weekDays = (0, _react.useMemo)(() => { if (cache.current[cacheKey]) { return cache.current[cacheKey]; } let count = 0; const days = getDays(month).reduce((acc, cur, i) => { var _context; acc[count] = acc[count] || []; (0, _push.default)(_context = acc[count]).call(_context, cur); if (i % 7 === 6) { count++; } return acc; }, {}); cache.current[cacheKey] = Object.values(days); return cache.current[cacheKey]; }, [cacheKey, getDays, month]); return _react.default.createElement("div", { className: 'dnb-date-picker__calendar' + (rtl ? " rtl" : ""), lang: locale }, !hideNavigation && !onlyMonth && _react.default.createElement("div", { className: "dnb-date-picker__header" }, _react.default.createElement(_DatePickerCalendarNavigator.DatePickerCalendarNav, { type: yearNavigation ? 'month' : 'both', id: id, nr: nr, date: month, locale: locale }), yearNavigation && _react.default.createElement(_DatePickerCalendarNavigator.DatePickerCalendarNav, { type: "year", id: id, nr: nr, date: month, locale: locale })), onlyMonth && _react.default.createElement("div", { className: "dnb-date-picker__header dnb-date-picker__header--only-month-label" }, _react.default.createElement("label", { id: `${id}--title`, className: "dnb-date-picker__header__title dnb-no-focus", title: selectedMonth.replace(/%s/, (0, _DateFormatUtils.formatDate)(month, { locale, options: { month: 'long' } })), tabIndex: -1 }, (0, _DateFormatUtils.formatDate)(month, { locale, options: { month: 'long' } }))), _react.default.createElement("table", { role: "grid", className: "dnb-no-focus", tabIndex: 0, "aria-labelledby": `${id}--title`, onKeyDown: onKeyDownHandler, onMouseLeave: onMouseLeaveHandler, ref: tableRef }, !hideDays && !onlyMonth && _react.default.createElement("thead", { "aria-hidden": true }, _react.default.createElement("tr", { role: "row", className: "dnb-date-picker__labels" }, (0, _DatePickerCalc.getWeek)((0, _DatePickerCalc.dayOffset)(firstDayOfWeek)).map((day, i) => _react.default.createElement("th", { key: i, role: "columnheader", scope: "col", className: "dnb-date-picker__labels__day", "aria-label": (0, _DateFormatUtils.formatDate)(day, { locale, options: { weekday: 'long' } }) }, (0, _DateFormatUtils.formatDate)(day, { locale, options: { weekday: 'short' } }).substring(0, 2))))), _react.default.createElement("tbody", null, weekDays.map((week, i) => { return _react.default.createElement("tr", { key: 'week' + i, role: "row", className: "dnb-date-picker__days" }, week.map((day, i) => { const title = (0, _DateFormatUtils.formatDate)(day.date, { locale, options: { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' } }); const handleAsDisabled = day.isLastMonth || day.isNextMonth || day.isDisabled || day.isInactive; const dateType = day.isStartDate ? 'start' : day.isEndDate ? 'end' : undefined; const isSelectedDate = nr === 0 ? day.isStartDate : day.isEndDate; const paramsCell = { tabIndex: -1, ...(dateType && { id: `${id}--button-${dateType}` }), ...(isSelectedDate && { ['aria-selected']: true }) }; const paramsButton = { ...(isSelectedDate && { ['aria-current']: 'date' }) }; return _react.default.createElement("td", _extends({ key: 'day' + i, role: "gridcell", className: (0, _classnames.default)("dnb-date-picker__day dnb-no-focus", buildDayClassNames(day)) }, paramsCell), _react.default.createElement(_Button.default, _extends({ size: "medium", variant: "secondary", text: day.date.getDate(), bounding: true, disabled: handleAsDisabled, tabIndex: handleAsDisabled ? 0 : -1, "aria-disabled": handleAsDisabled, "aria-label": title }, paramsButton, { on_click: handleAsDisabled ? undefined : ({ event }) => onSelectRange({ day, isRange, startDate, endDate, resetDate, event, setHasClickedCalendarDay, onSelect: state => { updateDates(state, dates => callOnSelect({ ...dates, event, nr, hidePicker: !isRange })); } }), onMouseOver: handleAsDisabled ? undefined : () => onHoverDay({ day, hoverDate, setHoverDate }), onFocus: handleAsDisabled ? undefined : () => onHoverDay({ day, hoverDate, setHoverDate }) }))); })); })))); } var _default = exports.default = DatePickerCalendar; function onSelectRange({ day, isRange, startDate, endDate, onSelect, resetDate, event, setHasClickedCalendarDay }) { event.persist(); if (!isRange) { return onSelect({ startDate: (0, _dateFns.startOfDay)(day.date), endDate: (0, _dateFns.startOfDay)(day.date), event }); } setHasClickedCalendarDay(true); if (!startDate || resetDate && startDate && endDate) { return onSelect({ startDate: (0, _dateFns.startOfDay)(day.date), endDate: undefined, event }); } const daysToStartDate = Math.abs((0, _dateFns.differenceInCalendarDays)(startDate, day.date)); const daysToEndDate = Math.abs((0, _dateFns.differenceInCalendarDays)(endDate, day.date)); const range = (0, _DatePickerCalc.toRange)(endDate && !resetDate && daysToStartDate < daysToEndDate ? endDate : startDate, day.date); return onSelect({ startDate: (0, _dateFns.startOfDay)(range.startDate), endDate: (0, _dateFns.startOfDay)(range.endDate), event }); } function onHoverDay({ day, hoverDate, setHoverDate }) { if (!(0, _dateFns.isSameDay)(day.date, hoverDate)) { setHoverDate === null || setHoverDate === void 0 || setHoverDate(day.date); } } function buildDayClassNames(day) { return (0, _classnames.default)(day.className, day.isStartDate && 'dnb-date-picker__day--start-date', day.isEndDate && 'dnb-date-picker__day--end-date', day.isPreview && 'dnb-date-picker__day--preview', day.isWithinSelection && 'dnb-date-picker__day--within-selection', day.isSelectable && 'dnb-date-picker__day--selectable', day.isInactive && 'dnb-date-picker__day--inactive', day.isDisabled && 'dnb-date-picker__day--disabled', day.isToday && 'dnb-date-picker__day--today'); } //# sourceMappingURL=DatePickerCalendar.js.map