UNPKG

@vtex/admin-ui

Version:

> VTEX admin component library

1,799 lines (1,629 loc) 360 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var adminUiCore = require('@vtex/admin-ui-core'); var adminUiReact = require('@vtex/admin-ui-react'); var adminUiHooks = require('@vtex/admin-ui-hooks'); var adminUiUtil = require('@vtex/admin-ui-util'); var React = require('react'); var React__default = _interopDefault(React); var Role = require('reakit/Role'); var Popover = require('reakit/Popover'); var Id = require('reakit/Id'); var phosphorIcons = require('@vtex/phosphor-icons'); var Clickable = require('reakit/Clickable'); var i18n = require('@react-aria/i18n'); var dateFns = require('date-fns'); var invariant = _interopDefault(require('tiny-invariant')); var Composite = require('reakit/Composite'); var spinbutton = require('@react-aria/spinbutton'); var utils = require('@react-aria/utils'); var Checkbox$1 = require('reakit/Checkbox'); var Button$1 = require('reakit/Button'); var reakit = require('reakit'); var VisuallyHidden = require('reakit/VisuallyHidden'); var listbox = require('@react-aria/listbox'); var collections = require('@react-stately/collections'); var list$1 = require('@react-stately/list'); var combobox = require('ariakit/combobox'); var checkbox = require('ariakit/checkbox'); var composite = require('ariakit/composite'); var focusable = require('ariakit/focusable'); var Menu$3 = require('reakit/Menu'); var useCollapse = _interopDefault(require('react-collapsed')); var reactIs = require('react-is'); var Separator = require('reakit/Separator'); var Tooltip$1 = require('reakit/Tooltip'); var Radio$1 = require('reakit/Radio'); var Dialog = require('reakit/Dialog'); var downshift = require('downshift'); var Input$2 = require('reakit/Input'); var Tab$1 = require('reakit/Tab'); var Tabbable = require('reakit/Tabbable'); var Portal = require('reakit/Portal'); var Toolbar$1 = require('reakit/Toolbar'); var reactDeviceDetect = require('react-device-detect'); var useDebounce = require('use-debounce'); var warning = _interopDefault(require('tiny-warning')); function _extends() { _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; }; return _extends.apply(this, arguments); } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _taggedTemplateLiteralLoose(strings, raw) { if (!raw) { raw = strings.slice(0); } strings.raw = raw; return strings; } var centerStyle = /*#__PURE__*/adminUiCore.style({ display: 'flex', justifyContent: 'center', alignItems: 'center' }); /** * Layout that aligns its children on the center * @example * import { Center } from `@vtex/admin-ui` * <Center>Centralized content</Center> */ var Center = /*#__PURE__*/adminUiReact.createComponent(function (props) { return adminUiReact.useElement('div', _extends({}, props, { baseStyle: centerStyle })); }); Center.displayName = 'Center'; var Picker = /*#__PURE__*/adminUiReact.createComponent(function (props) { var _props$state = props.state, visible = _props$state.visible, isDisabled = _props$state.isDisabled, isReadOnly = _props$state.isReadOnly, show = _props$state.show, pickerId = _props$state.pickerId, popoverId = _props$state.popoverId, segmentFocus = _props$state.segmentFocus, htmlOnKeyDown = props.onKeyDown, htmlOnClick = props.onClick, htmlOnMouseDown = props.onMouseDown, htmlProps = _objectWithoutPropertiesLoose(props, ["state", "onKeyDown", "onClick", "onMouseDown"]); var onClick = React.useCallback(function () { if (adminUiUtil.isTouch()) show(); }, [show]); var onKeyDown = adminUiHooks.useOnKeyDown({ onKey: htmlOnKeyDown, keyMap: function keyMap(event) { var isAlt = event.altKey; return { // Open the popover on alt + arrow down ArrowDown: function ArrowDown() { if (isAlt) show(); } }; } }); var onMouseDown = React.useCallback(function (e) { e.stopPropagation(); segmentFocus === null || segmentFocus === void 0 ? void 0 : segmentFocus(); }, [segmentFocus]); return adminUiReact.useElement(Role.Role, _extends({ id: pickerId, role: 'button', 'aria-haspopup': 'dialog', 'aria-expanded': visible, 'aria-owns': visible ? popoverId : undefined, 'aria-disabled': adminUiUtil.ariaAttr(isDisabled), 'aria-readonly': adminUiUtil.ariaAttr(isReadOnly), onKeyDown: adminUiUtil.callAllHandlers(htmlOnKeyDown, onKeyDown), onClick: adminUiUtil.callAllHandlers(htmlOnClick, onClick), onMouseDown: adminUiUtil.callAllHandlers(htmlOnMouseDown, onMouseDown) }, htmlProps)); }); var popoverStyle = /*#__PURE__*/adminUiCore.style({ bg: '$primary', boxShadow: '$overlay.center', border: '$neutral', borderRadius: '$default' }); var PickerPopover = /*#__PURE__*/adminUiReact.createComponent(function (props) { var state = props.state, popoverProps = _objectWithoutPropertiesLoose(props, ["state"]); return adminUiReact.useElement(Popover.Popover, _extends({ id: state.popoverId, state: state, baseStyle: popoverStyle }, popoverProps)); }); var PickerDisclosure = /*#__PURE__*/adminUiReact.createComponent(function (props) { var state = props.state, htmlOnMouseDown = props.onMouseDown, htmlProps = _objectWithoutPropertiesLoose(props, ["state", "onMouseDown"]); var onMouseDown = function onMouseDown(e) { e.stopPropagation(); }; return adminUiReact.useElement(Popover.PopoverDisclosure, _extends({ state: state, tabIndex: -1, disabled: state.isDisabled || state.isReadOnly, onMouseDown: adminUiUtil.callAllHandlers(htmlOnMouseDown, onMouseDown) }, htmlProps)); }); function usePickerState(props) { if (props === void 0) { props = {}; } var _props = props, pickerIdProp = _props.pickerId, popoverIdProp = _props.popoverId, isDisabled = _props.isDisabled, isReadOnly = _props.isReadOnly, segmentFocus = _props.segmentFocus; var _useId = Id.unstable_useId({ id: pickerIdProp, baseId: 'picker' }), pickerId = _useId.id; var _useId2 = Id.unstable_useId({ id: popoverIdProp, baseId: 'popover' }), popoverId = _useId2.id; var popover = Popover.usePopoverState(_extends({ modal: true, gutter: 4 }, props)); return _extends({ pickerId: pickerId, popoverId: popoverId, isDisabled: isDisabled, isReadOnly: isReadOnly, segmentFocus: segmentFocus }, popover); } function action(options) { var tone = options.tone, variant = options.variant; return adminUiCore.style(_extends({ color: "action." + tone + "." + variant, bg: "action." + tone + "." + variant, ':hover': { color: "action." + tone + "." + variant + "Hover", bg: "action." + tone + "." + variant + "Hover" }, ':active': { color: "action." + tone + "." + variant + "Pressed", bg: "action." + tone + "." + variant + "Pressed" }, ':disabled': { bg: variant === 'tertiary' ? 'transparent' : '$disabled', color: '$disabled' } }, adminUiCore.focusVisible(tone))); } var buttonStyle = /*#__PURE__*/adminUiCore.style({ text: '$action1', border: 'none', borderRadius: 'default', cursor: 'pointer', position: 'relative' }); var bleedY = /*#__PURE__*/adminUiCore.styleVariants({ size: { normal: { marginY: '$-l' }, large: { marginY: '$-xl' } } }); var bleedX = /*#__PURE__*/adminUiCore.styleVariants({ size: { normal: { marginX: '$-l' }, large: { marginX: '$-xl' } } }); var variants = /*#__PURE__*/adminUiCore.styleVariants({ variant: { primary: /*#__PURE__*/action({ tone: 'main', variant: 'primary' }), secondary: /*#__PURE__*/action({ tone: 'main', variant: 'secondary' }), tertiary: /*#__PURE__*/action({ tone: 'main', variant: 'tertiary' }), critical: /*#__PURE__*/action({ tone: 'critical', variant: 'primary' }), criticalSecondary: /*#__PURE__*/action({ tone: 'critical', variant: 'secondary' }), criticalTertiary: /*#__PURE__*/action({ tone: 'critical', variant: 'tertiary' }), neutralTertiary: /*#__PURE__*/action({ tone: 'neutral', variant: 'tertiary' }) }, size: { normal: { padding: '$s', height: '2.25rem' }, large: { padding: '$m', height: '2.75rem' } } }); var innerContainerStyle = /*#__PURE__*/adminUiCore.style({ text: '$action1' }); var innerContainerVariants = /*#__PURE__*/adminUiCore.styleVariants({ loading: { "true": { visibility: 'hidden' }, "false": { visibility: 'visible' } }, iconPosition: { start: { flexDirection: 'row', svg: { marginRight: '$s' } }, end: { flexDirection: 'row-reverse', svg: { marginLeft: '$xs' } } } }); var spinnerContainerStyle = /*#__PURE__*/adminUiCore.style({ text: '$action1', position: 'absolute', bottom: 0, top: 0, left: 0, right: 0, svg: { size: '1.3rem' } }); var calendar = /*#__PURE__*/adminUiCore.style({ maxWidth: '19.75rem', display: 'flex', flexDirection: 'column', padding: '$l', '[aria-disabled="true"]': { color: '$disabled', bg: 'transparent' }, '[aria-selected] > button': { bg: '$action.main.primary', color: '$action.main.primary' } }); var calendarHeader = /*#__PURE__*/adminUiCore.style({ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%', marginBottom: '$xl' }); var calendarButton = /*#__PURE__*/adminUiCore.style( /*#__PURE__*/_extends({}, buttonStyle, /*#__PURE__*/variants({ size: 'normal', variant: 'neutralTertiary' }), { display: 'flex', alignItems: 'center', justifyContent: 'center' })); var calendarCell = /*#__PURE__*/adminUiCore.style({ size: '2.25rem' }); var calendarCellButton = /*#__PURE__*/adminUiCore.style( /*#__PURE__*/_extends({}, buttonStyle, /*#__PURE__*/variants({ size: 'normal', variant: 'neutralTertiary' }), { padding: 0, marginBottom: '$s', text: '$action1', border: 'none', cursor: 'pointer', size: '2.25rem', borderRadius: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' })); var calendarHeaderTitle = /*#__PURE__*/adminUiCore.style({ text: '$title1' }); var calendarDayTitle = /*#__PURE__*/adminUiCore.style({ text: '$body', textDecoration: 'none', color: '$secondary', paddingY: 2, textAlign: 'center', size: '2.25rem' }); var CalendarHeaderButton = /*#__PURE__*/adminUiReact.createComponent(function (props) { var handler = props.handler, _props$state = props.state, focusNextMonth = _props$state.focusNextMonth, focusPreviousMonth = _props$state.focusPreviousMonth, focusPreviousYear = _props$state.focusPreviousYear, focusNextYear = _props$state.focusNextYear, htmlOnClick = props.onClick, htmlProps = _objectWithoutPropertiesLoose(props, ["handler", "state", "onClick"]); var currentHandler = React.useMemo(function () { return { nextMonth: { handle: focusNextMonth, ariaLabel: 'Next Month' }, previousMonth: { handle: focusPreviousMonth, ariaLabel: 'Previous Month' }, nextYear: { handle: focusNextYear, ariaLabel: 'Next Year' }, previousYear: { handle: focusPreviousYear, ariaLabel: 'Previous Year' } }[handler]; }, [focusNextMonth, focusPreviousMonth, focusNextYear, focusPreviousYear]); return adminUiReact.useElement(Clickable.Clickable, _extends({ baseStyle: calendarButton, 'aria-label': currentHandler === null || currentHandler === void 0 ? void 0 : currentHandler.ariaLabel, onClick: adminUiUtil.callAllHandlers(htmlOnClick, currentHandler === null || currentHandler === void 0 ? void 0 : currentHandler.handle) }, htmlProps)); }); var CalendarGrid = /*#__PURE__*/adminUiReact.createComponent(function (props) { var _props$state = props.state, isReadOnly = _props$state.isReadOnly, isDisabled = _props$state.isDisabled, setFocused = _props$state.setFocused, selectFocusedDate = _props$state.selectFocusedDate, focusPreviousYear = _props$state.focusPreviousYear, focusPreviousMonth = _props$state.focusPreviousMonth, focusNextYear = _props$state.focusNextYear, focusNextMonth = _props$state.focusNextMonth, focusEndOfMonth = _props$state.focusEndOfMonth, focusStartOfMonth = _props$state.focusStartOfMonth, focusNextDay = _props$state.focusNextDay, focusPreviousDay = _props$state.focusPreviousDay, focusNextWeek = _props$state.focusNextWeek, focusPreviousWeek = _props$state.focusPreviousWeek, calendarId = _props$state.calendarId, htmlOnKeyDown = props.onKeyDown, htmlOnFocus = props.onBlur, htmlOnBlur = props.onBlur, htmlProps = _objectWithoutPropertiesLoose(props, ["state", "onKeyDown", "onBlur", "onBlur"]); var onKeyDown = adminUiHooks.useOnKeyDown({ onKeyDown: htmlOnKeyDown, keyMap: function keyMap(event) { var shift = event.shiftKey; return { ' ': selectFocusedDate, Enter: selectFocusedDate, End: focusEndOfMonth, Home: focusStartOfMonth, ArrowLeft: focusPreviousDay, ArrowUp: focusPreviousWeek, ArrowRight: focusNextDay, ArrowDown: focusNextWeek, PageUp: function PageUp() { shift ? focusPreviousYear() : focusPreviousMonth(); }, PageDown: function PageDown() { shift ? focusNextYear() : focusNextMonth(); } }; } }); return adminUiReact.useElement(Role.Role, _extends({ role: 'grid', 'aria-labelledby': calendarId, 'aria-readonly': adminUiUtil.ariaAttr(isReadOnly), 'aria-disabled': adminUiUtil.ariaAttr(isDisabled), onKeyDown: adminUiUtil.callAllHandlers(htmlOnKeyDown, onKeyDown), onFocus: adminUiUtil.callAllHandlers(htmlOnFocus, function () { return setFocused(true); }), onBlur: adminUiUtil.callAllHandlers(htmlOnBlur, function () { return setFocused(false); }) }, htmlProps)); }); /** * Returns the region from the locale */ function useRegion() { var _useLocale = i18n.useLocale(), locale = _useLocale.locale; // If the Intl.Locale API is available, use it to get the region for the locale. if (Intl.Locale) { return new Intl.Locale(locale).maximize().region; } // If not, just try splitting the string. return locale.split('-')[1]; } // Data from https://github.com/unicode-cldr/cldr-core/blob/master/supplemental/weekData.json var weekData = { '001': 1, AD: 1, AE: 6, AF: 6, AI: 1, AL: 1, AM: 1, AN: 1, AT: 1, AX: 1, AZ: 1, BA: 1, BE: 1, BG: 1, BH: 6, BM: 1, BN: 1, BY: 1, CH: 1, CL: 1, CM: 1, CR: 1, CY: 1, CZ: 1, DE: 1, DJ: 6, DK: 1, DZ: 6, EC: 1, EE: 1, EG: 6, ES: 1, FI: 1, FJ: 1, FO: 1, FR: 1, GB: 1, GE: 1, GF: 1, GP: 1, GR: 1, HR: 1, HU: 1, IE: 1, IQ: 6, IR: 6, IS: 1, IT: 1, JO: 6, KG: 1, KW: 6, KZ: 1, LB: 1, LI: 1, LK: 1, LT: 1, LU: 1, LV: 1, LY: 6, MC: 1, MD: 1, ME: 1, MK: 1, MN: 1, MQ: 1, MV: 5, MY: 1, NL: 1, NO: 1, NZ: 1, OM: 6, PL: 1, QA: 6, RE: 1, RO: 1, RS: 1, RU: 1, SD: 6, SE: 1, SI: 1, SK: 1, SM: 1, SY: 6, TJ: 1, TM: 1, TR: 1, UA: 1, UY: 1, UZ: 1, VA: 1, VN: 1, XK: 1 }; /** * Returns the day that the week start on the current region */ function useWeekStart() { var region = useRegion(); return weekData[region] || 0; } var CalendarHeaderTitle = /*#__PURE__*/adminUiReact.createComponent(function (props) { var _props$format = props.format, format = _props$format === void 0 ? { month: 'long', year: 'numeric' } : _props$format, _props$state = props.state, calendarId = _props$state.calendarId, currentMonth = _props$state.currentMonth, htmlProps = _objectWithoutPropertiesLoose(props, ["format", "state"]); return adminUiReact.useElement('h2', _extends({ id: calendarId, 'aria-live': 'polite', children: i18n.useDateFormatter(format).format(currentMonth !== null && currentMonth !== void 0 ? currentMonth : new Date()), baseStyle: calendarHeaderTitle }, htmlProps)); }); var CalendarDayTitle = /*#__PURE__*/adminUiReact.createComponent(function (props) { var _weekDays$dayIndex; var weekDays = props.state.weekDays, dayIndex = props.dayIndex, htmlProps = _objectWithoutPropertiesLoose(props, ["state", "dayIndex"]); return adminUiReact.useElement(Role.Role, _extends({ baseStyle: calendarDayTitle, 'aria-label': weekDays === null || weekDays === void 0 ? void 0 : (_weekDays$dayIndex = weekDays[dayIndex]) === null || _weekDays$dayIndex === void 0 ? void 0 : _weekDays$dayIndex.title }, htmlProps)); }); var CalendarHeader = /*#__PURE__*/adminUiReact.createComponent(function (props) { return adminUiReact.useElement('header', _extends({ baseStyle: calendarHeader }, props)); }); var CalendarCell = /*#__PURE__*/adminUiReact.createComponent(function (props) { var date = props.date, dateValue = props.state.dateValue, htmlProps = _objectWithoutPropertiesLoose(props, ["date", "state"]); var isSelected = dateValue ? dateFns.isSameDay(date, dateValue) : false; var customDataAttr = { 'data-weekend': adminUiUtil.dataAttr(dateFns.isWeekend(date)) }; return adminUiReact.useElement(Role.Role, _extends({ baseStyle: calendarCell, role: 'gridcell', 'aria-selected': adminUiUtil.ariaAttr(isSelected) }, customDataAttr, htmlProps)); }); var CalendarCellButton = /*#__PURE__*/adminUiReact.createComponent(function (props) { var date = props.date, _props$state = props.state, isDisabledOption = _props$state.isDisabled, month = _props$state.month, isInvalidDateRange = _props$state.isInvalidDateRange, dateValue = _props$state.dateValue, focusedDate = _props$state.focusedDate, isFocusedOption = _props$state.isFocused, selectDate = _props$state.selectDate, setFocusedDate = _props$state.setFocusedDate, htmlDisabled = props.disabled, htmlOnClick = props.onClick, htmlOnFocus = props.onFocus, htmlRef = props.ref, htmlProps = _objectWithoutPropertiesLoose(props, ["date", "state", "disabled", "onClick", "onFocus", "ref"]); var ref = React.useRef(null); var isCurrentMonth = date.getMonth() === month; var isDisabled = isDisabledOption || !isCurrentMonth || isInvalidDateRange(date); var disabled = htmlDisabled || isDisabled; var isSelected = dateValue ? dateFns.isSameDay(date, dateValue) : false; var isFocused = isFocusedOption && focusedDate && dateFns.isSameDay(date, focusedDate); var isToday = dateFns.isSameDay(date, new Date()); // Focus the button in the DOM when the state updates. React.useEffect(function () { if (isFocused && ref.current) { adminUiUtil.ensureFocus(ref.current); } }, [date, focusedDate, isFocused, ref]); var onClick = React.useCallback(function () { if (disabled) return; selectDate(date); setFocusedDate(date); }, [date, disabled, selectDate, setFocusedDate]); var onFocus = React.useCallback(function () { if (disabled) return; setFocusedDate(date); }, [date, disabled, setFocusedDate]); var dateFormatter = i18n.useDateFormatter({ weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }); // aria-label should be localize Day of week, Month, Day and Year without Time. function getAriaLabel() { var dateLabel = dateFormatter.format(date); var isTodayLabel = isToday ? 'Today, ' : ''; var isSelectedLabel = isSelected ? ' selected' : ''; return "" + isTodayLabel + dateLabel + isSelectedLabel; } return adminUiReact.useElement(Clickable.Clickable, _extends({ baseStyle: calendarCellButton, ref: adminUiHooks.useForkRef(ref, htmlRef), children: i18n.useDateFormatter({ day: 'numeric' }).format(date), 'aria-label': getAriaLabel(), disabled: disabled, tabIndex: !disabled ? dateFns.isSameDay(date, focusedDate !== null && focusedDate !== void 0 ? focusedDate : new Date()) ? 0 : -1 : undefined, onClick: adminUiUtil.callAllHandlers(htmlOnClick, onClick), onFocus: adminUiUtil.callAllHandlers(htmlOnFocus, onFocus) }, htmlProps)); }); /** * Abbreviation component * @example * <Abbr title="Long Version">lv</Abbr> */ var Abbr = /*#__PURE__*/adminUiReact.createComponent(function (props) { return adminUiReact.useElement('abbr', _extends({ baseStyle: { textDecoration: 'none', text: '$body' } }, props)); }); var Calendar = /*#__PURE__*/adminUiReact.createComponent(function (props) { var _state$weekDays, _state$daysInMonth; var state = props.state, htmlProps = _objectWithoutPropertiesLoose(props, ["state"]); return adminUiReact.useElement(Role.Role, _extends({ baseStyle: calendar, role: 'group', 'aria-labelledby': state.calendarId, children: React__default.createElement(React__default.Fragment, null, React__default.createElement(CalendarHeader, null, React__default.createElement(CalendarHeaderButton, { state: state, handler: "previousMonth" }, React__default.createElement(phosphorIcons.IconCaretLeft, null)), React__default.createElement(CalendarHeaderTitle, { state: state }), React__default.createElement(CalendarHeaderButton, { state: state, handler: "nextMonth" }, React__default.createElement(phosphorIcons.IconCaretRight, null))), React__default.createElement(CalendarGrid, { state: state, as: "table" }, React__default.createElement("thead", null, React__default.createElement("tr", null, state === null || state === void 0 ? void 0 : (_state$weekDays = state.weekDays) === null || _state$weekDays === void 0 ? void 0 : _state$weekDays.map(function (day, dayIndex) { return React__default.createElement(CalendarDayTitle, { as: "th", scope: "col", key: dayIndex, dayIndex: dayIndex, state: state }, React__default.createElement(Abbr, { title: day.title }, day.abbr)); }))), React__default.createElement("tbody", null, state === null || state === void 0 ? void 0 : (_state$daysInMonth = state.daysInMonth) === null || _state$daysInMonth === void 0 ? void 0 : _state$daysInMonth.map(function (week, weekIndex) { return React__default.createElement("tr", { key: weekIndex }, week.map(function (date, index) { return React__default.createElement(CalendarCell, { state: state, date: date, as: "td", key: index }, React__default.createElement(CalendarCellButton, { state: state, date: date })); })); })))) }, htmlProps)); }); function useWeekDays(weekStart) { var dayFormatter = i18n.useDateFormatter({ weekday: 'narrow' }); var dayFormatterLong = i18n.useDateFormatter({ weekday: 'long' }); return [0, 1, 2, 3, 4, 5, 6].map(function (index) { var dateDay = dateFns.setDay(Date.now(), (index + weekStart) % 7); var day = dayFormatter.format(dateDay); var dayLong = dayFormatterLong.format(dateDay); return { title: dayLong, abbr: day }; }); } function createDate(date) { if (!date) { return new Date(); } var year = date.year, month = date.month, day = date.day; !(year >= 0) ? invariant(false, 'The year must be greater then 0') : void 0; !(month >= 0 && month <= 11) ? invariant(false, 'The month must be between 0 and 11') : void 0; !(day >= 1 && day <= 31) ? invariant(false, 'The day must be between 1 and 31') : void 0; return new Date(year, month, day); } function getDateObject(date) { var dateToParse = date !== null && date !== void 0 ? date : new Date(); return { year: dateFns.getYear(dateToParse), month: dateFns.getMonth(dateToParse), day: dateFns.getDate(dateToParse) }; } function toUTCString(date) { return date.toISOString().slice(0, 10); } function generateDaysInMonthArray(month, monthStartsAt, weeksInMonth, year) { return Array(weeksInMonth).fill(1).reduce(function (weeks, _, weekIndex) { var daysInWeek = [0, 1, 2, 3, 4, 5, 6].reduce(function (days, dayIndex) { var day = weekIndex * 7 + dayIndex - monthStartsAt + 2; var utcDate = toUTCString(new Date(year, month, day)); var cellDate = new Date(utcDate); return [].concat(days, [cellDate]); }, []); return [].concat(weeks, [daysInWeek]); }, []); } function useCalendarState(props) { if (props === void 0) { props = {}; } var _props = props, initialValue = _props.value, _props$defaultValue = _props.defaultValue, defaultValue = _props$defaultValue === void 0 ? getDateObject() : _props$defaultValue, onChange = _props.onChange, _props$minValue = _props.minValue, minValue = _props$minValue === void 0 ? { year: 1, month: 0, day: 1 } : _props$minValue, _props$maxValue = _props.maxValue, maxValue = _props$maxValue === void 0 ? { year: 8000, month: 11, day: 31 } : _props$maxValue, _props$isDisabled = _props.isDisabled, isDisabled = _props$isDisabled === void 0 ? false : _props$isDisabled, _props$isReadOnly = _props.isReadOnly, isReadOnly = _props$isReadOnly === void 0 ? false : _props$isReadOnly, _props$autoFocus = _props.autoFocus, autoFocus = _props$autoFocus === void 0 ? false : _props$autoFocus; var _useControllableState = adminUiHooks.useControllableState({ value: initialValue, defaultValue: defaultValue, onChange: onChange }), value = _useControllableState[0], setValue = _useControllableState[1]; var date = React.useMemo(function () { return createDate(value); }, [value]); var minDate = React.useMemo(function () { return createDate(minValue); }, [minValue]); var maxDate = React.useMemo(function () { return createDate(maxValue); }, [maxValue]); var _useState = React.useState(date), currentMonth = _useState[0], setCurrentMonth = _useState[1]; var _useState2 = React.useState(date), focusedDate = _useState2[0], setFocusedDate = _useState2[1]; var _useState3 = React.useState(autoFocus), isFocused = _useState3[0], setFocused = _useState3[1]; var month = currentMonth.getMonth(); var year = currentMonth.getFullYear(); var weekStart = useWeekStart(); var weekDays = useWeekDays(weekStart); // Get 2D Date arrays in 7 days a week format var daysInMonth = React.useMemo(function () { var monthStartsAt = (dateFns.startOfMonth(currentMonth).getDay() - weekStart) % 7; if (monthStartsAt < 0) { monthStartsAt += 7; } var days = dateFns.getDaysInMonth(currentMonth); var weeksInMonth = Math.ceil((monthStartsAt + days) / 7); return generateDaysInMonthArray(month, monthStartsAt, weeksInMonth, year); }, [month, year, currentMonth, weekStart]); var isInvalidDateRange = React.useCallback(function (value) { return value < minDate || value > maxDate; }, [minDate, maxDate]); var focusCell = React.useCallback(function (date) { if (isInvalidDateRange(date)) return; if (!dateFns.isSameMonth(date, currentMonth)) { setCurrentMonth(dateFns.startOfMonth(date)); } setFocusedDate(date); }, [isInvalidDateRange, currentMonth]); var setDate = React.useCallback(function (value) { if (!isDisabled && !isReadOnly) { setValue(getDateObject(value)); } }, [isDisabled, isReadOnly, setValue]); var _useId = Id.unstable_useId({ id: props.id, baseId: 'calendar' }), calendarId = _useId.id; return { dateValue: date, setDateValue: setDate, minDateValue: minDate, maxDateValue: maxDate, calendarId: calendarId, month: month, year: year, weekStart: weekStart, weekDays: weekDays, daysInMonth: daysInMonth, isDisabled: isDisabled, isFocused: isFocused, isReadOnly: isReadOnly, setFocused: setFocused, currentMonth: currentMonth, setCurrentMonth: setCurrentMonth, focusedDate: focusedDate, focusCell: focusCell, setFocusedDate: setFocusedDate, focusNextDay: function focusNextDay() { focusCell(dateFns.addDays(focusedDate, 1)); }, focusPreviousDay: function focusPreviousDay() { focusCell(dateFns.subDays(focusedDate, 1)); }, focusNextWeek: function focusNextWeek() { focusCell(dateFns.addWeeks(focusedDate, 1)); }, focusPreviousWeek: function focusPreviousWeek() { focusCell(dateFns.subWeeks(focusedDate, 1)); }, focusNextMonth: function focusNextMonth() { focusCell(dateFns.addMonths(focusedDate, 1)); }, focusPreviousMonth: function focusPreviousMonth() { focusCell(dateFns.subMonths(focusedDate, 1)); }, focusStartOfMonth: function focusStartOfMonth() { focusCell(dateFns.startOfMonth(focusedDate)); }, focusEndOfMonth: function focusEndOfMonth() { focusCell(dateFns.endOfMonth(dateFns.startOfDay(focusedDate))); }, focusNextYear: function focusNextYear() { focusCell(dateFns.addYears(focusedDate, 1)); }, focusPreviousYear: function focusPreviousYear() { focusCell(dateFns.subYears(focusedDate, 1)); }, selectFocusedDate: function selectFocusedDate() { setDate(focusedDate); }, selectDate: function selectDate(date) { setDate(date); }, isInvalidDateRange: isInvalidDateRange }; } var DatePickerCalendar = /*#__PURE__*/React.forwardRef(function (props, ref) { var _props$state = props.state, pickerState = _props$state.pickerState, calendarState = _props$state.calendarState, _props$csx = props.csx, csx = _props$csx === void 0 ? {} : _props$csx; return React__default.createElement(PickerPopover, { csx: csx, ref: ref, state: pickerState }, React__default.createElement(Calendar, { state: calendarState })); }); DatePickerCalendar.displayName = 'DatePickerCalendar'; var Text = /*#__PURE__*/Object.assign( /*#__PURE__*/adminUiReact.jsx('span')({ variants: { variant: { pageTitle: { text: '$pageTitle' }, title1: { text: '$title1' }, title2: { text: '$title2' }, action1: { text: '$action1' }, action2: { text: '$action2' }, display: { text: '$display' }, body: { text: '$body' }, detail: { text: '$detail' } }, tone: { primary: { color: '$primary' }, secondary: { color: '$secondary' }, info: { color: '$info' }, positive: { color: '$positive' }, critical: { color: '$critical' }, warning: { color: '$warning' } } } }), { displayName: "Text" }); Text.defaultProps = { tone: 'primary', variant: 'body' }; /** * Form label component. * It renders a label jsx element by default * @example * <Label>label</Label> */ var Label = /*#__PURE__*/Object.assign( /*#__PURE__*/adminUiReact.jsx('label')({ text: '$body' }), { displayName: "Label" }); var Flex = /*#__PURE__*/Object.assign( /*#__PURE__*/adminUiReact.jsx('div')({ display: 'flex' }, { options: ['align', 'basis', 'grow', 'direction', 'shrink', 'justify', 'wrap', 'order'], useOptions: function useOptions(options, props) { var propertyMap = { basis: 'flexBasis', direction: 'flexDirection', wrap: 'flexWrap', align: 'alignItems', justify: 'justifyContent', grow: 'flexGrow', shrink: 'flexShrink', order: 'order' }; var csx = props.csx, htmlProps = _objectWithoutPropertiesLoose(props, ["csx"]); var cssProps = Object.keys(propertyMap); var cssPropsStyle = adminUiUtil.renameKeys(propertyMap, adminUiUtil.pick(options, cssProps)); return _extends({}, htmlProps, { csx: _extends({}, cssPropsStyle, csx) }); } }), { displayName: "Flex" }); var FlexSpacer = /*#__PURE__*/Object.assign( /*#__PURE__*/adminUiReact.jsx('div')({ flex: 1, justifySelf: 'stretch', alignSelf: 'stretch' }), { displayName: "FlexSpacer" }); var dateField = /*#__PURE__*/adminUiCore.style({ display: 'flex', justifyContent: 'space-between', alignContent: 'center', padding: '$s', height: 52, width: 288, borderRadius: 4 }); var variants$1 = /*#__PURE__*/adminUiCore.styleVariants({ tone: { critical: { border: '$form.critical' }, neutral: { border: '$form.neutral' } }, disabled: { "true": { border: '$disabled' } } }); var label = /*#__PURE__*/adminUiCore.style({ text: '$detail', color: '$secondary' }); function getSegmentLimits(date, type, options) { switch (type) { case 'day': return { value: dateFns.getDate(date), minValue: 1, maxValue: dateFns.getDaysInMonth(date) }; case 'dayPeriod': return { value: dateFns.getHours(date) >= 12 ? 12 : 0, minValue: 0, maxValue: 12 }; case 'hour': { var value = dateFns.getHours(date); if (options.hour12) { var isPM = value >= 12; return { value: value, minValue: isPM ? 12 : 0, maxValue: isPM ? 23 : 11 }; } return { value: value, minValue: 0, maxValue: 23 }; } case 'minute': return { value: dateFns.getMinutes(date), minValue: 0, maxValue: 59 }; case 'second': return { value: dateFns.getSeconds(date), minValue: 0, maxValue: 59 }; case 'month': return { value: dateFns.getMonth(date) + 1, minValue: 1, maxValue: 12 }; case 'year': return { value: dateFns.getYear(date), minValue: 1, maxValue: 9999 }; default: return {}; } } function add(value, part, amount, options) { switch (part) { case 'day': { var day = dateFns.getDate(value); return dateFns.setDate(value, cycleValue(day, amount, 1, dateFns.getDaysInMonth(value))); } case 'dayPeriod': { var hours = dateFns.getHours(value); var isPM = hours >= 12; return dateFns.setHours(value, isPM ? hours - 12 : hours + 12); } case 'hour': { var _hours = dateFns.getHours(value); var min = 0; var max = 23; if (options.hour12) { var _isPM = _hours >= 12; min = _isPM ? 12 : 0; max = _isPM ? 23 : 11; } _hours = cycleValue(_hours, amount, min, max); return dateFns.setHours(value, _hours); } case 'minute': { var minutes = cycleValue(dateFns.getMinutes(value), amount, 0, 59, true); return dateFns.setMinutes(value, minutes); } case 'month': { var months = cycleValue(dateFns.getMonth(value), amount, 0, 11); return dateFns.setMonth(value, months); } case 'second': { var seconds = cycleValue(dateFns.getSeconds(value), amount, 0, 59, true); return dateFns.setSeconds(value, seconds); } case 'year': { var year = cycleValue(dateFns.getYear(value), amount, 1, 9999, true); return dateFns.setYear(value, year); } default: { console.warn('add: Out of bounds'); return new Date(); } } } function cycleValue(value, amount, min, max, round) { if (round === void 0) { round = false; } if (round) { value += amount > 0 ? 1 : -1; if (value < min) { value = max; } var div = Math.abs(amount); if (amount > 0) { value = Math.ceil(value / div) * div; } else { value = Math.floor(value / div) * div; } if (value > max) { value = min; } } else { value += amount; if (value < min) { value = max - (min - value - 1); } else if (value > max) { value = min + (value - max - 1); } } return value; } function setSegment(value, part, segmentValue, options) { switch (part) { case 'day': return dateFns.setDay(value, segmentValue); case 'dayPeriod': { var hours = dateFns.getHours(value); var wasPM = hours >= 12; var isPM = segmentValue >= 12; if (isPM === wasPM) { return value; } return dateFns.setHours(value, wasPM ? hours - 12 : Number(hours) + 12); } case 'hour': // In 12 hour time, ensure that AM/PM does not change if (options.hour12) { var _hours2 = dateFns.getHours(value); var _wasPM = _hours2 >= 12; if (!_wasPM && segmentValue === 12) { segmentValue = 0; } if (_wasPM && segmentValue < 12) { segmentValue += 12; } } return dateFns.setHours(value, segmentValue); case 'minute': return dateFns.setMinutes(value, segmentValue); case 'month': return dateFns.setMonth(value, segmentValue - 1); case 'second': return dateFns.setSeconds(value, segmentValue); case 'year': return dateFns.setYear(value, segmentValue); default: { console.warn('setSegment: Out of bounds'); return new Date(); } } } /** * Converts unicode number strings to real JS numbers. * Numbers can be displayed and typed in many number systems, but JS * only understands latin numbers. * @see https://www.fileformat.info/info/unicode/category/Nd/list.htm * for a list of unicode numeric characters. * Currently only Arabic and Latin numbers are supported, but more * could be added here in the future. * Keep this in sync with `isNumeric` below. */ function parseNumber(str) { str = str // Arabic Indic .replace(/[\u0660-\u0669]/g, function (c) { return String(c.charCodeAt(0) - 0x0660); }) // Extended Arabic Indic .replace(/[\u06f0-\u06f9]/g, function (c) { return String(c.charCodeAt(0) - 0x06f0); }); return Number(str); } /** * Checks whether a unicode string could be converted to a number. * Keep this in sync with `parseNumber` above. */ function isNumeric(str) { return /^[0-9\u0660-\u0669\u06f0-\u06f9]+$/.test(str); } var segmentList = /*#__PURE__*/adminUiCore.style({ display: 'flex' }); var segment = /*#__PURE__*/adminUiCore.style({ cursor: 'pointer', text: '$body', paddingY: 0, bg: '$action.neutral.tertiary', color: '$action.neutral.tertiary', ':disabled': { color: '$disabled' } }); var segmentVariants = /*#__PURE__*/adminUiCore.styleVariants({ literal: { "true": { paddingX: '$xs' }, "false": { paddingX: '$s', ':hover': { bg: '$action.neutral.tertiaryHover', color: '$action.neutral.tertiaryHover' }, ':active': { bg: '$action.neutral.tertiaryPressed', color: '$action.neutral.tertiaryPressed' }, ':focus': { bg: '$action.neutral.tertiaryHover', color: '$action.netural.tertiaryHover', outline: 'none' } } } }); var Segment = /*#__PURE__*/adminUiReact.createComponent(function (props) { var isDisabled = props.isDisabled, isReadOnly = props.isReadOnly, isRequired = props.isRequired, segment$1 = props.segment, state = props.state, htmlOnMouseDown = props.onMouseDown, htmlOnKeyDown = props.onKeyDown, htmlOnFocus = props.onFocus, htmlProps = _objectWithoutPropertiesLoose(props, ["isDisabled", "isReadOnly", "isRequired", "segment", "state", "onMouseDown", "onKeyDown", "onFocus"]); var next = state.next, dateFormatter = state.dateFormatter, increment = state.increment, decrement = state.decrement, incrementPage = state.incrementPage, decrementPage = state.decrementPage, setSegment = state.setSegment; var disabled = React.useMemo(function () { return isDisabled || isReadOnly || segment$1.type === 'literal'; }, [isDisabled, isReadOnly, segment$1.type]); var _useId = Id.unstable_useId({ baseId: 'datepicker-segment' }), id = _useId.id; var _useState = React.useState(''), enteredKeys = _useState[0], setEnteredKeys = _useState[1]; var monthFormatter = i18n.useDateFormatter({ month: 'long' }); var hourFormatter = i18n.useDateFormatter({ hour: 'numeric', hour12: dateFormatter.resolvedOptions().hour12 }); var _useSpinButton = spinbutton.useSpinButton({ value: segment$1.value, textValue: getTextValue(segment$1, state, { month: monthFormatter, hour: hourFormatter }), minValue: segment$1.minValue, maxValue: segment$1.maxValue, isDisabled: isDisabled, isReadOnly: isReadOnly, isRequired: isRequired, onIncrement: function onIncrement() { return increment(segment$1.type); }, onDecrement: function onDecrement() { return decrement(segment$1.type); }, onIncrementPage: function onIncrementPage() { return incrementPage(segment$1.type); }, onDecrementPage: function onDecrementPage() { return decrementPage(segment$1.type); }, onIncrementToMax: function onIncrementToMax() { return setSegment(segment$1.type, segment$1.maxValue); }, onDecrementToMin: function onDecrementToMin() { return setSegment(segment$1.type, segment$1.minValue); } }), spinButtonProps = _useSpinButton.spinButtonProps; var onNumericKeyDown = React.useCallback(function (key) { var newValue = enteredKeys + key; if (segment$1.type === 'dayPeriod') { if (key === 'a') { state.setSegment('dayPeriod', 0); } else if (key === 'p') { state.setSegment('dayPeriod', 12); } state.next(); } else { if (!isNumeric(newValue)) { return; } var numberValue = parseNumber(newValue); var segmentValue = numberValue; if (segment$1.type === 'hour' && state.dateFormatter.resolvedOptions().hour12 && numberValue === 12) { segmentValue = 0; } else if (numberValue > segment$1.maxValue) { segmentValue = parseNumber(key); } state.setSegment(segment$1.type, segmentValue); if (Number(numberValue + "0") > segment$1.maxValue) { setEnteredKeys(''); state.next(); } else { setEnteredKeys(newValue); } } }, [enteredKeys, next, segment$1.maxValue, segment$1.type]); var onKeyDown = React.useCallback(function (e) { if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) { return; } switch (e.key) { case 'Enter': e.preventDefault(); next(); break; case 'Tab': break; case 'Backspace': { e.preventDefault(); if (isNumeric(segment$1.text) && !isReadOnly) { var newValue = segment$1.text.slice(0, -1); setSegment(segment$1.type, newValue.length === 0 ? segment$1.minValue : parseNumber(newValue)); setEnteredKeys(newValue); } break; } default: e.preventDefault(); e.stopPropagation(); if ((isNumeric(e.key) || /^[ap]$/.test(e.key)) && !isReadOnly) ; } }, [next, onNumericKeyDown, segment$1.minValue, segment$1.text, segment$1.type]); var onFocus = React.useCallback(function () { setEnteredKeys(''); }, []); var onMouseDown = React.useCallback(function (e) { return e.stopPropagation(); }, []); var elementProps = React.useMemo(function () { var baseProps = _extends({ state: state, disabled: disabled, tabIndex: disabled ? -1 : 0, children: segment$1.text }, htmlProps); switch (segment$1.type) { case 'literal': return _extends({}, baseProps, { baseStyle: _extends({}, segment, segmentVariants({ literal: true })) }); case 'era': return _extends({}, baseProps, { baseStyle: _extends({}, segment, segmentVariants({ literal: false })) }); default: return utils.mergeProps(spinButtonProps, _extends({}, baseProps, { 'aria-label': segment$1.type, onKeyDown: adminUiUtil.callAllHandlers(htmlOnKeyDown, onKeyDown), onFocus: adminUiUtil.callAllHandlers(htmlOnFocus, onFocus), onMouseDown: adminUiUtil.callAllHandlers(htmlOnMouseDown, onMouseDown), children: getTextValue(segment$1, state, { month: monthFormatter, hour: hourFormatter }), baseStyle: _extends({}, segment, segmentVariants({ literal: false })) })); } }, [segment$1, state, disabled]); return adminUiReact.useElement(Composite.CompositeItem, _extends({}, elementProps, { id: id, 'aria-labelledby': id })); }); function getTextValue(segment, state, formatters) { switch (segment.type) { case 'hour': { var hourFormattedValue = formatters.hour.format(state.fieldValue); return hourFormattedValue.split(' ')[0]; } case 'dayPeriod': { var _hourFormattedValue = formatters.hour.format(state.fieldValue); return _hourFormattedValue.split(' ')[1]; } default: { var _state$showPlaceholde; var displayPlaceholder = (_state$showPlaceholde = state.showPlaceholder.current[segment.type]) !== null && _state$showPlaceholde !== void 0 ? _state$showPlaceholde : false; return displayPlaceholder ? segment.placeholder : segment.text; } } } var SegmentList = /*#__PURE__*/adminUiReact.createComponent(function (props) { return adminUiReact.useElement(Composite.Composite, _extends({ baseStyle: segmentList }, props)); }); var EDITABLE_SEGMENTS = { year: true, month: true, day: true, hour: true, minute: true, second: true, dayPeriod: true }; var PAGE_STEP = { year: 5, month: 2, day: 7, hour: 2, minute: 15, second: 15 }; var RESET_PlACEHOLDER = { day: false, month: false, year: false }; var DISPLAY_PlACEHOLDER = { day: true, month: true, year: true }; var TYPO_MAPPING = { dayperiod: 'dayPeriod' }; function useSegmentState(props) { if (props === void 0) { props = {}; } var _props = props, value = _props.value, onChange = _props.onChange, _props$defaultValue = _props.defaultValue, defaultValue = _props$defaultValue === void 0 ? new Date() : _props$defaultValue, formatOptions = _props.formatOptions, placeholder = _props.placeholder; var segmentComposite = Composite.useCompositeState({ orientation: 'horizontal' }); var validSegments = React.useRef(EDITABLE_SEGMENTS); var dateFormatter = i18n.useDateFormatter(formatOptions); var showPlaceholder = React.useRef(placeholder ? DISPLAY_PlACEHOLDER : RESET_PlACEHOLDER); var resolvedOptions = React.useMemo(function () { return dateFormatter.resolvedOptions(); }, [dateFormatter]); var numSegments = React.useMemo(function () { return dateFormatter.formatToParts(new Date()).filter(function (seg) { return adminUiUtil.get(EDITABLE_SEGMENTS, seg.type); }).length; }, [dateFormatter]); var _useControllableState = adminUiHooks.useControllableState({ value: value, defaultValue: defaultValue, onChange: onChange }), date = _useControllableState[0], setDate = _useControllableState[1]; var segments = React.useMemo(function () { return dateFormatter.formatToParts(date).map(function (segment) { return _extends({ type: adminUiUtil.get(TYPO_MAPPING, segment.type) || segment.type, text: segment.value, placeholder: adminUiUtil.get(placeholder, segment.type) }, getSegmentLimits(date, segment.type, resolvedOptions)); }); }, [resolvedOptions, dateFormatter, placeholder, date]); React.useEffect(function () { if (value && Object.keys(validSegments.current).length < numSegments) { validSegments.current = EDITABLE_SEGMENTS; } }, [value, numSegments]); var adjustSegment = function adjustSegment(type, amount) { validSegments.current[type] = true; showPlaceholder.current[type] = false; setDate(add(date, type, amount, resolvedOptions)); }; var resetPlaceholder = function resetPlaceholder() { showPlaceholder.current = RESET_PlACEHOLDER; }; var displayPlaceholder = function displayPlaceholder() { showPlaceholder.current = DISPLAY_PlACEHOLDER; }; return _extends({}, segmentComposite, { showPlaceholder: showPlaceholder, fieldValue: date, setFieldValue: setDate, segments: segments, dateFormatter