UNPKG

@vtex/admin-ui

Version:

> VTEX admin component library

1,745 lines (1,584 loc) 334 kB
import { style as style$1, styleVariants, focusVisible, negative, tokens, palette } from '@vtex/admin-ui-core'; export * from '@vtex/admin-ui-core'; import { createComponent, useElement, jsx, tag, createHook, IconContainer, useSystem, useResponsiveValue } from '@vtex/admin-ui-react'; export * from '@vtex/admin-ui-react'; import { useOnKeyDown, useForkRef, useControllableState, useDebounce, useSafeLayoutEffect, useDebouncedCache, useQueryState, useTimeout } from '@vtex/admin-ui-hooks'; export * from '@vtex/admin-ui-hooks'; import { isTouch, ariaAttr, callAllHandlers, dataAttr, ensureFocus, renameKeys, pick, get, isBrowser, forwardRef as forwardRef$1, merge, isFunction } from '@vtex/admin-ui-util'; export * from '@vtex/admin-ui-util'; import React, { useCallback, useMemo, useRef, useEffect, useState, forwardRef, createContext, useContext, Fragment, Children, cloneElement, useReducer } from 'react'; import { Role } from 'reakit/Role'; import { Popover, PopoverDisclosure, usePopoverState } from 'reakit/Popover'; import { unstable_useId } from 'reakit/Id'; import { IconCaretLeft, IconCaretRight, IconCalendarBlank, IconCaretUp, IconXCircle, IconX, IconDotsThreeVertical, IconCaretDown, IconEyeSlash, IconEye, IconMinus, IconPlus, IconMagnifyingGlass, IconCheckCircle, IconWarning, IconXOctagon, IconBell, IconCopy, IconTrash, IconClockCounterClockwise, IconArrowLeft } from '@vtex/phosphor-icons'; export { IconActivity, IconAlarm, IconArchive, IconArrowCircleUpRight, IconArrowCounterClockwise, IconArrowDown, IconArrowLeft, IconArrowLineDown, IconArrowLineUp, IconArrowRight, IconArrowSquareOut, IconArrowSquareUpRight, IconArrowUUpLeft, IconArrowUp, IconArrowUpRight, IconArrowsClockwise, IconBarcode, IconBell, IconCalendarBlank, IconCaretDown, IconCaretLeft, IconCaretRight, IconCaretUp, IconChartBar, IconChartLineUp, IconChatText, IconCheck, IconCheckCircle, IconCirclesThreePlus, IconClock, IconCloudArrowUp, IconCode, IconCopySimple, IconCornersOut, IconCreditCard, IconCube, IconCurrencyCircleDollar, IconDotsSixVertical, IconDotsThreeVertical, IconEnvelope, IconEye, IconEyeSlash, IconFaders, IconFileText, IconFlag, IconFolder, IconGear, IconGearSix, IconGift, IconGlobeHemisphereWest, IconHandbagSimple, IconHeadset, IconHeart, IconHouse, IconIdentificationCard, IconImageSquare, IconKey, IconLayout, IconLink, IconLinkBreak, IconList, IconListDashes, IconListNumbers, IconLockKey, IconLockKeyOpen, IconMagnifyingGlass, IconMagnifyingGlassPlus, IconMapPin, IconMegaphone, IconMinus, IconNotebook, IconPackage, IconPaperPlaneTilt, IconPaperclip, IconPencil, IconPlus, IconPrinter, IconQuestion, IconReceipt, IconRocketLaunch, IconRows, IconShareNetwork, IconShoppingCartSimple, IconSignOut, IconSquaresFour, IconStack, IconStorefront, IconTag, IconTextAlignCenter, IconTextAlignLeft, IconTextAlignRight, IconTextBolder, IconTextItalic, IconTextUnderline, IconTicket, IconTrash, IconTreeStructure, IconTruck, IconUser, IconUsers, IconWarning, IconWarningCircle, IconX, IconXCircle, IconXOctagon } from '@vtex/phosphor-icons'; import { Clickable } from 'reakit/Clickable'; import { useLocale as useLocale$1, useDateFormatter, useMessageFormatter } from '@react-aria/i18n'; export { I18nProvider as experimental_I18nProvider, useDateFormatter as experimental_useDateFormatter } from '@react-aria/i18n'; import { isSameDay, isWeekend, getYear, getMonth, getDate, setDay, addDays, subDays, addWeeks, subWeeks, addMonths, subMonths, startOfMonth, endOfMonth, startOfDay, addYears, subYears, getDaysInMonth, isSameMonth, setYear, setSeconds, setMonth, setMinutes, getHours, setHours, getSeconds, getMinutes, setDate } from 'date-fns'; import invariant from 'tiny-invariant'; import { CompositeItem, Composite, useCompositeState, CompositeGroup, useComposite, useCompositeItem } from 'reakit/Composite'; import { useSpinButton } from '@react-aria/spinbutton'; import { mergeProps } from '@react-aria/utils'; import { Checkbox as Checkbox$1, useCheckboxState } from 'reakit/Checkbox'; export { useCheckboxState, useCheckboxState as useToggleState } from 'reakit/Checkbox'; import { Button as Button$1 } from 'reakit/Button'; import { Role as Role$1 } from 'reakit'; import { VisuallyHidden } from 'reakit/VisuallyHidden'; export { VisuallyHidden } from 'reakit/VisuallyHidden'; import { useOption, useListBox } from '@react-aria/listbox'; import { Item } from '@react-stately/collections'; import { useListState } from '@react-stately/list'; import { useComboboxState as useComboboxState$1, useComboboxItem, Combobox, ComboboxCancel, ComboboxPopover as ComboboxPopover$1 } from 'ariakit/combobox'; import { CheckboxCheck } from 'ariakit/checkbox'; import { CompositeItem as CompositeItem$1, useCompositeState as useCompositeState$1, Composite as Composite$1 } from 'ariakit/composite'; import { Focusable } from 'ariakit/focusable'; import { useMenuState as useMenuState$1, MenuButton as MenuButton$1, Menu as Menu$3, MenuSeparator as MenuSeparator$1, MenuItem as MenuItem$1 } from 'reakit/Menu'; import useCollapse from 'react-collapsed'; import { isElement } from 'react-is'; import { Separator } from 'reakit/Separator'; import { useTooltipState, TooltipReference, Tooltip as Tooltip$1 } from 'reakit/Tooltip'; import { Radio as Radio$1, RadioGroup as RadioGroup$1 } from 'reakit/Radio'; export { useRadioState } from 'reakit/Radio'; import { DialogBackdrop, Dialog, DialogDisclosure, useDialogState } from 'reakit/Dialog'; import { useSelect, useCombobox } from 'downshift'; export { useSelect as useDropdownState } from 'downshift'; import { Input as Input$2 } from 'reakit/Input'; import { TabList as TabList$1, TabPanel as TabPanel$1, Tab as Tab$1 } from 'reakit/Tab'; export { useTabState } from 'reakit/Tab'; import { Tabbable } from 'reakit/Tabbable'; import { Portal } from 'reakit/Portal'; import { Toolbar as Toolbar$1, ToolbarItem as ToolbarItem$1 } from 'reakit/Toolbar'; export { useToolbarState } from 'reakit/Toolbar'; export { isChrome, isEdge, isFirefox, isMobile, isSafari } from 'react-device-detect'; import { useDebounce as useDebounce$1 } from 'use-debounce'; import warning from '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__*/style$1({ 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__*/createComponent(function (props) { return useElement('div', _extends({}, props, { baseStyle: centerStyle })); }); Center.displayName = 'Center'; var Picker = /*#__PURE__*/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 = useCallback(function () { if (isTouch()) show(); }, [show]); var onKeyDown = 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 = useCallback(function (e) { e.stopPropagation(); segmentFocus === null || segmentFocus === void 0 ? void 0 : segmentFocus(); }, [segmentFocus]); return useElement(Role, _extends({ id: pickerId, role: 'button', 'aria-haspopup': 'dialog', 'aria-expanded': visible, 'aria-owns': visible ? popoverId : undefined, 'aria-disabled': ariaAttr(isDisabled), 'aria-readonly': ariaAttr(isReadOnly), onKeyDown: callAllHandlers(htmlOnKeyDown, onKeyDown), onClick: callAllHandlers(htmlOnClick, onClick), onMouseDown: callAllHandlers(htmlOnMouseDown, onMouseDown) }, htmlProps)); }); var popoverStyle = /*#__PURE__*/style$1({ bg: '$primary', boxShadow: '$overlay.center', border: '$neutral', borderRadius: '$default' }); var PickerPopover = /*#__PURE__*/createComponent(function (props) { var state = props.state, popoverProps = _objectWithoutPropertiesLoose(props, ["state"]); return useElement(Popover, _extends({ id: state.popoverId, state: state, baseStyle: popoverStyle }, popoverProps)); }); var PickerDisclosure = /*#__PURE__*/createComponent(function (props) { var state = props.state, htmlOnMouseDown = props.onMouseDown, htmlProps = _objectWithoutPropertiesLoose(props, ["state", "onMouseDown"]); var onMouseDown = function onMouseDown(e) { e.stopPropagation(); }; return useElement(PopoverDisclosure, _extends({ state: state, tabIndex: -1, disabled: state.isDisabled || state.isReadOnly, onMouseDown: 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 = unstable_useId({ id: pickerIdProp, baseId: 'picker' }), pickerId = _useId.id; var _useId2 = unstable_useId({ id: popoverIdProp, baseId: 'popover' }), popoverId = _useId2.id; var 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 style$1(_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' } }, focusVisible(tone))); } var buttonStyle = /*#__PURE__*/style$1({ text: '$action1', border: 'none', borderRadius: 'default', cursor: 'pointer', position: 'relative' }); var bleedY = /*#__PURE__*/styleVariants({ size: { normal: { marginY: '$-l' }, large: { marginY: '$-xl' } } }); var bleedX = /*#__PURE__*/styleVariants({ size: { normal: { marginX: '$-l' }, large: { marginX: '$-xl' } } }); var variants = /*#__PURE__*/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__*/style$1({ text: '$action1' }); var innerContainerVariants = /*#__PURE__*/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__*/style$1({ text: '$action1', position: 'absolute', bottom: 0, top: 0, left: 0, right: 0, svg: { size: '1.3rem' } }); var calendar = /*#__PURE__*/style$1({ 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__*/style$1({ display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%', marginBottom: '$xl' }); var calendarButton = /*#__PURE__*/style$1( /*#__PURE__*/_extends({}, buttonStyle, /*#__PURE__*/variants({ size: 'normal', variant: 'neutralTertiary' }), { display: 'flex', alignItems: 'center', justifyContent: 'center' })); var calendarCell = /*#__PURE__*/style$1({ size: '2.25rem' }); var calendarCellButton = /*#__PURE__*/style$1( /*#__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__*/style$1({ text: '$title1' }); var calendarDayTitle = /*#__PURE__*/style$1({ text: '$body', textDecoration: 'none', color: '$secondary', paddingY: 2, textAlign: 'center', size: '2.25rem' }); var CalendarHeaderButton = /*#__PURE__*/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 = 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 useElement(Clickable, _extends({ baseStyle: calendarButton, 'aria-label': currentHandler === null || currentHandler === void 0 ? void 0 : currentHandler.ariaLabel, onClick: callAllHandlers(htmlOnClick, currentHandler === null || currentHandler === void 0 ? void 0 : currentHandler.handle) }, htmlProps)); }); var CalendarGrid = /*#__PURE__*/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 = 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 useElement(Role, _extends({ role: 'grid', 'aria-labelledby': calendarId, 'aria-readonly': ariaAttr(isReadOnly), 'aria-disabled': ariaAttr(isDisabled), onKeyDown: callAllHandlers(htmlOnKeyDown, onKeyDown), onFocus: callAllHandlers(htmlOnFocus, function () { return setFocused(true); }), onBlur: callAllHandlers(htmlOnBlur, function () { return setFocused(false); }) }, htmlProps)); }); /** * Returns the region from the locale */ function useRegion() { var _useLocale = useLocale$1(), 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__*/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 useElement('h2', _extends({ id: calendarId, 'aria-live': 'polite', children: useDateFormatter(format).format(currentMonth !== null && currentMonth !== void 0 ? currentMonth : new Date()), baseStyle: calendarHeaderTitle }, htmlProps)); }); var CalendarDayTitle = /*#__PURE__*/createComponent(function (props) { var _weekDays$dayIndex; var weekDays = props.state.weekDays, dayIndex = props.dayIndex, htmlProps = _objectWithoutPropertiesLoose(props, ["state", "dayIndex"]); return useElement(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__*/createComponent(function (props) { return useElement('header', _extends({ baseStyle: calendarHeader }, props)); }); var CalendarCell = /*#__PURE__*/createComponent(function (props) { var date = props.date, dateValue = props.state.dateValue, htmlProps = _objectWithoutPropertiesLoose(props, ["date", "state"]); var isSelected = dateValue ? isSameDay(date, dateValue) : false; var customDataAttr = { 'data-weekend': dataAttr(isWeekend(date)) }; return useElement(Role, _extends({ baseStyle: calendarCell, role: 'gridcell', 'aria-selected': ariaAttr(isSelected) }, customDataAttr, htmlProps)); }); var CalendarCellButton = /*#__PURE__*/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 = useRef(null); var isCurrentMonth = date.getMonth() === month; var isDisabled = isDisabledOption || !isCurrentMonth || isInvalidDateRange(date); var disabled = htmlDisabled || isDisabled; var isSelected = dateValue ? isSameDay(date, dateValue) : false; var isFocused = isFocusedOption && focusedDate && isSameDay(date, focusedDate); var isToday = isSameDay(date, new Date()); // Focus the button in the DOM when the state updates. useEffect(function () { if (isFocused && ref.current) { ensureFocus(ref.current); } }, [date, focusedDate, isFocused, ref]); var onClick = useCallback(function () { if (disabled) return; selectDate(date); setFocusedDate(date); }, [date, disabled, selectDate, setFocusedDate]); var onFocus = useCallback(function () { if (disabled) return; setFocusedDate(date); }, [date, disabled, setFocusedDate]); var dateFormatter = 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 useElement(Clickable, _extends({ baseStyle: calendarCellButton, ref: useForkRef(ref, htmlRef), children: useDateFormatter({ day: 'numeric' }).format(date), 'aria-label': getAriaLabel(), disabled: disabled, tabIndex: !disabled ? isSameDay(date, focusedDate !== null && focusedDate !== void 0 ? focusedDate : new Date()) ? 0 : -1 : undefined, onClick: callAllHandlers(htmlOnClick, onClick), onFocus: callAllHandlers(htmlOnFocus, onFocus) }, htmlProps)); }); /** * Abbreviation component * @example * <Abbr title="Long Version">lv</Abbr> */ var Abbr = /*#__PURE__*/createComponent(function (props) { return useElement('abbr', _extends({ baseStyle: { textDecoration: 'none', text: '$body' } }, props)); }); var Calendar = /*#__PURE__*/createComponent(function (props) { var _state$weekDays, _state$daysInMonth; var state = props.state, htmlProps = _objectWithoutPropertiesLoose(props, ["state"]); return useElement(Role, _extends({ baseStyle: calendar, role: 'group', 'aria-labelledby': state.calendarId, children: React.createElement(React.Fragment, null, React.createElement(CalendarHeader, null, React.createElement(CalendarHeaderButton, { state: state, handler: "previousMonth" }, React.createElement(IconCaretLeft, null)), React.createElement(CalendarHeaderTitle, { state: state }), React.createElement(CalendarHeaderButton, { state: state, handler: "nextMonth" }, React.createElement(IconCaretRight, null))), React.createElement(CalendarGrid, { state: state, as: "table" }, React.createElement("thead", null, React.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.createElement(CalendarDayTitle, { as: "th", scope: "col", key: dayIndex, dayIndex: dayIndex, state: state }, React.createElement(Abbr, { title: day.title }, day.abbr)); }))), React.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.createElement("tr", { key: weekIndex }, week.map(function (date, index) { return React.createElement(CalendarCell, { state: state, date: date, as: "td", key: index }, React.createElement(CalendarCellButton, { state: state, date: date })); })); })))) }, htmlProps)); }); function useWeekDays(weekStart) { var dayFormatter = useDateFormatter({ weekday: 'narrow' }); var dayFormatterLong = useDateFormatter({ weekday: 'long' }); return [0, 1, 2, 3, 4, 5, 6].map(function (index) { var dateDay = 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) ? process.env.NODE_ENV !== "production" ? invariant(false, 'The year must be greater then 0') : invariant(false) : void 0; !(month >= 0 && month <= 11) ? process.env.NODE_ENV !== "production" ? invariant(false, 'The month must be between 0 and 11') : invariant(false) : void 0; !(day >= 1 && day <= 31) ? process.env.NODE_ENV !== "production" ? invariant(false, 'The day must be between 1 and 31') : invariant(false) : void 0; return new Date(year, month, day); } function getDateObject(date) { var dateToParse = date !== null && date !== void 0 ? date : new Date(); return { year: getYear(dateToParse), month: getMonth(dateToParse), day: 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 = useControllableState({ value: initialValue, defaultValue: defaultValue, onChange: onChange }), value = _useControllableState[0], setValue = _useControllableState[1]; var date = useMemo(function () { return createDate(value); }, [value]); var minDate = useMemo(function () { return createDate(minValue); }, [minValue]); var maxDate = useMemo(function () { return createDate(maxValue); }, [maxValue]); var _useState = useState(date), currentMonth = _useState[0], setCurrentMonth = _useState[1]; var _useState2 = useState(date), focusedDate = _useState2[0], setFocusedDate = _useState2[1]; var _useState3 = 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 = useMemo(function () { var monthStartsAt = (startOfMonth(currentMonth).getDay() - weekStart) % 7; if (monthStartsAt < 0) { monthStartsAt += 7; } var days = getDaysInMonth(currentMonth); var weeksInMonth = Math.ceil((monthStartsAt + days) / 7); return generateDaysInMonthArray(month, monthStartsAt, weeksInMonth, year); }, [month, year, currentMonth, weekStart]); var isInvalidDateRange = useCallback(function (value) { return value < minDate || value > maxDate; }, [minDate, maxDate]); var focusCell = useCallback(function (date) { if (isInvalidDateRange(date)) return; if (!isSameMonth(date, currentMonth)) { setCurrentMonth(startOfMonth(date)); } setFocusedDate(date); }, [isInvalidDateRange, currentMonth]); var setDate = useCallback(function (value) { if (!isDisabled && !isReadOnly) { setValue(getDateObject(value)); } }, [isDisabled, isReadOnly, setValue]); var _useId = 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(addDays(focusedDate, 1)); }, focusPreviousDay: function focusPreviousDay() { focusCell(subDays(focusedDate, 1)); }, focusNextWeek: function focusNextWeek() { focusCell(addWeeks(focusedDate, 1)); }, focusPreviousWeek: function focusPreviousWeek() { focusCell(subWeeks(focusedDate, 1)); }, focusNextMonth: function focusNextMonth() { focusCell(addMonths(focusedDate, 1)); }, focusPreviousMonth: function focusPreviousMonth() { focusCell(subMonths(focusedDate, 1)); }, focusStartOfMonth: function focusStartOfMonth() { focusCell(startOfMonth(focusedDate)); }, focusEndOfMonth: function focusEndOfMonth() { focusCell(endOfMonth(startOfDay(focusedDate))); }, focusNextYear: function focusNextYear() { focusCell(addYears(focusedDate, 1)); }, focusPreviousYear: function focusPreviousYear() { focusCell(subYears(focusedDate, 1)); }, selectFocusedDate: function selectFocusedDate() { setDate(focusedDate); }, selectDate: function selectDate(date) { setDate(date); }, isInvalidDateRange: isInvalidDateRange }; } var DatePickerCalendar = /*#__PURE__*/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.createElement(PickerPopover, { csx: csx, ref: ref, state: pickerState }, React.createElement(Calendar, { state: calendarState })); }); DatePickerCalendar.displayName = 'DatePickerCalendar'; var Text = /*#__PURE__*/Object.assign( /*#__PURE__*/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__*/jsx('label')({ text: '$body' }), { displayName: "Label" }); var Flex = /*#__PURE__*/Object.assign( /*#__PURE__*/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 = renameKeys(propertyMap, pick(options, cssProps)); return _extends({}, htmlProps, { csx: _extends({}, cssPropsStyle, csx) }); } }), { displayName: "Flex" }); var FlexSpacer = /*#__PURE__*/Object.assign( /*#__PURE__*/jsx('div')({ flex: 1, justifySelf: 'stretch', alignSelf: 'stretch' }), { displayName: "FlexSpacer" }); var dateField = /*#__PURE__*/style$1({ display: 'flex', justifyContent: 'space-between', alignContent: 'center', padding: '$s', height: 52, width: 288, borderRadius: 4 }); var variants$1 = /*#__PURE__*/styleVariants({ tone: { critical: { border: '$form.critical' }, neutral: { border: '$form.neutral' } }, disabled: { "true": { border: '$disabled' } } }); var label = /*#__PURE__*/style$1({ text: '$detail', color: '$secondary' }); function getSegmentLimits(date, type, options) { switch (type) { case 'day': return { value: getDate(date), minValue: 1, maxValue: getDaysInMonth(date) }; case 'dayPeriod': return { value: getHours(date) >= 12 ? 12 : 0, minValue: 0, maxValue: 12 }; case 'hour': { var value = 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: getMinutes(date), minValue: 0, maxValue: 59 }; case 'second': return { value: getSeconds(date), minValue: 0, maxValue: 59 }; case 'month': return { value: getMonth(date) + 1, minValue: 1, maxValue: 12 }; case 'year': return { value: getYear(date), minValue: 1, maxValue: 9999 }; default: return {}; } } function add(value, part, amount, options) { switch (part) { case 'day': { var day = getDate(value); return setDate(value, cycleValue(day, amount, 1, getDaysInMonth(value))); } case 'dayPeriod': { var hours = getHours(value); var isPM = hours >= 12; return setHours(value, isPM ? hours - 12 : hours + 12); } case 'hour': { var _hours = 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 setHours(value, _hours); } case 'minute': { var minutes = cycleValue(getMinutes(value), amount, 0, 59, true); return setMinutes(value, minutes); } case 'month': { var months = cycleValue(getMonth(value), amount, 0, 11); return setMonth(value, months); } case 'second': { var seconds = cycleValue(getSeconds(value), amount, 0, 59, true); return setSeconds(value, seconds); } case 'year': { var year = cycleValue(getYear(value), amount, 1, 9999, true); return 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 setDay(value, segmentValue); case 'dayPeriod': { var hours = getHours(value); var wasPM = hours >= 12; var isPM = segmentValue >= 12; if (isPM === wasPM) { return value; } return 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 = getHours(value); var _wasPM = _hours2 >= 12; if (!_wasPM && segmentValue === 12) { segmentValue = 0; } if (_wasPM && segmentValue < 12) { segmentValue += 12; } } return setHours(value, segmentValue); case 'minute': return setMinutes(value, segmentValue); case 'month': return setMonth(value, segmentValue - 1); case 'second': return setSeconds(value, segmentValue); case 'year': return 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__*/style$1({ display: 'flex' }); var segment = /*#__PURE__*/style$1({ cursor: 'pointer', text: '$body', paddingY: 0, bg: '$action.neutral.tertiary', color: '$action.neutral.tertiary', ':disabled': { color: '$disabled' } }); var segmentVariants = /*#__PURE__*/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__*/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 = useMemo(function () { return isDisabled || isReadOnly || segment$1.type === 'literal'; }, [isDisabled, isReadOnly, segment$1.type]); var _useId = unstable_useId({ baseId: 'datepicker-segment' }), id = _useId.id; var _useState = useState(''), enteredKeys = _useState[0], setEnteredKeys = _useState[1]; var monthFormatter = useDateFormatter({ month: 'long' }); var hourFormatter = useDateFormatter({ hour: 'numeric', hour12: dateFormatter.resolvedOptions().hour12 }); var _useSpinButton = 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 = 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 = 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 = useCallback(function () { setEnteredKeys(''); }, []); var onMouseDown = useCallback(function (e) { return e.stopPropagation(); }, []); var elementProps = 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 mergeProps(spinButtonProps, _extends({}, baseProps, { 'aria-label': segment$1.type, onKeyDown: callAllHandlers(htmlOnKeyDown, onKeyDown), onFocus: callAllHandlers(htmlOnFocus, onFocus), onMouseDown: callAllHandlers(htmlOnMouseDown, onMouseDown), children: getTextValue(segment$1, state, { month: monthFormatter, hour: hourFormatter }), baseStyle: _extends({}, segment, segmentVariants({ literal: false })) })); } }, [segment$1, state, disabled]); return useElement(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__*/createComponent(function (props) { return useElement(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, fo