@chassis-ui/react 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/autocomplete.js +1 -1
  2. package/dist/chunks/{Menu-264aGoBR.js → Menu-BiE9CzNk.js} +2 -2
  3. package/dist/chunks/{Menu-264aGoBR.js.map → Menu-BiE9CzNk.js.map} +1 -1
  4. package/dist/chunks/{MenuToggle-DcPEh55c.js → MenuToggle-W-ZSHFwF.js} +2 -2
  5. package/dist/chunks/{MenuToggle-DcPEh55c.js.map → MenuToggle-W-ZSHFwF.js.map} +1 -1
  6. package/dist/chunks/{autocomplete-99usnvgh.js → autocomplete-Btcsjrh3.js} +2 -2
  7. package/dist/chunks/{autocomplete-99usnvgh.js.map → autocomplete-Btcsjrh3.js.map} +1 -1
  8. package/dist/chunks/{combobox-BQh3uJWB.js → combobox-DNqR4d3V.js} +2 -2
  9. package/dist/chunks/{combobox-BQh3uJWB.js.map → combobox-DNqR4d3V.js.map} +1 -1
  10. package/dist/chunks/{context-menu-8KIuH4cJ.js → context-menu-D3DNFN-P.js} +2 -2
  11. package/dist/chunks/{context-menu-8KIuH4cJ.js.map → context-menu-D3DNFN-P.js.map} +1 -1
  12. package/dist/chunks/{menu-DEu-Nbv8.js → menu-Bqlhottl.js} +2 -2
  13. package/dist/chunks/{menu-DEu-Nbv8.js.map → menu-Bqlhottl.js.map} +1 -1
  14. package/dist/chunks/{nav-overflow-DpX_lRYf.js → nav-overflow-GWARvoQZ.js} +2 -2
  15. package/dist/chunks/{nav-overflow-DpX_lRYf.js.map → nav-overflow-GWARvoQZ.js.map} +1 -1
  16. package/dist/chunks/overlayPlacement-Q6bcbXA5.js.map +1 -1
  17. package/dist/chunks/useOverlayMaxHeight-DTgbr4UQ.js +2 -0
  18. package/dist/chunks/useOverlayMaxHeight-DTgbr4UQ.js.map +1 -0
  19. package/dist/combobox.js +1 -1
  20. package/dist/context-menu.js +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/menu.js +1 -1
  23. package/dist/nav-overflow.js +1 -1
  24. package/package.json +1 -1
  25. package/dist/chunks/useOverlayMaxHeight-8mQL2Q6d.js +0 -2
  26. package/dist/chunks/useOverlayMaxHeight-8mQL2Q6d.js.map +0 -1
