UNPKG

@wix/design-system

Version:

@wix/design-system

525 lines (518 loc) 20.2 kB
"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;