prevents 's negative margins from collapsing when used in a flex container
+ // which will render the track with the wrong height
+ React__namespace.createElement("div", null, /*#__PURE__*/React__namespace.createElement(react.TabList, _objectSpread2({
+ store: tabStore,
+ render: /*#__PURE__*/React__namespace.createElement(Box$1, {
+ position: "relative",
+ width: "maxContent"
+ })
+ }, props), /*#__PURE__*/React__namespace.createElement(Box$1, {
+ className: [modules_40c67f5b.track, modules_40c67f5b["track-" + variant]]
+ }), /*#__PURE__*/React__namespace.createElement(Inline, {
+ space: space
+ }, children)))
+ );
+}
+/**
+ * Used to define the content to be rendered when a tab is active. Each `` must have a
+ * corresponding `` component.
+ */
+
+
+const TabPanel = /*#__PURE__*/React__namespace.forwardRef(function TabPanel(_ref3, ref) {
+ let {
+ children,
+ id,
+ renderMode = 'always'
+ } = _ref3,
+ props = _objectWithoutProperties(_ref3, _excluded2$1);
+
+ const tabContextValue = React__namespace.useContext(TabsContext);
+ const [tabRendered, setTabRendered] = React__namespace.useState(false);
+ const selectedId = tabContextValue == null ? void 0 : tabContextValue.tabStore.useState('selectedId');
+ const tabIsActive = selectedId === id;
+ React__namespace.useEffect(function trackTabRenderedState() {
+ if (!tabRendered && tabIsActive) {
+ setTabRendered(true);
+ }
+ }, [tabRendered, tabIsActive]);
+
+ if (!tabContextValue) {
+ return null;
+ }
+
+ const {
+ tabStore
+ } = tabContextValue;
+ const shouldRender = renderMode === 'always' || renderMode === 'active' && tabIsActive || renderMode === 'lazy' && (tabIsActive || tabRendered);
+ return shouldRender ? /*#__PURE__*/React__namespace.createElement(react.TabPanel, _objectSpread2(_objectSpread2({}, props), {}, {
+ tabId: id,
+ store: tabStore,
+ ref: ref
+ }), children) : null;
+});
+/**
+ * Allows content to be rendered based on the current tab being selected while outside of the
+ * TabPanel component. Can be placed freely within the main `` component.
+ */
+
+function TabAwareSlot({
+ children
+}) {
+ const tabContextValue = React__namespace.useContext(TabsContext);
+ const selectedId = tabContextValue == null ? void 0 : tabContextValue.tabStore.useState('selectedId');
+ return tabContextValue ? children({
+ selectedId
+ }) : null;
+}
+
+const _excluded$4 = ["children", "onItemSelect"],
+ _excluded2 = ["exceptionallySetClassName"],
+ _excluded3 = ["render"],
+ _excluded4 = ["exceptionallySetClassName", "modal"],
+ _excluded5 = ["value", "children", "onSelect", "hideOnSelect", "onClick", "exceptionallySetClassName"],
+ _excluded6 = ["label", "children", "exceptionallySetClassName"];
+const MenuContext = /*#__PURE__*/React__namespace.createContext({
+ menuStore: null,
+ handleItemSelect: () => undefined,
+ getAnchorRect: null,
+ setAnchorRect: () => undefined
+});
+/**
+ * Wrapper component to control a menu. It does not render anything, only providing the state
+ * management for the menu components inside it.
+ */
+
+function Menu(_ref) {
+ let {
+ children,
+ onItemSelect
+ } = _ref,
+ props = _objectWithoutProperties(_ref, _excluded$4);
+
+ const [anchorRect, setAnchorRect] = React__namespace.useState(null);
+ const getAnchorRect = React__namespace.useMemo(() => anchorRect ? () => anchorRect : null, [anchorRect]);
+ const menuStore = react.useMenuStore(_objectSpread2({
+ focusLoop: true
+ }, props));
+ const value = React__namespace.useMemo(() => ({
+ menuStore,
+ handleItemSelect: onItemSelect,
+ getAnchorRect,
+ setAnchorRect
+ }), [menuStore, onItemSelect, getAnchorRect, setAnchorRect]);
+ return /*#__PURE__*/React__namespace.createElement(MenuContext.Provider, {
+ value: value
+ }, children);
+}
+/**
+ * A button to toggle a dropdown menu open or closed.
+ */
+
+
+const MenuButton = /*#__PURE__*/React__namespace.forwardRef(function MenuButton(_ref2, ref) {
+ let {
+ exceptionallySetClassName
+ } = _ref2,
+ props = _objectWithoutProperties(_ref2, _excluded2);
+
+ const {
+ menuStore
+ } = React__namespace.useContext(MenuContext);
+
+ if (!menuStore) {
+ throw new Error('MenuButton must be wrapped in ');
+ }
+
+ return /*#__PURE__*/React__namespace.createElement(react.MenuButton, _objectSpread2(_objectSpread2({}, props), {}, {
+ store: menuStore,
+ ref: ref,
+ className: classNames__default["default"]('reactist_menubutton', exceptionallySetClassName)
+ }));
+});
+const ContextMenuTrigger = /*#__PURE__*/React__namespace.forwardRef(function ContextMenuTrigger(_ref3, ref) {
+ let {
+ render
+ } = _ref3,
+ props = _objectWithoutProperties(_ref3, _excluded3);
+
+ const {
+ setAnchorRect,
+ menuStore
+ } = React__namespace.useContext(MenuContext);
+
+ if (!menuStore) {
+ throw new Error('ContextMenuTrigger must be wrapped in ');
+ }
+
+ const handleContextMenu = React__namespace.useCallback(function handleContextMenu(event) {
+ event.preventDefault();
+ setAnchorRect({
+ x: event.clientX,
+ y: event.clientY
+ });
+ menuStore.show();
+ }, [setAnchorRect, menuStore]);
+ const isOpen = menuStore.useState('open');
+ React__namespace.useEffect(() => {
+ if (!isOpen) setAnchorRect(null);
+ }, [isOpen, setAnchorRect]);
+ return /*#__PURE__*/React__namespace.createElement(react.Role.div, _objectSpread2(_objectSpread2({}, props), {}, {
+ onContextMenu: handleContextMenu,
+ ref: ref,
+ render: render
+ }));
+});
+/**
+ * The dropdown menu itself, containing a list of menu items.
+ */
+
+const MenuList = /*#__PURE__*/React__namespace.forwardRef(function MenuList(_ref4, ref) {
+ let {
+ exceptionallySetClassName,
+ modal = true
+ } = _ref4,
+ props = _objectWithoutProperties(_ref4, _excluded4);
+
+ const {
+ menuStore,
+ getAnchorRect
+ } = React__namespace.useContext(MenuContext);
+
+ if (!menuStore) {
+ throw new Error('MenuList must be wrapped in ');
+ }
+
+ const isOpen = menuStore.useState('open');
+ return isOpen ? /*#__PURE__*/React__namespace.createElement(react.Portal, {
+ preserveTabOrder: true
+ }, /*#__PURE__*/React__namespace.createElement(react.Menu, _objectSpread2(_objectSpread2({}, props), {}, {
+ store: menuStore,
+ gutter: 8,
+ shift: 4,
+ ref: ref,
+ className: classNames__default["default"]('reactist_menulist', exceptionallySetClassName),
+ getAnchorRect: getAnchorRect != null ? getAnchorRect : undefined,
+ modal: modal
+ }))) : null;
+});
+/**
+ * A menu item inside a menu list. It can be selected by the user, triggering the `onSelect`
+ * callback.
+ */
+
+const MenuItem = /*#__PURE__*/React__namespace.forwardRef(function MenuItem(_ref5, ref) {
+ let {
+ value,
+ children,
+ onSelect,
+ hideOnSelect = true,
+ onClick,
+ exceptionallySetClassName
+ } = _ref5,
+ props = _objectWithoutProperties(_ref5, _excluded5);
+
+ const {
+ handleItemSelect,
+ menuStore
+ } = React__namespace.useContext(MenuContext);
+
+ if (!menuStore) {
+ throw new Error('MenuItem must be wrapped in ');
+ }
+
+ const {
+ hide
+ } = menuStore;
+ const handleClick = React__namespace.useCallback(function handleClick(event) {
+ onClick == null ? void 0 : onClick(event);
+ const onSelectResult = onSelect && !event.defaultPrevented ? onSelect() : undefined;
+ const shouldClose = onSelectResult !== false && hideOnSelect;
+ handleItemSelect == null ? void 0 : handleItemSelect(value);
+ if (shouldClose) hide();
+ }, [onSelect, onClick, handleItemSelect, hideOnSelect, hide, value]);
+ return /*#__PURE__*/React__namespace.createElement(react.MenuItem, _objectSpread2(_objectSpread2({}, props), {}, {
+ store: menuStore,
+ ref: ref,
+ onClick: handleClick,
+ className: exceptionallySetClassName,
+ hideOnClick: false
+ }), children);
+});
+/**
+ * This component can be rendered alongside other `MenuItem` inside a `MenuList` in order to have
+ * a sub-menu.
+ *
+ * Its children are expected to have the structure of a first level menu (a `MenuButton` and a
+ * `MenuList`).
+ *
+ * ```jsx
+ *
+ *
+ * More options
+ *
+ *
+ *
+ *
+ *
+ * ```
+ *
+ * The `MenuButton` will become a menu item in the current menu items list, and it will lead to
+ * opening a sub-menu with the menu items list below it.
+ */
+
+const SubMenu = /*#__PURE__*/React__namespace.forwardRef(function SubMenu({
+ children,
+ onItemSelect
+}, ref) {
+ const {
+ handleItemSelect: parentMenuItemSelect,
+ menuStore
+ } = React__namespace.useContext(MenuContext);
+
+ if (!menuStore) {
+ throw new Error('SubMenu must be wrapped in ');
+ }
+
+ const {
+ hide: parentMenuHide
+ } = menuStore;
+ const handleSubItemSelect = React__namespace.useCallback(function handleSubItemSelect(value) {
+ onItemSelect == null ? void 0 : onItemSelect(value);
+ parentMenuItemSelect == null ? void 0 : parentMenuItemSelect(value);
+ parentMenuHide();
+ }, [parentMenuHide, parentMenuItemSelect, onItemSelect]);
+ const [button, list] = React__namespace.Children.toArray(children);
+ const buttonElement = button;
+ return /*#__PURE__*/React__namespace.createElement(Menu, {
+ onItemSelect: handleSubItemSelect
+ }, /*#__PURE__*/React__namespace.createElement(react.MenuItem, {
+ store: menuStore,
+ ref: ref,
+ hideOnClick: false,
+ render: buttonElement
+ }, buttonElement.props.children), list);
+});
+/**
+ * A way to semantically group some menu items.
+ *
+ * This group does not add any visual separator. You can do that yourself adding `` elements
+ * before and/or after the group if you so wish.
+ */
+
+const MenuGroup = /*#__PURE__*/React__namespace.forwardRef(function MenuGroup(_ref6, ref) {
+ let {
+ label,
+ children,
+ exceptionallySetClassName
+ } = _ref6,
+ props = _objectWithoutProperties(_ref6, _excluded6);
+
+ const {
+ menuStore
+ } = React__namespace.useContext(MenuContext);
+
+ if (!menuStore) {
+ throw new Error('MenuGroup must be wrapped in ');
+ }
+
+ return /*#__PURE__*/React__namespace.createElement(react.MenuGroup, _objectSpread2(_objectSpread2({}, props), {}, {
+ ref: ref,
+ store: menuStore,
+ className: exceptionallySetClassName
+ }), label ? /*#__PURE__*/React__namespace.createElement("div", {
+ role: "presentation",
+ className: "reactist_menugroup__label"
+ }, label) : null, children);
+});
+
+const _excluded$3 = ["type", "variant", "size", "loading", "disabled", "tooltip", "onClick", "children"];
+/**
+ * @deprecated
+ */
+
+const Button = /*#__PURE__*/React__namespace.forwardRef(function Button(_ref, ref) {
+ let {
+ type = 'button',
+ variant,
+ size = 'default',
+ loading = false,
+ disabled = false,
+ tooltip,
+ onClick,
+ children
+ } = _ref,
+ props = _objectWithoutProperties(_ref, _excluded$3);
+
+ const className = classNames__default["default"]('reactist_button', variant ? "reactist_button--" + variant : null, size !== 'default' ? "reactist_button--" + size : null, {
+ 'reactist_button--loading': loading
+ }, props.className);
+ const button = /*#__PURE__*/React__namespace.createElement("button", _objectSpread2(_objectSpread2({}, props), {}, {
+ ref: ref,
+ type: type,
+ className: className,
+ "aria-disabled": disabled || loading,
+ onClick: disabled || loading ? undefined : onClick
+ }), children);
+ return tooltip ? /*#__PURE__*/React__namespace.createElement(Tooltip, {
+ content: tooltip
+ }, button) : button;
+});
+Button.displayName = 'Button';
+Button.defaultProps = {
+ size: 'default',
+ loading: false,
+ disabled: false
+};
+
+const _excluded$2 = ["children", "onClick", "tooltip", "className"];
+
+class Box extends React__namespace.Component {
+ constructor(props, context) {
+ super(props, context);
+ this._timeout = void 0;
+
+ this._handleClickOutside = event => {
+ const dropdownDOMNode = ReactDOM__default["default"].findDOMNode(this);
+ if (dropdownDOMNode && !dropdownDOMNode.contains(event.target)) this._toggleShowBody();else if (!this.props.allowBodyInteractions) {
+ // won't close when body interactions are allowed
+ this._timeout = setTimeout(() => {
+ if (this.state.showBody) {
+ this._toggleShowBody();
+ }
+ }, 100);
+ }
+ };
+
+ this._toggleShowBody = () => {
+ if (!this.state.showBody) {
+ // will show
+ if (this.props.onShowBody) this.props.onShowBody();
+ document.addEventListener('click', this._handleClickOutside, true);
+ } else {
+ // will hide
+ if (this.props.onHideBody) this.props.onHideBody();
+ document.removeEventListener('click', this._handleClickOutside, true);
+ }
+
+ this.setState({
+ showBody: !this.state.showBody
+ });
+ };
+
+ this._setPosition = body => {
+ if (body) {
+ const scrollingParent = document.getElementById(this.props.scrolling_parent ? this.props.scrolling_parent : '');
+
+ if (scrollingParent) {
+ const dropdown = ReactDOM__default["default"].findDOMNode(this);
+
+ if (!dropdown) {
+ return;
+ }
+
+ const dropdownVerticalPosition = ReactDOM__default["default"].findDOMNode(this).offsetTop;
+ const dropdownTrigger = dropdown.querySelector('.trigger');
+
+ if (!dropdownTrigger) {
+ return;
+ }
+
+ const dropdownTriggerHeight = dropdownTrigger.clientHeight;
+ const dropdownBodyHeight = body.clientHeight;
+ const scrollingParentHeight = scrollingParent.clientHeight;
+ const scrollingParentOffset = scrollingParent.scrollTop;
+ const bottomOffset = scrollingParentHeight + scrollingParentOffset - dropdownVerticalPosition - dropdownTriggerHeight;
+ const top = bottomOffset < dropdownBodyHeight;
+
+ if (top !== this.state.top) {
+ this.setState({
+ top
+ });
+ }
+ }
+ }
+ };
+
+ this.state = {
+ showBody: false,
+ top: props.top || false
+ };
+ this._timeout = undefined;
+ }
+
+ componentWillUnmount() {
+ document.removeEventListener('click', this._handleClickOutside, true);
+
+ if (this._timeout) {
+ clearTimeout(this._timeout);
+ }
+ }
+
+ _getTriggerComponent() {
+ var _this$props$children;
+
+ const _trigger = (_this$props$children = this.props.children) == null ? void 0 : _this$props$children[0];
+
+ return _trigger ? /*#__PURE__*/React__namespace.cloneElement(_trigger, {
+ onClick: this._toggleShowBody
+ }) : undefined;
+ } // https://facebook.github.io/react/docs/refs-and-the-dom.html#exposing-dom-refs-to-parent-components
+
+
+ _getBodyComponent() {
+ if (!this.state.showBody) {
+ return null;
+ }
+
+ const {
+ top
+ } = this.state;
+ const {
+ right = false,
+ children
+ } = this.props;
+ const props = {
+ top,
+ right,
+ setPosition: this._setPosition
+ };
+ const className = classNames__default["default"]({
+ body_wrapper: true,
+ with_arrow: true,
+ top: top,
+ bottom: !top
+ });
+ const body = children == null ? void 0 : children[1];
+ const contentMarkup = typeof body === 'function' ? body(props) : body ? /*#__PURE__*/React__namespace.cloneElement(body, props) : undefined;
+ return /*#__PURE__*/React__namespace.createElement("div", {
+ className: className,
+ style: {
+ position: 'relative'
+ }
+ }, contentMarkup);
+ }
+
+ render() {
+ const className = classNames__default["default"]('reactist_dropdown', this.props.className);
+ const {
+ top
+ } = this.state;
+ return /*#__PURE__*/React__namespace.createElement("div", {
+ style: {
+ display: 'inline-block'
+ },
+ className: className,
+ "data-testid": "reactist-dropdown-box"
+ }, top && this._getBodyComponent(), this._getTriggerComponent(), !top && this._getBodyComponent());
+ }
+
+}
+
+Box.displayName = void 0;
+Box.displayName = 'Dropdown.Box';
+const Trigger = /*#__PURE__*/React__namespace.forwardRef(function Trigger(_ref, ref) {
+ let {
+ children,
+ onClick,
+ tooltip,
+ className
+ } = _ref,
+ props = _objectWithoutProperties(_ref, _excluded$2);
+
+ function handleClick(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ if (onClick) onClick(event);
+ }
+
+ return /*#__PURE__*/React__namespace.createElement(Button, _objectSpread2(_objectSpread2({}, props), {}, {
+ className: classNames__default["default"]('trigger', className),
+ onClick: handleClick,
+ tooltip: tooltip,
+ ref: ref
+ }), children);
+});
+Trigger.displayName = 'Dropdown.Trigger';
+
+function Body({
+ top,
+ right,
+ children,
+ setPosition
+}) {
+ const style = {
+ position: 'absolute',
+ right: 0,
+ top: 0
+ };
+
+ if (top) {
+ style.top = 'auto';
+ style.bottom = 0;
+ }
+
+ if (right) {
+ style.right = 'auto';
+ style.left = 0;
+ }
+
+ return /*#__PURE__*/React__namespace.createElement("div", {
+ ref: setPosition,
+ style: style,
+ className: "body",
+ id: "reactist-dropdown-body",
+ "data-testid": "reactist-dropdown-body"
+ }, children);
+}
+
+Body.displayName = 'Dropdown.Body';
+const Dropdown = {
+ Box,
+ Trigger,
+ Body
+};
+
+const COLORS = ['#606060', '#4A90E2', '#03B3B2', '#008299', '#82BA00', '#D24726', '#AC193D', '#DC4FAD', '#3BD5FB', '#74E8D3', '#FFCC00', '#FB886E', '#CCCCCC'];
+
+const _isNamedColor = color => typeof color !== 'string';
+
+const _getColor = (colorList, colorIndex) => {
+ const index = colorIndex >= colorList.length ? 0 : colorIndex;
+ return colorList[index];
+};
+
+function ColorPicker({
+ color = 0,
+ small,
+ onChange,
+ colorList = COLORS
+}) {
+ return /*#__PURE__*/React__namespace.createElement(Dropdown.Box, {
+ right: true,
+ className: "reactist_color_picker"
+ }, /*#__PURE__*/React__namespace.createElement(Dropdown.Trigger, null, (() => {
+ const backgroundColor = _getColor(colorList, color);
+
+ return /*#__PURE__*/React__namespace.createElement("span", {
+ className: classNames__default["default"]('color_trigger', {
+ small
+ }),
+ style: {
+ backgroundColor: _isNamedColor(backgroundColor) ? backgroundColor.color : backgroundColor
+ }
+ }, /*#__PURE__*/React__namespace.createElement("span", {
+ className: "color_trigger--inner_ring"
+ }));
+ })()), /*#__PURE__*/React__namespace.createElement(Dropdown.Body, null, /*#__PURE__*/React__namespace.createElement("div", {
+ className: "color_options"
+ }, colorList.reduce((items, currentColor, currentIndex) => {
+ items.push( /*#__PURE__*/React__namespace.createElement(ColorItem, {
+ isActive: color >= colorList.length ? currentIndex === 0 : currentIndex === color,
+ key: currentIndex,
+ color: _isNamedColor(currentColor) ? currentColor.color : currentColor,
+ colorIndex: currentIndex,
+ onClick: onChange,
+ tooltip: _isNamedColor(currentColor) ? currentColor.name : null
+ }));
+ return items;
+ }, []))));
+}
+
+ColorPicker.displayName = 'ColorPicker';
+
+function ColorItem({
+ color,
+ colorIndex,
+ isActive,
+ onClick,
+ tooltip
+}) {
+ const item = /*#__PURE__*/React__namespace.createElement("span", {
+ "data-testid": "reactist-color-item",
+ className: 'reactist color_item' + (isActive ? ' active' : ''),
+ style: {
+ backgroundColor: color
+ },
+ onClick: () => onClick == null ? void 0 : onClick(colorIndex)
+ }, /*#__PURE__*/React__namespace.createElement("span", {
+ className: "color_item--inner_ring"
+ }));
+ return tooltip ? /*#__PURE__*/React__namespace.createElement(Tooltip, {
+ content: tooltip
+ }, item) : item;
+}
+
+ColorItem.displayName = 'ColorItem';
+
+const _excluded$1 = ["children", "className", "translateKey", "isMac"];
+// Support for setting up how to translate modifiers globally.
+//
+
+let globalTranslateKey = key => key;
+
+KeyboardShortcut.setTranslateKey = tr => {
+ globalTranslateKey = tr;
+};
+
+function translateKeyMac(key) {
+ switch (key.toLowerCase()) {
+ case 'cmd':
+ case 'mod':
+ return '⌘';
+
+ case 'control':
+ case 'ctrl':
+ return '⌃';
+
+ case 'alt':
+ return '⌥';
+
+ case 'shift':
+ return '⇧';
+
+ case 'space':
+ return '␣';
+
+ default:
+ return key;
+ }
+} //
+// Some helpers
+//
+
+
+function capitalize(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
+}
+
+function hasModifiers(str) {
+ return /\b(mod|cmd|ctrl|control|alt|shift)\b/i.test(str);
+}
+
+function isSpecialKey(str) {
+ return /^(mod|cmd|ctrl|control|alt|shift|space|super)$/i.test(str);
+}
+
+function parseKeys(shortcut, isMac, translateKey) {
+ const t = isMac ? translateKeyMac : translateKey;
+
+ const _hasModifiers = hasModifiers(shortcut);
+
+ function mapIndividualKey(str) {
+ if (isSpecialKey(str)) {
+ return capitalize(t(str));
+ }
+
+ if (_hasModifiers && str.length === 1) {
+ return str.toUpperCase();
+ }
+
+ return str;
+ }
+
+ if (!isMac) {
+ shortcut = shortcut.replace(/\b(mod|cmd)\b/i, 'ctrl');
+ }
+
+ return shortcut.split(/\s*\+\s*/).map(mapIndividualKey);
+}
+
+function KeyboardShortcut(_ref) {
+ var _navigator$platform$t, _navigator$platform;
+
+ let {
+ children,
+ className,
+ translateKey = globalTranslateKey,
+ isMac = (_navigator$platform$t = (_navigator$platform = navigator.platform) == null ? void 0 : _navigator$platform.toUpperCase().includes('MAC')) != null ? _navigator$platform$t : false
+ } = _ref,
+ props = _objectWithoutProperties(_ref, _excluded$1);
+
+ const shortcuts = typeof children === 'string' ? [children] : children;
+ return /*#__PURE__*/React__namespace.createElement("span", _objectSpread2({
+ className: classNames__default["default"]('reactist_keyboard_shortcut', className, {
+ 'reactist_keyboard_shortcut--macos': isMac
+ })
+ }, props), shortcuts.map((shortcut, i) => /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, {
+ key: i
+ }, i === 0 ? null : ', ', /*#__PURE__*/React__namespace.createElement("kbd", null, parseKeys(shortcut, isMac, translateKey).map((key, j) => /*#__PURE__*/React__namespace.createElement("kbd", {
+ key: j
+ }, key))))));
+}
+
+const SUPPORTED_KEYS = {
+ ARROW_UP: 'ArrowUp',
+ ARROW_RIGHT: 'ArrowRight',
+ ARROW_DOWN: 'ArrowDown',
+ ARROW_LEFT: 'ArrowLeft',
+ ENTER: 'Enter',
+ BACKSPACE: 'Backspace',
+ ESCAPE: 'Escape'
+};
+const KeyCapturerResolver = {
+ resolveByKey(eventKey) {
+ switch (eventKey) {
+ case 'Left': // IE specific
+
+ case 'ArrowLeft':
+ {
+ return 'ArrowLeft';
+ }
+
+ case 'Up': // IE specific
+
+ case 'ArrowUp':
+ {
+ return 'ArrowUp';
+ }
+
+ case 'Right': // IE specific
+
+ case 'ArrowRight':
+ {
+ return 'ArrowRight';
+ }
+
+ case 'Down': // IE specific
+
+ case 'ArrowDown':
+ {
+ return 'ArrowDown';
+ }
+
+ case 'Enter':
+ {
+ return 'Enter';
+ }
+
+ case 'Backspace':
+ {
+ return 'Backspace';
+ }
+
+ case 'Esc': // IE specific
+
+ case 'Escape':
+ {
+ return 'Escape';
+ }
+
+ default:
+ {
+ return null;
+ }
+ }
+ },
+
+ resolveByKeyCode(keyCode) {
+ switch (keyCode) {
+ case 37:
+ {
+ return 'ArrowLeft';
+ }
+
+ case 38:
+ {
+ return 'ArrowUp';
+ }
+
+ case 39:
+ {
+ return 'ArrowRight';
+ }
+
+ case 40:
+ {
+ return 'ArrowDown';
+ }
+
+ case 13:
+ {
+ return 'Enter';
+ }
+
+ case 8:
+ {
+ return 'Backspace';
+ }
+
+ case 27:
+ {
+ return 'Escape';
+ }
+
+ default:
+ {
+ return null;
+ }
+ }
+ }
+
+};
+const keyEventHandlerMapping = {
+ ArrowUp: 'onArrowUp',
+ ArrowDown: 'onArrowDown',
+ ArrowLeft: 'onArrowLeft',
+ ArrowRight: 'onArrowRight',
+ Enter: 'onEnter',
+ Backspace: 'onBackspace',
+ Escape: 'onEscape'
+};
+const keyPropagatePropMapping = {
+ ArrowUp: 'propagateArrowUp',
+ ArrowDown: 'propagateArrowDown',
+ ArrowLeft: 'propagateArrowLeft',
+ ArrowRight: 'propagateArrowRight',
+ Enter: 'propagateEnter',
+ Backspace: 'propagateBackspace',
+ Escape: 'propagateEscape'
+};
+/**
+ * Use this component to wrap anything you want to handle key events for (e.g. an input).
+ * You can specify the `eventName` to capture (defaults to `onKeyDown`).
+ * Check the SUPPORTED_KEYS map to see which keys are supported and supply the respective
+ * `on${Key}` prop (i.e. `onEnter` or `onArrowDown`).
+ * If you want the default behaviour to be preserved (i.e. only want to hook into the event
+ * instead of replacing it) set the `propagate${Key}` prop (e.g. propagateBackspace).
+ */
+
+function KeyCapturer(props) {
+ const {
+ children,
+ eventName = 'onKeyDown'
+ } = props;
+ const composingRef = React__namespace.useRef(false);
+ const composingEventHandlers = props.onEnter ? {
+ onCompositionStart: () => {
+ composingRef.current = true;
+ },
+ onCompositionEnd: () => {
+ composingRef.current = false;
+ }
+ } : undefined;
+
+ function handleKeyEvent(event) {
+ // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
+ const key = event.key !== undefined ? KeyCapturerResolver.resolveByKey(event.key) : KeyCapturerResolver.resolveByKeyCode(event.keyCode);
+ if (!key) return;
+ const propagateEvent = props[keyPropagatePropMapping[key]] || false;
+ const eventHandler = props[keyEventHandlerMapping[key]];
+
+ if (key === 'Enter' && eventHandler) {
+ if (composingRef.current || // Safari fires the onCompositionEnd event before the keydown event, so we
+ // have to rely on the 229 keycode, which is Enter when fired from an IME
+ // https://www.w3.org/TR/uievents/#determine-keydown-keyup-keyCode
+ (event.keyCode || event.which) === 229) {
+ return;
+ }
+ }
+
+ if (eventHandler) {
+ eventHandler(event);
+
+ if (!propagateEvent) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+
+ return /*#__PURE__*/React__namespace.cloneElement(children, _objectSpread2({
+ [eventName]: handleKeyEvent
+ }, composingEventHandlers));
+}
+
+function ProgressBar({
+ fillPercentage = 0,
+ className,
+ 'aria-valuetext': ariaValuetext
+}) {
+ const finalClassName = classNames__default["default"]('reactist_progress_bar', className);
+ const width = fillPercentage < 0 ? 0 : fillPercentage > 100 ? 100 : fillPercentage;
+ return /*#__PURE__*/React__namespace.createElement("div", {
+ className: finalClassName
+ }, /*#__PURE__*/React__namespace.createElement("div", {
+ className: "inner",
+ style: {
+ width: width + "%"
+ }
+ }), /*#__PURE__*/React__namespace.createElement(HiddenVisually, null, /*#__PURE__*/React__namespace.createElement("progress", {
+ value: width,
+ max: 100,
+ "aria-valuetext": ariaValuetext != null ? ariaValuetext : undefined
+ })));
+}
+
+ProgressBar.displayName = 'ProgressBar';
+
+dayjs__default["default"].extend(LocalizedFormat__default["default"]);
+const TimeUtils = {
+ SHORT_FORMAT_CURRENT_YEAR: 'L',
+ SHORT_FORMAT_PAST_YEAR: 'LL',
+ LONG_FORMAT: 'LL, LT',
+
+ timeAgo(timestamp, config = {}) {
+ const {
+ locale = 'en',
+ shortFormatCurrentYear = this.SHORT_FORMAT_CURRENT_YEAR,
+ shortFormatPastYear = this.SHORT_FORMAT_PAST_YEAR,
+ daysSuffix = 'd',
+ hoursSuffix = 'h',
+ minutesSuffix = 'm',
+ momentsAgo = 'moments ago'
+ } = config;
+ const now = dayjs__default["default"]();
+ const date = dayjs__default["default"](timestamp * 1000);
+ date.locale(locale);
+ const diffMinutes = now.diff(date, 'minute');
+ const diffHours = now.diff(date, 'hour');
+ const diffDays = now.diff(date, 'day');
+
+ if (diffDays > 1) {
+ if (date.isSame(now, 'year')) {
+ return date.format(shortFormatCurrentYear);
+ } else {
+ return date.format(shortFormatPastYear);
+ }
+ } else if (diffDays === 1) {
+ return "" + diffDays + daysSuffix;
+ } else if (diffHours > 0 && diffHours <= 23) {
+ return "" + diffHours + hoursSuffix;
+ } else if (diffMinutes > 0 && diffMinutes <= 59) {
+ return "" + diffMinutes + minutesSuffix;
+ } else {
+ return momentsAgo;
+ }
+ },
+
+ formatTime(timestamp, config = {}) {
+ const {
+ locale = 'en',
+ shortFormatCurrentYear = this.SHORT_FORMAT_CURRENT_YEAR,
+ shortFormatPastYear = this.SHORT_FORMAT_PAST_YEAR
+ } = config;
+ const date = dayjs__default["default"](timestamp * 1000);
+ date.locale(locale);
+
+ if (date.isSame(dayjs__default["default"](), 'year')) {
+ return date.format(shortFormatCurrentYear);
+ } else {
+ return date.format(shortFormatPastYear);
+ }
+ },
+
+ formatTimeLong(timestamp, config = {}) {
+ const {
+ locale = 'en',
+ longFormat = this.LONG_FORMAT
+ } = config;
+ const date = dayjs__default["default"](timestamp * 1000);
+ date.locale(locale);
+ return date.format(longFormat);
+ }
+
+};
+
+const DELAY = 60000;
+
+class Time extends React__namespace.Component {
+ constructor(props) {
+ super(props);
+ this.refreshInterval = void 0;
+ this.refreshInterval = undefined;
+ this.state = {
+ hovered: false,
+ mouseX: undefined,
+ mouseY: undefined
+ };
+ }
+
+ componentDidMount() {
+ if (this.props.refresh) {
+ this._refresh();
+ }
+ }
+
+ componentDidUpdate(prevProps) {
+ if (!prevProps.refresh && this.props.refresh) {
+ this._refresh();
+ }
+
+ if (prevProps.refresh && !this.props.refresh) {
+ if (this.refreshInterval) {
+ clearTimeout(this.refreshInterval);
+ }
+ }
+ }
+
+ componentWillUnmount() {
+ if (this.refreshInterval) {
+ clearTimeout(this.refreshInterval);
+ }
+ }
+
+ _setHovered(hovered, event) {
+ const {
+ mouseX,
+ mouseY
+ } = this.state;
+ const {
+ clientX,
+ clientY
+ } = event;
+
+ if (clientX !== mouseX || clientY !== mouseY) {
+ // mouse has moved
+ this.setState(() => ({
+ hovered,
+ mouseX: clientX,
+ mouseY: clientY
+ }));
+ }
+ }
+
+ _renderTime(config) {
+ if (!this.props.time) {
+ return;
+ }
+
+ if (this.state.hovered) {
+ if (this.props.expandFullyOnHover && !this.props.tooltipOnHover) {
+ return TimeUtils.formatTimeLong(this.props.time, config);
+ }
+
+ if (this.props.expandOnHover && !this.props.tooltipOnHover) {
+ return TimeUtils.formatTime(this.props.time, config);
+ }
+ }
+
+ return TimeUtils.timeAgo(this.props.time, config);
+ }
+
+ _refresh() {
+ this.refreshInterval = setInterval(() => {
+ this.forceUpdate();
+ }, DELAY);
+ }
+
+ render() {
+ let className = 'reactist_time';
+
+ if (this.props.className) {
+ className = this.props.className;
+ }
+
+ const timeComponent = this._renderTime(this.props.config);
+
+ return /*#__PURE__*/React__namespace.createElement("time", {
+ className: className,
+ onMouseEnter: event => this._setHovered(true, event),
+ onMouseLeave: event => this._setHovered(false, event)
+ }, this.props.tooltipOnHover ? /*#__PURE__*/React__namespace.createElement(Tooltip, {
+ content: this.props.tooltip || this.props.time && TimeUtils.formatTimeLong(this.props.time, this.props.config)
+ }, /*#__PURE__*/React__namespace.createElement("span", null, timeComponent)) : timeComponent);
+ }
+
+}
+
+Time.displayName = void 0;
+Time.defaultProps = void 0;
+Time.displayName = 'Time';
+Time.defaultProps = {
+ expandOnHover: false,
+ expandFullyOnHover: false,
+ tooltipOnHover: false,
+ refresh: true,
+ config: {
+ locale: 'en',
+ daysSuffix: 'd',
+ hoursSuffix: 'h',
+ minutesSuffix: 'm',
+ momentsAgo: 'moments ago'
+ }
+};
+
+/**
+ * @deprecated
+ */
+
+const Input = /*#__PURE__*/React__namespace.forwardRef(function Input(props, ref) {
+ const className = classNames__default["default"]('reactist_input', props.className);
+ return /*#__PURE__*/React__namespace.createElement("input", _objectSpread2(_objectSpread2({}, props), {}, {
+ className: className,
+ ref: ref
+ }));
+});
+Input.displayName = 'Input';
+
+const _excluded = ["value", "options", "onChange", "disabled", "className", "defaultValue"];
+
+function Select(_ref) {
+ let {
+ value,
+ options = [],
+ onChange,
+ disabled = true,
+ className = '',
+ defaultValue
+ } = _ref,
+ otherProps = _objectWithoutProperties(_ref, _excluded);
+
+ const selectClassName = classNames__default["default"]('reactist_select', {
+ disabled
+ }, className);
+ return /*#__PURE__*/React__namespace.createElement("select", _objectSpread2({
+ className: selectClassName,
+ value: value,
+ onChange: event => onChange ? onChange(event.target.value) : undefined,
+ disabled: disabled,
+ defaultValue: defaultValue
+ }, otherProps), options == null ? void 0 : options.map(option => /*#__PURE__*/React__namespace.createElement("option", {
+ key: option.key || option.value,
+ value: option.value,
+ disabled: option.disabled
+ }, option.text)));
+}
+
+Select.displayName = 'Select';
+Select.defaultProps = {
+ options: [],
+ disabled: false
+};
+
+exports.Alert = Alert;
+exports.Avatar = Avatar;
+exports.Badge = Badge;
+exports.Banner = Banner;
+exports.Box = Box$1;
+exports.Button = Button$1;
+exports.COLORS = COLORS;
+exports.CheckboxField = CheckboxField;
+exports.ColorPicker = ColorPicker;
+exports.Column = Column;
+exports.Columns = Columns;
+exports.ContextMenuTrigger = ContextMenuTrigger;
+exports.DeprecatedButton = Button;
+exports.DeprecatedDropdown = Dropdown;
+exports.DeprecatedInput = Input;
+exports.DeprecatedSelect = Select;
+exports.Divider = Divider;
+exports.Heading = Heading;
+exports.Hidden = Hidden;
+exports.HiddenVisually = HiddenVisually;
+exports.IconButton = IconButton;
+exports.Inline = Inline;
+exports.KeyCapturer = KeyCapturer;
+exports.KeyboardShortcut = KeyboardShortcut;
+exports.Loading = Loading;
+exports.Menu = Menu;
+exports.MenuButton = MenuButton;
+exports.MenuGroup = MenuGroup;
+exports.MenuItem = MenuItem;
+exports.MenuList = MenuList;
+exports.Modal = Modal;
+exports.ModalActions = ModalActions;
+exports.ModalBody = ModalBody;
+exports.ModalCloseButton = ModalCloseButton;
+exports.ModalFooter = ModalFooter;
+exports.ModalHeader = ModalHeader;
+exports.Notice = Notice;
+exports.PasswordField = PasswordField;
+exports.ProgressBar = ProgressBar;
+exports.Prose = Prose;
+exports.SUPPORTED_KEYS = SUPPORTED_KEYS;
+exports.SelectField = SelectField;
+exports.Stack = Stack;
+exports.StaticToast = StaticToast;
+exports.SubMenu = SubMenu;
+exports.SwitchField = SwitchField;
+exports.Tab = Tab;
+exports.TabAwareSlot = TabAwareSlot;
+exports.TabList = TabList;
+exports.TabPanel = TabPanel;
+exports.Tabs = Tabs;
+exports.Text = Text;
+exports.TextArea = TextArea;
+exports.TextField = TextField;
+exports.TextLink = TextLink;
+exports.Time = Time;
+exports.Toast = Toast;
+exports.ToastsProvider = ToastsProvider;
+exports.Tooltip = Tooltip;
+exports.getBoxClassNames = getBoxClassNames;
+exports.useToasts = useToasts;
+//# sourceMappingURL=reactist.cjs.development.js.map
diff --git a/dist/reactist.cjs.development.js.map b/dist/reactist.cjs.development.js.map
new file mode 100644
index 000000000..ded962b95
--- /dev/null
+++ b/dist/reactist.cjs.development.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"reactist.cjs.development.js","sources":["../src/utils/polymorphism.ts","../src/utils/responsive-props.ts","../src/box/box.tsx","../src/columns/columns.tsx","../src/divider/divider.tsx","../src/inline/inline.tsx","../src/stack/stack.tsx","../src/hidden/hidden.tsx","../src/hidden-visually/hidden-visually.tsx","../src/spinner/spinner.tsx","../src/tooltip/tooltip.tsx","../src/button/button.tsx","../src/icons/alert-icon.tsx","../src/icons/close-icon.tsx","../src/alert/alert.tsx","../src/utils/common-helpers.ts","../src/banner/banner.tsx","../src/loading/loading.tsx","../src/notice/notice.tsx","../src/text/text.tsx","../src/toast/static-toast.tsx","../src/toast/toast-animation.ts","../src/toast/use-toasts.tsx","../src/heading/heading.tsx","../src/prose/prose.tsx","../src/text-link/text-link.tsx","../src/checkbox-field/checkbox-icon.tsx","../src/checkbox-field/use-fork-ref.ts","../src/checkbox-field/checkbox-field.tsx","../src/icons/password-visible-icon.tsx","../src/icons/password-hidden-icon.tsx","../src/base-field/base-field.tsx","../src/text-field/text-field.tsx","../src/password-field/password-field.tsx","../src/select-field/select-field.tsx","../src/switch-field/switch-field.tsx","../src/text-area/text-area.tsx","../src/avatar/utils.ts","../src/avatar/avatar.tsx","../src/badge/badge.tsx","../src/modal/modal.tsx","../src/tabs/tabs.tsx","../src/menu/menu.tsx","../src/components/deprecated-button/deprecated-button.tsx","../src/components/deprecated-dropdown/dropdown.tsx","../src/components/color-picker/color-picker.tsx","../src/components/keyboard-shortcut/keyboard-shortcut.tsx","../src/components/key-capturer/key-capturer.tsx","../src/components/progress-bar/progress-bar.tsx","../src/components/time/time-utils.ts","../src/components/time/time.tsx","../src/components/deprecated-input/input.tsx","../src/components/deprecated-select/select.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport * as React from 'react'\nimport type { ObfuscatedClassName } from './common-types'\n\ntype Merge = Omit & P2\n\ntype EmptyObject = {\n [K in any]: never\n}\n\ntype ObfuscateClassNameMode = 'keepClassName' | 'obfuscateClassName' | 'omitClassName'\n\n/**\n * If a set of props include the `className` prop, we replace it with a `exceptionallySetClassName`\n * prop instead.\n *\n * This can be customized via the second generic parameter, as there are cases where it may be\n * needed to omit this behaviour and keep the `className`. You can also instruct it to remove the\n * `className` prop while not replacing it with the `exceptionallySetClassName` one.\n *\n * @see ObfuscatedClassName['exceptionallySetClassName'] for details about this prop\n * @see PolymorphicComponent for details about this feature\n */\ntype WithObfuscatedClassName<\n Props,\n ShouldObfuscateClassName extends ObfuscateClassNameMode\n> = 'className' extends keyof Props\n ? ShouldObfuscateClassName extends 'obfuscateClassName'\n ? Omit & ObfuscatedClassName\n : ShouldObfuscateClassName extends 'omitClassName'\n ? Omit\n : ShouldObfuscateClassName extends 'keepClassName'\n ? Props\n : never\n : Props\n\ntype PolymorphicProp = {\n /**\n * Used to instruct this component what React element to render as. It can be both a string\n * representing a HTML tag name, or a React component.\n *\n * When using this prop, the component you apply it to will also recognize in its props types\n * all the props from the component or HTML element you are rendering it as.\n *\n * Some uses for this feature:\n *\n * - Using some of our layout components, while at the same time being able to set them to use\n * semantic HTML elements needed for accessibility purposes (e.g. `nav`, `main`, etc).\n * - Using a design system link component, but have it internally use a client-side router link\n * implemented via a React component (e.g. react-router's `Link`).\n *\n * Keep in mind that not all compositions of this kind may work well, especially when composing\n * with another React component and not with a HTML tag name. In particular, if the components\n * being composed have opposing concerns of clashing features (e.g. they have contradicting\n * styles applied to them) things may not go well. In those cases prefer to nest them instead.\n *\n * @see PolymorphicComponent\n */\n as?: ComponentType\n}\n\n/**\n * Given a component or element type, and a set of additional props, this builds the entire set of\n * props for a polymorphic component.\n *\n * It does three things:\n *\n * 1. it merges the element type props with the `OwnProps`\n * 2. it adds the `as` prop to allow for polymorphism to happen\n * 3. it optionally obfuscates or omits the className prop if present\n *\n * @see PolymorphicProp\n * @see WithObfuscatedClassName\n */\ntype PolymorphicComponentProps<\n ComponentType extends React.ElementType,\n OwnProps,\n ShouldObfuscateClassName extends ObfuscateClassNameMode\n> = Merge<\n WithObfuscatedClassName, ShouldObfuscateClassName>,\n OwnProps & PolymorphicProp\n>\n\ntype ElementTagNameMap = HTMLElementTagNameMap &\n Pick>\n\ntype ElementByTag = ElementTagNameMap[TagName]\n\ntype ElementByTagOrAny<\n ComponentType extends React.ElementType\n> = ComponentType extends keyof ElementTagNameMap ? ElementByTag : any\n\n/**\n * The function passed to React.forwardRef, but typed in a way that's prepared for polymorphism via\n * the `as` prop. It also allows to specify if the `className` prop should be obfuscated or omitted.\n *\n * @see PolymorphicComponentProps\n * @see WithObfuscatedClassName\n */\ninterface ForwardRefFunction<\n ComponentType extends React.ElementType,\n OwnProps,\n ShouldObfuscateClassName extends ObfuscateClassNameMode\n> {\n (\n props: PolymorphicComponentProps,\n ref:\n | ((instance: ElementByTagOrAny | null) => void)\n | React.MutableRefObject | null>\n | null,\n ): React.ReactElement | null\n displayName?: string\n}\n\n/**\n * A component that can customize the React element type that it renders (a.k.a. a polymorphic\n * component). This is achieved by passing a prop `as={ElementType}` or `as=\"html-tag-name\"`.\n *\n * It transparently takes care of forwarding refs, and properly sets the ref type depending on the\n * element type.\n *\n * ## Recognizing props based on the polymorphic type\n *\n * The `ComponentType` argument sets the default type for the `as` prop. Whatever the `as` prop\n * component or HTML element is, the type system will automatically allow you to pass props that are\n * not explicitly defined by you, but that are recognized as valid props to be passed to the\n * component you are rendering.\n *\n * For instance, see the following example:\n *\n * ```jsx\n * Hello\n * ```\n *\n * The `htmlFor` prop is exclusive to label elements. If you omit the `as=\"label\"` prop, the type\n * system will consider the `htmlFor` prop to be an error. The same happens if you pass a value of\n * an incorrect type to such prop. For instance, the example below will issue a type error:\n *\n * ```jsx\n * Hello\n * ```\n *\n * ## Omitting or obfuscating the `className` prop\n *\n * If a set of props include the `className` prop, we replace it with a `exceptionallySetClassName`\n * prop instead.\n *\n * This is to discourage customizing design system components via custom styling, while still\n * leaving the door open to do it as an escape hatch when the design system still has shortcomings\n * with respect to the product designs we want to achieve.\n *\n * The cumbersome name also serves the purpose of aiding in easily searching for the places in the\n * code where this escape hatch was needed, in order to identify areas where the design system\n * components need to improve to better match our needs.\n *\n * This behaviour can be customized via an optional second generic argument that allows to disable\n * this feature, or to omit the `className` altogether without replacing it with the obfuscated prop\n * name.\n *\n * @deprecated Use Ariakit's composition instead (https://ariakit.org/guide/composition)\n */\ninterface PolymorphicComponent<\n ComponentType extends React.ElementType,\n OwnProps,\n ShouldObfuscateClassName extends ObfuscateClassNameMode = 'obfuscateClassName'\n> {\n (\n props: PolymorphicComponentProps,\n ): React.ReactElement | null\n readonly $$typeof: symbol\n defaultProps?: Partial<\n PolymorphicComponentProps\n >\n propTypes?: React.WeakValidationMap<\n PolymorphicComponentProps\n >\n displayName?: string\n}\n\n/**\n * A wrapper to use React.forwardRef with polymorphic components in a type-safe manner. This is a\n * convenience over merely using React.forwardRef directly, and then manually forcing the resulting\n * value to be typed using `as PolymorphicComponent<…>`.\n *\n * @deprecated Use Ariakit's composition instead (https://ariakit.org/guide/composition)\n */\nfunction polymorphicComponent<\n ComponentType extends React.ElementType = 'div',\n OwnProps = EmptyObject,\n ShouldObfuscateClassName extends ObfuscateClassNameMode = 'obfuscateClassName'\n>(render: ForwardRefFunction) {\n return React.forwardRef(render) as PolymorphicComponent<\n ComponentType,\n OwnProps,\n ShouldObfuscateClassName\n >\n}\n\nexport type { PolymorphicComponent }\nexport { polymorphicComponent }\n","type ResponsiveBreakpoints = 'mobile' | 'tablet' | 'desktop'\n\ntype Atom = string | number | boolean\n\n/**\n * A responsive prop supports receiving values of its given base type, or an object mapping a\n * responsive breakpoint name to a value from the prop's base type.\n *\n * Some examples:\n *\n * - `align={{ mobile: 'left', tablet: 'center', desktop: 'right' }}`\n */\ntype ResponsiveProp =\n | AtomType\n | Readonly<{ [key in ResponsiveBreakpoints]?: AtomType }>\n\nconst DEBUG = process.env.NODE_ENV === 'development'\n\n/**\n * Builds a css module class name for a given prop + prop-value combination.\n *\n * We have a convention of building the internal utility-based class names system in a way that\n * resembles the prop for which it is used and the value of the prop. For instance, in a component\n * with a prop `width` with possible values `narrow` and `wide`, we encode the styles for each of\n * these alternatives in the class-names `.width-narrow` and `.width-wide`.\n *\n * Furthermore, this helper is aware of responsive prop values. For instance, if you provide the\n * `width` prop above with the value `['narrow', 'wide']` this returns `['narrow', 'tablet-wide']`.\n * That is, it returns an array of class names, following the same convention above, but also\n * prefixing by the viewport width variant (`tablet-` or `desktop-`).\n *\n * @param styles the class names mapping imported from a css module\n * @param property the prop name\n * @param value the given prop's value\n */\nfunction getClassNames(\n styles: Record,\n property: string,\n value: ResponsiveProp | null | undefined,\n): Array | null {\n if (!value) {\n return null\n }\n\n const classList: Array = []\n\n if (typeof value === 'string') {\n classList.push(styles[`${property}-${value}`])\n } else {\n if (value.mobile) classList.push(styles[`${property}-${value.mobile}`])\n if (value.tablet) classList.push(styles[`tablet-${property}-${value.tablet}`])\n if (value.desktop) classList.push(styles[`desktop-${property}-${value.desktop}`])\n }\n\n if (DEBUG && !classList.every(Boolean)) {\n // eslint-disable-next-line no-console\n console.warn('Not all generated class names were found', { property, value, classList })\n }\n\n return classList\n}\n\n/**\n * A mapping over a responsive prop value.\n *\n * Since response values can be an object but also a scalar value, this helper makes it easier to\n * to map the values when it's an object but keeps it consistent for the case when it is a scalar\n * value as well.\n *\n * @param fromValue the responsive prop value\n * @param mapper the mapping function\n */\nfunction mapResponsiveProp(\n fromValue: ResponsiveProp | undefined,\n mapper: (from: From) => To,\n): ResponsiveProp | undefined {\n if (!fromValue) {\n return undefined\n }\n\n if (typeof fromValue !== 'object') {\n return mapper(fromValue)\n }\n\n return {\n mobile: fromValue.mobile ? mapper(fromValue.mobile) : undefined,\n tablet: fromValue.tablet ? mapper(fromValue.tablet) : undefined,\n desktop: fromValue.desktop ? mapper(fromValue.desktop) : undefined,\n }\n}\n\nexport type { ResponsiveProp, ResponsiveBreakpoints }\nexport { getClassNames, mapResponsiveProp }\n","import * as React from 'react'\nimport classNames from 'classnames'\nimport { polymorphicComponent } from '../utils/polymorphism'\nimport { getClassNames } from '../utils/responsive-props'\n\nimport type { ResponsiveProp } from '../utils/responsive-props'\nimport type {\n DividerWeight,\n Space,\n SpaceWithNegatives,\n WithEnhancedClassName,\n} from '../utils/common-types'\n\nimport styles from './box.module.css'\nimport paddingStyles from './padding.module.css'\nimport marginStyles from './margin.module.css'\nimport widthStyles from './width.module.css'\nimport gapStyles from './gap.module.css'\n\ninterface BoxPaddingProps {\n padding?: ResponsiveProp\n paddingX?: ResponsiveProp\n paddingY?: ResponsiveProp\n paddingTop?: ResponsiveProp\n paddingRight?: ResponsiveProp\n paddingBottom?: ResponsiveProp\n paddingLeft?: ResponsiveProp\n}\n\ninterface BoxMarginProps {\n margin?: ResponsiveProp\n marginX?: ResponsiveProp\n marginY?: ResponsiveProp\n marginTop?: ResponsiveProp\n marginRight?: ResponsiveProp\n marginBottom?: ResponsiveProp\n marginLeft?: ResponsiveProp\n}\n\ntype BoxDisplay = 'block' | 'flex' | 'inline' | 'inlineBlock' | 'inlineFlex' | 'none'\ntype BoxFlexDirection = 'column' | 'row'\ntype BoxFlexWrap = 'nowrap' | 'wrap'\ntype BoxAlignItems = 'center' | 'flexEnd' | 'flexStart' | 'baseline'\ntype BoxJustifyContent =\n | 'center'\n | 'flexEnd'\n | 'flexStart'\n | 'spaceAround'\n | 'spaceBetween'\n | 'spaceEvenly'\ntype BoxAlignSelf = 'flexStart' | 'flexEnd' | 'center' | 'baseline' | 'stretch'\ntype BoxOverflow = 'hidden' | 'auto' | 'visible' | 'scroll'\n\ntype BoxMaxMinWidth = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'\ntype BoxMinWidth = 0 | BoxMaxMinWidth\ntype BoxMaxWidth = BoxMaxMinWidth | 'full'\ntype BoxWidth = 0 | BoxMaxMinWidth | 'full' | 'auto' | 'maxContent' | 'minContent' | 'fitContent'\ntype BoxBackground = 'default' | 'aside' | 'highlight' | 'selected' | 'toast'\ntype BoxBorderRadius = 'standard' | 'none' | 'full'\n\ninterface BorderProps {\n borderRadius?: BoxBorderRadius\n border?: DividerWeight\n}\n\ninterface ReusableBoxProps extends BorderProps, BoxPaddingProps {\n minWidth?: BoxMinWidth\n maxWidth?: BoxMaxWidth\n width?: BoxWidth\n background?: BoxBackground\n flexGrow?: 0 | 1\n flexShrink?: 0\n}\n\ntype BoxPosition = 'absolute' | 'fixed' | 'relative' | 'static' | 'sticky'\ntype BoxTextAlign = 'start' | 'center' | 'end' | 'justify'\n\ninterface BoxProps extends WithEnhancedClassName, ReusableBoxProps, BoxMarginProps {\n position?: ResponsiveProp\n display?: ResponsiveProp\n flexDirection?: ResponsiveProp\n flexWrap?: BoxFlexWrap\n gap?: ResponsiveProp\n alignItems?: ResponsiveProp\n alignSelf?: ResponsiveProp\n justifyContent?: ResponsiveProp\n overflow?: BoxOverflow\n height?: 'full'\n textAlign?: ResponsiveProp\n}\n\nfunction getBoxClassNames({\n position = 'static',\n display,\n flexDirection = 'row',\n flexWrap,\n flexGrow,\n flexShrink,\n gap,\n alignItems,\n justifyContent,\n alignSelf,\n overflow,\n width,\n height,\n background,\n border,\n borderRadius,\n minWidth,\n maxWidth,\n textAlign,\n padding,\n paddingY,\n paddingX,\n paddingTop,\n paddingRight,\n paddingBottom,\n paddingLeft,\n margin,\n marginY,\n marginX,\n marginTop,\n marginRight,\n marginBottom,\n marginLeft,\n className,\n}: BoxProps) {\n const resolvedPaddingTop = paddingTop ?? paddingY ?? padding\n const resolvedPaddingRight = paddingRight ?? paddingX ?? padding\n const resolvedPaddingBottom = paddingBottom ?? paddingY ?? padding\n const resolvedPaddingLeft = paddingLeft ?? paddingX ?? padding\n\n const resolvedMarginTop = marginTop ?? marginY ?? margin\n const resolvedMarginRight = marginRight ?? marginX ?? margin\n const resolvedMarginBottom = marginBottom ?? marginY ?? margin\n const resolvedMarginLeft = marginLeft ?? marginX ?? margin\n\n const omitFlex =\n !display || (typeof display === 'string' && display !== 'flex' && display !== 'inlineFlex')\n\n return classNames(\n className,\n styles.box,\n display ? getClassNames(styles, 'display', display) : null,\n position !== 'static' ? getClassNames(styles, 'position', position) : null,\n minWidth != null ? getClassNames(widthStyles, 'minWidth', String(minWidth)) : null,\n getClassNames(widthStyles, 'maxWidth', maxWidth),\n getClassNames(styles, 'textAlign', textAlign),\n // padding\n getClassNames(paddingStyles, 'paddingTop', resolvedPaddingTop),\n getClassNames(paddingStyles, 'paddingRight', resolvedPaddingRight),\n getClassNames(paddingStyles, 'paddingBottom', resolvedPaddingBottom),\n getClassNames(paddingStyles, 'paddingLeft', resolvedPaddingLeft),\n // margin\n getClassNames(marginStyles, 'marginTop', resolvedMarginTop),\n getClassNames(marginStyles, 'marginRight', resolvedMarginRight),\n getClassNames(marginStyles, 'marginBottom', resolvedMarginBottom),\n getClassNames(marginStyles, 'marginLeft', resolvedMarginLeft),\n // flex props\n omitFlex ? null : getClassNames(styles, 'flexDirection', flexDirection),\n omitFlex ? null : getClassNames(styles, 'flexWrap', flexWrap),\n omitFlex ? null : getClassNames(styles, 'alignItems', alignItems),\n omitFlex ? null : getClassNames(styles, 'justifyContent', justifyContent),\n alignSelf != null ? getClassNames(styles, 'alignSelf', alignSelf) : null,\n flexShrink != null ? getClassNames(styles, 'flexShrink', String(flexShrink)) : null,\n flexGrow != null ? getClassNames(styles, 'flexGrow', String(flexGrow)) : null,\n gap ? getClassNames(gapStyles, 'gap', gap) : null,\n // other props\n getClassNames(styles, 'overflow', overflow),\n width != null ? getClassNames(widthStyles, 'width', String(width)) : null,\n getClassNames(styles, 'height', height),\n getClassNames(styles, 'bg', background),\n borderRadius !== 'none' ? getClassNames(styles, 'borderRadius', borderRadius) : null,\n border !== 'none' ? getClassNames(styles, 'border', border) : null,\n )\n}\n\nconst Box = polymorphicComponent<'div', BoxProps, 'keepClassName'>(function Box(\n {\n as: component = 'div',\n position = 'static',\n display,\n flexDirection = 'row',\n flexWrap,\n flexGrow,\n flexShrink,\n gap,\n alignItems,\n justifyContent,\n alignSelf,\n overflow,\n width,\n height,\n background,\n border,\n borderRadius,\n minWidth,\n maxWidth,\n textAlign,\n padding,\n paddingY,\n paddingX,\n paddingTop,\n paddingRight,\n paddingBottom,\n paddingLeft,\n margin,\n marginY,\n marginX,\n marginTop,\n marginRight,\n marginBottom,\n marginLeft,\n className,\n children,\n ...props\n },\n ref,\n) {\n return React.createElement(\n component,\n {\n ...props,\n className: getBoxClassNames({\n position,\n display,\n flexDirection,\n flexWrap,\n flexGrow,\n flexShrink,\n gap,\n alignItems,\n justifyContent,\n alignSelf,\n overflow,\n width,\n height,\n background,\n border,\n borderRadius,\n minWidth,\n maxWidth,\n textAlign,\n padding,\n paddingY,\n paddingX,\n paddingTop,\n paddingRight,\n paddingBottom,\n paddingLeft,\n margin,\n marginY,\n marginX,\n marginTop,\n marginRight,\n marginBottom,\n marginLeft,\n className,\n }),\n ref,\n },\n children,\n )\n})\n\nexport type {\n BoxProps,\n BoxPaddingProps,\n BoxMarginProps,\n ReusableBoxProps,\n BoxMinWidth,\n BoxMaxWidth,\n BoxDisplay,\n BoxPosition,\n BoxFlexDirection,\n BoxFlexWrap,\n BoxAlignItems,\n BoxJustifyContent,\n BoxOverflow,\n BoxTextAlign,\n BoxBackground,\n BoxBorderRadius,\n}\n\nexport { Box, getBoxClassNames }\n","import * as React from 'react'\nimport { polymorphicComponent } from '../utils/polymorphism'\nimport { getClassNames, mapResponsiveProp } from '../utils/responsive-props'\nimport { Box } from '../box'\n\nimport type { ResponsiveProp, ResponsiveBreakpoints } from '../utils/responsive-props'\nimport type { Space } from '../utils/common-types'\nimport type { ReusableBoxProps } from '../box'\n\nimport styles from './columns.module.css'\n\ntype ColumnWidth =\n | 'auto'\n | 'content'\n | '1/2'\n | '1/3'\n | '2/3'\n | '1/4'\n | '3/4'\n | '1/5'\n | '2/5'\n | '3/5'\n | '4/5'\n\ninterface ColumnProps {\n width?: ColumnWidth\n}\n\nconst Column = polymorphicComponent<'div', ColumnProps>(function Column(\n { width = 'auto', children, exceptionallySetClassName, ...props },\n ref,\n) {\n return (\n \n {children}\n \n )\n})\n\ntype ColumnsHorizontalAlignment = 'left' | 'center' | 'right'\ntype ColumnsVerticalAlignment = 'top' | 'center' | 'bottom' | 'baseline'\ntype ColumnsCollapseBelow = Exclude\n\ninterface ColumnsProps extends ReusableBoxProps {\n space?: ResponsiveProp\n align?: ResponsiveProp\n alignY?: ResponsiveProp\n collapseBelow?: ResponsiveBreakpoints\n}\n\nconst Columns = polymorphicComponent<'div', ColumnsProps>(function Columns(\n {\n space,\n align = 'left',\n alignY = 'top',\n collapseBelow,\n children,\n exceptionallySetClassName,\n ...props\n },\n ref,\n) {\n return (\n \n alignY === 'top' ? 'flexStart' : alignY === 'bottom' ? 'flexEnd' : alignY,\n )}\n justifyContent={mapResponsiveProp(align, (align) =>\n align === 'left' ? 'flexStart' : align === 'right' ? 'flexEnd' : align,\n )}\n ref={ref}\n >\n {children}\n \n )\n})\n\nexport type {\n ColumnProps,\n ColumnsProps,\n ColumnWidth,\n ColumnsCollapseBelow,\n ColumnsHorizontalAlignment,\n ColumnsVerticalAlignment,\n}\n\nexport { Column, Columns }\n","import * as React from 'react'\nimport { getClassNames } from '../utils/responsive-props'\nimport { Box } from '../box'\nimport type { DividerWeight } from '../utils/common-types'\n\nimport styles from './divider.module.css'\n\ninterface DividerProps {\n weight?: Exclude\n}\n\nfunction Divider({ weight = 'tertiary', ...props }: DividerProps) {\n return \n}\n\nexport type { DividerProps, DividerWeight }\nexport { Divider }\n","import * as React from 'react'\nimport { polymorphicComponent } from '../utils/polymorphism'\nimport { mapResponsiveProp } from '../utils/responsive-props'\nimport { Box } from '../box'\n\nimport type { ResponsiveProp } from '../utils/responsive-props'\nimport type { Space } from '../utils/common-types'\nimport type { ReusableBoxProps } from '../box'\n\ntype InlineAlign = 'left' | 'center' | 'right'\n\ninterface InlineProps extends ReusableBoxProps {\n space?: ResponsiveProp\n align?: ResponsiveProp\n alignY?: ResponsiveProp<'top' | 'center' | 'bottom'>\n}\n\nconst Inline = polymorphicComponent<'div', InlineProps>(function Inline(\n { as, space, align = 'left', alignY = 'center', children, exceptionallySetClassName, ...props },\n ref,\n) {\n return (\n \n alignY === 'top' ? 'flexStart' : alignY === 'bottom' ? 'flexEnd' : 'center',\n )}\n justifyContent={mapResponsiveProp(align, (align) =>\n align === 'left' ? 'flexStart' : align === 'right' ? 'flexEnd' : 'center',\n )}\n >\n {children}\n \n )\n})\n\nexport type { InlineProps, InlineAlign }\nexport { Inline }\n","import * as React from 'react'\nimport flattenChildren from 'react-keyed-flatten-children'\nimport { polymorphicComponent } from '../utils/polymorphism'\nimport { mapResponsiveProp } from '../utils/responsive-props'\nimport { Box } from '../box'\nimport { Divider } from '../divider'\n\nimport type { ResponsiveProp } from '../utils/responsive-props'\nimport type { DividerWeight, Space } from '../utils/common-types'\nimport type { BoxProps, ReusableBoxProps } from '../box'\n\ntype Align = 'start' | 'center' | 'end'\n\ninterface StackProps extends ReusableBoxProps {\n /** Space between items */\n space?: ResponsiveProp\n /** Align items horizontally */\n align?: ResponsiveProp\n /** The weight of the dividers to add. Defaults to 'none', which means no dividers are added */\n dividers?: DividerWeight\n}\n\nconst Stack = polymorphicComponent<'div', StackProps>(function Stack(\n {\n as,\n space,\n align,\n dividers = 'none',\n width = 'full',\n children,\n exceptionallySetClassName,\n ...props\n },\n ref,\n) {\n const alignItems: BoxProps['alignItems'] =\n align === undefined\n ? undefined\n : mapResponsiveProp(align, (align) =>\n align === 'start' ? 'flexStart' : align === 'end' ? 'flexEnd' : 'center',\n )\n\n return (\n \n {dividers !== 'none'\n ? React.Children.map(flattenChildren(children), (child, index) =>\n index > 0 ? (\n <>\n \n {child}\n >\n ) : (\n child\n ),\n )\n : children}\n \n )\n})\n\nexport type { StackProps }\nexport { Stack }\n","import * as React from 'react'\nimport { Box } from '../box'\nimport styles from './hidden.module.css'\nimport type { ResponsiveBreakpoints } from '../utils/responsive-props'\nimport { polymorphicComponent } from '../utils/polymorphism'\n\ntype AboveProp = {\n /**\n * Hides the element on viewport sizes equal or larger to the one given.\n *\n * It is not supported to pass it alongside `below`, and the resulting behavior is undefined\n * (most likely itʼll hide the element all the time to make it apparent that there's a problem).\n *\n * @see below\n */\n above: Exclude\n below?: never\n}\n\ntype BelowProp = {\n /**\n * Hides the element on viewport sizes equal or smaller to the one given.\n *\n * It is not supported to pass it alongside `above`, and the resulting behavior is undefined\n * (most likely itʼll hide the element all the time to make it apparent that there's a problem).\n *\n * @see above\n */\n below: Exclude\n above?: never\n}\n\ntype CommonProps = {\n children: React.ReactNode\n /**\n * hides the element when on print media.\n */\n print?: boolean\n /**\n * Useful if you want the element to be an inline element when it is visible.\n */\n display?: 'inline' | 'block'\n}\n\ntype HiddenProps = CommonProps & (AboveProp | BelowProp | Required>)\n\n/**\n * A component that allows to specify how to hide itself on certain responsive screen sizes, or on\n * print media.\n *\n * @see HiddenProps\n * @see HiddenVisually for hiding content only visually, while keeping it available for assistive\n * technologies.\n */\nconst Hidden = polymorphicComponent<'div', HiddenProps>(function Hidden(\n { display = 'block', children, exceptionallySetClassName, ...props },\n ref,\n) {\n const hiddenOnPrint = 'print' in props && props.print\n\n const hiddenOnDesktop = 'above' in props\n const hiddenOnMobile = 'below' in props\n const hiddenOnTablet =\n ('below' in props && props.below === 'desktop') ||\n ('above' in props && props.above === 'mobile')\n\n if (hiddenOnDesktop && hiddenOnMobile) {\n // eslint-disable-next-line no-console\n console.warn(' should receive either above=\"…\" or below=\"…\" but not both')\n }\n\n if (!hiddenOnDesktop && !hiddenOnMobile && !hiddenOnPrint) {\n // eslint-disable-next-line no-console\n console.warn(' did not receive any criteria to hide itself')\n }\n\n // We need to delete these so they do not get forwarded to the Box\n if ('above' in props) delete props['above']\n if ('below' in props) delete props['below']\n if ('print' in props) delete props['print']\n\n return (\n \n {children}\n \n )\n})\n\nexport { Hidden }\nexport type { HiddenProps }\n","import * as React from 'react'\nimport { polymorphicComponent } from '../utils/polymorphism'\nimport { Box } from '../box'\nimport styles from './hidden-visually.module.css'\n\ntype Props = {\n children: React.ReactNode\n}\n\n/**\n * Provides content to assistive technologies while hiding it from the screen.\n *\n * @see Hidden for fully hiding content, and only under certain conditions.\n */\nconst HiddenVisually = polymorphicComponent<'div', Props, 'omitClassName'>(function HiddenVisually(\n props,\n ref,\n) {\n return (\n \n )\n})\n\nexport { HiddenVisually }\n","import * as React from 'react'\nimport styles from './spinner.module.css'\n\nfunction Spinner({ size = 24 }: { size?: number }) {\n return (\n \n )\n}\n\nexport { Spinner }\n","import * as React from 'react'\n\nimport {\n useTooltipStore,\n Tooltip as AriakitTooltip,\n TooltipAnchor,\n TooltipArrow,\n} from '@ariakit/react'\nimport { Box } from '../box'\n\nimport type { TooltipStoreState } from '@ariakit/react'\n\nimport styles from './tooltip.module.css'\nimport type { ObfuscatedClassName } from '../utils/common-types'\n\ninterface TooltipProps extends ObfuscatedClassName {\n /**\n * The element that triggers the tooltip. Generally a button or link.\n *\n * It should be an interactive element accessible both via mouse and keyboard interactions.\n */\n children: React.ReactNode\n\n /**\n * The content to show in the tooltip.\n *\n * It can be rich content provided via React elements, or string content. It should not include\n * interactive elements inside it. This includes links or buttons.\n *\n * You can provide a function instead of the content itself. In this case, the function should\n * return the desired content. This is useful if the content is expensive to generate. It can\n * also be useful if the content dynamically changes often, so every time you trigger the\n * tooltip the content may have changed (e.g. if you show a ticking time clock in the tooltip).\n *\n * The trigger element will be associated to this content via `aria-describedby`. This means\n * that the tooltip content will be read by assistive technologies such as screen readers. It\n * will likely read this content right after reading the trigger element label.\n */\n content: React.ReactNode | (() => React.ReactNode)\n\n /**\n * How to place the tooltip relative to its trigger element.\n *\n * The possible values are \"top\", \"bottom\", \"left\", \"right\". Additionally, any of these values\n * can be combined with `-start` or `-end` for even more control. For instance `top-start` will\n * place the tooltip at the top, but with the start (e.g. left) side of the toolip and the\n * trigger aligned. If neither `-start` or `-end` are provided, the tooltip is centered along\n * the vertical or horizontal axis with the trigger.\n *\n * The position is enforced whenever possible, but tooltips can appear in different positions\n * if the specified one would make the tooltip intersect with the viewport edges.\n *\n * @default 'top'\n */\n position?: TooltipStoreState['placement']\n\n /**\n * The separation (in pixels) between the trigger element and the tooltip.\n * @default 3\n */\n gapSize?: number\n\n /**\n * Whether to show an arrow-like element attached to the tooltip, and pointing towards the\n * trigger element.\n * @default false\n */\n withArrow?: boolean\n}\n\nfunction Tooltip({\n children,\n content,\n position = 'top',\n gapSize = 3,\n withArrow = false,\n exceptionallySetClassName,\n}: TooltipProps) {\n const tooltip = useTooltipStore({ placement: position, showTimeout: 500, hideTimeout: 100 })\n const isOpen = tooltip.useState('open')\n\n const child = React.Children.only(\n children as React.FunctionComponentElement | null,\n )\n\n if (!child) {\n return child\n }\n\n if (typeof child.ref === 'string') {\n throw new Error('Tooltip: String refs cannot be used as they cannot be forwarded')\n }\n\n return (\n <>\n \n {isOpen && content ? (\n \n }\n >\n {withArrow ? : null}\n {typeof content === 'function' ? content() : content}\n \n ) : null}\n >\n )\n}\n\nexport type { TooltipProps }\nexport { Tooltip }\n","import * as React from 'react'\nimport classNames from 'classnames'\nimport { Role, RoleProps } from '@ariakit/react'\n\nimport { Box, getBoxClassNames } from '../box'\nimport { Spinner } from '../spinner'\nimport { Tooltip, TooltipProps } from '../tooltip'\n\nimport styles from './button.module.css'\n\nimport type { ObfuscatedClassName } from '../utils/common-types'\n\nfunction preventDefault(event: React.SyntheticEvent) {\n event.preventDefault()\n}\n\ntype ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'quaternary'\ntype ButtonTone = 'normal' | 'destructive'\ntype ButtonSize = 'small' | 'normal' | 'large'\ntype IconElement = React.ReactElement | string\n\ninterface CommonButtonProps\n extends ObfuscatedClassName,\n Omit, 'className'>,\n Pick {\n /**\n * The button's variant.\n */\n variant: ButtonVariant\n\n /**\n * The button's tone.\n *\n * @default 'normal'\n */\n tone?: ButtonTone\n\n /**\n * The button's size.\n *\n * @default 'normal'\n */\n size?: ButtonSize\n\n /**\n * Controls the shape of the button.\n *\n * Specifically, it allows to make it have slightly curved corners (the default) vs. having them\n * fully curved to the point that they are as round as possible.\n *\n * In icon-only buttons this allows to have the button be circular.\n *\n * @default 'normal'\n */\n shape?: 'normal' | 'rounded'\n\n /**\n * Whether the button is disabled or not.\n *\n * Buttons are disabled using aria-disabled, rather than the HTML disabled attribute. This\n * allows the buttons to be focusable, which can aid discoverability. This way, users can tab to\n * the button and read its label, even if they can't activate it.\n *\n * It is also convenient when buttons are rendered as a link. Links cannot normally be disabled,\n * but by using aria-disabled, we can make them behave as if they were.\n *\n * The `onClick` handler is automatically prevented when the button is disabled in this way, to\n * mimic the behavior of a native disabled attribute.\n *\n * @default false\n */\n disabled?: boolean\n\n /**\n * Whether the button is busy/loading.\n *\n * A button in this state is functionally and semantically disabled. Visually is does not look\n * dimmed (as disabled buttons normally do), but it shows a loading spinner instead.\n *\n * @default false\n */\n loading?: boolean\n\n /**\n * A tooltip linked to the button element.\n */\n tooltip?: TooltipProps['content']\n\n /**\n * The type of the button.\n *\n * @default 'button'\n */\n type?: 'button' | 'submit' | 'reset'\n}\n\ninterface ButtonProps extends CommonButtonProps {\n /**\n * The button label content.\n */\n children?: React.ReactNode\n\n /**\n * The icon to display at the start of the button (before the label).\n */\n startIcon?: IconElement\n\n /**\n * The icon to display at the end of the button (after the label).\n */\n endIcon?: IconElement\n\n /**\n * The width of the button.\n *\n * - `'auto'`: The button will be as wide as its content.\n * - `'full'`: The button will be as wide as its container.\n *\n * @default 'auto'\n */\n width?: 'auto' | 'full'\n\n /**\n * The alignment of the button label inside the button.\n *\n * @default 'center'\n */\n align?: 'start' | 'center' | 'end'\n}\n\n/**\n * A button element that displays a text label and optionally a start or end icon. It follows the\n * [WAI-ARIA Button Pattern](https://www.w3.org/TR/wai-aria-practices/#button).\n */\nconst Button = React.forwardRef(function Button(\n {\n variant,\n tone = 'normal',\n size = 'normal',\n shape = 'normal',\n type = 'button',\n disabled = false,\n loading = false,\n tooltip,\n render,\n onClick,\n exceptionallySetClassName,\n children,\n startIcon,\n endIcon,\n width = 'auto',\n align = 'center',\n ...props\n },\n ref,\n) {\n const isDisabled = loading || disabled\n const buttonElement = (\n \n <>\n {startIcon ? (\n \n {loading && !endIcon ? : startIcon}\n \n ) : null}\n\n {children ? (\n \n {children}\n \n ) : null}\n\n {endIcon || (loading && !startIcon) ? (\n \n {loading ? : endIcon}\n \n ) : null}\n >\n \n )\n\n return tooltip ? {buttonElement} : buttonElement\n})\n\ninterface IconButtonProps extends CommonButtonProps {\n /**\n * The icon to display inside the button.\n */\n icon: IconElement\n\n /**\n * The button label.\n *\n * It is used for assistive technologies, and it is also shown as a tooltip (if not tooltip is\n * provided explicitly).\n */\n 'aria-label': string\n}\n\n/**\n * A button element that displays an icon only, visually, though it is semantically labelled. It\n * also makes sure to always show a tooltip with its label. It follows the\n * [WAI-ARIA Button Pattern](https://www.w3.org/TR/wai-aria-practices/#button).\n */\nconst IconButton = React.forwardRef(function IconButton(\n {\n variant,\n tone = 'normal',\n size = 'normal',\n shape = 'normal',\n type = 'button',\n disabled = false,\n loading = false,\n tooltip,\n render,\n onClick,\n exceptionallySetClassName,\n children,\n icon,\n ...props\n },\n ref,\n) {\n const isDisabled = loading || disabled\n const buttonElement = (\n \n {(loading && ) || icon}\n \n )\n\n const tooltipContent = tooltip === undefined ? props['aria-label'] : tooltip\n return tooltipContent ? (\n {buttonElement}\n ) : (\n buttonElement\n )\n})\n\nexport type { ButtonProps, IconButtonProps, ButtonVariant, ButtonTone }\nexport { Button, IconButton }\n","import * as React from 'react'\nimport type { AlertTone } from '../utils/common-types'\n\nconst alertIconForTone: Record = {\n info: AlertInfoIcon,\n positive: AlertPositiveIcon,\n caution: AlertCautionIcon,\n critical: AlertCriticalIcon,\n}\n\nfunction AlertIcon({ tone, ...props }: JSX.IntrinsicElements['svg'] & { tone: AlertTone }) {\n const Icon = alertIconForTone[tone]\n return Icon ? : null\n}\n\nfunction AlertInfoIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nfunction AlertPositiveIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nfunction AlertCautionIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nfunction AlertCriticalIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nexport { AlertIcon }\n","import * as React from 'react'\n\nfunction CloseIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nexport { CloseIcon }\n","import * as React from 'react'\nimport { getClassNames } from '../utils/responsive-props'\nimport { Box } from '../box'\nimport { Button } from '../button'\nimport { Columns, Column } from '../columns'\n\nimport { AlertIcon } from '../icons/alert-icon'\nimport { CloseIcon } from '../icons/close-icon'\n\nimport styles from './alert.module.css'\n\nimport type { AlertTone } from '../utils/common-types'\n\ntype AllOrNone = T | { [K in keyof T]?: never }\n\ntype AlertCloseProps = AllOrNone<{\n closeLabel: string\n onClose: () => void\n}>\n\ntype AlertProps = {\n id?: string\n children: React.ReactNode\n tone: AlertTone\n} & AlertCloseProps\n\nfunction Alert({ id, children, tone, closeLabel, onClose }: AlertProps) {\n return (\n \n \n \n \n \n \n \n {children}\n \n \n {onClose != null && closeLabel != null ? (\n \n }\n style={{\n // @ts-expect-error not sure how to make TypeScript understand custom CSS properties\n '--reactist-btn-hover-fill': 'transparent',\n }}\n />\n \n ) : null}\n \n \n )\n}\n\nexport { Alert }\nexport type { AlertProps }\n","import * as React from 'react'\n\nlet uid = 0\nfunction uniqueId() {\n return uid++\n}\n\nexport function generateElementId(prefix: string): string {\n const num = uniqueId()\n return `${prefix}-${num}`\n}\n\nexport function useId(providedId?: string): string {\n const ref = React.useRef(providedId ?? null)\n if (!ref.current) {\n ref.current = generateElementId('element')\n }\n return ref.current\n}\n","import * as React from 'react'\nimport { Box } from '../box'\nimport { Columns, Column } from '../columns'\nimport { useId } from '../utils/common-helpers'\n\nimport styles from './banner.module.css'\n\nexport type BannerTone = 'info' | 'promotion'\n\ntype BannerProps = {\n id?: string\n\n /**\n * The tone of the Banner. Affects the background color and the outline.\n */\n tone: BannerTone\n\n /**\n * The icon that should be added inside the Banner.\n */\n icon: React.ReactElement | string | number\n\n /**\n * The title to be displayed at the top of the Banner.\n */\n title: React.ReactNode\n\n /**\n * An optional description to be displayed inside the Banner.\n */\n description?: React.ReactNode\n\n /**\n * An optional action to displayed inside the Banner.\n */\n action?: React.ReactElement | string | number\n}\n\nconst Banner = React.forwardRef(function Banner(\n { id, tone, icon, title, description, action, ...props }: BannerProps,\n ref,\n) {\n const titleId = useId()\n const descriptionId = useId()\n return (\n \n \n \n {icon}\n \n \n \n {description ? (\n \n {title}\n \n ) : (\n \n {title}\n \n )}\n {description ? (\n \n {description}\n \n ) : null}\n \n \n {action ? {action} : null}\n \n \n )\n})\n\nexport { Banner }\nexport type { BannerProps }\n","import * as React from 'react'\nimport { Box } from '../box'\nimport { Spinner } from '../spinner'\nimport type { ObfuscatedClassName } from '../utils/common-types'\n\ntype Size = 'xsmall' | 'small' | 'medium' | 'large'\n\ntype NativeProps = Omit<\n React.HTMLAttributes,\n 'className' | 'aria-describedby' | 'aria-label' | 'aria-labelledby' | 'role' | 'size'\n>\n\ntype LoadingProps = NativeProps &\n ObfuscatedClassName & {\n /**\n * The size of the loading spinner.\n * @default 'small'\n */\n size?: Size\n\n /**\n * Identifies the element (or elements) that describes the loading component for assistive technologies.\n */\n 'aria-describedby'?: string\n } & (\n | {\n /** Defines a string value that labels the current loading component for assistive technologies. */\n 'aria-label': string\n 'aria-labelledby'?: never\n }\n | {\n /** Identifies the element (or elements) that labels the current loading component for assistive technologies. */\n 'aria-labelledby': string\n 'aria-label'?: never\n }\n )\n\nconst sizeMapping: Record = {\n xsmall: 16,\n small: 24,\n medium: 36,\n large: 48,\n}\n\nfunction Loading({ size = 'small', exceptionallySetClassName, ...props }: LoadingProps) {\n const numericSize = sizeMapping[size] ?? sizeMapping.small\n const ariaLabel = props['aria-label']\n ? props['aria-label']\n : !props['aria-labelledby']\n ? 'Loading…'\n : undefined\n\n return (\n \n \n \n )\n}\n\nexport { Loading }\nexport type { LoadingProps }\n","import * as React from 'react'\nimport { getClassNames } from '../utils/responsive-props'\nimport { Box } from '../box'\nimport { Columns, Column } from '../columns'\nimport { AlertIcon } from '../icons/alert-icon'\n\nimport type { AlertTone } from '../utils/common-types'\n\nimport styles from './notice.module.css'\n\ntype NoticeProps = {\n id?: string\n children: React.ReactNode\n tone: AlertTone\n}\n\nfunction Notice({ id, children, tone }: NoticeProps) {\n return (\n \n \n \n \n \n \n {children}\n \n \n \n )\n}\n\nexport { Notice }\nexport type { NoticeProps }\n","import * as React from 'react'\nimport { getClassNames } from '../utils/responsive-props'\nimport { Box } from '../box'\nimport { polymorphicComponent } from '../utils/polymorphism'\n\nimport type { Tone } from '../utils/common-types'\nimport type { BoxProps } from '../box'\n\nimport styles from './text.module.css'\n\ntype TextProps = {\n children: React.ReactNode\n /**\n * The size of the text.\n *\n * The supported values, from smaller size to larger size, are:\n * 'caption', 'copy', 'body', and 'subtitle'\n *\n * @default 'body'\n */\n size?: 'caption' | 'copy' | 'body' | 'subtitle'\n /**\n * The weight of the text font.\n *\n * @default 'regular'\n */\n weight?: 'regular' | 'semibold' | 'bold'\n /**\n * The tone (semantic color) of the text.\n *\n * @default 'normal'\n */\n tone?: Tone\n /**\n * Used to truncate the text to a given number of lines.\n *\n * It will add an ellipsis (`…`) to the text at the end of the last line, only if the text was\n * truncated. If the text fits without it being truncated, no ellipsis is added.\n *\n * By default, the text is not truncated at all, no matter how many lines it takes to render it.\n *\n * @default undefined\n */\n lineClamp?: 1 | 2 | 3 | 4 | 5 | '1' | '2' | '3' | '4' | '5'\n /**\n * How to align the text horizontally.\n *\n * @default 'start'\n */\n align?: BoxProps['textAlign']\n}\n\nconst Text = polymorphicComponent<'div', TextProps>(function Text(\n {\n as,\n size = 'body',\n weight = 'regular',\n tone = 'normal',\n align,\n children,\n lineClamp,\n exceptionallySetClassName,\n ...props\n },\n ref,\n) {\n const lineClampMultipleLines =\n typeof lineClamp === 'string' ? Number(lineClamp) > 1 : (lineClamp ?? 1) > 1\n\n return (\n \n {children}\n \n )\n})\n\nexport type { TextProps }\nexport { Text }\n","import React from 'react'\n\nimport { CloseIcon } from '../icons/close-icon'\nimport { Box } from '../box'\nimport { IconButton, Button } from '../button'\nimport { Stack } from '../stack'\nimport { Text } from '../text'\n\nimport styles from './toast.module.css'\n\ntype ToastActionObject = {\n label: string\n onClick: () => void\n}\n\ntype StaticToastProps = {\n /**\n * The message shown in the toast.\n */\n message: NonNullable\n\n /**\n * An optional extra description that complements the main message shown in the toast.\n */\n description?: React.ReactNode\n\n /**\n * An icon to be shown in front of the message.\n */\n icon?: React.ReactNode\n\n /**\n * The action to call when the user clicks on the dismiss button. If omitted, the dismiss button\n * does not appear.\n */\n onDismiss?: () => void\n\n /**\n * The label for the button that dismisses the toast.\n */\n dismissLabel?: string\n\n /**\n * What to render in the action slot. Usually a button or link.\n *\n * You can also pass an object that containst the action label, and a function that performs the\n * action. This is used by the toast component to render a button for you.\n *\n * In general, you should prefer the action object most of the time. But it is possible to pass\n * a React element instead, if you need more control over what to render. For instance, you may\n * want to render a link instead of a button.\n *\n * Keep in mind, though, that the default button rendered uses `variant=\"tertiary\"` and\n * `size=\"small\"`. In most cases you should stick to the variants `tertiary` or `primary`, which\n * are the ones that look better in the toast's dark background. And in all cases you should use\n * size `small`.\n */\n action?: React.ReactElement | ToastActionObject\n}\n\n/**\n * A toast that shows a message, and an optional action associated with it.\n *\n * This component is generally not meant to be used directly. Most of the time you'll want to use\n * toasts generated via `useToasts` instead. However, this component is available in case you need\n * to take control of rendering a toast under different circumstances than that of notification-like\n * floating toasts.\n *\n * This component makes no assumptions outwardly about how it is positioned on the screen. That is,\n * it will not be shown floating or fixed to the viewport edges, as toasts normally show up. It only\n * provides the toast look and feel, but you are responsible for positioning it as you want.\n *\n * @see useToasts\n */\nconst StaticToast = React.forwardRef(function Toast(\n { message, description, icon, action, onDismiss, dismissLabel = 'Close', ...props },\n ref,\n) {\n return (\n \n {icon ? {icon} : null}\n\n \n {description ? (\n \n {message} \n {description}\n \n ) : (\n {message}\n )}\n \n\n {action ? (\n \n {isActionObject(action) ? (\n \n ) : (\n action\n )}\n \n ) : null}\n\n {onDismiss ? (\n \n }\n />\n \n ) : null}\n \n )\n})\n\nfunction isActionObject(action: StaticToastProps['action']): action is ToastActionObject {\n return (\n action != null &&\n typeof action === 'object' &&\n 'label' in action &&\n 'onClick' in action &&\n typeof action.label === 'string' &&\n typeof action.onClick === 'function'\n )\n}\n\nfunction ToastContentSlot({ children }: { children: React.ReactNode }) {\n return (\n \n {children}\n \n )\n}\n\nexport { StaticToast, isActionObject }\nexport type { StaticToastProps }\n","/**\n * Adapted with minor changes from https://github.com/seek-oss/braid-design-system/blob/7a5ebccb/packages/braid-design-system/lib/components/useToast/useFlipList.ts\n *\n * MIT License\n *\n * Copyright (c) 2018 SEEK\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { useMemo, useCallback, useLayoutEffect } from 'react'\n\nconst ANIMATION_TIMEOUT = 400\nconst ENTRANCE_TRANSITION = 'transform 0.3s ease, opacity 0.3s ease'\nconst EXIT_TRANSITION = 'opacity 0.2s ease'\n\ntype Transform = {\n property: 'opacity' | 'transform' | 'scale'\n from?: string\n to?: string\n}\n\n/**\n * Applies the \"from\" value of given CSS properties, and also sets a transition CSS property. Then\n * it waits an animation frame before setting the same CSS properties to the target \"to\" value. This\n * triggers the browser to perform the CSS transition on them.\n *\n * At the end of the animation, it cleans up, unsetting all the CSS properties (including the\n * transition), and calls the \"done\" callback, if given.\n */\nfunction animate({\n element,\n transforms,\n transition,\n done,\n}: {\n element: HTMLElement\n transforms: Transform[]\n transition: string\n done?: () => void\n}) {\n const fallbackTimeout = setTimeout(() => {\n done?.()\n }, ANIMATION_TIMEOUT)\n\n transforms.forEach(({ property, from = '' }) => {\n element.style.setProperty(property, from)\n })\n element.style.setProperty('transition', '')\n\n function transitionEndHandler(event: TransitionEvent) {\n if (event.target !== element) {\n return\n }\n element.style.setProperty('transition', '')\n done?.()\n element.removeEventListener('transitionend', transitionEndHandler)\n clearTimeout(fallbackTimeout)\n }\n\n element.addEventListener('transitionend', transitionEndHandler)\n\n // Call requestAnimationFrame twice to make sure we have a full animation frame at our disposal\n window.requestAnimationFrame(() => {\n window.requestAnimationFrame(() => {\n element.style.setProperty('transition', transition)\n transforms.forEach(({ property, to = '' }) => {\n element.style.setProperty(property, to)\n })\n })\n })\n}\n\ntype ToastsAnimationToolkit = {\n /**\n * Used for gathering all the active stacked toast elements. Should be used by passing\n * `ref={mappedRef(toastId)}` to the stacked toasts.\n */\n mappedRef: (toastId: string) => (ref: HTMLElement | null) => void\n\n /**\n * The stacked toasts view should use this callback when it needs to remove a toast, instead of\n * removing it right away. The actual removal from the state (and consequently, from the DOM)\n * should happen in the `onAnimationDone` instead.\n */\n animateRemove: (toastId: string, onAnimationDone: () => void) => void\n}\n\n/**\n * Provides the functionality of animating the stacked toasts when they appear and before they\n * disappear.\n *\n * It works by keeping a mapping from toast IDs to the toast elements, and keeping a mapping from\n * toast IDs to their top position. Then, on every single re-render, it compares the new DOM\n * situation with the previously stored one in these mappings. With this information, it applies\n * animations that smoothly transitions between both states.\n */\nfunction useToastsAnimation(): ToastsAnimationToolkit {\n const refs = useMemo(() => new Map(), [])\n const positions = useMemo(() => new Map(), [])\n\n useLayoutEffect(() => {\n const animations: Array<{\n element: HTMLElement\n transforms: Transform[]\n transition: string\n }> = []\n\n Array.from(refs.entries()).forEach(([id, element]) => {\n if (!element) {\n refs.delete(id)\n return\n }\n\n const prevTop = positions.get(id)\n const { top, height } = element.getBoundingClientRect()\n\n if (typeof prevTop === 'number' && prevTop !== top) {\n // Move animation\n animations.push({\n element,\n transition: ENTRANCE_TRANSITION,\n transforms: [{ property: 'transform', from: `translateY(${prevTop - top}px)` }],\n })\n } else if (typeof prevTop !== 'number') {\n // Enter animation\n animations.push({\n element,\n transition: ENTRANCE_TRANSITION,\n transforms: [\n { property: 'transform', from: `translateY(${height}px)` },\n { property: 'opacity', from: '0' },\n ],\n })\n }\n\n positions.set(id, element.getBoundingClientRect().top)\n })\n\n animations.forEach(({ element, transforms, transition }) => {\n animate({ element, transforms, transition })\n })\n })\n\n const animateRemove = useCallback(\n function animateRemove(id: string, onAnimationDone: () => void) {\n const element = refs.get(id)\n if (element) {\n // Removal animation\n animate({\n element,\n transforms: [{ property: 'opacity', to: '0' }],\n transition: EXIT_TRANSITION,\n done: onAnimationDone,\n })\n }\n },\n [refs],\n )\n\n const mappedRef = useCallback(\n (id: string) => (ref: HTMLElement | null) => {\n refs.set(id, ref)\n },\n [refs],\n )\n\n return { mappedRef, animateRemove }\n}\n\nexport { ANIMATION_TIMEOUT, useToastsAnimation }\n","import React from 'react'\nimport { Portal } from '@ariakit/react'\n\nimport { generateElementId } from '../utils/common-helpers'\nimport { Box } from '../box'\nimport { Stack } from '../stack'\nimport { isActionObject, StaticToast, StaticToastProps } from './static-toast'\n\nimport styles from './toast.module.css'\n\nimport type { Space } from '../utils/common-types'\nimport { useToastsAnimation } from './toast-animation'\n\n/**\n * The props needed to fire up a new notification toast.\n */\ntype ToastProps = StaticToastProps & {\n /**\n * The number of seconds the toast is expected to be shown before it is dismissed automatically,\n * or false to disable auto-dismiss.\n *\n * It defaults to whatever is the autoDismissDelay set in the ToastsProvider.\n */\n autoDismissDelay?: number | false\n\n /**\n * The label for the button that dismisses the toast.\n *\n * It defaults to the value set in the ToastsProvider, but individual toasts can have a\n * different value if needed.\n */\n dismissLabel?: string\n\n /**\n * Whether to show the dismiss button or not.\n *\n * Use this value with care. If combined with disabling `autoDismissDelay`, it may leave you\n * with toasts that the user won't be able to dismiss at will. It then is your responsibility to\n * dismiss the toast by calling the function returned by `showToast`.\n */\n showDismissButton?: boolean\n}\n\n//\n// InternalToast component and its props\n//\n\ntype InternalToastProps = Omit &\n Required> & {\n toastId: string\n onRemoveToast: (toastId: string) => void\n }\n\n/** @private */\nconst InternalToast = React.forwardRef(function InternalToast(\n {\n message,\n description,\n icon,\n action,\n autoDismissDelay,\n dismissLabel,\n showDismissButton = true,\n toastId,\n onDismiss,\n onRemoveToast,\n },\n ref,\n) {\n const [timeoutRunning, setTimeoutRunning] = React.useState(Boolean(autoDismissDelay))\n const timeoutRef = React.useRef()\n\n const startTimeout = React.useCallback(function startTimeout() {\n setTimeoutRunning(true)\n }, [])\n\n const stopTimeout = React.useCallback(function stopTimeout() {\n setTimeoutRunning(false)\n clearTimeout(timeoutRef.current)\n timeoutRef.current = undefined\n }, [])\n\n const removeToast = React.useCallback(\n function removeToast() {\n onRemoveToast(toastId)\n onDismiss?.()\n },\n [onDismiss, onRemoveToast, toastId],\n )\n\n React.useEffect(\n function setupAutoDismiss() {\n if (!timeoutRunning || !autoDismissDelay) return\n timeoutRef.current = window.setTimeout(removeToast, autoDismissDelay * 1000)\n return stopTimeout\n },\n [autoDismissDelay, removeToast, stopTimeout, timeoutRunning],\n )\n\n /**\n * If the action is toast action object and not a custom element,\n * the `onClick` property is wrapped in another handler responsible\n * for removing the toast when the action is triggered.\n */\n const actionWithCustomActionHandler = React.useMemo(() => {\n if (!isActionObject(action)) {\n return action\n }\n\n return {\n ...action,\n onClick: function handleActionClick() {\n if (!action) {\n return\n }\n\n action.onClick()\n removeToast()\n },\n }\n }, [action, removeToast])\n\n return (\n \n )\n})\n\n//\n// Internal state and context\n//\n\ntype InternalToastEntry = Omit\ntype ToastsList = readonly InternalToastEntry[]\n\ntype ShowToastAction = (props: ToastProps) => () => void\nconst ToastsContext = React.createContext(() => () => undefined)\n\n/**\n * The props needed by the ToastsProvider component.\n *\n * @see ToastsProvider\n */\ntype ToastsProviderProps = {\n /**\n * The default label to apply to toast dismiss buttons.\n *\n * This is useful in environments that need locatization, so you do not need to pass the same\n * translated label every time you trigger a toast.\n *\n * However, you can still apply a different label to a specific toast, by passing a different\n * value when calling showToast.\n *\n * @default 'Close'\n */\n defaultDismissLabel?: string\n\n /**\n * The default number of seconds after which the toast will be dismissed automatically.\n *\n * You can pass a different value to a specific toast when calling `showToast`. You can even\n * pass `false` if you want a certain toast to never be dismissed automatically.\n *\n * @default 10 (seconds)\n */\n defaultAutoDismissDelay?: number\n\n /**\n * The padding used to separate the toasts from the viewport borders.\n *\n * @default 'large'\n */\n padding?: Space\n\n /**\n * The app wrapped by the provider.\n */\n children: NonNullable\n\n /**\n * Custom classname for the toasts container, if you need to fine-tune the position or other styles\n */\n containerClassName?: string\n}\n\n/**\n * Provides the state management and rendering of the toasts currently active.\n *\n * You need to render this near the top of your app components tree, in order to `useToasts`.\n *\n * @see useToasts\n */\nfunction ToastsProvider({\n children,\n padding = 'large',\n defaultAutoDismissDelay = 10 /* seconds */,\n defaultDismissLabel = 'Close',\n containerClassName,\n}: ToastsProviderProps) {\n const [toasts, setToasts] = React.useState([])\n const { mappedRef, animateRemove } = useToastsAnimation()\n\n const removeToast = React.useCallback(\n function onRemoveToast(toastId: string) {\n animateRemove(toastId, () => {\n setToasts((list) => {\n const index = list.findIndex((n) => n.toastId === toastId)\n if (index < 0) return list\n const copy = [...list]\n copy.splice(index, 1)\n return copy\n })\n })\n },\n [animateRemove],\n )\n\n const showToast = React.useCallback(\n function showToast(props: ToastProps) {\n const toastId = generateElementId('toast')\n const newToast: InternalToastEntry = {\n autoDismissDelay: defaultAutoDismissDelay,\n dismissLabel: defaultDismissLabel,\n ...props,\n toastId,\n }\n setToasts((list) => [...list, newToast])\n return () => removeToast(toastId)\n },\n [defaultAutoDismissDelay, defaultDismissLabel, removeToast],\n )\n\n return (\n \n {children}\n \n {toasts.length === 0 ? null : (\n \n \n {toasts.map(({ toastId, ...props }) => (\n \n ))}\n \n \n )}\n \n \n )\n}\n\n/**\n * Provides a function `showToast` that shows a new toast every time you call it.\n *\n * ```jsx\n * const showToast = useToasts()\n *\n * \n * ```\n *\n * All toasts fired via this function are rendered in a global fixed location, and stacked one on\n * top of the other.\n *\n * When called, `showToast` returns a function that dismisses the toast when called.\n *\n * @see ToastsProvider\n */\nfunction useToasts() {\n return React.useContext(ToastsContext)\n}\n\n/**\n * Adds a toast to be rendered, stacked alongside any other currently active toasts.\n *\n * For most situations, you should prefer to use the `showToast` function obtained from `useToasts`.\n * This component is provided for convenience to render toasts in the markup, but it has some\n * peculiarities, which are discussed below.\n *\n * Internally, this calls `showToast`. It is provided for two reasons:\n *\n * 1. Convenience, when you want to fire a toast in markup/jsx code. Keep in mind, though, that\n * toasts rendered in this way will be removed from view when the context where it is rendered\n * is unmounted. Unlike toasts fired with `showToast`, which will normally be dismissed, either\n * by the user or after a delay. They'll still be animated on their way out, though.\n * 2. When combined with disabling dismissing it (e.g. `showDismissButton={false}` and\n * `autoDismissDelay={false}` it provides a way to show \"permanent\" toasts that only go away when\n * the component ceases to be rendered).\n *\n * This is useful for cases when the consumer wants to control when a toast is visible, and to keep\n * it visible based on an app-specific condition.\n *\n * Something important to note about this component is that it triggers the toast based on the props\n * passed when first rendered, and it does not update the toast if these props change on subsequent\n * renders. In this sense, this is an imperative component, more than a descriptive one. This is\n * done to simplify the internals, and to keep it in line with how `showToast` works: you fire up a\n * toast imperatively, and you loose control over it. It remains rendered according to the props you\n * first passed.\n *\n * @see useToasts\n */\nfunction Toast(props: ToastProps) {\n const showToast = useToasts()\n const propsRef = React.useRef(props)\n React.useEffect(() => {\n const dismissToast = showToast(propsRef.current)\n return dismissToast\n }, [showToast])\n return null\n}\n\nexport { Toast, ToastsProvider, useToasts }\nexport type { ToastProps, ToastsProviderProps }\n","import * as React from 'react'\nimport { getClassNames } from '../utils/responsive-props'\nimport { Box } from '../box'\nimport styles from './heading.module.css'\nimport type { ObfuscatedClassName, Tone } from '../utils/common-types'\nimport type { BoxProps } from '../box'\n\ntype HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6 | '1' | '2' | '3' | '4' | '5' | '6'\ntype HeadingElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n\ntype HeadingProps = Omit, 'className' | 'children'> & {\n children: React.ReactNode\n /**\n * The semantic level of the heading.\n */\n level: HeadingLevel\n\n /**\n * The weight of the heading. Used to de-emphasize the heading visually when using 'medium' or 'light'.\n *\n * @default 'regular'\n */\n weight?: 'regular' | 'medium' | 'light'\n\n /**\n * Shifts the default heading visual text size up or down, depending on the original size\n * imposed by the `level`. The heading continues to be semantically at the given level.\n *\n * By default, no value is applied, and the default size from the level is applied. The values\n * have the following effect:\n *\n * - 'smaller' shifts the default level size down in the font-size scale (it tends to make the\n * level look visually as if it were of the immediately lower level).\n * - 'larger' has the opposite effect than 'smaller' shifting the visual font size up in the\n * scale.\n * - 'largest' can be thought of as applying 'larger' twice.\n *\n * @see level\n * @default undefined\n */\n size?: 'smaller' | 'larger' | 'largest'\n\n /**\n * The tone (semantic color) of the heading.\n *\n * @default 'normal'\n */\n tone?: Tone\n\n /**\n * Used to truncate the heading to a given number of lines.\n *\n * It will add an ellipsis (`…`) to the text at the end of the last line, only if the text was\n * truncated. If the text fits without it being truncated, no ellipsis is added.\n *\n * By default, the text is not truncated at all, no matter how many lines it takes to render it.\n *\n * @default undefined\n */\n lineClamp?: 1 | 2 | 3 | 4 | 5 | '1' | '2' | '3' | '4' | '5'\n\n /**\n * How to align the heading text horizontally.\n *\n * @default 'start'\n */\n align?: BoxProps['textAlign']\n}\n\nconst Heading = React.forwardRef(\n function Heading(\n {\n level,\n weight = 'regular',\n size,\n tone = 'normal',\n children,\n lineClamp,\n align,\n exceptionallySetClassName,\n ...props\n },\n ref,\n ) {\n // In TypeScript v4.1, this would be properly recognized without needing the type assertion\n // https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types\n const headingElementName = `h${level}` as HeadingElement\n const lineClampMultipleLines =\n typeof lineClamp === 'string' ? parseInt(lineClamp, 10) > 1 : (lineClamp || 0) > 1\n\n return (\n \n {children}\n \n )\n },\n)\n\nexport type { HeadingProps, HeadingLevel }\nexport { Heading }\n","import * as React from 'react'\nimport { Box } from '../box'\nimport styles from './prose.module.css'\nimport type { ObfuscatedClassName } from '../utils/common-types'\n\ninterface ProseProps extends ObfuscatedClassName {\n /**\n * The prose content.\n *\n * This must consist of React nodes and elements. It is the consumer’s responsibility to\n * generate this from other sources, such as converting raw markdown content to React elements,\n * etc.\n *\n * Alternatively, you can use ``\n * instead.\n */\n children?: React.ReactNode\n\n /**\n * Sets the prose content to be raw HTML stored in a string value.\n *\n * Warning: be advised that setting HTML content in this way is risky, because you can\n * inadvertently be vulnerable to a cross-site scripting (XSS) attack. Make sure you only use\n * this option with HTML content that has been sanitized (especially if it comes from user\n * provided content) or content that you fully control how it's generated, that cannot possibly\n * have any XSS content in it.\n *\n * @see https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml\n */\n dangerouslySetInnerHTML?: { __html: string } | undefined\n\n /**\n * Whether to customize the typography styles for dark mode.\n *\n * Applies finessed optimizations since our eyes perceive space differently when looking at dark\n * text on a light background and light text on a dark background.\n *\n * This does not apply a dark theme on the text. That's still the consumer apps’ responsibility.\n */\n darkModeTypography: boolean\n}\n\n/**\n * Used to style HTML you don’t control, like HTML content generated from Markdown.\n */\nfunction Prose({ darkModeTypography, exceptionallySetClassName, ...props }: ProseProps) {\n return (\n \n )\n}\n\nexport { Prose }\nexport type { ProseProps }\n","import * as React from 'react'\nimport { Box } from '../box'\nimport { polymorphicComponent } from '../utils/polymorphism'\nimport styles from './text-link.module.css'\nimport type { OpenInNewTab } from '../utils/common-types'\n\ntype TextLinkProps = OpenInNewTab\n\nconst TextLink = polymorphicComponent<'a', TextLinkProps>(function TextLink(\n { as = 'a', openInNewTab = false, exceptionallySetClassName, ...props },\n ref,\n) {\n return (\n \n )\n})\n\nexport { TextLink }\nexport type { TextLinkProps }\n","import * as React from 'react'\n\nconst svgPath = {\n checked:\n 'M18 4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h12zm-2.457 4.293l-5.293 5.293-1.793-1.793a1 1 0 1 0-1.414 1.414l2.5 2.5a1 1 0 0 0 1.414 0l6-6a1 1 0 1 0-1.414-1.414z',\n unchecked:\n 'M18 4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h12zm0 1H6a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1z',\n mixed:\n 'M18 4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h12zm-2 7H8a1 1 0 0 0 0 2h8a1 1 0 0 0 0-2z',\n filled:\n 'M6 4H18C19.1046 4 20 4.89543 20 6V18C20 19.1046 19.1046 20 18 20H6C4.89543 20 4 19.1046 4 18V6C4 4.89543 4.89543 4 6 4Z',\n} as const\n\ntype Props = React.SVGProps & {\n checked?: boolean\n indeterminate?: boolean\n disabled?: boolean\n}\n\nfunction getPathKey({ checked, indeterminate, disabled }: Props): keyof typeof svgPath {\n if (indeterminate) {\n return 'mixed' // indeterminate, when true, overrides the checked state\n }\n\n if (checked) {\n return 'checked'\n }\n\n // We only used 'filled' when unchecked AND disabled, because the default unchecked icon\n // is not enough to convey the disabled state with opacity alone. For all other cases\n // above, when disabled, we use the same icon the corresponds to that state, and the\n // opacity conveys the fact that the checkbox is disabled.\n // See https://twist.com/a/1585/ch/414345/t/2257308/c/65201390\n if (disabled) {\n return 'filled'\n }\n\n return 'unchecked'\n}\n\nfunction CheckboxIcon({ checked, indeterminate, disabled, ...props }: Props) {\n const pathKey = getPathKey({ checked, indeterminate, disabled })\n return (\n \n )\n}\n\nexport { CheckboxIcon }\n","import { useMemo } from 'react'\n\n/**\n * Sets both a function and object React ref.\n */\nfunction setRef(\n ref: React.RefCallback | React.MutableRefObject | null | undefined,\n value: T,\n) {\n if (typeof ref === 'function') {\n ref(value)\n } else if (ref) {\n ref.current = value\n }\n}\n\n/**\n * Merges React Refs into a single memoized function ref so you can pass it to an element.\n * @example\n * const Component = React.forwardRef((props, ref) => {\n * const internalRef = React.useRef();\n * return ;\n * });\n */\nfunction useForkRef(...refs: Array | undefined>) {\n return useMemo(\n () => {\n if (!refs.some(Boolean)) return\n return (value: unknown) => {\n refs.forEach((ref) => setRef(ref, value))\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n refs,\n )\n}\n\nexport { useForkRef }\n","import * as React from 'react'\nimport { Box } from '../box'\nimport { Text } from '../text'\nimport { CheckboxIcon } from './checkbox-icon'\n\nimport styles from './checkbox-field.module.css'\nimport { useForkRef } from './use-fork-ref'\n\ninterface CheckboxFieldProps\n extends Omit<\n JSX.IntrinsicElements['input'],\n | 'type'\n | 'className'\n | 'disabled'\n | 'aria-controls'\n | 'aria-describedby'\n | 'aria-label'\n | 'aria-labelledby'\n > {\n 'aria-checked'?: never\n /**\n *\n * Identifies the set of checkboxes controlled by the mixed checkbox for assistive technologies.\n */\n 'aria-controls'?: string\n\n /**\n * Identifies the element (or elements) that describes the checkbox for assistive technologies.\n */\n 'aria-describedby'?: string\n\n /**\n * Defines a string value that labels the current checkbox for assistive technologies.\n */\n 'aria-label'?: string\n\n /**\n * Identifies the element (or elements) that labels the current checkbox for assistive technologies.\n */\n 'aria-labelledby'?: string\n\n /**\n * Defines whether or not the checkbox is disabled.\n */\n disabled?: boolean\n\n /**\n * The label for the checkbox element.\n */\n label?: React.ReactNode\n\n /**\n * The icon that should be added to the checkbox label.\n */\n icon?: React.ReactElement | string | number\n\n /**\n * Defines whether or not the checkbox can be of a `mixed` state.\n */\n indeterminate?: boolean\n}\n\nconst CheckboxField = React.forwardRef(function CheckboxField(\n { label, icon, disabled, indeterminate, defaultChecked, onChange, ...props },\n ref,\n) {\n const isControlledComponent = typeof props.checked === 'boolean'\n if (typeof indeterminate === 'boolean' && !isControlledComponent) {\n // eslint-disable-next-line no-console\n console.warn('Cannot use indeterminate on an uncontrolled checkbox')\n indeterminate = undefined\n }\n\n if (!label && !props['aria-label'] && !props['aria-labelledby']) {\n // eslint-disable-next-line no-console\n console.warn('A Checkbox needs a label')\n }\n\n const [keyFocused, setKeyFocused] = React.useState(false)\n const [checkedState, setChecked] = React.useState(props.checked ?? defaultChecked ?? false)\n const isChecked = props.checked ?? checkedState\n\n const internalRef = React.useRef(null)\n const combinedRef = useForkRef(internalRef, ref)\n React.useEffect(\n function setIndeterminate() {\n if (internalRef.current && typeof indeterminate === 'boolean') {\n internalRef.current.indeterminate = indeterminate\n }\n },\n [indeterminate],\n )\n\n return (\n \n {\n onChange?.(event)\n if (!event.defaultPrevented) {\n setChecked(event.currentTarget.checked)\n }\n }}\n onBlur={(event) => {\n setKeyFocused(false)\n props?.onBlur?.(event)\n }}\n onKeyUp={(event) => {\n setKeyFocused(true)\n props?.onKeyUp?.(event)\n }}\n />\n \n {icon ? (\n \n {icon}\n \n ) : null}\n {label ? (\n \n {label}\n \n ) : null}\n \n )\n})\n\nexport { CheckboxField }\nexport type { CheckboxFieldProps }\n","import * as React from 'react'\n\nfunction PasswordVisibleIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nexport { PasswordVisibleIcon }\n","import * as React from 'react'\n\nfunction PasswordHiddenIcon(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nexport { PasswordHiddenIcon }\n","import * as React from 'react'\nimport { Box, BoxProps } from '../box'\nimport { useId } from '../utils/common-helpers'\nimport { Text } from '../text'\nimport styles from './base-field.module.css'\nimport { Stack } from '../stack'\n\nimport type { WithEnhancedClassName } from '../utils/common-types'\nimport { Spinner } from '../spinner'\nimport { Column, Columns } from '../columns'\n\nconst MAX_CHARACTER_LENGTH_THRESHOLD = 10\n\ntype FieldTone = 'neutral' | 'success' | 'error' | 'loading'\n\ntype FieldMessageProps = {\n id: string\n children: React.ReactNode\n tone: FieldTone\n}\n\nfunction fieldToneToTextTone(tone: FieldTone) {\n return tone === 'error' ? 'danger' : tone === 'success' ? 'positive' : 'secondary'\n}\n\nfunction FieldMessage({ id, children, tone }: FieldMessageProps) {\n return (\n \n \n {tone === 'loading' ? : null}\n \n {children}\n \n )\n}\n\ntype FieldCharacterCountProps = {\n children: React.ReactNode\n tone: FieldTone\n}\n\nfunction FieldCharacterCount({ children, tone }: FieldCharacterCountProps) {\n return (\n \n {children}\n \n )\n}\n\n//\n// BaseField\n//\n\ntype ChildrenRenderProps = {\n id: string\n 'aria-describedby'?: string\n 'aria-invalid'?: true\n onChange?: React.ChangeEventHandler\n}\n\ntype HtmlInputProps = React.DetailedHTMLProps<\n React.InputHTMLAttributes,\n T\n>\n\ntype BaseFieldVariant = 'default' | 'bordered'\ntype BaseFieldVariantProps = {\n /**\n * Provides alternative visual layouts or modes that the field can be rendered in.\n *\n * Namely, there are two variants supported:\n *\n * - the default one\n * - a \"bordered\" variant, where the border of the field surrounds also the labels, instead\n * of just surrounding the actual field element\n *\n * In both cases, the message and description texts for the field lie outside the bordered\n * area.\n */\n variant?: BaseFieldVariant\n}\n\ntype BaseFieldProps = WithEnhancedClassName &\n Pick, 'id' | 'hidden' | 'maxLength' | 'aria-describedby'> & {\n /**\n * The main label for this field element.\n *\n * This prop is not optional. Consumers of field components must be explicit about not\n * wanting a label by passing `label=\"\"` or `label={null}`. In those situations, consumers\n * should make sure that fields are properly labelled semantically by other means (e.g using\n * `aria-labelledby`, or rendering a `` element referencing the field by id).\n *\n * Avoid providing interactive elements in the label. Prefer `auxiliaryLabel` for that.\n *\n * @see BaseFieldProps['auxiliaryLabel']\n */\n label: React.ReactNode\n\n /**\n * An optional extra element to be placed to the right of the main label.\n *\n * This extra element is not included in the accessible name of the field element. Its only\n * purpose is either visual, or functional (if you include interactive elements in it).\n *\n * @see BaseFieldProps['label']\n */\n auxiliaryLabel?: React.ReactNode\n\n /**\n * A message associated with the field. It is rendered below the field, and with an\n * appearance that conveys the tone of the field (e.g. coloured red for errors, green for\n * success, etc).\n *\n * The message element is associated to the field via the `aria-describedby` attribute.\n *\n * In the future, when `aria-errormessage` gets better user agent support, we should use it\n * to associate the filed with a message when tone is `\"error\"`.\n *\n * @see BaseFieldProps['tone']\n * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-errormessage\n * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-invalid\n */\n message?: React.ReactNode\n\n /**\n * The tone with which the message, if any, is presented.\n *\n * If the tone is `\"error\"`, the field border turns red, and the message, if any, is also\n * red.\n *\n * When the tone is `\"loading\"`, it is recommended that you also disable the field. However,\n * this is not enforced by the component. It is only a recommendation.\n *\n * @see BaseFieldProps['message']\n * @see BaseFieldProps['hint']\n */\n tone?: FieldTone\n\n /**\n * The maximum width that the input field can expand to.\n */\n maxWidth?: BoxProps['maxWidth']\n\n /**\n * Used internally by components composed using `BaseField`. It is not exposed as part of\n * the public props of such components.\n */\n children: (props: ChildrenRenderProps) => React.ReactNode\n }\n\ntype FieldComponentProps = Omit<\n BaseFieldProps,\n 'children' | 'className' | 'variant'\n> &\n Omit, 'className' | 'style'>\n\nfunction BaseField({\n variant = 'default',\n label,\n auxiliaryLabel,\n message,\n tone = 'neutral',\n className,\n children,\n maxWidth,\n maxLength,\n hidden,\n 'aria-describedby': originalAriaDescribedBy,\n id: originalId,\n}: BaseFieldProps & BaseFieldVariantProps & WithEnhancedClassName) {\n const id = useId(originalId)\n const messageId = useId()\n\n const [characterCount, setCharacterCount] = React.useState(\n maxLength ? `0/${maxLength}` : null,\n )\n const [characterCountTone, setCharacterCountTone] = React.useState('neutral')\n\n const ariaDescribedBy = originalAriaDescribedBy ?? (message ? messageId : null)\n\n const childrenProps: ChildrenRenderProps = {\n id,\n ...(ariaDescribedBy ? { 'aria-describedby': ariaDescribedBy } : {}),\n 'aria-invalid': tone === 'error' ? true : undefined,\n onChange(event) {\n if (!maxLength) {\n return\n }\n\n const currentLength = event.currentTarget.value.length\n const isNearCharacterLimit = maxLength - currentLength <= MAX_CHARACTER_LENGTH_THRESHOLD\n\n setCharacterCount(`${currentLength}/${maxLength}`)\n setCharacterCountTone(isNearCharacterLimit ? 'error' : 'neutral')\n },\n }\n\n return (\n \n \n {label || auxiliaryLabel ? (\n \n \n {label ? {label} : null}\n \n {auxiliaryLabel ? (\n \n {auxiliaryLabel}\n \n ) : null}\n \n ) : null}\n {children(childrenProps)}\n \n {message || characterCount ? (\n \n {message ? (\n \n \n {message}\n \n \n ) : null}\n {characterCount ? (\n \n \n {characterCount}\n \n \n ) : null}\n \n ) : null}\n \n )\n}\n\nexport { BaseField, FieldMessage }\nexport type { BaseFieldVariant, BaseFieldVariantProps, FieldComponentProps }\n","import * as React from 'react'\nimport { BaseField, BaseFieldVariantProps } from '../base-field'\nimport { Box } from '../box'\nimport styles from './text-field.module.css'\nimport type { FieldComponentProps } from '../base-field'\nimport { useMergeRefs } from 'use-callback-ref'\n\ntype TextFieldType = 'email' | 'search' | 'tel' | 'text' | 'url'\n\ninterface TextFieldProps\n extends Omit, 'type'>,\n BaseFieldVariantProps {\n type?: TextFieldType\n startSlot?: React.ReactElement | string | number\n endSlot?: React.ReactElement | string | number\n}\n\nconst TextField = React.forwardRef(function TextField(\n {\n variant = 'default',\n id,\n label,\n auxiliaryLabel,\n message,\n tone,\n type = 'text',\n maxWidth,\n maxLength,\n hidden,\n 'aria-describedby': ariaDescribedBy,\n startSlot,\n endSlot,\n onChange: originalOnChange,\n ...props\n },\n ref,\n) {\n const internalRef = React.useRef(null)\n const combinedRef = useMergeRefs([ref, internalRef])\n\n function handleClick(event: React.MouseEvent) {\n if (event.currentTarget === combinedRef.current) return\n internalRef.current?.focus()\n }\n\n return (\n \n {({ onChange, ...extraProps }) => (\n \n {startSlot ? (\n \n {startSlot}\n \n ) : null}\n {\n originalOnChange?.(event)\n onChange?.(event)\n }}\n />\n {endSlot ? (\n \n {endSlot}\n \n ) : null}\n \n )}\n \n )\n})\n\nexport { TextField }\nexport type { TextFieldProps, TextFieldType }\n","import * as React from 'react'\n\nimport { PasswordVisibleIcon } from '../icons/password-visible-icon'\nimport { PasswordHiddenIcon } from '../icons/password-hidden-icon'\n\nimport { TextField, TextFieldProps } from '../text-field'\nimport { IconButton } from '../button'\n\nimport type { BaseFieldVariantProps } from '../base-field'\n\ninterface PasswordFieldProps\n extends Omit,\n BaseFieldVariantProps {\n togglePasswordLabel?: string\n}\n\nconst PasswordField = React.forwardRef(function PasswordField(\n { togglePasswordLabel = 'Toggle password visibility', ...props },\n ref,\n) {\n const [isPasswordVisible, setPasswordVisible] = React.useState(false)\n const Icon = isPasswordVisible ? PasswordVisibleIcon : PasswordHiddenIcon\n return (\n }\n aria-label={togglePasswordLabel}\n onClick={() => setPasswordVisible((v) => !v)}\n />\n }\n />\n )\n})\n\nexport { PasswordField }\nexport type { PasswordFieldProps }\n","import * as React from 'react'\nimport { BaseField, BaseFieldVariantProps, FieldComponentProps } from '../base-field'\nimport { Box } from '../box'\nimport styles from './select-field.module.css'\n\ninterface SelectFieldProps extends FieldComponentProps, BaseFieldVariantProps {}\n\nconst SelectField = React.forwardRef(function SelectField(\n {\n variant = 'default',\n id,\n label,\n auxiliaryLabel,\n message,\n tone,\n maxWidth,\n children,\n hidden,\n 'aria-describedby': ariaDescribedBy,\n onChange: originalOnChange,\n ...props\n },\n ref,\n) {\n return (\n \n {(extraProps) => (\n \n \n \n \n )}\n \n )\n})\n\nfunction SelectChevron(props: JSX.IntrinsicElements['svg']) {\n return (\n \n )\n}\n\nexport { SelectField }\nexport type { SelectFieldProps }\n","import * as React from 'react'\nimport { Box } from '../box'\nimport { Stack } from '../stack'\nimport { Text } from '../text'\nimport { HiddenVisually } from '../hidden-visually'\nimport { FieldComponentProps, FieldMessage } from '../base-field'\nimport { useId } from '../utils/common-helpers'\nimport styles from './switch-field.module.css'\n\ninterface SwitchFieldProps\n extends Omit<\n FieldComponentProps,\n | 'type'\n | 'auxiliaryLabel'\n | 'maxWidth'\n | 'aria-describedby'\n | 'aria-label'\n | 'aria-labelledby'\n > {\n /**\n * Identifies the element (or elements) that describes the switch for assistive technologies.\n */\n 'aria-describedby'?: string\n\n /**\n * Defines a string value that labels the current switch for assistive technologies.\n */\n 'aria-label'?: string\n\n /**\n * Identifies the element (or elements) that labels the current switch for assistive technologies.\n */\n 'aria-labelledby'?: string\n}\n\nconst SwitchField = React.forwardRef(function SwitchField(\n {\n label,\n message,\n tone = 'neutral',\n disabled = false,\n hidden,\n defaultChecked,\n id: originalId,\n 'aria-describedby': originalAriaDescribedBy,\n 'aria-label': originalAriaLabel,\n 'aria-labelledby': originalAriaLabelledby,\n onChange,\n ...props\n },\n ref,\n) {\n const id = useId(originalId)\n const messageId = useId()\n\n const ariaDescribedBy = originalAriaDescribedBy ?? (message ? messageId : undefined)\n const ariaLabel = originalAriaLabel ?? undefined\n const ariaLabelledBy = originalAriaLabelledby ?? undefined\n\n const [keyFocused, setKeyFocused] = React.useState(false)\n const [checkedState, setChecked] = React.useState(props.checked ?? defaultChecked ?? false)\n const isChecked = props.checked ?? checkedState\n\n return (\n \n \n \n \n {\n onChange?.(event)\n if (!event.defaultPrevented) {\n setChecked(event.currentTarget.checked)\n }\n }}\n onBlur={(event) => {\n setKeyFocused(false)\n props?.onBlur?.(event)\n }}\n onKeyUp={(event) => {\n setKeyFocused(true)\n props?.onKeyUp?.(event)\n }}\n />\n \n \n \n {label}\n \n {message ? (\n \n {message}\n \n ) : null}\n \n )\n})\n\nexport { SwitchField }\nexport type { SwitchFieldProps }\n","import * as React from 'react'\nimport classNames from 'classnames'\nimport { useMergeRefs } from 'use-callback-ref'\nimport { BaseField, BaseFieldVariantProps, FieldComponentProps } from '../base-field'\nimport { Box } from '../box'\nimport styles from './text-area.module.css'\n\ninterface TextAreaProps extends FieldComponentProps, BaseFieldVariantProps {\n /**\n * The number of visible text lines for the text area.\n *\n * If it is specified, it must be a positive integer. If it is not specified, the default\n * value is 2 (set by the browser).\n *\n * When `autoExpand` is true, this value serves the purpose of specifying the minimum number\n * of rows that the textarea will shrink to when the content is not large enough to make it\n * expand.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea#attr-rows\n */\n rows?: number\n\n /**\n * If `true`, the textarea will be automatically resized to fit the content, and the ability to\n * manually resize the textarea will be disabled.\n */\n autoExpand?: boolean\n\n /**\n * If `true`, the ability to manually resize the textarea will be disabled.\n *\n * When `autoExpand` is true, this property serves no purpose, because the ability to manually\n * resize the textarea is always disabled when `autoExpand` is true.\n */\n disableResize?: boolean\n}\n\nconst TextArea = React.forwardRef(function TextArea(\n {\n variant = 'default',\n id,\n label,\n auxiliaryLabel,\n message,\n tone,\n maxWidth,\n maxLength,\n hidden,\n 'aria-describedby': ariaDescribedBy,\n rows,\n autoExpand = false,\n disableResize = false,\n onChange: originalOnChange,\n ...props\n },\n ref,\n) {\n const containerRef = React.useRef(null)\n const internalRef = React.useRef(null)\n const combinedRef = useMergeRefs([ref, internalRef])\n\n const textAreaClassName = classNames([\n autoExpand ? styles.disableResize : null,\n disableResize ? styles.disableResize : null,\n ])\n\n React.useEffect(\n function setupAutoExpand() {\n const containerElement = containerRef.current\n\n function handleAutoExpand(value: string) {\n if (containerElement) {\n containerElement.dataset.replicatedValue = value\n }\n }\n\n function handleInput(event: Event) {\n handleAutoExpand((event.currentTarget as HTMLTextAreaElement).value)\n }\n\n const textAreaElement = internalRef.current\n if (!textAreaElement || !autoExpand) {\n return undefined\n }\n\n // Apply change initially, in case the text area has a non-empty initial value\n handleAutoExpand(textAreaElement.value)\n\n textAreaElement.addEventListener('input', handleInput)\n return () => textAreaElement.removeEventListener('input', handleInput)\n },\n [autoExpand],\n )\n\n return (\n \n {({ onChange, ...extraProps }) => (\n \n \n )}\n \n )\n})\n\nexport { TextArea }\nexport type { TextAreaProps }\n","function getInitials(name?: string) {\n if (!name) {\n return ''\n }\n\n const seed = name.trim().split(' ')\n const firstInitial = seed[0]\n const lastInitial = seed[seed.length - 1]\n\n let initials = firstInitial?.[0]\n if (\n firstInitial != null &&\n lastInitial != null &&\n initials != null &&\n // Better readable this way.\n // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with\n firstInitial[0] !== lastInitial[0]\n ) {\n initials += lastInitial[0]\n }\n return initials?.toUpperCase()\n}\n\nfunction emailToIndex(email: string, maxIndex: number) {\n const seed = email.split('@')[0]\n const hash = seed ? seed.charCodeAt(0) + seed.charCodeAt(seed.length - 1) || 0 : 0\n return hash % maxIndex\n}\n\nexport { getInitials, emailToIndex }\n","import * as React from 'react'\n\nimport { getInitials, emailToIndex } from './utils'\n\nimport { getClassNames, ResponsiveProp } from '../utils/responsive-props'\nimport styles from './avatar.module.css'\nimport { Box } from '../box'\nimport type { ObfuscatedClassName } from '../utils/common-types'\n\nconst AVATAR_COLORS = [\n '#fcc652',\n '#e9952c',\n '#e16b2d',\n '#d84b40',\n '#e8435a',\n '#e5198a',\n '#ad3889',\n '#86389c',\n '#a8a8a8',\n '#98be2f',\n '#5d9d50',\n '#5f9f85',\n '#5bbcb6',\n '#32a3bf',\n '#2bafeb',\n '#2d88c3',\n '#3863cc',\n '#5e5e5e',\n]\n\ntype AvatarSize = 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl' | 'xxxl'\n\ntype Props = ObfuscatedClassName & {\n /** @deprecated Please use `exceptionallySetClassName` */\n className?: string\n /** @deprecated */\n colorList?: string[]\n size?: ResponsiveProp\n avatarUrl?: string\n user: { name?: string; email: string }\n}\n\nfunction Avatar({\n user,\n avatarUrl,\n size = 'l',\n className,\n colorList = AVATAR_COLORS,\n exceptionallySetClassName,\n ...props\n}: Props) {\n const userInitials = getInitials(user.name) || getInitials(user.email)\n const avatarSize = size ? size : 'l'\n\n const style = avatarUrl\n ? {\n backgroundImage: `url(${avatarUrl})`,\n textIndent: '-9999px', // hide the initials\n }\n : {\n backgroundColor: colorList[emailToIndex(user.email, colorList.length)],\n }\n\n const sizeClassName = getClassNames(styles, 'size', avatarSize)\n\n return (\n \n {userInitials}\n \n )\n}\nAvatar.displayName = 'Avatar'\n\nexport { Avatar }\n","import * as React from 'react'\n\nimport { Box } from '../box'\n\nimport styles from './badge.module.css'\n\ntype BadgeTone = 'info' | 'positive' | 'promote' | 'attention' | 'warning'\n\ntype BadgeProps = {\n /**\n * The label to show inside the badge element.\n */\n label: string\n /**\n * The tone of the badge.\n */\n tone: BadgeTone\n}\n\nfunction Badge({ tone, label, ...props }: BadgeProps) {\n return (\n \n {label}\n \n )\n}\n\nexport { Badge }\nexport type { BadgeProps }\n","import * as React from 'react'\nimport classNames from 'classnames'\nimport FocusLock from 'react-focus-lock'\nimport { hideOthers } from 'aria-hidden'\n\nimport { Dialog, DialogOptions, useDialogStore, Portal, PortalOptions } from '@ariakit/react'\n\nimport { CloseIcon } from '../icons/close-icon'\nimport { Column, Columns } from '../columns'\nimport { Inline } from '../inline'\nimport { Divider } from '../divider'\nimport { Box } from '../box'\nimport { IconButtonProps, IconButton } from '../button'\n\nimport styles from './modal.module.css'\nimport type { ObfuscatedClassName } from '../utils/common-types'\nimport { forwardRef } from 'react'\n\ntype ModalWidth = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'full'\ntype ModalHeightMode = 'expand' | 'fitContent'\n\n//\n// ModalContext\n//\n\ntype ModalContextValue = {\n onDismiss?(this: void): void\n height: ModalHeightMode\n}\n\nconst ModalContext = React.createContext({\n onDismiss: undefined,\n height: 'fitContent',\n})\n\n//\n// Modal container\n//\n\ntype DivProps = Omit<\n React.DetailedHTMLProps, HTMLDivElement>,\n 'className' | 'children' | `aria-label` | `aria-labelledby`\n>\n\nexport interface ModalProps extends DivProps, ObfuscatedClassName {\n /**\n * The content of the modal.\n */\n children: React.ReactNode\n\n /**\n * Whether the modal is open and visible or not.\n */\n isOpen: boolean\n\n /**\n * Called when the user triggers closing the modal.\n */\n onDismiss?(): void\n\n /**\n * A descriptive setting for how wide the modal should aim to be, depending on how much space\n * it has on screen.\n * @default 'medium'\n */\n width?: ModalWidth\n\n /**\n * A descriptive setting for how tall the modal should aim to be.\n *\n * - 'expand': the modal aims to fill most of the available screen height, leaving only a small\n * padding above and below.\n * - 'fitContent': the modal shrinks to the smallest size that allow it to fit its content.\n *\n * In either case, if content does not fit, the content of the main body is set to scroll\n * (provided you use `ModalBody`) so that the modal never has to strech vertically beyond the\n * viewport boundaries.\n *\n * If you do not use `ModalBody`, the modal still prevents overflow, and you are in charge of\n * the inner layout to ensure scroll, or whatever other strategy you may want.\n */\n height?: ModalHeightMode\n\n /**\n * Whether to set or not the focus initially to the first focusable element inside the modal.\n */\n autoFocus?: boolean\n\n /**\n * Controls if the modal is dismissed when pressing \"Escape\".\n */\n hideOnEscape?: DialogOptions['hideOnEscape']\n\n /**\n * Controls if the modal is dismissed when clicking outside the modal body, on the overlay.\n */\n hideOnInteractOutside?: DialogOptions['hideOnInteractOutside']\n\n /**\n * An escape hatch in case you need to provide a custom class name to the overlay element.\n */\n exceptionallySetOverlayClassName?: string\n\n /**\n * Defines a string value that labels the current modal for assistive technologies.\n */\n 'aria-label'?: string\n\n /**\n * Identifies the element (or elements) that labels the current modal for assistive technologies.\n */\n 'aria-labelledby'?: string\n\n /**\n * An HTML element or a memoized callback function that returns an HTML element to be used as\n * the portal element. By default, the portal element will be a `div` element appended to the\n * `document.body`.\n *\n * @default HTMLDivElement\n *\n * @example\n * const [portal, setPortal] = useState(null);\n * ;\n * ;\n *\n * @example\n * const getPortalElement = useCallback(() => {\n * const div = document.createElement(\"div\");\n * const portalRoot = document.getElementById(\"portal-root\");\n * portalRoot.appendChild(div);\n * return div;\n * }, []);\n * ;\n */\n portalElement?: PortalOptions['portalElement']\n}\n\nfunction isNotInternalFrame(element: HTMLElement) {\n return !(element.ownerDocument === document && element.tagName.toLowerCase() === 'iframe')\n}\n\n/**\n * Renders a modal that sits on top of the rest of the content in the entire page.\n *\n * Follows the WAI-ARIA Dialog (Modal) Pattern.\n *\n * @see ModalHeader\n * @see ModalFooter\n * @see ModalBody\n */\nexport function Modal({\n isOpen,\n onDismiss,\n height = 'fitContent',\n width = 'medium',\n exceptionallySetClassName,\n exceptionallySetOverlayClassName,\n autoFocus = true,\n hideOnEscape = true,\n hideOnInteractOutside = true,\n children,\n portalElement,\n onKeyDown,\n // @ts-expect-error we want to make sure to not pass it to the Dialog component\n className,\n ...props\n}: ModalProps) {\n const setOpen = React.useCallback(\n (visible: boolean) => {\n if (!visible) {\n onDismiss?.()\n }\n },\n [onDismiss],\n )\n const store = useDialogStore({ open: isOpen, setOpen })\n\n const contextValue: ModalContextValue = React.useMemo(() => ({ onDismiss, height }), [\n onDismiss,\n height,\n ])\n\n const portalRef = React.useRef(null)\n const dialogRef = React.useRef(null)\n const backdropRef = React.useRef(null)\n const handleBackdropClick = React.useCallback(\n (event: React.MouseEvent) => {\n if (\n // The focus lock element takes up the same space as the backdrop and is where the event bubbles up from,\n // so instead of checking the backdrop as the event target, we need to make sure it's just above the dialog\n !dialogRef.current?.contains(event.target as Node) &&\n // Events fired from other portals will bubble up to the backdrop, even if it isn't a child in the DOM\n backdropRef.current?.contains(event.target as Node)\n ) {\n event.stopPropagation()\n onDismiss?.()\n }\n },\n [onDismiss],\n )\n\n React.useLayoutEffect(\n function disableAccessibilityTreeOutside() {\n if (!isOpen || !portalRef.current) {\n return\n }\n\n return hideOthers(portalRef.current)\n },\n [isOpen],\n )\n\n const handleKeyDown = React.useCallback(\n function handleKeyDown(event: React.KeyboardEvent) {\n if (\n hideOnEscape &&\n onDismiss != null &&\n event.key === 'Escape' &&\n !event.defaultPrevented\n ) {\n event.stopPropagation()\n onDismiss()\n }\n onKeyDown?.(event)\n },\n [onDismiss, hideOnEscape, onKeyDown],\n )\n\n if (!isOpen) {\n return null\n }\n\n return (\n \n \n \n \n }\n className={classNames(exceptionallySetClassName, styles.container)}\n store={store}\n preventBodyScroll\n // Disable focus lock as we set up our own using ReactFocusLock\n modal={false}\n autoFocus={false}\n autoFocusOnShow={false}\n autoFocusOnHide={false}\n // Disable portal and backdrop as we control their markup\n portal={false}\n backdrop={false}\n hideOnInteractOutside={false}\n hideOnEscape={false}\n onKeyDown={handleKeyDown}\n >\n \n {children}\n \n \n \n \n \n )\n}\n\n//\n// ModalCloseButton\n//\n\nexport interface ModalCloseButtonProps\n extends Omit<\n IconButtonProps,\n 'type' | 'variant' | 'icon' | 'disabled' | 'loading' | 'tabIndex' | 'ref'\n > {\n /**\n * The descriptive label of the button.\n */\n 'aria-label': string\n}\n\n/**\n * The close button rendered by ModalHeader. Provided independently so that consumers can customize\n * the button's label.\n *\n * @see ModalHeader\n */\nexport function ModalCloseButton(props: ModalCloseButtonProps) {\n const { onDismiss } = React.useContext(ModalContext)\n const [includeInTabOrder, setIncludeInTabOrder] = React.useState(false)\n const [isMounted, setIsMounted] = React.useState(false)\n\n React.useEffect(\n function skipAutoFocus() {\n if (isMounted) {\n setIncludeInTabOrder(true)\n } else {\n setIsMounted(true)\n }\n },\n [isMounted],\n )\n\n return (\n }\n tabIndex={includeInTabOrder ? 0 : -1}\n />\n )\n}\n\n//\n// ModalHeader\n//\n\nexport interface ModalHeaderProps extends DivProps, ObfuscatedClassName {\n /**\n * The content of the header.\n */\n children: React.ReactNode\n\n /**\n * Allows to provide a custom button element, or to omit the close button if set to false.\n * @see ModalCloseButton\n */\n button?: React.ReactNode | boolean\n\n /**\n * Whether to render a divider line below the header.\n * @default false\n */\n withDivider?: boolean\n}\n\n/**\n * Renders a standard modal header area with an optional close button.\n *\n * @see Modal\n * @see ModalFooter\n * @see ModalBody\n */\nexport function ModalHeader({\n children,\n button = true,\n withDivider = false,\n exceptionallySetClassName,\n ...props\n}: ModalHeaderProps) {\n return (\n <>\n \n \n {children}\n {button === false || button === null ? (\n \n ) : (\n \n {typeof button === 'boolean' ? (\n \n ) : (\n button\n )}\n \n )}\n \n \n {withDivider ? : null}\n >\n )\n}\n\n//\n// ModalBody\n//\n\nexport interface ModalBodyProps extends DivProps, ObfuscatedClassName {\n /**\n * The content of the modal body.\n */\n children: React.ReactNode\n}\n\n/**\n * Renders the body of a modal.\n *\n * Convenient to use alongside ModalHeader and/or ModalFooter as needed. It ensures, among other\n * things, that the content of the modal body expands or contracts depending on the modal height\n * setting or the size of the content. The body content also automatically scrolls when it's too\n * large to fit the available space.\n *\n * @see Modal\n * @see ModalHeader\n * @see ModalFooter\n */\nexport const ModalBody = forwardRef(function ModalBody(\n { exceptionallySetClassName, children, ...props },\n ref,\n) {\n const { height } = React.useContext(ModalContext)\n return (\n \n \n {children}\n \n \n )\n})\n\n//\n// ModalFooter\n//\n\nexport interface ModalFooterProps extends DivProps, ObfuscatedClassName {\n /**\n * The contant of the modal footer.\n */\n children: React.ReactNode\n /**\n * Whether to render a divider line below the footer.\n * @default false\n */\n withDivider?: boolean\n}\n\n/**\n * Renders a standard modal footer area.\n *\n * @see Modal\n * @see ModalHeader\n * @see ModalBody\n */\nexport function ModalFooter({\n exceptionallySetClassName,\n withDivider = false,\n ...props\n}: ModalFooterProps) {\n return (\n <>\n {withDivider ? : null}\n \n >\n )\n}\n\n//\n// ModalActions\n//\n\nexport type ModalActionsProps = ModalFooterProps\n\n/**\n * A specific version of the ModalFooter, tailored to showing an inline list of actions (buttons).\n * @see ModalFooter\n */\nexport function ModalActions({ children, ...props }: ModalActionsProps) {\n return (\n \n \n {children}\n \n \n )\n}\n","import * as React from 'react'\nimport classNames from 'classnames'\nimport {\n useTabStore,\n Tab as BaseTab,\n TabProps as BaseTabProps,\n TabList as BaseTabList,\n TabPanel as BaseTabPanel,\n TabPanelProps as BaseTabPanelProps,\n TabStore,\n} from '@ariakit/react'\nimport { Inline } from '../inline'\nimport type { ObfuscatedClassName, Space } from '../utils/common-types'\n\nimport styles from './tabs.module.css'\nimport { Box } from '../box'\n\ntype TabsContextValue = Required> & {\n tabStore: TabStore\n}\n\nconst TabsContext = React.createContext(null)\n\ninterface TabsProps {\n /**\n * The `` component must be composed from a `` and corresponding ``\n * components\n */\n children: React.ReactNode\n\n /**\n * Determines the look and feel of the tabs\n */\n variant?: 'themed' | 'neutral'\n\n /**\n * The id of the selected tab. Assigning a value makes this a controlled component\n */\n selectedId?: string | null\n\n /**\n * The tab to initially select. This can be used if the component should not\n * be a controlled component but needs to have a tab selected\n */\n defaultSelectedId?: string | null\n\n /**\n * Called with the tab id when a tab is selected\n */\n onSelectedIdChange?: (selectedId: string | null | undefined) => void\n}\n\n/**\n * Used to group components that compose a set of tabs. There can only be one active tab within the same `` group.\n */\nfunction Tabs({\n children,\n selectedId,\n defaultSelectedId,\n variant = 'neutral',\n onSelectedIdChange,\n}: TabsProps): React.ReactElement {\n const tabStore = useTabStore({\n defaultSelectedId,\n selectedId,\n setSelectedId: onSelectedIdChange,\n })\n const actualSelectedId = tabStore.useState('selectedId')\n\n const memoizedTabState = React.useMemo(\n () => ({ tabStore, variant, selectedId: selectedId ?? actualSelectedId ?? null }),\n [variant, tabStore, selectedId, actualSelectedId],\n )\n return {children}\n}\n\ninterface TabProps\n extends ObfuscatedClassName,\n Omit {\n /**\n * The content to render inside of the tab button\n */\n children: React.ReactNode\n\n /**\n * The tab's identifier. This must match its corresponding ``'s id\n */\n id: string\n}\n\n/**\n * Represents the individual tab elements within the group. Each `` must have a corresponding `` component.\n */\nconst Tab = React.forwardRef(function Tab(\n { children, id, exceptionallySetClassName, render, onClick },\n ref,\n): React.ReactElement | null {\n const tabContextValue = React.useContext(TabsContext)\n if (!tabContextValue) return null\n\n const { variant, tabStore } = tabContextValue\n const className = classNames(exceptionallySetClassName, styles.tab, styles[`tab-${variant}`])\n\n return (\n \n {children}\n \n )\n})\n\ntype TabListProps = (\n | {\n /** Labels the tab list for assistive technologies. This must be provided if `aria-labelledby` is omitted. */\n 'aria-label': string\n }\n | {\n /**\n * One or more element IDs used to label the tab list for assistive technologies. Required if\n * `aria-label` is omitted.\n */\n 'aria-labelledby': string\n }\n | {\n /**\n * For cases where multiple instances of the tab list exists, the duplicates may be marked as aria-hidden\n */\n 'aria-hidden': boolean\n }\n) & {\n /**\n * A list of `` elements\n */\n children: React.ReactNode\n\n /**\n * Controls the spacing between tabs\n */\n space?: Space\n}\n\n/**\n * A component used to group `` elements together.\n */\nfunction TabList({ children, space, ...props }: TabListProps): React.ReactElement | null {\n const tabContextValue = React.useContext(TabsContext)\n\n if (!tabContextValue) {\n return null\n }\n\n const { tabStore, variant } = tabContextValue\n\n return (\n // The extra