@@ -1 +1 @@
1
- "use client";export{t as Autocomplete,r as AutocompleteGroup,n as AutocompleteItem}from"./chunks/autocomplete-99usnvgh.js";
1
+ "use client";export{t as Autocomplete,r as AutocompleteGroup,n as AutocompleteItem}from"./chunks/autocomplete-Btcsjrh3.js";
@@ -1,2 +1,2 @@
1
- import{t as e}from"./useForkedRef-WoqMqsWE.js";import{t}from"./polymorphic-CZIFszAy.js";import{t as n}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{t as r}from"./dialogTransition-C8fYTsSa.js";import{n as i}from"./overlayStack-BXtTGCRm.js";import{r as a}from"./useFloatingOverlay-BuiI_CCn.js";import{t as o}from"./useOpenStateProps-BhjSQ3f6.js";import{t as s}from"./useOverlayMaxHeight-8mQL2Q6d.js";import{i as c,r as l}from"./overlayPlacement-Q6bcbXA5.js";import{n as ee}from"./insideEvents-CWcNrMu7.js";import{t as te}from"./navOverflow-C_QJmkPM.js";import u,{Fragment as d,createContext as f,useEffect as p,useMemo as ne,useRef as m}from"react";import re from"classnames";import{useMenuTrigger as ie,useOverlayPosition as h}from"react-aria";import{useMenuTriggerState as g}from"react-stately";const _=()=>void 0,v=f({autoClose:!0,close:_,focusStrategy:null,hide:_,menuId:``,menuStyle:{},menuTriggerProps:{},overlayRef:{current:null},placementAttr:`bottom-start`,reference:`toggle`,registerOverlay:_,show:_,targetRef:{current:null},toggle:_,toggleNodeRef:{current:null},triggerId:``,visible:!1}),y=/* @__PURE__ */ new WeakSet,b=/* @__PURE__ */ new Set;function x({children:t,autoClose:f=!0,className:_,component:x,container:S,defaultVisible:C,offset:w=[0,2],onHide:ae,onHidden:T,onShow:oe,onShown:E,onVisibleChange:D,placement:O=`bottom-start`,reference:k=`toggle`,visible:A,...se},ce){let j=x??d,M=m(null),le=e(ce,M),N=m(null),P=m(null),F=m(null),I=m(/* @__PURE__ */ new Map),L=(e,t)=>{t?I.current.set(e,t):I.current.delete(e)},R=g(o({defaultVisible:C,onVisibleChange:D,visible:A},`Menu`)),{menuTriggerProps:z,menuProps:B}=ie({},R,N);n(()=>{k===`parent`&&(P.current=M.current)},[k]);let V=m(!1);p(()=>{let e=F.current,t=!V.current;if(V.current=!0,!t){if(R.isOpen){if(oe?.(),!e){E?.();return}return r(e,()=>E?.(),!0)}if(ae?.(),!e)T?.();else return r(e,()=>T?.(),!0)}},[R.isOpen]);let{overlayProps:H,placement:U,updatePosition:ue}=h({targetRef:P,overlayRef:F,placement:c(O),offset:w[1],crossOffset:w[0],containerPadding:8,isOpen:R.isOpen,onClose:null});s(F,R.isOpen);let{menuStyle:W,placementAttr:G}=l(H.style,O,U),K=m(!0);K.current=A===void 0||!!D;let q=m(!1);q.current=A!==void 0;let J=m(!1),de=e=>R.open(e),Y=()=>{J.current=!1,R.close()},X=e=>R.toggle(e),Z=()=>{R.close(),q.current?J.current=K.current:N.current?.focus()};p(()=>{!R.isOpen&&J.current&&N.current?.focus(),J.current=!1},[R.isOpen]);let Q=a({close:Y,isOpen:R.isOpen,triggerRef:N});n(()=>{R.isOpen&&ue()},[Q]),p(()=>{if(!R.isOpen||f===!1)return;let e=/* @__PURE__ */ new WeakSet,t=t=>{if(t instanceof KeyboardEvent&&t.key!==`Tab`||e.has(t))return;e.add(t);let n=t.target,r=N.current,i=F.current;if(r?.contains(n))return;let a=!!i?.contains(n)||Array.from(I.current.values()).some(e=>e.contains(n));if(!a&&ee(t,F)||a&&y.has(t)||f===`inside`&&!a||f===`outside`&&a||a&&(t instanceof KeyboardEvent&&t.key===`Tab`||/input|select|option|textarea|form/i.test(n.tagName??``)))return;let o=document.activeElement,s=!o||o===document.body||!!i?.contains(o)||Array.from(I.current.values()).some(e=>e.contains(o));a&&s?Z():Y()},n=window.setTimeout(()=>{window.addEventListener(`click`,t),window.addEventListener(`keyup`,t),b.add(t)});return()=>{window.clearTimeout(n),window.removeEventListener(`click`,t),window.removeEventListener(`keyup`,t),b.delete(t)}},[R.isOpen,f]),p(()=>{if(R.isOpen)return i({nodes:()=>[F.current,N.current],onEscape:Z})},[R.isOpen]);let fe=ne(()=>({autoClose:f,close:Z,container:S===!0?Q??!0:S,focusStrategy:R.focusStrategy,hide:Y,menuId:B.id??``,menuStyle:W,menuTriggerProps:z,overlayRef:F,placementAttr:G,portalContainer:Q,reference:k,registerOverlay:L,show:de,targetRef:P,toggle:X,toggleNodeRef:N,triggerId:z.id??``,visible:R.isOpen}),[f,S,R.focusStrategy,B.id,W,z,G,Q,k,R.isOpen]),$=/* @__PURE__ */ u.createElement(te,null,t);return/* @__PURE__ */ u.createElement(v.Provider,{value:fe},j===d?$:/* @__PURE__ */ u.createElement(j,{className:re(_,{show:R.isOpen}),...se,ref:le},$))}const S=t(x,`Menu`);export{b as i,v as n,y as r,S as t};
2
- //# sourceMappingURL=Menu-264aGoBR.js.map
1
+ import{t as e}from"./useForkedRef-WoqMqsWE.js";import{t}from"./polymorphic-CZIFszAy.js";import{t as n}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{t as r}from"./dialogTransition-C8fYTsSa.js";import{n as i}from"./overlayStack-BXtTGCRm.js";import{r as a}from"./useFloatingOverlay-BuiI_CCn.js";import{t as o}from"./useOpenStateProps-BhjSQ3f6.js";import{t as s}from"./useOverlayMaxHeight-DTgbr4UQ.js";import{i as c,r as l}from"./overlayPlacement-Q6bcbXA5.js";import{n as ee}from"./insideEvents-CWcNrMu7.js";import{t as te}from"./navOverflow-C_QJmkPM.js";import u,{Fragment as d,createContext as f,useEffect as p,useMemo as ne,useRef as m}from"react";import re from"classnames";import{useMenuTrigger as ie,useOverlayPosition as h}from"react-aria";import{useMenuTriggerState as g}from"react-stately";const _=()=>void 0,v=f({autoClose:!0,close:_,focusStrategy:null,hide:_,menuId:``,menuStyle:{},menuTriggerProps:{},overlayRef:{current:null},placementAttr:`bottom-start`,reference:`toggle`,registerOverlay:_,show:_,targetRef:{current:null},toggle:_,toggleNodeRef:{current:null},triggerId:``,visible:!1}),y=/* @__PURE__ */ new WeakSet,b=/* @__PURE__ */ new Set;function x({children:t,autoClose:f=!0,className:_,component:x,container:S,defaultVisible:C,offset:w=[0,2],onHide:ae,onHidden:T,onShow:oe,onShown:E,onVisibleChange:D,placement:O=`bottom-start`,reference:k=`toggle`,visible:A,...se},ce){let j=x??d,M=m(null),le=e(ce,M),N=m(null),P=m(null),F=m(null),I=m(/* @__PURE__ */ new Map),L=(e,t)=>{t?I.current.set(e,t):I.current.delete(e)},R=g(o({defaultVisible:C,onVisibleChange:D,visible:A},`Menu`)),{menuTriggerProps:z,menuProps:B}=ie({},R,N);n(()=>{k===`parent`&&(P.current=M.current)},[k]);let V=m(!1);p(()=>{let e=F.current,t=!V.current;if(V.current=!0,!t){if(R.isOpen){if(oe?.(),!e){E?.();return}return r(e,()=>E?.(),!0)}if(ae?.(),!e)T?.();else return r(e,()=>T?.(),!0)}},[R.isOpen]);let{overlayProps:H,placement:U,updatePosition:ue}=h({targetRef:P,overlayRef:F,placement:c(O),offset:w[1],crossOffset:w[0],containerPadding:8,isOpen:R.isOpen,onClose:null});s(F,R.isOpen);let{menuStyle:W,placementAttr:G}=l(H.style,O,U),K=m(!0);K.current=A===void 0||!!D;let q=m(!1);q.current=A!==void 0;let J=m(!1),de=e=>R.open(e),Y=()=>{J.current=!1,R.close()},X=e=>R.toggle(e),Z=()=>{R.close(),q.current?J.current=K.current:N.current?.focus()};p(()=>{!R.isOpen&&J.current&&N.current?.focus(),J.current=!1},[R.isOpen]);let Q=a({close:Y,isOpen:R.isOpen,triggerRef:N});n(()=>{R.isOpen&&ue()},[Q]),p(()=>{if(!R.isOpen||f===!1)return;let e=/* @__PURE__ */ new WeakSet,t=t=>{if(t instanceof KeyboardEvent&&t.key!==`Tab`||e.has(t))return;e.add(t);let n=t.target,r=N.current,i=F.current;if(r?.contains(n))return;let a=!!i?.contains(n)||Array.from(I.current.values()).some(e=>e.contains(n));if(!a&&ee(t,F)||a&&y.has(t)||f===`inside`&&!a||f===`outside`&&a||a&&(t instanceof KeyboardEvent&&t.key===`Tab`||/input|select|option|textarea|form/i.test(n.tagName??``)))return;let o=document.activeElement,s=!o||o===document.body||!!i?.contains(o)||Array.from(I.current.values()).some(e=>e.contains(o));a&&s?Z():Y()},n=window.setTimeout(()=>{window.addEventListener(`click`,t),window.addEventListener(`keyup`,t),b.add(t)});return()=>{window.clearTimeout(n),window.removeEventListener(`click`,t),window.removeEventListener(`keyup`,t),b.delete(t)}},[R.isOpen,f]),p(()=>{if(R.isOpen)return i({nodes:()=>[F.current,N.current],onEscape:Z})},[R.isOpen]);let fe=ne(()=>({autoClose:f,close:Z,container:S===!0?Q??!0:S,focusStrategy:R.focusStrategy,hide:Y,menuId:B.id??``,menuStyle:W,menuTriggerProps:z,overlayRef:F,placementAttr:G,portalContainer:Q,reference:k,registerOverlay:L,show:de,targetRef:P,toggle:X,toggleNodeRef:N,triggerId:z.id??``,visible:R.isOpen}),[f,S,R.focusStrategy,B.id,W,z,G,Q,k,R.isOpen]),$=/* @__PURE__ */ u.createElement(te,null,t);return/* @__PURE__ */ u.createElement(v.Provider,{value:fe},j===d?$:/* @__PURE__ */ u.createElement(j,{className:re(_,{show:R.isOpen}),...se,ref:le},$))}const S=t(x,`Menu`);export{b as i,v as n,y as r,S as t};
2
+ //# sourceMappingURL=Menu-BiE9CzNk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu-264aGoBR.js","names":["useForkedRef","useIsomorphicLayoutEffect","executeAfterTransition","pushOverlay","useFloatingOverlay","useOpenStateProps","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","isEventInside","NavOverflowBoundary","React","classNames","noop","MenuContext","createContext","menuToggleClicks","openMenuDismissals","MenuRender","offsetProp","rest","Component","component","Fragment","wrapperRef","useRef","forkedRef","ref","toggleNodeRef","targetRef","overlayRef","submenuOverlaysRef","registerOverlay","node","id","state","useMenuTriggerState","useMenuTrigger","reference","mountedRef","useEffect","overlay","isInitialCommit","onShow","onShown","onHide","onHidden","resolvedPlacement","useOverlayPosition","placement","overlayProps","followsRequestsRef","visible","onVisibleChange","isControlledRef","focusReturnOwedRef","show","focusStrategy","hide","toggleVisible","close","portalContainer","updatePosition","autoClose","handled","handleDismiss","event","target","toggleNode","menuNode","isMenuTarget","active","holdsFocus","contextValue","useMemo","container","menuProps","menuTriggerProps","menuStyle","placementAttr","content","children","className","Menu","createPolymorphicComponent"],"sources":["../../src/components/menu/Menu.tsx"],"sourcesContent":["import React, {\n createContext,\n ElementType,\n ForwardRefRenderFunction,\n Fragment,\n ReactElement,\n useEffect,\n useMemo,\n useRef\n} from 'react'\nimport classNames from 'classnames'\nimport { AriaButtonProps, useMenuTrigger, useOverlayPosition } from 'react-aria'\nimport { useMenuTriggerState } from 'react-stately'\n\nimport {\n useFloatingOverlay,\n useForkedRef,\n useIsomorphicLayoutEffect,\n useOpenStateProps,\n useOverlayMaxHeight\n} from '../../hooks'\nimport { executeAfterTransition } from '../../utils/dialogTransition'\nimport { isEventInside } from '../../utils/insideEvents'\nimport {\n Placement,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { NavOverflowBoundary } from '../../utils/navOverflow'\nimport { pushOverlay } from '../../utils/overlayStack'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\n\nexport type { Placement }\nexport type MenuFocusStrategy = 'first' | 'last'\n\nexport type MenuAutoClose = boolean | 'inside' | 'outside'\n\ntype MenuOwnProps<C extends ElementType> = {\n /**\n * Controls which clicks close the menu. `true` closes on any click inside or outside.\n * `false` leaves closing to the toggle, the Escape key and `visible`. `'inside'` closes only\n * on click inside the menu. `'outside'` closes only on click outside the menu.\n */\n autoClose?: MenuAutoClose\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Component used for the root node. Either a string to use a HTML element or a component.\n * Defaults to `Fragment` — `MenuToggle`/`MenuList` render with no wrapping element, so\n * they land as direct children of whatever contains the `Menu`. This matters inside\n * `ButtonGroup`/`InputGroup`, whose CSS expects the toggle button and menu panel as direct\n * children rather than nested inside an intermediate node.\n *\n * Pass an actual element (e.g. `\"div\"`, or `\"li\"` for a navbar item) to opt back into a\n * wrapper — needed if you want to apply `className`/`style`/other rest props to a container\n * around the whole menu, for semantic wrapping like a nav `<li>`, or for `reference=\"parent\"`,\n * which positions off this wrapper and has nothing to measure against without one.\n */\n component?: C\n /**\n * Teleports the menu panel to a container element on open. Accepts an element reference, or\n * `true` to append to `document.body`, or to the open dialog the menu is in, so the panel\n * stays in that dialog's top layer.\n */\n container?: boolean | Element\n /**\n * Whether the menu is open when it first renders. Use it instead of `visible` when nothing\n * outside needs to control the menu.\n */\n defaultVisible?: boolean\n /**\n * Distance between the menu and its reference element, as `[skidding, distance]` in pixels.\n */\n offset?: [number, number]\n /**\n * Callback fired when the menu starts to hide.\n */\n onHide?: () => void\n /**\n * Callback fired after the menu finishes hiding.\n */\n onHidden?: () => void\n /**\n * Callback fired when the menu starts to show.\n */\n onShow?: () => void\n /**\n * Callback fired after the menu finishes showing.\n */\n onShown?: () => void\n /**\n * Callback fired when the menu asks to show or hide: the toggle, a click that `autoClose`\n * counts, or the Escape or Tab key. Receives the state it asks for. With `visible` set, the\n * menu changes only when `visible` does.\n */\n onVisibleChange?: (visible: boolean) => void\n /**\n * Initial placement. Chassis will flip it to keep the menu in view.\n *\n * @type 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end'\n */\n placement?: Placement\n /**\n * Reference element used for positioning. `'toggle'` uses the trigger. `'parent'` uses this\n * component's own rendered element, useful for split buttons and button groups.\n */\n reference?: 'toggle' | 'parent'\n /**\n * Whether the menu is open. Setting it makes the menu controlled: it opens and closes only\n * when this changes, so pair it with `onVisibleChange`. Leave it unset, or use\n * `defaultVisible`, for a menu that opens and closes itself.\n */\n visible?: boolean\n}\n\nexport type MenuProps<C extends ElementType = typeof Fragment> = PolymorphicComponentProps<\n C,\n MenuOwnProps<C>\n>\n\ntype MenuComponent = (<C extends ElementType = typeof Fragment>(\n props: MenuProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nexport interface MenuContextProps {\n autoClose: MenuAutoClose\n close: () => void\n container?: boolean | Element\n focusStrategy: MenuFocusStrategy | null\n hide: () => void\n menuId: string\n menuStyle: React.CSSProperties\n menuTriggerProps: AriaButtonProps\n overlayRef: React.MutableRefObject<HTMLElement | null>\n placementAttr: string\n /**\n * The open dialog the menu is in, or `document.body`; `null` until the menu first opens. A\n * `MenuSubmenu` portals its panel there, so inside a modal dialog it is in the top layer with\n * the menu rather than under it, where the page is inert.\n */\n portalContainer?: Element | null\n reference: 'toggle' | 'parent'\n /**\n * Registers (or, passing `null`, unregisters) a nested `MenuSubmenu`'s own portaled panel\n * element, so this `Menu`'s outside/inside click-dismiss logic recognizes clicks landing in it\n * as \"inside\" the menu — see `MenuSubmenu`'s own use for why this is necessary: its panel\n * portals straight to `document.body`, structurally detached from this menu's own DOM subtree.\n */\n registerOverlay: (id: string, node: HTMLElement | null) => void\n show: (focusStrategy?: MenuFocusStrategy | null) => void\n targetRef: React.MutableRefObject<HTMLElement | null>\n toggle: (focusStrategy?: MenuFocusStrategy | null) => void\n toggleNodeRef: React.MutableRefObject<HTMLElement | null>\n triggerId: string\n visible: boolean\n}\n\n// A fully-shaped no-op default so a `MenuToggle`/`MenuList`/`MenuSubmenu` rendered without a\n// `Menu` ancestor (or in an environment where context can't cross a component boundary, e.g.\n// some static-site prerenderers) degrades to an inert, always-closed menu instead of throwing.\nconst noop = () => undefined\n\nconst defaultMenuContext: MenuContextProps = {\n autoClose: true,\n close: noop,\n focusStrategy: null,\n hide: noop,\n menuId: '',\n menuStyle: {},\n menuTriggerProps: {},\n overlayRef: { current: null },\n placementAttr: 'bottom-start',\n reference: 'toggle',\n registerOverlay: noop,\n show: noop,\n targetRef: { current: null },\n toggle: noop,\n toggleNodeRef: { current: null },\n triggerId: '',\n visible: false\n}\n\nexport const MenuContext = createContext(defaultMenuContext)\n\n// The clicks on a `MenuToggle` or a `MenuSubmenu` trigger. One in a menu's list opens a menu of\n// its own: it is no click on an item of that list.\nexport const menuToggleClicks = new WeakSet<Event>()\n\n// The outside-click handlers of the open menus. react-aria's press handling stops the click on a\n// `MenuToggle` before it reaches `window`, where those handlers listen, so another menu stayed open\n// beside the one the click opened: the toggle hands its click to each of them itself.\nexport const openMenuDismissals = new Set<(event: Event) => void>()\n\nfunction MenuRender<C extends ElementType = typeof Fragment>(\n {\n children,\n autoClose = true,\n className,\n component,\n container,\n defaultVisible,\n offset: offsetProp = [0, 2],\n onHide,\n onHidden,\n onShow,\n onShown,\n onVisibleChange,\n placement = 'bottom-start',\n reference = 'toggle',\n visible,\n ...rest\n }: MenuProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? (Fragment as ElementType)\n const wrapperRef = useRef<HTMLElement>(null)\n const forkedRef = useForkedRef(ref, wrapperRef)\n const toggleNodeRef = useRef<HTMLElement | null>(null)\n const targetRef = useRef<HTMLElement | null>(null)\n const overlayRef = useRef<HTMLElement | null>(null)\n // Portaled `MenuSubmenu` panels register themselves here (see `registerOverlay` below and\n // `MenuSubmenu`'s own ref callback) so `handleDismiss` can recognize clicks inside them as\n // \"inside\" this menu despite living outside `overlayRef.current`'s own DOM subtree.\n const submenuOverlaysRef = useRef<Map<string, HTMLElement>>(new Map())\n const registerOverlay = (id: string, node: HTMLElement | null) => {\n if (node) submenuOverlaysRef.current.set(id, node)\n else submenuOverlaysRef.current.delete(id)\n }\n\n // Controlled by `visible` when it is set: `show`/`hide`/`toggle` (from `MenuToggle`, autoClose\n // dismissal, an item) then only report to `onVisibleChange`.\n const state = useMenuTriggerState(\n useOpenStateProps({ defaultVisible, onVisibleChange, visible }, 'Menu')\n )\n const { menuTriggerProps, menuProps } = useMenuTrigger<unknown>({}, state, toggleNodeRef)\n\n useIsomorphicLayoutEffect(() => {\n if (reference === 'parent') {\n targetRef.current = wrapperRef.current\n }\n }, [reference])\n\n // `onShown`/`onHidden` wait for chassis-css's own opacity/transform transition on `.menu`\n // (see `_menu.scss`) to actually finish, matching `Modal`'s identically-worded \"requests to\n // be shown\" vs \"finishes showing\" contract (`Modal.tsx`'s own `executeAfterTransition` use).\n // `overlayRef.current` is `MenuList`'s root element — already in the DOM and already\n // reflecting the new `.show` class by the time this effect runs, since React commits the\n // render before passive effects execute. Falls back to firing synchronously when no\n // `MenuList` is mounted to measure (nothing to transition, so nothing to wait for).\n //\n // All four report *transitions*, so none fires for the initial commit — mounting closed is not\n // a hide. Without this guard, mounting fired `onHide` (and scheduled `onHidden`) for every menu\n // on the page before `onShow` had ever fired once, which `Menu.spec.tsx` used to have to\n // `mockClear()` past.\n const mountedRef = useRef(false)\n\n useEffect(() => {\n const overlay = overlayRef.current\n const isInitialCommit = !mountedRef.current\n mountedRef.current = true\n if (isInitialCommit) return undefined\n\n if (state.isOpen) {\n onShow?.()\n if (!overlay) {\n onShown?.()\n return undefined\n }\n return executeAfterTransition(overlay, () => onShown?.(), true)\n }\n\n onHide?.()\n if (!overlay) {\n onHidden?.()\n return undefined\n }\n return executeAfterTransition(overlay, () => onHidden?.(), true)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen])\n\n const {\n overlayProps,\n placement: resolvedPlacement,\n updatePosition\n } = useOverlayPosition({\n targetRef,\n overlayRef,\n placement: toAriaPlacement(placement),\n offset: offsetProp[1],\n crossOffset: offsetProp[0],\n containerPadding: 8,\n isOpen: state.isOpen,\n // `useOverlayPosition` closes on any window scroll via a backward-compat `WeakMap` that\n // `useMenuTrigger` populates for `targetRef.current` (see `MenuToggle`'s `setRefs`).\n // Passing `null` opts out so the menu repositions with its trigger instead of vanishing —\n // matching `Autocomplete`/`Combobox`, neither of which is wired into that map.\n onClose: null\n })\n useOverlayMaxHeight(overlayRef, state.isOpen)\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n placement,\n resolvedPlacement\n )\n\n // Escape closes the menu and returns focus to the toggle. Controlled, the close is a request:\n // focus returns when `visible` follows it, in the effect below, and stays where it is when\n // nothing can follow it or the caller declines. Read through a ref because the context value\n // these functions travel in is memoized.\n const followsRequestsRef = useRef(true)\n followsRequestsRef.current = visible === undefined || !!onVisibleChange\n const isControlledRef = useRef(false)\n isControlledRef.current = visible !== undefined\n const focusReturnOwedRef = useRef(false)\n\n const show = (focusStrategy?: MenuFocusStrategy | null) => state.open(focusStrategy)\n const hide = () => {\n focusReturnOwedRef.current = false\n state.close()\n }\n const toggleVisible = (focusStrategy?: MenuFocusStrategy | null) => state.toggle(focusStrategy)\n const close = () => {\n state.close()\n if (!isControlledRef.current) toggleNodeRef.current?.focus()\n else focusReturnOwedRef.current = followsRequestsRef.current\n }\n\n useEffect(() => {\n if (!state.isOpen && focusReturnOwedRef.current) toggleNodeRef.current?.focus()\n focusReturnOwedRef.current = false\n }, [state.isOpen])\n\n // The open dialog the toggle is in, if any, as `Popover` and `ContextMenu` resolve it: a list\n // teleported by `container` goes into that dialog rather than `document.body`, which lies\n // under a modal dialog's top layer, and the menu closes when the dialog does, teleported or\n // not, so a reopened dialog doesn't show a menu left open. `onShow`/`onHide` stay with the\n // effect above.\n const portalContainer = useFloatingOverlay({\n close: hide,\n isOpen: state.isOpen,\n triggerRef: toggleNodeRef\n })\n\n // The list is mounted again when it moves into the dialog, as a new element in another\n // containing block: placed again here, after its ref is set and before the paint.\n useIsomorphicLayoutEffect(() => {\n if (state.isOpen) updatePosition()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [portalContainer])\n\n // Deferred so the click that opened the menu doesn't immediately close it, and scoped\n // to match menu.js's `clearMenus`: skip the toggle itself, honor `inside`/`outside`\n // modes, and let Tab or clicks on form controls inside the menu pass through untouched.\n useEffect(() => {\n if (!state.isOpen || autoClose === false) return undefined\n\n // A toggle's click can come both ways: from the toggle, and on `window` when nothing stopped it.\n const handled = new WeakSet<Event>()\n const handleDismiss = (event: Event) => {\n if (event instanceof KeyboardEvent && event.key !== 'Tab') return\n if (handled.has(event)) return\n handled.add(event)\n\n const target = event.target as Node\n const toggleNode = toggleNodeRef.current\n const menuNode = overlayRef.current\n\n if (toggleNode?.contains(target)) return\n\n const isMenuTarget =\n !!menuNode?.contains(target) ||\n Array.from(submenuOverlaysRef.current.values()).some((node) => node.contains(target))\n\n // An overlay opened from the menu (a popover on an item, a picker's list) is portaled out\n // of the list, and React still renders it under it (`insideEvents`). A click there is\n // neither a click on an item nor one outside the menu: it is that overlay's.\n if (!isMenuTarget && isEventInside(event, overlayRef)) return\n if (isMenuTarget && menuToggleClicks.has(event)) return\n\n if (autoClose === 'inside' && !isMenuTarget) return\n if (autoClose === 'outside' && isMenuTarget) return\n\n if (\n isMenuTarget &&\n ((event instanceof KeyboardEvent && event.key === 'Tab') ||\n /input|select|option|textarea|form/i.test((target as HTMLElement).tagName ?? ''))\n ) {\n return\n }\n\n // An item chosen returns focus to the toggle, as Escape does: the closed list is\n // `display: none`, and focus on an item in it fell to `<body>`. Only while the menu holds\n // focus, or nothing does: an item that opened a dialog has moved it there. A click outside\n // or Tab has put focus where it is going already.\n const active = document.activeElement\n const holdsFocus =\n !active ||\n active === document.body ||\n !!menuNode?.contains(active) ||\n Array.from(submenuOverlaysRef.current.values()).some((node) => node.contains(active))\n if (isMenuTarget && holdsFocus) close()\n else hide()\n }\n\n const id = window.setTimeout(() => {\n window.addEventListener('click', handleDismiss)\n window.addEventListener('keyup', handleDismiss)\n openMenuDismissals.add(handleDismiss)\n })\n\n return () => {\n window.clearTimeout(id)\n window.removeEventListener('click', handleDismiss)\n window.removeEventListener('keyup', handleDismiss)\n openMenuDismissals.delete(handleDismiss)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen, autoClose])\n\n // Escape should always close the menu, independent of `autoClose`'s inside/outside/false\n // modes. `MenuList`'s own `onKeyDown` handling only fires when focus is already inside the\n // panel (e.g. opened via ArrowDown) — a mouse-press open via `useMenuTrigger` leaves focus on\n // the trigger button, where that handler is unreachable. The stack of open overlays listens on\n // `window`, which catches Escape regardless of where focus currently is, and gives it to this\n // menu only while nothing opened since is still open, and never to the popover or the dialog\n // around the menu as well.\n useEffect(() => {\n if (!state.isOpen) return undefined\n\n return pushOverlay({\n nodes: () => [overlayRef.current, toggleNodeRef.current],\n onEscape: close\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen])\n\n const contextValue: MenuContextProps = useMemo(\n () => ({\n autoClose,\n close,\n container: container === true ? (portalContainer ?? true) : container,\n focusStrategy: state.focusStrategy as MenuFocusStrategy | null,\n hide,\n menuId: menuProps.id ?? '',\n menuStyle,\n menuTriggerProps,\n overlayRef,\n placementAttr,\n portalContainer,\n reference,\n registerOverlay,\n show,\n targetRef,\n toggle: toggleVisible,\n toggleNodeRef,\n triggerId: menuTriggerProps.id ?? '',\n visible: state.isOpen\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n autoClose,\n container,\n state.focusStrategy,\n menuProps.id,\n menuStyle,\n menuTriggerProps,\n placementAttr,\n portalContainer,\n reference,\n state.isOpen\n ]\n )\n\n // Inside a `NavOverflow`, a menu in a nav item is that item's content, not its link: a toggle\n // rendered as a `NavLink` has nothing to show in the overflow menu.\n const content = <NavOverflowBoundary>{children}</NavOverflowBoundary>\n\n return (\n <MenuContext.Provider value={contextValue}>\n {Component === Fragment ? (\n content\n ) : (\n // `show` mirrors vanilla menu.js's `this._parent.classList.add('show')` — needed for\n // e.g. `.nav-item.show .nav-link` to put a `NavLink`-rooted `MenuToggle` into its\n // pressed look while open, since a bare `.nav-link.show` has no styling of its own.\n <Component\n className={classNames(className, { show: state.isOpen })}\n {...rest}\n ref={forkedRef}\n >\n {content}\n </Component>\n )}\n </MenuContext.Provider>\n )\n}\n\nexport const Menu = createPolymorphicComponent<MenuComponent>(\n MenuRender as ForwardRefRenderFunction<Element, MenuProps<ElementType>>,\n 'Menu'\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"Menu-BiE9CzNk.js","names":["useForkedRef","useIsomorphicLayoutEffect","executeAfterTransition","pushOverlay","useFloatingOverlay","useOpenStateProps","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","isEventInside","NavOverflowBoundary","React","classNames","noop","MenuContext","createContext","menuToggleClicks","openMenuDismissals","MenuRender","offsetProp","rest","Component","component","Fragment","wrapperRef","useRef","forkedRef","ref","toggleNodeRef","targetRef","overlayRef","submenuOverlaysRef","registerOverlay","node","id","state","useMenuTriggerState","useMenuTrigger","reference","mountedRef","useEffect","overlay","isInitialCommit","onShow","onShown","onHide","onHidden","resolvedPlacement","useOverlayPosition","placement","overlayProps","followsRequestsRef","visible","onVisibleChange","isControlledRef","focusReturnOwedRef","show","focusStrategy","hide","toggleVisible","close","portalContainer","updatePosition","autoClose","handled","handleDismiss","event","target","toggleNode","menuNode","isMenuTarget","active","holdsFocus","contextValue","useMemo","container","menuProps","menuTriggerProps","menuStyle","placementAttr","content","children","className","Menu","createPolymorphicComponent"],"sources":["../../src/components/menu/Menu.tsx"],"sourcesContent":["import React, {\n createContext,\n ElementType,\n ForwardRefRenderFunction,\n Fragment,\n ReactElement,\n useEffect,\n useMemo,\n useRef\n} from 'react'\nimport classNames from 'classnames'\nimport { AriaButtonProps, useMenuTrigger, useOverlayPosition } from 'react-aria'\nimport { useMenuTriggerState } from 'react-stately'\n\nimport {\n useFloatingOverlay,\n useForkedRef,\n useIsomorphicLayoutEffect,\n useOpenStateProps,\n useOverlayMaxHeight\n} from '../../hooks'\nimport { executeAfterTransition } from '../../utils/dialogTransition'\nimport { isEventInside } from '../../utils/insideEvents'\nimport {\n Placement,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { NavOverflowBoundary } from '../../utils/navOverflow'\nimport { pushOverlay } from '../../utils/overlayStack'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\n\nexport type { Placement }\nexport type MenuFocusStrategy = 'first' | 'last'\n\nexport type MenuAutoClose = boolean | 'inside' | 'outside'\n\ntype MenuOwnProps<C extends ElementType> = {\n /**\n * Controls which clicks close the menu. `true` closes on any click inside or outside.\n * `false` leaves closing to the toggle, the Escape key and `visible`. `'inside'` closes only\n * on click inside the menu. `'outside'` closes only on click outside the menu.\n */\n autoClose?: MenuAutoClose\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Component used for the root node. Either a string to use a HTML element or a component.\n * Defaults to `Fragment` — `MenuToggle`/`MenuList` render with no wrapping element, so\n * they land as direct children of whatever contains the `Menu`. This matters inside\n * `ButtonGroup`/`InputGroup`, whose CSS expects the toggle button and menu panel as direct\n * children rather than nested inside an intermediate node.\n *\n * Pass an actual element (e.g. `\"div\"`, or `\"li\"` for a navbar item) to opt back into a\n * wrapper — needed if you want to apply `className`/`style`/other rest props to a container\n * around the whole menu, for semantic wrapping like a nav `<li>`, or for `reference=\"parent\"`,\n * which positions off this wrapper and has nothing to measure against without one.\n */\n component?: C\n /**\n * Teleports the menu panel to a container element on open. Accepts an element reference, or\n * `true` to append to `document.body`, or to the open dialog the menu is in, so the panel\n * stays in that dialog's top layer.\n */\n container?: boolean | Element\n /**\n * Whether the menu is open when it first renders. Use it instead of `visible` when nothing\n * outside needs to control the menu.\n */\n defaultVisible?: boolean\n /**\n * Distance between the menu and its reference element, as `[skidding, distance]` in pixels.\n */\n offset?: [number, number]\n /**\n * Callback fired when the menu starts to hide.\n */\n onHide?: () => void\n /**\n * Callback fired after the menu finishes hiding.\n */\n onHidden?: () => void\n /**\n * Callback fired when the menu starts to show.\n */\n onShow?: () => void\n /**\n * Callback fired after the menu finishes showing.\n */\n onShown?: () => void\n /**\n * Callback fired when the menu asks to show or hide: the toggle, a click that `autoClose`\n * counts, or the Escape or Tab key. Receives the state it asks for. With `visible` set, the\n * menu changes only when `visible` does.\n */\n onVisibleChange?: (visible: boolean) => void\n /**\n * Initial placement. Chassis will flip it to keep the menu in view.\n *\n * @type 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end'\n */\n placement?: Placement\n /**\n * Reference element used for positioning. `'toggle'` uses the trigger. `'parent'` uses this\n * component's own rendered element, useful for split buttons and button groups.\n */\n reference?: 'toggle' | 'parent'\n /**\n * Whether the menu is open. Setting it makes the menu controlled: it opens and closes only\n * when this changes, so pair it with `onVisibleChange`. Leave it unset, or use\n * `defaultVisible`, for a menu that opens and closes itself.\n */\n visible?: boolean\n}\n\nexport type MenuProps<C extends ElementType = typeof Fragment> = PolymorphicComponentProps<\n C,\n MenuOwnProps<C>\n>\n\ntype MenuComponent = (<C extends ElementType = typeof Fragment>(\n props: MenuProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nexport interface MenuContextProps {\n autoClose: MenuAutoClose\n close: () => void\n container?: boolean | Element\n focusStrategy: MenuFocusStrategy | null\n hide: () => void\n menuId: string\n menuStyle: React.CSSProperties\n menuTriggerProps: AriaButtonProps\n overlayRef: React.MutableRefObject<HTMLElement | null>\n placementAttr: string\n /**\n * The open dialog the menu is in, or `document.body`; `null` until the menu first opens. A\n * `MenuSubmenu` portals its panel there, so inside a modal dialog it is in the top layer with\n * the menu rather than under it, where the page is inert.\n */\n portalContainer?: Element | null\n reference: 'toggle' | 'parent'\n /**\n * Registers (or, passing `null`, unregisters) a nested `MenuSubmenu`'s own portaled panel\n * element, so this `Menu`'s outside/inside click-dismiss logic recognizes clicks landing in it\n * as \"inside\" the menu — see `MenuSubmenu`'s own use for why this is necessary: its panel\n * portals straight to `document.body`, structurally detached from this menu's own DOM subtree.\n */\n registerOverlay: (id: string, node: HTMLElement | null) => void\n show: (focusStrategy?: MenuFocusStrategy | null) => void\n targetRef: React.MutableRefObject<HTMLElement | null>\n toggle: (focusStrategy?: MenuFocusStrategy | null) => void\n toggleNodeRef: React.MutableRefObject<HTMLElement | null>\n triggerId: string\n visible: boolean\n}\n\n// A fully-shaped no-op default so a `MenuToggle`/`MenuList`/`MenuSubmenu` rendered without a\n// `Menu` ancestor (or in an environment where context can't cross a component boundary, e.g.\n// some static-site prerenderers) degrades to an inert, always-closed menu instead of throwing.\nconst noop = () => undefined\n\nconst defaultMenuContext: MenuContextProps = {\n autoClose: true,\n close: noop,\n focusStrategy: null,\n hide: noop,\n menuId: '',\n menuStyle: {},\n menuTriggerProps: {},\n overlayRef: { current: null },\n placementAttr: 'bottom-start',\n reference: 'toggle',\n registerOverlay: noop,\n show: noop,\n targetRef: { current: null },\n toggle: noop,\n toggleNodeRef: { current: null },\n triggerId: '',\n visible: false\n}\n\nexport const MenuContext = createContext(defaultMenuContext)\n\n// The clicks on a `MenuToggle` or a `MenuSubmenu` trigger. One in a menu's list opens a menu of\n// its own: it is no click on an item of that list.\nexport const menuToggleClicks = new WeakSet<Event>()\n\n// The outside-click handlers of the open menus. react-aria's press handling stops the click on a\n// `MenuToggle` before it reaches `window`, where those handlers listen, so another menu stayed open\n// beside the one the click opened: the toggle hands its click to each of them itself.\nexport const openMenuDismissals = new Set<(event: Event) => void>()\n\nfunction MenuRender<C extends ElementType = typeof Fragment>(\n {\n children,\n autoClose = true,\n className,\n component,\n container,\n defaultVisible,\n offset: offsetProp = [0, 2],\n onHide,\n onHidden,\n onShow,\n onShown,\n onVisibleChange,\n placement = 'bottom-start',\n reference = 'toggle',\n visible,\n ...rest\n }: MenuProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? (Fragment as ElementType)\n const wrapperRef = useRef<HTMLElement>(null)\n const forkedRef = useForkedRef(ref, wrapperRef)\n const toggleNodeRef = useRef<HTMLElement | null>(null)\n const targetRef = useRef<HTMLElement | null>(null)\n const overlayRef = useRef<HTMLElement | null>(null)\n // Portaled `MenuSubmenu` panels register themselves here (see `registerOverlay` below and\n // `MenuSubmenu`'s own ref callback) so `handleDismiss` can recognize clicks inside them as\n // \"inside\" this menu despite living outside `overlayRef.current`'s own DOM subtree.\n const submenuOverlaysRef = useRef<Map<string, HTMLElement>>(new Map())\n const registerOverlay = (id: string, node: HTMLElement | null) => {\n if (node) submenuOverlaysRef.current.set(id, node)\n else submenuOverlaysRef.current.delete(id)\n }\n\n // Controlled by `visible` when it is set: `show`/`hide`/`toggle` (from `MenuToggle`, autoClose\n // dismissal, an item) then only report to `onVisibleChange`.\n const state = useMenuTriggerState(\n useOpenStateProps({ defaultVisible, onVisibleChange, visible }, 'Menu')\n )\n const { menuTriggerProps, menuProps } = useMenuTrigger<unknown>({}, state, toggleNodeRef)\n\n useIsomorphicLayoutEffect(() => {\n if (reference === 'parent') {\n targetRef.current = wrapperRef.current\n }\n }, [reference])\n\n // `onShown`/`onHidden` wait for chassis-css's own opacity/transform transition on `.menu`\n // (see `_menu.scss`) to actually finish, matching `Modal`'s identically-worded \"requests to\n // be shown\" vs \"finishes showing\" contract (`Modal.tsx`'s own `executeAfterTransition` use).\n // `overlayRef.current` is `MenuList`'s root element — already in the DOM and already\n // reflecting the new `.show` class by the time this effect runs, since React commits the\n // render before passive effects execute. Falls back to firing synchronously when no\n // `MenuList` is mounted to measure (nothing to transition, so nothing to wait for).\n //\n // All four report *transitions*, so none fires for the initial commit — mounting closed is not\n // a hide. Without this guard, mounting fired `onHide` (and scheduled `onHidden`) for every menu\n // on the page before `onShow` had ever fired once, which `Menu.spec.tsx` used to have to\n // `mockClear()` past.\n const mountedRef = useRef(false)\n\n useEffect(() => {\n const overlay = overlayRef.current\n const isInitialCommit = !mountedRef.current\n mountedRef.current = true\n if (isInitialCommit) return undefined\n\n if (state.isOpen) {\n onShow?.()\n if (!overlay) {\n onShown?.()\n return undefined\n }\n return executeAfterTransition(overlay, () => onShown?.(), true)\n }\n\n onHide?.()\n if (!overlay) {\n onHidden?.()\n return undefined\n }\n return executeAfterTransition(overlay, () => onHidden?.(), true)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen])\n\n const {\n overlayProps,\n placement: resolvedPlacement,\n updatePosition\n } = useOverlayPosition({\n targetRef,\n overlayRef,\n placement: toAriaPlacement(placement),\n offset: offsetProp[1],\n crossOffset: offsetProp[0],\n containerPadding: 8,\n isOpen: state.isOpen,\n // `useOverlayPosition` closes on any window scroll via a backward-compat `WeakMap` that\n // `useMenuTrigger` populates for `targetRef.current` (see `MenuToggle`'s `setRefs`).\n // Passing `null` opts out so the menu repositions with its trigger instead of vanishing —\n // matching `Autocomplete`/`Combobox`, neither of which is wired into that map.\n onClose: null\n })\n useOverlayMaxHeight(overlayRef, state.isOpen)\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n placement,\n resolvedPlacement\n )\n\n // Escape closes the menu and returns focus to the toggle. Controlled, the close is a request:\n // focus returns when `visible` follows it, in the effect below, and stays where it is when\n // nothing can follow it or the caller declines. Read through a ref because the context value\n // these functions travel in is memoized.\n const followsRequestsRef = useRef(true)\n followsRequestsRef.current = visible === undefined || !!onVisibleChange\n const isControlledRef = useRef(false)\n isControlledRef.current = visible !== undefined\n const focusReturnOwedRef = useRef(false)\n\n const show = (focusStrategy?: MenuFocusStrategy | null) => state.open(focusStrategy)\n const hide = () => {\n focusReturnOwedRef.current = false\n state.close()\n }\n const toggleVisible = (focusStrategy?: MenuFocusStrategy | null) => state.toggle(focusStrategy)\n const close = () => {\n state.close()\n if (!isControlledRef.current) toggleNodeRef.current?.focus()\n else focusReturnOwedRef.current = followsRequestsRef.current\n }\n\n useEffect(() => {\n if (!state.isOpen && focusReturnOwedRef.current) toggleNodeRef.current?.focus()\n focusReturnOwedRef.current = false\n }, [state.isOpen])\n\n // The open dialog the toggle is in, if any, as `Popover` and `ContextMenu` resolve it: a list\n // teleported by `container` goes into that dialog rather than `document.body`, which lies\n // under a modal dialog's top layer, and the menu closes when the dialog does, teleported or\n // not, so a reopened dialog doesn't show a menu left open. `onShow`/`onHide` stay with the\n // effect above.\n const portalContainer = useFloatingOverlay({\n close: hide,\n isOpen: state.isOpen,\n triggerRef: toggleNodeRef\n })\n\n // The list is mounted again when it moves into the dialog, as a new element in another\n // containing block: placed again here, after its ref is set and before the paint.\n useIsomorphicLayoutEffect(() => {\n if (state.isOpen) updatePosition()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [portalContainer])\n\n // Deferred so the click that opened the menu doesn't immediately close it, and scoped\n // to match menu.js's `clearMenus`: skip the toggle itself, honor `inside`/`outside`\n // modes, and let Tab or clicks on form controls inside the menu pass through untouched.\n useEffect(() => {\n if (!state.isOpen || autoClose === false) return undefined\n\n // A toggle's click can come both ways: from the toggle, and on `window` when nothing stopped it.\n const handled = new WeakSet<Event>()\n const handleDismiss = (event: Event) => {\n if (event instanceof KeyboardEvent && event.key !== 'Tab') return\n if (handled.has(event)) return\n handled.add(event)\n\n const target = event.target as Node\n const toggleNode = toggleNodeRef.current\n const menuNode = overlayRef.current\n\n if (toggleNode?.contains(target)) return\n\n const isMenuTarget =\n !!menuNode?.contains(target) ||\n Array.from(submenuOverlaysRef.current.values()).some((node) => node.contains(target))\n\n // An overlay opened from the menu (a popover on an item, a picker's list) is portaled out\n // of the list, and React still renders it under it (`insideEvents`). A click there is\n // neither a click on an item nor one outside the menu: it is that overlay's.\n if (!isMenuTarget && isEventInside(event, overlayRef)) return\n if (isMenuTarget && menuToggleClicks.has(event)) return\n\n if (autoClose === 'inside' && !isMenuTarget) return\n if (autoClose === 'outside' && isMenuTarget) return\n\n if (\n isMenuTarget &&\n ((event instanceof KeyboardEvent && event.key === 'Tab') ||\n /input|select|option|textarea|form/i.test((target as HTMLElement).tagName ?? ''))\n ) {\n return\n }\n\n // An item chosen returns focus to the toggle, as Escape does: the closed list is\n // `display: none`, and focus on an item in it fell to `<body>`. Only while the menu holds\n // focus, or nothing does: an item that opened a dialog has moved it there. A click outside\n // or Tab has put focus where it is going already.\n const active = document.activeElement\n const holdsFocus =\n !active ||\n active === document.body ||\n !!menuNode?.contains(active) ||\n Array.from(submenuOverlaysRef.current.values()).some((node) => node.contains(active))\n if (isMenuTarget && holdsFocus) close()\n else hide()\n }\n\n const id = window.setTimeout(() => {\n window.addEventListener('click', handleDismiss)\n window.addEventListener('keyup', handleDismiss)\n openMenuDismissals.add(handleDismiss)\n })\n\n return () => {\n window.clearTimeout(id)\n window.removeEventListener('click', handleDismiss)\n window.removeEventListener('keyup', handleDismiss)\n openMenuDismissals.delete(handleDismiss)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen, autoClose])\n\n // Escape should always close the menu, independent of `autoClose`'s inside/outside/false\n // modes. `MenuList`'s own `onKeyDown` handling only fires when focus is already inside the\n // panel (e.g. opened via ArrowDown) — a mouse-press open via `useMenuTrigger` leaves focus on\n // the trigger button, where that handler is unreachable. The stack of open overlays listens on\n // `window`, which catches Escape regardless of where focus currently is, and gives it to this\n // menu only while nothing opened since is still open, and never to the popover or the dialog\n // around the menu as well.\n useEffect(() => {\n if (!state.isOpen) return undefined\n\n return pushOverlay({\n nodes: () => [overlayRef.current, toggleNodeRef.current],\n onEscape: close\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen])\n\n const contextValue: MenuContextProps = useMemo(\n () => ({\n autoClose,\n close,\n container: container === true ? (portalContainer ?? true) : container,\n focusStrategy: state.focusStrategy as MenuFocusStrategy | null,\n hide,\n menuId: menuProps.id ?? '',\n menuStyle,\n menuTriggerProps,\n overlayRef,\n placementAttr,\n portalContainer,\n reference,\n registerOverlay,\n show,\n targetRef,\n toggle: toggleVisible,\n toggleNodeRef,\n triggerId: menuTriggerProps.id ?? '',\n visible: state.isOpen\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n autoClose,\n container,\n state.focusStrategy,\n menuProps.id,\n menuStyle,\n menuTriggerProps,\n placementAttr,\n portalContainer,\n reference,\n state.isOpen\n ]\n )\n\n // Inside a `NavOverflow`, a menu in a nav item is that item's content, not its link: a toggle\n // rendered as a `NavLink` has nothing to show in the overflow menu.\n const content = <NavOverflowBoundary>{children}</NavOverflowBoundary>\n\n return (\n <MenuContext.Provider value={contextValue}>\n {Component === Fragment ? (\n content\n ) : (\n // `show` mirrors vanilla menu.js's `this._parent.classList.add('show')` — needed for\n // e.g. `.nav-item.show .nav-link` to put a `NavLink`-rooted `MenuToggle` into its\n // pressed look while open, since a bare `.nav-link.show` has no styling of its own.\n <Component\n className={classNames(className, { show: state.isOpen })}\n {...rest}\n ref={forkedRef}\n >\n {content}\n </Component>\n )}\n </MenuContext.Provider>\n )\n}\n\nexport const Menu = createPolymorphicComponent<MenuComponent>(\n MenuRender as ForwardRefRenderFunction<Element, MenuProps<ElementType>>,\n 'Menu'\n)\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{d as e,f as t,m as n,v as r}from"./slot-BQVx1Eew.js";import{t as i}from"./useForkedRef-WoqMqsWE.js";import{t as a}from"./polymorphic-CZIFszAy.js";import{t as o}from"./useHydrated-Dud4JEwp.js";import{t as s}from"./renderMenuItemContent-DNdj-Ukz.js";import{t as c}from"./Portal-BTDylxAi.js";import{t as l}from"./Link-DE8NSAXJ.js";import{t as u}from"./Button-ZU-x1uN_.js";import{t as d}from"./insideEvents-CWcNrMu7.js";import{i as f,n as p,r as m}from"./Menu-264aGoBR.js";import h,{createContext as g,forwardRef as _,useContext as v,useEffect as y,useRef as b}from"react";import x from"classnames";import{mergeProps as S,useButton as C}from"react-aria";const w=_(({className:e,...t},n)=>{let r=x(`menu-divider`,e);return/* @__PURE__ */ h.createElement(`hr`,{className:r,...t,ref:n})});w.displayName=`MenuDivider`;function T({children:e,className:t,component:n,role:r=`presentation`,...i},a){let o=n??`h4`,s=x(`menu-header`,t);return/* @__PURE__ */ h.createElement(o,{className:s,role:r,...i,ref:a},e)}const E=a(T,`MenuHeader`);function D({children:e,className:t,component:r,description:i,href:a,icon:o,onClick:c,selected:u,...d},f){let p=x(`menu-item`,{selected:u},t);return/* @__PURE__ */ h.createElement(l,{role:`menuitem`,component:n(r,a,`button`),href:a,onClick:e=>{a===`#`&&e.preventDefault(),c?.(e)},...d,className:p,ref:f},s({icon:o,label:e,description:i}))}const O=a(D,`MenuItem`),k=`:is(.menu-item, .submenu-back):not(.disabled):not(:disabled)`,A=e=>!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length),j=e=>{if(!e)return[];let t=[];for(let n of Array.from(e.children))if(n.matches(k))t.push(n);else if(n.classList.contains(`submenu`)){let e=Array.from(n.children).find(e=>e.matches(k));e&&t.push(e)}return t.filter(A)},M=(e,t)=>{e.length&&(t===`first`?e[0]:e[e.length-1]).focus()},N=(e,{onArrowLeft:t,onArrowRight:n,onEscape:r})=>{let i=e.currentTarget,a=e.target;switch(e.key){case`ArrowDown`:case`ArrowUp`:{e.preventDefault(),e.stopPropagation();let t=j(i);if(!t.length)return;let n=t.indexOf(a);t[n===-1?e.key===`ArrowDown`?0:t.length-1:(n+(e.key===`ArrowDown`?1:-1)+t.length)%t.length].focus();return}case`Home`:case`End`:e.preventDefault(),e.stopPropagation(),M(j(i),e.key===`Home`?`first`:`last`);return;case`Escape`:if(!r)return;e.preventDefault(),e.stopPropagation(),r();return;case`ArrowLeft`:if(!t)return;e.preventDefault(),e.stopPropagation(),t();return;case`ArrowRight`:if(!n)return;e.preventDefault(),e.stopPropagation(),n();return}},P=g(null),F=()=>{let e=b(null);if(!e.current){let t=/* @__PURE__ */ new Map;e.current={register:(e,n)=>(t.set(e,n),()=>{t.delete(e)}),notifyOpen:e=>{t.forEach((t,n)=>{n!==e&&t()})}}}return e.current},I=g(null),L=g(!0),R=e=>e.type===`header`?/* @__PURE__ */ h.createElement(E,{key:e.id},e.label):e.type===`divider`?/* @__PURE__ */ h.createElement(w,{key:e.id}):/* @__PURE__ */ h.createElement(O,{key:e.id,href:e.href,disabled:e.disabled,selected:e.selected,onClick:e.onClick},s({icon:e.icon,label:e.label,description:e.description,selected:e.selected}));function z({children:e,className:t,component:n,items:r,onKeyDown:a,...s},l){let u=n??`div`,{close:f,container:m,focusStrategy:g,menuId:_,menuStyle:b,overlayRef:C,placementAttr:w,triggerId:T,visible:E}=v(p),D=i(l,C),O=F(),k=o(),A=E&&k;y(()=>{E&&g&&M(j(C.current),g===`last`?`last`:`first`)},[E,g]);let I=e=>{N(e,{onEscape:f}),a?.(e)},L=s[`aria-label`]?void 0:T||void 0,z=/* @__PURE__ */ h.createElement(u,{role:`menu`,id:_,"aria-labelledby":L,className:x(`menu`,{show:A},t),style:b,"data-cx-placement":w,...S(s,d(C)),onKeyDown:I,ref:D},/* @__PURE__ */ h.createElement(P.Provider,{value:O},r?r.map(R):e));return m?/* @__PURE__ */ h.createElement(c,{container:m===!0?void 0:m},z):z}const B=a(z,`MenuList`);function V({children:n,caret:a=!0,className:o,component:s,href:c,onClick:l,onKeyDown:d,tabIndex:g,..._},y){let{hide:w,menuTriggerProps:T,reference:E,targetRef:D,toggleNodeRef:O,visible:k}=v(p),A=s??u,j=b(null),M=A===u?e(c)?`anchor`:`button`:r(A,c,_),N=M===`button`,P=A===u?{href:c}:t(M,c,`MenuToggle`),{buttonProps:F}=C({...T,elementType:N?`button`:`a`},j),I=b(!1),L=i(y,e=>{j.current=e,O.current=e,E!==`parent`&&(D.current=e)}),R=e=>{I.current=e.pointerType!==`touch`&&k},z=e=>{e.preventDefault(),m.add(e.nativeEvent);for(let t of[...f])t(e.nativeEvent);I.current&&(I.current=!1,w()),l?.(e)};return/* @__PURE__ */ h.createElement(A,{...N?{type:`button`}:{},className:x({caret:a,show:k},o),...S({onPointerDown:R},_,F,{onClick:z,onKeyDown:d,...g!==void 0&&{tabIndex:g}}),...P,ref:L},n)}const H=a(V,`MenuToggle`);export{L as a,j as c,E as d,w as f,P as i,N as l,B as n,F as o,I as r,M as s,H as t,O as u};
2
- //# sourceMappingURL=MenuToggle-DcPEh55c.js.map
1
+ import{d as e,f as t,m as n,v as r}from"./slot-BQVx1Eew.js";import{t as i}from"./useForkedRef-WoqMqsWE.js";import{t as a}from"./polymorphic-CZIFszAy.js";import{t as o}from"./useHydrated-Dud4JEwp.js";import{t as s}from"./renderMenuItemContent-DNdj-Ukz.js";import{t as c}from"./Portal-BTDylxAi.js";import{t as l}from"./Link-DE8NSAXJ.js";import{t as u}from"./Button-ZU-x1uN_.js";import{t as d}from"./insideEvents-CWcNrMu7.js";import{i as f,n as p,r as m}from"./Menu-BiE9CzNk.js";import h,{createContext as g,forwardRef as _,useContext as v,useEffect as y,useRef as b}from"react";import x from"classnames";import{mergeProps as S,useButton as C}from"react-aria";const w=_(({className:e,...t},n)=>{let r=x(`menu-divider`,e);return/* @__PURE__ */ h.createElement(`hr`,{className:r,...t,ref:n})});w.displayName=`MenuDivider`;function T({children:e,className:t,component:n,role:r=`presentation`,...i},a){let o=n??`h4`,s=x(`menu-header`,t);return/* @__PURE__ */ h.createElement(o,{className:s,role:r,...i,ref:a},e)}const E=a(T,`MenuHeader`);function D({children:e,className:t,component:r,description:i,href:a,icon:o,onClick:c,selected:u,...d},f){let p=x(`menu-item`,{selected:u},t);return/* @__PURE__ */ h.createElement(l,{role:`menuitem`,component:n(r,a,`button`),href:a,onClick:e=>{a===`#`&&e.preventDefault(),c?.(e)},...d,className:p,ref:f},s({icon:o,label:e,description:i}))}const O=a(D,`MenuItem`),k=`:is(.menu-item, .submenu-back):not(.disabled):not(:disabled)`,A=e=>!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length),j=e=>{if(!e)return[];let t=[];for(let n of Array.from(e.children))if(n.matches(k))t.push(n);else if(n.classList.contains(`submenu`)){let e=Array.from(n.children).find(e=>e.matches(k));e&&t.push(e)}return t.filter(A)},M=(e,t)=>{e.length&&(t===`first`?e[0]:e[e.length-1]).focus()},N=(e,{onArrowLeft:t,onArrowRight:n,onEscape:r})=>{let i=e.currentTarget,a=e.target;switch(e.key){case`ArrowDown`:case`ArrowUp`:{e.preventDefault(),e.stopPropagation();let t=j(i);if(!t.length)return;let n=t.indexOf(a);t[n===-1?e.key===`ArrowDown`?0:t.length-1:(n+(e.key===`ArrowDown`?1:-1)+t.length)%t.length].focus();return}case`Home`:case`End`:e.preventDefault(),e.stopPropagation(),M(j(i),e.key===`Home`?`first`:`last`);return;case`Escape`:if(!r)return;e.preventDefault(),e.stopPropagation(),r();return;case`ArrowLeft`:if(!t)return;e.preventDefault(),e.stopPropagation(),t();return;case`ArrowRight`:if(!n)return;e.preventDefault(),e.stopPropagation(),n();return}},P=g(null),F=()=>{let e=b(null);if(!e.current){let t=/* @__PURE__ */ new Map;e.current={register:(e,n)=>(t.set(e,n),()=>{t.delete(e)}),notifyOpen:e=>{t.forEach((t,n)=>{n!==e&&t()})}}}return e.current},I=g(null),L=g(!0),R=e=>e.type===`header`?/* @__PURE__ */ h.createElement(E,{key:e.id},e.label):e.type===`divider`?/* @__PURE__ */ h.createElement(w,{key:e.id}):/* @__PURE__ */ h.createElement(O,{key:e.id,href:e.href,disabled:e.disabled,selected:e.selected,onClick:e.onClick},s({icon:e.icon,label:e.label,description:e.description,selected:e.selected}));function z({children:e,className:t,component:n,items:r,onKeyDown:a,...s},l){let u=n??`div`,{close:f,container:m,focusStrategy:g,menuId:_,menuStyle:b,overlayRef:C,placementAttr:w,triggerId:T,visible:E}=v(p),D=i(l,C),O=F(),k=o(),A=E&&k;y(()=>{E&&g&&M(j(C.current),g===`last`?`last`:`first`)},[E,g]);let I=e=>{N(e,{onEscape:f}),a?.(e)},L=s[`aria-label`]?void 0:T||void 0,z=/* @__PURE__ */ h.createElement(u,{role:`menu`,id:_,"aria-labelledby":L,className:x(`menu`,{show:A},t),style:b,"data-cx-placement":w,...S(s,d(C)),onKeyDown:I,ref:D},/* @__PURE__ */ h.createElement(P.Provider,{value:O},r?r.map(R):e));return m?/* @__PURE__ */ h.createElement(c,{container:m===!0?void 0:m},z):z}const B=a(z,`MenuList`);function V({children:n,caret:a=!0,className:o,component:s,href:c,onClick:l,onKeyDown:d,tabIndex:g,..._},y){let{hide:w,menuTriggerProps:T,reference:E,targetRef:D,toggleNodeRef:O,visible:k}=v(p),A=s??u,j=b(null),M=A===u?e(c)?`anchor`:`button`:r(A,c,_),N=M===`button`,P=A===u?{href:c}:t(M,c,`MenuToggle`),{buttonProps:F}=C({...T,elementType:N?`button`:`a`},j),I=b(!1),L=i(y,e=>{j.current=e,O.current=e,E!==`parent`&&(D.current=e)}),R=e=>{I.current=e.pointerType!==`touch`&&k},z=e=>{e.preventDefault(),m.add(e.nativeEvent);for(let t of[...f])t(e.nativeEvent);I.current&&(I.current=!1,w()),l?.(e)};return/* @__PURE__ */ h.createElement(A,{...N?{type:`button`}:{},className:x({caret:a,show:k},o),...S({onPointerDown:R},_,F,{onClick:z,onKeyDown:d,...g!==void 0&&{tabIndex:g}}),...P,ref:L},n)}const H=a(V,`MenuToggle`);export{L as a,j as c,E as d,w as f,P as i,N as l,B as n,F as o,I as r,M as s,H as t,O as u};
2
+ //# sourceMappingURL=MenuToggle-W-ZSHFwF.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MenuToggle-DcPEh55c.js","names":["hasHref","hrefProps","linkElement","resolveLinkKind","useForkedRef","createPolymorphicComponent","useHydrated","renderMenuItemContent","Portal","Link","Button","insideEventProps","openMenuDismissals","MenuContext","menuToggleClicks","React","classNames","MenuDivider","forwardRef","rest","_className","className","MenuHeaderRender","Component","component","children","MenuHeader","MenuItemRender","href","event","onClick","MenuItem","VISIBLE_ITEMS_SELECTOR","isVisible","element","getMenuItems","menu","items","child","trigger","grandchild","focusMenuItem","target","handleMenuKeyDown","currentIndex","onEscape","onArrowLeft","onArrowRight","SubmenuGroupContext","createContext","useSubmenuGroupProvider","ref","useRef","closers","id","close","key","SubmenuActionsContext","SubmenuVisibleContext","renderMenuItemDef","def","MenuListRender","useContext","forkedRef","overlayRef","submenuGroup","hydrated","shown","visible","useEffect","focusStrategy","handleKeyDown","onKeyDown","labelledBy","triggerId","content","menuId","menuStyle","placementAttr","mergeProps","container","MenuList","MenuToggleRender","buttonRef","kind","rendersButton","linkProps","useButton","menuTriggerProps","wasOpenRef","node","reference","handlePointerDown","handleClick","dismiss","hide","buttonProps","tabIndex","MenuToggle"],"sources":["../../src/components/menu/MenuDivider.tsx","../../src/components/menu/MenuHeader.tsx","../../src/components/menu/MenuItem.tsx","../../src/components/menu/menuNavigation.ts","../../src/components/menu/submenuGroup.ts","../../src/components/menu/MenuList.tsx","../../src/components/menu/MenuToggle.tsx"],"sourcesContent":["import React, { forwardRef, HTMLAttributes } from 'react'\nimport classNames from 'classnames'\n\nexport interface MenuDividerProps extends HTMLAttributes<HTMLHRElement> {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLHRElement, MenuDividerProps>(\n ({ className, ...rest }, ref) => {\n const _className = classNames('menu-divider', className)\n\n return <hr className={_className} {...rest} ref={ref} />\n }\n)\n\nMenuDivider.displayName = 'MenuDivider'\n","import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'\nimport classNames from 'classnames'\n\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\n\ntype MenuHeaderOwnProps<C extends ElementType> = {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n /**\n * Component used for the root node. Either a string to use a HTML element or a component.\n */\n component?: C\n /**\n * ARIA role applied to the root node. Defaults to `'presentation'` — see the render function\n * for why.\n */\n role?: React.AriaRole\n}\n\nexport type MenuHeaderProps<C extends ElementType = 'h4'> = PolymorphicComponentProps<\n C,\n MenuHeaderOwnProps<C>\n>\n\ntype MenuHeaderComponent = (<C extends ElementType = 'h4'>(\n props: MenuHeaderProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuHeaderRender<C extends ElementType = 'h4'>(\n { children, className, component, role = 'presentation', ...rest }: MenuHeaderProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'h4'\n const _className = classNames('menu-header', className)\n\n // Always rendered as a direct child of `role=\"menu\"` (see MenuList) — ARIA's menu role only\n // permits menuitem/group/separator children, so a bare heading fails aria-required-children.\n // `role=\"presentation\"` opts the element itself out without hiding its text content.\n return (\n <Component className={_className} role={role} {...rest} ref={ref}>\n {children}\n </Component>\n )\n}\n\nexport const MenuHeader = createPolymorphicComponent<MenuHeaderComponent>(\n MenuHeaderRender as ForwardRefRenderFunction<Element, MenuHeaderProps<ElementType>>,\n 'MenuHeader'\n)\n","import React, {\n ElementType,\n ForwardRefRenderFunction,\n MouseEvent,\n ReactElement,\n ReactNode\n} from 'react'\nimport classNames from 'classnames'\n\nimport { linkElement } from '../../utils/elementKind'\nimport {\n createPolymorphicComponent,\n PolymorphicRef,\n PolymorphicRefWithFallback\n} from '../../utils/polymorphic'\nimport { renderMenuItemContent } from './renderMenuItemContent'\nimport { LinkProps, Link } from '../link/Link'\n\ntype MenuItemOwnProps = {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n /**\n * Secondary line of text rendered below `children` (`.menu-item-description`).\n */\n description?: ReactNode\n /**\n * Icon rendered at the item's leading edge (`.menu-item-icon`).\n */\n icon?: ReactNode\n /**\n * Marks the item as the current selection in a choice list. Renders in a heavier font weight.\n * Combine with a manually-composed `.menu-item-check` icon (in `children`, or via `icon` on a\n * plain, non-selection item) to also show a checkmark — this prop alone doesn't add one, so\n * existing font-weight-only usage keeps rendering unchanged.\n */\n selected?: boolean\n}\n\nexport type MenuItemProps<C extends ElementType = 'a'> = LinkProps<C> & MenuItemOwnProps\n\ntype MenuItemComponent = (<C extends ElementType = 'a'>(\n props: MenuItemProps<C> & {\n ref?: PolymorphicRefWithFallback<C, HTMLAnchorElement | HTMLButtonElement>\n }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuItemRender<C extends ElementType = 'a'>(\n {\n children,\n className,\n component,\n description,\n href,\n icon,\n onClick,\n selected,\n ...rest\n }: MenuItemProps<C>,\n ref: PolymorphicRef<C>\n) {\n const _className = classNames('menu-item', { selected }, className)\n\n // `href=\"#\"` is a common placeholder for menu items that act via `onClick` rather than\n // real navigation. Left alone, a plain anchor click still navigates to the empty fragment,\n // which scrolls the page to the top — so we suppress that default for the placeholder case\n // only, leaving real same-page anchors (`href=\"#some-id\"`) free to navigate as expected.\n const handleClick = (event: MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => {\n if (href === '#') event.preventDefault()\n onClick?.(event)\n }\n\n // An item with `href` is an `<a>`, one without is a `<button type=\"button\">`, unless `component`\n // or `asChild` chose the element (see `linkElement`). chassis-css styles both as `.menu-item`.\n // An item without `href` used to be an `<a>` with no `href`, which isn't focusable, so keyboard\n // users couldn't reach it outside the menu's own arrow-key handling.\n return (\n <Link\n role=\"menuitem\"\n component={linkElement(component as ElementType | undefined, href, 'button')}\n href={href}\n onClick={handleClick}\n {...(rest as Record<string, unknown>)}\n className={_className}\n ref={ref as PolymorphicRef<ElementType>}\n >\n {renderMenuItemContent({ icon, label: children, description })}\n </Link>\n )\n}\n\nexport const MenuItem = createPolymorphicComponent<MenuItemComponent>(\n MenuItemRender as ForwardRefRenderFunction<Element, MenuItemProps<ElementType>>,\n 'MenuItem'\n)\n","import React from 'react'\n\n// Mirrors Chassis CSS's menu.js SELECTOR_VISIBLE_ITEMS / SELECTOR_KB_NAV_ITEMS: direct-child\n// menu items and submenu-back buttons, plus submenu trigger items nested one level inside a\n// `.submenu` wrapper (which aren't direct children of the `.menu`).\n//\n// Walks `children` directly rather than a `:scope`-based `querySelectorAll` — jsdom's selector\n// engine (nwsapi) mis-parses `:scope` queries against an element whose `id` contains a colon,\n// which is exactly the shape of React 18's default `useId()` output now that `MenuList`/\n// `MenuSubmenu` set a real `id` for `aria-controls`/`aria-labelledby` linking. Real browsers don't\n// have this bug, but walking children is just as correct and sidesteps it either way.\nconst VISIBLE_ITEMS_SELECTOR = ':is(.menu-item, .submenu-back):not(.disabled):not(:disabled)'\n\nconst isVisible = (element: HTMLElement) =>\n Boolean(element.offsetWidth || element.offsetHeight || element.getClientRects().length)\n\nexport const getMenuItems = (menu: HTMLElement | null): HTMLElement[] => {\n if (!menu) return []\n const items: HTMLElement[] = []\n for (const child of Array.from(menu.children)) {\n if (child.matches(VISIBLE_ITEMS_SELECTOR)) {\n items.push(child as HTMLElement)\n } else if (child.classList.contains('submenu')) {\n const trigger = Array.from(child.children).find((grandchild) =>\n grandchild.matches(VISIBLE_ITEMS_SELECTOR)\n )\n if (trigger) items.push(trigger as HTMLElement)\n }\n }\n return items.filter(isVisible)\n}\n\nexport const focusMenuItem = (items: HTMLElement[], target: 'first' | 'last') => {\n if (!items.length) return\n ;(target === 'first' ? items[0]! : items[items.length - 1]!).focus()\n}\n\nexport interface MenuKeyDownOptions {\n onArrowLeft?: () => void\n onArrowRight?: () => void\n onEscape?: () => void\n}\n\n// Scoped to `event.currentTarget` (the `.menu` element the handler is bound to), so the same\n// function drives keyboard navigation for both the top-level menu and any nested submenu list.\n// `onArrowLeft`/`onArrowRight` are both optional and independent (rather than a single\n// direction-agnostic \"close\" callback) so a caller under an RTL locale can wire the one that\n// actually points back toward the trigger — see `MenuSubmenu`, the only current consumer of\n// either.\nexport const handleMenuKeyDown = (\n event: React.KeyboardEvent<HTMLElement>,\n { onArrowLeft, onArrowRight, onEscape }: MenuKeyDownOptions\n): void => {\n const menu = event.currentTarget\n const target = event.target as HTMLElement\n\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault()\n event.stopPropagation()\n const items = getMenuItems(menu)\n if (!items.length) return\n const currentIndex = items.indexOf(target)\n const nextIndex =\n currentIndex === -1\n ? event.key === 'ArrowDown'\n ? 0\n : items.length - 1\n : (currentIndex + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length\n // `nextIndex` is always a valid index into `items` here (0, items.length - 1, or a modulo\n // result — the `if (!items.length) return` above already ruled out the empty-array case).\n items[nextIndex]!.focus()\n return\n }\n case 'Home':\n case 'End': {\n event.preventDefault()\n event.stopPropagation()\n focusMenuItem(getMenuItems(menu), event.key === 'Home' ? 'first' : 'last')\n return\n }\n case 'Escape': {\n if (!onEscape) return\n event.preventDefault()\n event.stopPropagation()\n onEscape()\n return\n }\n case 'ArrowLeft': {\n if (!onArrowLeft) return\n event.preventDefault()\n event.stopPropagation()\n onArrowLeft()\n return\n }\n case 'ArrowRight': {\n if (!onArrowRight) return\n event.preventDefault()\n event.stopPropagation()\n onArrowRight()\n return\n }\n default:\n }\n}\n","import { createContext, useRef } from 'react'\n\n// Lets sibling `.submenu` flyouts at the same menu level close one another when a new one\n// opens, mirroring menu.js's `_closeSiblingSubmenus`. One provider instance is created per\n// menu level (the top-level `.menu` and each `.submenu`'s own nested list) and lives for the\n// lifetime of that level, so registration doesn't churn on every render.\nexport interface SubmenuGroupContextValue {\n register: (id: string, close: () => void) => () => void\n notifyOpen: (id: string) => void\n}\n\nexport const SubmenuGroupContext = createContext<SubmenuGroupContextValue | null>(null)\n\nexport const useSubmenuGroupProvider = (): SubmenuGroupContextValue => {\n const ref = useRef<SubmenuGroupContextValue | null>(null)\n\n if (!ref.current) {\n const closers = new Map<string, () => void>()\n ref.current = {\n register: (id, close) => {\n closers.set(id, close)\n return () => {\n closers.delete(id)\n }\n },\n notifyOpen: (id) => {\n closers.forEach((close, key) => {\n if (key !== id) close()\n })\n }\n }\n }\n\n return ref.current\n}\n\n// Exposes the current `.submenu`'s own close-and-refocus action to a nested `MenuSubmenuBack`\n// button, without threading it through the sibling-group registry above.\nexport interface SubmenuActionsContextValue {\n close: () => void\n}\n\nexport const SubmenuActionsContext = createContext<SubmenuActionsContextValue | null>(null)\n\n// Whether the `.submenu` a nested `MenuSubmenu` is in is open. A submenu's panel is portaled out\n// of its parent's, so nothing hides it when the parent closes: it follows this, as the first\n// level follows the `Menu` itself. `true` at the top level, where there is no parent submenu.\nexport const SubmenuVisibleContext = createContext(true)\n","import React, {\n ElementType,\n ForwardRefRenderFunction,\n ReactElement,\n ReactNode,\n useContext,\n useEffect\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps } from 'react-aria'\n\nimport { useForkedRef } from '../../hooks'\nimport { insideEventProps } from '../../utils/insideEvents'\nimport { renderMenuItemContent } from './renderMenuItemContent'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\nimport { useHydrated } from '../../hooks/useHydrated'\nimport { Portal } from '../portal/Portal'\nimport { MenuContext } from './Menu'\nimport { MenuDivider } from './MenuDivider'\nimport { MenuHeader } from './MenuHeader'\nimport { MenuItem } from './MenuItem'\nimport { MenuItemsDef } from './MenuItemDef'\nimport { focusMenuItem, getMenuItems, handleMenuKeyDown } from './menuNavigation'\nimport { SubmenuGroupContext, useSubmenuGroupProvider } from './submenuGroup'\n\ntype MenuListOwnProps<C extends ElementType> = {\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Component used for the root node. Either a string to use a HTML element or a component.\n */\n component?: C\n /**\n * Array of item/header/divider definitions for data-driven rendering. When provided, children\n * are ignored. Covers flat items, headers, and dividers only — for nested submenus, compose\n * with `children` and `MenuSubmenu` instead.\n */\n items?: MenuItemsDef\n}\n\nexport type MenuListProps<C extends ElementType = 'div'> = PolymorphicComponentProps<\n C,\n MenuListOwnProps<C>\n>\n\ntype MenuListComponent = (<C extends ElementType = 'div'>(\n props: MenuListProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nconst renderMenuItemDef = (def: MenuItemsDef[number]): ReactNode => {\n if (def.type === 'header') {\n return <MenuHeader key={def.id}>{def.label}</MenuHeader>\n }\n if (def.type === 'divider') {\n return <MenuDivider key={def.id} />\n }\n return (\n <MenuItem\n key={def.id}\n href={def.href}\n disabled={def.disabled}\n selected={def.selected}\n onClick={def.onClick}\n >\n {renderMenuItemContent({\n icon: def.icon,\n label: def.label,\n description: def.description,\n selected: def.selected\n })}\n </MenuItem>\n )\n}\n\nfunction MenuListRender<C extends ElementType = 'div'>(\n { children, className, component, items, onKeyDown, ...rest }: MenuListProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'div'\n const {\n close,\n container,\n focusStrategy,\n menuId,\n menuStyle,\n overlayRef,\n placementAttr,\n triggerId,\n visible\n } = useContext(MenuContext)\n const forkedRef = useForkedRef(ref, overlayRef)\n const submenuGroup = useSubmenuGroupProvider()\n // The list is positioned in a layout effect, which the server never runs: a menu open on its\n // first render was painted at the top left of the page until the JavaScript had loaded. It is\n // shown once hydration has finished, where that effect has placed it.\n const hydrated = useHydrated()\n const shown = visible && hydrated\n\n // ArrowDown/ArrowUp on the trigger opens the menu with a focus strategy (see `Menu`'s\n // `useMenuTrigger` wiring) — this is where that intent actually lands, since we're not\n // adopting `useMenu`'s own collection-aware auto-focus.\n useEffect(() => {\n if (!visible || !focusStrategy) return\n focusMenuItem(getMenuItems(overlayRef.current), focusStrategy === 'last' ? 'last' : 'first')\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, focusStrategy])\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n handleMenuKeyDown(event, { onEscape: close })\n onKeyDown?.(event as React.KeyboardEvent<HTMLDivElement>)\n }\n\n // Labelled by the trigger, unless the caller names the list itself: `aria-labelledby` would\n // outrank that `aria-label`. Left out when there is no trigger to point at (a `ContextMenu`'s\n // region with no id of its own has one; a list rendered with no `Menu` around it has none).\n const ariaLabel = (rest as { 'aria-label'?: string })['aria-label']\n const labelledBy = ariaLabel ? undefined : triggerId || undefined\n\n const content = (\n <Component\n role=\"menu\"\n id={menuId}\n aria-labelledby={labelledBy}\n className={classNames('menu', { show: shown }, className)}\n style={menuStyle}\n data-cx-placement={placementAttr}\n // Marks the events that reach the list through React's tree, for the `Menu` or the\n // `ContextMenu` to tell an overlay opened from an item from the page outside.\n {...(mergeProps(rest, insideEventProps(overlayRef)) as Record<string, unknown>)}\n onKeyDown={handleKeyDown}\n ref={forkedRef}\n >\n <SubmenuGroupContext.Provider value={submenuGroup}>\n {items ? items.map(renderMenuItemDef) : children}\n </SubmenuGroupContext.Provider>\n </Component>\n )\n\n if (container) {\n return <Portal container={container === true ? undefined : container}>{content}</Portal>\n }\n\n return content\n}\n\nexport const MenuList = createPolymorphicComponent<MenuListComponent>(\n MenuListRender as ForwardRefRenderFunction<Element, MenuListProps<ElementType>>,\n 'MenuList'\n)\n","import React, {\n ElementType,\n ForwardRefRenderFunction,\n ReactElement,\n useContext,\n useRef\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps, useButton } from 'react-aria'\n\nimport { Button, ButtonProps } from '../button/Button'\nimport { MenuContext, menuToggleClicks, openMenuDismissals } from './Menu'\nimport { ContextColor, Shapes } from '../../types'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\nimport { useForkedRef } from '../../hooks'\nimport { hasHref, hrefProps, resolveLinkKind } from '../../utils/elementKind'\n\ntype MenuToggleOwnProps<C extends ElementType> = {\n /**\n * Toggle the active state for the component.\n */\n active?: boolean\n /**\n * Draws the caret after the toggle's content. Set it to `false` for a toggle that shows what it\n * is another way, such as an icon-only \"more\" button.\n *\n * @default true\n */\n caret?: boolean\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Sets the color of the component to one of Chassis context colors. Only applies to the\n * default `Button` root.\n */\n color?: ContextColor\n /**\n * Component used for the root node — the trigger element the menu opens from. Defaults to\n * `Button`; swap for e.g. `NavLink` to render a nav-item-style trigger (`.nav-link.caret`)\n * instead of a `.button.caret`. Its own props are type-checked at the call site once passed\n * here.\n */\n component?: C\n /**\n * Toggle the disabled state for the component.\n */\n disabled?: boolean\n /**\n * The href attribute specifies the URL of the page the link goes to.\n */\n href?: string\n /**\n * Select the shape of the component. Only applies to the default `Button` root.\n */\n shape?: Shapes\n /**\n * Size the component sm or lg. Only applies to the default `Button` root.\n */\n size?: 'sm' | 'lg'\n /**\n * Sets the style variant of the component, as `Button`'s own `variant` does. Only applies to\n * the default `Button` root.\n */\n variant?: ButtonProps['variant']\n}\n\nexport type MenuToggleProps<C extends ElementType = typeof Button> = PolymorphicComponentProps<\n C,\n MenuToggleOwnProps<C>\n>\n\ntype MenuToggleComponent = (<C extends ElementType = typeof Button>(\n props: MenuToggleProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuToggleRender<C extends ElementType = typeof Button>(\n {\n children,\n caret = true,\n className,\n component,\n href,\n onClick,\n onKeyDown,\n tabIndex,\n ...rest\n }: MenuToggleProps<C>,\n ref: PolymorphicRef<C>\n) {\n const { hide, menuTriggerProps, reference, targetRef, toggleNodeRef, visible } =\n useContext(MenuContext)\n const Component = component ?? Button\n const buttonRef = useRef<HTMLButtonElement | null>(null)\n // What the root renders. The default `Button` renders a `<button>`, or an `<a>` given `href`.\n // Anything else is asked, like every polymorphic component asks: `NavLink` is a component\n // reference, and `component=\"button\"` a real `<button>`.\n const kind =\n Component === Button\n ? hasHref(href)\n ? 'anchor'\n : 'button'\n : resolveLinkKind(Component, href, rest)\n const rendersButton = kind === 'button'\n // `Button` applies the `href` rule itself; anything else gets `href` only if it can take one.\n const linkProps = Component === Button ? { href } : hrefProps(kind, href, 'MenuToggle')\n // `elementType` tells react-aria whether the rendered root already has native button\n // semantics or needs them emulated (`role=\"button\"`, keyboard activation).\n const { buttonProps } = useButton(\n { ...menuTriggerProps, elementType: rendersButton ? 'button' : 'a' },\n buttonRef\n )\n const wasOpenRef = useRef(false)\n\n const setRefs = (node: HTMLButtonElement | null) => {\n buttonRef.current = node\n toggleNodeRef.current = node\n if (reference !== 'parent') {\n targetRef.current = node\n }\n }\n\n const forkedRef = useForkedRef(ref, setRefs)\n\n // react-aria's `useMenuTrigger` opens (rather than toggles) on mouse/pen press start, so\n // re-clicking an already-open trigger would otherwise re-open it right back instead of\n // closing it. Capture whether it was open before that happens — ours has to run ahead of\n // `buttonProps`' own `onPointerDown` in the `mergeProps` chain below — then close it back\n // down on click. Touch is exempt: react-aria's `onPress` already toggles it correctly there.\n const handlePointerDown = (event: React.PointerEvent<HTMLButtonElement>) => {\n wasOpenRef.current = event.pointerType !== 'touch' && visible\n }\n\n // Another open menu closes on the click (`openMenuDismissals`), unless this toggle is in its\n // list (`menuToggleClicks`).\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault()\n menuToggleClicks.add(event.nativeEvent)\n for (const dismiss of [...openMenuDismissals]) dismiss(event.nativeEvent)\n if (wasOpenRef.current) {\n wasOpenRef.current = false\n hide()\n }\n onClick?.(event)\n }\n\n return (\n <Component\n // A `<button>` root needs an explicit `type` to avoid an implicit form submit; other roots\n // (e.g. `NavLink`) don't render a `<button>` at all.\n {...(rendersButton ? { type: 'button' } : {})}\n // The `.caret` utility (rather than styling off `[data-cx-toggle=\"menu\"]`, as the vanilla\n // CSS docs show) keeps this element from also matching Chassis CSS's own vanilla menu.js\n // selectors on a page that happens to load both — this component reimplements all of that\n // behavior itself, so there's nothing for the vanilla plugin to usefully do with it anyway.\n // `show` mirrors `MenuList`'s own `{ show: visible }` and vanilla menu.js's\n // `this._element.classList.add('show')` — it's what puts the trigger itself into a\n // pressed look while its menu is open (`.button.show`/`.nav-item.show .nav-link`).\n className={classNames({ caret, show: visible }, className)}\n {...(mergeProps({ onPointerDown: handlePointerDown }, rest, buttonProps, {\n onClick: handleClick,\n onKeyDown,\n // The caller's, when it gives one: react-aria's own `tabIndex` would replace it.\n ...(tabIndex !== undefined && { tabIndex })\n }) as Record<string, unknown>)}\n // After `buttonProps`: for an `<a>`, react-aria returns an `href` of its own, the one it was\n // given, which is none.\n {...linkProps}\n ref={forkedRef}\n >\n {children}\n </Component>\n )\n}\n\nexport const MenuToggle = createPolymorphicComponent<MenuToggleComponent>(\n MenuToggleRender as ForwardRefRenderFunction<Element, MenuToggleProps<ElementType>>,\n 'MenuToggle'\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"MenuToggle-W-ZSHFwF.js","names":["hasHref","hrefProps","linkElement","resolveLinkKind","useForkedRef","createPolymorphicComponent","useHydrated","renderMenuItemContent","Portal","Link","Button","insideEventProps","openMenuDismissals","MenuContext","menuToggleClicks","React","classNames","MenuDivider","forwardRef","rest","_className","className","MenuHeaderRender","Component","component","children","MenuHeader","MenuItemRender","href","event","onClick","MenuItem","VISIBLE_ITEMS_SELECTOR","isVisible","element","getMenuItems","menu","items","child","trigger","grandchild","focusMenuItem","target","handleMenuKeyDown","currentIndex","onEscape","onArrowLeft","onArrowRight","SubmenuGroupContext","createContext","useSubmenuGroupProvider","ref","useRef","closers","id","close","key","SubmenuActionsContext","SubmenuVisibleContext","renderMenuItemDef","def","MenuListRender","useContext","forkedRef","overlayRef","submenuGroup","hydrated","shown","visible","useEffect","focusStrategy","handleKeyDown","onKeyDown","labelledBy","triggerId","content","menuId","menuStyle","placementAttr","mergeProps","container","MenuList","MenuToggleRender","buttonRef","kind","rendersButton","linkProps","useButton","menuTriggerProps","wasOpenRef","node","reference","handlePointerDown","handleClick","dismiss","hide","buttonProps","tabIndex","MenuToggle"],"sources":["../../src/components/menu/MenuDivider.tsx","../../src/components/menu/MenuHeader.tsx","../../src/components/menu/MenuItem.tsx","../../src/components/menu/menuNavigation.ts","../../src/components/menu/submenuGroup.ts","../../src/components/menu/MenuList.tsx","../../src/components/menu/MenuToggle.tsx"],"sourcesContent":["import React, { forwardRef, HTMLAttributes } from 'react'\nimport classNames from 'classnames'\n\nexport interface MenuDividerProps extends HTMLAttributes<HTMLHRElement> {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLHRElement, MenuDividerProps>(\n ({ className, ...rest }, ref) => {\n const _className = classNames('menu-divider', className)\n\n return <hr className={_className} {...rest} ref={ref} />\n }\n)\n\nMenuDivider.displayName = 'MenuDivider'\n","import React, { ElementType, ForwardRefRenderFunction, ReactElement } from 'react'\nimport classNames from 'classnames'\n\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\n\ntype MenuHeaderOwnProps<C extends ElementType> = {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n /**\n * Component used for the root node. Either a string to use a HTML element or a component.\n */\n component?: C\n /**\n * ARIA role applied to the root node. Defaults to `'presentation'` — see the render function\n * for why.\n */\n role?: React.AriaRole\n}\n\nexport type MenuHeaderProps<C extends ElementType = 'h4'> = PolymorphicComponentProps<\n C,\n MenuHeaderOwnProps<C>\n>\n\ntype MenuHeaderComponent = (<C extends ElementType = 'h4'>(\n props: MenuHeaderProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuHeaderRender<C extends ElementType = 'h4'>(\n { children, className, component, role = 'presentation', ...rest }: MenuHeaderProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'h4'\n const _className = classNames('menu-header', className)\n\n // Always rendered as a direct child of `role=\"menu\"` (see MenuList) — ARIA's menu role only\n // permits menuitem/group/separator children, so a bare heading fails aria-required-children.\n // `role=\"presentation\"` opts the element itself out without hiding its text content.\n return (\n <Component className={_className} role={role} {...rest} ref={ref}>\n {children}\n </Component>\n )\n}\n\nexport const MenuHeader = createPolymorphicComponent<MenuHeaderComponent>(\n MenuHeaderRender as ForwardRefRenderFunction<Element, MenuHeaderProps<ElementType>>,\n 'MenuHeader'\n)\n","import React, {\n ElementType,\n ForwardRefRenderFunction,\n MouseEvent,\n ReactElement,\n ReactNode\n} from 'react'\nimport classNames from 'classnames'\n\nimport { linkElement } from '../../utils/elementKind'\nimport {\n createPolymorphicComponent,\n PolymorphicRef,\n PolymorphicRefWithFallback\n} from '../../utils/polymorphic'\nimport { renderMenuItemContent } from './renderMenuItemContent'\nimport { LinkProps, Link } from '../link/Link'\n\ntype MenuItemOwnProps = {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n /**\n * Secondary line of text rendered below `children` (`.menu-item-description`).\n */\n description?: ReactNode\n /**\n * Icon rendered at the item's leading edge (`.menu-item-icon`).\n */\n icon?: ReactNode\n /**\n * Marks the item as the current selection in a choice list. Renders in a heavier font weight.\n * Combine with a manually-composed `.menu-item-check` icon (in `children`, or via `icon` on a\n * plain, non-selection item) to also show a checkmark — this prop alone doesn't add one, so\n * existing font-weight-only usage keeps rendering unchanged.\n */\n selected?: boolean\n}\n\nexport type MenuItemProps<C extends ElementType = 'a'> = LinkProps<C> & MenuItemOwnProps\n\ntype MenuItemComponent = (<C extends ElementType = 'a'>(\n props: MenuItemProps<C> & {\n ref?: PolymorphicRefWithFallback<C, HTMLAnchorElement | HTMLButtonElement>\n }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuItemRender<C extends ElementType = 'a'>(\n {\n children,\n className,\n component,\n description,\n href,\n icon,\n onClick,\n selected,\n ...rest\n }: MenuItemProps<C>,\n ref: PolymorphicRef<C>\n) {\n const _className = classNames('menu-item', { selected }, className)\n\n // `href=\"#\"` is a common placeholder for menu items that act via `onClick` rather than\n // real navigation. Left alone, a plain anchor click still navigates to the empty fragment,\n // which scrolls the page to the top — so we suppress that default for the placeholder case\n // only, leaving real same-page anchors (`href=\"#some-id\"`) free to navigate as expected.\n const handleClick = (event: MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => {\n if (href === '#') event.preventDefault()\n onClick?.(event)\n }\n\n // An item with `href` is an `<a>`, one without is a `<button type=\"button\">`, unless `component`\n // or `asChild` chose the element (see `linkElement`). chassis-css styles both as `.menu-item`.\n // An item without `href` used to be an `<a>` with no `href`, which isn't focusable, so keyboard\n // users couldn't reach it outside the menu's own arrow-key handling.\n return (\n <Link\n role=\"menuitem\"\n component={linkElement(component as ElementType | undefined, href, 'button')}\n href={href}\n onClick={handleClick}\n {...(rest as Record<string, unknown>)}\n className={_className}\n ref={ref as PolymorphicRef<ElementType>}\n >\n {renderMenuItemContent({ icon, label: children, description })}\n </Link>\n )\n}\n\nexport const MenuItem = createPolymorphicComponent<MenuItemComponent>(\n MenuItemRender as ForwardRefRenderFunction<Element, MenuItemProps<ElementType>>,\n 'MenuItem'\n)\n","import React from 'react'\n\n// Mirrors Chassis CSS's menu.js SELECTOR_VISIBLE_ITEMS / SELECTOR_KB_NAV_ITEMS: direct-child\n// menu items and submenu-back buttons, plus submenu trigger items nested one level inside a\n// `.submenu` wrapper (which aren't direct children of the `.menu`).\n//\n// Walks `children` directly rather than a `:scope`-based `querySelectorAll` — jsdom's selector\n// engine (nwsapi) mis-parses `:scope` queries against an element whose `id` contains a colon,\n// which is exactly the shape of React 18's default `useId()` output now that `MenuList`/\n// `MenuSubmenu` set a real `id` for `aria-controls`/`aria-labelledby` linking. Real browsers don't\n// have this bug, but walking children is just as correct and sidesteps it either way.\nconst VISIBLE_ITEMS_SELECTOR = ':is(.menu-item, .submenu-back):not(.disabled):not(:disabled)'\n\nconst isVisible = (element: HTMLElement) =>\n Boolean(element.offsetWidth || element.offsetHeight || element.getClientRects().length)\n\nexport const getMenuItems = (menu: HTMLElement | null): HTMLElement[] => {\n if (!menu) return []\n const items: HTMLElement[] = []\n for (const child of Array.from(menu.children)) {\n if (child.matches(VISIBLE_ITEMS_SELECTOR)) {\n items.push(child as HTMLElement)\n } else if (child.classList.contains('submenu')) {\n const trigger = Array.from(child.children).find((grandchild) =>\n grandchild.matches(VISIBLE_ITEMS_SELECTOR)\n )\n if (trigger) items.push(trigger as HTMLElement)\n }\n }\n return items.filter(isVisible)\n}\n\nexport const focusMenuItem = (items: HTMLElement[], target: 'first' | 'last') => {\n if (!items.length) return\n ;(target === 'first' ? items[0]! : items[items.length - 1]!).focus()\n}\n\nexport interface MenuKeyDownOptions {\n onArrowLeft?: () => void\n onArrowRight?: () => void\n onEscape?: () => void\n}\n\n// Scoped to `event.currentTarget` (the `.menu` element the handler is bound to), so the same\n// function drives keyboard navigation for both the top-level menu and any nested submenu list.\n// `onArrowLeft`/`onArrowRight` are both optional and independent (rather than a single\n// direction-agnostic \"close\" callback) so a caller under an RTL locale can wire the one that\n// actually points back toward the trigger — see `MenuSubmenu`, the only current consumer of\n// either.\nexport const handleMenuKeyDown = (\n event: React.KeyboardEvent<HTMLElement>,\n { onArrowLeft, onArrowRight, onEscape }: MenuKeyDownOptions\n): void => {\n const menu = event.currentTarget\n const target = event.target as HTMLElement\n\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp': {\n event.preventDefault()\n event.stopPropagation()\n const items = getMenuItems(menu)\n if (!items.length) return\n const currentIndex = items.indexOf(target)\n const nextIndex =\n currentIndex === -1\n ? event.key === 'ArrowDown'\n ? 0\n : items.length - 1\n : (currentIndex + (event.key === 'ArrowDown' ? 1 : -1) + items.length) % items.length\n // `nextIndex` is always a valid index into `items` here (0, items.length - 1, or a modulo\n // result — the `if (!items.length) return` above already ruled out the empty-array case).\n items[nextIndex]!.focus()\n return\n }\n case 'Home':\n case 'End': {\n event.preventDefault()\n event.stopPropagation()\n focusMenuItem(getMenuItems(menu), event.key === 'Home' ? 'first' : 'last')\n return\n }\n case 'Escape': {\n if (!onEscape) return\n event.preventDefault()\n event.stopPropagation()\n onEscape()\n return\n }\n case 'ArrowLeft': {\n if (!onArrowLeft) return\n event.preventDefault()\n event.stopPropagation()\n onArrowLeft()\n return\n }\n case 'ArrowRight': {\n if (!onArrowRight) return\n event.preventDefault()\n event.stopPropagation()\n onArrowRight()\n return\n }\n default:\n }\n}\n","import { createContext, useRef } from 'react'\n\n// Lets sibling `.submenu` flyouts at the same menu level close one another when a new one\n// opens, mirroring menu.js's `_closeSiblingSubmenus`. One provider instance is created per\n// menu level (the top-level `.menu` and each `.submenu`'s own nested list) and lives for the\n// lifetime of that level, so registration doesn't churn on every render.\nexport interface SubmenuGroupContextValue {\n register: (id: string, close: () => void) => () => void\n notifyOpen: (id: string) => void\n}\n\nexport const SubmenuGroupContext = createContext<SubmenuGroupContextValue | null>(null)\n\nexport const useSubmenuGroupProvider = (): SubmenuGroupContextValue => {\n const ref = useRef<SubmenuGroupContextValue | null>(null)\n\n if (!ref.current) {\n const closers = new Map<string, () => void>()\n ref.current = {\n register: (id, close) => {\n closers.set(id, close)\n return () => {\n closers.delete(id)\n }\n },\n notifyOpen: (id) => {\n closers.forEach((close, key) => {\n if (key !== id) close()\n })\n }\n }\n }\n\n return ref.current\n}\n\n// Exposes the current `.submenu`'s own close-and-refocus action to a nested `MenuSubmenuBack`\n// button, without threading it through the sibling-group registry above.\nexport interface SubmenuActionsContextValue {\n close: () => void\n}\n\nexport const SubmenuActionsContext = createContext<SubmenuActionsContextValue | null>(null)\n\n// Whether the `.submenu` a nested `MenuSubmenu` is in is open. A submenu's panel is portaled out\n// of its parent's, so nothing hides it when the parent closes: it follows this, as the first\n// level follows the `Menu` itself. `true` at the top level, where there is no parent submenu.\nexport const SubmenuVisibleContext = createContext(true)\n","import React, {\n ElementType,\n ForwardRefRenderFunction,\n ReactElement,\n ReactNode,\n useContext,\n useEffect\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps } from 'react-aria'\n\nimport { useForkedRef } from '../../hooks'\nimport { insideEventProps } from '../../utils/insideEvents'\nimport { renderMenuItemContent } from './renderMenuItemContent'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\nimport { useHydrated } from '../../hooks/useHydrated'\nimport { Portal } from '../portal/Portal'\nimport { MenuContext } from './Menu'\nimport { MenuDivider } from './MenuDivider'\nimport { MenuHeader } from './MenuHeader'\nimport { MenuItem } from './MenuItem'\nimport { MenuItemsDef } from './MenuItemDef'\nimport { focusMenuItem, getMenuItems, handleMenuKeyDown } from './menuNavigation'\nimport { SubmenuGroupContext, useSubmenuGroupProvider } from './submenuGroup'\n\ntype MenuListOwnProps<C extends ElementType> = {\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Component used for the root node. Either a string to use a HTML element or a component.\n */\n component?: C\n /**\n * Array of item/header/divider definitions for data-driven rendering. When provided, children\n * are ignored. Covers flat items, headers, and dividers only — for nested submenus, compose\n * with `children` and `MenuSubmenu` instead.\n */\n items?: MenuItemsDef\n}\n\nexport type MenuListProps<C extends ElementType = 'div'> = PolymorphicComponentProps<\n C,\n MenuListOwnProps<C>\n>\n\ntype MenuListComponent = (<C extends ElementType = 'div'>(\n props: MenuListProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nconst renderMenuItemDef = (def: MenuItemsDef[number]): ReactNode => {\n if (def.type === 'header') {\n return <MenuHeader key={def.id}>{def.label}</MenuHeader>\n }\n if (def.type === 'divider') {\n return <MenuDivider key={def.id} />\n }\n return (\n <MenuItem\n key={def.id}\n href={def.href}\n disabled={def.disabled}\n selected={def.selected}\n onClick={def.onClick}\n >\n {renderMenuItemContent({\n icon: def.icon,\n label: def.label,\n description: def.description,\n selected: def.selected\n })}\n </MenuItem>\n )\n}\n\nfunction MenuListRender<C extends ElementType = 'div'>(\n { children, className, component, items, onKeyDown, ...rest }: MenuListProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'div'\n const {\n close,\n container,\n focusStrategy,\n menuId,\n menuStyle,\n overlayRef,\n placementAttr,\n triggerId,\n visible\n } = useContext(MenuContext)\n const forkedRef = useForkedRef(ref, overlayRef)\n const submenuGroup = useSubmenuGroupProvider()\n // The list is positioned in a layout effect, which the server never runs: a menu open on its\n // first render was painted at the top left of the page until the JavaScript had loaded. It is\n // shown once hydration has finished, where that effect has placed it.\n const hydrated = useHydrated()\n const shown = visible && hydrated\n\n // ArrowDown/ArrowUp on the trigger opens the menu with a focus strategy (see `Menu`'s\n // `useMenuTrigger` wiring) — this is where that intent actually lands, since we're not\n // adopting `useMenu`'s own collection-aware auto-focus.\n useEffect(() => {\n if (!visible || !focusStrategy) return\n focusMenuItem(getMenuItems(overlayRef.current), focusStrategy === 'last' ? 'last' : 'first')\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, focusStrategy])\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n handleMenuKeyDown(event, { onEscape: close })\n onKeyDown?.(event as React.KeyboardEvent<HTMLDivElement>)\n }\n\n // Labelled by the trigger, unless the caller names the list itself: `aria-labelledby` would\n // outrank that `aria-label`. Left out when there is no trigger to point at (a `ContextMenu`'s\n // region with no id of its own has one; a list rendered with no `Menu` around it has none).\n const ariaLabel = (rest as { 'aria-label'?: string })['aria-label']\n const labelledBy = ariaLabel ? undefined : triggerId || undefined\n\n const content = (\n <Component\n role=\"menu\"\n id={menuId}\n aria-labelledby={labelledBy}\n className={classNames('menu', { show: shown }, className)}\n style={menuStyle}\n data-cx-placement={placementAttr}\n // Marks the events that reach the list through React's tree, for the `Menu` or the\n // `ContextMenu` to tell an overlay opened from an item from the page outside.\n {...(mergeProps(rest, insideEventProps(overlayRef)) as Record<string, unknown>)}\n onKeyDown={handleKeyDown}\n ref={forkedRef}\n >\n <SubmenuGroupContext.Provider value={submenuGroup}>\n {items ? items.map(renderMenuItemDef) : children}\n </SubmenuGroupContext.Provider>\n </Component>\n )\n\n if (container) {\n return <Portal container={container === true ? undefined : container}>{content}</Portal>\n }\n\n return content\n}\n\nexport const MenuList = createPolymorphicComponent<MenuListComponent>(\n MenuListRender as ForwardRefRenderFunction<Element, MenuListProps<ElementType>>,\n 'MenuList'\n)\n","import React, {\n ElementType,\n ForwardRefRenderFunction,\n ReactElement,\n useContext,\n useRef\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps, useButton } from 'react-aria'\n\nimport { Button, ButtonProps } from '../button/Button'\nimport { MenuContext, menuToggleClicks, openMenuDismissals } from './Menu'\nimport { ContextColor, Shapes } from '../../types'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\nimport { useForkedRef } from '../../hooks'\nimport { hasHref, hrefProps, resolveLinkKind } from '../../utils/elementKind'\n\ntype MenuToggleOwnProps<C extends ElementType> = {\n /**\n * Toggle the active state for the component.\n */\n active?: boolean\n /**\n * Draws the caret after the toggle's content. Set it to `false` for a toggle that shows what it\n * is another way, such as an icon-only \"more\" button.\n *\n * @default true\n */\n caret?: boolean\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Sets the color of the component to one of Chassis context colors. Only applies to the\n * default `Button` root.\n */\n color?: ContextColor\n /**\n * Component used for the root node — the trigger element the menu opens from. Defaults to\n * `Button`; swap for e.g. `NavLink` to render a nav-item-style trigger (`.nav-link.caret`)\n * instead of a `.button.caret`. Its own props are type-checked at the call site once passed\n * here.\n */\n component?: C\n /**\n * Toggle the disabled state for the component.\n */\n disabled?: boolean\n /**\n * The href attribute specifies the URL of the page the link goes to.\n */\n href?: string\n /**\n * Select the shape of the component. Only applies to the default `Button` root.\n */\n shape?: Shapes\n /**\n * Size the component sm or lg. Only applies to the default `Button` root.\n */\n size?: 'sm' | 'lg'\n /**\n * Sets the style variant of the component, as `Button`'s own `variant` does. Only applies to\n * the default `Button` root.\n */\n variant?: ButtonProps['variant']\n}\n\nexport type MenuToggleProps<C extends ElementType = typeof Button> = PolymorphicComponentProps<\n C,\n MenuToggleOwnProps<C>\n>\n\ntype MenuToggleComponent = (<C extends ElementType = typeof Button>(\n props: MenuToggleProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuToggleRender<C extends ElementType = typeof Button>(\n {\n children,\n caret = true,\n className,\n component,\n href,\n onClick,\n onKeyDown,\n tabIndex,\n ...rest\n }: MenuToggleProps<C>,\n ref: PolymorphicRef<C>\n) {\n const { hide, menuTriggerProps, reference, targetRef, toggleNodeRef, visible } =\n useContext(MenuContext)\n const Component = component ?? Button\n const buttonRef = useRef<HTMLButtonElement | null>(null)\n // What the root renders. The default `Button` renders a `<button>`, or an `<a>` given `href`.\n // Anything else is asked, like every polymorphic component asks: `NavLink` is a component\n // reference, and `component=\"button\"` a real `<button>`.\n const kind =\n Component === Button\n ? hasHref(href)\n ? 'anchor'\n : 'button'\n : resolveLinkKind(Component, href, rest)\n const rendersButton = kind === 'button'\n // `Button` applies the `href` rule itself; anything else gets `href` only if it can take one.\n const linkProps = Component === Button ? { href } : hrefProps(kind, href, 'MenuToggle')\n // `elementType` tells react-aria whether the rendered root already has native button\n // semantics or needs them emulated (`role=\"button\"`, keyboard activation).\n const { buttonProps } = useButton(\n { ...menuTriggerProps, elementType: rendersButton ? 'button' : 'a' },\n buttonRef\n )\n const wasOpenRef = useRef(false)\n\n const setRefs = (node: HTMLButtonElement | null) => {\n buttonRef.current = node\n toggleNodeRef.current = node\n if (reference !== 'parent') {\n targetRef.current = node\n }\n }\n\n const forkedRef = useForkedRef(ref, setRefs)\n\n // react-aria's `useMenuTrigger` opens (rather than toggles) on mouse/pen press start, so\n // re-clicking an already-open trigger would otherwise re-open it right back instead of\n // closing it. Capture whether it was open before that happens — ours has to run ahead of\n // `buttonProps`' own `onPointerDown` in the `mergeProps` chain below — then close it back\n // down on click. Touch is exempt: react-aria's `onPress` already toggles it correctly there.\n const handlePointerDown = (event: React.PointerEvent<HTMLButtonElement>) => {\n wasOpenRef.current = event.pointerType !== 'touch' && visible\n }\n\n // Another open menu closes on the click (`openMenuDismissals`), unless this toggle is in its\n // list (`menuToggleClicks`).\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault()\n menuToggleClicks.add(event.nativeEvent)\n for (const dismiss of [...openMenuDismissals]) dismiss(event.nativeEvent)\n if (wasOpenRef.current) {\n wasOpenRef.current = false\n hide()\n }\n onClick?.(event)\n }\n\n return (\n <Component\n // A `<button>` root needs an explicit `type` to avoid an implicit form submit; other roots\n // (e.g. `NavLink`) don't render a `<button>` at all.\n {...(rendersButton ? { type: 'button' } : {})}\n // The `.caret` utility (rather than styling off `[data-cx-toggle=\"menu\"]`, as the vanilla\n // CSS docs show) keeps this element from also matching Chassis CSS's own vanilla menu.js\n // selectors on a page that happens to load both — this component reimplements all of that\n // behavior itself, so there's nothing for the vanilla plugin to usefully do with it anyway.\n // `show` mirrors `MenuList`'s own `{ show: visible }` and vanilla menu.js's\n // `this._element.classList.add('show')` — it's what puts the trigger itself into a\n // pressed look while its menu is open (`.button.show`/`.nav-item.show .nav-link`).\n className={classNames({ caret, show: visible }, className)}\n {...(mergeProps({ onPointerDown: handlePointerDown }, rest, buttonProps, {\n onClick: handleClick,\n onKeyDown,\n // The caller's, when it gives one: react-aria's own `tabIndex` would replace it.\n ...(tabIndex !== undefined && { tabIndex })\n }) as Record<string, unknown>)}\n // After `buttonProps`: for an `<a>`, react-aria returns an `href` of its own, the one it was\n // given, which is none.\n {...linkProps}\n ref={forkedRef}\n >\n {children}\n </Component>\n )\n}\n\nexport const MenuToggle = createPolymorphicComponent<MenuToggleComponent>(\n MenuToggleRender as ForwardRefRenderFunction<Element, MenuToggleProps<ElementType>>,\n 'MenuToggle'\n)\n"],"mappings":"A,ipBAUA,MAAaiB,EAAcC,GACxB,CAAE,YAAW,GAAGC,GAAQ,IAAQ,CAC/B,IAAMC,EAAaJ,EAAW,eAAgBK,CAAS,EAEvD,MAAO,kBAAA,cAAC,KAAD,CAAI,UAAWD,EAAY,GAAID,EAAW,KAAM,CAAA,CACzD,CACF,EAEA,EAAY,YAAc,cCgB1B,SAASG,EACP,CAAE,WAAU,YAAW,YAAW,OAAO,eAAgB,GAAGH,GAC5D,EACA,CACA,IAAMI,EAAYC,GAAa,KACzBJ,EAAaJ,EAAW,cAAeK,CAAS,EAKtD,MACE,kBAAA,cAACE,EAAD,CAAW,UAAWH,EAAkB,OAAM,GAAID,EAAW,KAElD,EADRM,CACQ,CAEf,CAEA,MAAaC,EAAarB,EACxBiB,EACA,YACF,ECNA,SAASK,EACP,CACE,WACA,YACA,YACA,cACA,OACA,OACA,UACA,WACA,GAAGR,GAEL,EACA,CACA,IAAMC,EAAaJ,EAAW,YAAa,CAAE,UAAS,EAAGK,CAAS,EAelE,MACE,kBAAA,cAACZ,EAAD,CACE,KAAK,WACL,UAAWP,EAAYsB,EAAsCI,EAAM,QAAQ,EACrE,OACN,QAdiB,GAA6D,CAC5EA,IAAS,KAAKC,EAAM,eAAe,EACvCC,IAAUD,CAAK,CACjB,EAYI,GAAKV,EACL,UAAWC,EACN,KAGD,EADHb,EAAsB,CAAE,OAAM,MAAOkB,EAAU,aAAY,CAAC,CACzD,CAEV,CAEA,MAAaM,EAAW1B,EACtBsB,EACA,UACF,ECpFMK,EAAyB,+DAEzBC,EAAa,GACjB,GAAQC,EAAQ,aAAeA,EAAQ,cAAgBA,EAAQ,eAAe,CAAC,CAAC,QAErEC,EAAgB,GAA4C,CACvE,GAAI,CAACC,EAAM,MAAO,CAAC,EACnB,IAAMC,EAAuB,CAAC,EAC9B,IAAK,IAAMC,KAAS,MAAM,KAAKF,EAAK,QAAQ,EAC1C,GAAIE,EAAM,QAAQN,CAAsB,EACtCK,EAAM,KAAKC,CAAoB,OAC1B,GAAIA,EAAM,UAAU,SAAS,SAAS,EAAG,CAC9C,IAAMC,EAAU,MAAM,KAAKD,EAAM,QAAQ,CAAC,CAAC,KAAM,GAC/CE,EAAW,QAAQR,CAAsB,CAC3C,EACIO,GAASF,EAAM,KAAKE,CAAsB,CAChD,CAEF,OAAOF,EAAM,OAAOJ,CAAS,CAC/B,EAEaQ,GAAiB,EAAsB,IAA6B,CAC1EJ,EAAM,SACTK,IAAW,QAAUL,EAAM,GAAMA,EAAMA,EAAM,OAAS,GAAA,CAAK,MAAM,CACrE,EAcaM,GACX,EACA,CAAE,cAAa,eAAc,cACpB,CACT,IAAMP,EAAOP,EAAM,cACba,EAASb,EAAM,OAErB,OAAQA,EAAM,IAAd,CACE,IAAK,YACL,IAAK,UAAW,CACdA,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EACtB,IAAMQ,EAAQF,EAAaC,CAAI,EAC/B,GAAI,CAACC,EAAM,OAAQ,OACnB,IAAMO,EAAeP,EAAM,QAAQK,CAAM,EASzCL,EAPEO,IAAiB,GACbf,EAAM,MAAQ,YACZ,EACAQ,EAAM,OAAS,GAChBO,GAAgBf,EAAM,MAAQ,YAAc,EAAI,IAAMQ,EAAM,QAAUA,EAAM,OAGnE,CAAE,MAAM,EACxB,MACF,CACA,IAAK,OACL,IAAK,MACHR,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EACtBY,EAAcN,EAAaC,CAAI,EAAGP,EAAM,MAAQ,OAAS,QAAU,MAAM,EACzE,OAEF,IAAK,SACH,GAAI,CAACgB,EAAU,OACfhB,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EACtBgB,EAAS,EACT,OAEF,IAAK,YACH,GAAI,CAACC,EAAa,OAClBjB,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EACtBiB,EAAY,EACZ,OAEF,IAAK,aACH,GAAI,CAACC,EAAc,OACnBlB,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EACtBkB,EAAa,EACb,MAGJ,CACF,EC9FaC,EAAsBC,EAA+C,IAAI,EAEzEC,MAA0D,CACrE,IAAMC,EAAMC,EAAwC,IAAI,EAExD,GAAI,CAACD,EAAI,QAAS,CAChB,IAAME,kBAAU,IAAI,IACpB,EAAI,QAAU,CACZ,UAAW,EAAI,KACbA,EAAQ,IAAIC,EAAIC,CAAK,MACR,CACXF,EAAQ,OAAOC,CAAE,CACnB,GAEF,WAAa,GAAO,CAClBD,EAAQ,SAAS,EAAO,IAAQ,CAC1BG,IAAQF,GAAIC,EAAM,CACxB,CAAC,CACH,CACF,CACF,CAEA,OAAOJ,EAAI,OACb,EAQaM,EAAwBR,EAAiD,IAAI,EAK7ES,EAAwBT,EAAc,EAAI,ECQjDU,EAAqB,GACrBC,EAAI,OAAS,SACR,kBAAA,cAAClC,EAAD,CAAY,IAAKkC,EAAI,EAA2B,EAAtBA,EAAI,KAAkB,EAErDA,EAAI,OAAS,UACR,kBAAA,cAAC3C,EAAD,CAAa,IAAK2C,EAAI,EAAK,CAAA,EAGlC,kBAAA,cAAC7B,EAAD,CACE,IAAK6B,EAAI,GACT,KAAMA,EAAI,KACV,SAAUA,EAAI,SACd,SAAUA,EAAI,SACd,QAASA,EAAI,OAQL,EANPrD,EAAsB,CACrB,KAAMqD,EAAI,KACV,MAAOA,EAAI,MACX,YAAaA,EAAI,YACjB,SAAUA,EAAI,QAChB,CAAC,CACO,EAId,SAASC,EACP,CAAE,WAAU,YAAW,YAAW,QAAO,YAAW,GAAG1C,GACvD,EACA,CACA,IAAMI,EAAYC,GAAa,MACzB,CACJ,QACA,YACA,gBACA,SACA,YACA,aACA,gBACA,YACA,WACEsC,EAAWjD,CAAW,EACpBkD,EAAY3D,EAAa+C,EAAKa,CAAU,EACxCC,EAAef,EAAwB,EAIvCgB,EAAW5D,EAAY,EACvB6D,EAAQC,GAAWF,EAKzBG,MAAgB,CACTD,GAAYE,GACjB7B,EAAcN,EAAa6B,EAAW,OAAO,EAAGM,IAAkB,OAAS,OAAS,OAAO,CAE7F,EAAG,CAACF,EAASE,CAAa,CAAC,EAE3B,IAAMC,EAAiB,GAA4C,CACjE5B,EAAkBd,EAAO,CAAE,SAAU0B,CAAM,CAAC,EAC5CiB,IAAY3C,CAA4C,CAC1D,EAMM4C,EADatD,EAAmC,cACvB,IAAA,GAAYuD,GAAa,IAAA,GAElDC,EACJ,kBAAA,cAACpD,EAAD,CACE,KAAK,OACL,GAAIqD,EACJ,kBAAiBH,EACjB,UAAWzD,EAAW,OAAQ,CAAE,KAAMmD,CAAM,EAAG9C,CAAS,EACxD,MAAOwD,EACP,oBAAmBC,EAGnB,GAAKC,EAAW5D,EAAMR,EAAiBqD,CAAU,CAAC,EAClD,UAAWO,EACX,IAAKR,CAKI,EAHT,kBAAA,cAACf,EAAoB,SAArB,CAA8B,MAAOiB,CAEP,EAD3B5B,EAAQA,EAAM,IAAIsB,CAAiB,EAAIlC,CACZ,CACrB,EAOb,OAJIuD,EACK,kBAAA,cAACxE,EAAD,CAAQ,UAAWwE,IAAc,GAAO,IAAA,GAAYA,CAA4B,EAAhBL,CAAgB,EAGlFA,CACT,CAEA,MAAaM,EAAW5E,EACtBwD,EACA,UACF,ECzEA,SAASqB,EACP,CACE,WACA,QAAQ,GACR,YACA,YACA,OACA,UACA,YACA,WACA,GAAG/D,GAEL,EACA,CACA,GAAM,CAAE,OAAM,mBAAkB,YAAW,YAAW,gBAAe,WACnE2C,EAAWjD,CAAW,EAClBU,EAAYC,GAAad,EACzByE,EAAY/B,EAAiC,IAAI,EAIjDgC,EACJ7D,IAAcb,EACVV,EAAQ4B,CAAI,EACV,SACA,SACFzB,EAAgBoB,EAAWK,EAAMT,CAAI,EACrCkE,EAAgBD,IAAS,SAEzBE,EAAY/D,IAAcb,EAAS,CAAE,MAAK,EAAIT,EAAUmF,EAAMxD,EAAM,YAAY,EAGhF,CAAE,eAAgB2D,EACtB,CAAE,GAAGC,EAAkB,YAAaH,EAAgB,SAAW,GAAI,EACnEF,CACF,EACMM,EAAarC,EAAO,EAAK,EAUzBW,EAAY3D,EAAa+C,EARd,GAAmC,CAClD,EAAU,QAAUuC,EACpB,EAAc,QAAUA,EACpBC,IAAc,WAChB,EAAU,QAAUD,EAExB,CAE2C,EAOrCE,EAAqB,GAAiD,CAC1E,EAAW,QAAU/D,EAAM,cAAgB,SAAWuC,CACxD,EAIMyB,EAAe,GAA+C,CAClEhE,EAAM,eAAe,EACrBf,EAAiB,IAAIe,EAAM,WAAW,EACtC,IAAK,IAAMiE,IAAW,CAAC,GAAGlF,CAAkB,EAAGkF,EAAQjE,EAAM,WAAW,EACpE4D,EAAW,UACb,EAAW,QAAU,GACrBM,EAAK,GAEPjE,IAAUD,CAAK,CACjB,EAEA,MACE,kBAAA,cAACN,EAAD,CAGE,GAAK8D,EAAgB,CAAE,KAAM,QAAS,EAAI,CAAC,EAQ3C,UAAWrE,EAAW,CAAE,QAAO,KAAMoD,CAAQ,EAAG/C,CAAS,EACzD,GAAK0D,EAAW,CAAE,cAAea,CAAkB,EAAGzE,EAAM6E,EAAa,CACvE,QAASH,EACT,YAEA,GAAII,IAAa,IAAA,IAAa,CAAE,UAAS,CAC3C,CAAC,EAGD,GAAIX,EACJ,IAAKvB,CAGI,EADRtC,CACQ,CAEf,CAEA,MAAayE,EAAa7F,EACxB6E,EACA,YACF,E"}
@@ -1,2 +1,2 @@
1
- import"./focus-ring-Bs80iIBN.js";import{t as e}from"./useForkedRef-WoqMqsWE.js";import{t}from"./useControllableState-CPUJxfKW.js";import{r as n}from"./useFloatingOverlay-BuiI_CCn.js";import{t as r}from"./useFormField-DH2tlc3e.js";import{t as ee}from"./useOverlayMaxHeight-8mQL2Q6d.js";import{i as te,r as ne,t as re}from"./overlayPlacement-Q6bcbXA5.js";import{t as ie}from"./useRequiredValueInput-gYN8I-LY.js";import{a as ae,i as oe,n as se,r as ce,t as le}from"./ComboboxListBox-Db0rSM3w.js";import{t as ue}from"./Portal-BTDylxAi.js";import{t as de}from"./renderFormField-_6WswnEX.js";import i,{forwardRef as a,useEffect as o,useMemo as s,useRef as c,useState as fe}from"react";import l from"classnames";import{mergeProps as u,useButton as d,useComboBox as f,useFilter as p,useOverlayPosition as m}from"react-aria";import{useComboBoxState as pe}from"react-stately";const h=e=>null;h.displayName=`AutocompleteGroup`;const g=e=>null;g.displayName=`AutocompleteItem`;const _=e=>e==null?[]:Array.isArray(e)?e:[e],v=(e,t)=>{if(e!==void 0)return t?_(e):Array.isArray(e)?e[0]??null:e},me=(e,t)=>{let n=_(e),r=_(t);return n.length===r.length&&n.every((e,t)=>e===r[t])},y=a(function({children:a,className:y,defaultValue:he,disabled:b,help:x,id:ge,invalid:S,invalidFeedback:C,items:w,label:T,multiple:E=!1,name:D,noResultsText:_e=`No results found`,onChange:ve,placeholder:O,required:k,searchPlaceholder:A,size:j,valid:M,validFeedback:N,value:P,...F},ye){let I=s(()=>w?ce(w):se(a,{Group:h,Item:g}),[w,a]),be=s(()=>ae(I),[I]),{contains:xe}=p({sensitivity:`base`}),[L,Se]=t(v(P,E),v(he,E)??(E?[]:null),ve),[Ce,R]=fe(``),z=pe({children:oe,defaultItems:I,disabledKeys:be,defaultFilter:xe,selectionMode:E?`multiple`:`single`,value:L,onChange:e=>{let t=_(e),n=E?t:t[0]??null;R(``),me(n,L)||Se(n)},inputValue:Ce,onInputChange:R,onOpenChange:e=>{e||R(``)},allowsEmptyCollection:!0,menuTrigger:`manual`}),B=c(null),we=e(ye,B),V=c(null),H=c(null),U=c(null),W=c(null),G=_(z.value),{inputProps:K,missing:Te,valid:q}=ie(W,{focus:()=>B.current?.focus(),invalid:S,required:k&&(!E||G.length===0),valid:M}),J=S||Te,{describedBy:Ee,feedbackId:De,helpId:Oe,inputId:ke,labelId:Ae,labelledBy:Y}=r({ariaDescribedBy:F[`aria-describedby`],ariaLabelledBy:F[`aria-labelledby`],help:x,id:ge,invalid:J,invalidFeedback:C,label:T,valid:q,validFeedback:N}),{buttonProps:je,inputProps:Me,listBoxProps:Ne}=f({"aria-label":F[`aria-label`],"aria-labelledby":Y,buttonRef:B,id:ke,inputRef:V,listBoxRef:H,popoverRef:U,isDisabled:b,isRequired:k,placeholder:A},z),{buttonProps:X}=d({...je,elementType:`div`,isDisabled:b,excludeFromTabOrder:!1},B),Z=c(z.isOpen);o(()=>{if(z.isOpen&&!Z.current)V.current?.focus();else if(!z.isOpen&&Z.current){let e=document.activeElement;(!e||e===document.body||U.current?.contains(e))&&B.current?.focus()}Z.current=z.isOpen},[z.isOpen]),o(()=>{if(!z.isOpen)return;let e=B.current;for(;e&&e!==document.body;)e.removeAttribute(`aria-hidden`),e=e.parentElement},[z.isOpen]);let{overlayProps:Pe,placement:Fe}=m({targetRef:B,overlayRef:U,placement:te(`bottom-start`),offset:2,isOpen:z.isOpen,onClose:null});ee(U,z.isOpen);let Ie=n({close:z.close,isOpen:z.isOpen,triggerRef:B}),{menuStyle:Le,placementAttr:Re}=ne(Pe.style,`bottom-start`,Fe),Q={...re,...Le},ze=e=>z.selectionManager.toggleSelection(e),Be=u(Me,{onKeyDown:e=>{if(!E||e.key!==`Backspace`||e.currentTarget.value!==``)return;let t=z.selectedItems[z.selectedItems.length-1];t&&ze(t.key)}}),$=z.selectedItems.length>0,Ve=$?z.selectedItems.length===1?z.selectedItems[0]?.textValue??``:`${z.selectedItems.length} selected`:O;return de({children:/* @__PURE__ */ i.createElement(i.Fragment,null,/* @__PURE__ */ i.createElement(`div`,{className:l(`form-input`,`combobox`,{sm:j===`sm`,lg:j===`lg`,disabled:b},{"is-invalid":J,"is-valid":q},y),...u(F,X),tabIndex:X.tabIndex,"aria-label":F[`aria-label`],"aria-labelledby":Y,"aria-describedby":Ee,"aria-invalid":J||void 0,ref:we},/* @__PURE__ */ i.createElement(`span`,{className:l(`combobox-value`,{"combobox-placeholder":!$})},Ve)),/* @__PURE__ */ i.createElement(ue,{container:Ie},/* @__PURE__ */ i.createElement(`div`,{className:l(`menu`,{show:z.isOpen}),"data-cx-placement":Re,style:Q,hidden:!z.isOpen,ref:U},/* @__PURE__ */ i.createElement(`div`,{className:`combobox-search`},/* @__PURE__ */ i.createElement(`input`,{autoComplete:`off`,className:`form-input combobox-search-input sm`,...Be,ref:V})),/* @__PURE__ */ i.createElement(le,{state:z,listBoxProps:Ne,listBoxRef:H}),z.collection.size===0&&/* @__PURE__ */ i.createElement(`div`,{className:`combobox-no-results`},_e))),E?/* @__PURE__ */ i.createElement(i.Fragment,null,D&&G.map(e=>/* @__PURE__ */ i.createElement(`input`,{key:e,type:`hidden`,name:D,value:e,disabled:b})),K&&/* @__PURE__ */ i.createElement(`input`,{disabled:b,value:``,...K,ref:W})):(D||k)&&/* @__PURE__ */ i.createElement(`input`,{type:`hidden`,name:D,value:G[0]??``,disabled:b,...K,ref:W})),help:x,ids:{feedback:De,help:Oe,label:Ae},invalid:J,invalidFeedback:C,label:T,valid:q,validFeedback:N})});y.displayName=`Autocomplete`;export{g as n,h as r,y as t};
2
- //# sourceMappingURL=autocomplete-99usnvgh.js.map
1
+ import"./focus-ring-Bs80iIBN.js";import{t as e}from"./useForkedRef-WoqMqsWE.js";import{t}from"./useControllableState-CPUJxfKW.js";import{r as n}from"./useFloatingOverlay-BuiI_CCn.js";import{t as r}from"./useFormField-DH2tlc3e.js";import{t as ee}from"./useOverlayMaxHeight-DTgbr4UQ.js";import{i as te,r as ne,t as re}from"./overlayPlacement-Q6bcbXA5.js";import{t as ie}from"./useRequiredValueInput-gYN8I-LY.js";import{a as ae,i as oe,n as se,r as ce,t as le}from"./ComboboxListBox-Db0rSM3w.js";import{t as ue}from"./Portal-BTDylxAi.js";import{t as de}from"./renderFormField-_6WswnEX.js";import i,{forwardRef as a,useEffect as o,useMemo as s,useRef as c,useState as fe}from"react";import l from"classnames";import{mergeProps as u,useButton as d,useComboBox as f,useFilter as p,useOverlayPosition as m}from"react-aria";import{useComboBoxState as pe}from"react-stately";const h=e=>null;h.displayName=`AutocompleteGroup`;const g=e=>null;g.displayName=`AutocompleteItem`;const _=e=>e==null?[]:Array.isArray(e)?e:[e],v=(e,t)=>{if(e!==void 0)return t?_(e):Array.isArray(e)?e[0]??null:e},me=(e,t)=>{let n=_(e),r=_(t);return n.length===r.length&&n.every((e,t)=>e===r[t])},y=a(function({children:a,className:y,defaultValue:he,disabled:b,help:x,id:ge,invalid:S,invalidFeedback:C,items:w,label:T,multiple:E=!1,name:D,noResultsText:_e=`No results found`,onChange:ve,placeholder:O,required:k,searchPlaceholder:A,size:j,valid:M,validFeedback:N,value:P,...F},ye){let I=s(()=>w?ce(w):se(a,{Group:h,Item:g}),[w,a]),be=s(()=>ae(I),[I]),{contains:xe}=p({sensitivity:`base`}),[L,Se]=t(v(P,E),v(he,E)??(E?[]:null),ve),[Ce,R]=fe(``),z=pe({children:oe,defaultItems:I,disabledKeys:be,defaultFilter:xe,selectionMode:E?`multiple`:`single`,value:L,onChange:e=>{let t=_(e),n=E?t:t[0]??null;R(``),me(n,L)||Se(n)},inputValue:Ce,onInputChange:R,onOpenChange:e=>{e||R(``)},allowsEmptyCollection:!0,menuTrigger:`manual`}),B=c(null),we=e(ye,B),V=c(null),H=c(null),U=c(null),W=c(null),G=_(z.value),{inputProps:K,missing:Te,valid:q}=ie(W,{focus:()=>B.current?.focus(),invalid:S,required:k&&(!E||G.length===0),valid:M}),J=S||Te,{describedBy:Ee,feedbackId:De,helpId:Oe,inputId:ke,labelId:Ae,labelledBy:Y}=r({ariaDescribedBy:F[`aria-describedby`],ariaLabelledBy:F[`aria-labelledby`],help:x,id:ge,invalid:J,invalidFeedback:C,label:T,valid:q,validFeedback:N}),{buttonProps:je,inputProps:Me,listBoxProps:Ne}=f({"aria-label":F[`aria-label`],"aria-labelledby":Y,buttonRef:B,id:ke,inputRef:V,listBoxRef:H,popoverRef:U,isDisabled:b,isRequired:k,placeholder:A},z),{buttonProps:X}=d({...je,elementType:`div`,isDisabled:b,excludeFromTabOrder:!1},B),Z=c(z.isOpen);o(()=>{if(z.isOpen&&!Z.current)V.current?.focus();else if(!z.isOpen&&Z.current){let e=document.activeElement;(!e||e===document.body||U.current?.contains(e))&&B.current?.focus()}Z.current=z.isOpen},[z.isOpen]),o(()=>{if(!z.isOpen)return;let e=B.current;for(;e&&e!==document.body;)e.removeAttribute(`aria-hidden`),e=e.parentElement},[z.isOpen]);let{overlayProps:Pe,placement:Fe}=m({targetRef:B,overlayRef:U,placement:te(`bottom-start`),offset:2,isOpen:z.isOpen,onClose:null});ee(U,z.isOpen);let Ie=n({close:z.close,isOpen:z.isOpen,triggerRef:B}),{menuStyle:Le,placementAttr:Re}=ne(Pe.style,`bottom-start`,Fe),Q={...re,...Le},ze=e=>z.selectionManager.toggleSelection(e),Be=u(Me,{onKeyDown:e=>{if(!E||e.key!==`Backspace`||e.currentTarget.value!==``)return;let t=z.selectedItems[z.selectedItems.length-1];t&&ze(t.key)}}),$=z.selectedItems.length>0,Ve=$?z.selectedItems.length===1?z.selectedItems[0]?.textValue??``:`${z.selectedItems.length} selected`:O;return de({children:/* @__PURE__ */ i.createElement(i.Fragment,null,/* @__PURE__ */ i.createElement(`div`,{className:l(`form-input`,`combobox`,{sm:j===`sm`,lg:j===`lg`,disabled:b},{"is-invalid":J,"is-valid":q},y),...u(F,X),tabIndex:X.tabIndex,"aria-label":F[`aria-label`],"aria-labelledby":Y,"aria-describedby":Ee,"aria-invalid":J||void 0,ref:we},/* @__PURE__ */ i.createElement(`span`,{className:l(`combobox-value`,{"combobox-placeholder":!$})},Ve)),/* @__PURE__ */ i.createElement(ue,{container:Ie},/* @__PURE__ */ i.createElement(`div`,{className:l(`menu`,{show:z.isOpen}),"data-cx-placement":Re,style:Q,hidden:!z.isOpen,ref:U},/* @__PURE__ */ i.createElement(`div`,{className:`combobox-search`},/* @__PURE__ */ i.createElement(`input`,{autoComplete:`off`,className:`form-input combobox-search-input sm`,...Be,ref:V})),/* @__PURE__ */ i.createElement(le,{state:z,listBoxProps:Ne,listBoxRef:H}),z.collection.size===0&&/* @__PURE__ */ i.createElement(`div`,{className:`combobox-no-results`},_e))),E?/* @__PURE__ */ i.createElement(i.Fragment,null,D&&G.map(e=>/* @__PURE__ */ i.createElement(`input`,{key:e,type:`hidden`,name:D,value:e,disabled:b})),K&&/* @__PURE__ */ i.createElement(`input`,{disabled:b,value:``,...K,ref:W})):(D||k)&&/* @__PURE__ */ i.createElement(`input`,{type:`hidden`,name:D,value:G[0]??``,disabled:b,...K,ref:W})),help:x,ids:{feedback:De,help:Oe,label:Ae},invalid:J,invalidFeedback:C,label:T,valid:q,validFeedback:N})});y.displayName=`Autocomplete`;export{g as n,h as r,y as t};
2
+ //# sourceMappingURL=autocomplete-Btcsjrh3.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-99usnvgh.js","names":["useForkedRef","useFloatingOverlay","useFormField","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","COMBOBOX_MENU_OVERLAY_STYLE","useRequiredValueInput","getDisabledKeys","comboboxCollectionChildren","buildEntriesFromChildren","buildEntriesFromItemsDef","ComboboxListBox","Portal","renderFormField","React","classNames","AutocompleteGroup","AutocompleteItem","asKeyArray","value","toModeValue","multiple","isSameSelection","left","a","right","b","key","index","Autocomplete","forwardRef","validProp","rest","entries","useMemo","items","children","disabledKeys","useFilter","selection","setSelection","useControllableState","defaultValue","onChange","query","setQuery","useState","state","useComboBoxState","contains","keyArray","keys","next","isOpen","triggerRef","useRef","forkedTriggerRef","ref","inputRef","listBoxRef","popoverRef","valueInputRef","selectedKeys","requiredInputProps","required","showInvalid","invalid","missing","useComboBox","labelledBy","inputId","disabled","searchPlaceholder","triggerButtonProps","useButton","buttonProps","wasOpen","useEffect","active","node","resolvedPlacement","useOverlayPosition","portalContainer","overlayProps","overlayStyle","menuStyle","removeSelected","inputHtmlProps","mergeProps","inputProps","event","last","hasSelection","triggerText","placeholder","size","valid","className","describedBy","placementAttr","noResultsText","name","feedbackId","helpId","labelId"],"sources":["../../src/components/autocomplete/AutocompleteGroup.tsx","../../src/components/autocomplete/AutocompleteItem.tsx","../../src/components/autocomplete/Autocomplete.tsx"],"sourcesContent":["import { ComboboxGroupProps } from '../combobox/ComboboxGroup'\n\n// Same shape as `ComboboxGroupProps` — see `AutocompleteItemProps` for why this is its own\n// named type instead of a re-export.\nexport type AutocompleteGroupProps = ComboboxGroupProps\n\n// `AutocompleteGroup` is never actually mounted — like `ComboboxGroup`, it's read as data by\n// `Autocomplete`, which splits its top-level children into groups (wrapping react-stately\n// `Section` nodes) and bare items. Groups and bare items can be mixed at the top level:\n//\n// <Autocomplete aria-label=\"Language\">\n// <AutocompleteGroup label=\"Frontend\">\n// <AutocompleteItem id=\"html\">HTML</AutocompleteItem>\n// <AutocompleteItem id=\"css\">CSS</AutocompleteItem>\n// </AutocompleteGroup>\n// <AutocompleteItem id=\"python\">Python</AutocompleteItem>\n// </Autocomplete>\nexport const AutocompleteGroup = (_props: AutocompleteGroupProps): null => null\n\nAutocompleteGroup.displayName = 'AutocompleteGroup'\n","import { ComboboxItemProps } from '../combobox/ComboboxItem'\n\n// Same shape as `ComboboxItemProps` — kept as its own named type (rather than re-exporting\n// `ComboboxItemProps` directly) so `Autocomplete`'s public API doesn't leak an unrelated\n// component's prop type, even though the two are structurally identical under the hood.\nexport type AutocompleteItemProps = ComboboxItemProps\n\n// `AutocompleteItem` is never actually mounted — like `ComboboxItem`, it's read as data by\n// `Autocomplete`, which builds react-aria's listbox collection from each item's `id` and\n// `children`. This keeps the public authoring shape as plain composed JSX:\n//\n// <Autocomplete aria-label=\"Fruit\">\n// <AutocompleteItem id=\"apple\">Apple</AutocompleteItem>\n// <AutocompleteItem id=\"banana\">Banana</AutocompleteItem>\n// </Autocomplete>\nexport const AutocompleteItem = (_props: AutocompleteItemProps): null => null\n\nAutocompleteItem.displayName = 'AutocompleteItem'\n","import React, {\n forwardRef,\n HTMLAttributes,\n InputHTMLAttributes,\n ReactNode,\n useEffect,\n useMemo,\n useRef,\n useState\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps, useButton, useComboBox, useFilter, useOverlayPosition } from 'react-aria'\nimport { Key, useComboBoxState } from 'react-stately'\n\nimport {\n useControllableState,\n useFloatingOverlay,\n useForkedRef,\n useFormField,\n useOverlayMaxHeight,\n useRequiredValueInput\n} from '../../hooks'\nimport {\n buildEntriesFromChildren,\n buildEntriesFromItemsDef,\n ComboboxEntry,\n comboboxCollectionChildren,\n getDisabledKeys\n} from '../combobox/comboboxCollection'\nimport {\n COMBOBOX_MENU_OVERLAY_STYLE,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { Portal } from '../portal/Portal'\nimport { ComboboxListBox } from '../combobox/ComboboxListBox'\nimport { renderFormField } from '../form-field/renderFormField'\nimport { MenuItemsDef } from '../menu/MenuItemDef'\nimport { AutocompleteGroup } from './AutocompleteGroup'\nimport { AutocompleteItem } from './AutocompleteItem'\n\n// `useComboBoxState`/`useComboBox` are generic over a `SelectionMode` ('single' | 'multiple')\n// that only affects *types* — actual runtime behavior (whether a selection closes the menu,\n// disallows an empty selection, *and* whether `state.value`/`onChange`'s callback argument come\n// through as a bare `Key` or a `Key[]`) is driven entirely by the `selectionMode` *string* passed\n// at the call site below, not by this type parameter. Fixing the parameter at `'multiple'` here\n// (the more permissive of the two shapes) lets one component serve both modes without a full\n// code fork, but it means the type system's claim that `state.value`/`onChange`'s argument are\n// always `Key[]` is untrustworthy for single-select at runtime — confirmed by testing (the\n// naive `keys[0]` on a bare string key silently returned its first *character*). `asKeyArray`\n// normalizes either shape; every read of `state.value` or `onChange`'s argument goes through it.\nconst asKeyArray = (value: unknown): Key[] => {\n if (value == null) return []\n return Array.isArray(value) ? value : [value as Key]\n}\n\n// The selection in the shape of the mode: `Key[]` with `multiple`, else a `Key` or `null`, which\n// react-stately reads as \"nothing selected\" and keeps controlled. `undefined` stays `undefined`\n// (an uncontrolled `value`).\nconst toModeValue = (\n value: Key | Key[] | null | undefined,\n multiple: boolean\n): Key | Key[] | null | undefined => {\n if (value === undefined) return undefined\n if (multiple) return asKeyArray(value)\n return Array.isArray(value) ? (value[0] ?? null) : value\n}\n\nconst isSameSelection = (a: Key | Key[] | null, b: Key | Key[] | null) => {\n const left = asKeyArray(a)\n const right = asKeyArray(b)\n return left.length === right.length && left.every((key, index) => key === right[index])\n}\n\nexport interface AutocompleteProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue'\n> {\n /**\n * An accessible label for the autocomplete, used when there's no visible `<label>`.\n */\n 'aria-label'?: string\n /**\n * Identifies a visible `<label>` element for the autocomplete.\n */\n 'aria-labelledby'?: string\n /**\n * `AutocompleteItem` elements, optionally wrapped in `AutocompleteGroup` — read as data by\n * `Autocomplete` to build the option list. Not rendered directly. Ignored when `items` is set.\n */\n children?: ReactNode\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * The initial selected option's id(s) (uncontrolled). An array when `multiple` is set.\n */\n defaultValue?: Key | Key[] | null\n /**\n * Prevents the autocomplete from being focused or interacted with.\n */\n disabled?: boolean\n /**\n * A description for the field, rendered below the autocomplete.\n */\n help?: ReactNode\n /**\n * `id` forwarded to the search input inside the popover. The toggle — the field's real,\n * always-focusable surface — has no single labelable element `<label for>` can target (it's a\n * `role=\"button\"` `<div>`, and the search input itself is hidden until open), so `label` is\n * associated via `aria-labelledby` on the toggle instead. See FORMS.md's \"role=group\" pattern.\n */\n id?: string\n /**\n * Set component validation state to invalid.\n */\n invalid?: boolean\n /**\n * An error message for the field, rendered below the autocomplete when `invalid` is set, and\n * after a submit that a `required` autocomplete with nothing selected held back.\n */\n invalidFeedback?: ReactNode\n /**\n * Array of item/header/divider definitions for data-driven rendering. When provided, children\n * are ignored. A `'header'` entry starts a group that all following items join until the next\n * header or the end of the array. `'divider'` entries are a no-op here — use\n * `AutocompleteGroup` composition instead if you need finer control over grouping. An entry's\n * `href`/`onClick` are `Menu`-only and are not read here — use `onChange` to react to the\n * selection instead.\n */\n items?: MenuItemsDef\n /**\n * The field's caption, rendered as a `FormLabel` associated with the toggle.\n */\n label?: ReactNode\n /**\n * Allows more than one option to be selected. The toggle shows the single selection's label,\n * or an \"N selected\" count once more than one is picked. The menu stays open after each\n * selection, and `Backspace` in the empty search field removes the last selected option.\n */\n multiple?: boolean\n /**\n * `name` of auto-created hidden input(s), kept in sync with the selection, for native form\n * submission. Single-select renders one; `multiple` renders one per selected key. Omit to skip\n * hidden-input creation.\n */\n name?: string\n /**\n * Text shown in the listbox when no options match the current query.\n */\n noResultsText?: ReactNode\n /**\n * Callback fired when the selection changes. Receives an array of keys when `multiple` is set.\n */\n onChange?: (value: Key | Key[] | null) => void\n /**\n * Text shown on the toggle when nothing is selected.\n */\n placeholder?: string\n /**\n * Toggle the required state for the component. A required autocomplete with nothing selected\n * holds its form back from submitting, takes focus on its toggle and shows as invalid, with\n * `invalidFeedback`, until an option is selected or the form is reset. `invalid`, once set, and\n * `valid` decide how it looks instead.\n */\n required?: boolean\n /**\n * Placeholder for the search field inside the dropdown.\n */\n searchPlaceholder?: string\n /**\n * Size the component sm or lg.\n */\n size?: 'sm' | 'lg'\n /**\n * Set component validation state to valid.\n */\n valid?: boolean\n /**\n * A success message for the field, rendered below the autocomplete when `valid` is set.\n */\n validFeedback?: ReactNode\n /**\n * The selected option's id(s) (controlled). An array when `multiple` is set.\n */\n value?: Key | Key[] | null\n}\n\n// `Autocomplete` implements chassis-css's button-trigger combobox — a display-only toggle\n// (not a text input) that opens a `.menu` containing its own search field, matching\n// https://chassis-ui.com/css/docs/forms/combobox/#search-field. This is deliberately NOT the\n// same composition as `Combobox` (whose text input *is* the trigger): here, react-aria's\n// `useComboBox` is given a separate `buttonRef` — a first-class option the hook supports\n// specifically for this \"button opens a listbox with its own input\" shape — so the real\n// `role=\"combobox\"` input lives inside the popover (styled as `.combobox-search-input`) while a\n// toggle serves as the always-visible, always-focusable trigger. The toggle is a `<div\n// role=\"button\">` (via `useButton`'s `elementType: 'div'`, the same pattern `Button.tsx` uses\n// for a non-native trigger) rather than a real `<button>` — an earlier version rendered\n// removable chips inside it for `multiple` mode, which a real (or ARIA) button can't legally\n// contain per axe's `nested-interactive` check; that's now plain \"N selected\" text instead (see\n// `triggerText` below), but the `<div>` stays since reverting buys little and this is proven.\n// `useComboBox`'s own `buttonProps` also sets `excludeFromTabOrder: true` by default — correct\n// for its usual \"auxiliary button beside an always-visible input\" composition, wrong here since\n// the toggle is the *only* focusable surface before opening; overridden back to reachable below.\n// The ref goes to the toggle, the `.combobox` element, as `Combobox`'s goes to its own.\nexport const Autocomplete = forwardRef<HTMLDivElement, AutocompleteProps>(function Autocomplete(\n {\n children,\n className,\n defaultValue,\n disabled,\n help,\n id,\n invalid,\n invalidFeedback,\n items,\n label,\n multiple = false,\n name,\n noResultsText = 'No results found',\n onChange,\n placeholder,\n required,\n searchPlaceholder,\n size,\n valid: validProp,\n validFeedback,\n value,\n ...rest\n },\n ref\n) {\n // `entries`/`disabledKeys` only need to change when the data driving them does — without this,\n // both re-derive from scratch on every render, including every keystroke while typing.\n const entries = useMemo(\n () =>\n items\n ? buildEntriesFromItemsDef(items)\n : buildEntriesFromChildren(children, { Group: AutocompleteGroup, Item: AutocompleteItem }),\n [items, children]\n )\n const disabledKeys = useMemo(() => getDisabledKeys(entries), [entries])\n\n // Case- and accent-insensitive substring matching, mirroring chassis-css's own\n // always-case-insensitive combobox.js filtering.\n const { contains } = useFilter({ sensitivity: 'base' })\n\n // The selection is held here and always given to react-stately as controlled, and so is the\n // text of the search field. react-stately's combobox treats the text as the selection's: it\n // writes the selected option's label into the field, and an emptied field clears an\n // uncontrolled selection. Here the field is a query only. It starts empty each time the list\n // opens and filters the list, and nothing typed in it, or taken out, changes the selection.\n const [selection, setSelection] = useControllableState<Key | Key[] | null>(\n toModeValue(value, multiple),\n toModeValue(defaultValue, multiple) ?? (multiple ? [] : null),\n onChange\n )\n const [query, setQuery] = useState('')\n\n const state = useComboBoxState<ComboboxEntry, 'multiple'>({\n children: comboboxCollectionChildren,\n defaultItems: entries,\n disabledKeys,\n defaultFilter: contains,\n // Cast: the actual runtime string ('single' or 'multiple') is what drives behavior — see the\n // `asKeyArray` comment above for why the *type* parameter above is fixed at 'multiple'.\n selectionMode: (multiple ? 'multiple' : 'single') as 'multiple',\n value: selection as Key[],\n // With both controlled, react-stately reports the selection again when the search field\n // blurs, or Enter picks the selected option: only a change is passed on.\n onChange: (keys) => {\n const keyArray = asKeyArray(keys)\n const next = multiple ? keyArray : (keyArray[0] ?? null)\n setQuery('')\n if (!isSameSelection(next, selection)) setSelection(next)\n },\n inputValue: query,\n onInputChange: setQuery,\n onOpenChange: (isOpen) => {\n if (!isOpen) setQuery('')\n },\n allowsEmptyCollection: true,\n // Opening is driven only by the toggle (see `buttonProps` below) — there's no input to focus\n // or type into until the panel is already open, so 'input'/'focus' triggers (the hook's\n // defaults, meant for `Combobox`'s text-input trigger) don't apply here.\n menuTrigger: 'manual'\n })\n\n const triggerRef = useRef<HTMLDivElement>(null)\n const forkedTriggerRef = useForkedRef(ref, triggerRef)\n const inputRef = useRef<HTMLInputElement>(null)\n const listBoxRef = useRef<HTMLElement>(null)\n const popoverRef = useRef<HTMLDivElement>(null)\n const valueInputRef = useRef<HTMLInputElement>(null)\n\n // What is submitted under `name`: a key that isn't in the list is still a value.\n const selectedKeys = asKeyArray(state.value)\n\n // `required` has to reach an input a form validates (FORMS.md, gotcha 9). The toggle is no form\n // control, the search input holds a query and not the value, and the input that carries the\n // value is `type=\"hidden\"`, which a form doesn't validate. As in `TimeField`, a required\n // autocomplete's value input is a text input that isn't displayed, and `missing` shows the\n // field as invalid from a submit that input held back until an option is selected. The toggle\n // takes the focus a browser would give an input it displays. With `multiple` each key has a\n // hidden input of its own and none while nothing is selected: the text input is then rendered\n // alone, with no `name`, as nothing is submitted for an empty selection. A disabled input isn't\n // validated; the field has no read-only state to leave out.\n const {\n inputProps: requiredInputProps,\n missing,\n valid\n } = useRequiredValueInput(valueInputRef, {\n focus: () => triggerRef.current?.focus(),\n invalid,\n required: required && (!multiple || selectedKeys.length === 0),\n valid: validProp\n })\n const showInvalid = invalid || missing\n\n const { describedBy, feedbackId, helpId, inputId, labelId, labelledBy } = useFormField({\n ariaDescribedBy: rest['aria-describedby'],\n ariaLabelledBy: rest['aria-labelledby'],\n help,\n id,\n invalid: showInvalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n\n const { buttonProps, inputProps, listBoxProps } = useComboBox<ComboboxEntry, 'multiple'>(\n {\n 'aria-label': rest['aria-label'],\n 'aria-labelledby': labelledBy,\n buttonRef: triggerRef,\n id: inputId,\n inputRef,\n listBoxRef,\n popoverRef,\n isDisabled: disabled,\n // `aria-required` on the search input, the `combobox` of this field. The toggle states\n // nothing: ARIA doesn't allow the attribute on a button.\n isRequired: required,\n placeholder: searchPlaceholder\n },\n state\n )\n\n // `useComboBox`'s own `buttonProps` sets `excludeFromTabOrder: true` — correct for its\n // intended composition (an auxiliary icon button *next to* an already-focusable, always-\n // visible input, e.g. a date picker's calendar-icon trigger), where the input is expected to\n // be the primary tab stop. That doesn't hold here: the input lives inside the popover, `hidden`\n // (and so untabbable) until opened, and this toggle is the *only* focusable surface before\n // that — leaving `excludeFromTabOrder` in place would make the whole control unreachable by\n // keyboard. Overriding it back to `false` is what actually makes the toggle the tab stop.\n const { buttonProps: triggerButtonProps } = useButton(\n { ...buttonProps, elementType: 'div', isDisabled: disabled, excludeFromTabOrder: false },\n triggerRef\n )\n\n // The search field autofocuses once the panel is actually open (chassis-css docs: \"When the\n // menu opens, focus jumps to the search field\"), and focus returns to the toggle once it\n // closes — `useComboBox` only knows about `inputRef` as its focus target, and that input is\n // `hidden` (via the panel) while closed, so without this, closing (via Escape, selection, or\n // outside click) would drop focus entirely instead of landing back on the toggle.\n // Only focus that the closing would lose is restored: still inside the panel, which is hidden\n // now, or already dropped to the body. Focus the user moved to another field, by Tab or a\n // press there, stays where they put it.\n const wasOpen = useRef(state.isOpen)\n useEffect(() => {\n if (state.isOpen && !wasOpen.current) {\n inputRef.current?.focus()\n } else if (!state.isOpen && wasOpen.current) {\n const active = document.activeElement\n const lost = !active || active === document.body || popoverRef.current?.contains(active)\n if (lost) triggerRef.current?.focus()\n }\n wasOpen.current = state.isOpen\n }, [state.isOpen])\n\n // `useComboBox` also runs react-aria's `ariaHideOutside` while open, to keep background\n // content out of screen readers' way — but it only knows to protect `inputRef`/`popoverRef`\n // (the elements it was given), not this separate toggle, so the toggle (and, in `multiple`\n // mode, its chips and their focusable remove buttons) would otherwise get `aria-hidden`\n // applied to it too while the panel is open. Walking up to `document.body` (rather than\n // clearing just `triggerRef.current` itself) matters now that the popover portals there too\n // (see `useFloatingOverlay` below): `ariaHideOutside` hides the *first* ancestor level whose\n // subtree contains no protected element, which — once the toggle and the popover no longer\n // share a common non-`body` container — can land on one of the toggle's own ancestors instead\n // of the toggle element itself. `ariaHideOutside`'s own doc comment says it watches for *new*\n // elements to hide, not attribute changes on existing ones, so removing it here (in an effect\n // that necessarily runs after react-aria's own — declared later in this same component)\n // doesn't get silently re-applied.\n useEffect(() => {\n if (!state.isOpen) return\n let node: HTMLElement | null = triggerRef.current\n while (node && node !== document.body) {\n node.removeAttribute('aria-hidden')\n node = node.parentElement\n }\n }, [state.isOpen])\n\n const { overlayProps, placement: resolvedPlacement } = useOverlayPosition({\n targetRef: triggerRef,\n overlayRef: popoverRef,\n placement: toAriaPlacement('bottom-start'),\n offset: 2,\n isOpen: state.isOpen,\n // Leaving `onClose` unset (`undefined`) doesn't actually disable react-aria's close-on-scroll\n // listener — only an explicit `null` does (`useCloseOnScroll` only early-returns on\n // `onClose === null`, not falsy). It happens to be a no-op today only because this toggle is\n // never registered in react-aria's `useOverlayTrigger`/`onCloseMap` backward-compat map (this\n // component calls `useComboBox`, not `useOverlayTrigger`) — an incidental, not guaranteed,\n // safety net. Passing `null` here makes the opt-out explicit, matching `Menu`/`Popover`.\n onClose: null\n })\n useOverlayMaxHeight(popoverRef, state.isOpen)\n\n // Portals the panel to `document.body` (or an enclosing open `<dialog>`) instead of rendering\n // it inline, matching `Popover`/`Tooltip`/`Combobox` — an inline-rendered panel gets clipped by\n // any ancestor with `overflow: hidden`/`auto` (a `ModalBody`, a scrollable card, a table cell),\n // and `Autocomplete` is commonly composed inside exactly those. See\n // `COMBOBOX_MENU_OVERLAY_STYLE` for the styling this trades away by leaving the DOM position\n // `.combobox + .menu` relies on.\n const portalContainer = useFloatingOverlay({\n close: state.close,\n isOpen: state.isOpen,\n triggerRef\n })\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n 'bottom-start',\n resolvedPlacement\n )\n const overlayStyle: React.CSSProperties = { ...COMBOBOX_MENU_OVERLAY_STYLE, ...menuStyle }\n\n const removeSelected = (key: Key) => state.selectionManager.toggleSelection(key)\n\n // Backspace-removes-last-chip only touches the search field's own keydown handling — no\n // nested interactive element needed for it, unlike a rendered \"remove\" button would be (see\n // the trigger's `combobox-value` text below for why that path was dropped).\n const handleSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (!multiple || event.key !== 'Backspace' || event.currentTarget.value !== '') return\n const last = state.selectedItems[state.selectedItems.length - 1]\n if (last) removeSelected(last.key)\n }\n\n const inputHtmlProps = mergeProps(inputProps, {\n onKeyDown: handleSearchKeyDown\n }) as InputHTMLAttributes<HTMLInputElement>\n\n const hasSelection = state.selectedItems.length > 0\n // Matches chassis-css's own vanilla multi-select combobox: the toggle shows the single\n // selected item's label, or \"N selected\" once more than one is picked — deliberately plain\n // text, not per-item chips with their own remove buttons. An earlier version rendered chips\n // here; that failed a real axe check (\"Interactive controls must not be nested\") because the\n // toggle is itself `role=\"button\"`, and a button can't correctly contain other focusable\n // controls. Deselecting an option is still possible by clicking it again in the open list\n // (native to `useComboBoxState`'s multiple-selection toggle behavior) or via Backspace in the\n // search field, just not from the toggle itself.\n const triggerText = !hasSelection\n ? placeholder\n : state.selectedItems.length === 1\n ? (state.selectedItems[0]?.textValue ?? '')\n : `${state.selectedItems.length} selected`\n\n return renderFormField({\n children: (\n <>\n <div\n className={classNames(\n 'form-input',\n 'combobox',\n { sm: size === 'sm', lg: size === 'lg', disabled },\n { 'is-invalid': showInvalid, 'is-valid': valid },\n className\n )}\n // `mergeProps`, so the caller's `onClick`, `onKeyDown` and `onFocus` run beside the\n // toggle's own instead of being replaced by them. It also lets a caller's value through\n // where the toggle's is `undefined`, which `tabIndex` is while disabled: set again.\n {...mergeProps(rest, triggerButtonProps)}\n tabIndex={triggerButtonProps.tabIndex}\n // `useComboBox`'s own `buttonProps` defaults to a generic \"Show suggestions\" label,\n // since its primary a11y attention goes to the search input — override with the same\n // label the input gets, so the toggle (the element actually reachable via Tab, since\n // the input is hidden until open) announces the field's real name, matching the\n // vanilla docs' own `aria-label=\"Select a country\"` on the toggle button.\n aria-label={rest['aria-label']}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n aria-invalid={showInvalid || undefined}\n ref={forkedTriggerRef}\n >\n <span className={classNames('combobox-value', { 'combobox-placeholder': !hasSelection })}>\n {triggerText}\n </span>\n </div>\n <Portal container={portalContainer}>\n <div\n className={classNames('menu', { show: state.isOpen })}\n data-cx-placement={placementAttr}\n style={overlayStyle}\n hidden={!state.isOpen}\n ref={popoverRef}\n >\n <div className=\"combobox-search\">\n <input\n autoComplete=\"off\"\n className=\"form-input combobox-search-input sm\"\n {...inputHtmlProps}\n ref={inputRef}\n />\n </div>\n <ComboboxListBox state={state} listBoxProps={listBoxProps} listBoxRef={listBoxRef} />\n {state.collection.size === 0 && (\n <div className=\"combobox-no-results\">{noResultsText}</div>\n )}\n </div>\n </Portal>\n {multiple ? (\n <>\n {name &&\n selectedKeys.map((key) => (\n <input key={key} type=\"hidden\" name={name} value={key} disabled={disabled} />\n ))}\n {requiredInputProps && (\n <input disabled={disabled} value=\"\" {...requiredInputProps} ref={valueInputRef} />\n )}\n </>\n ) : (\n (name || required) && (\n <input\n type=\"hidden\"\n name={name}\n value={selectedKeys[0] ?? ''}\n disabled={disabled}\n {...requiredInputProps}\n ref={valueInputRef}\n />\n )\n )}\n </>\n ),\n help,\n // No `input` id: the toggle is a `role=\"button\"` `<div>`, not a labelable element, so\n // `htmlFor` can't target it — `aria-labelledby={labelledBy}` on the toggle above (fed by\n // `labelId`) is what actually associates the label, matching DatePicker/OtpInput's\n // `role=\"group\"` pattern in FORMS.md. Passing `inputId` here would point `<label for>` at\n // the hidden search input instead, which sits inert until the popover opens.\n ids: { feedback: feedbackId, help: helpId, label: labelId },\n invalid: showInvalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n})\n\nAutocomplete.displayName = 'Autocomplete'\n"],"mappings":"A,k2BAiBA,MAAaiB,EAAqB,GAAyC,KAE3E,EAAkB,YAAc,oBCJhC,MAAaC,EAAoB,GAAwC,KAEzE,EAAiB,YAAc,mBCkC/B,MAAMC,EAAc,GACdC,GAAS,KAAa,CAAC,EACpB,MAAM,QAAQA,CAAK,EAAIA,EAAQ,CAACA,CAAY,EAM/CC,GACJ,EACA,IACmC,CACnC,GAAID,IAAU,IAAA,GAEd,OADIE,EAAiBH,EAAWC,CAAK,EAC9B,MAAM,QAAQA,CAAK,EAAKA,EAAM,IAAM,KAAQA,CACrD,EAEMG,IAAmB,EAAuB,IAA0B,CACxE,IAAMC,EAAOL,EAAWM,CAAC,EACnBC,EAAQP,EAAWQ,CAAC,EAC1B,OAAOH,EAAK,SAAWE,EAAM,QAAUF,EAAK,OAAO,EAAK,IAAUI,IAAQF,EAAMG,EAAM,CACxF,EAsIaC,EAAeC,EAA8C,SACxE,CACE,WACA,YACA,gBACA,WACA,OACA,MACA,UACA,kBACA,QACA,QACA,WAAW,GACX,OACA,iBAAgB,mBAChB,YACA,cACA,WACA,oBACA,OACA,MAAOC,EACP,gBACA,QACA,GAAGC,GAEL,GACA,CAGA,IAAMC,EAAUC,MAEZC,EACIzB,GAAyByB,CAAK,EAC9B1B,GAAyB2B,EAAU,CAAE,MAAOpB,EAAmB,KAAMC,CAAiB,CAAC,EAC7F,CAACkB,EAAOC,CAAQ,CAClB,EACMC,GAAeH,MAAc3B,GAAgB0B,CAAO,EAAG,CAACA,CAAO,CAAC,EAIhE,CAAE,aAAaK,EAAU,CAAE,YAAa,MAAO,CAAC,EAOhD,CAACC,EAAWC,IAAgBC,EAChCrB,EAAYD,EAAOE,CAAQ,EAC3BD,EAAYsB,GAAcrB,CAAQ,IAAMA,EAAW,CAAC,EAAI,MACxDsB,EACF,EACM,CAACC,GAAOC,GAAYC,GAAS,EAAE,EAE/BC,EAAQC,GAA4C,CACxD,SAAUxC,GACV,aAAcyB,EACd,gBACA,cAAegB,GAGf,cAAgB5B,EAAW,WAAa,SACxC,MAAOkB,EAGP,SAAW,GAAS,CAClB,IAAMW,EAAWhC,EAAWiC,CAAI,EAC1BC,EAAO/B,EAAW6B,EAAYA,EAAS,IAAM,KACnDL,EAAS,EAAE,EACNvB,GAAgB8B,EAAMb,CAAS,GAAGC,GAAaY,CAAI,CAC1D,EACA,WAAYR,GACZ,cAAeC,EACf,aAAe,GAAW,CACnBQ,GAAQR,EAAS,EAAE,CAC1B,EACA,sBAAuB,GAIvB,YAAa,QACf,CAAC,EAEKS,EAAaC,EAAuB,IAAI,EACxCC,GAAmBzD,EAAa0D,GAAKH,CAAU,EAC/CI,EAAWH,EAAyB,IAAI,EACxCI,EAAaJ,EAAoB,IAAI,EACrCK,EAAaL,EAAuB,IAAI,EACxCM,EAAgBN,EAAyB,IAAI,EAG7CO,EAAe5C,EAAW6B,EAAM,KAAK,EAWrC,CACJ,WAAYgB,EACZ,WACA,SACEzD,GAAsBuD,EAAe,CACvC,UAAaP,EAAW,SAAS,MAAM,EACvC,UACA,SAAUU,IAAa,CAAC3C,GAAYyC,EAAa,SAAW,GAC5D,MAAO/B,CACT,CAAC,EACKkC,EAAcC,GAAWC,GAEzB,CAAE,eAAa,cAAY,UAAQ,WAAS,WAAS,cAAelE,EAAa,CACrF,gBAAiB+B,EAAK,oBACtB,eAAgBA,EAAK,mBACrB,OACA,MACA,QAASiC,EACT,kBACA,QACA,QACA,eACF,CAAC,EAEK,CAAE,eAAa,cAAY,iBAAiBG,EAChD,CACE,aAAcpC,EAAK,cACnB,kBAAmBqC,EACnB,UAAWf,EACX,GAAIgB,GACJ,WACA,aACA,aACA,WAAYC,EAGZ,WAAYP,EACZ,YAAaQ,CACf,EACAzB,CACF,EASM,CAAE,YAAa0B,GAAuBC,EAC1C,CAAE,GAAGC,GAAa,YAAa,MAAO,WAAYJ,EAAU,oBAAqB,EAAM,EACvFjB,CACF,EAUMsB,EAAUrB,EAAOR,EAAM,MAAM,EACnC8B,MAAgB,CACd,GAAI9B,EAAM,QAAU,CAAC6B,EAAQ,QAC3BlB,EAAS,SAAS,MAAM,OACnB,GAAI,CAACX,EAAM,QAAU6B,EAAQ,QAAS,CAC3C,IAAME,EAAS,SAAS,eACX,CAACA,GAAUA,IAAW,SAAS,MAAQlB,EAAW,SAAS,SAASkB,CAAM,IAC7ExB,EAAW,SAAS,MAAM,CACtC,CACA,EAAQ,QAAUP,EAAM,MAC1B,EAAG,CAACA,EAAM,MAAM,CAAC,EAejB8B,MAAgB,CACd,GAAI,CAAC9B,EAAM,OAAQ,OACnB,IAAIgC,EAA2BzB,EAAW,QAC1C,KAAOyB,GAAQA,IAAS,SAAS,MAC/BA,EAAK,gBAAgB,aAAa,EAClC,EAAOA,EAAK,aAEhB,EAAG,CAAChC,EAAM,MAAM,CAAC,EAEjB,GAAM,CAAE,gBAAc,UAAWiC,IAAsBC,EAAmB,CACxE,UAAW3B,EACX,WAAYM,EACZ,UAAWzD,GAAgB,cAAc,EACzC,OAAQ,EACR,OAAQ4C,EAAM,OAOd,QAAS,IACX,CAAC,EACD7C,GAAoB0D,EAAYb,EAAM,MAAM,EAQ5C,IAAMmC,GAAkBlF,EAAmB,CACzC,MAAO+C,EAAM,MACb,OAAQA,EAAM,OACd,YACF,CAAC,EAEK,CAAE,aAAW,kBAAkB3C,GACnC+E,GAAa,MACb,eACAH,EACF,EACMI,EAAoC,CAAE,GAAG/E,GAA6B,GAAGgF,EAAU,EAEnFC,GAAkB,GAAavC,EAAM,iBAAiB,gBAAgBpB,CAAG,EAWzE4D,GAAiBC,EAAWC,GAAY,CAC5C,UAP2B,GAAiD,CAC5E,GAAI,CAACpE,GAAYqE,EAAM,MAAQ,aAAeA,EAAM,cAAc,QAAU,GAAI,OAChF,IAAMC,EAAO5C,EAAM,cAAcA,EAAM,cAAc,OAAS,GAC1D4C,GAAML,GAAeK,EAAK,GAAG,CACnC,CAIA,CAAC,EAEKC,EAAe7C,EAAM,cAAc,OAAS,EAS5C8C,GAAeD,EAEjB7C,EAAM,cAAc,SAAW,EAC5BA,EAAM,cAAc,EAAE,EAAE,WAAa,GACtC,GAAGA,EAAM,cAAc,OAAO,WAHhC+C,EAKJ,OAAOjF,GAAgB,CACrB,SACE,kBAAA,cAAAC,EAAA,SAAA,KACE,kBAAA,cAAC,MAAD,CACE,UAAWC,EACT,aACA,WACA,CAAE,GAAIgF,IAAS,KAAM,GAAIA,IAAS,KAAM,UAAS,EACjD,CAAE,aAAc9B,EAAa,WAAY+B,CAAM,EAC/CC,CACF,EAIA,GAAIT,EAAWxD,EAAMyC,CAAkB,EACvC,SAAUA,EAAmB,SAM7B,aAAYzC,EAAK,cACjB,kBAAiBqC,EACjB,mBAAkB6B,GAClB,eAAcjC,GAAe,IAAA,GAC7B,IAAKT,EAKF,EAHH,kBAAA,cAAC,OAAD,CAAM,UAAWzC,EAAW,iBAAkB,CAAE,uBAAwB,CAAC6E,CAAa,CAAC,CAEjF,EADHC,EACG,CACH,EACL,kBAAA,cAACjF,GAAD,CAAQ,UAAWsE,EAqBX,EApBN,kBAAA,cAAC,MAAD,CACE,UAAWnE,EAAW,OAAQ,CAAE,KAAMgC,EAAM,MAAO,CAAC,EACpD,oBAAmBoD,GACnB,MAAOf,EACP,OAAQ,CAACrC,EAAM,OACf,IAAKa,CAcF,EAZH,kBAAA,cAAC,MAAD,CAAK,UAAU,iBAOV,EANH,kBAAA,cAAC,QAAD,CACE,aAAa,MACb,UAAU,sCACV,GAAI2B,GACJ,IAAK7B,CACN,CAAA,CACE,EACL,kBAAA,cAAC/C,GAAD,CAAwB,QAAqB,gBAA0B,YAAa,CAAA,EACnFoC,EAAM,WAAW,OAAS,GACzB,kBAAA,cAAC,MAAD,CAAK,UAAU,qBAA0C,EAAnBqD,EAAmB,CAExD,CACC,EACP/E,EACC,kBAAA,cAAAP,EAAA,SAAA,KACGuF,GACCvC,EAAa,IAAK,GAChB,kBAAA,cAAC,QAAD,CAAY,MAAK,KAAK,SAAe,OAAM,MAAOnC,EAAe,UAAW,CAAA,CAC7E,EACFoC,GACC,kBAAA,cAAC,QAAD,CAAiB,WAAU,MAAM,GAAG,GAAIA,EAAoB,IAAKF,CAAgB,CAAA,CAEnF,GAEDwC,GAAQrC,IACP,kBAAA,cAAC,QAAD,CACE,KAAK,SACC,OACN,MAAOF,EAAa,IAAM,GAChB,WACV,GAAIC,EACJ,IAAKF,CACN,CAAA,CAGL,EAEJ,OAMA,IAAK,CAAE,SAAUyC,GAAY,KAAMC,GAAQ,MAAOC,EAAQ,EAC1D,QAASvC,EACT,kBACA,QACA,QACA,eACF,CAAC,CACH,CAAC,EAED,EAAa,YAAc,e"}
1
+ {"version":3,"file":"autocomplete-Btcsjrh3.js","names":["useForkedRef","useFloatingOverlay","useFormField","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","COMBOBOX_MENU_OVERLAY_STYLE","useRequiredValueInput","getDisabledKeys","comboboxCollectionChildren","buildEntriesFromChildren","buildEntriesFromItemsDef","ComboboxListBox","Portal","renderFormField","React","classNames","AutocompleteGroup","AutocompleteItem","asKeyArray","value","toModeValue","multiple","isSameSelection","left","a","right","b","key","index","Autocomplete","forwardRef","validProp","rest","entries","useMemo","items","children","disabledKeys","useFilter","selection","setSelection","useControllableState","defaultValue","onChange","query","setQuery","useState","state","useComboBoxState","contains","keyArray","keys","next","isOpen","triggerRef","useRef","forkedTriggerRef","ref","inputRef","listBoxRef","popoverRef","valueInputRef","selectedKeys","requiredInputProps","required","showInvalid","invalid","missing","useComboBox","labelledBy","inputId","disabled","searchPlaceholder","triggerButtonProps","useButton","buttonProps","wasOpen","useEffect","active","node","resolvedPlacement","useOverlayPosition","portalContainer","overlayProps","overlayStyle","menuStyle","removeSelected","inputHtmlProps","mergeProps","inputProps","event","last","hasSelection","triggerText","placeholder","size","valid","className","describedBy","placementAttr","noResultsText","name","feedbackId","helpId","labelId"],"sources":["../../src/components/autocomplete/AutocompleteGroup.tsx","../../src/components/autocomplete/AutocompleteItem.tsx","../../src/components/autocomplete/Autocomplete.tsx"],"sourcesContent":["import { ComboboxGroupProps } from '../combobox/ComboboxGroup'\n\n// Same shape as `ComboboxGroupProps` — see `AutocompleteItemProps` for why this is its own\n// named type instead of a re-export.\nexport type AutocompleteGroupProps = ComboboxGroupProps\n\n// `AutocompleteGroup` is never actually mounted — like `ComboboxGroup`, it's read as data by\n// `Autocomplete`, which splits its top-level children into groups (wrapping react-stately\n// `Section` nodes) and bare items. Groups and bare items can be mixed at the top level:\n//\n// <Autocomplete aria-label=\"Language\">\n// <AutocompleteGroup label=\"Frontend\">\n// <AutocompleteItem id=\"html\">HTML</AutocompleteItem>\n// <AutocompleteItem id=\"css\">CSS</AutocompleteItem>\n// </AutocompleteGroup>\n// <AutocompleteItem id=\"python\">Python</AutocompleteItem>\n// </Autocomplete>\nexport const AutocompleteGroup = (_props: AutocompleteGroupProps): null => null\n\nAutocompleteGroup.displayName = 'AutocompleteGroup'\n","import { ComboboxItemProps } from '../combobox/ComboboxItem'\n\n// Same shape as `ComboboxItemProps` — kept as its own named type (rather than re-exporting\n// `ComboboxItemProps` directly) so `Autocomplete`'s public API doesn't leak an unrelated\n// component's prop type, even though the two are structurally identical under the hood.\nexport type AutocompleteItemProps = ComboboxItemProps\n\n// `AutocompleteItem` is never actually mounted — like `ComboboxItem`, it's read as data by\n// `Autocomplete`, which builds react-aria's listbox collection from each item's `id` and\n// `children`. This keeps the public authoring shape as plain composed JSX:\n//\n// <Autocomplete aria-label=\"Fruit\">\n// <AutocompleteItem id=\"apple\">Apple</AutocompleteItem>\n// <AutocompleteItem id=\"banana\">Banana</AutocompleteItem>\n// </Autocomplete>\nexport const AutocompleteItem = (_props: AutocompleteItemProps): null => null\n\nAutocompleteItem.displayName = 'AutocompleteItem'\n","import React, {\n forwardRef,\n HTMLAttributes,\n InputHTMLAttributes,\n ReactNode,\n useEffect,\n useMemo,\n useRef,\n useState\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps, useButton, useComboBox, useFilter, useOverlayPosition } from 'react-aria'\nimport { Key, useComboBoxState } from 'react-stately'\n\nimport {\n useControllableState,\n useFloatingOverlay,\n useForkedRef,\n useFormField,\n useOverlayMaxHeight,\n useRequiredValueInput\n} from '../../hooks'\nimport {\n buildEntriesFromChildren,\n buildEntriesFromItemsDef,\n ComboboxEntry,\n comboboxCollectionChildren,\n getDisabledKeys\n} from '../combobox/comboboxCollection'\nimport {\n COMBOBOX_MENU_OVERLAY_STYLE,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { Portal } from '../portal/Portal'\nimport { ComboboxListBox } from '../combobox/ComboboxListBox'\nimport { renderFormField } from '../form-field/renderFormField'\nimport { MenuItemsDef } from '../menu/MenuItemDef'\nimport { AutocompleteGroup } from './AutocompleteGroup'\nimport { AutocompleteItem } from './AutocompleteItem'\n\n// `useComboBoxState`/`useComboBox` are generic over a `SelectionMode` ('single' | 'multiple')\n// that only affects *types* — actual runtime behavior (whether a selection closes the menu,\n// disallows an empty selection, *and* whether `state.value`/`onChange`'s callback argument come\n// through as a bare `Key` or a `Key[]`) is driven entirely by the `selectionMode` *string* passed\n// at the call site below, not by this type parameter. Fixing the parameter at `'multiple'` here\n// (the more permissive of the two shapes) lets one component serve both modes without a full\n// code fork, but it means the type system's claim that `state.value`/`onChange`'s argument are\n// always `Key[]` is untrustworthy for single-select at runtime — confirmed by testing (the\n// naive `keys[0]` on a bare string key silently returned its first *character*). `asKeyArray`\n// normalizes either shape; every read of `state.value` or `onChange`'s argument goes through it.\nconst asKeyArray = (value: unknown): Key[] => {\n if (value == null) return []\n return Array.isArray(value) ? value : [value as Key]\n}\n\n// The selection in the shape of the mode: `Key[]` with `multiple`, else a `Key` or `null`, which\n// react-stately reads as \"nothing selected\" and keeps controlled. `undefined` stays `undefined`\n// (an uncontrolled `value`).\nconst toModeValue = (\n value: Key | Key[] | null | undefined,\n multiple: boolean\n): Key | Key[] | null | undefined => {\n if (value === undefined) return undefined\n if (multiple) return asKeyArray(value)\n return Array.isArray(value) ? (value[0] ?? null) : value\n}\n\nconst isSameSelection = (a: Key | Key[] | null, b: Key | Key[] | null) => {\n const left = asKeyArray(a)\n const right = asKeyArray(b)\n return left.length === right.length && left.every((key, index) => key === right[index])\n}\n\nexport interface AutocompleteProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue'\n> {\n /**\n * An accessible label for the autocomplete, used when there's no visible `<label>`.\n */\n 'aria-label'?: string\n /**\n * Identifies a visible `<label>` element for the autocomplete.\n */\n 'aria-labelledby'?: string\n /**\n * `AutocompleteItem` elements, optionally wrapped in `AutocompleteGroup` — read as data by\n * `Autocomplete` to build the option list. Not rendered directly. Ignored when `items` is set.\n */\n children?: ReactNode\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * The initial selected option's id(s) (uncontrolled). An array when `multiple` is set.\n */\n defaultValue?: Key | Key[] | null\n /**\n * Prevents the autocomplete from being focused or interacted with.\n */\n disabled?: boolean\n /**\n * A description for the field, rendered below the autocomplete.\n */\n help?: ReactNode\n /**\n * `id` forwarded to the search input inside the popover. The toggle — the field's real,\n * always-focusable surface — has no single labelable element `<label for>` can target (it's a\n * `role=\"button\"` `<div>`, and the search input itself is hidden until open), so `label` is\n * associated via `aria-labelledby` on the toggle instead. See FORMS.md's \"role=group\" pattern.\n */\n id?: string\n /**\n * Set component validation state to invalid.\n */\n invalid?: boolean\n /**\n * An error message for the field, rendered below the autocomplete when `invalid` is set, and\n * after a submit that a `required` autocomplete with nothing selected held back.\n */\n invalidFeedback?: ReactNode\n /**\n * Array of item/header/divider definitions for data-driven rendering. When provided, children\n * are ignored. A `'header'` entry starts a group that all following items join until the next\n * header or the end of the array. `'divider'` entries are a no-op here — use\n * `AutocompleteGroup` composition instead if you need finer control over grouping. An entry's\n * `href`/`onClick` are `Menu`-only and are not read here — use `onChange` to react to the\n * selection instead.\n */\n items?: MenuItemsDef\n /**\n * The field's caption, rendered as a `FormLabel` associated with the toggle.\n */\n label?: ReactNode\n /**\n * Allows more than one option to be selected. The toggle shows the single selection's label,\n * or an \"N selected\" count once more than one is picked. The menu stays open after each\n * selection, and `Backspace` in the empty search field removes the last selected option.\n */\n multiple?: boolean\n /**\n * `name` of auto-created hidden input(s), kept in sync with the selection, for native form\n * submission. Single-select renders one; `multiple` renders one per selected key. Omit to skip\n * hidden-input creation.\n */\n name?: string\n /**\n * Text shown in the listbox when no options match the current query.\n */\n noResultsText?: ReactNode\n /**\n * Callback fired when the selection changes. Receives an array of keys when `multiple` is set.\n */\n onChange?: (value: Key | Key[] | null) => void\n /**\n * Text shown on the toggle when nothing is selected.\n */\n placeholder?: string\n /**\n * Toggle the required state for the component. A required autocomplete with nothing selected\n * holds its form back from submitting, takes focus on its toggle and shows as invalid, with\n * `invalidFeedback`, until an option is selected or the form is reset. `invalid`, once set, and\n * `valid` decide how it looks instead.\n */\n required?: boolean\n /**\n * Placeholder for the search field inside the dropdown.\n */\n searchPlaceholder?: string\n /**\n * Size the component sm or lg.\n */\n size?: 'sm' | 'lg'\n /**\n * Set component validation state to valid.\n */\n valid?: boolean\n /**\n * A success message for the field, rendered below the autocomplete when `valid` is set.\n */\n validFeedback?: ReactNode\n /**\n * The selected option's id(s) (controlled). An array when `multiple` is set.\n */\n value?: Key | Key[] | null\n}\n\n// `Autocomplete` implements chassis-css's button-trigger combobox — a display-only toggle\n// (not a text input) that opens a `.menu` containing its own search field, matching\n// https://chassis-ui.com/css/docs/forms/combobox/#search-field. This is deliberately NOT the\n// same composition as `Combobox` (whose text input *is* the trigger): here, react-aria's\n// `useComboBox` is given a separate `buttonRef` — a first-class option the hook supports\n// specifically for this \"button opens a listbox with its own input\" shape — so the real\n// `role=\"combobox\"` input lives inside the popover (styled as `.combobox-search-input`) while a\n// toggle serves as the always-visible, always-focusable trigger. The toggle is a `<div\n// role=\"button\">` (via `useButton`'s `elementType: 'div'`, the same pattern `Button.tsx` uses\n// for a non-native trigger) rather than a real `<button>` — an earlier version rendered\n// removable chips inside it for `multiple` mode, which a real (or ARIA) button can't legally\n// contain per axe's `nested-interactive` check; that's now plain \"N selected\" text instead (see\n// `triggerText` below), but the `<div>` stays since reverting buys little and this is proven.\n// `useComboBox`'s own `buttonProps` also sets `excludeFromTabOrder: true` by default — correct\n// for its usual \"auxiliary button beside an always-visible input\" composition, wrong here since\n// the toggle is the *only* focusable surface before opening; overridden back to reachable below.\n// The ref goes to the toggle, the `.combobox` element, as `Combobox`'s goes to its own.\nexport const Autocomplete = forwardRef<HTMLDivElement, AutocompleteProps>(function Autocomplete(\n {\n children,\n className,\n defaultValue,\n disabled,\n help,\n id,\n invalid,\n invalidFeedback,\n items,\n label,\n multiple = false,\n name,\n noResultsText = 'No results found',\n onChange,\n placeholder,\n required,\n searchPlaceholder,\n size,\n valid: validProp,\n validFeedback,\n value,\n ...rest\n },\n ref\n) {\n // `entries`/`disabledKeys` only need to change when the data driving them does — without this,\n // both re-derive from scratch on every render, including every keystroke while typing.\n const entries = useMemo(\n () =>\n items\n ? buildEntriesFromItemsDef(items)\n : buildEntriesFromChildren(children, { Group: AutocompleteGroup, Item: AutocompleteItem }),\n [items, children]\n )\n const disabledKeys = useMemo(() => getDisabledKeys(entries), [entries])\n\n // Case- and accent-insensitive substring matching, mirroring chassis-css's own\n // always-case-insensitive combobox.js filtering.\n const { contains } = useFilter({ sensitivity: 'base' })\n\n // The selection is held here and always given to react-stately as controlled, and so is the\n // text of the search field. react-stately's combobox treats the text as the selection's: it\n // writes the selected option's label into the field, and an emptied field clears an\n // uncontrolled selection. Here the field is a query only. It starts empty each time the list\n // opens and filters the list, and nothing typed in it, or taken out, changes the selection.\n const [selection, setSelection] = useControllableState<Key | Key[] | null>(\n toModeValue(value, multiple),\n toModeValue(defaultValue, multiple) ?? (multiple ? [] : null),\n onChange\n )\n const [query, setQuery] = useState('')\n\n const state = useComboBoxState<ComboboxEntry, 'multiple'>({\n children: comboboxCollectionChildren,\n defaultItems: entries,\n disabledKeys,\n defaultFilter: contains,\n // Cast: the actual runtime string ('single' or 'multiple') is what drives behavior — see the\n // `asKeyArray` comment above for why the *type* parameter above is fixed at 'multiple'.\n selectionMode: (multiple ? 'multiple' : 'single') as 'multiple',\n value: selection as Key[],\n // With both controlled, react-stately reports the selection again when the search field\n // blurs, or Enter picks the selected option: only a change is passed on.\n onChange: (keys) => {\n const keyArray = asKeyArray(keys)\n const next = multiple ? keyArray : (keyArray[0] ?? null)\n setQuery('')\n if (!isSameSelection(next, selection)) setSelection(next)\n },\n inputValue: query,\n onInputChange: setQuery,\n onOpenChange: (isOpen) => {\n if (!isOpen) setQuery('')\n },\n allowsEmptyCollection: true,\n // Opening is driven only by the toggle (see `buttonProps` below) — there's no input to focus\n // or type into until the panel is already open, so 'input'/'focus' triggers (the hook's\n // defaults, meant for `Combobox`'s text-input trigger) don't apply here.\n menuTrigger: 'manual'\n })\n\n const triggerRef = useRef<HTMLDivElement>(null)\n const forkedTriggerRef = useForkedRef(ref, triggerRef)\n const inputRef = useRef<HTMLInputElement>(null)\n const listBoxRef = useRef<HTMLElement>(null)\n const popoverRef = useRef<HTMLDivElement>(null)\n const valueInputRef = useRef<HTMLInputElement>(null)\n\n // What is submitted under `name`: a key that isn't in the list is still a value.\n const selectedKeys = asKeyArray(state.value)\n\n // `required` has to reach an input a form validates (FORMS.md, gotcha 9). The toggle is no form\n // control, the search input holds a query and not the value, and the input that carries the\n // value is `type=\"hidden\"`, which a form doesn't validate. As in `TimeField`, a required\n // autocomplete's value input is a text input that isn't displayed, and `missing` shows the\n // field as invalid from a submit that input held back until an option is selected. The toggle\n // takes the focus a browser would give an input it displays. With `multiple` each key has a\n // hidden input of its own and none while nothing is selected: the text input is then rendered\n // alone, with no `name`, as nothing is submitted for an empty selection. A disabled input isn't\n // validated; the field has no read-only state to leave out.\n const {\n inputProps: requiredInputProps,\n missing,\n valid\n } = useRequiredValueInput(valueInputRef, {\n focus: () => triggerRef.current?.focus(),\n invalid,\n required: required && (!multiple || selectedKeys.length === 0),\n valid: validProp\n })\n const showInvalid = invalid || missing\n\n const { describedBy, feedbackId, helpId, inputId, labelId, labelledBy } = useFormField({\n ariaDescribedBy: rest['aria-describedby'],\n ariaLabelledBy: rest['aria-labelledby'],\n help,\n id,\n invalid: showInvalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n\n const { buttonProps, inputProps, listBoxProps } = useComboBox<ComboboxEntry, 'multiple'>(\n {\n 'aria-label': rest['aria-label'],\n 'aria-labelledby': labelledBy,\n buttonRef: triggerRef,\n id: inputId,\n inputRef,\n listBoxRef,\n popoverRef,\n isDisabled: disabled,\n // `aria-required` on the search input, the `combobox` of this field. The toggle states\n // nothing: ARIA doesn't allow the attribute on a button.\n isRequired: required,\n placeholder: searchPlaceholder\n },\n state\n )\n\n // `useComboBox`'s own `buttonProps` sets `excludeFromTabOrder: true` — correct for its\n // intended composition (an auxiliary icon button *next to* an already-focusable, always-\n // visible input, e.g. a date picker's calendar-icon trigger), where the input is expected to\n // be the primary tab stop. That doesn't hold here: the input lives inside the popover, `hidden`\n // (and so untabbable) until opened, and this toggle is the *only* focusable surface before\n // that — leaving `excludeFromTabOrder` in place would make the whole control unreachable by\n // keyboard. Overriding it back to `false` is what actually makes the toggle the tab stop.\n const { buttonProps: triggerButtonProps } = useButton(\n { ...buttonProps, elementType: 'div', isDisabled: disabled, excludeFromTabOrder: false },\n triggerRef\n )\n\n // The search field autofocuses once the panel is actually open (chassis-css docs: \"When the\n // menu opens, focus jumps to the search field\"), and focus returns to the toggle once it\n // closes — `useComboBox` only knows about `inputRef` as its focus target, and that input is\n // `hidden` (via the panel) while closed, so without this, closing (via Escape, selection, or\n // outside click) would drop focus entirely instead of landing back on the toggle.\n // Only focus that the closing would lose is restored: still inside the panel, which is hidden\n // now, or already dropped to the body. Focus the user moved to another field, by Tab or a\n // press there, stays where they put it.\n const wasOpen = useRef(state.isOpen)\n useEffect(() => {\n if (state.isOpen && !wasOpen.current) {\n inputRef.current?.focus()\n } else if (!state.isOpen && wasOpen.current) {\n const active = document.activeElement\n const lost = !active || active === document.body || popoverRef.current?.contains(active)\n if (lost) triggerRef.current?.focus()\n }\n wasOpen.current = state.isOpen\n }, [state.isOpen])\n\n // `useComboBox` also runs react-aria's `ariaHideOutside` while open, to keep background\n // content out of screen readers' way — but it only knows to protect `inputRef`/`popoverRef`\n // (the elements it was given), not this separate toggle, so the toggle (and, in `multiple`\n // mode, its chips and their focusable remove buttons) would otherwise get `aria-hidden`\n // applied to it too while the panel is open. Walking up to `document.body` (rather than\n // clearing just `triggerRef.current` itself) matters now that the popover portals there too\n // (see `useFloatingOverlay` below): `ariaHideOutside` hides the *first* ancestor level whose\n // subtree contains no protected element, which — once the toggle and the popover no longer\n // share a common non-`body` container — can land on one of the toggle's own ancestors instead\n // of the toggle element itself. `ariaHideOutside`'s own doc comment says it watches for *new*\n // elements to hide, not attribute changes on existing ones, so removing it here (in an effect\n // that necessarily runs after react-aria's own — declared later in this same component)\n // doesn't get silently re-applied.\n useEffect(() => {\n if (!state.isOpen) return\n let node: HTMLElement | null = triggerRef.current\n while (node && node !== document.body) {\n node.removeAttribute('aria-hidden')\n node = node.parentElement\n }\n }, [state.isOpen])\n\n const { overlayProps, placement: resolvedPlacement } = useOverlayPosition({\n targetRef: triggerRef,\n overlayRef: popoverRef,\n placement: toAriaPlacement('bottom-start'),\n offset: 2,\n isOpen: state.isOpen,\n // Leaving `onClose` unset (`undefined`) doesn't actually disable react-aria's close-on-scroll\n // listener — only an explicit `null` does (`useCloseOnScroll` only early-returns on\n // `onClose === null`, not falsy). It happens to be a no-op today only because this toggle is\n // never registered in react-aria's `useOverlayTrigger`/`onCloseMap` backward-compat map (this\n // component calls `useComboBox`, not `useOverlayTrigger`) — an incidental, not guaranteed,\n // safety net. Passing `null` here makes the opt-out explicit, matching `Menu`/`Popover`.\n onClose: null\n })\n useOverlayMaxHeight(popoverRef, state.isOpen)\n\n // Portals the panel to `document.body` (or an enclosing open `<dialog>`) instead of rendering\n // it inline, matching `Popover`/`Tooltip`/`Combobox` — an inline-rendered panel gets clipped by\n // any ancestor with `overflow: hidden`/`auto` (a `ModalBody`, a scrollable card, a table cell),\n // and `Autocomplete` is commonly composed inside exactly those. See\n // `COMBOBOX_MENU_OVERLAY_STYLE` for the styling this trades away by leaving the DOM position\n // `.combobox + .menu` relies on.\n const portalContainer = useFloatingOverlay({\n close: state.close,\n isOpen: state.isOpen,\n triggerRef\n })\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n 'bottom-start',\n resolvedPlacement\n )\n const overlayStyle: React.CSSProperties = { ...COMBOBOX_MENU_OVERLAY_STYLE, ...menuStyle }\n\n const removeSelected = (key: Key) => state.selectionManager.toggleSelection(key)\n\n // Backspace-removes-last-chip only touches the search field's own keydown handling — no\n // nested interactive element needed for it, unlike a rendered \"remove\" button would be (see\n // the trigger's `combobox-value` text below for why that path was dropped).\n const handleSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (!multiple || event.key !== 'Backspace' || event.currentTarget.value !== '') return\n const last = state.selectedItems[state.selectedItems.length - 1]\n if (last) removeSelected(last.key)\n }\n\n const inputHtmlProps = mergeProps(inputProps, {\n onKeyDown: handleSearchKeyDown\n }) as InputHTMLAttributes<HTMLInputElement>\n\n const hasSelection = state.selectedItems.length > 0\n // Matches chassis-css's own vanilla multi-select combobox: the toggle shows the single\n // selected item's label, or \"N selected\" once more than one is picked — deliberately plain\n // text, not per-item chips with their own remove buttons. An earlier version rendered chips\n // here; that failed a real axe check (\"Interactive controls must not be nested\") because the\n // toggle is itself `role=\"button\"`, and a button can't correctly contain other focusable\n // controls. Deselecting an option is still possible by clicking it again in the open list\n // (native to `useComboBoxState`'s multiple-selection toggle behavior) or via Backspace in the\n // search field, just not from the toggle itself.\n const triggerText = !hasSelection\n ? placeholder\n : state.selectedItems.length === 1\n ? (state.selectedItems[0]?.textValue ?? '')\n : `${state.selectedItems.length} selected`\n\n return renderFormField({\n children: (\n <>\n <div\n className={classNames(\n 'form-input',\n 'combobox',\n { sm: size === 'sm', lg: size === 'lg', disabled },\n { 'is-invalid': showInvalid, 'is-valid': valid },\n className\n )}\n // `mergeProps`, so the caller's `onClick`, `onKeyDown` and `onFocus` run beside the\n // toggle's own instead of being replaced by them. It also lets a caller's value through\n // where the toggle's is `undefined`, which `tabIndex` is while disabled: set again.\n {...mergeProps(rest, triggerButtonProps)}\n tabIndex={triggerButtonProps.tabIndex}\n // `useComboBox`'s own `buttonProps` defaults to a generic \"Show suggestions\" label,\n // since its primary a11y attention goes to the search input — override with the same\n // label the input gets, so the toggle (the element actually reachable via Tab, since\n // the input is hidden until open) announces the field's real name, matching the\n // vanilla docs' own `aria-label=\"Select a country\"` on the toggle button.\n aria-label={rest['aria-label']}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n aria-invalid={showInvalid || undefined}\n ref={forkedTriggerRef}\n >\n <span className={classNames('combobox-value', { 'combobox-placeholder': !hasSelection })}>\n {triggerText}\n </span>\n </div>\n <Portal container={portalContainer}>\n <div\n className={classNames('menu', { show: state.isOpen })}\n data-cx-placement={placementAttr}\n style={overlayStyle}\n hidden={!state.isOpen}\n ref={popoverRef}\n >\n <div className=\"combobox-search\">\n <input\n autoComplete=\"off\"\n className=\"form-input combobox-search-input sm\"\n {...inputHtmlProps}\n ref={inputRef}\n />\n </div>\n <ComboboxListBox state={state} listBoxProps={listBoxProps} listBoxRef={listBoxRef} />\n {state.collection.size === 0 && (\n <div className=\"combobox-no-results\">{noResultsText}</div>\n )}\n </div>\n </Portal>\n {multiple ? (\n <>\n {name &&\n selectedKeys.map((key) => (\n <input key={key} type=\"hidden\" name={name} value={key} disabled={disabled} />\n ))}\n {requiredInputProps && (\n <input disabled={disabled} value=\"\" {...requiredInputProps} ref={valueInputRef} />\n )}\n </>\n ) : (\n (name || required) && (\n <input\n type=\"hidden\"\n name={name}\n value={selectedKeys[0] ?? ''}\n disabled={disabled}\n {...requiredInputProps}\n ref={valueInputRef}\n />\n )\n )}\n </>\n ),\n help,\n // No `input` id: the toggle is a `role=\"button\"` `<div>`, not a labelable element, so\n // `htmlFor` can't target it — `aria-labelledby={labelledBy}` on the toggle above (fed by\n // `labelId`) is what actually associates the label, matching DatePicker/OtpInput's\n // `role=\"group\"` pattern in FORMS.md. Passing `inputId` here would point `<label for>` at\n // the hidden search input instead, which sits inert until the popover opens.\n ids: { feedback: feedbackId, help: helpId, label: labelId },\n invalid: showInvalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n})\n\nAutocomplete.displayName = 'Autocomplete'\n"],"mappings":"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"}