@wix/design-system
Version:
@wix/design-system
476 lines (473 loc) • 17.1 kB
JavaScript
"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