UNPKG

@spicy-ui/core

Version:

A themable and extensible React UI library, ready to use out of the box

1,749 lines (1,568 loc) 131 kB
import { useMemo, useRef, forwardRef, createElement, useState, useCallback, useEffect, Fragment, Children, isValidElement, cloneElement, useContext, useReducer, createContext } from 'react'; import { get, css, compose, animation as animation$1, background, border, color, flexbox, grid, layout, other, position, shadow, space as space$1, transition as transition$1, typography as typography$1, shouldForwardProp, extendedFlexbox, extendedGrid, sfp } from '@spicy-ui/styled-system'; import deepmerge from 'deepmerge'; import isEqual from 'react-fast-compare'; import styled, { useTheme, keyframes, css as css$1, createGlobalStyle, ThemeProvider as ThemeProvider$1 } from 'styled-components'; import { HiOutlineUser, HiX, HiChevronDown } from 'react-icons/hi'; import { usePopper as usePopper$1 } from 'react-popper'; import FocusLock from 'react-focus-lock'; import { motion, AnimatePresence } from 'framer-motion'; import { createPortal } from 'react-dom'; import { useCombobox } from 'downshift'; import { normalize } from 'styled-normalize'; import { transparentize, rgba } from 'polished'; 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; } function isFunction(value) { return typeof value === 'function'; } function runIfFn(valueOrFn) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return isFunction(valueOrFn) ? valueOrFn.apply(void 0, args) : valueOrFn; } // https://github.com/gregberge/react-merge-refs function mergeRefs(refs) { return function (value) { refs.forEach(function (ref) { if (typeof ref === 'function') { ref(value); } else if (ref != null) { // eslint-disable-next-line no-param-reassign ref.current = value; } }); }; } var _excluded = ["children"], _excluded2 = ["children", "theme"]; function getStyles(config, props) { if (props === void 0) { props = {}; } if (config) { var _config$propToScaleMa, _props$sx; var propToScaleMap = (_config$propToScaleMa = config.propToScaleMap) != null ? _config$propToScaleMa : []; var baseStyles = config.baseStyle ? runIfFn(config.baseStyle, props) : {}; var scaleStyles = propToScaleMap.map(function (_ref) { var _config$scales$scale; var prop = _ref[0], scale = _ref[1]; return config.scales && props[prop] ? runIfFn((_config$scales$scale = config.scales[scale]) == null ? void 0 : _config$scales$scale[props[prop]], props) : undefined; }).filter(function (style) { return !!style; }); return deepmerge.all([baseStyles].concat(scaleStyles, [(_props$sx = props.sx) != null ? _props$sx : {}])); } return {}; } /** * Hook for resolving a component's styles. * The result of which can then be passed to the `sx` prop. */ function useComponentStyles(componentKey, props) { if (props === void 0) { props = {}; } var theme = useTheme(); var config = get(theme, "components." + componentKey); var allProps = useMemo(function () { var _props = props, rest = _objectWithoutPropertiesLoose(_props, _excluded); return deepmerge.all([{ theme: theme }, rest]); }, [props, theme]); var stylesRef = useRef({}); return useMemo(function () { var styles = getStyles(config, allProps); if (!isEqual(stylesRef.current, styles)) { stylesRef.current = styles; } return stylesRef.current; }, [allProps, config]); } /** * Parser for resolving a component's styles. */ function componentStylesMixin(componentKey) { return function (props) { var theme = props.theme, rest = _objectWithoutPropertiesLoose(props, _excluded2); var config = get(theme, "components." + componentKey); var allProps = deepmerge.all([{ theme: theme }, rest]); var styles = getStyles(config, allProps); return css(styles)(props); }; } function sxMixin(p) { return p.sx ? css(p.sx) : {}; } var allSystem = /*#__PURE__*/compose(animation$1, background, border, color, flexbox, grid, layout, other, position, shadow, space$1, transition$1, typography$1); var Box = /*#__PURE__*/styled.div.withConfig({ shouldForwardProp: shouldForwardProp })(sxMixin, allSystem); Box.displayName = 'Box'; var _excluded$1 = ["children", "sx", "color"]; var Alert = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$1); var styles = useComponentStyles('Alert', props); return createElement(Box, Object.assign({ ref: ref, sx: styles }, rest), children); }); Alert.defaultProps = { color: 'gray' }; Alert.displayName = 'Alert'; function useDisclosure(props) { if (props === void 0) { props = {}; } var _props = props, defaultIsOpen = _props.defaultIsOpen, onOpenProp = _props.onOpen, onCloseProp = _props.onClose; var _React$useState = useState(defaultIsOpen || false), isOpen = _React$useState[0], setIsOpen = _React$useState[1]; var onOpen = useCallback(function () { setIsOpen(true); if (onOpenProp) { onOpenProp(); } }, [onOpenProp]); var onClose = useCallback(function () { setIsOpen(false); if (onCloseProp) { onCloseProp(); } }, [onCloseProp]); var onToggle = useCallback(function () { var action = isOpen ? onClose : onOpen; action(); }, [isOpen, onClose, onOpen]); return { isOpen: !!isOpen, onOpen: onOpen, onClose: onClose, onToggle: onToggle }; } var defaultState = { image: undefined, status: 'loading' }; function useImage(url, crossOrigin) { var _React$useState = useState(defaultState), state = _React$useState[0], setState = _React$useState[1]; var image = state.image, status = state.status; useEffect(function () { if (!url) { return undefined; } var img = document.createElement('img'); function onload() { setState({ image: img, status: 'loaded' }); } function onerror() { setState({ image: undefined, status: 'failed' }); } img.addEventListener('load', onload); img.addEventListener('error', onerror); if (crossOrigin) { img.crossOrigin = crossOrigin; } img.src = url; return function () { img.removeEventListener('load', onload); img.removeEventListener('error', onerror); setState(defaultState); }; }, [crossOrigin, url]); return { image: image, status: status }; } var useKeyPress = function useKeyPress(targetKey, onDown, onUp) { if (onDown === void 0) { onDown = function onDown() {}; } if (onUp === void 0) { onUp = function onUp() {}; } var prevKey = useRef(''); var handleDown = useCallback(function (_ref) { var key = _ref.key; // Don't re-run if the key is the same as last press if (targetKey === prevKey.current) { return; } if (key === targetKey) { onDown(); prevKey.current = key; } }, [targetKey, onDown]); var handleUp = useCallback(function (_ref2) { var key = _ref2.key; if (key === targetKey) { onUp(); prevKey.current = ''; } }, [targetKey, onUp]); useEffect(function () { window.addEventListener('keydown', handleDown); window.addEventListener('keyup', handleUp); return function () { window.removeEventListener('keydown', handleDown); window.removeEventListener('keyup', handleUp); }; }, [targetKey, handleDown, handleUp]); }; var defaultOptions = { closeOnBlur: false, closeOnEsc: false, closeOnInnerClick: false, closeOnOuterClick: false, placement: 'bottom-start', offset: [0, 0] }; function usePopper(options) { var _defaultOptions$optio = _extends({}, defaultOptions, options), isOpen = _defaultOptions$optio.isOpen, onClose = _defaultOptions$optio.onClose, closeOnBlur = _defaultOptions$optio.closeOnBlur, closeOnEsc = _defaultOptions$optio.closeOnEsc, closeOnInnerClick = _defaultOptions$optio.closeOnInnerClick, closeOnOuterClick = _defaultOptions$optio.closeOnOuterClick, placement = _defaultOptions$optio.placement, offset = _defaultOptions$optio.offset; var triggerRef = useRef(null); var childRef = useRef(null); var _useReactPopper = usePopper$1(triggerRef.current, childRef.current, { placement: placement, modifiers: [{ name: 'offset', options: { offset: offset } }] }), attributes = _useReactPopper.attributes, styles = _useReactPopper.styles; var onTriggerBlur = useCallback(function () { if (closeOnBlur && onClose) { onClose(); } }, [closeOnBlur, onClose]); var onDocumentClick = useCallback(function (e) { var _childRef$current, _triggerRef$current, _childRef$current2; if (!isOpen || !onClose) { return; } if (closeOnInnerClick && (_childRef$current = childRef.current) != null && _childRef$current.contains(e.target)) { onClose(); return; } if (closeOnOuterClick && !((_triggerRef$current = triggerRef.current) != null && _triggerRef$current.contains(e.target)) && !((_childRef$current2 = childRef.current) != null && _childRef$current2.contains(e.target))) { onClose(); } }, [closeOnInnerClick, closeOnOuterClick, isOpen, onClose]); useKeyPress('Escape', function () { if (isOpen && closeOnEsc && onClose) { onClose(); } }); useEffect(function () { document.addEventListener('mouseup', onDocumentClick); return function () { return document.removeEventListener('mouseup', onDocumentClick); }; }, [onDocumentClick]); var _useTheme = useTheme(), zIndices = _useTheme.zIndices; return { triggerProps: { ref: triggerRef, onBlur: onTriggerBlur, 'data-active': isOpen ? true : undefined }, childProps: _extends({ ref: childRef, style: _extends({}, styles.popper, { zIndex: zIndices.popover }) }, attributes.popper) }; } var Text = /*#__PURE__*/styled.p.withConfig({ shouldForwardProp: shouldForwardProp })( /*#__PURE__*/componentStylesMixin('Text'), sxMixin, allSystem); Text.defaultProps = { variant: 'md' }; Text.displayName = 'Text'; var _excluded$2 = ["children", "sx", "getInitials", "icon", "name", "showBorder", "size", "src", "variant"]; var AvatarImage = function AvatarImage(_ref) { var getInitials = _ref.getInitials, icon = _ref.icon, name = _ref.name, src = _ref.src; var _useImage = useImage(src), status = _useImage.status; if (!src || status !== 'loaded') { return name ? createElement(Text, { as: "span", fontSize: "inherit", fontFamily: "inherit", lineHeight: "inherit" }, getInitials(name)) : createElement(Fragment, null, icon); } return createElement(Box, { as: "img", src: src, alt: name, size: "full", objectFit: "cover" }); }; var defaultGetInitials = function defaultGetInitials(name) { var _name$split = name.split(' '), first = _name$split[0], last = _name$split[1]; return first && last ? "" + first.charAt(0) + last.charAt(0) : first.charAt(0); }; var Avatar = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, _props$getInitials = props.getInitials, getInitials = _props$getInitials === void 0 ? defaultGetInitials : _props$getInitials, _props$icon = props.icon, icon = _props$icon === void 0 ? createElement(HiOutlineUser, { size: "75%" }) : _props$icon, name = props.name, src = props.src, rest = _objectWithoutPropertiesLoose(props, _excluded$2); var styles = useComponentStyles('Avatar', props); return createElement(Box, Object.assign({ ref: ref, sx: styles }, rest), createElement(AvatarImage, { getInitials: getInitials, icon: icon, name: name, src: src }), children); }); Avatar.defaultProps = { size: 'md', variant: 'circle' }; Avatar.displayName = 'Avatar'; var _excluded$3 = ["children", "sx", "borderColor", "max", "size", "spacing", "variant"]; var AvatarGroup = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, borderColor = props.borderColor, max = props.max, size = props.size, spacing = props.spacing, variant = props.variant, rest = _objectWithoutPropertiesLoose(props, _excluded$3); var styles = useComponentStyles('Avatar', _extends({}, props, { showBorder: true })); var validChildren = Children.toArray(children).filter(function (child) { return isValidElement(child); }); var visibleChildren = max ? validChildren.slice(0, max) : validChildren; var reversedVisible = visibleChildren.reverse(); var overflow = max != null && validChildren.length - max; return createElement(Box, Object.assign({ ref: ref, display: "flex", alignItems: "center", justifyContent: "flex-end", flexDirection: "row-reverse" }, rest), overflow > 0 && createElement(Box, { as: "span", sx: _extends({}, styles, borderColor ? { borderColor: borderColor } : {}), ml: spacing }, "+", overflow), reversedVisible.map(function (avatar, index) { return cloneElement(avatar, { showBorder: true, sx: _extends({ mr: index === 0 ? 0 : spacing }, borderColor ? { borderColor: borderColor } : {}, avatar.props.sx), size: size, variant: variant }); })); }); AvatarGroup.defaultProps = { spacing: '-0.75rem', variant: 'circle', size: 'md' }; AvatarGroup.displayName = 'AvatarGroup'; var _excluded$4 = ["as", "children", "sx", "color", "variant"]; var Badge = /*#__PURE__*/forwardRef(function (props, ref) { var as = props.as, children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$4); var styles = useComponentStyles('Badge', props); return createElement(Box, Object.assign({ ref: ref, as: as != null ? as : 'span', sx: styles }, rest), children); }); Badge.defaultProps = { color: 'gray', variant: 'subtle' }; Badge.displayName = 'Badge'; var _excluded$5 = ["sx", "color", "trackColor", "thickness", "speed", "size"]; var Spinner = /*#__PURE__*/forwardRef(function (props, ref) { var rest = _objectWithoutPropertiesLoose(props, _excluded$5); var styles = useComponentStyles('Spinner', props); return createElement(Box, Object.assign({ ref: ref, sx: styles }, rest)); }); Spinner.defaultProps = { color: 'blue.500', trackColor: 'transparent', thickness: '2px', speed: '0.45s', size: 'md' }; Spinner.displayName = 'Spinner'; var _excluded$6 = ["as", "children", "sx", "iconSpacing", "iconBefore", "iconAfter", "isActive", "isDisabled", "isLoading", "loadingText", "spinner", "type", "color", "size", "variant"]; var ButtonSpinner = function ButtonSpinner(props) { var _props$children = props.children, children = _props$children === void 0 ? createElement(Spinner, { sx: { color: 'currentcolor', height: '1em', width: '1em' } }) : _props$children; var styles = useComponentStyles('ButtonSpinner', props); return createElement(Box, { sx: styles }, children); }; var iconStyles = { '& > *': { display: 'inline-block' } }; var Button = /*#__PURE__*/forwardRef(function (props, ref) { var as = props.as, children = props.children, iconSpacing = props.iconSpacing, iconBefore = props.iconBefore, iconAfter = props.iconAfter, isActive = props.isActive, isDisabled = props.isDisabled, isLoading = props.isLoading, loadingText = props.loadingText, spinner = props.spinner, type = props.type, rest = _objectWithoutPropertiesLoose(props, _excluded$6); var styles = useComponentStyles('Button', props); return createElement(Box, Object.assign({ ref: ref, as: as != null ? as : 'button', disabled: isLoading || isDisabled, type: as ? undefined : type, role: "button", "data-active": isActive, "data-loading": isLoading, sx: styles }, rest), iconBefore && !isLoading && createElement(Box, { as: "span", mr: iconSpacing, sx: iconStyles }, iconBefore), isLoading && createElement(ButtonSpinner, { hasText: !!loadingText, spacing: iconSpacing }, spinner), isLoading ? loadingText || createElement(Box, { as: "span", opacity: "0" }, children) : createElement(Box, { as: "span", userSelect: "none" }, children), iconAfter && !isLoading && createElement(Box, { as: "span", ml: iconSpacing, sx: iconStyles }, iconAfter)); }); Button.defaultProps = { iconSpacing: '0.5rem', type: 'button', color: 'gray', size: 'md', variant: 'filled' }; Button.displayName = 'Button'; var _excluded$7 = ["children", "sx", "icon", "isRound"]; var IconButton = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, icon = props.icon, rest = _objectWithoutPropertiesLoose(props, _excluded$7); var styles = useComponentStyles('IconButton', props); return createElement(Button, Object.assign({ ref: ref, sx: styles }, rest), icon || children); }); IconButton.displayName = 'IconButton'; var _excluded$8 = ["id", "name", "value", "label", "checked", "isDisabled", "isInvalid", "color", "size"]; var Checkbox = /*#__PURE__*/forwardRef(function (props, ref) { var id = props.id, name = props.name, value = props.value, label = props.label, checked = props.checked, isDisabled = props.isDisabled, rest = _objectWithoutPropertiesLoose(props, _excluded$8); var outerStyles = useComponentStyles('CheckboxOuter', props); var inputStyles = useComponentStyles('CheckboxInput', props); var labelStyles = useComponentStyles('CheckboxLabel', props); return createElement(Box, { as: "label", htmlFor: id, sx: outerStyles }, createElement(Box, Object.assign({ ref: ref, as: "input", type: "checkbox", id: id, name: name, value: value, defaultChecked: checked, "data-checked": !checked ? undefined : checked, disabled: isDisabled, sx: inputStyles }, rest)), label && createElement(Text, { as: "div", fontSize: "inherit", lineHeight: "inherit", sx: labelStyles }, label)); }); Checkbox.defaultProps = { color: 'blue', size: 'md' }; Checkbox.displayName = 'Checkbox'; var _excluded$9 = ["sx", "icon"]; var CloseButton = /*#__PURE__*/forwardRef(function (props, ref) { var _props$icon = props.icon, icon = _props$icon === void 0 ? createElement(HiX, null) : _props$icon, rest = _objectWithoutPropertiesLoose(props, _excluded$9); var styles = useComponentStyles('CloseButton', props); return createElement(IconButton, Object.assign({ ref: ref, icon: icon, sx: styles }, rest)); }); CloseButton.defaultProps = { color: 'blackAlpha', variant: 'ghost' }; CloseButton.displayName = 'CloseButton'; var _excluded$a = ["as", "children", "sx", "color", "variant"]; var Code = /*#__PURE__*/forwardRef(function (props, ref) { var as = props.as, children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$a); var styles = useComponentStyles('Code', props); return createElement(Box, Object.assign({ ref: ref, as: as != null ? as : 'code', sx: styles }, rest), children); }); Code.defaultProps = { color: 'gray', variant: 'subtle' }; Code.displayName = 'Code'; var _excluded$b = ["as", "children", "sx", "isCentered"]; var Container = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$b); var styles = useComponentStyles('Container', props); return createElement(Box, Object.assign({ ref: ref, sx: styles }, rest), children); }); Container.displayName = 'Container'; var _excluded$c = ["sx", "orientation"]; var Divider = /*#__PURE__*/forwardRef(function (props, ref) { var rest = _objectWithoutPropertiesLoose(props, _excluded$c); var styles = useComponentStyles('Divider', props); return createElement(Box, Object.assign({ ref: ref, sx: styles }, rest)); }); Divider.defaultProps = { orientation: 'horizontal' }; Divider.displayName = 'Divider'; var Portal = function Portal(_ref) { var children = _ref.children; var _React$useState = useState(false), ready = _React$useState[0], setReady = _React$useState[1]; var container = useRef(); useEffect(function () { if (!container.current) { var el = document.createElement('div'); el.setAttribute('data-spicy-portal', ''); container.current = el; } document.body.appendChild(container.current); setReady(true); return function () { if (container.current) { document.body.removeChild(container.current); container.current = undefined; setReady(false); } }; }, []); if (ready && container.current) { return createPortal(children, container.current); } return null; }; Portal.displayName = 'Portal'; var _excluded$d = ["children", "sx", "isOpen", "onClick"]; var Motion = /*#__PURE__*/styled(motion.div)(sxMixin); var variants = { hidden: { opacity: 0, pointerEvents: 'none', transition: { duration: 0.3 } }, visible: { opacity: 1, pointerEvents: 'auto', transition: { duration: 0.2 } } }; var Overlay = function Overlay(props) { var children = props.children, isOpen = props.isOpen, onClick = props.onClick, rest = _objectWithoutPropertiesLoose(props, _excluded$d); var style = useComponentStyles('Overlay', props); return createElement(Portal, null, createElement(Motion, Object.assign({ initial: "hidden", animate: isOpen ? 'visible' : 'hidden', variants: variants, onClick: onClick, sx: style }, rest), children)); }; Overlay.displayName = 'Overlay'; var _excluded$e = ["children", "sx", "isOpen", "onClose", "anchor", "closeOnEsc", "closeOnOverlayClick", "disableFocusTrap", "size"]; var getAnchor = function getAnchor(anchor) { switch (anchor) { case 'top': return { top: 0, right: 0, bottom: 'unset', left: 0 }; case 'right': return { top: 0, right: 0, bottom: 0, left: 'unset' }; case 'bottom': return { top: 'unset', right: 0, bottom: 0, left: 0 }; default: return { top: 0, right: 'unset', bottom: 0, left: 0 }; } }; var Drawer = function Drawer(props) { var children = props.children, isOpen = props.isOpen, onClose = props.onClose, anchor = props.anchor, closeOnEsc = props.closeOnEsc, closeOnOverlayClick = props.closeOnOverlayClick, disableFocusTrap = props.disableFocusTrap, rest = _objectWithoutPropertiesLoose(props, _excluded$e); useKeyPress('Escape', function () { if (isOpen && !closeOnEsc && onClose) { onClose(); } }); var onOverlayClick = useCallback(function (e) { if (e.target !== e.currentTarget) { return; } if (closeOnOverlayClick && onClose) { onClose(); } }, [closeOnOverlayClick, onClose]); useEffect(function () { if (isOpen && !document.body.classList.contains('noscroll')) { document.body.classList.add('noscroll'); } return function () { return document.body.classList.remove('noscroll'); }; }, [isOpen]); var style = useComponentStyles('Drawer', props); return createElement(Overlay, { isOpen: isOpen, onClick: onOverlayClick, sx: getAnchor(anchor) }, createElement(FocusLock, { disabled: disableFocusTrap || !isOpen }, createElement(Box, Object.assign({ role: "dialog", "aria-modal": "true", sx: style }, rest), children))); }; Drawer.defaultProps = { anchor: 'right', closeOnOverlayClick: true, size: 'xs' }; Drawer.displayName = 'Drawer'; var Flex = /*#__PURE__*/styled.div.withConfig({ shouldForwardProp: shouldForwardProp })(sxMixin, allSystem, extendedFlexbox); Flex.defaultProps = { display: 'flex' }; Flex.displayName = 'Flex'; var Grid = /*#__PURE__*/styled.div.withConfig({ shouldForwardProp: shouldForwardProp })(sxMixin, allSystem, extendedGrid); Grid.defaultProps = { display: 'grid' }; Grid.displayName = 'Grid'; var Heading = /*#__PURE__*/styled.h2.withConfig({ shouldForwardProp: shouldForwardProp })( /*#__PURE__*/componentStylesMixin('Heading'), sxMixin, allSystem); Heading.defaultProps = { variant: 'h2' }; Heading.displayName = 'Heading'; var _excluded$f = ["sx", "crossOrigin", "fallback", "fallbackSrc", "src"]; var Image = /*#__PURE__*/forwardRef(function (props, ref) { var crossOrigin = props.crossOrigin, fallback = props.fallback, fallbackSrc = props.fallbackSrc, src = props.src, rest = _objectWithoutPropertiesLoose(props, _excluded$f); var _useImage = useImage(src, crossOrigin), status = _useImage.status; var styles = useComponentStyles('Image', props); if (status !== 'loaded') { return fallback || createElement(Box, Object.assign({ ref: ref, as: "img", sx: styles, src: fallbackSrc }, rest)); } return createElement(Box, Object.assign({ ref: ref, as: "img", sx: styles, src: src }, rest)); }); Image.displayName = 'Image'; var _excluded$g = ["as", "children", "sx", "isDisabled", "isInvalid", "isReadOnly", "isRequired", "size", "variant"]; var Input = /*#__PURE__*/forwardRef(function (props, ref) { var as = props.as, children = props.children, isDisabled = props.isDisabled, isReadOnly = props.isReadOnly, isRequired = props.isRequired, rest = _objectWithoutPropertiesLoose(props, _excluded$g); var styles = useComponentStyles('Input', props); return createElement(Box, Object.assign({ ref: ref, as: as != null ? as : 'input', disabled: isDisabled, readOnly: isReadOnly, required: isRequired, sx: styles }, rest), children); }); Input.defaultProps = { size: 'md', type: 'text', variant: 'outlined' }; Input.displayName = 'Input'; var _excluded$h = ["as", "children", "sx"]; var Kbd = /*#__PURE__*/forwardRef(function (props, ref) { var as = props.as, children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$h); var styles = useComponentStyles('Kbd', props); return createElement(Box, Object.assign({ ref: ref, as: as != null ? as : 'kbd', sx: styles }, rest), children); }); Kbd.displayName = 'Kbd'; var Link = /*#__PURE__*/styled.a.attrs(function (_ref) { var isDisabled = _ref.isDisabled, isExternal = _ref.isExternal, _onClick = _ref.onClick; return { 'aria-disabled': isDisabled || undefined, 'data-disabled': isDisabled || undefined, tabIndex: isDisabled ? -1 : undefined, target: isExternal ? '_blank' : undefined, role: isExternal ? "noopener noreferrer" : undefined, onClick: function onClick(e) { if (isDisabled) { e.preventDefault(); return; } if (_onClick) { _onClick(e); } } }; }).withConfig({ shouldForwardProp: sfp(['color', 'hoverColor', 'isDisabled', 'isExternal', 'underlineBehaviour']) })( /*#__PURE__*/componentStylesMixin('Link'), sxMixin); Link.defaultProps = { underlineBehaviour: 'hover' }; Link.displayName = 'Link'; var _excluded$i = ["children", "sx", "trigger", "closeOnBlur", "closeOnEsc", "closeOnInnerClick", "closeOnOuterClick", "openOnHover", "placement", "offset"]; var Motion$1 = /*#__PURE__*/styled(motion.div)(sxMixin); var variants$1 = { hidden: { opacity: 0, pointerEvents: 'none', transition: { duration: 0.2 } }, visible: { opacity: 1, pointerEvents: 'auto', transition: { duration: 0.2 } } }; var Menu = function Menu(props) { var children = props.children, trigger = props.trigger, closeOnBlur = props.closeOnBlur, closeOnEsc = props.closeOnEsc, closeOnInnerClick = props.closeOnInnerClick, closeOnOuterClick = props.closeOnOuterClick, openOnHover = props.openOnHover, placement = props.placement, offset = props.offset, rest = _objectWithoutPropertiesLoose(props, _excluded$i); var styles = useComponentStyles('Menu', props); var _useDisclosure = useDisclosure(), isOpen = _useDisclosure.isOpen, onOpen = _useDisclosure.onOpen, onClose = _useDisclosure.onClose, onToggle = _useDisclosure.onToggle; var _usePopper = usePopper({ isOpen: isOpen, onClose: onClose, closeOnBlur: closeOnBlur, closeOnEsc: closeOnEsc, closeOnInnerClick: closeOnInnerClick, closeOnOuterClick: closeOnOuterClick, placement: placement, offset: offset }), triggerProps = _usePopper.triggerProps, childProps = _usePopper.childProps; return createElement(Fragment, null, cloneElement(runIfFn(trigger, { isOpen: isOpen, onOpen: onOpen, onClose: onClose, onToggle: onToggle }), _extends({}, triggerProps, { onClick: openOnHover ? undefined : onToggle, onKeyDown: function onKeyDown(_ref) { var key = _ref.key; return key === 'Enter' ? onToggle : undefined; }, onMouseEnter: openOnHover ? onOpen : undefined })), createElement(Portal, null, createElement(Motion$1, Object.assign({}, childProps, { initial: "hidden", tabIndex: isOpen ? 0 : -1, animate: isOpen ? 'visible' : 'hidden', variants: variants$1, sx: styles }, rest), runIfFn(children, { isOpen: isOpen, onOpen: onOpen, onClose: onClose, onToggle: onToggle })))); }; Menu.defaultProps = { closeOnBlur: false, closeOnEsc: true, closeOnInnerClick: true, closeOnOuterClick: true, openOnHover: false, placement: 'bottom-start', offset: [0, 8] }; Menu.displayName = 'Menu'; var MenuDivider = /*#__PURE__*/styled.div( /*#__PURE__*/componentStylesMixin('MenuDivider'), sxMixin); MenuDivider.displayName = 'MenuDivider'; var MenuHeader = /*#__PURE__*/styled.div( /*#__PURE__*/componentStylesMixin('MenuHeader'), sxMixin); MenuHeader.displayName = 'MenuHeader'; var MenuItem = /*#__PURE__*/styled.div( /*#__PURE__*/componentStylesMixin('MenuItem'), sxMixin); MenuItem.displayName = 'MenuItem'; var _excluded$j = ["children", "sx", "isOpen", "onClose", "size", "closeOnEsc", "closeOnOverlayClick", "disableFocusTrap"]; var Modal = function Modal(props) { var children = props.children, isOpen = props.isOpen, onClose = props.onClose, closeOnEsc = props.closeOnEsc, closeOnOverlayClick = props.closeOnOverlayClick, disableFocusTrap = props.disableFocusTrap, rest = _objectWithoutPropertiesLoose(props, _excluded$j); useKeyPress('Escape', function () { if (isOpen && closeOnEsc && onClose) { onClose(); } }); var onOverlayClick = useCallback(function (e) { if (e.target !== e.currentTarget) { return; } if (closeOnOverlayClick && onClose) { onClose(); } }, [closeOnOverlayClick, onClose]); useEffect(function () { if (isOpen && !document.body.classList.contains('noscroll')) { document.body.classList.add('noscroll'); } return function () { return document.body.classList.remove('noscroll'); }; }, [isOpen]); var style = useComponentStyles('Modal', props); return createElement(Overlay, { isOpen: isOpen, onClick: onOverlayClick }, createElement(FocusLock, { disabled: disableFocusTrap || !isOpen }, createElement(Box, Object.assign({ role: "dialog", "aria-modal": "true", sx: style }, rest), children))); }; Modal.defaultProps = { closeOnOverlayClick: true, size: 'md' }; Modal.displayName = 'Modal'; var _excluded$k = ["children", "sx"]; var ModalBody = function ModalBody(props) { var children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$k); var styles = useComponentStyles('ModalBody', props); return createElement(Box, Object.assign({ sx: styles }, rest), children); }; ModalBody.displayName = 'ModalBody'; var _excluded$l = ["sx"]; var ModalCloseButton = function ModalCloseButton(props) { var rest = _objectWithoutPropertiesLoose(props, _excluded$l); var styles = useComponentStyles('ModalCloseButton', props); return createElement(CloseButton, Object.assign({ sx: styles }, rest)); }; ModalCloseButton.displayName = 'ModalCloseButton'; var _excluded$m = ["children", "sx"]; var ModalFooter = function ModalFooter(props) { var children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$m); var styles = useComponentStyles('ModalFooter', props); return createElement(Box, Object.assign({ as: "footer", sx: styles }, rest), children); }; ModalFooter.displayName = 'ModalFooter'; var _excluded$n = ["children", "sx"]; var ModalHeader = function ModalHeader(props) { var children = props.children, rest = _objectWithoutPropertiesLoose(props, _excluded$n); var styles = useComponentStyles('ModalHeader', props); return createElement(Box, Object.assign({ as: "header", sx: styles }, rest), children); }; ModalHeader.displayName = 'ModalHeader'; var _excluded$o = ["children", "angle", "color", "isCapRound", "isIndeterminate", "max", "min", "trackColor", "thickness", "value"]; var Svg = /*#__PURE__*/styled.svg(sxMixin); var Circle = /*#__PURE__*/styled.circle(sxMixin); var CircularProgress = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, _props$angle = props.angle, angle = _props$angle === void 0 ? 0 : _props$angle, _props$color = props.color, color = _props$color === void 0 ? 'blue.500' : _props$color, _props$isCapRound = props.isCapRound, isCapRound = _props$isCapRound === void 0 ? false : _props$isCapRound, _props$isIndeterminat = props.isIndeterminate, isIndeterminate = _props$isIndeterminat === void 0 ? false : _props$isIndeterminat, _props$max = props.max, max = _props$max === void 0 ? 100 : _props$max, _props$min = props.min, min = _props$min === void 0 ? 0 : _props$min, _props$trackColor = props.trackColor, trackColor = _props$trackColor === void 0 ? 'gray.100' : _props$trackColor, _props$thickness = props.thickness, thickness = _props$thickness === void 0 ? 1 : _props$thickness, _props$value = props.value, value = _props$value === void 0 ? 0 : _props$value, rest = _objectWithoutPropertiesLoose(props, _excluded$o); var rootStyles = useComponentStyles('ProgressCircular', props); var svgStyles = useComponentStyles('ProgressCircularSvg', props); var shapeStyles = useComponentStyles('ProgressCircularShape', props); var innerStyles = useComponentStyles('ProgressCircularInner', props); var percent = Math.min(Math.max((value - min) * 100 / (max - min), min), max) / 100; return createElement(Box, Object.assign({ ref: ref, role: "progressbar", sx: rootStyles }, rest), createElement(Svg, { viewBox: "0 0 100 100", sx: svgStyles }, createElement(Circle, { cx: 50, cy: 50, r: 42, fill: "transparent", stroke: "currentColor", strokeWidth: 8 * thickness, sx: _extends({}, shapeStyles, { color: trackColor }) }), createElement(Circle, { cx: 50, cy: 50, r: 42, fill: "transparent", stroke: "currentColor", strokeWidth: 8 * thickness, strokeLinecap: isCapRound ? 'round' : undefined, strokeDasharray: Math.PI * 42 * 2 * percent + ", " + Math.PI * 42 * 2, transform: "rotate(" + (angle - 90) + ", 50, 50)", sx: _extends({}, shapeStyles, { color: color }) }, isIndeterminate && createElement(Fragment, null, createElement("animate", { attributeName: "stroke-dasharray", values: "1,400;400,400;400,400", dur: "2", repeatCount: "indefinite" }), createElement("animate", { attributeName: "stroke-dashoffset", values: "0;-100;-260", dur: "2", repeatCount: "indefinite" }), createElement("animateTransform", { attributeName: "transform", type: "rotate", from: "0 50 50", to: "360 50 50", dur: "2", repeatCount: "indefinite" })))), children && createElement(Box, { sx: innerStyles }, children)); }); CircularProgress.defaultProps = { size: '48px' }; CircularProgress.displayName = 'CircularProgress'; var _templateObject, _templateObject2; var progressKeyframe = /*#__PURE__*/keyframes(_templateObject || (_templateObject = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n 0% {\n margin-left: 0;\n margin-right: 100%;\n }\n\n 50% {\n margin-left: 25%;\n margin-right: 0;\n }\n\n 100% {\n margin-left: 100%;\n margin-right: 0%;\n }\n"]))); var ProgressAnimation = /*#__PURE__*/styled.div(_templateObject2 || (_templateObject2 = /*#__PURE__*/_taggedTemplateLiteralLoose(["\n /* ", " */\n\n display: none;\n"])), progressKeyframe); var _excluded$p = ["children", "isIndeterminate", "max", "min", "trackColor", "value"]; var HorizontalProgress = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, _props$isIndeterminat = props.isIndeterminate, isIndeterminate = _props$isIndeterminat === void 0 ? false : _props$isIndeterminat, _props$max = props.max, max = _props$max === void 0 ? 100 : _props$max, _props$min = props.min, min = _props$min === void 0 ? 0 : _props$min, _props$trackColor = props.trackColor, trackColor = _props$trackColor === void 0 ? 'gray.100' : _props$trackColor, _props$value = props.value, value = _props$value === void 0 ? 0 : _props$value, rest = _objectWithoutPropertiesLoose(props, _excluded$p); var rootStyles = useComponentStyles('ProgressHorizontal', props); var indeterminateInnerStyles = useComponentStyles('ProgressHorizontalIndeterminateInner', props); var innerStyles = useComponentStyles('ProgressHorizontalInner', props); return createElement(Box, Object.assign({ ref: ref, role: "progressbar", bg: trackColor, height: 4, sx: rootStyles }, rest), isIndeterminate ? createElement(Fragment, null, createElement(ProgressAnimation, null), createElement(Box, { animationName: progressKeyframe.getName(), sx: indeterminateInnerStyles })) : createElement(Box, { width: Math.min(Math.max((value - min) * 100 / (max - min), min), max) + "%", sx: innerStyles }, children)); }); HorizontalProgress.defaultProps = { color: 'blue.500' }; HorizontalProgress.displayName = 'HorizontalProgress'; var _excluded$q = ["isCircular"]; var Progress = /*#__PURE__*/forwardRef(function (_ref, ref) { var _ref$isCircular = _ref.isCircular, isCircular = _ref$isCircular === void 0 ? false : _ref$isCircular, rest = _objectWithoutPropertiesLoose(_ref, _excluded$q); return isCircular ? createElement(CircularProgress, Object.assign({ ref: ref }, rest)) : createElement(HorizontalProgress, Object.assign({ ref: ref }, rest)); }); Progress.displayName = 'Progress'; var _excluded$r = ["id", "name", "value", "label", "checked", "isDisabled", "isInvalid", "color", "size"]; var Radio = /*#__PURE__*/forwardRef(function (props, ref) { var id = props.id, name = props.name, value = props.value, label = props.label, checked = props.checked, isDisabled = props.isDisabled, rest = _objectWithoutPropertiesLoose(props, _excluded$r); var outerStyles = useComponentStyles('RadioOuter', props); var inputStyles = useComponentStyles('RadioInput', props); var labelStyles = useComponentStyles('RadioLabel', props); return createElement(Box, { as: "label", htmlFor: id, sx: outerStyles }, createElement(Box, Object.assign({ ref: ref, as: "input", type: "radio", id: id, name: name, value: value, defaultChecked: checked, "data-checked": !checked ? undefined : checked, disabled: isDisabled, sx: inputStyles }, rest)), label && createElement(Text, { as: "div", fontSize: "inherit", lineHeight: "inherit", sx: labelStyles }, label)); }); Radio.defaultProps = { color: 'blue', size: 'md' }; Radio.displayName = 'Radio'; var _excluded$s = ["children", "sx", "flexDir", "flexDirection", "direction", "align", "justify", "wrap", "spacing", "shouldWrapChildren", "divider"]; function responsive(prop, mapper) { if (Array.isArray(prop)) { return prop.map(function (item) { if (item === null) { return null; } return mapper(item); }); } var type = typeof prop; // isObject check if ((type === 'function' || type === 'object') && !!prop) { var result = {}; Object.keys(prop).forEach(function (key) { result[key] = mapper(prop[key]); }); return result; } if (prop != null) { return mapper(prop); } return null; } var Stack = /*#__PURE__*/forwardRef(function (props, ref) { var children = props.children, sx = props.sx, flexDir = props.flexDir, flexDirection = props.flexDirection, _props$direction = props.direction, direction = _props$direction === void 0 ? 'column' : _props$direction, align = props.align, justify = props.justify, wrap = props.wrap, spacing = props.spacing, shouldWrapChildren = props.shouldWrapChildren, dividerComponent = props.divider, rest = _objectWithoutPropertiesLoose(props, _excluded$s); var _direction = flexDir || flexDirection || direction; var stackStyle = useMemo(function () { var directions = { row: { marginLeft: spacing, marginTop: 0 }, column: { marginTop: spacing, marginLeft: 0 }, 'row-reverse': { marginRight: spacing, marginBottom: 0 }, 'column-reverse': { marginBottom: spacing, marginRight: 0 } }; return { '& > * ~ *': responsive(_direction, function (v) { return directions[v]; }) }; }, [_direction, spacing]); var dividerStyle = useMemo(function () { var dividers = { row: { my: 0, mx: spacing }, column: { my: spacing, mx: 0 }, 'row-reverse': { my: 0, mx: spacing }, 'column-reverse': { my: spacing, mx: 0 } }; return { '&': responsive(_direction, function (v) { return dividers[v]; }) }; }, [_direction, spacing]); var validChildren = Children.toArray(children).filter(function (child) { return isValidElement(child); }); var styles = useMemo(function () { return !dividerComponent ? _extends({}, stackStyle, sx) : sx; }, [dividerComponent, stackStyle, sx]); return createElement(Box, Object.assign({ ref: ref, display: "flex", alignItems: align, justifyContent: justify, flexDirection: _direction, flexWrap: wrap, sx: styles }, rest), !shouldWrapChildren && !dividerComponent ? validChildren : validChildren.map(function (element, index) { var child = shouldWrapChildren ? // eslint-disable-next-line react/no-array-index-key createElement(Box, { key: "stack-child-" + index }, element) : element; if (!dividerComponent) { return child; } var divider = index + 1 !== validChildren.length ? cloneElement(dividerComponent, { sx: dividerStyle }) : null; return (// eslint-disable-next-line react/no-array-index-key createElement(Fragment, { key: "stack-fragment-" + index }, child, divider) ); })); }); Stack.displayName = 'Stack'; var _excluded$t = ["icon", "sx"]; function defaultItemToString(item) { return item ? item.label : ''; } function defaultRenderItem(item, fallback) { if (fallback === void 0) { fallback = null; } if (!item && fallback) { return createElement(Text, { as: "span", color: "gray.400", userSelect: "none" }, fallback); } return item ? createElement(Text, { as: "span", userSelect: "none" }, item.label) : null; } var SelectText = function SelectText(_ref) { var label = _ref.label, sx = _ref.sx; return createElement(Flex, { py: 4, align: "center", justify: "center" }, createElement(Text, { as: "span", userSelect: "none", sx: sx }, label)); }; var SelectIcon = function SelectIcon(_ref2) { var icon = _ref2.icon, sx = _ref2.sx, rest = _objectWithoutPropertiesLoose(_ref2, _excluded$t); return createElement(Text, Object.assign({ as: "span", sx: sx }, rest), icon); }; var defaultI18n = { loading: 'Loading...', noItems: 'No items' }; var Motion$2 = /*#__PURE__*/styled(motion.div)(sxMixin); var variants$2 = { hidden: { opacity: 0, pointerEvents: 'none', transition: { duration: 0.3 } }, visible: { opacity: 1, pointerEvents: 'auto', transition: { duration: 0.2 } } }; var Select = function Select(_ref3) { var searchValue = _ref3.searchValue, onSearchChange = _ref3.onSearchChange, items = _ref3.items, _ref3$itemToString = _ref3.itemToString, itemToString = _ref3$itemToString === void 0 ? defaultItemToString : _ref3$itemToString, _ref3$renderItem = _ref3.renderItem, renderItem = _ref3$renderItem === void 0 ? defaultRenderItem : _ref3$renderItem, value = _ref3.value, onChange = _ref3.onChange, isClearable = _ref3.isClearable, isDisabled = _ref3.isDisabled, isInvalid = _ref3.isInvalid, isLoading = _ref3.isLoading, isSearchable = _ref3.isSearchable, autoFocus = _ref3.autoFocus, placeholder = _ref3.placeholder, size = _ref3.size, variant = _ref3.variant, i18n = _ref3.i18n; var localization = _extends({}, defaultI18n, i18n); var onSelectedItemChange = useCallback(function (changes) { if (changes.selectedItem) { onChange(changes.selectedItem); } }, [onChange]); var onSearchValueChange = useCallback(function (changes) { if (onSearchChange && changes.inputValue !== undefined && changes.inputValue !== null) { onSearchChange(changes.inputValue); } }, [onSearchChange]); var _useCombobox = useCombobox({ items: items, selectedItem: value, onSelectedItemChange: onSelectedItemChange, itemToString: itemToString, inputValue: searchValue, onInputValueChange: onSearchValueChange }), isOpen = _useCombobox.isOpen, selectedItem = _useCombobox.selectedItem, getComboboxProps = _useCombobox.getComboboxProps, getToggleButtonProps = _useCombobox.getToggleButtonProps, getInputProps = _useCombobox.getInputProps, getMenuProps = _useCombobox.getMenuProps, getItemProps = _useCombobox.getItemProps, setInputValue = _useCombobox.setInputValue, highlightedIndex = _useCombobox.highlightedIndex, closeMenu = _useCombobox.closeMenu; var _usePopper = usePopper({ isOpen: isOpen, offset: [0, 8] }), triggerProps = _usePopper.triggerProps, childProps = _usePopper.childProps; var onClear = useCallback(function (e) { e.stopPropagation(); if (isOpen) { closeMenu(); } setInputValue(''); onChange(null); }, [closeMenu, isOpen, onChange, setInputValue]); var comboboxProps = getComboboxProps(); var toggleButtonProps = getToggleButtonProps(); var inputProps = getInputProps({}, { suppressRefError: true }); var menuProps = getMenuProps({}, { suppressRefError: true }); var menuStyles = useComponentStyles('Menu', { isFullWidth: true, size: size, variant: variant }); var textStyles = useComponentStyles('SelectText', { size: size, variant: variant }); var iconStyles = useComponentStyles('SelectIcon', { size: size, variant: variant }); return createElement(Box, Object.assign({ pos: "relative" }, comboboxProps), createElement(Input, Object.assign({ as: "button", type: "button", isDisabled: isDisabled, isInvalid: isInvalid, size: size, variant: variant, autoFocus: autoFocus }, triggerProps, toggleButtonProps, { ref: mergeRefs([triggerProps.ref, toggleButtonProps.ref]) }), createElement(Flex, { pr: 2, flex: "1 1 0%" }, isSearchable ? createElement(Input, Object.assign({ isDisabled: isDisabled, placeholder: placeholder, variant: "unstyled", sx: { boxShadow: 'none !important' } }, inputProps)) : renderItem(selectedItem, placeholder)), createElement(Stack, { spacing: 2, direction: "row", align: "center", flexShrink: 0 }, isLoading && createElement(Spinner, { color: "gray.400", size: siz