@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,2 +1,2 @@
1
- import"./focus-ring-Bs80iIBN.js";import{c as ee}from"./slot-BQVx1Eew.js";import{t as te}from"./useForkedRef-WoqMqsWE.js";import{t as ne}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{t as re}from"./useHydrated-Dud4JEwp.js";import{r as ie}from"./useFloatingOverlay-BuiI_CCn.js";import{t as ae}from"./useFormField-DH2tlc3e.js";import{t as oe}from"./useOverlayMaxHeight-8mQL2Q6d.js";import{i as e,r as t,t as n}from"./overlayPlacement-Q6bcbXA5.js";import{t as r}from"./useHeldBack-eeTfpa_t.js";import{a as i,i as a,n as o,o as s,r as c,t as l}from"./ComboboxListBox-Db0rSM3w.js";import{t as u}from"./Portal-BTDylxAi.js";import{t as d}from"./renderFormField-_6WswnEX.js";import{t as se}from"./validationClassName-gRGs4KBm.js";import f,{forwardRef as p,useId as ce,useMemo as m,useRef as h}from"react";import g from"classnames";import{useComboBox as le,useFilter as ue,useOverlayPosition as de}from"react-aria";import{useComboBoxState as _}from"react-stately";const v=ee=>null;v.displayName=`ComboboxGroup`;const y=p(({"aria-describedby":p,"aria-label":y,"aria-labelledby":b,children:x,className:S,defaultValue:C,disabled:w,help:T,id:E,invalid:D,invalidFeedback:O,items:k,label:A,name:j,noResultsText:M=`No results found`,onChange:N,placeholder:P,required:F,size:I,valid:L,validFeedback:R,value:z,...B},V)=>{let H=m(()=>k?c(k):o(x,{Group:v,Item:s}),[k,x]),fe=m(()=>i(H),[H]),{contains:pe}=ue({sensitivity:`base`}),U=_({children:a,defaultItems:H,disabledKeys:fe,defaultFilter:pe,defaultValue:C,value:z,onChange:N,allowsEmptyCollection:!0,menuTrigger:`focus`}),W=h(null),me=te(V,W),G=h(null),K=h(null),he=!!F&&U.value==null;ne(()=>{G.current?.setCustomValidity(he?`Select an option from the list.`:``)});let{invalid:q,valid:J}=r(G,{invalid:D,valid:L}),Y=h(null),X=ce(),ge=re(),{describedBy:_e,feedbackId:ve,helpId:ye,inputId:Z,labelId:be,labelledBy:xe}=ae({ariaDescribedBy:p,ariaLabelledBy:b,help:T,id:E,invalid:q,invalidFeedback:O,label:A,valid:J,validFeedback:R}),{inputProps:Q,listBoxProps:Se}=le({"aria-label":y,"aria-labelledby":xe,id:Z,inputRef:G,listBoxRef:K,popoverRef:Y,isDisabled:w,isRequired:F,placeholder:P},U),{overlayProps:Ce,placement:we}=de({targetRef:W,overlayRef:Y,placement:e(`bottom-start`),offset:2,isOpen:U.isOpen,onClose:null});oe(Y,U.isOpen);let Te=ie({close:U.close,isOpen:U.isOpen,triggerRef:W}),{menuStyle:Ee,placementAttr:De}=t(Ce.style,`bottom-start`,we),Oe={...n,...Ee},ke=Q,$=U.collection.size===0,Ae=ee(_e,$&&ge&&X);return d({children:/* @__PURE__ */ f.createElement(f.Fragment,null,/* @__PURE__ */ f.createElement(`div`,{className:g(`form-input`,`combobox`,I,{disabled:w},se(q,J),S),ref:me,...B},/* @__PURE__ */ f.createElement(`input`,{autoComplete:`off`,className:`combobox-value`,...ke,"aria-describedby":Ae,"aria-invalid":q||void 0,"aria-required":void 0,ref:G,required:F||void 0})),/* @__PURE__ */ f.createElement(u,{container:Te},/* @__PURE__ */ f.createElement(`div`,{className:g(`menu`,{show:U.isOpen}),"data-cx-placement":De,style:Oe,hidden:!U.isOpen,ref:Y},/* @__PURE__ */ f.createElement(l,{state:U,listBoxProps:Se,listBoxRef:K}),$&&/* @__PURE__ */ f.createElement(`div`,{className:`combobox-no-results`,id:X,role:`status`},M))),j&&/* @__PURE__ */ f.createElement(`input`,{type:`hidden`,name:j,value:U.value??``,disabled:w})),help:T,ids:{feedback:ve,help:ye,input:Z,label:be},invalid:q,invalidFeedback:O,label:A,valid:J,validFeedback:R})});y.displayName=`Combobox`;export{v as n,y as t};
2
- //# sourceMappingURL=combobox-BQh3uJWB.js.map
1
+ import"./focus-ring-Bs80iIBN.js";import{c as ee}from"./slot-BQVx1Eew.js";import{t as te}from"./useForkedRef-WoqMqsWE.js";import{t as ne}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{t as re}from"./useHydrated-Dud4JEwp.js";import{r as ie}from"./useFloatingOverlay-BuiI_CCn.js";import{t as ae}from"./useFormField-DH2tlc3e.js";import{t as oe}from"./useOverlayMaxHeight-DTgbr4UQ.js";import{i as e,r as t,t as n}from"./overlayPlacement-Q6bcbXA5.js";import{t as r}from"./useHeldBack-eeTfpa_t.js";import{a as i,i as a,n as o,o as s,r as c,t as l}from"./ComboboxListBox-Db0rSM3w.js";import{t as u}from"./Portal-BTDylxAi.js";import{t as d}from"./renderFormField-_6WswnEX.js";import{t as se}from"./validationClassName-gRGs4KBm.js";import f,{forwardRef as p,useId as ce,useMemo as m,useRef as h}from"react";import g from"classnames";import{useComboBox as le,useFilter as ue,useOverlayPosition as de}from"react-aria";import{useComboBoxState as _}from"react-stately";const v=ee=>null;v.displayName=`ComboboxGroup`;const y=p(({"aria-describedby":p,"aria-label":y,"aria-labelledby":b,children:x,className:S,defaultValue:C,disabled:w,help:T,id:E,invalid:D,invalidFeedback:O,items:k,label:A,name:j,noResultsText:M=`No results found`,onChange:N,placeholder:P,required:F,size:I,valid:L,validFeedback:R,value:z,...B},V)=>{let H=m(()=>k?c(k):o(x,{Group:v,Item:s}),[k,x]),fe=m(()=>i(H),[H]),{contains:pe}=ue({sensitivity:`base`}),U=_({children:a,defaultItems:H,disabledKeys:fe,defaultFilter:pe,defaultValue:C,value:z,onChange:N,allowsEmptyCollection:!0,menuTrigger:`focus`}),W=h(null),me=te(V,W),G=h(null),K=h(null),he=!!F&&U.value==null;ne(()=>{G.current?.setCustomValidity(he?`Select an option from the list.`:``)});let{invalid:q,valid:J}=r(G,{invalid:D,valid:L}),Y=h(null),X=ce(),ge=re(),{describedBy:_e,feedbackId:ve,helpId:ye,inputId:Z,labelId:be,labelledBy:xe}=ae({ariaDescribedBy:p,ariaLabelledBy:b,help:T,id:E,invalid:q,invalidFeedback:O,label:A,valid:J,validFeedback:R}),{inputProps:Q,listBoxProps:Se}=le({"aria-label":y,"aria-labelledby":xe,id:Z,inputRef:G,listBoxRef:K,popoverRef:Y,isDisabled:w,isRequired:F,placeholder:P},U),{overlayProps:Ce,placement:we}=de({targetRef:W,overlayRef:Y,placement:e(`bottom-start`),offset:2,isOpen:U.isOpen,onClose:null});oe(Y,U.isOpen);let Te=ie({close:U.close,isOpen:U.isOpen,triggerRef:W}),{menuStyle:Ee,placementAttr:De}=t(Ce.style,`bottom-start`,we),Oe={...n,...Ee},ke=Q,$=U.collection.size===0,Ae=ee(_e,$&&ge&&X);return d({children:/* @__PURE__ */ f.createElement(f.Fragment,null,/* @__PURE__ */ f.createElement(`div`,{className:g(`form-input`,`combobox`,I,{disabled:w},se(q,J),S),ref:me,...B},/* @__PURE__ */ f.createElement(`input`,{autoComplete:`off`,className:`combobox-value`,...ke,"aria-describedby":Ae,"aria-invalid":q||void 0,"aria-required":void 0,ref:G,required:F||void 0})),/* @__PURE__ */ f.createElement(u,{container:Te},/* @__PURE__ */ f.createElement(`div`,{className:g(`menu`,{show:U.isOpen}),"data-cx-placement":De,style:Oe,hidden:!U.isOpen,ref:Y},/* @__PURE__ */ f.createElement(l,{state:U,listBoxProps:Se,listBoxRef:K}),$&&/* @__PURE__ */ f.createElement(`div`,{className:`combobox-no-results`,id:X,role:`status`},M))),j&&/* @__PURE__ */ f.createElement(`input`,{type:`hidden`,name:j,value:U.value??``,disabled:w})),help:T,ids:{feedback:ve,help:ye,input:Z,label:be},invalid:q,invalidFeedback:O,label:A,valid:J,validFeedback:R})});y.displayName=`Combobox`;export{v as n,y as t};
2
+ //# sourceMappingURL=combobox-DNqR4d3V.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"combobox-BQh3uJWB.js","names":["joinIds","useForkedRef","useIsomorphicLayoutEffect","useHydrated","useFloatingOverlay","useFormField","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","COMBOBOX_MENU_OVERLAY_STYLE","useHeldBack","getDisabledKeys","comboboxCollectionChildren","buildEntriesFromChildren","ComboboxItem","buildEntriesFromItemsDef","ComboboxListBox","Portal","renderFormField","validationClassName","React","classNames","ComboboxGroup","Combobox","forwardRef","ariaDescribedBy","ariaLabel","ariaLabelledBy","invalidProp","validProp","rest","entries","useMemo","items","children","disabledKeys","useFilter","state","useComboBoxState","contains","wrapperRef","useRef","forkedWrapperRef","ref","inputRef","listBoxRef","unselected","required","popoverRef","noResultsId","useId","hydrated","useComboBox","labelledBy","inputId","disabled","resolvedPlacement","useOverlayPosition","portalContainer","overlayProps","overlayStyle","menuStyle","inputHtmlProps","inputProps","showNoResults","inputDescribedBy","describedBy","size","invalid","valid","className","placementAttr","noResultsText","name","feedbackId","helpId","labelId"],"sources":["../../src/components/combobox/ComboboxGroup.tsx","../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import { ReactNode } from 'react'\n\nexport interface ComboboxGroupProps {\n /**\n * Items belonging to this group.\n */\n children: ReactNode\n /**\n * Header content for the group (`.menu-header`).\n */\n label: ReactNode\n}\n\n// `ComboboxGroup` is never actually mounted — like `ComboboxItem`, it's read as data by\n// `Combobox`, 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// <Combobox aria-label=\"Language\">\n// <ComboboxGroup label=\"Frontend\">\n// <ComboboxItem id=\"html\">HTML</ComboboxItem>\n// <ComboboxItem id=\"css\">CSS</ComboboxItem>\n// </ComboboxGroup>\n// <ComboboxItem id=\"python\">Python</ComboboxItem>\n// </Combobox>\nexport const ComboboxGroup = (_props: ComboboxGroupProps): null => null\n\nComboboxGroup.displayName = 'ComboboxGroup'\n","import React, {\n forwardRef,\n HTMLAttributes,\n InputHTMLAttributes,\n ReactNode,\n useId,\n useMemo,\n useRef\n} from 'react'\nimport classNames from 'classnames'\nimport { useComboBox, useFilter, useOverlayPosition } from 'react-aria'\nimport { Key, useComboBoxState } from 'react-stately'\n\nimport {\n useFloatingOverlay,\n useForkedRef,\n useFormField,\n useHeldBack,\n useIsomorphicLayoutEffect,\n useOverlayMaxHeight\n} from '../../hooks'\nimport { useHydrated } from '../../hooks/useHydrated'\nimport { joinIds } from '../../utils/idRefs'\nimport {\n buildEntriesFromChildren,\n buildEntriesFromItemsDef,\n ComboboxEntry,\n comboboxCollectionChildren,\n getDisabledKeys\n} from './comboboxCollection'\nimport {\n COMBOBOX_MENU_OVERLAY_STYLE,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { Portal } from '../portal/Portal'\nimport { validationClassName } from '../../utils/validationClassName'\nimport { renderFormField } from '../form-field/renderFormField'\nimport { MenuItemsDef } from '../menu/MenuItemDef'\nimport { ComboboxGroup } from './ComboboxGroup'\nimport { ComboboxItem } from './ComboboxItem'\nimport { ComboboxListBox } from './ComboboxListBox'\n\nexport interface ComboboxProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue'\n> {\n /**\n * An accessible label for the combobox, used when there's no visible `<label>`.\n */\n 'aria-label'?: string\n /**\n * Identifies a visible `<label>` element for the combobox.\n */\n 'aria-labelledby'?: string\n /**\n * `ComboboxItem` elements, optionally wrapped in `ComboboxGroup` — read as data by\n * `Combobox` 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 (uncontrolled).\n */\n defaultValue?: Key | null\n /**\n * Prevents the combobox from being focused or interacted with.\n */\n disabled?: boolean\n /**\n * A description for the field, rendered below the combobox.\n */\n help?: ReactNode\n /**\n * `id` forwarded to the input element — useful for pairing with a `<label for>`.\n */\n id?: string\n /**\n * Set component validation state to invalid. Left unset, the component shows as invalid by itself\n * from a submit it held back (an empty `required` one, say) until it no longer would, or its\n * form is reset. Set it, to `false` too, and it alone decides.\n */\n invalid?: boolean\n /**\n * An error message for the field, rendered below the combobox when `invalid` is set, and after a\n * submit the field held back, until it no longer would.\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 (dividers aren't\n * meaningful for a listbox/option collection) — use `ComboboxGroup` composition instead if\n * you need finer control over grouping. An entry's `href`/`onClick` are `Menu`-only and are not\n * read here — use `onChange` to react to the selection instead.\n */\n items?: MenuItemsDef\n /**\n * The field's caption, rendered as a `FormLabel` associated with the input.\n */\n label?: ReactNode\n /**\n * `name` of an auto-created hidden input, kept in sync with the selection, for native form\n * submission. Omit to skip creating one.\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 selected option changes.\n */\n onChange?: (value: Key | null) => void\n /**\n * Placeholder shown in the input when nothing is selected.\n */\n placeholder?: string\n /**\n * Toggle the required state for the component. A required combobox with no option selected\n * holds its form back from submitting, and takes focus: text typed without selecting an option\n * is not a value.\n */\n required?: boolean\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 combobox when `valid` is set.\n */\n validFeedback?: ReactNode\n /**\n * The selected option's id (controlled).\n */\n value?: Key | null\n}\n\n// See `unselected`.\nconst UNSELECTED_TEXT_MESSAGE = 'Select an option from the list.'\n\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n children,\n className,\n defaultValue,\n disabled,\n help,\n id,\n invalid: invalidProp,\n invalidFeedback,\n items,\n label,\n name,\n noResultsText = 'No results found',\n onChange,\n placeholder,\n required,\n size,\n valid: validProp,\n validFeedback,\n value,\n ...rest\n }: ComboboxProps,\n ref\n ): ReactNode => {\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: ComboboxGroup, Item: ComboboxItem }),\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 const state = useComboBoxState<ComboboxEntry>({\n children: comboboxCollectionChildren,\n defaultItems: entries,\n disabledKeys,\n defaultFilter: contains,\n defaultValue,\n value,\n onChange,\n allowsEmptyCollection: true,\n // Matches chassis-css's vanilla combobox.js: the menu opens on focus, not only once the\n // user starts typing.\n menuTrigger: 'focus'\n })\n\n const wrapperRef = useRef<HTMLDivElement>(null)\n const forkedWrapperRef = useForkedRef(ref, wrapperRef)\n const inputRef = useRef<HTMLInputElement>(null)\n const listBoxRef = useRef<HTMLElement>(null)\n\n // `required` asks for what the form submits under `name`: the selected option's id, not the\n // text in the input. The native attribute on the input covers an empty one, and the two agree\n // nearly always, since react-stately puts the selection's text back, none without one, when\n // the list closes: on blur, Enter and Escape. Not while the user is still typing, though, and\n // a form submitted then (a shortcut or a timer that calls `requestSubmit()`) would go with\n // text in the input and nothing under `name`. A custom validity covers that: with nothing\n // selected the input is invalid whatever its text. The message is never shown: react-aria\n // cancels the input's `invalid` event, which keeps a browser's bubble away, and focuses the\n // input instead.\n //\n // Set after each render, as the input may be a new one, in a layout effect declared before\n // `useHeldBack`, whose own layout effect reads the validity after each render, and for an\n // empty input too: the hook's `input` listener reads\n // it before the render a keystroke causes, where the first character typed would have made\n // an empty input valid.\n const unselected = Boolean(required) && state.value == null\n useIsomorphicLayoutEffect(() => {\n inputRef.current?.setCustomValidity(unselected ? UNSELECTED_TEXT_MESSAGE : '')\n })\n\n // Shown as invalid from a submit it held back until it no longer would (`useHeldBack`):\n // react-aria cancels the browser's own message, and the form stayed with nothing to say why.\n const { invalid, valid } = useHeldBack(inputRef, { invalid: invalidProp, valid: validProp })\n const popoverRef = useRef<HTMLDivElement>(null)\n const noResultsId = useId()\n const hydrated = useHydrated()\n\n const { describedBy, feedbackId, helpId, inputId, labelId, labelledBy } = useFormField({\n ariaDescribedBy,\n ariaLabelledBy,\n help,\n id,\n invalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n\n const { inputProps, listBoxProps } = useComboBox<ComboboxEntry>(\n {\n 'aria-label': ariaLabel,\n 'aria-labelledby': labelledBy,\n id: inputId,\n inputRef,\n listBoxRef,\n popoverRef,\n isDisabled: disabled,\n isRequired: required,\n placeholder\n },\n state\n )\n\n const { overlayProps, placement: resolvedPlacement } = useOverlayPosition({\n targetRef: wrapperRef,\n overlayRef: popoverRef,\n placement: toAriaPlacement('bottom-start'),\n offset: 2,\n isOpen: state.isOpen,\n // Leaving `onClose` unset doesn't actually disable react-aria's close-on-scroll listener —\n // only an explicit `null` does. Matches the fix already applied to `Autocomplete`'s identical\n // positioning call.\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` — an inline-rendered panel gets clipped by any\n // ancestor with `overflow: hidden`/`auto` (a `ModalBody`, a scrollable card, a table cell), and\n // `Combobox` is commonly composed inside exactly those. See `COMBOBOX_MENU_OVERLAY_STYLE` for\n // the styling this trades away by leaving the DOM position `.combobox + .menu` relies on.\n const portalContainer = useFloatingOverlay({\n close: state.close,\n isOpen: state.isOpen,\n triggerRef: wrapperRef\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 inputHtmlProps = inputProps as InputHTMLAttributes<HTMLInputElement>\n const showNoResults = state.collection.size === 0\n // Merges the no-results message into the input's own description (for AT that reads\n // descriptions on demand) in addition to the `aria-live` region below (for AT that announces\n // live-region changes proactively as the user types) — belt and braces, since screen reader\n // support for announcing a freshly-mounted live region is inconsistent. Only once hydrated:\n // the message is inside `Portal`, which renders nothing on the server and while hydrating, so\n // an empty combobox's server HTML referred to an id no element had.\n const inputDescribedBy = joinIds(describedBy, showNoResults && hydrated && noResultsId)\n\n return renderFormField({\n children: (\n <>\n <div\n className={classNames(\n 'form-input',\n 'combobox',\n size,\n { disabled },\n validationClassName(invalid, valid),\n className\n )}\n ref={forkedWrapperRef}\n {...rest}\n >\n <input\n autoComplete=\"off\"\n className=\"combobox-value\"\n {...inputHtmlProps}\n aria-describedby={inputDescribedBy}\n aria-invalid={invalid || undefined}\n // The native `required` below says the same.\n aria-required={undefined}\n ref={inputRef}\n // On the visible input, not the hidden one that carries `name`: a hidden input is\n // barred from constraint validation (FORMS.md, gotcha 9). react-aria writes\n // `aria-required` alone, which no form checks. A disabled input isn't validated;\n // the combobox has no read-only state to leave out.\n required={required || undefined}\n />\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 <ComboboxListBox state={state} listBoxProps={listBoxProps} listBoxRef={listBoxRef} />\n {showNoResults && (\n <div className=\"combobox-no-results\" id={noResultsId} role=\"status\">\n {noResultsText}\n </div>\n )}\n </div>\n </Portal>\n {name && (\n <input type=\"hidden\" name={name} value={state.value ?? ''} disabled={disabled} />\n )}\n </>\n ),\n help,\n ids: { feedback: feedbackId, help: helpId, input: inputId, label: labelId },\n invalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n }\n)\n\nCombobox.displayName = 'Combobox'\n"],"mappings":"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"}
1
+ {"version":3,"file":"combobox-DNqR4d3V.js","names":["joinIds","useForkedRef","useIsomorphicLayoutEffect","useHydrated","useFloatingOverlay","useFormField","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","COMBOBOX_MENU_OVERLAY_STYLE","useHeldBack","getDisabledKeys","comboboxCollectionChildren","buildEntriesFromChildren","ComboboxItem","buildEntriesFromItemsDef","ComboboxListBox","Portal","renderFormField","validationClassName","React","classNames","ComboboxGroup","Combobox","forwardRef","ariaDescribedBy","ariaLabel","ariaLabelledBy","invalidProp","validProp","rest","entries","useMemo","items","children","disabledKeys","useFilter","state","useComboBoxState","contains","wrapperRef","useRef","forkedWrapperRef","ref","inputRef","listBoxRef","unselected","required","popoverRef","noResultsId","useId","hydrated","useComboBox","labelledBy","inputId","disabled","resolvedPlacement","useOverlayPosition","portalContainer","overlayProps","overlayStyle","menuStyle","inputHtmlProps","inputProps","showNoResults","inputDescribedBy","describedBy","size","invalid","valid","className","placementAttr","noResultsText","name","feedbackId","helpId","labelId"],"sources":["../../src/components/combobox/ComboboxGroup.tsx","../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import { ReactNode } from 'react'\n\nexport interface ComboboxGroupProps {\n /**\n * Items belonging to this group.\n */\n children: ReactNode\n /**\n * Header content for the group (`.menu-header`).\n */\n label: ReactNode\n}\n\n// `ComboboxGroup` is never actually mounted — like `ComboboxItem`, it's read as data by\n// `Combobox`, 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// <Combobox aria-label=\"Language\">\n// <ComboboxGroup label=\"Frontend\">\n// <ComboboxItem id=\"html\">HTML</ComboboxItem>\n// <ComboboxItem id=\"css\">CSS</ComboboxItem>\n// </ComboboxGroup>\n// <ComboboxItem id=\"python\">Python</ComboboxItem>\n// </Combobox>\nexport const ComboboxGroup = (_props: ComboboxGroupProps): null => null\n\nComboboxGroup.displayName = 'ComboboxGroup'\n","import React, {\n forwardRef,\n HTMLAttributes,\n InputHTMLAttributes,\n ReactNode,\n useId,\n useMemo,\n useRef\n} from 'react'\nimport classNames from 'classnames'\nimport { useComboBox, useFilter, useOverlayPosition } from 'react-aria'\nimport { Key, useComboBoxState } from 'react-stately'\n\nimport {\n useFloatingOverlay,\n useForkedRef,\n useFormField,\n useHeldBack,\n useIsomorphicLayoutEffect,\n useOverlayMaxHeight\n} from '../../hooks'\nimport { useHydrated } from '../../hooks/useHydrated'\nimport { joinIds } from '../../utils/idRefs'\nimport {\n buildEntriesFromChildren,\n buildEntriesFromItemsDef,\n ComboboxEntry,\n comboboxCollectionChildren,\n getDisabledKeys\n} from './comboboxCollection'\nimport {\n COMBOBOX_MENU_OVERLAY_STYLE,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { Portal } from '../portal/Portal'\nimport { validationClassName } from '../../utils/validationClassName'\nimport { renderFormField } from '../form-field/renderFormField'\nimport { MenuItemsDef } from '../menu/MenuItemDef'\nimport { ComboboxGroup } from './ComboboxGroup'\nimport { ComboboxItem } from './ComboboxItem'\nimport { ComboboxListBox } from './ComboboxListBox'\n\nexport interface ComboboxProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue'\n> {\n /**\n * An accessible label for the combobox, used when there's no visible `<label>`.\n */\n 'aria-label'?: string\n /**\n * Identifies a visible `<label>` element for the combobox.\n */\n 'aria-labelledby'?: string\n /**\n * `ComboboxItem` elements, optionally wrapped in `ComboboxGroup` — read as data by\n * `Combobox` 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 (uncontrolled).\n */\n defaultValue?: Key | null\n /**\n * Prevents the combobox from being focused or interacted with.\n */\n disabled?: boolean\n /**\n * A description for the field, rendered below the combobox.\n */\n help?: ReactNode\n /**\n * `id` forwarded to the input element — useful for pairing with a `<label for>`.\n */\n id?: string\n /**\n * Set component validation state to invalid. Left unset, the component shows as invalid by itself\n * from a submit it held back (an empty `required` one, say) until it no longer would, or its\n * form is reset. Set it, to `false` too, and it alone decides.\n */\n invalid?: boolean\n /**\n * An error message for the field, rendered below the combobox when `invalid` is set, and after a\n * submit the field held back, until it no longer would.\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 (dividers aren't\n * meaningful for a listbox/option collection) — use `ComboboxGroup` composition instead if\n * you need finer control over grouping. An entry's `href`/`onClick` are `Menu`-only and are not\n * read here — use `onChange` to react to the selection instead.\n */\n items?: MenuItemsDef\n /**\n * The field's caption, rendered as a `FormLabel` associated with the input.\n */\n label?: ReactNode\n /**\n * `name` of an auto-created hidden input, kept in sync with the selection, for native form\n * submission. Omit to skip creating one.\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 selected option changes.\n */\n onChange?: (value: Key | null) => void\n /**\n * Placeholder shown in the input when nothing is selected.\n */\n placeholder?: string\n /**\n * Toggle the required state for the component. A required combobox with no option selected\n * holds its form back from submitting, and takes focus: text typed without selecting an option\n * is not a value.\n */\n required?: boolean\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 combobox when `valid` is set.\n */\n validFeedback?: ReactNode\n /**\n * The selected option's id (controlled).\n */\n value?: Key | null\n}\n\n// See `unselected`.\nconst UNSELECTED_TEXT_MESSAGE = 'Select an option from the list.'\n\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n 'aria-describedby': ariaDescribedBy,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n children,\n className,\n defaultValue,\n disabled,\n help,\n id,\n invalid: invalidProp,\n invalidFeedback,\n items,\n label,\n name,\n noResultsText = 'No results found',\n onChange,\n placeholder,\n required,\n size,\n valid: validProp,\n validFeedback,\n value,\n ...rest\n }: ComboboxProps,\n ref\n ): ReactNode => {\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: ComboboxGroup, Item: ComboboxItem }),\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 const state = useComboBoxState<ComboboxEntry>({\n children: comboboxCollectionChildren,\n defaultItems: entries,\n disabledKeys,\n defaultFilter: contains,\n defaultValue,\n value,\n onChange,\n allowsEmptyCollection: true,\n // Matches chassis-css's vanilla combobox.js: the menu opens on focus, not only once the\n // user starts typing.\n menuTrigger: 'focus'\n })\n\n const wrapperRef = useRef<HTMLDivElement>(null)\n const forkedWrapperRef = useForkedRef(ref, wrapperRef)\n const inputRef = useRef<HTMLInputElement>(null)\n const listBoxRef = useRef<HTMLElement>(null)\n\n // `required` asks for what the form submits under `name`: the selected option's id, not the\n // text in the input. The native attribute on the input covers an empty one, and the two agree\n // nearly always, since react-stately puts the selection's text back, none without one, when\n // the list closes: on blur, Enter and Escape. Not while the user is still typing, though, and\n // a form submitted then (a shortcut or a timer that calls `requestSubmit()`) would go with\n // text in the input and nothing under `name`. A custom validity covers that: with nothing\n // selected the input is invalid whatever its text. The message is never shown: react-aria\n // cancels the input's `invalid` event, which keeps a browser's bubble away, and focuses the\n // input instead.\n //\n // Set after each render, as the input may be a new one, in a layout effect declared before\n // `useHeldBack`, whose own layout effect reads the validity after each render, and for an\n // empty input too: the hook's `input` listener reads\n // it before the render a keystroke causes, where the first character typed would have made\n // an empty input valid.\n const unselected = Boolean(required) && state.value == null\n useIsomorphicLayoutEffect(() => {\n inputRef.current?.setCustomValidity(unselected ? UNSELECTED_TEXT_MESSAGE : '')\n })\n\n // Shown as invalid from a submit it held back until it no longer would (`useHeldBack`):\n // react-aria cancels the browser's own message, and the form stayed with nothing to say why.\n const { invalid, valid } = useHeldBack(inputRef, { invalid: invalidProp, valid: validProp })\n const popoverRef = useRef<HTMLDivElement>(null)\n const noResultsId = useId()\n const hydrated = useHydrated()\n\n const { describedBy, feedbackId, helpId, inputId, labelId, labelledBy } = useFormField({\n ariaDescribedBy,\n ariaLabelledBy,\n help,\n id,\n invalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n\n const { inputProps, listBoxProps } = useComboBox<ComboboxEntry>(\n {\n 'aria-label': ariaLabel,\n 'aria-labelledby': labelledBy,\n id: inputId,\n inputRef,\n listBoxRef,\n popoverRef,\n isDisabled: disabled,\n isRequired: required,\n placeholder\n },\n state\n )\n\n const { overlayProps, placement: resolvedPlacement } = useOverlayPosition({\n targetRef: wrapperRef,\n overlayRef: popoverRef,\n placement: toAriaPlacement('bottom-start'),\n offset: 2,\n isOpen: state.isOpen,\n // Leaving `onClose` unset doesn't actually disable react-aria's close-on-scroll listener —\n // only an explicit `null` does. Matches the fix already applied to `Autocomplete`'s identical\n // positioning call.\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` — an inline-rendered panel gets clipped by any\n // ancestor with `overflow: hidden`/`auto` (a `ModalBody`, a scrollable card, a table cell), and\n // `Combobox` is commonly composed inside exactly those. See `COMBOBOX_MENU_OVERLAY_STYLE` for\n // the styling this trades away by leaving the DOM position `.combobox + .menu` relies on.\n const portalContainer = useFloatingOverlay({\n close: state.close,\n isOpen: state.isOpen,\n triggerRef: wrapperRef\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 inputHtmlProps = inputProps as InputHTMLAttributes<HTMLInputElement>\n const showNoResults = state.collection.size === 0\n // Merges the no-results message into the input's own description (for AT that reads\n // descriptions on demand) in addition to the `aria-live` region below (for AT that announces\n // live-region changes proactively as the user types) — belt and braces, since screen reader\n // support for announcing a freshly-mounted live region is inconsistent. Only once hydrated:\n // the message is inside `Portal`, which renders nothing on the server and while hydrating, so\n // an empty combobox's server HTML referred to an id no element had.\n const inputDescribedBy = joinIds(describedBy, showNoResults && hydrated && noResultsId)\n\n return renderFormField({\n children: (\n <>\n <div\n className={classNames(\n 'form-input',\n 'combobox',\n size,\n { disabled },\n validationClassName(invalid, valid),\n className\n )}\n ref={forkedWrapperRef}\n {...rest}\n >\n <input\n autoComplete=\"off\"\n className=\"combobox-value\"\n {...inputHtmlProps}\n aria-describedby={inputDescribedBy}\n aria-invalid={invalid || undefined}\n // The native `required` below says the same.\n aria-required={undefined}\n ref={inputRef}\n // On the visible input, not the hidden one that carries `name`: a hidden input is\n // barred from constraint validation (FORMS.md, gotcha 9). react-aria writes\n // `aria-required` alone, which no form checks. A disabled input isn't validated;\n // the combobox has no read-only state to leave out.\n required={required || undefined}\n />\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 <ComboboxListBox state={state} listBoxProps={listBoxProps} listBoxRef={listBoxRef} />\n {showNoResults && (\n <div className=\"combobox-no-results\" id={noResultsId} role=\"status\">\n {noResultsText}\n </div>\n )}\n </div>\n </Portal>\n {name && (\n <input type=\"hidden\" name={name} value={state.value ?? ''} disabled={disabled} />\n )}\n </>\n ),\n help,\n ids: { feedback: feedbackId, help: helpId, input: inputId, label: labelId },\n invalid,\n invalidFeedback,\n label,\n valid,\n validFeedback\n })\n }\n)\n\nCombobox.displayName = 'Combobox'\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import"./focus-ring-Bs80iIBN.js";import{y as e}from"./slot-BQVx1Eew.js";import{t}from"./useForkedRef-WoqMqsWE.js";import{t as n}from"./polymorphic-CZIFszAy.js";import{t as r}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{n as i}from"./overlayStack-BXtTGCRm.js";import{r as ee}from"./useFloatingOverlay-BuiI_CCn.js";import{t as te}from"./useOpenStateProps-BhjSQ3f6.js";import{t as ne}from"./useOverlayMaxHeight-8mQL2Q6d.js";import{i as re,r as a}from"./overlayPlacement-Q6bcbXA5.js";import{n as o}from"./insideEvents-CWcNrMu7.js";import{n as s,r as c}from"./Menu-264aGoBR.js";import l,{useEffect as u,useId as ie,useMemo as ae,useRef as d,useState as oe}from"react";import f from"classnames";import{mergeProps as p,useLocale as m,useOverlayPosition as h}from"react-aria";import{useMenuTriggerState as se}from"react-stately";const ce=(e,t)=>({x:e,y:t,top:t,left:e,right:e,bottom:t,width:0,height:0,toJSON:()=>({x:e,y:t,width:0,height:0})});function g({children:n,autoClose:g=!0,className:_,component:le,defaultVisible:ue,disabled:v=!1,id:y,onHide:b,onShow:x,onVisibleChange:de,visible:fe,...pe},me){let S=le??`div`,C=ie(),w=e(S)??y??`${C}-trigger`,T=`${C}-menu`,E=d(null),D=t(me,E);r(()=>{E.current?.style.setProperty(`-webkit-touch-callout`,`none`)},[]);let O=d(null),k=d(null),A=d(null),j=d(/* @__PURE__ */ new Map),M=(e,t)=>{t?j.current.set(e,t):j.current.delete(e)},N=se(te({defaultVisible:ue,onVisibleChange:de,visible:fe},`ContextMenu`)),P=d(null),[F,I]=oe(0),L=d(null),R=e=>{v||(P.current=e,N.isOpen||(L.current=document.activeElement),I(e=>e+1),N.open(`first`))},z=()=>{L.current=null,N.close()},B=()=>N.close();u(()=>{if(N.isOpen)return;let e=L.current;if(L.current=null,!e||!document.contains(e))return;let t=document.activeElement,n=!t||t===document.body,r=!!t&&!!O.current?.contains(t);(n||r)&&e.focus()},[N.isOpen]);let V=ee({close:N.close,isOpen:N.isOpen,onHide:b,onShow:x,triggerRef:E}),{direction:he}=m(),H=he===`rtl`?`bottom-end`:`bottom-start`,{overlayProps:ge,placement:_e,updatePosition:ve}=h({targetRef:E,overlayRef:O,placement:re(H),containerPadding:8,isOpen:N.isOpen,onClose:null,getTargetRect:()=>{let e=P.current;if(e)return e.kind===`point`?ce(e.x,e.y):e.element.getBoundingClientRect()}});ne(O,N.isOpen),r(()=>{N.isOpen&&ve()},[N.isOpen,F]);let{menuStyle:U,placementAttr:W}=a(ge.style,H,_e);u(()=>{if(!N.isOpen||g===!1)return;let e=e=>!!O.current?.contains(e)||Array.from(j.current.values()).some(t=>t.contains(e)),t=e=>o(e,O),n=n=>{let r=n.target;e(r)||t(n)||g===`inside`||n.button===2&&E.current?.contains(r)||z()},r=t=>{let n=t.target;e(n)&&g!==`outside`&&!c.has(t)&&(/input|select|option|textarea|form/i.test(n.tagName??``)||B())},i=n=>{n.key!==`Tab`||e(n.target)||t(n)||z()};return window.addEventListener(`pointerdown`,n),window.addEventListener(`click`,r),window.addEventListener(`keyup`,i),()=>{window.removeEventListener(`pointerdown`,n),window.removeEventListener(`click`,r),window.removeEventListener(`keyup`,i)}},[N.isOpen,g]),u(()=>{if(N.isOpen)return i({nodes:()=>[O.current,E.current],onEscape:B})},[N.isOpen]);let G=d(v);u(()=>{v&&!G.current&&z(),G.current=v},[v]);let K=e=>e.currentTarget.contains(e.target),ye=e=>{v||e.defaultPrevented||(e.preventDefault(),K(e)&&R({kind:`point`,x:e.clientX,y:e.clientY}))},q=e=>e.key===`ContextMenu`||e.key===`F10`&&e.shiftKey,be=e=>{v||e.defaultPrevented||!q(e)||(e.preventDefault(),K(e)&&R({kind:`element`,element:e.target}))},xe=e=>{!v&&q(e)&&e.preventDefault()},J=d(null),Y=d(null),Se=()=>{let e=E.current;e&&Y.current!==null&&(e.style.setProperty(`-webkit-user-select`,Y.current),e.style.setProperty(`user-select`,Y.current),Y.current=null)},X=()=>{J.current&&=(window.clearTimeout(J.current.timer),null)},Z=()=>{X(),Se()},Q=d(null),$=()=>{Q.current?.(),Q.current=null},Ce=()=>{$();let e=e=>{e.preventDefault(),e.stopPropagation(),$()};window.addEventListener(`click`,e,{capture:!0});let t=window.setTimeout($,1e3);Q.current=()=>{window.removeEventListener(`click`,e,{capture:!0}),window.clearTimeout(t)}};u(()=>()=>{Z(),$()},[]);let we=e=>{if(v||e.pointerType===`mouse`||!K(e))return;Z();let t=e.currentTarget;Y.current=t.style.getPropertyValue(`user-select`),t.style.setProperty(`-webkit-user-select`,`none`),t.style.setProperty(`user-select`,`none`);let{clientX:n,clientY:r}=e;J.current={x:n,y:r,timer:window.setTimeout(()=>{J.current=null,Ce(),R({kind:`point`,x:n,y:r})},500)}},Te=e=>{let t=J.current;t&&Math.hypot(e.clientX-t.x,e.clientY-t.y)>10&&X()},Ee=ae(()=>({autoClose:g,close:B,container:V??!0,focusStrategy:N.focusStrategy,hide:z,menuId:T,menuStyle:U,menuTriggerProps:{},overlayRef:O,placementAttr:W,portalContainer:V,reference:`toggle`,registerOverlay:M,show:e=>N.open(e??`first`),targetRef:A,toggle:e=>N.toggle(e??`first`),toggleNodeRef:k,triggerId:w,visible:N.isOpen}),[g,T,U,W,V,N.focusStrategy,N.isOpen,w]);return/* @__PURE__ */ l.createElement(s.Provider,{value:Ee},/* @__PURE__ */ l.createElement(S,{id:w,className:f(`context-menu`,_),...p({onContextMenu:ye,onKeyDown:be,onKeyUp:xe,onPointerDown:we,onPointerMove:Te,onPointerUp:Z,onPointerCancel:Z,onPointerLeave:Z},pe),ref:D},n))}const _=n(g,`ContextMenu`);export{_ as t};
2
- //# sourceMappingURL=context-menu-8KIuH4cJ.js.map
1
+ import"./focus-ring-Bs80iIBN.js";import{y as e}from"./slot-BQVx1Eew.js";import{t}from"./useForkedRef-WoqMqsWE.js";import{t as n}from"./polymorphic-CZIFszAy.js";import{t as r}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{n as i}from"./overlayStack-BXtTGCRm.js";import{r as ee}from"./useFloatingOverlay-BuiI_CCn.js";import{t as te}from"./useOpenStateProps-BhjSQ3f6.js";import{t as ne}from"./useOverlayMaxHeight-DTgbr4UQ.js";import{i as re,r as a}from"./overlayPlacement-Q6bcbXA5.js";import{n as o}from"./insideEvents-CWcNrMu7.js";import{n as s,r as c}from"./Menu-BiE9CzNk.js";import l,{useEffect as u,useId as ie,useMemo as ae,useRef as d,useState as oe}from"react";import f from"classnames";import{mergeProps as p,useLocale as m,useOverlayPosition as h}from"react-aria";import{useMenuTriggerState as se}from"react-stately";const ce=(e,t)=>({x:e,y:t,top:t,left:e,right:e,bottom:t,width:0,height:0,toJSON:()=>({x:e,y:t,width:0,height:0})});function g({children:n,autoClose:g=!0,className:_,component:le,defaultVisible:ue,disabled:v=!1,id:y,onHide:b,onShow:x,onVisibleChange:de,visible:fe,...pe},me){let S=le??`div`,C=ie(),w=e(S)??y??`${C}-trigger`,T=`${C}-menu`,E=d(null),D=t(me,E);r(()=>{E.current?.style.setProperty(`-webkit-touch-callout`,`none`)},[]);let O=d(null),k=d(null),A=d(null),j=d(/* @__PURE__ */ new Map),M=(e,t)=>{t?j.current.set(e,t):j.current.delete(e)},N=se(te({defaultVisible:ue,onVisibleChange:de,visible:fe},`ContextMenu`)),P=d(null),[F,I]=oe(0),L=d(null),R=e=>{v||(P.current=e,N.isOpen||(L.current=document.activeElement),I(e=>e+1),N.open(`first`))},z=()=>{L.current=null,N.close()},B=()=>N.close();u(()=>{if(N.isOpen)return;let e=L.current;if(L.current=null,!e||!document.contains(e))return;let t=document.activeElement,n=!t||t===document.body,r=!!t&&!!O.current?.contains(t);(n||r)&&e.focus()},[N.isOpen]);let V=ee({close:N.close,isOpen:N.isOpen,onHide:b,onShow:x,triggerRef:E}),{direction:he}=m(),H=he===`rtl`?`bottom-end`:`bottom-start`,{overlayProps:ge,placement:_e,updatePosition:ve}=h({targetRef:E,overlayRef:O,placement:re(H),containerPadding:8,isOpen:N.isOpen,onClose:null,getTargetRect:()=>{let e=P.current;if(e)return e.kind===`point`?ce(e.x,e.y):e.element.getBoundingClientRect()}});ne(O,N.isOpen),r(()=>{N.isOpen&&ve()},[N.isOpen,F]);let{menuStyle:U,placementAttr:W}=a(ge.style,H,_e);u(()=>{if(!N.isOpen||g===!1)return;let e=e=>!!O.current?.contains(e)||Array.from(j.current.values()).some(t=>t.contains(e)),t=e=>o(e,O),n=n=>{let r=n.target;e(r)||t(n)||g===`inside`||n.button===2&&E.current?.contains(r)||z()},r=t=>{let n=t.target;e(n)&&g!==`outside`&&!c.has(t)&&(/input|select|option|textarea|form/i.test(n.tagName??``)||B())},i=n=>{n.key!==`Tab`||e(n.target)||t(n)||z()};return window.addEventListener(`pointerdown`,n),window.addEventListener(`click`,r),window.addEventListener(`keyup`,i),()=>{window.removeEventListener(`pointerdown`,n),window.removeEventListener(`click`,r),window.removeEventListener(`keyup`,i)}},[N.isOpen,g]),u(()=>{if(N.isOpen)return i({nodes:()=>[O.current,E.current],onEscape:B})},[N.isOpen]);let G=d(v);u(()=>{v&&!G.current&&z(),G.current=v},[v]);let K=e=>e.currentTarget.contains(e.target),ye=e=>{v||e.defaultPrevented||(e.preventDefault(),K(e)&&R({kind:`point`,x:e.clientX,y:e.clientY}))},q=e=>e.key===`ContextMenu`||e.key===`F10`&&e.shiftKey,be=e=>{v||e.defaultPrevented||!q(e)||(e.preventDefault(),K(e)&&R({kind:`element`,element:e.target}))},xe=e=>{!v&&q(e)&&e.preventDefault()},J=d(null),Y=d(null),Se=()=>{let e=E.current;e&&Y.current!==null&&(e.style.setProperty(`-webkit-user-select`,Y.current),e.style.setProperty(`user-select`,Y.current),Y.current=null)},X=()=>{J.current&&=(window.clearTimeout(J.current.timer),null)},Z=()=>{X(),Se()},Q=d(null),$=()=>{Q.current?.(),Q.current=null},Ce=()=>{$();let e=e=>{e.preventDefault(),e.stopPropagation(),$()};window.addEventListener(`click`,e,{capture:!0});let t=window.setTimeout($,1e3);Q.current=()=>{window.removeEventListener(`click`,e,{capture:!0}),window.clearTimeout(t)}};u(()=>()=>{Z(),$()},[]);let we=e=>{if(v||e.pointerType===`mouse`||!K(e))return;Z();let t=e.currentTarget;Y.current=t.style.getPropertyValue(`user-select`),t.style.setProperty(`-webkit-user-select`,`none`),t.style.setProperty(`user-select`,`none`);let{clientX:n,clientY:r}=e;J.current={x:n,y:r,timer:window.setTimeout(()=>{J.current=null,Ce(),R({kind:`point`,x:n,y:r})},500)}},Te=e=>{let t=J.current;t&&Math.hypot(e.clientX-t.x,e.clientY-t.y)>10&&X()},Ee=ae(()=>({autoClose:g,close:B,container:V??!0,focusStrategy:N.focusStrategy,hide:z,menuId:T,menuStyle:U,menuTriggerProps:{},overlayRef:O,placementAttr:W,portalContainer:V,reference:`toggle`,registerOverlay:M,show:e=>N.open(e??`first`),targetRef:A,toggle:e=>N.toggle(e??`first`),toggleNodeRef:k,triggerId:w,visible:N.isOpen}),[g,T,U,W,V,N.focusStrategy,N.isOpen,w]);return/* @__PURE__ */ l.createElement(s.Provider,{value:Ee},/* @__PURE__ */ l.createElement(S,{id:w,className:f(`context-menu`,_),...p({onContextMenu:ye,onKeyDown:be,onKeyUp:xe,onPointerDown:we,onPointerMove:Te,onPointerUp:Z,onPointerCancel:Z,onPointerLeave:Z},pe),ref:D},n))}const _=n(g,`ContextMenu`);export{_ as t};
2
+ //# sourceMappingURL=context-menu-D3DNFN-P.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu-8KIuH4cJ.js","names":["resolveSlottedId","createPolymorphicComponent","useIsomorphicLayoutEffect","pushOverlay","useFloatingOverlay","useOpenStateProps","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","isEventInside","MenuContext","menuToggleClicks","React","classNames","pointRect","y","x","ContextMenuRender","rest","Component","component","generatedId","useId","triggerId","id","menuId","regionRef","useRef","forkedRef","useForkedRef","ref","overlayRef","toggleNodeRef","targetRef","submenuOverlaysRef","registerOverlay","node","overlayId","state","useMenuTriggerState","anchorRef","anchorVersion","setAnchorVersion","useState","restoreFocusRef","openAt","disabled","anchor","version","hide","close","useEffect","element","active","focusIsLoose","focusIsInMenu","portalContainer","useLocale","placement","direction","resolvedPlacement","useOverlayPosition","updatePosition","overlayProps","autoClose","isInMenu","target","isInOverlayOfMenu","event","handlePointerDown","handleClick","handleKeyUp","wasDisabledRef","isInRegion","handleContextMenu","isContextMenuKey","handleKeyDown","longPressRef","userSelectRef","restoreUserSelect","region","cancelLongPress","endPress","clickSwallowRef","stopSwallowingClicks","swallowNextClick","swallow","timer","handlePointerMove","press","contextValue","useMemo","focusStrategy","menuStyle","placementAttr","className","mergeProps","children","ContextMenu"],"sources":["../../src/components/context-menu/ContextMenu.tsx"],"sourcesContent":["import React, {\n ElementType,\n ForwardRefRenderFunction,\n ReactElement,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps, useLocale, 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 { resolveSlottedId } from '../../utils/elementKind'\nimport { isEventInside } from '../../utils/insideEvents'\nimport { resolveMenuOverlayPositioning, toAriaPlacement } from '../../utils/overlayPlacement'\nimport { pushOverlay } from '../../utils/overlayStack'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\nimport {\n MenuAutoClose,\n MenuContext,\n MenuContextProps,\n MenuFocusStrategy,\n menuToggleClicks\n} from '../menu/Menu'\n\n// How long a touch or pen has to stay down, and how far it may travel meanwhile, for a long\n// press. react-aria's `useLongPress` uses the same threshold; it isn't used here because its\n// `usePress` prevents the default of key and pointer events on the element it is given, which\n// would break the buttons and links inside a region.\nconst LONG_PRESS_MS = 500\nconst LONG_PRESS_TOLERANCE_PX = 10\n// iOS emits a click when the finger that long-pressed lifts, on whatever is under it by then: the\n// first item of the menu that has just opened at the finger. A click this soon after a long press\n// is that release, not a choice.\nconst LONG_PRESS_CLICK_WINDOW_MS = 1000\n\n// Where the menu opens: at a point (the pointer, or a finger's long press), or at an element (the\n// one focused when the keyboard asked for it). Read from a ref inside `getTargetRect`, since\n// `useOverlayPosition` captures that function once.\ntype Anchor = { kind: 'point'; x: number; y: number } | { kind: 'element'; element: Element }\n\nconst pointRect = (x: number, y: number): DOMRect =>\n ({\n x,\n y,\n top: y,\n left: x,\n right: x,\n bottom: y,\n width: 0,\n height: 0,\n toJSON: () => ({ x, y, width: 0, height: 0 })\n }) as DOMRect\n\ntype ContextMenuOwnProps<C extends ElementType> = {\n /**\n * Controls which presses close the menu. `true` closes on a click on an item and on a press\n * outside the menu. `false` leaves closing to the Escape key and `visible`. `'inside'` closes\n * only on a click on an item. `'outside'` closes only on a press outside the menu.\n */\n autoClose?: MenuAutoClose\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, the region the menu opens from. Either a string to use an\n * HTML element or a component.\n *\n * @default 'div'\n */\n component?: C\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. Opened this way, the menu sits under the region's start\n * edge, since no pointer has asked for it anywhere.\n */\n defaultVisible?: boolean\n /**\n * Leaves the region to the browser: a right-click shows the browser's own menu, a long press\n * and the keys do nothing.\n */\n disabled?: boolean\n /**\n * Callback fired when the menu hides.\n */\n onHide?: () => void\n /**\n * Callback fired when the menu shows.\n */\n onShow?: () => void\n /**\n * Callback fired when the menu asks to show or hide: a right-click, a long press or Shift+F10\n * in the region, a click on an item, a press outside, the Escape key, or the closing of the\n * dialog it is in. Receives the state it asks for. With `visible` set, the menu changes only\n * when `visible` does.\n */\n onVisibleChange?: (visible: boolean) => void\n /**\n * Whether the menu is open. Setting it makes the menu controlled: it shows and hides only when\n * this changes, so pair it with `onVisibleChange`. Leave it unset, or use `defaultVisible`, for\n * a menu that opens and closes itself.\n */\n visible?: boolean\n}\n\nexport type ContextMenuProps<C extends ElementType = 'div'> = PolymorphicComponentProps<\n C,\n ContextMenuOwnProps<C>\n>\n\ntype ContextMenuComponent = (<C extends ElementType = 'div'>(\n props: ContextMenuProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\n// The region a context menu belongs to. The region is the component's own element: `className`,\n// `style`, the rest of the props and the ref go to it. The menu is a `MenuList` among its\n// children, with `Menu`'s own items, headers, dividers and submenus: this component provides\n// `Menu`'s context, so `MenuList` renders, positions, portals and navigates the list as it does\n// under a `Menu`. What differs is the trigger, the whole region rather than a button, and the\n// position, the pointer rather than that button.\nfunction ContextMenuRender<C extends ElementType = 'div'>(\n {\n children,\n autoClose = true,\n className,\n component,\n defaultVisible,\n disabled = false,\n id,\n onHide,\n onShow,\n onVisibleChange,\n visible,\n ...rest\n }: ContextMenuProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'div'\n const generatedId = useId()\n // The list is labelled by the region, the way `Menu`'s is labelled by its toggle. A caller\n // that names the list itself (`aria-label` on the `MenuList`) drops that link. Read in each\n // render, so a changed `id` reaches the region and the label. Under `asChild` the child's own\n // `id` wins the merge (`Slot`), so the label follows the element that renders.\n const triggerId =\n resolveSlottedId(Component) ?? (id as string | undefined) ?? `${generatedId}-trigger`\n const menuId = `${generatedId}-menu`\n const regionRef = useRef<HTMLElement | null>(null)\n const forkedRef = useForkedRef(ref, regionRef)\n\n // iOS shows its own callout for a long press on a link or an image; the region's menu takes\n // its place. Set on the element rather than through `style`, which a slotted child's own\n // `style` would replace. The property is inherited, so the region's children lose it too.\n useIsomorphicLayoutEffect(() => {\n regionRef.current?.style.setProperty('-webkit-touch-callout', 'none')\n }, [])\n const overlayRef = useRef<HTMLElement | null>(null)\n // `MenuToggle` writes into these two: a `MenuToggle` inside a region belongs to no `Menu`, so\n // it gets refs of its own to write to rather than the region's.\n const toggleNodeRef = useRef<HTMLElement | null>(null)\n const targetRef = useRef<HTMLElement | null>(null)\n // Portaled `MenuSubmenu` panels register themselves here, so a press inside one counts as inside\n // the menu (see `MenuContext.registerOverlay`).\n const submenuOverlaysRef = useRef<Map<string, HTMLElement>>(new Map())\n const registerOverlay = (overlayId: string, node: HTMLElement | null) => {\n if (node) submenuOverlaysRef.current.set(overlayId, node)\n else submenuOverlaysRef.current.delete(overlayId)\n }\n\n const state = useMenuTriggerState(\n useOpenStateProps({ defaultVisible, onVisibleChange, visible }, 'ContextMenu')\n )\n\n const anchorRef = useRef<Anchor | null>(null)\n // Bumped with each request to open, so the menu is placed again when a second right-click\n // moves an open menu: `useOverlayPosition` positions on its own only when the open state\n // changes.\n const [anchorVersion, setAnchorVersion] = useState(0)\n // The element focused when the menu opened, focused again when the menu closes from the\n // keyboard or an item. Cleared by a press outside, which puts focus somewhere else itself.\n const restoreFocusRef = useRef<HTMLElement | null>(null)\n\n const openAt = (anchor: Anchor) => {\n if (disabled) return\n anchorRef.current = anchor\n if (!state.isOpen) restoreFocusRef.current = document.activeElement as HTMLElement | null\n setAnchorVersion((version) => version + 1)\n state.open('first')\n }\n\n const hide = () => {\n restoreFocusRef.current = null\n state.close()\n }\n const close = () => state.close()\n\n useEffect(() => {\n if (state.isOpen) return\n const element = restoreFocusRef.current\n restoreFocusRef.current = null\n if (!element || !document.contains(element)) return\n // Only when the menu still holds focus, or nothing does: focus the user has put on another\n // control since, or an app closing the menu through `visible` while they type elsewhere,\n // stays there (`Popover` does the same).\n const active = document.activeElement\n const focusIsLoose = !active || active === document.body\n const focusIsInMenu = !!active && !!overlayRef.current?.contains(active)\n if (focusIsLoose || focusIsInMenu) element.focus()\n }, [state.isOpen])\n\n // Resolves the `<dialog>` the region is in, if any, so the list portals into its top layer and\n // closes with it, and fires `onShow`/`onHide`.\n const portalContainer = useFloatingOverlay({\n close: state.close,\n isOpen: state.isOpen,\n onHide,\n onShow,\n triggerRef: regionRef\n })\n\n // A context menu opens toward the reading direction: its start edge at the pointer, and flipped\n // above the pointer when there is no room below (`useOverlayPosition`'s own flip).\n const { direction } = useLocale()\n const placement = direction === 'rtl' ? 'bottom-end' : 'bottom-start'\n\n const {\n overlayProps,\n placement: resolvedPlacement,\n updatePosition\n } = useOverlayPosition({\n // The region is the target `useOverlayPosition` measures; `getTargetRect` replaces its\n // rectangle with the anchor's. A menu opened by `defaultVisible` or `visible` alone, with no\n // anchor yet, sits under the region's start edge.\n targetRef: regionRef,\n overlayRef,\n placement: toAriaPlacement(placement),\n containerPadding: 8,\n isOpen: state.isOpen,\n // See `Menu`: `null` opts out of closing on any window scroll, so the menu scrolls with the\n // page instead of vanishing.\n onClose: null,\n getTargetRect: () => {\n const anchor = anchorRef.current\n if (!anchor) return undefined\n return anchor.kind === 'point'\n ? pointRect(anchor.x, anchor.y)\n : anchor.element.getBoundingClientRect()\n }\n })\n useOverlayMaxHeight(overlayRef, state.isOpen)\n\n useIsomorphicLayoutEffect(() => {\n if (state.isOpen) updatePosition()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen, anchorVersion])\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n placement,\n resolvedPlacement\n )\n\n // Presses outside the menu, and clicks on its items. A press rather than a click outside, as\n // a native menu closes: the click that follows a long press's release then finds no open menu\n // to close, and a right-click elsewhere closes this menu before it opens another.\n useEffect(() => {\n if (!state.isOpen || autoClose === false) return undefined\n\n const isInMenu = (target: Node) =>\n !!overlayRef.current?.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) is portaled out of the list, and\n // React still renders it under it (`insideEvents`): a press there isn't one outside.\n const isInOverlayOfMenu = (event: Event) => isEventInside(event, overlayRef)\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node\n if (isInMenu(target) || isInOverlayOfMenu(event) || autoClose === 'inside') return\n // A right-click inside the region asks for the menu at a new place: the `contextmenu`\n // event that follows moves it.\n if (event.button === 2 && regionRef.current?.contains(target)) return\n hide()\n }\n\n const handleClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement\n if (!isInMenu(target) || autoClose === 'outside' || menuToggleClicks.has(event)) return\n // A form control inside the menu is used in place, as in `Menu`.\n if (/input|select|option|textarea|form/i.test(target.tagName ?? '')) return\n close()\n }\n\n // Tab has moved focus out of the menu by the time the key comes up.\n const handleKeyUp = (event: KeyboardEvent) => {\n if (event.key !== 'Tab' || isInMenu(event.target as Node) || isInOverlayOfMenu(event)) return\n hide()\n }\n\n window.addEventListener('pointerdown', handlePointerDown)\n window.addEventListener('click', handleClick)\n window.addEventListener('keyup', handleKeyUp)\n\n return () => {\n window.removeEventListener('pointerdown', handlePointerDown)\n window.removeEventListener('click', handleClick)\n window.removeEventListener('keyup', handleKeyUp)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen, autoClose])\n\n // Escape closes the menu wherever focus is, independent of `autoClose`, as in `Menu`: through\n // the stack of open overlays, so the key closes the innermost one only.\n useEffect(() => {\n if (!state.isOpen) return undefined\n\n return pushOverlay({\n nodes: () => [overlayRef.current, regionRef.current],\n onEscape: close\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen])\n\n // Becoming `disabled` closes an open menu. Not on mount: `disabled` with `visible` is the\n // caller's to hold.\n const wasDisabledRef = useRef(disabled)\n useEffect(() => {\n if (disabled && !wasDisabledRef.current) hide()\n wasDisabledRef.current = disabled\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [disabled])\n\n // The list is a React child of the region, so its events reach these handlers through the\n // portal: a right-click on an item, or Shift+F10 with an item focused, is not a request to open\n // the menu somewhere else. Only what happens in the region's own element counts.\n const isInRegion = (event: React.SyntheticEvent<HTMLElement>) =>\n event.currentTarget.contains(event.target as Node)\n\n // The browser's own menu is replaced. When `disabled`, the event isn't handled at all, so the\n // browser's menu shows.\n // One handled already, by a region nested in this one, isn't this region's: both opened.\n const handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {\n if (disabled || event.defaultPrevented) return\n // Prevented for the list too: a browser that fires `contextmenu` for the context menu key on\n // key up (Chromium) fires it at the item the key down has just focused.\n event.preventDefault()\n if (!isInRegion(event)) return\n openAt({ kind: 'point', x: event.clientX, y: event.clientY })\n }\n\n const isContextMenuKey = (event: React.KeyboardEvent<HTMLElement>) =>\n event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey)\n\n // Shift+F10 and the context menu key, on any element in the region: the menu opens under that\n // element. Preventing the default keeps the browser from firing its own `contextmenu` event\n // for the key, which would move the menu to where the browser reports the key. Firefox fires\n // it from the key down, Chromium from the key up, so both are prevented.\n const handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n if (disabled || event.defaultPrevented || !isContextMenuKey(event)) return\n event.preventDefault()\n if (!isInRegion(event)) return\n openAt({ kind: 'element', element: event.target as Element })\n }\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLElement>) => {\n if (!disabled && isContextMenuKey(event)) event.preventDefault()\n }\n\n // A long press by a finger or a pen. A browser that fires `contextmenu` for it as well (Android)\n // opens the menu through `handleContextMenu` at the same point.\n const longPressRef = useRef<{ timer: number; x: number; y: number } | null>(null)\n // While a finger is down, the region selects no text: iOS starts selecting at about the same\n // time the press becomes long. Restored when the finger lifts.\n const userSelectRef = useRef<string | null>(null)\n const restoreUserSelect = () => {\n const region = regionRef.current\n if (!region || userSelectRef.current === null) return\n region.style.setProperty('-webkit-user-select', userSelectRef.current)\n region.style.setProperty('user-select', userSelectRef.current)\n userSelectRef.current = null\n }\n const cancelLongPress = () => {\n if (!longPressRef.current) return\n window.clearTimeout(longPressRef.current.timer)\n longPressRef.current = null\n }\n const endPress = () => {\n cancelLongPress()\n restoreUserSelect()\n }\n // The click the release of a long press emits (iOS) lands on the item that has just opened\n // under the finger: swallowed before it reaches the item or the click-inside dismissal.\n const clickSwallowRef = useRef<(() => void) | null>(null)\n const stopSwallowingClicks = () => {\n clickSwallowRef.current?.()\n clickSwallowRef.current = null\n }\n const swallowNextClick = () => {\n stopSwallowingClicks()\n const swallow = (event: MouseEvent) => {\n event.preventDefault()\n event.stopPropagation()\n stopSwallowingClicks()\n }\n window.addEventListener('click', swallow, { capture: true })\n const timer = window.setTimeout(stopSwallowingClicks, LONG_PRESS_CLICK_WINDOW_MS)\n clickSwallowRef.current = () => {\n window.removeEventListener('click', swallow, { capture: true })\n window.clearTimeout(timer)\n }\n }\n\n useEffect(\n () => () => {\n endPress()\n stopSwallowingClicks()\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n )\n\n const handlePointerDown = (event: React.PointerEvent<HTMLElement>) => {\n if (disabled || event.pointerType === 'mouse' || !isInRegion(event)) return\n endPress()\n const region = event.currentTarget\n userSelectRef.current = region.style.getPropertyValue('user-select')\n region.style.setProperty('-webkit-user-select', 'none')\n region.style.setProperty('user-select', 'none')\n const { clientX: x, clientY: y } = event\n longPressRef.current = {\n x,\n y,\n timer: window.setTimeout(() => {\n longPressRef.current = null\n swallowNextClick()\n openAt({ kind: 'point', x, y })\n }, LONG_PRESS_MS)\n }\n }\n\n const handlePointerMove = (event: React.PointerEvent<HTMLElement>) => {\n const press = longPressRef.current\n if (!press) return\n if (Math.hypot(event.clientX - press.x, event.clientY - press.y) > LONG_PRESS_TOLERANCE_PX) {\n cancelLongPress()\n }\n }\n\n const contextValue: MenuContextProps = useMemo(\n () => ({\n autoClose,\n close,\n container: portalContainer ?? true,\n focusStrategy: state.focusStrategy as MenuFocusStrategy | null,\n hide,\n menuId,\n menuStyle,\n menuTriggerProps: {},\n overlayRef,\n placementAttr,\n portalContainer,\n reference: 'toggle',\n registerOverlay,\n show: (focusStrategy) => state.open(focusStrategy ?? 'first'),\n targetRef,\n toggle: (focusStrategy) => state.toggle(focusStrategy ?? 'first'),\n toggleNodeRef,\n triggerId,\n visible: state.isOpen\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n autoClose,\n menuId,\n menuStyle,\n placementAttr,\n portalContainer,\n state.focusStrategy,\n state.isOpen,\n triggerId\n ]\n )\n\n return (\n <MenuContext.Provider value={contextValue}>\n <Component\n id={triggerId}\n className={classNames('context-menu', className)}\n {...(mergeProps(\n {\n onContextMenu: handleContextMenu,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: endPress,\n onPointerCancel: endPress,\n onPointerLeave: endPress\n },\n rest\n ) as Record<string, unknown>)}\n ref={forkedRef}\n >\n {children}\n </Component>\n </MenuContext.Provider>\n )\n}\n\nexport const ContextMenu = createPolymorphicComponent<ContextMenuComponent>(\n ContextMenuRender as ForwardRefRenderFunction<Element, ContextMenuProps<ElementType>>,\n 'ContextMenu'\n)\n"],"mappings":"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"}
1
+ {"version":3,"file":"context-menu-D3DNFN-P.js","names":["resolveSlottedId","createPolymorphicComponent","useIsomorphicLayoutEffect","pushOverlay","useFloatingOverlay","useOpenStateProps","useOverlayMaxHeight","toAriaPlacement","resolveMenuOverlayPositioning","isEventInside","MenuContext","menuToggleClicks","React","classNames","pointRect","y","x","ContextMenuRender","rest","Component","component","generatedId","useId","triggerId","id","menuId","regionRef","useRef","forkedRef","useForkedRef","ref","overlayRef","toggleNodeRef","targetRef","submenuOverlaysRef","registerOverlay","node","overlayId","state","useMenuTriggerState","anchorRef","anchorVersion","setAnchorVersion","useState","restoreFocusRef","openAt","disabled","anchor","version","hide","close","useEffect","element","active","focusIsLoose","focusIsInMenu","portalContainer","useLocale","placement","direction","resolvedPlacement","useOverlayPosition","updatePosition","overlayProps","autoClose","isInMenu","target","isInOverlayOfMenu","event","handlePointerDown","handleClick","handleKeyUp","wasDisabledRef","isInRegion","handleContextMenu","isContextMenuKey","handleKeyDown","longPressRef","userSelectRef","restoreUserSelect","region","cancelLongPress","endPress","clickSwallowRef","stopSwallowingClicks","swallowNextClick","swallow","timer","handlePointerMove","press","contextValue","useMemo","focusStrategy","menuStyle","placementAttr","className","mergeProps","children","ContextMenu"],"sources":["../../src/components/context-menu/ContextMenu.tsx"],"sourcesContent":["import React, {\n ElementType,\n ForwardRefRenderFunction,\n ReactElement,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState\n} from 'react'\nimport classNames from 'classnames'\nimport { mergeProps, useLocale, 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 { resolveSlottedId } from '../../utils/elementKind'\nimport { isEventInside } from '../../utils/insideEvents'\nimport { resolveMenuOverlayPositioning, toAriaPlacement } from '../../utils/overlayPlacement'\nimport { pushOverlay } from '../../utils/overlayStack'\nimport {\n createPolymorphicComponent,\n PolymorphicComponentProps,\n PolymorphicRef\n} from '../../utils/polymorphic'\nimport {\n MenuAutoClose,\n MenuContext,\n MenuContextProps,\n MenuFocusStrategy,\n menuToggleClicks\n} from '../menu/Menu'\n\n// How long a touch or pen has to stay down, and how far it may travel meanwhile, for a long\n// press. react-aria's `useLongPress` uses the same threshold; it isn't used here because its\n// `usePress` prevents the default of key and pointer events on the element it is given, which\n// would break the buttons and links inside a region.\nconst LONG_PRESS_MS = 500\nconst LONG_PRESS_TOLERANCE_PX = 10\n// iOS emits a click when the finger that long-pressed lifts, on whatever is under it by then: the\n// first item of the menu that has just opened at the finger. A click this soon after a long press\n// is that release, not a choice.\nconst LONG_PRESS_CLICK_WINDOW_MS = 1000\n\n// Where the menu opens: at a point (the pointer, or a finger's long press), or at an element (the\n// one focused when the keyboard asked for it). Read from a ref inside `getTargetRect`, since\n// `useOverlayPosition` captures that function once.\ntype Anchor = { kind: 'point'; x: number; y: number } | { kind: 'element'; element: Element }\n\nconst pointRect = (x: number, y: number): DOMRect =>\n ({\n x,\n y,\n top: y,\n left: x,\n right: x,\n bottom: y,\n width: 0,\n height: 0,\n toJSON: () => ({ x, y, width: 0, height: 0 })\n }) as DOMRect\n\ntype ContextMenuOwnProps<C extends ElementType> = {\n /**\n * Controls which presses close the menu. `true` closes on a click on an item and on a press\n * outside the menu. `false` leaves closing to the Escape key and `visible`. `'inside'` closes\n * only on a click on an item. `'outside'` closes only on a press outside the menu.\n */\n autoClose?: MenuAutoClose\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, the region the menu opens from. Either a string to use an\n * HTML element or a component.\n *\n * @default 'div'\n */\n component?: C\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. Opened this way, the menu sits under the region's start\n * edge, since no pointer has asked for it anywhere.\n */\n defaultVisible?: boolean\n /**\n * Leaves the region to the browser: a right-click shows the browser's own menu, a long press\n * and the keys do nothing.\n */\n disabled?: boolean\n /**\n * Callback fired when the menu hides.\n */\n onHide?: () => void\n /**\n * Callback fired when the menu shows.\n */\n onShow?: () => void\n /**\n * Callback fired when the menu asks to show or hide: a right-click, a long press or Shift+F10\n * in the region, a click on an item, a press outside, the Escape key, or the closing of the\n * dialog it is in. Receives the state it asks for. With `visible` set, the menu changes only\n * when `visible` does.\n */\n onVisibleChange?: (visible: boolean) => void\n /**\n * Whether the menu is open. Setting it makes the menu controlled: it shows and hides only when\n * this changes, so pair it with `onVisibleChange`. Leave it unset, or use `defaultVisible`, for\n * a menu that opens and closes itself.\n */\n visible?: boolean\n}\n\nexport type ContextMenuProps<C extends ElementType = 'div'> = PolymorphicComponentProps<\n C,\n ContextMenuOwnProps<C>\n>\n\ntype ContextMenuComponent = (<C extends ElementType = 'div'>(\n props: ContextMenuProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\n// The region a context menu belongs to. The region is the component's own element: `className`,\n// `style`, the rest of the props and the ref go to it. The menu is a `MenuList` among its\n// children, with `Menu`'s own items, headers, dividers and submenus: this component provides\n// `Menu`'s context, so `MenuList` renders, positions, portals and navigates the list as it does\n// under a `Menu`. What differs is the trigger, the whole region rather than a button, and the\n// position, the pointer rather than that button.\nfunction ContextMenuRender<C extends ElementType = 'div'>(\n {\n children,\n autoClose = true,\n className,\n component,\n defaultVisible,\n disabled = false,\n id,\n onHide,\n onShow,\n onVisibleChange,\n visible,\n ...rest\n }: ContextMenuProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'div'\n const generatedId = useId()\n // The list is labelled by the region, the way `Menu`'s is labelled by its toggle. A caller\n // that names the list itself (`aria-label` on the `MenuList`) drops that link. Read in each\n // render, so a changed `id` reaches the region and the label. Under `asChild` the child's own\n // `id` wins the merge (`Slot`), so the label follows the element that renders.\n const triggerId =\n resolveSlottedId(Component) ?? (id as string | undefined) ?? `${generatedId}-trigger`\n const menuId = `${generatedId}-menu`\n const regionRef = useRef<HTMLElement | null>(null)\n const forkedRef = useForkedRef(ref, regionRef)\n\n // iOS shows its own callout for a long press on a link or an image; the region's menu takes\n // its place. Set on the element rather than through `style`, which a slotted child's own\n // `style` would replace. The property is inherited, so the region's children lose it too.\n useIsomorphicLayoutEffect(() => {\n regionRef.current?.style.setProperty('-webkit-touch-callout', 'none')\n }, [])\n const overlayRef = useRef<HTMLElement | null>(null)\n // `MenuToggle` writes into these two: a `MenuToggle` inside a region belongs to no `Menu`, so\n // it gets refs of its own to write to rather than the region's.\n const toggleNodeRef = useRef<HTMLElement | null>(null)\n const targetRef = useRef<HTMLElement | null>(null)\n // Portaled `MenuSubmenu` panels register themselves here, so a press inside one counts as inside\n // the menu (see `MenuContext.registerOverlay`).\n const submenuOverlaysRef = useRef<Map<string, HTMLElement>>(new Map())\n const registerOverlay = (overlayId: string, node: HTMLElement | null) => {\n if (node) submenuOverlaysRef.current.set(overlayId, node)\n else submenuOverlaysRef.current.delete(overlayId)\n }\n\n const state = useMenuTriggerState(\n useOpenStateProps({ defaultVisible, onVisibleChange, visible }, 'ContextMenu')\n )\n\n const anchorRef = useRef<Anchor | null>(null)\n // Bumped with each request to open, so the menu is placed again when a second right-click\n // moves an open menu: `useOverlayPosition` positions on its own only when the open state\n // changes.\n const [anchorVersion, setAnchorVersion] = useState(0)\n // The element focused when the menu opened, focused again when the menu closes from the\n // keyboard or an item. Cleared by a press outside, which puts focus somewhere else itself.\n const restoreFocusRef = useRef<HTMLElement | null>(null)\n\n const openAt = (anchor: Anchor) => {\n if (disabled) return\n anchorRef.current = anchor\n if (!state.isOpen) restoreFocusRef.current = document.activeElement as HTMLElement | null\n setAnchorVersion((version) => version + 1)\n state.open('first')\n }\n\n const hide = () => {\n restoreFocusRef.current = null\n state.close()\n }\n const close = () => state.close()\n\n useEffect(() => {\n if (state.isOpen) return\n const element = restoreFocusRef.current\n restoreFocusRef.current = null\n if (!element || !document.contains(element)) return\n // Only when the menu still holds focus, or nothing does: focus the user has put on another\n // control since, or an app closing the menu through `visible` while they type elsewhere,\n // stays there (`Popover` does the same).\n const active = document.activeElement\n const focusIsLoose = !active || active === document.body\n const focusIsInMenu = !!active && !!overlayRef.current?.contains(active)\n if (focusIsLoose || focusIsInMenu) element.focus()\n }, [state.isOpen])\n\n // Resolves the `<dialog>` the region is in, if any, so the list portals into its top layer and\n // closes with it, and fires `onShow`/`onHide`.\n const portalContainer = useFloatingOverlay({\n close: state.close,\n isOpen: state.isOpen,\n onHide,\n onShow,\n triggerRef: regionRef\n })\n\n // A context menu opens toward the reading direction: its start edge at the pointer, and flipped\n // above the pointer when there is no room below (`useOverlayPosition`'s own flip).\n const { direction } = useLocale()\n const placement = direction === 'rtl' ? 'bottom-end' : 'bottom-start'\n\n const {\n overlayProps,\n placement: resolvedPlacement,\n updatePosition\n } = useOverlayPosition({\n // The region is the target `useOverlayPosition` measures; `getTargetRect` replaces its\n // rectangle with the anchor's. A menu opened by `defaultVisible` or `visible` alone, with no\n // anchor yet, sits under the region's start edge.\n targetRef: regionRef,\n overlayRef,\n placement: toAriaPlacement(placement),\n containerPadding: 8,\n isOpen: state.isOpen,\n // See `Menu`: `null` opts out of closing on any window scroll, so the menu scrolls with the\n // page instead of vanishing.\n onClose: null,\n getTargetRect: () => {\n const anchor = anchorRef.current\n if (!anchor) return undefined\n return anchor.kind === 'point'\n ? pointRect(anchor.x, anchor.y)\n : anchor.element.getBoundingClientRect()\n }\n })\n useOverlayMaxHeight(overlayRef, state.isOpen)\n\n useIsomorphicLayoutEffect(() => {\n if (state.isOpen) updatePosition()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen, anchorVersion])\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n placement,\n resolvedPlacement\n )\n\n // Presses outside the menu, and clicks on its items. A press rather than a click outside, as\n // a native menu closes: the click that follows a long press's release then finds no open menu\n // to close, and a right-click elsewhere closes this menu before it opens another.\n useEffect(() => {\n if (!state.isOpen || autoClose === false) return undefined\n\n const isInMenu = (target: Node) =>\n !!overlayRef.current?.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) is portaled out of the list, and\n // React still renders it under it (`insideEvents`): a press there isn't one outside.\n const isInOverlayOfMenu = (event: Event) => isEventInside(event, overlayRef)\n\n const handlePointerDown = (event: PointerEvent) => {\n const target = event.target as Node\n if (isInMenu(target) || isInOverlayOfMenu(event) || autoClose === 'inside') return\n // A right-click inside the region asks for the menu at a new place: the `contextmenu`\n // event that follows moves it.\n if (event.button === 2 && regionRef.current?.contains(target)) return\n hide()\n }\n\n const handleClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement\n if (!isInMenu(target) || autoClose === 'outside' || menuToggleClicks.has(event)) return\n // A form control inside the menu is used in place, as in `Menu`.\n if (/input|select|option|textarea|form/i.test(target.tagName ?? '')) return\n close()\n }\n\n // Tab has moved focus out of the menu by the time the key comes up.\n const handleKeyUp = (event: KeyboardEvent) => {\n if (event.key !== 'Tab' || isInMenu(event.target as Node) || isInOverlayOfMenu(event)) return\n hide()\n }\n\n window.addEventListener('pointerdown', handlePointerDown)\n window.addEventListener('click', handleClick)\n window.addEventListener('keyup', handleKeyUp)\n\n return () => {\n window.removeEventListener('pointerdown', handlePointerDown)\n window.removeEventListener('click', handleClick)\n window.removeEventListener('keyup', handleKeyUp)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen, autoClose])\n\n // Escape closes the menu wherever focus is, independent of `autoClose`, as in `Menu`: through\n // the stack of open overlays, so the key closes the innermost one only.\n useEffect(() => {\n if (!state.isOpen) return undefined\n\n return pushOverlay({\n nodes: () => [overlayRef.current, regionRef.current],\n onEscape: close\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.isOpen])\n\n // Becoming `disabled` closes an open menu. Not on mount: `disabled` with `visible` is the\n // caller's to hold.\n const wasDisabledRef = useRef(disabled)\n useEffect(() => {\n if (disabled && !wasDisabledRef.current) hide()\n wasDisabledRef.current = disabled\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [disabled])\n\n // The list is a React child of the region, so its events reach these handlers through the\n // portal: a right-click on an item, or Shift+F10 with an item focused, is not a request to open\n // the menu somewhere else. Only what happens in the region's own element counts.\n const isInRegion = (event: React.SyntheticEvent<HTMLElement>) =>\n event.currentTarget.contains(event.target as Node)\n\n // The browser's own menu is replaced. When `disabled`, the event isn't handled at all, so the\n // browser's menu shows.\n // One handled already, by a region nested in this one, isn't this region's: both opened.\n const handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {\n if (disabled || event.defaultPrevented) return\n // Prevented for the list too: a browser that fires `contextmenu` for the context menu key on\n // key up (Chromium) fires it at the item the key down has just focused.\n event.preventDefault()\n if (!isInRegion(event)) return\n openAt({ kind: 'point', x: event.clientX, y: event.clientY })\n }\n\n const isContextMenuKey = (event: React.KeyboardEvent<HTMLElement>) =>\n event.key === 'ContextMenu' || (event.key === 'F10' && event.shiftKey)\n\n // Shift+F10 and the context menu key, on any element in the region: the menu opens under that\n // element. Preventing the default keeps the browser from firing its own `contextmenu` event\n // for the key, which would move the menu to where the browser reports the key. Firefox fires\n // it from the key down, Chromium from the key up, so both are prevented.\n const handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n if (disabled || event.defaultPrevented || !isContextMenuKey(event)) return\n event.preventDefault()\n if (!isInRegion(event)) return\n openAt({ kind: 'element', element: event.target as Element })\n }\n\n const handleKeyUp = (event: React.KeyboardEvent<HTMLElement>) => {\n if (!disabled && isContextMenuKey(event)) event.preventDefault()\n }\n\n // A long press by a finger or a pen. A browser that fires `contextmenu` for it as well (Android)\n // opens the menu through `handleContextMenu` at the same point.\n const longPressRef = useRef<{ timer: number; x: number; y: number } | null>(null)\n // While a finger is down, the region selects no text: iOS starts selecting at about the same\n // time the press becomes long. Restored when the finger lifts.\n const userSelectRef = useRef<string | null>(null)\n const restoreUserSelect = () => {\n const region = regionRef.current\n if (!region || userSelectRef.current === null) return\n region.style.setProperty('-webkit-user-select', userSelectRef.current)\n region.style.setProperty('user-select', userSelectRef.current)\n userSelectRef.current = null\n }\n const cancelLongPress = () => {\n if (!longPressRef.current) return\n window.clearTimeout(longPressRef.current.timer)\n longPressRef.current = null\n }\n const endPress = () => {\n cancelLongPress()\n restoreUserSelect()\n }\n // The click the release of a long press emits (iOS) lands on the item that has just opened\n // under the finger: swallowed before it reaches the item or the click-inside dismissal.\n const clickSwallowRef = useRef<(() => void) | null>(null)\n const stopSwallowingClicks = () => {\n clickSwallowRef.current?.()\n clickSwallowRef.current = null\n }\n const swallowNextClick = () => {\n stopSwallowingClicks()\n const swallow = (event: MouseEvent) => {\n event.preventDefault()\n event.stopPropagation()\n stopSwallowingClicks()\n }\n window.addEventListener('click', swallow, { capture: true })\n const timer = window.setTimeout(stopSwallowingClicks, LONG_PRESS_CLICK_WINDOW_MS)\n clickSwallowRef.current = () => {\n window.removeEventListener('click', swallow, { capture: true })\n window.clearTimeout(timer)\n }\n }\n\n useEffect(\n () => () => {\n endPress()\n stopSwallowingClicks()\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n )\n\n const handlePointerDown = (event: React.PointerEvent<HTMLElement>) => {\n if (disabled || event.pointerType === 'mouse' || !isInRegion(event)) return\n endPress()\n const region = event.currentTarget\n userSelectRef.current = region.style.getPropertyValue('user-select')\n region.style.setProperty('-webkit-user-select', 'none')\n region.style.setProperty('user-select', 'none')\n const { clientX: x, clientY: y } = event\n longPressRef.current = {\n x,\n y,\n timer: window.setTimeout(() => {\n longPressRef.current = null\n swallowNextClick()\n openAt({ kind: 'point', x, y })\n }, LONG_PRESS_MS)\n }\n }\n\n const handlePointerMove = (event: React.PointerEvent<HTMLElement>) => {\n const press = longPressRef.current\n if (!press) return\n if (Math.hypot(event.clientX - press.x, event.clientY - press.y) > LONG_PRESS_TOLERANCE_PX) {\n cancelLongPress()\n }\n }\n\n const contextValue: MenuContextProps = useMemo(\n () => ({\n autoClose,\n close,\n container: portalContainer ?? true,\n focusStrategy: state.focusStrategy as MenuFocusStrategy | null,\n hide,\n menuId,\n menuStyle,\n menuTriggerProps: {},\n overlayRef,\n placementAttr,\n portalContainer,\n reference: 'toggle',\n registerOverlay,\n show: (focusStrategy) => state.open(focusStrategy ?? 'first'),\n targetRef,\n toggle: (focusStrategy) => state.toggle(focusStrategy ?? 'first'),\n toggleNodeRef,\n triggerId,\n visible: state.isOpen\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n autoClose,\n menuId,\n menuStyle,\n placementAttr,\n portalContainer,\n state.focusStrategy,\n state.isOpen,\n triggerId\n ]\n )\n\n return (\n <MenuContext.Provider value={contextValue}>\n <Component\n id={triggerId}\n className={classNames('context-menu', className)}\n {...(mergeProps(\n {\n onContextMenu: handleContextMenu,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n onPointerDown: handlePointerDown,\n onPointerMove: handlePointerMove,\n onPointerUp: endPress,\n onPointerCancel: endPress,\n onPointerLeave: endPress\n },\n rest\n ) as Record<string, unknown>)}\n ref={forkedRef}\n >\n {children}\n </Component>\n </MenuContext.Provider>\n )\n}\n\nexport const ContextMenu = createPolymorphicComponent<ContextMenuComponent>(\n ContextMenuRender as ForwardRefRenderFunction<Element, ContextMenuProps<ElementType>>,\n 'ContextMenu'\n)\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import"./focus-ring-Bs80iIBN.js";import{t as e}from"./polymorphic-CZIFszAy.js";import{t}from"./useOverlayMaxHeight-8mQL2Q6d.js";import{i as n,r}from"./overlayPlacement-Q6bcbXA5.js";import{t as i}from"./Portal-BTDylxAi.js";import{n as a,r as o}from"./Menu-264aGoBR.js";import{a as s,c as ee,i as c,l as te,o as ne,r as l,s as u}from"./MenuToggle-DcPEh55c.js";import d,{forwardRef as f,useCallback as p,useContext as m,useEffect as h,useId as re,useRef as g,useState as ie}from"react";import _ from"classnames";import{useLocale as v,useOverlayPosition as ae}from"react-aria";function y({children:e,className:t,component:n,...r},i){let a=n??`span`,o=_(`menu-text`,t);return/* @__PURE__ */ d.createElement(a,{className:o,...r,ref:i},e)}const b=e(y,`MenuText`),x=f(({children:e,activation:f=`both`,className:y,disabled:b,offset:x=[-4,0],placement:S,stacked:C,submenuDelay:w=100,trigger:T,...E},oe)=>{let D=re(),O=`${D}-trigger`,k=`${D}-menu`,[A,j]=ie(!1),M=g(void 0),N=g(void 0),P=g(!1),F=g(null),I=g(null),L=m(c),se=ne(),{portalContainer:ce,registerOverlay:le,visible:R}=m(a),z=m(s),{direction:B}=v(),V=B===`rtl`,H=S??(V?`left-start`:`right-start`),{overlayProps:U,placement:ue}=ae({targetRef:F,overlayRef:I,placement:n(H),offset:x[1],crossOffset:x[0],containerPadding:8,isOpen:A,onClose:null});t(I,A);let{menuStyle:de,placementAttr:fe}=r(U.style,H,ue),W=p(()=>{M.current!==void 0&&(window.clearTimeout(M.current),M.current=void 0)},[]),G=p(()=>{N.current!==void 0&&(cancelAnimationFrame(N.current),N.current=void 0)},[]),K=p(()=>{W(),G(),j(!1)},[W,G]),q=()=>{b||A||(W(),L?.notifyOpen(D),j(!0))},J=()=>{W(),M.current=window.setTimeout(K,w)};h(()=>L?.register(D,K),[L,D,K]),h(()=>W,[W]),h(()=>G,[G]),h(()=>{(!R||!z)&&K()},[R,z,K]);let Y=typeof window<`u`&&!!window.matchMedia&&window.matchMedia(`(hover: hover)`).matches,X=Y&&(f===`hover`||f===`both`),Z=f!==`hover`||!Y,Q=()=>{q(),G(),N.current=requestAnimationFrame(()=>{N.current=void 0,u(ee(I.current),`first`)})},$=()=>{P.current=!0,K()};h(()=>{!A&&P.current&&F.current?.focus(),P.current=!1},[A]);let pe=e=>{e.preventDefault(),o.add(e.nativeEvent),Z&&!b&&(A?K():Q())},me=V?`ArrowLeft`:`ArrowRight`,he=e=>{b||(e.key===`Enter`||e.key===` `||e.key===me)&&(e.preventDefault(),e.stopPropagation(),Q())},ge={close:$};return/* @__PURE__ */ d.createElement(`div`,{className:_(`submenu`,{show:A},y),...E,ref:oe},/* @__PURE__ */ d.createElement(`button`,{type:`button`,id:O,role:`menuitem`,className:`menu-item`,"aria-expanded":A,"aria-haspopup":`true`,"aria-controls":A?k:void 0,disabled:b,onClick:pe,onKeyDown:he,onMouseEnter:X?q:void 0,onMouseLeave:X?J:void 0,ref:e=>{F.current=e}},T),(()=>{let t=/* @__PURE__ */ d.createElement(`div`,{role:`menu`,id:k,"aria-labelledby":O,className:_(`menu`,{show:A,"submenu-stacked":C}),style:de,"data-cx-placement":fe,onKeyDown:e=>te(e,{onEscape:$,...V?{onArrowRight:$}:{onArrowLeft:$}}),onMouseEnter:X?W:void 0,onMouseLeave:X?J:void 0,ref:e=>{I.current=e,le(k,e)}},/* @__PURE__ */ d.createElement(l.Provider,{value:ge},/* @__PURE__ */ d.createElement(c.Provider,{value:se},/* @__PURE__ */ d.createElement(s.Provider,{value:A},e))));return C?t:/* @__PURE__ */ d.createElement(i,{container:ce,fallback:t},t)})())});x.displayName=`MenuSubmenu`;const S=f(({children:e,className:t,onClick:n,type:r=`button`,...i},a)=>{let o=m(l),s=e=>{n?.(e),o&&(e.stopPropagation(),o.close())};return/* @__PURE__ */ d.createElement(`button`,{type:r,role:`menuitem`,className:_(`submenu-back`,`menu-item`,t),...i,onClick:s,ref:a},e)});S.displayName=`MenuSubmenuBack`;export{x as n,b as r,S as t};
2
- //# sourceMappingURL=menu-DEu-Nbv8.js.map
1
+ import"./focus-ring-Bs80iIBN.js";import{t as e}from"./polymorphic-CZIFszAy.js";import{t}from"./useOverlayMaxHeight-DTgbr4UQ.js";import{i as n,r}from"./overlayPlacement-Q6bcbXA5.js";import{t as i}from"./Portal-BTDylxAi.js";import{n as a,r as o}from"./Menu-BiE9CzNk.js";import{a as s,c as ee,i as c,l as te,o as ne,r as l,s as u}from"./MenuToggle-W-ZSHFwF.js";import d,{forwardRef as f,useCallback as p,useContext as m,useEffect as h,useId as re,useRef as g,useState as ie}from"react";import _ from"classnames";import{useLocale as v,useOverlayPosition as ae}from"react-aria";function y({children:e,className:t,component:n,...r},i){let a=n??`span`,o=_(`menu-text`,t);return/* @__PURE__ */ d.createElement(a,{className:o,...r,ref:i},e)}const b=e(y,`MenuText`),x=f(({children:e,activation:f=`both`,className:y,disabled:b,offset:x=[-4,0],placement:S,stacked:C,submenuDelay:w=100,trigger:T,...E},oe)=>{let D=re(),O=`${D}-trigger`,k=`${D}-menu`,[A,j]=ie(!1),M=g(void 0),N=g(void 0),P=g(!1),F=g(null),I=g(null),L=m(c),se=ne(),{portalContainer:ce,registerOverlay:le,visible:R}=m(a),z=m(s),{direction:B}=v(),V=B===`rtl`,H=S??(V?`left-start`:`right-start`),{overlayProps:U,placement:ue}=ae({targetRef:F,overlayRef:I,placement:n(H),offset:x[1],crossOffset:x[0],containerPadding:8,isOpen:A,onClose:null});t(I,A);let{menuStyle:de,placementAttr:fe}=r(U.style,H,ue),W=p(()=>{M.current!==void 0&&(window.clearTimeout(M.current),M.current=void 0)},[]),G=p(()=>{N.current!==void 0&&(cancelAnimationFrame(N.current),N.current=void 0)},[]),K=p(()=>{W(),G(),j(!1)},[W,G]),q=()=>{b||A||(W(),L?.notifyOpen(D),j(!0))},J=()=>{W(),M.current=window.setTimeout(K,w)};h(()=>L?.register(D,K),[L,D,K]),h(()=>W,[W]),h(()=>G,[G]),h(()=>{(!R||!z)&&K()},[R,z,K]);let Y=typeof window<`u`&&!!window.matchMedia&&window.matchMedia(`(hover: hover)`).matches,X=Y&&(f===`hover`||f===`both`),Z=f!==`hover`||!Y,Q=()=>{q(),G(),N.current=requestAnimationFrame(()=>{N.current=void 0,u(ee(I.current),`first`)})},$=()=>{P.current=!0,K()};h(()=>{!A&&P.current&&F.current?.focus(),P.current=!1},[A]);let pe=e=>{e.preventDefault(),o.add(e.nativeEvent),Z&&!b&&(A?K():Q())},me=V?`ArrowLeft`:`ArrowRight`,he=e=>{b||(e.key===`Enter`||e.key===` `||e.key===me)&&(e.preventDefault(),e.stopPropagation(),Q())},ge={close:$};return/* @__PURE__ */ d.createElement(`div`,{className:_(`submenu`,{show:A},y),...E,ref:oe},/* @__PURE__ */ d.createElement(`button`,{type:`button`,id:O,role:`menuitem`,className:`menu-item`,"aria-expanded":A,"aria-haspopup":`true`,"aria-controls":A?k:void 0,disabled:b,onClick:pe,onKeyDown:he,onMouseEnter:X?q:void 0,onMouseLeave:X?J:void 0,ref:e=>{F.current=e}},T),(()=>{let t=/* @__PURE__ */ d.createElement(`div`,{role:`menu`,id:k,"aria-labelledby":O,className:_(`menu`,{show:A,"submenu-stacked":C}),style:de,"data-cx-placement":fe,onKeyDown:e=>te(e,{onEscape:$,...V?{onArrowRight:$}:{onArrowLeft:$}}),onMouseEnter:X?W:void 0,onMouseLeave:X?J:void 0,ref:e=>{I.current=e,le(k,e)}},/* @__PURE__ */ d.createElement(l.Provider,{value:ge},/* @__PURE__ */ d.createElement(c.Provider,{value:se},/* @__PURE__ */ d.createElement(s.Provider,{value:A},e))));return C?t:/* @__PURE__ */ d.createElement(i,{container:ce,fallback:t},t)})())});x.displayName=`MenuSubmenu`;const S=f(({children:e,className:t,onClick:n,type:r=`button`,...i},a)=>{let o=m(l),s=e=>{n?.(e),o&&(e.stopPropagation(),o.close())};return/* @__PURE__ */ d.createElement(`button`,{type:r,role:`menuitem`,className:_(`submenu-back`,`menu-item`,t),...i,onClick:s,ref:a},e)});S.displayName=`MenuSubmenuBack`;export{x as n,b as r,S as t};
2
+ //# sourceMappingURL=menu-Bqlhottl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-DEu-Nbv8.js","names":["createPolymorphicComponent","toAriaPlacement","Portal","MenuContext","menuToggleClicks","SubmenuVisibleContext","getMenuItems","SubmenuGroupContext","handleMenuKeyDown","useSubmenuGroupProvider","SubmenuActionsContext","focusMenuItem","React","classNames","MenuTextRender","rest","Component","component","_className","className","children","MenuText","MenuSubmenu","forwardRef","offsetProp","id","useId","triggerId","menuId","visible","setVisible","useState","closeTimeoutRef","useRef","focusFirstRafRef","refocusTriggerRef","triggerRef","overlayRef","parentGroup","useContext","ownGroup","parentMenuVisible","parentSubmenuVisible","useLocale","isRtl","direction","effectivePlacement","placement","resolvedPlacement","useOverlayPosition","useOverlayMaxHeight","resolveMenuOverlayPositioning","overlayProps","clearCloseTimeout","useCallback","cancelFocusFirstRaf","close","open","disabled","scheduleClose","submenuDelay","useEffect","supportsHover","hoverEnabled","activation","clickEnabled","openAndFocusFirst","closeAndRefocusTrigger","handleTriggerClick","event","openKey","handleTriggerKeyDown","actionsValue","node","trigger","panel","stacked","menuStyle","placementAttr","registerOverlay","portalContainer","MenuSubmenuBack","actions","handleClick","onClick"],"sources":["../../src/components/menu/MenuText.tsx","../../src/components/menu/MenuSubmenu.tsx","../../src/components/menu/MenuSubmenuBack.tsx"],"sourcesContent":["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 MenuTextOwnProps<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\nexport type MenuTextProps<C extends ElementType = 'span'> = PolymorphicComponentProps<\n C,\n MenuTextOwnProps<C>\n>\n\ntype MenuTextComponent = (<C extends ElementType = 'span'>(\n props: MenuTextProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuTextRender<C extends ElementType = 'span'>(\n { children, className, component, ...rest }: MenuTextProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'span'\n const _className = classNames('menu-text', className)\n\n return (\n <Component className={_className} {...rest} ref={ref}>\n {children}\n </Component>\n )\n}\n\nexport const MenuText = createPolymorphicComponent<MenuTextComponent>(\n MenuTextRender as ForwardRefRenderFunction<Element, MenuTextProps<ElementType>>,\n 'MenuText'\n)\n","import React, {\n forwardRef,\n HTMLAttributes,\n ReactNode,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState\n} from 'react'\nimport classNames from 'classnames'\nimport { useLocale, useOverlayPosition } from 'react-aria'\n\nimport { useOverlayMaxHeight } from '../../hooks/useOverlayMaxHeight'\nimport { MenuContext, menuToggleClicks } from './Menu'\nimport {\n Placement,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { Portal } from '../portal/Portal'\nimport { focusMenuItem, getMenuItems, handleMenuKeyDown } from './menuNavigation'\nimport {\n SubmenuActionsContext,\n SubmenuGroupContext,\n SubmenuVisibleContext,\n useSubmenuGroupProvider\n} from './submenuGroup'\n\nexport interface MenuSubmenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /**\n * MenuSubmenu activation mode on hover-capable devices. `'click'` activates on click only.\n * `'hover'` activates on hover only. `'both'` (the default) activates on both. Touch\n * devices always use tap regardless of this setting.\n */\n activation?: 'click' | 'hover' | 'both'\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Prevents the submenu from opening.\n */\n disabled?: boolean\n /**\n * Distance between the nested menu and the trigger, as `[skidding, distance]` in pixels.\n */\n offset?: [number, number]\n /**\n * Placement of the nested menu relative to the trigger. Defaults to cascading in the reading\n * direction — `'right-start'` under LTR locales, `'left-start'` under RTL ones (see\n * `useLocale`) — matching native OS/browser submenu behavior. An explicit value always wins\n * over that locale-based default.\n */\n placement?: Placement\n /**\n * Switches to a view-replacement pattern below the `sm` breakpoint. Pair with a\n * `MenuSubmenuBack` as the first item of the nested menu.\n */\n stacked?: boolean\n /**\n * Milliseconds before closing the submenu when the pointer leaves it.\n */\n submenuDelay?: number\n /**\n * Content of the `.menu-item` trigger that opens the submenu.\n */\n trigger: ReactNode\n}\n\nexport const MenuSubmenu = forwardRef<HTMLDivElement, MenuSubmenuProps>(\n (\n {\n children,\n activation = 'both',\n className,\n disabled,\n offset: offsetProp = [-4, 0],\n placement,\n stacked,\n submenuDelay = 100,\n trigger,\n ...rest\n },\n ref\n ) => {\n const id = useId()\n const triggerId = `${id}-trigger`\n const menuId = `${id}-menu`\n const [visible, setVisible] = useState(false)\n const closeTimeoutRef = useRef<number | undefined>(undefined)\n const focusFirstRafRef = useRef<number | undefined>(undefined)\n const refocusTriggerRef = useRef(false)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const overlayRef = useRef<HTMLElement | null>(null)\n const parentGroup = useContext(SubmenuGroupContext)\n const ownGroup = useSubmenuGroupProvider()\n const { portalContainer, registerOverlay, visible: parentMenuVisible } = useContext(MenuContext)\n const parentSubmenuVisible = useContext(SubmenuVisibleContext)\n const { direction } = useLocale()\n const isRtl = direction === 'rtl'\n const effectivePlacement = placement ?? (isRtl ? 'left-start' : 'right-start')\n\n const { overlayProps, placement: resolvedPlacement } = useOverlayPosition({\n targetRef: triggerRef,\n overlayRef,\n // Viewport-relative (matching the portal below): the trigger lives inside the parent\n // menu's own floated panel, and `useOverlayPosition` measures against the overlay's real\n // containing block — since the panel portals straight to `document.body`, that resolves\n // the same way a `fixed`-strategy engine would.\n placement: toAriaPlacement(effectivePlacement),\n offset: offsetProp[1],\n crossOffset: offsetProp[0],\n containerPadding: 8,\n isOpen: visible,\n // See `useOverlayPlacement`'s comment for why this needs to be explicit `null`, not left\n // unset — matches the same fix already applied to `Autocomplete`/`Combobox`/`Menu`/`Popover`.\n onClose: null\n })\n useOverlayMaxHeight(overlayRef, visible)\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n effectivePlacement,\n resolvedPlacement\n )\n\n const clearCloseTimeout = useCallback(() => {\n if (closeTimeoutRef.current !== undefined) {\n window.clearTimeout(closeTimeoutRef.current)\n closeTimeoutRef.current = undefined\n }\n }, [])\n\n const cancelFocusFirstRaf = useCallback(() => {\n if (focusFirstRafRef.current !== undefined) {\n cancelAnimationFrame(focusFirstRafRef.current)\n focusFirstRafRef.current = undefined\n }\n }, [])\n\n const close = useCallback(() => {\n clearCloseTimeout()\n cancelFocusFirstRaf()\n setVisible(false)\n }, [clearCloseTimeout, cancelFocusFirstRaf])\n\n const open = () => {\n if (disabled || visible) return\n clearCloseTimeout()\n parentGroup?.notifyOpen(id)\n setVisible(true)\n }\n\n const scheduleClose = () => {\n clearCloseTimeout()\n closeTimeoutRef.current = window.setTimeout(close, submenuDelay)\n }\n\n useEffect(() => parentGroup?.register(id, close), [parentGroup, id, close])\n useEffect(() => clearCloseTimeout, [clearCloseTimeout])\n useEffect(() => cancelFocusFirstRaf, [cancelFocusFirstRaf])\n\n // The submenu's own open state is local and doesn't otherwise hear about its ancestor\n // `Menu` closing (via Escape, outside click, etc.), or about the submenu it is nested in\n // closing (the pointer leaving it, a sibling opening, ArrowLeft) — without this it's left\n // open and fully visible (it's portaled to `document.body`, so nothing hides it for free)\n // even after the menu or the submenu it belongs to has disappeared.\n useEffect(() => {\n if (!parentMenuVisible || !parentSubmenuVisible) close()\n }, [parentMenuVisible, parentSubmenuVisible, close])\n\n const supportsHover =\n typeof window !== 'undefined' &&\n !!window.matchMedia &&\n window.matchMedia('(hover: hover)').matches\n const hoverEnabled = supportsHover && (activation === 'hover' || activation === 'both')\n // A device without hover takes a tap whatever `activation` says, as the prop promises:\n // `'hover'` left nothing to open the submenu with there.\n const clickEnabled = activation !== 'hover' || !supportsHover\n\n const openAndFocusFirst = () => {\n open()\n cancelFocusFirstRaf()\n focusFirstRafRef.current = requestAnimationFrame(() => {\n focusFirstRafRef.current = undefined\n focusMenuItem(getMenuItems(overlayRef.current), 'first')\n })\n }\n\n // Focus returns to the trigger once the close has rendered, in the effect below, not here:\n // below the `sm` breakpoint a shown `stacked` panel hides its trigger (chassis-css's\n // `.submenu:has(.submenu-stacked.show)` rule), and focusing a hidden element leaves focus on\n // `document.body`.\n const closeAndRefocusTrigger = () => {\n refocusTriggerRef.current = true\n close()\n }\n\n useEffect(() => {\n if (!visible && refocusTriggerRef.current) triggerRef.current?.focus()\n refocusTriggerRef.current = false\n }, [visible])\n\n // Marked as a toggle's click even when it doesn't toggle the submenu (`activation=\"hover\"`):\n // the trigger is in the menu's list, and the menu's listener on `window` took the click for\n // an item's and closed the whole menu.\n const handleTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault()\n menuToggleClicks.add(event.nativeEvent)\n if (!clickEnabled || disabled) return\n visible ? close() : openAndFocusFirst()\n }\n\n // A submenu cascades toward the reading direction, so the arrow key that opens it (and the\n // one its own item list closes on, below) mirror too: ArrowRight/ArrowLeft under LTR,\n // ArrowLeft/ArrowRight under RTL.\n const openKey = isRtl ? 'ArrowLeft' : 'ArrowRight'\n\n const handleTriggerKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return\n if (event.key === 'Enter' || event.key === ' ' || event.key === openKey) {\n event.preventDefault()\n event.stopPropagation()\n openAndFocusFirst()\n }\n }\n\n const actionsValue = { close: closeAndRefocusTrigger }\n\n return (\n <div className={classNames('submenu', { show: visible }, className)} {...rest} ref={ref}>\n <button\n type=\"button\"\n id={triggerId}\n role=\"menuitem\"\n className=\"menu-item\"\n aria-expanded={visible}\n aria-haspopup=\"true\"\n aria-controls={visible ? menuId : undefined}\n disabled={disabled}\n onClick={handleTriggerClick}\n onKeyDown={handleTriggerKeyDown}\n onMouseEnter={hoverEnabled ? open : undefined}\n onMouseLeave={hoverEnabled ? scheduleClose : undefined}\n ref={(node) => {\n triggerRef.current = node\n }}\n >\n {trigger}\n </button>\n {(() => {\n const panel = (\n <div\n role=\"menu\"\n id={menuId}\n aria-labelledby={triggerId}\n className={classNames('menu', { show: visible, 'submenu-stacked': stacked })}\n style={menuStyle}\n data-cx-placement={placementAttr}\n onKeyDown={(event) =>\n handleMenuKeyDown(event, {\n onEscape: closeAndRefocusTrigger,\n ...(isRtl\n ? { onArrowRight: closeAndRefocusTrigger }\n : { onArrowLeft: closeAndRefocusTrigger })\n })\n }\n onMouseEnter={hoverEnabled ? clearCloseTimeout : undefined}\n onMouseLeave={hoverEnabled ? scheduleClose : undefined}\n // Registers this panel with the ancestor `Menu` (see `MenuContext.registerOverlay`)\n // so its own click-dismiss logic recognizes clicks here as \"inside\" the menu — the\n // panel portals straight to `document.body` when not `stacked`, so plain DOM\n // containment against the top-level menu's own element wouldn't otherwise see it.\n ref={(node) => {\n overlayRef.current = node\n registerOverlay(menuId, node)\n }}\n >\n <SubmenuActionsContext.Provider value={actionsValue}>\n <SubmenuGroupContext.Provider value={ownGroup}>\n <SubmenuVisibleContext.Provider value={visible}>\n {children}\n </SubmenuVisibleContext.Provider>\n </SubmenuGroupContext.Provider>\n </SubmenuActionsContext.Provider>\n </div>\n )\n\n // `stacked`'s sm-breakpoint CSS (`.menu:has(.submenu-stacked.show) ...`) needs the\n // panel to be a real DOM descendant of `.menu`/`.submenu` to match — portaling would\n // break that ancestor relationship, so it renders inline instead. Trade-off: above the\n // `sm` breakpoint a `stacked` submenu no longer escapes ancestor overflow/stacking-\n // context clipping the way a portaled one does; accepted since `stacked` targets mobile\n // nav/drawer usage, not floating dropdowns.\n // On the server and during hydration the panel renders inline next to its trigger, which\n // is what the server's HTML holds; `Portal` moves it to `document.body` afterwards, or\n // to the open dialog the menu is in: under a modal dialog's top layer the panel would be\n // behind the backdrop, and inert.\n return stacked ? (\n panel\n ) : (\n <Portal container={portalContainer} fallback={panel}>\n {panel}\n </Portal>\n )\n })()}\n </div>\n )\n }\n)\n\nMenuSubmenu.displayName = 'MenuSubmenu'\n","import React, { ButtonHTMLAttributes, forwardRef, useContext } from 'react'\nimport classNames from 'classnames'\n\nimport { SubmenuActionsContext } from './submenuGroup'\n\nexport interface MenuSubmenuBackProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n}\n\n// First item of a stacked submenu's nested menu (see `MenuSubmenu`'s `stacked` prop). Closes\n// the submenu and returns focus to its trigger — visible only below the `sm` breakpoint.\nexport const MenuSubmenuBack = forwardRef<HTMLButtonElement, MenuSubmenuBackProps>(\n ({ children, className, onClick, type = 'button', ...rest }, ref) => {\n const actions = useContext(SubmenuActionsContext)\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event)\n if (!actions) return\n // Going back is the submenu's own action, as opening it from its trigger is: the click\n // stops here. On `window`, the `autoClose` listener of `Menu` and `ContextMenu` would read\n // it as a click on an item and close the whole menu.\n event.stopPropagation()\n actions.close()\n }\n\n return (\n <button\n type={type}\n role=\"menuitem\"\n className={classNames('submenu-back', 'menu-item', className)}\n {...rest}\n onClick={handleClick}\n ref={ref}\n >\n {children}\n </button>\n )\n }\n)\n\nMenuSubmenuBack.displayName = 'MenuSubmenuBack'\n"],"mappings":"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"}
1
+ {"version":3,"file":"menu-Bqlhottl.js","names":["createPolymorphicComponent","toAriaPlacement","Portal","MenuContext","menuToggleClicks","SubmenuVisibleContext","getMenuItems","SubmenuGroupContext","handleMenuKeyDown","useSubmenuGroupProvider","SubmenuActionsContext","focusMenuItem","React","classNames","MenuTextRender","rest","Component","component","_className","className","children","MenuText","MenuSubmenu","forwardRef","offsetProp","id","useId","triggerId","menuId","visible","setVisible","useState","closeTimeoutRef","useRef","focusFirstRafRef","refocusTriggerRef","triggerRef","overlayRef","parentGroup","useContext","ownGroup","parentMenuVisible","parentSubmenuVisible","useLocale","isRtl","direction","effectivePlacement","placement","resolvedPlacement","useOverlayPosition","useOverlayMaxHeight","resolveMenuOverlayPositioning","overlayProps","clearCloseTimeout","useCallback","cancelFocusFirstRaf","close","open","disabled","scheduleClose","submenuDelay","useEffect","supportsHover","hoverEnabled","activation","clickEnabled","openAndFocusFirst","closeAndRefocusTrigger","handleTriggerClick","event","openKey","handleTriggerKeyDown","actionsValue","node","trigger","panel","stacked","menuStyle","placementAttr","registerOverlay","portalContainer","MenuSubmenuBack","actions","handleClick","onClick"],"sources":["../../src/components/menu/MenuText.tsx","../../src/components/menu/MenuSubmenu.tsx","../../src/components/menu/MenuSubmenuBack.tsx"],"sourcesContent":["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 MenuTextOwnProps<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\nexport type MenuTextProps<C extends ElementType = 'span'> = PolymorphicComponentProps<\n C,\n MenuTextOwnProps<C>\n>\n\ntype MenuTextComponent = (<C extends ElementType = 'span'>(\n props: MenuTextProps<C> & { ref?: PolymorphicRef<C> }\n) => ReactElement | null) & { displayName?: string }\n\nfunction MenuTextRender<C extends ElementType = 'span'>(\n { children, className, component, ...rest }: MenuTextProps<C>,\n ref: PolymorphicRef<C>\n) {\n const Component = component ?? 'span'\n const _className = classNames('menu-text', className)\n\n return (\n <Component className={_className} {...rest} ref={ref}>\n {children}\n </Component>\n )\n}\n\nexport const MenuText = createPolymorphicComponent<MenuTextComponent>(\n MenuTextRender as ForwardRefRenderFunction<Element, MenuTextProps<ElementType>>,\n 'MenuText'\n)\n","import React, {\n forwardRef,\n HTMLAttributes,\n ReactNode,\n useCallback,\n useContext,\n useEffect,\n useId,\n useRef,\n useState\n} from 'react'\nimport classNames from 'classnames'\nimport { useLocale, useOverlayPosition } from 'react-aria'\n\nimport { useOverlayMaxHeight } from '../../hooks/useOverlayMaxHeight'\nimport { MenuContext, menuToggleClicks } from './Menu'\nimport {\n Placement,\n resolveMenuOverlayPositioning,\n toAriaPlacement\n} from '../../utils/overlayPlacement'\nimport { Portal } from '../portal/Portal'\nimport { focusMenuItem, getMenuItems, handleMenuKeyDown } from './menuNavigation'\nimport {\n SubmenuActionsContext,\n SubmenuGroupContext,\n SubmenuVisibleContext,\n useSubmenuGroupProvider\n} from './submenuGroup'\n\nexport interface MenuSubmenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /**\n * MenuSubmenu activation mode on hover-capable devices. `'click'` activates on click only.\n * `'hover'` activates on hover only. `'both'` (the default) activates on both. Touch\n * devices always use tap regardless of this setting.\n */\n activation?: 'click' | 'hover' | 'both'\n /**\n * A string of all className you want applied to the base component.\n */\n className?: string\n /**\n * Prevents the submenu from opening.\n */\n disabled?: boolean\n /**\n * Distance between the nested menu and the trigger, as `[skidding, distance]` in pixels.\n */\n offset?: [number, number]\n /**\n * Placement of the nested menu relative to the trigger. Defaults to cascading in the reading\n * direction — `'right-start'` under LTR locales, `'left-start'` under RTL ones (see\n * `useLocale`) — matching native OS/browser submenu behavior. An explicit value always wins\n * over that locale-based default.\n */\n placement?: Placement\n /**\n * Switches to a view-replacement pattern below the `sm` breakpoint. Pair with a\n * `MenuSubmenuBack` as the first item of the nested menu.\n */\n stacked?: boolean\n /**\n * Milliseconds before closing the submenu when the pointer leaves it.\n */\n submenuDelay?: number\n /**\n * Content of the `.menu-item` trigger that opens the submenu.\n */\n trigger: ReactNode\n}\n\nexport const MenuSubmenu = forwardRef<HTMLDivElement, MenuSubmenuProps>(\n (\n {\n children,\n activation = 'both',\n className,\n disabled,\n offset: offsetProp = [-4, 0],\n placement,\n stacked,\n submenuDelay = 100,\n trigger,\n ...rest\n },\n ref\n ) => {\n const id = useId()\n const triggerId = `${id}-trigger`\n const menuId = `${id}-menu`\n const [visible, setVisible] = useState(false)\n const closeTimeoutRef = useRef<number | undefined>(undefined)\n const focusFirstRafRef = useRef<number | undefined>(undefined)\n const refocusTriggerRef = useRef(false)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const overlayRef = useRef<HTMLElement | null>(null)\n const parentGroup = useContext(SubmenuGroupContext)\n const ownGroup = useSubmenuGroupProvider()\n const { portalContainer, registerOverlay, visible: parentMenuVisible } = useContext(MenuContext)\n const parentSubmenuVisible = useContext(SubmenuVisibleContext)\n const { direction } = useLocale()\n const isRtl = direction === 'rtl'\n const effectivePlacement = placement ?? (isRtl ? 'left-start' : 'right-start')\n\n const { overlayProps, placement: resolvedPlacement } = useOverlayPosition({\n targetRef: triggerRef,\n overlayRef,\n // Viewport-relative (matching the portal below): the trigger lives inside the parent\n // menu's own floated panel, and `useOverlayPosition` measures against the overlay's real\n // containing block — since the panel portals straight to `document.body`, that resolves\n // the same way a `fixed`-strategy engine would.\n placement: toAriaPlacement(effectivePlacement),\n offset: offsetProp[1],\n crossOffset: offsetProp[0],\n containerPadding: 8,\n isOpen: visible,\n // See `useOverlayPlacement`'s comment for why this needs to be explicit `null`, not left\n // unset — matches the same fix already applied to `Autocomplete`/`Combobox`/`Menu`/`Popover`.\n onClose: null\n })\n useOverlayMaxHeight(overlayRef, visible)\n\n const { menuStyle, placementAttr } = resolveMenuOverlayPositioning(\n overlayProps.style,\n effectivePlacement,\n resolvedPlacement\n )\n\n const clearCloseTimeout = useCallback(() => {\n if (closeTimeoutRef.current !== undefined) {\n window.clearTimeout(closeTimeoutRef.current)\n closeTimeoutRef.current = undefined\n }\n }, [])\n\n const cancelFocusFirstRaf = useCallback(() => {\n if (focusFirstRafRef.current !== undefined) {\n cancelAnimationFrame(focusFirstRafRef.current)\n focusFirstRafRef.current = undefined\n }\n }, [])\n\n const close = useCallback(() => {\n clearCloseTimeout()\n cancelFocusFirstRaf()\n setVisible(false)\n }, [clearCloseTimeout, cancelFocusFirstRaf])\n\n const open = () => {\n if (disabled || visible) return\n clearCloseTimeout()\n parentGroup?.notifyOpen(id)\n setVisible(true)\n }\n\n const scheduleClose = () => {\n clearCloseTimeout()\n closeTimeoutRef.current = window.setTimeout(close, submenuDelay)\n }\n\n useEffect(() => parentGroup?.register(id, close), [parentGroup, id, close])\n useEffect(() => clearCloseTimeout, [clearCloseTimeout])\n useEffect(() => cancelFocusFirstRaf, [cancelFocusFirstRaf])\n\n // The submenu's own open state is local and doesn't otherwise hear about its ancestor\n // `Menu` closing (via Escape, outside click, etc.), or about the submenu it is nested in\n // closing (the pointer leaving it, a sibling opening, ArrowLeft) — without this it's left\n // open and fully visible (it's portaled to `document.body`, so nothing hides it for free)\n // even after the menu or the submenu it belongs to has disappeared.\n useEffect(() => {\n if (!parentMenuVisible || !parentSubmenuVisible) close()\n }, [parentMenuVisible, parentSubmenuVisible, close])\n\n const supportsHover =\n typeof window !== 'undefined' &&\n !!window.matchMedia &&\n window.matchMedia('(hover: hover)').matches\n const hoverEnabled = supportsHover && (activation === 'hover' || activation === 'both')\n // A device without hover takes a tap whatever `activation` says, as the prop promises:\n // `'hover'` left nothing to open the submenu with there.\n const clickEnabled = activation !== 'hover' || !supportsHover\n\n const openAndFocusFirst = () => {\n open()\n cancelFocusFirstRaf()\n focusFirstRafRef.current = requestAnimationFrame(() => {\n focusFirstRafRef.current = undefined\n focusMenuItem(getMenuItems(overlayRef.current), 'first')\n })\n }\n\n // Focus returns to the trigger once the close has rendered, in the effect below, not here:\n // below the `sm` breakpoint a shown `stacked` panel hides its trigger (chassis-css's\n // `.submenu:has(.submenu-stacked.show)` rule), and focusing a hidden element leaves focus on\n // `document.body`.\n const closeAndRefocusTrigger = () => {\n refocusTriggerRef.current = true\n close()\n }\n\n useEffect(() => {\n if (!visible && refocusTriggerRef.current) triggerRef.current?.focus()\n refocusTriggerRef.current = false\n }, [visible])\n\n // Marked as a toggle's click even when it doesn't toggle the submenu (`activation=\"hover\"`):\n // the trigger is in the menu's list, and the menu's listener on `window` took the click for\n // an item's and closed the whole menu.\n const handleTriggerClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n event.preventDefault()\n menuToggleClicks.add(event.nativeEvent)\n if (!clickEnabled || disabled) return\n visible ? close() : openAndFocusFirst()\n }\n\n // A submenu cascades toward the reading direction, so the arrow key that opens it (and the\n // one its own item list closes on, below) mirror too: ArrowRight/ArrowLeft under LTR,\n // ArrowLeft/ArrowRight under RTL.\n const openKey = isRtl ? 'ArrowLeft' : 'ArrowRight'\n\n const handleTriggerKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return\n if (event.key === 'Enter' || event.key === ' ' || event.key === openKey) {\n event.preventDefault()\n event.stopPropagation()\n openAndFocusFirst()\n }\n }\n\n const actionsValue = { close: closeAndRefocusTrigger }\n\n return (\n <div className={classNames('submenu', { show: visible }, className)} {...rest} ref={ref}>\n <button\n type=\"button\"\n id={triggerId}\n role=\"menuitem\"\n className=\"menu-item\"\n aria-expanded={visible}\n aria-haspopup=\"true\"\n aria-controls={visible ? menuId : undefined}\n disabled={disabled}\n onClick={handleTriggerClick}\n onKeyDown={handleTriggerKeyDown}\n onMouseEnter={hoverEnabled ? open : undefined}\n onMouseLeave={hoverEnabled ? scheduleClose : undefined}\n ref={(node) => {\n triggerRef.current = node\n }}\n >\n {trigger}\n </button>\n {(() => {\n const panel = (\n <div\n role=\"menu\"\n id={menuId}\n aria-labelledby={triggerId}\n className={classNames('menu', { show: visible, 'submenu-stacked': stacked })}\n style={menuStyle}\n data-cx-placement={placementAttr}\n onKeyDown={(event) =>\n handleMenuKeyDown(event, {\n onEscape: closeAndRefocusTrigger,\n ...(isRtl\n ? { onArrowRight: closeAndRefocusTrigger }\n : { onArrowLeft: closeAndRefocusTrigger })\n })\n }\n onMouseEnter={hoverEnabled ? clearCloseTimeout : undefined}\n onMouseLeave={hoverEnabled ? scheduleClose : undefined}\n // Registers this panel with the ancestor `Menu` (see `MenuContext.registerOverlay`)\n // so its own click-dismiss logic recognizes clicks here as \"inside\" the menu — the\n // panel portals straight to `document.body` when not `stacked`, so plain DOM\n // containment against the top-level menu's own element wouldn't otherwise see it.\n ref={(node) => {\n overlayRef.current = node\n registerOverlay(menuId, node)\n }}\n >\n <SubmenuActionsContext.Provider value={actionsValue}>\n <SubmenuGroupContext.Provider value={ownGroup}>\n <SubmenuVisibleContext.Provider value={visible}>\n {children}\n </SubmenuVisibleContext.Provider>\n </SubmenuGroupContext.Provider>\n </SubmenuActionsContext.Provider>\n </div>\n )\n\n // `stacked`'s sm-breakpoint CSS (`.menu:has(.submenu-stacked.show) ...`) needs the\n // panel to be a real DOM descendant of `.menu`/`.submenu` to match — portaling would\n // break that ancestor relationship, so it renders inline instead. Trade-off: above the\n // `sm` breakpoint a `stacked` submenu no longer escapes ancestor overflow/stacking-\n // context clipping the way a portaled one does; accepted since `stacked` targets mobile\n // nav/drawer usage, not floating dropdowns.\n // On the server and during hydration the panel renders inline next to its trigger, which\n // is what the server's HTML holds; `Portal` moves it to `document.body` afterwards, or\n // to the open dialog the menu is in: under a modal dialog's top layer the panel would be\n // behind the backdrop, and inert.\n return stacked ? (\n panel\n ) : (\n <Portal container={portalContainer} fallback={panel}>\n {panel}\n </Portal>\n )\n })()}\n </div>\n )\n }\n)\n\nMenuSubmenu.displayName = 'MenuSubmenu'\n","import React, { ButtonHTMLAttributes, forwardRef, useContext } from 'react'\nimport classNames from 'classnames'\n\nimport { SubmenuActionsContext } from './submenuGroup'\n\nexport interface MenuSubmenuBackProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /**\n * A string of all className you want applied to the component.\n */\n className?: string\n}\n\n// First item of a stacked submenu's nested menu (see `MenuSubmenu`'s `stacked` prop). Closes\n// the submenu and returns focus to its trigger — visible only below the `sm` breakpoint.\nexport const MenuSubmenuBack = forwardRef<HTMLButtonElement, MenuSubmenuBackProps>(\n ({ children, className, onClick, type = 'button', ...rest }, ref) => {\n const actions = useContext(SubmenuActionsContext)\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event)\n if (!actions) return\n // Going back is the submenu's own action, as opening it from its trigger is: the click\n // stops here. On `window`, the `autoClose` listener of `Menu` and `ContextMenu` would read\n // it as a click on an item and close the whole menu.\n event.stopPropagation()\n actions.close()\n }\n\n return (\n <button\n type={type}\n role=\"menuitem\"\n className={classNames('submenu-back', 'menu-item', className)}\n {...rest}\n onClick={handleClick}\n ref={ref}\n >\n {children}\n </button>\n )\n }\n)\n\nMenuSubmenuBack.displayName = 'MenuSubmenuBack'\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import"./focus-ring-Bs80iIBN.js";import{S as e}from"./slot-BQVx1Eew.js";import{t}from"./useForkedRef-WoqMqsWE.js";import{t as n}from"./polymorphic-CZIFszAy.js";import{t as r}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{t as i}from"./useHydrated-Dud4JEwp.js";import{t as a}from"./iconSlot-DU_WcSL_.js";import{n as o}from"./navOverflow-C_QJmkPM.js";import{t as s}from"./Menu-264aGoBR.js";import{n as c,t as l,u}from"./MenuToggle-DcPEh55c.js";import d,{createContext as f,useCallback as p,useContext as m,useEffect as h,useMemo as g,useRef as _,useState as v,useSyncExternalStore as y}from"react";import b from"classnames";import{flushSync as x}from"react-dom";const S=f(null);function C(e){for(let t=e.previousElementSibling;t;t=t.previousElementSibling){if(t.hasAttribute(`data-cx-nav-overflow`))continue;let e=t.querySelector(`a[href], button:not(:disabled), [tabindex]`);if(e)return e}return null}function w({tabs:e}){let t=m(S),[n,i]=v(!1),o=_(null),f=_(!1),p=t?.hidden,h=!p?.length;r(()=>{let e=o.current;if(!e||!f.current)return;let t=e.ownerDocument.activeElement;(!t||t===e.ownerDocument.body||h&&e.contains(t))&&(f.current=!h,(h?C(e):e.querySelector(`.nav-overflow-toggle`))?.focus())},[p,h]);let g=t=>{f.current=!0,e&&t.stopPropagation()},x=()=>{f.current=!1};if(y(t?.subscribe??D,t?.getVersion??O,t?.getVersion??O),!t||!p)return null;let{getLink:w,iconPlacement:k,menuContainer:A,menuPlacement:j,moreIcon:M,moreLabel:N,moreText:P}=t;h&&n&&i(!1);let F=/* @__PURE__ */ d.createElement(`span`,{key:`icon`,className:`nav-overflow-icon`,style:E},/* @__PURE__ */ d.createElement(a,{icon:`more`,override:M})),I=P===!1?null:/* @__PURE__ */ d.createElement(`span`,{key:`text`,className:`nav-overflow-text`},P);return/* @__PURE__ */ d.createElement(s,{component:`li`,className:b(`nav-item nav-overflow-item`,{[T]:h}),container:e&&typeof A!=`object`||A,onBlur:x,onFocus:g,onVisibleChange:i,placement:j,visible:n&&!h,...e&&{role:`presentation`},ref:o},/* @__PURE__ */ d.createElement(l,{"aria-label":P===!1?N:void 0,caret:!1,className:`nav-link nav-overflow-toggle`,component:`button`,...e&&{"aria-selected":!1,role:`tab`,tabIndex:-1}},k===`end`?[I,F]:[F,I]),/* @__PURE__ */ d.createElement(c,{className:`nav-overflow-menu`},p.map(e=>{let t=w(e);return t&&/* @__PURE__ */ d.createElement(u,{key:e,...t})})))}const T=`d-none`,E={"--cx-icon-color":`currentcolor`,"--cx-icon-size":`1rem`},D=()=>()=>{},O=()=>0;function k({available:e,collapseAll:t,gap:n,items:r,more:i,threshold:a}){let o=r.filter(e=>!e.keep),s=e=>e.map(e=>e.id);if(t)return s(o);if(r.reduce((e,t)=>e+t.width,0)+n*(r.length-1)<=e+1)return[];let c=i+r.reduce((e,t)=>t.keep?e+t.width+n:e,0),l=o.filter(t=>(c+=t.width+n,c>e+1));return r.length-l.length<a&&(l=r.slice(a).filter(e=>!e.keep)),s(l)}function A(){let e=/* @__PURE__ */ new Map,t=/* @__PURE__ */ new Set,n=0,r=t=>{let n=e.get(t);return n||(n={element:null,link:null},e.set(t,n)),n};return{entries:e,getVersion:()=>n,notify:()=>{n+=1,t.forEach(e=>e())},set:(t,n)=>{let i=Object.assign(r(t),n);!i.element&&!i.link&&e.delete(t)},subscribe:e=>(t.add(e),()=>{t.delete(e)})}}const j=`data-cx-nav-overflow`,M=`d-none`,N=[],P=e=>Number.parseFloat(e)||0,F=e=>`offsetWidth`in e,I=(e,t)=>e.length===t.length&&e.every((e,n)=>e===t[n]);function ee(e,t){if(typeof e==`number`)return e;if(!e)return 0;let n=getComputedStyle(t.ownerDocument.documentElement),r=n.getPropertyValue(`--cx-breakpoint-${e}`).trim();return/r?em$/.test(r)?P(r)*(P(n.fontSize)||16):P(r)}const te={overflowX:`auto`,scrollbarWidth:`none`};function L({children:n,className:a,collapseBelow:s,component:c,iconPlacement:l=`start`,menuContainer:u,menuPlacement:f=`bottom-end`,moreIcon:m,moreLabel:y=`More`,moreText:C=`More`,onOverflow:T,style:E,threshold:D=0,...O},L){let R=c??`div`,z=_(null),ne=p(e=>{e&&(z.current=e)},[]),re=t(L,ne),ie=i(),[B]=v(A),[V,H]=v(N),U=_(V),W=_(0),G=_({collapseBelow:s,threshold:D});G.current={collapseBelow:s,threshold:D};let K=_(null),q=p(()=>{let t=z.current?.isConnected?z.current:null,n=t&&Array.from(t.children).find(e=>e.matches(`.nav`));if(e(!!t&&!n,"NavOverflow: expects a `Nav`, a `NavbarNav` or a `TabList` as its child; found no `.nav` to collapse."),!t||!n)return null;let r=Array.from(n.children).filter(F),i=r.find(e=>e.classList.contains(`nav-overflow-item`)),a=r.filter(e=>e!==i);if(Y(t,n,r),W.current=a.length,!i)return[];let o=/* @__PURE__ */ new Map;B.entries.forEach((e,t)=>{e.element&&o.set(e.element,t)});let s=a.filter(e=>e.hasAttribute(j)),c=i.classList.contains(M);s.forEach(e=>e.removeAttribute(j)),i.classList.remove(M);try{let e=getComputedStyle(t),r=getComputedStyle(n),s=t.clientWidth-P(e.paddingInlineStart)-P(e.paddingInlineEnd),c=t.ownerDocument.activeElement,l=a.map(e=>{let t=o.get(e);return{id:t,keep:!t||!B.entries.get(t)?.link||e.classList.contains(`nav-overflow-keep`)||e.querySelector(`.nav-link.active, .nav-link[aria-current]:not([aria-current="false"]), [role="tab"][tabindex="0"]`)!==null||e.contains(c),width:e.offsetWidth}}),{collapseBelow:u,threshold:d}=G.current;return k({available:s-P(r.paddingInlineStart)-P(r.paddingInlineEnd)-P(r.borderInlineStartWidth)-P(r.borderInlineEndWidth),collapseAll:s<ee(u,t),gap:P(r.columnGap),items:l,more:i.offsetWidth,threshold:d})}finally{s.forEach(e=>e.setAttribute(j,`true`)),c&&i.classList.add(M),t.offsetWidth,K.current?.mutation?.takeRecords()}},[B]),J=p(()=>{let e=q();e&&!I(e,U.current)&&(U.current=e,H(e))},[q]);function Y(e,t,n){let r=K.current;if(r&&r.wrapper!==e&&(X(),r=null),!r){let t=()=>x(J),n={frame:0,mutation:typeof MutationObserver>`u`?null:new MutationObserver(t),nav:null,observed:/* @__PURE__ */ new Set,resize:typeof ResizeObserver>`u`?null:new ResizeObserver(r=>{if(!r.some(t=>t.target===e)){cancelAnimationFrame(n.frame),n.frame=requestAnimationFrame(t);return}let i=U.current;t(),U.current!==i&&K.current===n&&(n.resize?.unobserve(e),cancelAnimationFrame(n.wrapperFrame),n.wrapperFrame=requestAnimationFrame(()=>n.resize?.observe(e)))}),wrapperFrame:0,wrapper:e};r=K.current=n,r.resize?.observe(e)}let{mutation:i,observed:a,resize:o}=r;r.nav!==t&&(r.nav=t,i?.disconnect(),i?.observe(t,{attributeFilter:[`class`,`aria-current`],attributes:!0,childList:!0,subtree:!0}));let s=new Set(n);a.forEach(e=>{s.has(e)||(o?.unobserve(e),a.delete(e))}),s.forEach(e=>{a.has(e)||(o?.observe(e),a.add(e))})}function X(){let e=K.current;e&&(cancelAnimationFrame(e.frame),cancelAnimationFrame(e.wrapperFrame),e.mutation?.disconnect(),e.resize?.disconnect(),K.current=null)}h(()=>X,[]),r(J,[J,R,s,D]);let Z=_(V);h(()=>{Z.current!==V&&(Z.current=V,T?.({overflowCount:V.length,visibleCount:W.current-V.length}))},[V]);let Q=p((e,t)=>B.set(e,{element:t}),[B]),$=p((e,t)=>{B.set(e,{link:t}),U.current.includes(e)&&B.notify()},[B]),ae=g(()=>({hidden:V,More:w,registerItem:Q,registerLink:$,update:J}),[V,Q,$,J]),oe=g(()=>({getLink:e=>B.entries.get(e)?.link??null,getVersion:B.getVersion,hidden:V,iconPlacement:l,menuContainer:u,menuPlacement:f,moreIcon:m,moreLabel:y,moreText:C,subscribe:B.subscribe}),[V,l,u,f,m,y,C,B]);return/* @__PURE__ */ d.createElement(o.Provider,{value:ae},/* @__PURE__ */ d.createElement(S.Provider,{value:oe},/* @__PURE__ */ d.createElement(R,{className:b(`nav-overflow`,a),style:ie?E:{...te,...E},...O,ref:re},n)))}const R=n(L,`NavOverflow`);export{R as t};
2
- //# sourceMappingURL=nav-overflow-DpX_lRYf.js.map
1
+ import"./focus-ring-Bs80iIBN.js";import{S as e}from"./slot-BQVx1Eew.js";import{t}from"./useForkedRef-WoqMqsWE.js";import{t as n}from"./polymorphic-CZIFszAy.js";import{t as r}from"./useIsomorphicLayoutEffect-BbqRwuqn.js";import{t as i}from"./useHydrated-Dud4JEwp.js";import{t as a}from"./iconSlot-DU_WcSL_.js";import{n as o}from"./navOverflow-C_QJmkPM.js";import{t as s}from"./Menu-BiE9CzNk.js";import{n as c,t as l,u}from"./MenuToggle-W-ZSHFwF.js";import d,{createContext as f,useCallback as p,useContext as m,useEffect as h,useMemo as g,useRef as _,useState as v,useSyncExternalStore as y}from"react";import b from"classnames";import{flushSync as x}from"react-dom";const S=f(null);function C(e){for(let t=e.previousElementSibling;t;t=t.previousElementSibling){if(t.hasAttribute(`data-cx-nav-overflow`))continue;let e=t.querySelector(`a[href], button:not(:disabled), [tabindex]`);if(e)return e}return null}function w({tabs:e}){let t=m(S),[n,i]=v(!1),o=_(null),f=_(!1),p=t?.hidden,h=!p?.length;r(()=>{let e=o.current;if(!e||!f.current)return;let t=e.ownerDocument.activeElement;(!t||t===e.ownerDocument.body||h&&e.contains(t))&&(f.current=!h,(h?C(e):e.querySelector(`.nav-overflow-toggle`))?.focus())},[p,h]);let g=t=>{f.current=!0,e&&t.stopPropagation()},x=()=>{f.current=!1};if(y(t?.subscribe??D,t?.getVersion??O,t?.getVersion??O),!t||!p)return null;let{getLink:w,iconPlacement:k,menuContainer:A,menuPlacement:j,moreIcon:M,moreLabel:N,moreText:P}=t;h&&n&&i(!1);let F=/* @__PURE__ */ d.createElement(`span`,{key:`icon`,className:`nav-overflow-icon`,style:E},/* @__PURE__ */ d.createElement(a,{icon:`more`,override:M})),I=P===!1?null:/* @__PURE__ */ d.createElement(`span`,{key:`text`,className:`nav-overflow-text`},P);return/* @__PURE__ */ d.createElement(s,{component:`li`,className:b(`nav-item nav-overflow-item`,{[T]:h}),container:e&&typeof A!=`object`||A,onBlur:x,onFocus:g,onVisibleChange:i,placement:j,visible:n&&!h,...e&&{role:`presentation`},ref:o},/* @__PURE__ */ d.createElement(l,{"aria-label":P===!1?N:void 0,caret:!1,className:`nav-link nav-overflow-toggle`,component:`button`,...e&&{"aria-selected":!1,role:`tab`,tabIndex:-1}},k===`end`?[I,F]:[F,I]),/* @__PURE__ */ d.createElement(c,{className:`nav-overflow-menu`},p.map(e=>{let t=w(e);return t&&/* @__PURE__ */ d.createElement(u,{key:e,...t})})))}const T=`d-none`,E={"--cx-icon-color":`currentcolor`,"--cx-icon-size":`1rem`},D=()=>()=>{},O=()=>0;function k({available:e,collapseAll:t,gap:n,items:r,more:i,threshold:a}){let o=r.filter(e=>!e.keep),s=e=>e.map(e=>e.id);if(t)return s(o);if(r.reduce((e,t)=>e+t.width,0)+n*(r.length-1)<=e+1)return[];let c=i+r.reduce((e,t)=>t.keep?e+t.width+n:e,0),l=o.filter(t=>(c+=t.width+n,c>e+1));return r.length-l.length<a&&(l=r.slice(a).filter(e=>!e.keep)),s(l)}function A(){let e=/* @__PURE__ */ new Map,t=/* @__PURE__ */ new Set,n=0,r=t=>{let n=e.get(t);return n||(n={element:null,link:null},e.set(t,n)),n};return{entries:e,getVersion:()=>n,notify:()=>{n+=1,t.forEach(e=>e())},set:(t,n)=>{let i=Object.assign(r(t),n);!i.element&&!i.link&&e.delete(t)},subscribe:e=>(t.add(e),()=>{t.delete(e)})}}const j=`data-cx-nav-overflow`,M=`d-none`,N=[],P=e=>Number.parseFloat(e)||0,F=e=>`offsetWidth`in e,I=(e,t)=>e.length===t.length&&e.every((e,n)=>e===t[n]);function ee(e,t){if(typeof e==`number`)return e;if(!e)return 0;let n=getComputedStyle(t.ownerDocument.documentElement),r=n.getPropertyValue(`--cx-breakpoint-${e}`).trim();return/r?em$/.test(r)?P(r)*(P(n.fontSize)||16):P(r)}const te={overflowX:`auto`,scrollbarWidth:`none`};function L({children:n,className:a,collapseBelow:s,component:c,iconPlacement:l=`start`,menuContainer:u,menuPlacement:f=`bottom-end`,moreIcon:m,moreLabel:y=`More`,moreText:C=`More`,onOverflow:T,style:E,threshold:D=0,...O},L){let R=c??`div`,z=_(null),ne=p(e=>{e&&(z.current=e)},[]),re=t(L,ne),ie=i(),[B]=v(A),[V,H]=v(N),U=_(V),W=_(0),G=_({collapseBelow:s,threshold:D});G.current={collapseBelow:s,threshold:D};let K=_(null),q=p(()=>{let t=z.current?.isConnected?z.current:null,n=t&&Array.from(t.children).find(e=>e.matches(`.nav`));if(e(!!t&&!n,"NavOverflow: expects a `Nav`, a `NavbarNav` or a `TabList` as its child; found no `.nav` to collapse."),!t||!n)return null;let r=Array.from(n.children).filter(F),i=r.find(e=>e.classList.contains(`nav-overflow-item`)),a=r.filter(e=>e!==i);if(Y(t,n,r),W.current=a.length,!i)return[];let o=/* @__PURE__ */ new Map;B.entries.forEach((e,t)=>{e.element&&o.set(e.element,t)});let s=a.filter(e=>e.hasAttribute(j)),c=i.classList.contains(M);s.forEach(e=>e.removeAttribute(j)),i.classList.remove(M);try{let e=getComputedStyle(t),r=getComputedStyle(n),s=t.clientWidth-P(e.paddingInlineStart)-P(e.paddingInlineEnd),c=t.ownerDocument.activeElement,l=a.map(e=>{let t=o.get(e);return{id:t,keep:!t||!B.entries.get(t)?.link||e.classList.contains(`nav-overflow-keep`)||e.querySelector(`.nav-link.active, .nav-link[aria-current]:not([aria-current="false"]), [role="tab"][tabindex="0"]`)!==null||e.contains(c),width:e.offsetWidth}}),{collapseBelow:u,threshold:d}=G.current;return k({available:s-P(r.paddingInlineStart)-P(r.paddingInlineEnd)-P(r.borderInlineStartWidth)-P(r.borderInlineEndWidth),collapseAll:s<ee(u,t),gap:P(r.columnGap),items:l,more:i.offsetWidth,threshold:d})}finally{s.forEach(e=>e.setAttribute(j,`true`)),c&&i.classList.add(M),t.offsetWidth,K.current?.mutation?.takeRecords()}},[B]),J=p(()=>{let e=q();e&&!I(e,U.current)&&(U.current=e,H(e))},[q]);function Y(e,t,n){let r=K.current;if(r&&r.wrapper!==e&&(X(),r=null),!r){let t=()=>x(J),n={frame:0,mutation:typeof MutationObserver>`u`?null:new MutationObserver(t),nav:null,observed:/* @__PURE__ */ new Set,resize:typeof ResizeObserver>`u`?null:new ResizeObserver(r=>{if(!r.some(t=>t.target===e)){cancelAnimationFrame(n.frame),n.frame=requestAnimationFrame(t);return}let i=U.current;t(),U.current!==i&&K.current===n&&(n.resize?.unobserve(e),cancelAnimationFrame(n.wrapperFrame),n.wrapperFrame=requestAnimationFrame(()=>n.resize?.observe(e)))}),wrapperFrame:0,wrapper:e};r=K.current=n,r.resize?.observe(e)}let{mutation:i,observed:a,resize:o}=r;r.nav!==t&&(r.nav=t,i?.disconnect(),i?.observe(t,{attributeFilter:[`class`,`aria-current`],attributes:!0,childList:!0,subtree:!0}));let s=new Set(n);a.forEach(e=>{s.has(e)||(o?.unobserve(e),a.delete(e))}),s.forEach(e=>{a.has(e)||(o?.observe(e),a.add(e))})}function X(){let e=K.current;e&&(cancelAnimationFrame(e.frame),cancelAnimationFrame(e.wrapperFrame),e.mutation?.disconnect(),e.resize?.disconnect(),K.current=null)}h(()=>X,[]),r(J,[J,R,s,D]);let Z=_(V);h(()=>{Z.current!==V&&(Z.current=V,T?.({overflowCount:V.length,visibleCount:W.current-V.length}))},[V]);let Q=p((e,t)=>B.set(e,{element:t}),[B]),$=p((e,t)=>{B.set(e,{link:t}),U.current.includes(e)&&B.notify()},[B]),ae=g(()=>({hidden:V,More:w,registerItem:Q,registerLink:$,update:J}),[V,Q,$,J]),oe=g(()=>({getLink:e=>B.entries.get(e)?.link??null,getVersion:B.getVersion,hidden:V,iconPlacement:l,menuContainer:u,menuPlacement:f,moreIcon:m,moreLabel:y,moreText:C,subscribe:B.subscribe}),[V,l,u,f,m,y,C,B]);return/* @__PURE__ */ d.createElement(o.Provider,{value:ae},/* @__PURE__ */ d.createElement(S.Provider,{value:oe},/* @__PURE__ */ d.createElement(R,{className:b(`nav-overflow`,a),style:ie?E:{...te,...E},...O,ref:re},n)))}const R=n(L,`NavOverflow`);export{R as t};
2
+ //# sourceMappingURL=nav-overflow-GWARvoQZ.js.map