wix-style-react
Version:
386 lines (321 loc) • 15.5 kB
JavaScript
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _inherits from "@babel/runtime/helpers/inherits";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
import { st, classes } from './Calendar.st.css';
import React from 'react';
import PropTypes from 'prop-types';
import BaseCalendar from './BaseCalendar/BaseCalendar';
import addMonths from 'date-fns/addMonths';
import subMonths from 'date-fns/subMonths';
import startOfMonth from 'date-fns/startOfMonth';
import isSameDay from 'date-fns/isSameDay';
import { CalendarView } from './utils';
import localeUtilsFactory from '../common/LocaleUtils/LocaleUtils'; // todo: remove it in the next major version.
// This file is used for backward compatibility. Since the `locale` prop allows passing `date-fns locale object` as value we still need to support it!
import dateFnsLocaleUtilsFactory from '../common/LocaleUtils/DateFnsLocaleUtils';
import deprecationLog from '../utils/deprecationLog';
import DatePickerHead from './DatePickerHead';
import { WixStyleReactEnvironmentContext } from '../WixStyleReactEnvironmentProvider/context';
import { supportedWixlocales } from 'wix-design-systems-locale-utils';
var Calendar = /*#__PURE__*/function (_React$PureComponent) {
_inherits(Calendar, _React$PureComponent);
var _super = _createSuper(Calendar);
function Calendar(props) {
var _this;
_classCallCheck(this, Calendar);
_this = _super.call(this, props);
_defineProperty(_assertThisInitialized(_this), "_setMonth", function (month) {
_this.setState({
month: month
});
var onMonthChange = _this.props.onMonthChange;
if (onMonthChange) {
onMonthChange(month);
}
});
_defineProperty(_assertThisInitialized(_this), "_getLocaleUtilsFactory", function (locale, firstDayOfWeek) {
// The `dateFnsLocaleUtilsFactory` is used for backward compatibility.
// In case that the user passes an `date-fns locale object` we need to use our old `LocaleUtilsFactory`.
return typeof locale === 'string' ? localeUtilsFactory(locale, firstDayOfWeek) : dateFnsLocaleUtilsFactory(locale, firstDayOfWeek);
});
_defineProperty(_assertThisInitialized(_this), "_createCaptionElement", function () {
var _this$props = _this.props,
showMonthDropdown = _this$props.showMonthDropdown,
showYearDropdown = _this$props.showYearDropdown,
leftArrowAriaLabel = _this$props.leftArrowAriaLabel,
leftArrowAriaLabelledBy = _this$props.leftArrowAriaLabelledBy,
rightArrowAriaLabel = _this$props.rightArrowAriaLabel,
rightArrowAriaLabelledBy = _this$props.rightArrowAriaLabelledBy,
monthDropdownAriaLabel = _this$props.monthDropdownAriaLabel,
monthDropdownAriaLabelledBy = _this$props.monthDropdownAriaLabelledBy,
yearDropdownAriaLabel = _this$props.yearDropdownAriaLabel,
yearDropdownAriaLabelledBy = _this$props.yearDropdownAriaLabelledBy;
var month = _this.state.month;
var locale = _this._getLocale();
var localeUtils = _this._getLocaleUtilsFactory(locale);
return /*#__PURE__*/React.createElement(DatePickerHead, {
className: classes.header,
date: month,
showYearDropdown: showYearDropdown,
showMonthDropdown: showMonthDropdown,
locale: typeof locale === 'string' ? locale : '',
localeUtils: localeUtils,
onChange: _this._setMonth,
onLeftArrowClick: function onLeftArrowClick() {
return _this._setMonth(startOfMonth(addMonths(month, -1)));
},
onRightArrowClick: function onRightArrowClick() {
return _this._setMonth(startOfMonth(addMonths(month, 1)));
},
leftArrowAriaLabel: leftArrowAriaLabel,
leftArrowAriaLabelledBy: leftArrowAriaLabelledBy,
rightArrowAriaLabel: rightArrowAriaLabel,
rightArrowAriaLabelledBy: rightArrowAriaLabelledBy,
monthDropdownAriaLabel: monthDropdownAriaLabel,
monthDropdownAriaLabelledBy: monthDropdownAriaLabelledBy,
yearDropdownAriaLabel: yearDropdownAriaLabel,
yearDropdownAriaLabelledBy: yearDropdownAriaLabelledBy
});
});
var initialMonth = Calendar.getUpdatedMonth(props.value, props.numOfMonths);
_this.state = {
month: initialMonth || new Date()
};
return _this;
}
_createClass(Calendar, [{
key: "UNSAFE_componentWillReceiveProps",
value: function UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.value) {
var month = Calendar.getUpdatedMonth(nextProps.value, nextProps.numOfMonths, this.state.month);
if (month) {
this.setState({
month: month
});
}
}
}
}, {
key: "_getLocale",
value: function _getLocale() {
if (typeof this.props.locale !== 'string') {
deprecationLog('<Calendar/> prop "locale" with value `date-fns locale object` is deprecated and will be removed in next major release, please pass a string instead');
}
return this.props.locale || this.context.locale || 'en';
}
}, {
key: "render",
value: function render() {
var _this$props2 = this.props,
dataHook = _this$props2.dataHook,
className = _this$props2.className,
autoFocus = _this$props2.autoFocus,
numOfMonths = _this$props2.numOfMonths,
firstDayOfWeek = _this$props2.firstDayOfWeek,
onChange = _this$props2.onChange,
onClose = _this$props2.onClose,
excludePastDates = _this$props2.excludePastDates,
filterDate = _this$props2.filterDate,
value = _this$props2.value,
selectionMode = _this$props2.selectionMode,
shouldCloseOnSelect = _this$props2.shouldCloseOnSelect,
locale = _this$props2.locale,
rtl = _this$props2.rtl,
dateIndication = _this$props2.dateIndication,
today = _this$props2.today;
var month = this.state.month;
return /*#__PURE__*/React.createElement(BaseCalendar, {
dataHook: dataHook,
className: st(classes.root, className),
autoFocus: autoFocus,
numOfMonths: numOfMonths,
firstDayOfWeek: firstDayOfWeek,
onChange: onChange,
onClose: onClose,
excludePastDates: excludePastDates,
filterDate: filterDate,
value: value,
selectionMode: selectionMode,
shouldCloseOnSelect: shouldCloseOnSelect,
locale: locale,
rtl: rtl,
dateIndication: dateIndication,
today: today,
onDisplayedViewChange: this._setMonth,
displayedMonth: month,
captionElement: this._createCaptionElement()
});
}
}], [{
key: "areValuesEqual",
value: function areValuesEqual() {
var value1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var value2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (!Boolean(value1) && !Boolean(value2)) {
return true;
}
if (Calendar.isRangeValue(value1) && Calendar.isRangeValue(value2)) {
return isSameDay(value1.from, value2.from) && isSameDay(value1.to, value2.to);
}
return isSameDay(value1, value2);
}
}, {
key: "isSingleDay",
value: function isSingleDay(value) {
return value instanceof Date;
}
}, {
key: "isRangeValue",
value: function isRangeValue(value) {
return Boolean(value.from || value.to);
}
}]);
return Calendar;
}(React.PureComponent);
_defineProperty(Calendar, "displayName", 'Calendar');
_defineProperty(Calendar, "defaultProps", {
className: '',
filterDate: function filterDate() {
return true;
},
dateIndication: function dateIndication() {
return null;
},
shouldCloseOnSelect: true,
onClose: function onClose() {},
autoFocus: true,
excludePastDates: false,
selectionMode: 'day',
showMonthDropdown: false,
showYearDropdown: false,
numOfMonths: 1
});
_defineProperty(Calendar, "optionalParse", BaseCalendar.optionalParse);
_defineProperty(Calendar, "parseValue", BaseCalendar.parseValue);
_defineProperty(Calendar, "nextDay", BaseCalendar.nextDay);
_defineProperty(Calendar, "prevDay", BaseCalendar.prevDay);
_defineProperty(Calendar, "getUpdatedMonth", function (nextPropsValue, numOfMonths, currentMonthDate) {
var nextValue = Calendar.parseValue(nextPropsValue);
if (!currentMonthDate) {
return Calendar.isSingleDay(nextValue) ? nextValue : nextValue.from || nextValue.to;
}
var view = new CalendarView(currentMonthDate, numOfMonths);
if (Calendar.isSingleDay(nextValue)) {
if (!view.isContained(nextValue)) {
return nextValue;
}
} else {
var from = nextValue.from,
to = nextValue.to;
if (from && view.isAfterView(from)) {
// F--- => F---
// VVVVV => VVVVV
return from;
} else if (to && view.isBeforeView(to)) {
if (view.isRangeFits(from, to)) {
// F-T => F-T
// VVVVV => VVVVV
return from;
} else {
// F-----T => F-----T
// VVVVV => VVVVV
return subMonths(to, numOfMonths - 1);
}
} else if (from && view.isBeforeView(from) && to && view.isAfterView(to)) {
// F-------T => F-------T
// VVVVV => VVVVV
return from; // choose the 'from' anchor arbitrarly
}
}
/*
* We only changed the month if the day (or range.edges) are outside the view.
* This is to avoid changing the month right after a user clicks on the calendar.
*/
return null;
});
export { Calendar as default };
Calendar.contextType = WixStyleReactEnvironmentContext;
Calendar.propTypes = {
/** Applies as data-hook HTML attribute that can be used in the tests */
dataHook: PropTypes.string,
/** Focus selected day automatically when component mounts or updates */
autoFocus: PropTypes.bool,
/** Allows to display multiple months at once. Currently it shows 1 or 2 months only. */
numOfMonths: PropTypes.oneOf([1, 2]),
/** First day of the week, allowing only from 0 to 6 (Sunday to Saturday). The default value is 1 which means Monday. */
firstDayOfWeek: PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6]),
/** A single CSS class name to be appended to the root element. */
className: PropTypes.string,
/** Provides a callback function when day in selected in the calendar */
onChange: PropTypes.func.isRequired,
/** Defines a callback function that is called with the date of the first day of the month whenever the user selects a month in the calendar */
onMonthChange: PropTypes.func,
/** Defines a callback function that is called whenever a user presses escape, clicks outside of the element or a date is selected and `shouldCloseOnSelect` is set. Receives an event as a first argument. */
onClose: PropTypes.func,
/** Specify whether past dates should be selectable or not */
excludePastDates: PropTypes.bool,
/**
* ##### Specify selectable dates:
* * `param` {Date} `date` - a date to check
* * `return` {boolean} - true if `date` should be selectable, false otherwise
*/
filterDate: PropTypes.func,
/** Defines the selected date */
value: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date), PropTypes.shape({
from: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),
to: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)])
})]),
/** Whether the user should be able to select a date range, or just a single day */
selectionMode: PropTypes.oneOf(['day', 'range']),
/** Displays a selectable yearDropdown */
showYearDropdown: PropTypes.bool,
/** Displays a selectable monthDropdown */
showMonthDropdown: PropTypes.bool,
/** Specify whether the calendar closes on day selection */
shouldCloseOnSelect: PropTypes.bool,
/** Specify date picker instance locale */
locale: PropTypes.oneOfType([PropTypes.oneOf(supportedWixlocales), PropTypes.shape({
code: PropTypes.string,
formatDistance: PropTypes.func,
formatRelative: PropTypes.func,
localize: PropTypes.object,
formatLong: PropTypes.object,
match: PropTypes.object,
options: PropTypes.object
})]),
/** Specify whether RTL mode is enabled or not. When true, the keyboard navigation will be changed means pressing on the right arrow will navigate to the previous day, and pressing on the left arrow will navigate to the next day. */
rtl: PropTypes.bool,
/**
##### Add an indication under a specific date.
Function returns the indication node of a specific date or null if this day doesn't have an indication.
* - `param` {date: Date, isSelected: boolean }
* - `date` - a date
* - `isSelected` - whether this date is the selected date
* - `return` {React.node} - the indication node of a specific date or null if this day doesn't have an indication.
*/
dateIndication: PropTypes.func,
/** Sets today's date. The today indication is added automatically according to the user timezone but in some cases, we need the ability to add the today indication based on the business timezone. */
today: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),
/** Defines a string value that labels the left arrow in calendar header */
leftArrowAriaLabel: PropTypes.string,
/** Identifies the element that labels the left arrow in calendar header */
leftArrowAriaLabelledBy: PropTypes.string,
/** Defines a string value that labels the right arrow in calendar header */
rightArrowAriaLabel: PropTypes.string,
/** Identifies the element that labels the right arrow in calendar header */
rightArrowAriaLabelledBy: PropTypes.string,
/** Defines a string value that labels the months dropdown in calendar header */
monthDropdownAriaLabel: PropTypes.string,
/** Identifies the element that labels the months dropdown in calendar header */
monthDropdownAriaLabelledBy: PropTypes.string,
/** Defines a string value that labels the years dropdown in calendar header */
yearDropdownAriaLabel: PropTypes.string,
/** Identifies the element that labels the years dropdown in calendar header */
yearDropdownAriaLabelledBy: PropTypes.string
};