UNPKG

@wix/design-system

Version:

@wix/design-system

476 lines (473 loc) 17.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _BaseCalendarSt = require("./BaseCalendar.st.css.js"); var _react = _interopRequireDefault(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _reactDayPicker = _interopRequireDefault(require("react-day-picker")); var _LocaleUtils = _interopRequireDefault(require("../../common/LocaleUtils/LocaleUtils")); var _context = require("../../WixStyleReactEnvironmentProvider/context"); var _wixDesignSystemsLocaleUtils = require("wix-design-systems-locale-utils"); var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/cjs/Calendar/BaseCalendar/BaseCalendar.tsx"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } class BaseCalendar extends _react.default.PureComponent { constructor() { var _this; super(...arguments); _this = this; this.context = void 0; this.dayPickerRef = void 0; this._renderDay = (day, modifiers) => { var { dateIndication } = this.props; var isOutsideDay = !!modifiers[(0, _BaseCalendarSt.cssStates)({ outside: true })]; var isSelectedDay = !!modifiers[(0, _BaseCalendarSt.cssStates)({ selected: true })]; var dateIndicationNode = dateIndication && dateIndication({ date: day, isSelected: isSelectedDay }); var shouldHasIndication = dateIndicationNode && !isOutsideDay; return /*#__PURE__*/_react.default.createElement("div", { className: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.dayWrapper, { hasIndication: shouldHasIndication }), "data-date": "".concat(day.getFullYear(), "-").concat(day.getMonth(), "-").concat(day.getDate()), "data-outsideday": isOutsideDay, __self: this, __source: { fileName: _jsxFileName, lineNumber: 134, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement("div", { className: _BaseCalendarSt.classes.dayText, __self: this, __source: { fileName: _jsxFileName, lineNumber: 141, columnNumber: 9 } }, day.getDate()), shouldHasIndication ? /*#__PURE__*/_react.default.createElement("div", { className: _BaseCalendarSt.classes.dayIndicationContainer, __self: this, __source: { fileName: _jsxFileName, lineNumber: 143, columnNumber: 11 } }, dateIndicationNode) : null); }; this._handleDayClick = function (value) { var modifiers = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var event = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; _this._preventActionEventDefault(event); var propsValue = _this.props.value || {}; var { onChange, shouldCloseOnSelect } = _this.props; var isNotRange = value => { if (!('from' in value) || !value.from) { return false; } if (!('to' in value) || !value.to) { return false; } return true; }; var isCompleteRange = value => { if (!('from' in value) || !('to' in value)) { return false; } return !!(value.from && value.to); }; if (_this.props.selectionMode === 'range') { if (isNotRange(propsValue) || isCompleteRange(propsValue)) { onChange({ from: value }, modifiers); } else { /** Previous `if` checks that both are missing or both are present. At least one should be here */ var anchor = propsValue.from || propsValue.to; var newVal = anchor < value ? { from: anchor, to: value } : { from: value, to: anchor }; onChange(newVal, modifiers); shouldCloseOnSelect && _this.props.onClose(event); } } else { onChange(value, modifiers); shouldCloseOnSelect && _this.props.onClose(event); } }; this._preventActionEventDefault = function () { var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; if (event && (!('key' in event) || event.key !== 'Escape' && event.key !== 'Tab')) { event.preventDefault(); } }; this._createWeekdayElement = localeUtils => { return _ref => { var { className, weekday } = _ref; var weekdayShort = localeUtils.formatWeekdayShort(weekday); var weekdayLong = localeUtils.formatWeekdayLong(weekday); return /*#__PURE__*/_react.default.createElement("div", { className: className, "aria-label": weekdayLong, role: "columnheader", __self: this, __source: { fileName: _jsxFileName, lineNumber: 242, columnNumber: 9 } }, /*#__PURE__*/_react.default.createElement("abbr", { "data-hook": "weekday-day", __self: this, __source: { fileName: _jsxFileName, lineNumber: 243, columnNumber: 11 } }, weekdayShort)); }; }; this._createDayPickerProps = () => { var { filterDate, excludePastDates, numOfMonths, firstDayOfWeek, rtl, today, onDisplayedViewChange, displayedMonth, captionElement, allowSelectingOutsideDays, size } = this.props; var locale = this._getLocale(); var value = BaseCalendar.parseValue(this.props.value); var localeUtils = (0, _LocaleUtils.default)(locale, firstDayOfWeek); var { from, to } = value instanceof Date ? { from: undefined, to: undefined } : value; var singleDay = !from && !to && value; var firstOfMonth = [new Date(displayedMonth.getFullYear(), displayedMonth.getMonth(), 1), new Date(displayedMonth.getFullYear(), displayedMonth.getMonth() + 1, 1)]; var lastOfMonth = [new Date(displayedMonth.getFullYear(), displayedMonth.getMonth() + 1, 0), new Date(displayedMonth.getFullYear(), displayedMonth.getMonth() + 2, 0)]; var selectedDays = this._getSelectedDays(value); var weekdayElement = this._createWeekdayElement(localeUtils); var modifiers = _objectSpread({ [(0, _BaseCalendarSt.cssStates)({ start: true })]: from, [(0, _BaseCalendarSt.cssStates)({ end: true })]: to, [(0, _BaseCalendarSt.cssStates)({ firstOfMonth: true })]: firstOfMonth, [(0, _BaseCalendarSt.cssStates)({ lastOfMonth: true })]: lastOfMonth, [(0, _BaseCalendarSt.cssStates)({ singleDay: true })]: singleDay }, this.props.modifiers); if (today) { /** parseValue always returns Date if you give it a Date */ modifiers[(0, _BaseCalendarSt.cssStates)({ today: true })] = BaseCalendar.parseValue(today); } // We must add the dummy state since ReactDayPicker use it as a selector in their code var outsideCssState = allowSelectingOutsideDays ? (0, _BaseCalendarSt.cssStates)({ dummyOutside: true }) : (0, _BaseCalendarSt.cssStates)({ outside: true }); return { disabledDays: [date => !filterDate(new Date(date)), excludePastDates ? { before: new Date() } : {}], initialMonth: displayedMonth, initialYear: displayedMonth, selectedDays, month: displayedMonth, year: displayedMonth, locale: typeof locale === 'string' ? locale : '', fixedWeeks: true, onKeyDown: this._handleKeyDown, onDayClick: this._handleDayClick, // @ts-expect-error Missing props probably aren't used localeUtils, navbarElement: () => null, captionElement, // @ts-expect-error Probably a live bug or there's no caption to click onCaptionClick: this._preventActionEventDefault, onDayKeyDown: this._handleDayKeyDown, numberOfMonths: numOfMonths, modifiers, renderDay: this._renderDay, dir: rtl ? 'rtl' : 'ltr', tabIndex: 0, weekdayElement, classNames: { /* The classes: 'DayPicker', 'DayPicker-wrapper', 'DayPicker-Month', 'DayPicker-Day', 'disabled' are used as selectors for the elements at the drivers and at the e2e tests */ container: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.container, { size }, 'DayPicker'), wrapper: 'DayPicker-wrapper', interactionDisabled: 'DayPicker--interactionDisabled', months: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.months, { twoMonths: numOfMonths > 1 }), month: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.month, { size }, 'DayPicker-Month'), weekdays: _BaseCalendarSt.classes.weekdays, weekdaysRow: _BaseCalendarSt.classes.weekdaysRow, weekday: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.weekday, { size }), body: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.body, { size }), week: _BaseCalendarSt.classes.week, weekNumber: 'DayPicker-WeekNumber', day: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.day, { size }, 'DayPicker-Day'), // default modifiers today: (0, _BaseCalendarSt.cssStates)({ today: !today }), selected: (0, _BaseCalendarSt.cssStates)({ selected: true }), disabled: (0, _BaseCalendarSt.st)('disabled', (0, _BaseCalendarSt.cssStates)({ disabled: true })), outside: outsideCssState }, onMonthChange: onDisplayedViewChange }; }; this._handleKeyDown = event => { var { onKeyDown } = this.props; if (onKeyDown) { onKeyDown(event); return; } if (event.key === 'Escape') { this.props.onClose(event); } }; this._toggleFirstDayTabIndex = tabIndex => { var firstDay = this._getDayPicker().dayPicker.querySelector(".DayPicker-Day[tabindex=\"".concat(tabIndex, "\"]")); if (!firstDay) { throw new Error('<BaseCalendar /> No first day found in day picker'); } firstDay.tabIndex = tabIndex === 0 ? -1 : 0; }; this._focusSelectedDay = () => { if (this.dayPickerRef) { var selectedDay = this.dayPickerRef.dayPicker.querySelector(".".concat((0, _BaseCalendarSt.cssStates)({ selected: true }))); if (selectedDay) { // The 'unfocused' class is used as a selector at the drivers and e2e test selectedDay.classList.add((0, _BaseCalendarSt.cssStates)({ unfocused: true }), 'unfocused'); selectedDay.tabIndex = 0; selectedDay.focus(); this._toggleFirstDayTabIndex(0); } else { this._toggleFirstDayTabIndex(-1); } } }; this._handleDayKeyDown = function (_value, _modifiers) { var event = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; _this._preventActionEventDefault(event); var unfocusedDay = _this._getDayPicker().dayPicker.querySelector(".".concat((0, _BaseCalendarSt.cssStates)({ unfocused: true }))); if (unfocusedDay) { // The 'unfocused' class is used as a selector at the drivers and e2e test unfocusedDay.classList.remove((0, _BaseCalendarSt.cssStates)({ unfocused: true }), 'unfocused'); } }; } _getSelectedDays(value) { var { from, to } = !value || value instanceof Date ? { from: undefined, to: undefined } : value; if (from && to) { return { from, to }; } else if (from) { return { after: BaseCalendar.prevDay(from) }; } else if (to) { return { before: BaseCalendar.nextDay(to) }; } else { // Single day OR empty value return value; } } _getDayPicker() { if (!this.dayPickerRef) { throw new Error("<BaseCalendar /> didn't have a day picker set"); } return this.dayPickerRef; } _getLocale() { return this.props.locale || this.context.locale || 'en'; } componentDidMount() { this.props.autoFocus && this._focusSelectedDay(); if (this.dayPickerRef) { // @ts-expect-error wrapper is badly declared on DayPicker class this.dayPickerRef.wrapper.tabIndex = -1; } } componentDidUpdate(prevProps) { if (!prevProps.autoFocus && this.props.autoFocus) { this._focusSelectedDay(); } } render() { var { dataHook, className, size } = this.props; return /*#__PURE__*/_react.default.createElement("div", { "data-hook": dataHook, "data-size": size, className: (0, _BaseCalendarSt.st)(_BaseCalendarSt.classes.root, className), onClick: this._preventActionEventDefault, role: "dialog", tabIndex: -1, __self: this, __source: { fileName: _jsxFileName, lineNumber: 453, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement(_reactDayPicker.default, (0, _extends2.default)({ ref: _ref2 => this.dayPickerRef = _ref2 }, this._createDayPickerProps(), { __self: this, __source: { fileName: _jsxFileName, lineNumber: 461, columnNumber: 9 } }))); } } exports.default = BaseCalendar; BaseCalendar.displayName = 'BaseCalendar'; BaseCalendar.defaultProps = { className: '', filterDate: () => true, dateIndication: () => null, shouldCloseOnSelect: true, onClose: () => {}, autoFocus: true, excludePastDates: false, selectionMode: 'day', numOfMonths: 1, size: 'medium', allowSelectingOutsideDays: false }; BaseCalendar.propTypes = { dataHook: _propTypes.default.string, autoFocus: _propTypes.default.bool, numOfMonths: _propTypes.default.oneOf([1, 2]), firstDayOfWeek: _propTypes.default.oneOf([0, 1, 2, 3, 4, 5, 6]), className: _propTypes.default.string, onChange: _propTypes.default.func.isRequired, onClose: _propTypes.default.func, onKeyDown: _propTypes.default.func, excludePastDates: _propTypes.default.bool, filterDate: _propTypes.default.func, value: _propTypes.default.oneOfType([_propTypes.default.instanceOf(Date), _propTypes.default.shape({ from: _propTypes.default.instanceOf(Date), to: _propTypes.default.instanceOf(Date) })]), selectionMode: _propTypes.default.oneOf(['day', 'range']), shouldCloseOnSelect: _propTypes.default.bool, locale: _propTypes.default.oneOfType([_propTypes.default.oneOf(_wixDesignSystemsLocaleUtils.SupportedWixLocales)]), rtl: _propTypes.default.bool, dateIndication: _propTypes.default.func, today: _propTypes.default.instanceOf(Date), displayedMonth: _propTypes.default.instanceOf(Date).isRequired, onDisplayedViewChange: _propTypes.default.func.isRequired, captionElement: _propTypes.default.node.isRequired, modifiers: _propTypes.default.object, allowSelectingOutsideDays: _propTypes.default.bool }; /** Return a value in which all string-dates are parsed into Date objects */ BaseCalendar.parseValue = value => { if (!value) { return new Date(); } if (value instanceof Date) { return value; } else { return { from: value.from, to: value.to }; } }; BaseCalendar.nextDay = date => { var day = new Date(date); day.setDate(day.getDate() + 1); return day; }; BaseCalendar.prevDay = date => { var day = new Date(date); day.setDate(day.getDate() - 1); return day; }; BaseCalendar.contextType = _context.WixStyleReactEnvironmentContext; //# sourceMappingURL=BaseCalendar.js.map