@wix/design-system
Version:
@wix/design-system
525 lines (518 loc) • 20.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
exports.__esModule = true;
exports["default"] = exports.DEFAULT_TIME_STYLE = exports.DEFAULT_STEP = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _Input = _interopRequireDefault(require("../Input"));
var _DropdownBase = _interopRequireDefault(require("../DropdownBase"));
var _constants = require("./constants");
var _TimeInputSt = require("./TimeInput.st.css.js");
var _designSystemsLocaleUtils = require("@wix/design-systems-locale-utils");
var _context = require("../WixStyleReactEnvironmentProvider/context");
var _TimeInputUtils = require("./TimeInputUtils");
var _useEventCallback = require("../common/useEventCallback/useEventCallback");
var _excluded = ["dataHook", "className", "size", "suffix", "prefix", "status", "statusMessage", "invalidMessage", "border", "disabled", "placeholder", "readOnly", "autoSelect", "width", "timeStyle", "onChange", "onInvalid", "step", "noRightBorderRadius", "noLeftBorderRadius", "popoverProps", "onFocus", "onBlur", "excludePastTimes", "filterTime", "disableKeyboardType", "disableAutoComplete", "hideStatusSuffix", "value", "inputRef", "customInput"];
var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/cjs/TimeInput/TimeInput.jsx",
_this = void 0;
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(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 (var _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 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; }
var DEFAULT_STEP = exports.DEFAULT_STEP = 15;
var DEFAULT_TIME_STYLE = exports.DEFAULT_TIME_STYLE = 'short';
var ERROR_TYPES = {
FORMAT: 'formatError',
OUT_OF_BOUNDS: 'outOfBoundsError'
};
var initialState = {
isDropdownOpen: false,
inputValue: '',
selectedId: null,
customInputId: null,
highlightedOptionId: null,
error: false,
selectionRange: false,
deleteEvent: false,
scrollToOption: null,
lastSavedDate: null
};
function reducer(state, action) {
switch (action.type) {
case _constants.ACTION.RESET:
return _objectSpread({}, initialState);
case _constants.ACTION.SET_STATE:
return _objectSpread(_objectSpread({}, state), action.payload);
case _constants.ACTION.SET_ERROR:
return _objectSpread(_objectSpread({}, state), {}, {
error: true,
validationType: action.payload
});
case _constants.ACTION.OPEN_DROPDOWN:
return _objectSpread(_objectSpread({}, state), {}, {
isDropdownOpen: true
});
case _constants.ACTION.CLOSE_DROPDOWN:
return _objectSpread(_objectSpread({}, state), {}, {
isDropdownOpen: false
});
case _constants.ACTION.DELETE_EVENT:
return _objectSpread(_objectSpread({}, state), {}, {
deleteEvent: true
});
default:
return state;
}
}
var TimeInput = /*#__PURE__*/_react["default"].forwardRef(function (_ref, ref) {
var dataHook = _ref.dataHook,
className = _ref.className,
size = _ref.size,
suffix = _ref.suffix,
prefix = _ref.prefix,
status = _ref.status,
statusMessage = _ref.statusMessage,
invalidMessage = _ref.invalidMessage,
border = _ref.border,
disabled = _ref.disabled,
placeholder = _ref.placeholder,
readOnly = _ref.readOnly,
autoSelect = _ref.autoSelect,
_ref$width = _ref.width,
width = _ref$width === void 0 ? 'auto' : _ref$width,
_ref$timeStyle = _ref.timeStyle,
timeStyle = _ref$timeStyle === void 0 ? DEFAULT_TIME_STYLE : _ref$timeStyle,
onChange = _ref.onChange,
onInvalid = _ref.onInvalid,
_ref$step = _ref.step,
step = _ref$step === void 0 ? DEFAULT_STEP : _ref$step,
noRightBorderRadius = _ref.noRightBorderRadius,
noLeftBorderRadius = _ref.noLeftBorderRadius,
popoverProps = _ref.popoverProps,
onFocus = _ref.onFocus,
onBlur = _ref.onBlur,
excludePastTimes = _ref.excludePastTimes,
filterTime = _ref.filterTime,
disableKeyboardType = _ref.disableKeyboardType,
disableAutoComplete = _ref.disableAutoComplete,
hideStatusSuffix = _ref.hideStatusSuffix,
value = _ref.value,
externalInputRef = _ref.inputRef,
customInput = _ref.customInput,
rest = (0, _objectWithoutProperties2["default"])(_ref, _excluded);
var inputRef = (0, _react.useRef)(null);
var context = (0, _react.useContext)(_context.WixStyleReactEnvironmentContext);
var _useReducer = (0, _react.useReducer)(reducer, initialState),
_useReducer2 = (0, _slicedToArray2["default"])(_useReducer, 2),
state = _useReducer2[0],
dispatch = _useReducer2[1];
var locale = rest.locale || context.locale || 'en';
var valueAsDate = value ? new Date(value).setSeconds(0, 0) : undefined;
var showError = invalidMessage && state.error;
var autofillValue = state.selectionRange ? state.inputValue.substring(state.selectionRange.selectionStart) : null;
var resolvedStatusMessage = showError ? invalidMessage : statusMessage;
var timeFilter = (0, _react.useMemo)(function () {
return (0, _TimeInputUtils.getTimeFilter)({
excludePastTimes: excludePastTimes,
filterTime: filterTime
});
}, [excludePastTimes, filterTime]);
var timeSlots = (0, _react.useMemo)(function () {
var slots = (0, _TimeInputUtils.getTimeSlots)({
value: valueAsDate,
timeStyle: timeStyle,
locale: locale,
step: step
});
return slots.filter(function (_ref2) {
var id = _ref2.id;
return timeFilter(new Date(id));
});
}, [valueAsDate, timeStyle, locale, step, timeFilter]);
var handleOnInvalid = (0, _useEventCallback.useEventCallback)(function () {
onInvalid == null || onInvalid({
validationType: state.validationType,
value: state.inputValue
});
});
var syncExternalValue = (0, _react.useCallback)(function () {
if (value === null) {
dispatch({
type: _constants.ACTION.RESET
});
return;
}
// External masks need a clean empty starting state.
if (!valueAsDate && disableAutoComplete) {
return;
}
var timeSlot = valueAsDate ? (0, _TimeInputUtils.getTimeSlot)({
value: valueAsDate,
timeStyle: timeStyle,
locale: locale
}) : (0, _TimeInputUtils.getClosestTimeSlot)({
value: valueAsDate,
timeSlots: timeSlots
});
var selectedOption = timeSlot && timeSlots.find(function (slot) {
return timeSlot.id === slot.id;
});
dispatch({
type: _constants.ACTION.SET_STATE,
payload: {
inputValue: timeSlot && timeSlot.value,
selectedId: selectedOption && selectedOption.id
}
});
}, [value, valueAsDate, locale, timeSlots, timeStyle, disableAutoComplete]);
var openDropdown = (0, _react.useCallback)(function () {
if (readOnly) {
return;
}
if (state.selectedId || state.highlightedOptionId) {
dispatch({
type: _constants.ACTION.OPEN_DROPDOWN
});
return;
}
var closestTimeSlot = (0, _TimeInputUtils.getClosestTimeSlot)({
value: new Date(state.customInputId || valueAsDate),
timeSlots: timeSlots
});
if (!state.isDropdownOpen) {
dispatch({
type: _constants.ACTION.OPEN_DROPDOWN
});
}
// Always scroll to the most relevant option once the list is displayed
dispatch({
type: _constants.ACTION.SET_STATE,
payload: {
scrollToOption: state.selectedId || state.highlightedOptionId || (closestTimeSlot == null ? void 0 : closestTimeSlot.id)
}
});
}, [readOnly, state.isDropdownOpen, state.selectedId, state.highlightedOptionId, state.customInputId, timeSlots, valueAsDate]);
var findSelectedOption = (0, _react.useCallback)(function () {
if (state.selectedId) {
return {
id: state.selectedId,
value: state.inputValue
};
}
var highlightedOption = timeSlots.find(function (slot) {
return slot.id === state.highlightedOptionId;
});
if (highlightedOption) {
return highlightedOption;
}
if (state.inputValue && !state.selectedId) {
var customValue = (0, _TimeInputUtils.getCustomTimeSlot)({
value: state.inputValue,
timeSlot: timeSlots[0].id,
timeStyle: timeStyle,
locale: locale
});
if (customValue) {
return {
value: customValue.value,
customId: customValue.id
};
}
}
}, [locale, state.highlightedOptionId, state.inputValue, state.selectedId, timeSlots, timeStyle]);
var validateAndSetOption = (0, _react.useCallback)(function (opt) {
var _state$lastSavedDate$, _state$lastSavedDate, _date$getTime;
var option = opt ? opt : findSelectedOption();
// Validate
if (!option) {
dispatch({
type: _constants.ACTION.SET_ERROR,
payload: ERROR_TYPES.FORMAT
});
return;
} else if (!timeFilter(new Date(option.id || option.customId))) {
dispatch({
type: _constants.ACTION.SET_ERROR,
payload: ERROR_TYPES.OUT_OF_BOUNDS
});
return;
}
// Set selected option
var date = option ? new Date(option.customId || option.id) : null;
var hasDateChanged = ((_state$lastSavedDate$ = (_state$lastSavedDate = state.lastSavedDate) == null || _state$lastSavedDate.getTime == null ? void 0 : _state$lastSavedDate.getTime()) !== null && _state$lastSavedDate$ !== void 0 ? _state$lastSavedDate$ : null) !== ((_date$getTime = date == null || date.getTime == null ? void 0 : date.getTime()) !== null && _date$getTime !== void 0 ? _date$getTime : null);
dispatch({
type: _constants.ACTION.SET_STATE,
payload: {
selectedId: option.id,
customInputId: option.customId,
inputValue: option.value,
selectionRange: false,
isDropdownOpen: false,
highlightedOptionId: null,
error: false,
lastSavedDate: date
}
});
if (option && hasDateChanged) {
onChange == null || onChange({
date: date
});
}
return option;
}, [findSelectedOption, timeFilter, onChange, state.lastSavedDate]);
var _onKeyDown = (0, _react.useCallback)(function (e, delegateKeyDown) {
if (e.key === ' ' || e.key === 'Spacebar') return;
if (!state.isDropdownOpen && e.key === 'ArrowDown') {
openDropdown();
return e.preventDefault();
}
delegateKeyDown(e);
if (e.key === 'Backspace') {
dispatch({
type: _constants.ACTION.DELETE_EVENT
});
}
if (state.isDropdownOpen) {
switch (e.key) {
case 'Escape':
{
dispatch({
type: _constants.ACTION.CLOSE_DROPDOWN
});
return e.preventDefault();
}
case 'Enter':
{
dispatch({
type: _constants.ACTION.CLOSE_DROPDOWN
});
inputRef.current.setSelectionRange(state.inputValue.length, state.inputValue.length);
if (!state.error) {
return validateAndSetOption();
}
}
}
}
}, [state.isDropdownOpen, state.inputValue, openDropdown, validateAndSetOption, state.error]);
var onInputChange = (0, _react.useCallback)(function (e) {
var inputValue = e.target.value;
var isDropdownOpen = state.isDropdownOpen;
var selectedId = state.selectedId;
var selectionRange = false;
var error = false;
var validationType;
// Open dropdown when value is selected with keyboard and/or value is typed again
if (!isDropdownOpen) {
isDropdownOpen = true;
}
// Skip mid-typing format validation under `disableAutoComplete`
// (the mask owns validity); blur still validates. Treat
// all-placeholder values as not-yet-entered.
if (!disableAutoComplete && (0, _TimeInputUtils.isInputInvalid)(e.target.value) && !(0, _TimeInputUtils.isMaskPlaceholderOnly)(e.target.value)) {
error = true;
validationType = ERROR_TYPES.FORMAT;
isDropdownOpen = false;
}
var selectedSlot = timeSlots.find(function (s) {
return s.id === state.selectedId;
});
if (!selectedSlot || inputValue !== selectedSlot.value) {
selectedId = null;
}
var suggestedOption = (0, _TimeInputUtils.getSuggestedOption)({
inputValue: (0, _TimeInputUtils.stripMaskPlaceholders)(inputValue),
timeSlots: timeSlots,
locale: locale
});
if (!state.deleteEvent && suggestedOption && !disableAutoComplete) {
var autoFillValue = (0, _TimeInputUtils.getAutoFilledValue)({
inputValue: inputValue,
suggestedOption: suggestedOption,
locale: locale
});
var inputWithAutoFill = inputValue + autoFillValue;
inputValue = inputValue + autoFillValue;
selectionRange = {
selectionStart: inputWithAutoFill.length - autoFillValue.length,
selectionEnd: inputWithAutoFill.length
};
}
var highlightedOptionId = suggestedOption ? suggestedOption.id : null;
dispatch({
type: _constants.ACTION.SET_STATE,
payload: {
isDropdownOpen: isDropdownOpen,
error: error,
validationType: validationType,
selectedId: selectedId,
highlightedOptionId: highlightedOptionId,
selectionRange: selectionRange,
inputValue: inputValue,
deleteEvent: false
}
});
}, [state.deleteEvent, timeSlots, state.isDropdownOpen, state.selectedId, locale, disableAutoComplete]);
var onInputBlur = (0, _react.useCallback)(function (e) {
onBlur == null || onBlur(e);
if (state.isDropdownOpen) {
dispatch({
type: _constants.ACTION.CLOSE_DROPDOWN
});
}
if (state.error) return;
if (state.inputValue === '') {
return onChange == null ? void 0 : onChange({
date: null
});
}
if ((0, _TimeInputUtils.isMaskPlaceholderOnly)(state.inputValue)) {
dispatch({
type: _constants.ACTION.RESET
});
return onChange == null ? void 0 : onChange({
date: null
});
}
validateAndSetOption();
}, [validateAndSetOption, onChange, onBlur, state.error, state.isDropdownOpen, state.inputValue]);
(0, _react.useImperativeHandle)(ref, function () {
return {
focus: function focus() {
inputRef.current.focus();
openDropdown();
},
blur: function blur() {
inputRef.current.blur();
},
clear: function clear() {
dispatch({
type: _constants.ACTION.RESET
});
onChange == null || onChange({
date: null
});
}
};
}, [onChange, openDropdown]);
(0, _react.useEffect)(syncExternalValue, [syncExternalValue]);
(0, _react.useEffect)(function () {
// Select range when suggestedInputValue is changed
if (state.selectionRange) {
inputRef.current.setSelectionRange(state.selectionRange.selectionStart, state.selectionRange.selectionEnd);
}
}, [state.selectionRange]);
(0, _react.useEffect)(function () {
if (state.error) {
handleOnInvalid();
}
}, [handleOnInvalid, state.error, state.inputValue, state.validationType]);
return /*#__PURE__*/_react["default"].createElement("div", {
className: (0, _TimeInputSt.st)(_TimeInputSt.classes.root, className),
style: {
width: width
},
"data-hook": dataHook,
"data-value": state.selectedId || valueAsDate,
"data-locale": locale,
"data-time-style": timeStyle,
"data-autofill": autofillValue,
"data-scroll-to-option": state.scrollToOption,
"data-status-message": statusMessage,
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 494,
columnNumber: 7
}
}, /*#__PURE__*/_react["default"].createElement(_DropdownBase["default"], (0, _extends2["default"])({
dataHook: _constants.DATA_HOOK.TimeInputDropdown,
open: state.isDropdownOpen,
onClickOutside: function onClickOutside() {
return dispatch({
type: _constants.ACTION.CLOSE_DROPDOWN
});
},
options: timeSlots,
onSelect: validateAndSetOption,
selectedId: state.selectedId,
maxHeight: "216px",
markedOptionId: state.highlightedOptionId,
focusOnOption: state.highlightedOptionId,
focusOnSelectedOption: true,
scrollToOption: state.scrollToOption,
onMouseDown: function onMouseDown(e) {
return e.preventDefault();
},
autoFocus: false,
dynamicWidth: true
}, popoverProps, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 505,
columnNumber: 9
}
}), function (_ref3) {
var isOpen = _ref3.isOpen,
activeDescendantId = _ref3.activeDescendantId,
listboxId = _ref3.listboxId,
delegateKeyDown = _ref3.delegateKeyDown;
return /*#__PURE__*/_react["default"].createElement(_Input["default"], {
dataHook: _constants.DATA_HOOK.TimeInputInput,
size: size,
status: showError ? 'error' : status,
statusMessage: resolvedStatusMessage,
suffix: suffix && /*#__PURE__*/_react["default"].createElement(_Input["default"].Affix, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 529,
columnNumber: 35
}
}, suffix),
prefix: prefix && /*#__PURE__*/_react["default"].createElement(_Input["default"].Affix, {
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 530,
columnNumber: 35
}
}, prefix),
border: border,
disabled: disabled,
placeholder: placeholder,
value: state.inputValue,
onChange: onInputChange,
onInputClicked: openDropdown,
onKeyDown: function onKeyDown(e) {
return _onKeyDown(e, delegateKeyDown);
},
ref: inputRef,
readOnly: readOnly,
autoSelect: autoSelect,
noLeftBorderRadius: noLeftBorderRadius,
noRightBorderRadius: noRightBorderRadius,
onFocus: onFocus,
onBlur: onInputBlur,
disableEditing: disableKeyboardType,
hideStatusSuffix: hideStatusSuffix,
ariaAutocomplete: "list",
ariaExpanded: isOpen,
ariaControls: isOpen ? listboxId : undefined,
ariaActiveDescendant: isOpen ? activeDescendantId : undefined,
inputRef: externalInputRef,
customInput: customInput,
__self: _this,
__source: {
fileName: _jsxFileName,
lineNumber: 524,
columnNumber: 15
}
});
}));
});
TimeInput.displayName = 'TimeInput';
var _default = exports["default"] = TimeInput;