wix-style-react
Version:
wix-style-react
347 lines (287 loc) • 13.2 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _class, _temp;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
import React from 'react';
import PropTypes from 'prop-types';
import Popper from 'popper.js';
import DayPickerInput from 'react-day-picker/DayPickerInput';
import isSameDay from 'date-fns/is_same_day';
import setYear from 'date-fns/set_year';
import setMonth from 'date-fns/set_month';
import setDate from 'date-fns/set_date';
import WixComponent from '../BaseComponents/WixComponent';
import CalendarIcon from '../new-icons/Date';
import { formatDate } from '../LocaleUtils';
import Calendar from '../Calendar';
import Input from '../Input';
import styles from './DatePicker.scss';
/**
* DatePicker component
*
* ### Keyboard support
* * `Left`: Move to the previous day.
* * `Right`: Move to the next day.
* * `Up`: Move to the previous week.
* * `Down`: Move to the next week.
* * `PgUp`: Move to the previous month.
* * `PgDn`: Move to the next month.
* * `Home`: Move to the previous year.
* * `End`: Move to the next year.
* * `Enter`/`Esc`/`Tab`: close the calendar. (`Enter` & `Esc` calls `preventDefault`)
*
*/
var DatePicker = (_temp = _class = function (_WixComponent) {
_inherits(DatePicker, _WixComponent);
function DatePicker(props) {
_classCallCheck(this, DatePicker);
var _this = _possibleConstructorReturn(this, (DatePicker.__proto__ || Object.getPrototypeOf(DatePicker)).call(this, props));
_this.openCalendar = function () {
if (!_this.state.isOpen) {
_this.setState({
isOpen: true,
isDateInputFocusable: false,
value: _this.props.value || new Date()
}, function () {
return _this._popper.scheduleUpdate();
});
}
};
_this.closeCalendar = function () {
_this.setState({ isOpen: false }, function () {
if (_this.props.onClose) {
_this.props.onClose();
}
});
/*
to fix case when user press tab in opened Calendar and:
1. Calendar become closed
2. Focus triggered
3. openCalendar triggered by focus
4. Calendar become visible
5. Looks like nothing happen
We need to do such steps:
1. Close calendar(with isDateInputFocusable: false)
2. After calendar is closed, on next event loop(after focus is fired) make isDateInputFocusable: focusable
to allow user to press tab in future and open Calendar
*/
setTimeout(function () {
return _this.makeInputFocusable();
});
};
_this.makeInputFocusable = function () {
return _this.setState({ isDateInputFocusable: true });
};
_this._saveNewValue = function (value) {
var modifiers = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (modifiers.disabled) {
return;
}
var isChanged = !isSameDay(value, _this.props.value);
if (isChanged) {
var newValue = [[value.getFullYear(), setYear], [value.getMonth(), setMonth], [value.getDate(), setDate]].reduce(function (_value, _ref) {
var _ref2 = _slicedToArray(_ref, 2),
datePart = _ref2[0],
setter = _ref2[1];
return setter(_value, datePart);
}, _this.props.value);
_this.setState({ value: newValue }, function () {
return _this.props.onChange(newValue);
});
}
};
_this._handleKeyDown = function (event) {
// TODO: dirty for now
// tab key should move focus so can't preventDefault
if (event.keyCode !== 9) {
event.preventDefault();
}
if (!_this.state.isOpen) {
_this.openCalendar();
}
// keyHandler(this.state.value);
};
_this._formatDateValue = function () {
var _this$props = _this.props,
value = _this$props.value,
dateFormat = _this$props.dateFormat,
locale = _this$props.locale;
if (!value) {
return '';
}
if (typeof dateFormat === 'function') {
return dateFormat(value);
}
return formatDate(value, dateFormat, locale);
};
_this._renderInput = function () {
var _this$props2 = _this.props,
inputDataHook = _this$props2.inputDataHook,
disabled = _this$props2.disabled,
placeholderText = _this$props2.placeholderText,
readOnly = _this$props2.readOnly,
initialValue = _this$props2.value,
error = _this$props2.error,
errorMessage = _this$props2.errorMessage,
customInput = _this$props2.customInput,
inputProps = _this$props2.inputProps;
var _inputProps = _extends({
dataHook: inputDataHook,
value: _this._formatDateValue(initialValue),
onInputClicked: _this.openCalendar,
disabled: disabled,
readOnly: readOnly,
placeholder: placeholderText,
prefix: React.createElement(
'span',
{ className: styles.icon },
React.createElement(CalendarIcon, null)
),
onFocus: _this.openCalendar,
onKeyDown: _this._handleKeyDown,
tabIndex: _this.state.isDateInputFocusable ? 1 : -1,
error: error,
errorMessage: errorMessage,
autoSelect: false
}, customInput ? customInput.props : {}, inputProps);
return React.cloneElement(customInput || React.createElement(Input, null), _inputProps);
};
_this._setInputRef = function (ref) {
return _this.inputRef = ref;
};
_this._setCalendarRef = function (ref) {
return _this.calendarRef = ref;
};
_this.state = {
value: props.value || new Date(),
isOpen: props.isOpen || false,
isDateInputFocusable: !props.isOpen
};
return _this;
}
_createClass(DatePicker, [{
key: 'componentDidMount',
value: function componentDidMount() {
_get(DatePicker.prototype.__proto__ || Object.getPrototypeOf(DatePicker.prototype), 'componentDidMount', this).call(this);
this._popper = new Popper(this.inputRef, this.calendarRef, {
placement: 'top-start'
});
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this._popper.destroy();
_get(DatePicker.prototype.__proto__ || Object.getPrototypeOf(DatePicker.prototype), 'componentWillUnmount', this).call(this);
}
}, {
key: 'onClickOutside',
value: function onClickOutside() {
this.closeCalendar();
}
}, {
key: 'render',
value: function render() {
var _props = this.props,
showMonthDropdown = _props.showMonthDropdown,
showYearDropdown = _props.showYearDropdown,
filterDate = _props.filterDate,
excludePastDates = _props.excludePastDates,
rtl = _props.rtl,
shouldCloseOnSelect = _props.shouldCloseOnSelect,
width = _props.width,
calendarDataHook = _props.calendarDataHook,
twoMonths = _props.twoMonths,
locale = _props.locale,
zIndex = _props.zIndex;
var _state = this.state,
isOpen = _state.isOpen,
value = _state.value;
var calendarProps = {
locale: locale,
showMonthDropdown: showMonthDropdown,
showYearDropdown: showYearDropdown,
filterDate: filterDate,
excludePastDates: excludePastDates,
rtl: rtl,
onChange: this._saveNewValue,
onClose: this.closeCalendar,
value: value,
shouldCloseOnSelect: shouldCloseOnSelect,
numOfMonths: twoMonths ? 2 : 1
};
return React.createElement(
'div',
{ style: { width: width }, className: styles.root },
React.createElement(
'div',
{ ref: this._setInputRef },
React.createElement(DayPickerInput, { component: this._renderInput, keepFocus: false })
),
React.createElement(
'div',
{
ref: this._setCalendarRef,
'data-hook': calendarDataHook,
style: { zIndex: zIndex }
},
isOpen && React.createElement(Calendar, _extends({
className: styles.datePickerCalendar
}, calendarProps))
)
);
}
}]);
return DatePicker;
}(WixComponent), _class.displayName = 'DatePicker', _class.defaultProps = {
locale: 'en',
dateFormat: 'MM/DD/YYYY',
filterDate: function filterDate() {
return true;
},
rtl: false,
width: 150,
zIndex: 1
}, _temp);
export { DatePicker as default };
DatePicker.propTypes = _extends({}, Calendar.propTypes, {
/** Can provide Input with your custom props. If you don't need a custom input element, and only want to pass props to the Input, then use inputProps prop. I think this is not in use outside of WSR, and can be deprecated. */
customInput: PropTypes.node,
/** Properties appended to the default Input component or the custom Input component. */
inputProps: PropTypes.object,
/** Custom date format, can be either:
* * `string` of tokens (see [`date-fns` docs](https://date-fns.org/v1.29.0/docs/format) for list of supported tokens)
* * `function` of signature `Date -> String`
*/
dateFormat: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
/** DatePicker instance locale */
locale: PropTypes.oneOfType([PropTypes.oneOf(['en', 'es', 'pt', 'fr', 'de', 'pl', 'it', 'ru', 'ja', 'ko', 'tr', 'sv', 'no', 'nl', 'da']), PropTypes.shape({
distanceInWords: PropTypes.object,
format: PropTypes.object
})]),
/** Is the DatePicker disabled */
disabled: PropTypes.bool,
/** dataHook for the DatePicker's Input */
inputDataHook: PropTypes.string,
/** calendarDataHook for the DatePicker's calendar view */
calendarDataHook: PropTypes.string,
/** placeholder of the Input */
placeholderText: PropTypes.string,
/** RTL mode */
rtl: PropTypes.bool,
/** The selected date */
value: PropTypes.object,
/** controls the whether the calendar will be visible or not */
isOpen: PropTypes.bool,
/** will show exclamation icon when true **/
error: PropTypes.bool,
/** will display message when hovering error icon **/
errorMessage: PropTypes.node,
/** set desired width of DatePicker input */
width: PropTypes.number,
/** set desired z-index of DatePicker popover */
zIndex: PropTypes.number
});