index.mjs 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. import $epM9y$babelruntimehelpersesmextends from "@babel/runtime/helpers/esm/extends";
  2. import {useState as $epM9y$useState, useRef as $epM9y$useRef, useEffect as $epM9y$useEffect, createElement as $epM9y$createElement, useCallback as $epM9y$useCallback, forwardRef as $epM9y$forwardRef, Fragment as $epM9y$Fragment} from "react";
  3. import {composeEventHandlers as $epM9y$composeEventHandlers} from "@radix-ui/primitive";
  4. import {createCollection as $epM9y$createCollection} from "@radix-ui/react-collection";
  5. import {useComposedRefs as $epM9y$useComposedRefs, composeRefs as $epM9y$composeRefs} from "@radix-ui/react-compose-refs";
  6. import {createContextScope as $epM9y$createContextScope} from "@radix-ui/react-context";
  7. import {useDirection as $epM9y$useDirection} from "@radix-ui/react-direction";
  8. import {DismissableLayer as $epM9y$DismissableLayer} from "@radix-ui/react-dismissable-layer";
  9. import {useFocusGuards as $epM9y$useFocusGuards} from "@radix-ui/react-focus-guards";
  10. import {FocusScope as $epM9y$FocusScope} from "@radix-ui/react-focus-scope";
  11. import {useId as $epM9y$useId} from "@radix-ui/react-id";
  12. import {createPopperScope as $epM9y$createPopperScope, Root as $epM9y$Root, Anchor as $epM9y$Anchor, Content as $epM9y$Content, Arrow as $epM9y$Arrow} from "@radix-ui/react-popper";
  13. import {Portal as $epM9y$Portal} from "@radix-ui/react-portal";
  14. import {Presence as $epM9y$Presence} from "@radix-ui/react-presence";
  15. import {Primitive as $epM9y$Primitive, dispatchDiscreteCustomEvent as $epM9y$dispatchDiscreteCustomEvent} from "@radix-ui/react-primitive";
  16. import {createRovingFocusGroupScope as $epM9y$createRovingFocusGroupScope, Root as $epM9y$Root1, Item as $epM9y$Item} from "@radix-ui/react-roving-focus";
  17. import {Slot as $epM9y$Slot} from "@radix-ui/react-slot";
  18. import {useCallbackRef as $epM9y$useCallbackRef} from "@radix-ui/react-use-callback-ref";
  19. import {hideOthers as $epM9y$hideOthers} from "aria-hidden";
  20. import {RemoveScroll as $epM9y$RemoveScroll} from "react-remove-scroll";
  21. const $6cc32821e9371a1c$var$SELECTION_KEYS = [
  22. 'Enter',
  23. ' '
  24. ];
  25. const $6cc32821e9371a1c$var$FIRST_KEYS = [
  26. 'ArrowDown',
  27. 'PageUp',
  28. 'Home'
  29. ];
  30. const $6cc32821e9371a1c$var$LAST_KEYS = [
  31. 'ArrowUp',
  32. 'PageDown',
  33. 'End'
  34. ];
  35. const $6cc32821e9371a1c$var$FIRST_LAST_KEYS = [
  36. ...$6cc32821e9371a1c$var$FIRST_KEYS,
  37. ...$6cc32821e9371a1c$var$LAST_KEYS
  38. ];
  39. const $6cc32821e9371a1c$var$SUB_OPEN_KEYS = {
  40. ltr: [
  41. ...$6cc32821e9371a1c$var$SELECTION_KEYS,
  42. 'ArrowRight'
  43. ],
  44. rtl: [
  45. ...$6cc32821e9371a1c$var$SELECTION_KEYS,
  46. 'ArrowLeft'
  47. ]
  48. };
  49. const $6cc32821e9371a1c$var$SUB_CLOSE_KEYS = {
  50. ltr: [
  51. 'ArrowLeft'
  52. ],
  53. rtl: [
  54. 'ArrowRight'
  55. ]
  56. };
  57. /* -------------------------------------------------------------------------------------------------
  58. * Menu
  59. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$MENU_NAME = 'Menu';
  60. const [$6cc32821e9371a1c$var$Collection, $6cc32821e9371a1c$var$useCollection, $6cc32821e9371a1c$var$createCollectionScope] = $epM9y$createCollection($6cc32821e9371a1c$var$MENU_NAME);
  61. const [$6cc32821e9371a1c$var$createMenuContext, $6cc32821e9371a1c$export$4027731b685e72eb] = $epM9y$createContextScope($6cc32821e9371a1c$var$MENU_NAME, [
  62. $6cc32821e9371a1c$var$createCollectionScope,
  63. $epM9y$createPopperScope,
  64. $epM9y$createRovingFocusGroupScope
  65. ]);
  66. const $6cc32821e9371a1c$var$usePopperScope = $epM9y$createPopperScope();
  67. const $6cc32821e9371a1c$var$useRovingFocusGroupScope = $epM9y$createRovingFocusGroupScope();
  68. const [$6cc32821e9371a1c$var$MenuProvider, $6cc32821e9371a1c$var$useMenuContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$MENU_NAME);
  69. const [$6cc32821e9371a1c$var$MenuRootProvider, $6cc32821e9371a1c$var$useMenuRootContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$MENU_NAME);
  70. const $6cc32821e9371a1c$export$d9b273488cd8ce6f = (props)=>{
  71. const { __scopeMenu: __scopeMenu , open: open = false , children: children , dir: dir , onOpenChange: onOpenChange , modal: modal = true } = props;
  72. const popperScope = $6cc32821e9371a1c$var$usePopperScope(__scopeMenu);
  73. const [content, setContent] = $epM9y$useState(null);
  74. const isUsingKeyboardRef = $epM9y$useRef(false);
  75. const handleOpenChange = $epM9y$useCallbackRef(onOpenChange);
  76. const direction = $epM9y$useDirection(dir);
  77. $epM9y$useEffect(()=>{
  78. // Capture phase ensures we set the boolean before any side effects execute
  79. // in response to the key or pointer event as they might depend on this value.
  80. const handleKeyDown = ()=>{
  81. isUsingKeyboardRef.current = true;
  82. document.addEventListener('pointerdown', handlePointer, {
  83. capture: true,
  84. once: true
  85. });
  86. document.addEventListener('pointermove', handlePointer, {
  87. capture: true,
  88. once: true
  89. });
  90. };
  91. const handlePointer = ()=>isUsingKeyboardRef.current = false
  92. ;
  93. document.addEventListener('keydown', handleKeyDown, {
  94. capture: true
  95. });
  96. return ()=>{
  97. document.removeEventListener('keydown', handleKeyDown, {
  98. capture: true
  99. });
  100. document.removeEventListener('pointerdown', handlePointer, {
  101. capture: true
  102. });
  103. document.removeEventListener('pointermove', handlePointer, {
  104. capture: true
  105. });
  106. };
  107. }, []);
  108. return /*#__PURE__*/ $epM9y$createElement($epM9y$Root, popperScope, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuProvider, {
  109. scope: __scopeMenu,
  110. open: open,
  111. onOpenChange: handleOpenChange,
  112. content: content,
  113. onContentChange: setContent
  114. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuRootProvider, {
  115. scope: __scopeMenu,
  116. onClose: $epM9y$useCallback(()=>handleOpenChange(false)
  117. , [
  118. handleOpenChange
  119. ]),
  120. isUsingKeyboardRef: isUsingKeyboardRef,
  121. dir: direction,
  122. modal: modal
  123. }, children)));
  124. };
  125. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$d9b273488cd8ce6f, {
  126. displayName: $6cc32821e9371a1c$var$MENU_NAME
  127. });
  128. /* -------------------------------------------------------------------------------------------------
  129. * MenuAnchor
  130. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$ANCHOR_NAME = 'MenuAnchor';
  131. const $6cc32821e9371a1c$export$9fa5ebd18bee4d43 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  132. const { __scopeMenu: __scopeMenu , ...anchorProps } = props;
  133. const popperScope = $6cc32821e9371a1c$var$usePopperScope(__scopeMenu);
  134. return /*#__PURE__*/ $epM9y$createElement($epM9y$Anchor, $epM9y$babelruntimehelpersesmextends({}, popperScope, anchorProps, {
  135. ref: forwardedRef
  136. }));
  137. });
  138. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$9fa5ebd18bee4d43, {
  139. displayName: $6cc32821e9371a1c$var$ANCHOR_NAME
  140. });
  141. /* -------------------------------------------------------------------------------------------------
  142. * MenuPortal
  143. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$PORTAL_NAME = 'MenuPortal';
  144. const [$6cc32821e9371a1c$var$PortalProvider, $6cc32821e9371a1c$var$usePortalContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$PORTAL_NAME, {
  145. forceMount: undefined
  146. });
  147. const $6cc32821e9371a1c$export$793392f970497feb = (props)=>{
  148. const { __scopeMenu: __scopeMenu , forceMount: forceMount , children: children , container: container } = props;
  149. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$PORTAL_NAME, __scopeMenu);
  150. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$PortalProvider, {
  151. scope: __scopeMenu,
  152. forceMount: forceMount
  153. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Presence, {
  154. present: forceMount || context.open
  155. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Portal, {
  156. asChild: true,
  157. container: container
  158. }, children)));
  159. };
  160. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$793392f970497feb, {
  161. displayName: $6cc32821e9371a1c$var$PORTAL_NAME
  162. });
  163. /* -------------------------------------------------------------------------------------------------
  164. * MenuContent
  165. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$CONTENT_NAME = 'MenuContent';
  166. const [$6cc32821e9371a1c$var$MenuContentProvider, $6cc32821e9371a1c$var$useMenuContentContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$CONTENT_NAME);
  167. const $6cc32821e9371a1c$export$479f0f2f71193efe = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  168. const portalContext = $6cc32821e9371a1c$var$usePortalContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  169. const { forceMount: forceMount = portalContext.forceMount , ...contentProps } = props;
  170. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  171. const rootContext = $6cc32821e9371a1c$var$useMenuRootContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  172. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$Collection.Provider, {
  173. scope: props.__scopeMenu
  174. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Presence, {
  175. present: forceMount || context.open
  176. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$Collection.Slot, {
  177. scope: props.__scopeMenu
  178. }, rootContext.modal ? /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuRootContentModal, $epM9y$babelruntimehelpersesmextends({}, contentProps, {
  179. ref: forwardedRef
  180. })) : /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuRootContentNonModal, $epM9y$babelruntimehelpersesmextends({}, contentProps, {
  181. ref: forwardedRef
  182. })))));
  183. });
  184. /* ---------------------------------------------------------------------------------------------- */ const $6cc32821e9371a1c$var$MenuRootContentModal = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  185. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  186. const ref = $epM9y$useRef(null);
  187. const composedRefs = $epM9y$useComposedRefs(forwardedRef, ref); // Hide everything from ARIA except the `MenuContent`
  188. $epM9y$useEffect(()=>{
  189. const content = ref.current;
  190. if (content) return $epM9y$hideOthers(content);
  191. }, []);
  192. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuContentImpl, $epM9y$babelruntimehelpersesmextends({}, props, {
  193. ref: composedRefs // we make sure we're not trapping once it's been closed
  194. ,
  195. trapFocus: context.open // make sure to only disable pointer events when open
  196. ,
  197. disableOutsidePointerEvents: context.open,
  198. disableOutsideScroll: true // When focus is trapped, a `focusout` event may still happen.
  199. ,
  200. onFocusOutside: $epM9y$composeEventHandlers(props.onFocusOutside, (event)=>event.preventDefault()
  201. , {
  202. checkForDefaultPrevented: false
  203. }),
  204. onDismiss: ()=>context.onOpenChange(false)
  205. }));
  206. });
  207. const $6cc32821e9371a1c$var$MenuRootContentNonModal = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  208. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  209. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuContentImpl, $epM9y$babelruntimehelpersesmextends({}, props, {
  210. ref: forwardedRef,
  211. trapFocus: false,
  212. disableOutsidePointerEvents: false,
  213. disableOutsideScroll: false,
  214. onDismiss: ()=>context.onOpenChange(false)
  215. }));
  216. });
  217. /* ---------------------------------------------------------------------------------------------- */ const $6cc32821e9371a1c$var$MenuContentImpl = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  218. const { __scopeMenu: __scopeMenu , loop: loop = false , trapFocus: trapFocus , onOpenAutoFocus: onOpenAutoFocus , onCloseAutoFocus: onCloseAutoFocus , disableOutsidePointerEvents: disableOutsidePointerEvents , onEntryFocus: onEntryFocus , onEscapeKeyDown: onEscapeKeyDown , onPointerDownOutside: onPointerDownOutside , onFocusOutside: onFocusOutside , onInteractOutside: onInteractOutside , onDismiss: onDismiss , disableOutsideScroll: disableOutsideScroll , ...contentProps } = props;
  219. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$CONTENT_NAME, __scopeMenu);
  220. const rootContext = $6cc32821e9371a1c$var$useMenuRootContext($6cc32821e9371a1c$var$CONTENT_NAME, __scopeMenu);
  221. const popperScope = $6cc32821e9371a1c$var$usePopperScope(__scopeMenu);
  222. const rovingFocusGroupScope = $6cc32821e9371a1c$var$useRovingFocusGroupScope(__scopeMenu);
  223. const getItems = $6cc32821e9371a1c$var$useCollection(__scopeMenu);
  224. const [currentItemId, setCurrentItemId] = $epM9y$useState(null);
  225. const contentRef = $epM9y$useRef(null);
  226. const composedRefs = $epM9y$useComposedRefs(forwardedRef, contentRef, context.onContentChange);
  227. const timerRef = $epM9y$useRef(0);
  228. const searchRef = $epM9y$useRef('');
  229. const pointerGraceTimerRef = $epM9y$useRef(0);
  230. const pointerGraceIntentRef = $epM9y$useRef(null);
  231. const pointerDirRef = $epM9y$useRef('right');
  232. const lastPointerXRef = $epM9y$useRef(0);
  233. const ScrollLockWrapper = disableOutsideScroll ? $epM9y$RemoveScroll : $epM9y$Fragment;
  234. const scrollLockWrapperProps = disableOutsideScroll ? {
  235. as: $epM9y$Slot,
  236. allowPinchZoom: true
  237. } : undefined;
  238. const handleTypeaheadSearch = (key)=>{
  239. var _items$find, _items$find2;
  240. const search = searchRef.current + key;
  241. const items = getItems().filter((item)=>!item.disabled
  242. );
  243. const currentItem = document.activeElement;
  244. const currentMatch = (_items$find = items.find((item)=>item.ref.current === currentItem
  245. )) === null || _items$find === void 0 ? void 0 : _items$find.textValue;
  246. const values = items.map((item)=>item.textValue
  247. );
  248. const nextMatch = $6cc32821e9371a1c$var$getNextMatch(values, search, currentMatch);
  249. const newItem = (_items$find2 = items.find((item)=>item.textValue === nextMatch
  250. )) === null || _items$find2 === void 0 ? void 0 : _items$find2.ref.current; // Reset `searchRef` 1 second after it was last updated
  251. (function updateSearch(value) {
  252. searchRef.current = value;
  253. window.clearTimeout(timerRef.current);
  254. if (value !== '') timerRef.current = window.setTimeout(()=>updateSearch('')
  255. , 1000);
  256. })(search);
  257. if (newItem) /**
  258. * Imperative focus during keydown is risky so we prevent React's batching updates
  259. * to avoid potential bugs. See: https://github.com/facebook/react/issues/20332
  260. */ setTimeout(()=>newItem.focus()
  261. );
  262. };
  263. $epM9y$useEffect(()=>{
  264. return ()=>window.clearTimeout(timerRef.current)
  265. ;
  266. }, []); // Make sure the whole tree has focus guards as our `MenuContent` may be
  267. // the last element in the DOM (beacuse of the `Portal`)
  268. $epM9y$useFocusGuards();
  269. const isPointerMovingToSubmenu = $epM9y$useCallback((event)=>{
  270. var _pointerGraceIntentRe, _pointerGraceIntentRe2;
  271. const isMovingTowards = pointerDirRef.current === ((_pointerGraceIntentRe = pointerGraceIntentRef.current) === null || _pointerGraceIntentRe === void 0 ? void 0 : _pointerGraceIntentRe.side);
  272. return isMovingTowards && $6cc32821e9371a1c$var$isPointerInGraceArea(event, (_pointerGraceIntentRe2 = pointerGraceIntentRef.current) === null || _pointerGraceIntentRe2 === void 0 ? void 0 : _pointerGraceIntentRe2.area);
  273. }, []);
  274. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuContentProvider, {
  275. scope: __scopeMenu,
  276. searchRef: searchRef,
  277. onItemEnter: $epM9y$useCallback((event)=>{
  278. if (isPointerMovingToSubmenu(event)) event.preventDefault();
  279. }, [
  280. isPointerMovingToSubmenu
  281. ]),
  282. onItemLeave: $epM9y$useCallback((event)=>{
  283. var _contentRef$current;
  284. if (isPointerMovingToSubmenu(event)) return;
  285. (_contentRef$current = contentRef.current) === null || _contentRef$current === void 0 || _contentRef$current.focus();
  286. setCurrentItemId(null);
  287. }, [
  288. isPointerMovingToSubmenu
  289. ]),
  290. onTriggerLeave: $epM9y$useCallback((event)=>{
  291. if (isPointerMovingToSubmenu(event)) event.preventDefault();
  292. }, [
  293. isPointerMovingToSubmenu
  294. ]),
  295. pointerGraceTimerRef: pointerGraceTimerRef,
  296. onPointerGraceIntentChange: $epM9y$useCallback((intent)=>{
  297. pointerGraceIntentRef.current = intent;
  298. }, [])
  299. }, /*#__PURE__*/ $epM9y$createElement(ScrollLockWrapper, scrollLockWrapperProps, /*#__PURE__*/ $epM9y$createElement($epM9y$FocusScope, {
  300. asChild: true,
  301. trapped: trapFocus,
  302. onMountAutoFocus: $epM9y$composeEventHandlers(onOpenAutoFocus, (event)=>{
  303. var _contentRef$current2;
  304. // when opening, explicitly focus the content area only and leave
  305. // `onEntryFocus` in control of focusing first item
  306. event.preventDefault();
  307. (_contentRef$current2 = contentRef.current) === null || _contentRef$current2 === void 0 || _contentRef$current2.focus();
  308. }),
  309. onUnmountAutoFocus: onCloseAutoFocus
  310. }, /*#__PURE__*/ $epM9y$createElement($epM9y$DismissableLayer, {
  311. asChild: true,
  312. disableOutsidePointerEvents: disableOutsidePointerEvents,
  313. onEscapeKeyDown: onEscapeKeyDown,
  314. onPointerDownOutside: onPointerDownOutside,
  315. onFocusOutside: onFocusOutside,
  316. onInteractOutside: onInteractOutside,
  317. onDismiss: onDismiss
  318. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Root1, $epM9y$babelruntimehelpersesmextends({
  319. asChild: true
  320. }, rovingFocusGroupScope, {
  321. dir: rootContext.dir,
  322. orientation: "vertical",
  323. loop: loop,
  324. currentTabStopId: currentItemId,
  325. onCurrentTabStopIdChange: setCurrentItemId,
  326. onEntryFocus: $epM9y$composeEventHandlers(onEntryFocus, (event)=>{
  327. // only focus first item when using keyboard
  328. if (!rootContext.isUsingKeyboardRef.current) event.preventDefault();
  329. })
  330. }), /*#__PURE__*/ $epM9y$createElement($epM9y$Content, $epM9y$babelruntimehelpersesmextends({
  331. role: "menu",
  332. "aria-orientation": "vertical",
  333. "data-state": $6cc32821e9371a1c$var$getOpenState(context.open),
  334. "data-radix-menu-content": "",
  335. dir: rootContext.dir
  336. }, popperScope, contentProps, {
  337. ref: composedRefs,
  338. style: {
  339. outline: 'none',
  340. ...contentProps.style
  341. },
  342. onKeyDown: $epM9y$composeEventHandlers(contentProps.onKeyDown, (event)=>{
  343. // submenu key events bubble through portals. We only care about keys in this menu.
  344. const target = event.target;
  345. const isKeyDownInside = target.closest('[data-radix-menu-content]') === event.currentTarget;
  346. const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
  347. const isCharacterKey = event.key.length === 1;
  348. if (isKeyDownInside) {
  349. // menus should not be navigated using tab key so we prevent it
  350. if (event.key === 'Tab') event.preventDefault();
  351. if (!isModifierKey && isCharacterKey) handleTypeaheadSearch(event.key);
  352. } // focus first/last item based on key pressed
  353. const content = contentRef.current;
  354. if (event.target !== content) return;
  355. if (!$6cc32821e9371a1c$var$FIRST_LAST_KEYS.includes(event.key)) return;
  356. event.preventDefault();
  357. const items = getItems().filter((item)=>!item.disabled
  358. );
  359. const candidateNodes = items.map((item)=>item.ref.current
  360. );
  361. if ($6cc32821e9371a1c$var$LAST_KEYS.includes(event.key)) candidateNodes.reverse();
  362. $6cc32821e9371a1c$var$focusFirst(candidateNodes);
  363. }),
  364. onBlur: $epM9y$composeEventHandlers(props.onBlur, (event)=>{
  365. // clear search buffer when leaving the menu
  366. if (!event.currentTarget.contains(event.target)) {
  367. window.clearTimeout(timerRef.current);
  368. searchRef.current = '';
  369. }
  370. }),
  371. onPointerMove: $epM9y$composeEventHandlers(props.onPointerMove, $6cc32821e9371a1c$var$whenMouse((event)=>{
  372. const target = event.target;
  373. const pointerXHasChanged = lastPointerXRef.current !== event.clientX; // We don't use `event.movementX` for this check because Safari will
  374. // always return `0` on a pointer event.
  375. if (event.currentTarget.contains(target) && pointerXHasChanged) {
  376. const newDir = event.clientX > lastPointerXRef.current ? 'right' : 'left';
  377. pointerDirRef.current = newDir;
  378. lastPointerXRef.current = event.clientX;
  379. }
  380. }))
  381. })))))));
  382. });
  383. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$479f0f2f71193efe, {
  384. displayName: $6cc32821e9371a1c$var$CONTENT_NAME
  385. });
  386. /* -------------------------------------------------------------------------------------------------
  387. * MenuGroup
  388. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$GROUP_NAME = 'MenuGroup';
  389. const $6cc32821e9371a1c$export$22a631d1f72787bb = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  390. const { __scopeMenu: __scopeMenu , ...groupProps } = props;
  391. return /*#__PURE__*/ $epM9y$createElement($epM9y$Primitive.div, $epM9y$babelruntimehelpersesmextends({
  392. role: "group"
  393. }, groupProps, {
  394. ref: forwardedRef
  395. }));
  396. });
  397. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$22a631d1f72787bb, {
  398. displayName: $6cc32821e9371a1c$var$GROUP_NAME
  399. });
  400. /* -------------------------------------------------------------------------------------------------
  401. * MenuLabel
  402. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$LABEL_NAME = 'MenuLabel';
  403. const $6cc32821e9371a1c$export$dd37bec0e8a99143 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  404. const { __scopeMenu: __scopeMenu , ...labelProps } = props;
  405. return /*#__PURE__*/ $epM9y$createElement($epM9y$Primitive.div, $epM9y$babelruntimehelpersesmextends({}, labelProps, {
  406. ref: forwardedRef
  407. }));
  408. });
  409. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$dd37bec0e8a99143, {
  410. displayName: $6cc32821e9371a1c$var$LABEL_NAME
  411. });
  412. /* -------------------------------------------------------------------------------------------------
  413. * MenuItem
  414. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$ITEM_NAME = 'MenuItem';
  415. const $6cc32821e9371a1c$var$ITEM_SELECT = 'menu.itemSelect';
  416. const $6cc32821e9371a1c$export$2ce376c2cc3355c8 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  417. const { disabled: disabled = false , onSelect: onSelect , ...itemProps } = props;
  418. const ref = $epM9y$useRef(null);
  419. const rootContext = $6cc32821e9371a1c$var$useMenuRootContext($6cc32821e9371a1c$var$ITEM_NAME, props.__scopeMenu);
  420. const contentContext = $6cc32821e9371a1c$var$useMenuContentContext($6cc32821e9371a1c$var$ITEM_NAME, props.__scopeMenu);
  421. const composedRefs = $epM9y$useComposedRefs(forwardedRef, ref);
  422. const isPointerDownRef = $epM9y$useRef(false);
  423. const handleSelect = ()=>{
  424. const menuItem = ref.current;
  425. if (!disabled && menuItem) {
  426. const itemSelectEvent = new CustomEvent($6cc32821e9371a1c$var$ITEM_SELECT, {
  427. bubbles: true,
  428. cancelable: true
  429. });
  430. menuItem.addEventListener($6cc32821e9371a1c$var$ITEM_SELECT, (event)=>onSelect === null || onSelect === void 0 ? void 0 : onSelect(event)
  431. , {
  432. once: true
  433. });
  434. $epM9y$dispatchDiscreteCustomEvent(menuItem, itemSelectEvent);
  435. if (itemSelectEvent.defaultPrevented) isPointerDownRef.current = false;
  436. else rootContext.onClose();
  437. }
  438. };
  439. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuItemImpl, $epM9y$babelruntimehelpersesmextends({}, itemProps, {
  440. ref: composedRefs,
  441. disabled: disabled,
  442. onClick: $epM9y$composeEventHandlers(props.onClick, handleSelect),
  443. onPointerDown: (event)=>{
  444. var _props$onPointerDown;
  445. (_props$onPointerDown = props.onPointerDown) === null || _props$onPointerDown === void 0 || _props$onPointerDown.call(props, event);
  446. isPointerDownRef.current = true;
  447. },
  448. onPointerUp: $epM9y$composeEventHandlers(props.onPointerUp, (event)=>{
  449. var _event$currentTarget;
  450. // Pointer down can move to a different menu item which should activate it on pointer up.
  451. // We dispatch a click for selection to allow composition with click based triggers and to
  452. // prevent Firefox from getting stuck in text selection mode when the menu closes.
  453. if (!isPointerDownRef.current) (_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 || _event$currentTarget.click();
  454. }),
  455. onKeyDown: $epM9y$composeEventHandlers(props.onKeyDown, (event)=>{
  456. const isTypingAhead = contentContext.searchRef.current !== '';
  457. if (disabled || isTypingAhead && event.key === ' ') return;
  458. if ($6cc32821e9371a1c$var$SELECTION_KEYS.includes(event.key)) {
  459. event.currentTarget.click();
  460. /**
  461. * We prevent default browser behaviour for selection keys as they should trigger
  462. * a selection only:
  463. * - prevents space from scrolling the page.
  464. * - if keydown causes focus to move, prevents keydown from firing on the new target.
  465. */ event.preventDefault();
  466. }
  467. })
  468. }));
  469. });
  470. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$2ce376c2cc3355c8, {
  471. displayName: $6cc32821e9371a1c$var$ITEM_NAME
  472. });
  473. /* ---------------------------------------------------------------------------------------------- */ const $6cc32821e9371a1c$var$MenuItemImpl = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  474. const { __scopeMenu: __scopeMenu , disabled: disabled = false , textValue: textValue , ...itemProps } = props;
  475. const contentContext = $6cc32821e9371a1c$var$useMenuContentContext($6cc32821e9371a1c$var$ITEM_NAME, __scopeMenu);
  476. const rovingFocusGroupScope = $6cc32821e9371a1c$var$useRovingFocusGroupScope(__scopeMenu);
  477. const ref = $epM9y$useRef(null);
  478. const composedRefs = $epM9y$useComposedRefs(forwardedRef, ref);
  479. const [isFocused, setIsFocused] = $epM9y$useState(false); // get the item's `.textContent` as default strategy for typeahead `textValue`
  480. const [textContent, setTextContent] = $epM9y$useState('');
  481. $epM9y$useEffect(()=>{
  482. const menuItem = ref.current;
  483. if (menuItem) {
  484. var _menuItem$textContent;
  485. setTextContent(((_menuItem$textContent = menuItem.textContent) !== null && _menuItem$textContent !== void 0 ? _menuItem$textContent : '').trim());
  486. }
  487. }, [
  488. itemProps.children
  489. ]);
  490. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$Collection.ItemSlot, {
  491. scope: __scopeMenu,
  492. disabled: disabled,
  493. textValue: textValue !== null && textValue !== void 0 ? textValue : textContent
  494. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Item, $epM9y$babelruntimehelpersesmextends({
  495. asChild: true
  496. }, rovingFocusGroupScope, {
  497. focusable: !disabled
  498. }), /*#__PURE__*/ $epM9y$createElement($epM9y$Primitive.div, $epM9y$babelruntimehelpersesmextends({
  499. role: "menuitem",
  500. "data-highlighted": isFocused ? '' : undefined,
  501. "aria-disabled": disabled || undefined,
  502. "data-disabled": disabled ? '' : undefined
  503. }, itemProps, {
  504. ref: composedRefs,
  505. onPointerMove: $epM9y$composeEventHandlers(props.onPointerMove, $6cc32821e9371a1c$var$whenMouse((event)=>{
  506. if (disabled) contentContext.onItemLeave(event);
  507. else {
  508. contentContext.onItemEnter(event);
  509. if (!event.defaultPrevented) {
  510. const item = event.currentTarget;
  511. item.focus();
  512. }
  513. }
  514. })),
  515. onPointerLeave: $epM9y$composeEventHandlers(props.onPointerLeave, $6cc32821e9371a1c$var$whenMouse((event)=>contentContext.onItemLeave(event)
  516. )),
  517. onFocus: $epM9y$composeEventHandlers(props.onFocus, ()=>setIsFocused(true)
  518. ),
  519. onBlur: $epM9y$composeEventHandlers(props.onBlur, ()=>setIsFocused(false)
  520. )
  521. }))));
  522. });
  523. /* -------------------------------------------------------------------------------------------------
  524. * MenuCheckboxItem
  525. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$CHECKBOX_ITEM_NAME = 'MenuCheckboxItem';
  526. const $6cc32821e9371a1c$export$f6f243521332502d = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  527. const { checked: checked = false , onCheckedChange: onCheckedChange , ...checkboxItemProps } = props;
  528. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$ItemIndicatorProvider, {
  529. scope: props.__scopeMenu,
  530. checked: checked
  531. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$export$2ce376c2cc3355c8, $epM9y$babelruntimehelpersesmextends({
  532. role: "menuitemcheckbox",
  533. "aria-checked": $6cc32821e9371a1c$var$isIndeterminate(checked) ? 'mixed' : checked
  534. }, checkboxItemProps, {
  535. ref: forwardedRef,
  536. "data-state": $6cc32821e9371a1c$var$getCheckedState(checked),
  537. onSelect: $epM9y$composeEventHandlers(checkboxItemProps.onSelect, ()=>onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange($6cc32821e9371a1c$var$isIndeterminate(checked) ? true : !checked)
  538. , {
  539. checkForDefaultPrevented: false
  540. })
  541. })));
  542. });
  543. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$f6f243521332502d, {
  544. displayName: $6cc32821e9371a1c$var$CHECKBOX_ITEM_NAME
  545. });
  546. /* -------------------------------------------------------------------------------------------------
  547. * MenuRadioGroup
  548. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$RADIO_GROUP_NAME = 'MenuRadioGroup';
  549. const [$6cc32821e9371a1c$var$RadioGroupProvider, $6cc32821e9371a1c$var$useRadioGroupContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$RADIO_GROUP_NAME, {
  550. value: undefined,
  551. onValueChange: ()=>{}
  552. });
  553. const $6cc32821e9371a1c$export$ea2200c9eee416b3 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  554. const { value: value , onValueChange: onValueChange , ...groupProps } = props;
  555. const handleValueChange = $epM9y$useCallbackRef(onValueChange);
  556. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$RadioGroupProvider, {
  557. scope: props.__scopeMenu,
  558. value: value,
  559. onValueChange: handleValueChange
  560. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$export$22a631d1f72787bb, $epM9y$babelruntimehelpersesmextends({}, groupProps, {
  561. ref: forwardedRef
  562. })));
  563. });
  564. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$ea2200c9eee416b3, {
  565. displayName: $6cc32821e9371a1c$var$RADIO_GROUP_NAME
  566. });
  567. /* -------------------------------------------------------------------------------------------------
  568. * MenuRadioItem
  569. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$RADIO_ITEM_NAME = 'MenuRadioItem';
  570. const $6cc32821e9371a1c$export$69bd225e9817f6d0 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  571. const { value: value , ...radioItemProps } = props;
  572. const context = $6cc32821e9371a1c$var$useRadioGroupContext($6cc32821e9371a1c$var$RADIO_ITEM_NAME, props.__scopeMenu);
  573. const checked = value === context.value;
  574. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$ItemIndicatorProvider, {
  575. scope: props.__scopeMenu,
  576. checked: checked
  577. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$export$2ce376c2cc3355c8, $epM9y$babelruntimehelpersesmextends({
  578. role: "menuitemradio",
  579. "aria-checked": checked
  580. }, radioItemProps, {
  581. ref: forwardedRef,
  582. "data-state": $6cc32821e9371a1c$var$getCheckedState(checked),
  583. onSelect: $epM9y$composeEventHandlers(radioItemProps.onSelect, ()=>{
  584. var _context$onValueChang;
  585. return (_context$onValueChang = context.onValueChange) === null || _context$onValueChang === void 0 ? void 0 : _context$onValueChang.call(context, value);
  586. }, {
  587. checkForDefaultPrevented: false
  588. })
  589. })));
  590. });
  591. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$69bd225e9817f6d0, {
  592. displayName: $6cc32821e9371a1c$var$RADIO_ITEM_NAME
  593. });
  594. /* -------------------------------------------------------------------------------------------------
  595. * MenuItemIndicator
  596. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$ITEM_INDICATOR_NAME = 'MenuItemIndicator';
  597. const [$6cc32821e9371a1c$var$ItemIndicatorProvider, $6cc32821e9371a1c$var$useItemIndicatorContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$ITEM_INDICATOR_NAME, {
  598. checked: false
  599. });
  600. const $6cc32821e9371a1c$export$a2593e23056970a3 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  601. const { __scopeMenu: __scopeMenu , forceMount: forceMount , ...itemIndicatorProps } = props;
  602. const indicatorContext = $6cc32821e9371a1c$var$useItemIndicatorContext($6cc32821e9371a1c$var$ITEM_INDICATOR_NAME, __scopeMenu);
  603. return /*#__PURE__*/ $epM9y$createElement($epM9y$Presence, {
  604. present: forceMount || $6cc32821e9371a1c$var$isIndeterminate(indicatorContext.checked) || indicatorContext.checked === true
  605. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Primitive.span, $epM9y$babelruntimehelpersesmextends({}, itemIndicatorProps, {
  606. ref: forwardedRef,
  607. "data-state": $6cc32821e9371a1c$var$getCheckedState(indicatorContext.checked)
  608. })));
  609. });
  610. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$a2593e23056970a3, {
  611. displayName: $6cc32821e9371a1c$var$ITEM_INDICATOR_NAME
  612. });
  613. /* -------------------------------------------------------------------------------------------------
  614. * MenuSeparator
  615. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$SEPARATOR_NAME = 'MenuSeparator';
  616. const $6cc32821e9371a1c$export$1cec7dcdd713e220 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  617. const { __scopeMenu: __scopeMenu , ...separatorProps } = props;
  618. return /*#__PURE__*/ $epM9y$createElement($epM9y$Primitive.div, $epM9y$babelruntimehelpersesmextends({
  619. role: "separator",
  620. "aria-orientation": "horizontal"
  621. }, separatorProps, {
  622. ref: forwardedRef
  623. }));
  624. });
  625. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$1cec7dcdd713e220, {
  626. displayName: $6cc32821e9371a1c$var$SEPARATOR_NAME
  627. });
  628. /* -------------------------------------------------------------------------------------------------
  629. * MenuArrow
  630. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$ARROW_NAME = 'MenuArrow';
  631. const $6cc32821e9371a1c$export$bcdda4773debf5fa = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  632. const { __scopeMenu: __scopeMenu , ...arrowProps } = props;
  633. const popperScope = $6cc32821e9371a1c$var$usePopperScope(__scopeMenu);
  634. return /*#__PURE__*/ $epM9y$createElement($epM9y$Arrow, $epM9y$babelruntimehelpersesmextends({}, popperScope, arrowProps, {
  635. ref: forwardedRef
  636. }));
  637. });
  638. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$bcdda4773debf5fa, {
  639. displayName: $6cc32821e9371a1c$var$ARROW_NAME
  640. });
  641. /* -------------------------------------------------------------------------------------------------
  642. * MenuSub
  643. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$SUB_NAME = 'MenuSub';
  644. const [$6cc32821e9371a1c$var$MenuSubProvider, $6cc32821e9371a1c$var$useMenuSubContext] = $6cc32821e9371a1c$var$createMenuContext($6cc32821e9371a1c$var$SUB_NAME);
  645. const $6cc32821e9371a1c$export$71bdb9d1e2909932 = (props)=>{
  646. const { __scopeMenu: __scopeMenu , children: children , open: open = false , onOpenChange: onOpenChange } = props;
  647. const parentMenuContext = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$SUB_NAME, __scopeMenu);
  648. const popperScope = $6cc32821e9371a1c$var$usePopperScope(__scopeMenu);
  649. const [trigger, setTrigger] = $epM9y$useState(null);
  650. const [content, setContent] = $epM9y$useState(null);
  651. const handleOpenChange = $epM9y$useCallbackRef(onOpenChange); // Prevent the parent menu from reopening with open submenus.
  652. $epM9y$useEffect(()=>{
  653. if (parentMenuContext.open === false) handleOpenChange(false);
  654. return ()=>handleOpenChange(false)
  655. ;
  656. }, [
  657. parentMenuContext.open,
  658. handleOpenChange
  659. ]);
  660. return /*#__PURE__*/ $epM9y$createElement($epM9y$Root, popperScope, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuProvider, {
  661. scope: __scopeMenu,
  662. open: open,
  663. onOpenChange: handleOpenChange,
  664. content: content,
  665. onContentChange: setContent
  666. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuSubProvider, {
  667. scope: __scopeMenu,
  668. contentId: $epM9y$useId(),
  669. triggerId: $epM9y$useId(),
  670. trigger: trigger,
  671. onTriggerChange: setTrigger
  672. }, children)));
  673. };
  674. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$71bdb9d1e2909932, {
  675. displayName: $6cc32821e9371a1c$var$SUB_NAME
  676. });
  677. /* -------------------------------------------------------------------------------------------------
  678. * MenuSubTrigger
  679. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$SUB_TRIGGER_NAME = 'MenuSubTrigger';
  680. const $6cc32821e9371a1c$export$5fbbb3ba7297405f = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  681. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$SUB_TRIGGER_NAME, props.__scopeMenu);
  682. const rootContext = $6cc32821e9371a1c$var$useMenuRootContext($6cc32821e9371a1c$var$SUB_TRIGGER_NAME, props.__scopeMenu);
  683. const subContext = $6cc32821e9371a1c$var$useMenuSubContext($6cc32821e9371a1c$var$SUB_TRIGGER_NAME, props.__scopeMenu);
  684. const contentContext = $6cc32821e9371a1c$var$useMenuContentContext($6cc32821e9371a1c$var$SUB_TRIGGER_NAME, props.__scopeMenu);
  685. const openTimerRef = $epM9y$useRef(null);
  686. const { pointerGraceTimerRef: pointerGraceTimerRef , onPointerGraceIntentChange: onPointerGraceIntentChange } = contentContext;
  687. const scope = {
  688. __scopeMenu: props.__scopeMenu
  689. };
  690. const clearOpenTimer = $epM9y$useCallback(()=>{
  691. if (openTimerRef.current) window.clearTimeout(openTimerRef.current);
  692. openTimerRef.current = null;
  693. }, []);
  694. $epM9y$useEffect(()=>clearOpenTimer
  695. , [
  696. clearOpenTimer
  697. ]);
  698. $epM9y$useEffect(()=>{
  699. const pointerGraceTimer = pointerGraceTimerRef.current;
  700. return ()=>{
  701. window.clearTimeout(pointerGraceTimer);
  702. onPointerGraceIntentChange(null);
  703. };
  704. }, [
  705. pointerGraceTimerRef,
  706. onPointerGraceIntentChange
  707. ]);
  708. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$export$9fa5ebd18bee4d43, $epM9y$babelruntimehelpersesmextends({
  709. asChild: true
  710. }, scope), /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuItemImpl, $epM9y$babelruntimehelpersesmextends({
  711. id: subContext.triggerId,
  712. "aria-haspopup": "menu",
  713. "aria-expanded": context.open,
  714. "aria-controls": subContext.contentId,
  715. "data-state": $6cc32821e9371a1c$var$getOpenState(context.open)
  716. }, props, {
  717. ref: $epM9y$composeRefs(forwardedRef, subContext.onTriggerChange) // This is redundant for mouse users but we cannot determine pointer type from
  718. ,
  719. onClick: (event)=>{
  720. var _props$onClick;
  721. (_props$onClick = props.onClick) === null || _props$onClick === void 0 || _props$onClick.call(props, event);
  722. if (props.disabled || event.defaultPrevented) return;
  723. /**
  724. * We manually focus because iOS Safari doesn't always focus on click (e.g. buttons)
  725. * and we rely heavily on `onFocusOutside` for submenus to close when switching
  726. * between separate submenus.
  727. */ event.currentTarget.focus();
  728. if (!context.open) context.onOpenChange(true);
  729. },
  730. onPointerMove: $epM9y$composeEventHandlers(props.onPointerMove, $6cc32821e9371a1c$var$whenMouse((event)=>{
  731. contentContext.onItemEnter(event);
  732. if (event.defaultPrevented) return;
  733. if (!props.disabled && !context.open && !openTimerRef.current) {
  734. contentContext.onPointerGraceIntentChange(null);
  735. openTimerRef.current = window.setTimeout(()=>{
  736. context.onOpenChange(true);
  737. clearOpenTimer();
  738. }, 100);
  739. }
  740. })),
  741. onPointerLeave: $epM9y$composeEventHandlers(props.onPointerLeave, $6cc32821e9371a1c$var$whenMouse((event)=>{
  742. var _context$content;
  743. clearOpenTimer();
  744. const contentRect = (_context$content = context.content) === null || _context$content === void 0 ? void 0 : _context$content.getBoundingClientRect();
  745. if (contentRect) {
  746. var _context$content2;
  747. // TODO: make sure to update this when we change positioning logic
  748. const side = (_context$content2 = context.content) === null || _context$content2 === void 0 ? void 0 : _context$content2.dataset.side;
  749. const rightSide = side === 'right';
  750. const bleed = rightSide ? -5 : 5;
  751. const contentNearEdge = contentRect[rightSide ? 'left' : 'right'];
  752. const contentFarEdge = contentRect[rightSide ? 'right' : 'left'];
  753. contentContext.onPointerGraceIntentChange({
  754. area: [
  755. // consistently within polygon bounds
  756. {
  757. x: event.clientX + bleed,
  758. y: event.clientY
  759. },
  760. {
  761. x: contentNearEdge,
  762. y: contentRect.top
  763. },
  764. {
  765. x: contentFarEdge,
  766. y: contentRect.top
  767. },
  768. {
  769. x: contentFarEdge,
  770. y: contentRect.bottom
  771. },
  772. {
  773. x: contentNearEdge,
  774. y: contentRect.bottom
  775. }
  776. ],
  777. side: side
  778. });
  779. window.clearTimeout(pointerGraceTimerRef.current);
  780. pointerGraceTimerRef.current = window.setTimeout(()=>contentContext.onPointerGraceIntentChange(null)
  781. , 300);
  782. } else {
  783. contentContext.onTriggerLeave(event);
  784. if (event.defaultPrevented) return; // There's 100ms where the user may leave an item before the submenu was opened.
  785. contentContext.onPointerGraceIntentChange(null);
  786. }
  787. })),
  788. onKeyDown: $epM9y$composeEventHandlers(props.onKeyDown, (event)=>{
  789. const isTypingAhead = contentContext.searchRef.current !== '';
  790. if (props.disabled || isTypingAhead && event.key === ' ') return;
  791. if ($6cc32821e9371a1c$var$SUB_OPEN_KEYS[rootContext.dir].includes(event.key)) {
  792. var _context$content3;
  793. context.onOpenChange(true); // The trigger may hold focus if opened via pointer interaction
  794. // so we ensure content is given focus again when switching to keyboard.
  795. (_context$content3 = context.content) === null || _context$content3 === void 0 || _context$content3.focus(); // prevent window from scrolling
  796. event.preventDefault();
  797. }
  798. })
  799. })));
  800. });
  801. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$5fbbb3ba7297405f, {
  802. displayName: $6cc32821e9371a1c$var$SUB_TRIGGER_NAME
  803. });
  804. /* -------------------------------------------------------------------------------------------------
  805. * MenuSubContent
  806. * -----------------------------------------------------------------------------------------------*/ const $6cc32821e9371a1c$var$SUB_CONTENT_NAME = 'MenuSubContent';
  807. const $6cc32821e9371a1c$export$e7142ab31822bde6 = /*#__PURE__*/ $epM9y$forwardRef((props, forwardedRef)=>{
  808. const portalContext = $6cc32821e9371a1c$var$usePortalContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  809. const { forceMount: forceMount = portalContext.forceMount , ...subContentProps } = props;
  810. const context = $6cc32821e9371a1c$var$useMenuContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  811. const rootContext = $6cc32821e9371a1c$var$useMenuRootContext($6cc32821e9371a1c$var$CONTENT_NAME, props.__scopeMenu);
  812. const subContext = $6cc32821e9371a1c$var$useMenuSubContext($6cc32821e9371a1c$var$SUB_CONTENT_NAME, props.__scopeMenu);
  813. const ref = $epM9y$useRef(null);
  814. const composedRefs = $epM9y$useComposedRefs(forwardedRef, ref);
  815. return /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$Collection.Provider, {
  816. scope: props.__scopeMenu
  817. }, /*#__PURE__*/ $epM9y$createElement($epM9y$Presence, {
  818. present: forceMount || context.open
  819. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$Collection.Slot, {
  820. scope: props.__scopeMenu
  821. }, /*#__PURE__*/ $epM9y$createElement($6cc32821e9371a1c$var$MenuContentImpl, $epM9y$babelruntimehelpersesmextends({
  822. id: subContext.contentId,
  823. "aria-labelledby": subContext.triggerId
  824. }, subContentProps, {
  825. ref: composedRefs,
  826. align: "start",
  827. side: rootContext.dir === 'rtl' ? 'left' : 'right',
  828. disableOutsidePointerEvents: false,
  829. disableOutsideScroll: false,
  830. trapFocus: false,
  831. onOpenAutoFocus: (event)=>{
  832. var _ref$current;
  833. // when opening a submenu, focus content for keyboard users only
  834. if (rootContext.isUsingKeyboardRef.current) (_ref$current = ref.current) === null || _ref$current === void 0 || _ref$current.focus();
  835. event.preventDefault();
  836. } // The menu might close because of focusing another menu item in the parent menu. We
  837. ,
  838. onCloseAutoFocus: (event)=>event.preventDefault()
  839. ,
  840. onFocusOutside: $epM9y$composeEventHandlers(props.onFocusOutside, (event)=>{
  841. // We prevent closing when the trigger is focused to avoid triggering a re-open animation
  842. // on pointer interaction.
  843. if (event.target !== subContext.trigger) context.onOpenChange(false);
  844. }),
  845. onEscapeKeyDown: $epM9y$composeEventHandlers(props.onEscapeKeyDown, (event)=>{
  846. rootContext.onClose(); // ensure pressing escape in submenu doesn't escape full screen mode
  847. event.preventDefault();
  848. }),
  849. onKeyDown: $epM9y$composeEventHandlers(props.onKeyDown, (event)=>{
  850. // Submenu key events bubble through portals. We only care about keys in this menu.
  851. const isKeyDownInside = event.currentTarget.contains(event.target);
  852. const isCloseKey = $6cc32821e9371a1c$var$SUB_CLOSE_KEYS[rootContext.dir].includes(event.key);
  853. if (isKeyDownInside && isCloseKey) {
  854. var _subContext$trigger;
  855. context.onOpenChange(false); // We focus manually because we prevented it in `onCloseAutoFocus`
  856. (_subContext$trigger = subContext.trigger) === null || _subContext$trigger === void 0 || _subContext$trigger.focus(); // prevent window from scrolling
  857. event.preventDefault();
  858. }
  859. })
  860. })))));
  861. });
  862. /*#__PURE__*/ Object.assign($6cc32821e9371a1c$export$e7142ab31822bde6, {
  863. displayName: $6cc32821e9371a1c$var$SUB_CONTENT_NAME
  864. });
  865. /* -----------------------------------------------------------------------------------------------*/ function $6cc32821e9371a1c$var$getOpenState(open) {
  866. return open ? 'open' : 'closed';
  867. }
  868. function $6cc32821e9371a1c$var$isIndeterminate(checked) {
  869. return checked === 'indeterminate';
  870. }
  871. function $6cc32821e9371a1c$var$getCheckedState(checked) {
  872. return $6cc32821e9371a1c$var$isIndeterminate(checked) ? 'indeterminate' : checked ? 'checked' : 'unchecked';
  873. }
  874. function $6cc32821e9371a1c$var$focusFirst(candidates) {
  875. const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
  876. for (const candidate of candidates){
  877. // if focus is already where we want to go, we don't want to keep going through the candidates
  878. if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
  879. candidate.focus();
  880. if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
  881. }
  882. }
  883. /**
  884. * Wraps an array around itself at a given start index
  885. * Example: `wrapArray(['a', 'b', 'c', 'd'], 2) === ['c', 'd', 'a', 'b']`
  886. */ function $6cc32821e9371a1c$var$wrapArray(array, startIndex) {
  887. return array.map((_, index)=>array[(startIndex + index) % array.length]
  888. );
  889. }
  890. /**
  891. * This is the "meat" of the typeahead matching logic. It takes in all the values,
  892. * the search and the current match, and returns the next match (or `undefined`).
  893. *
  894. * We normalize the search because if a user has repeatedly pressed a character,
  895. * we want the exact same behavior as if we only had that one character
  896. * (ie. cycle through options starting with that character)
  897. *
  898. * We also reorder the values by wrapping the array around the current match.
  899. * This is so we always look forward from the current match, and picking the first
  900. * match will always be the correct one.
  901. *
  902. * Finally, if the normalized search is exactly one character, we exclude the
  903. * current match from the values because otherwise it would be the first to match always
  904. * and focus would never move. This is as opposed to the regular case, where we
  905. * don't want focus to move if the current match still matches.
  906. */ function $6cc32821e9371a1c$var$getNextMatch(values, search, currentMatch) {
  907. const isRepeated = search.length > 1 && Array.from(search).every((char)=>char === search[0]
  908. );
  909. const normalizedSearch = isRepeated ? search[0] : search;
  910. const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
  911. let wrappedValues = $6cc32821e9371a1c$var$wrapArray(values, Math.max(currentMatchIndex, 0));
  912. const excludeCurrentMatch = normalizedSearch.length === 1;
  913. if (excludeCurrentMatch) wrappedValues = wrappedValues.filter((v)=>v !== currentMatch
  914. );
  915. const nextMatch = wrappedValues.find((value)=>value.toLowerCase().startsWith(normalizedSearch.toLowerCase())
  916. );
  917. return nextMatch !== currentMatch ? nextMatch : undefined;
  918. }
  919. // Determine if a point is inside of a polygon.
  920. // Based on https://github.com/substack/point-in-polygon
  921. function $6cc32821e9371a1c$var$isPointInPolygon(point, polygon) {
  922. const { x: x , y: y } = point;
  923. let inside = false;
  924. for(let i = 0, j = polygon.length - 1; i < polygon.length; j = i++){
  925. const xi = polygon[i].x;
  926. const yi = polygon[i].y;
  927. const xj = polygon[j].x;
  928. const yj = polygon[j].y; // prettier-ignore
  929. const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi;
  930. if (intersect) inside = !inside;
  931. }
  932. return inside;
  933. }
  934. function $6cc32821e9371a1c$var$isPointerInGraceArea(event, area) {
  935. if (!area) return false;
  936. const cursorPos = {
  937. x: event.clientX,
  938. y: event.clientY
  939. };
  940. return $6cc32821e9371a1c$var$isPointInPolygon(cursorPos, area);
  941. }
  942. function $6cc32821e9371a1c$var$whenMouse(handler) {
  943. return (event)=>event.pointerType === 'mouse' ? handler(event) : undefined
  944. ;
  945. }
  946. const $6cc32821e9371a1c$export$be92b6f5f03c0fe9 = $6cc32821e9371a1c$export$d9b273488cd8ce6f;
  947. const $6cc32821e9371a1c$export$b688253958b8dfe7 = $6cc32821e9371a1c$export$9fa5ebd18bee4d43;
  948. const $6cc32821e9371a1c$export$602eac185826482c = $6cc32821e9371a1c$export$793392f970497feb;
  949. const $6cc32821e9371a1c$export$7c6e2c02157bb7d2 = $6cc32821e9371a1c$export$479f0f2f71193efe;
  950. const $6cc32821e9371a1c$export$eb2fcfdbd7ba97d4 = $6cc32821e9371a1c$export$22a631d1f72787bb;
  951. const $6cc32821e9371a1c$export$b04be29aa201d4f5 = $6cc32821e9371a1c$export$dd37bec0e8a99143;
  952. const $6cc32821e9371a1c$export$6d08773d2e66f8f2 = $6cc32821e9371a1c$export$2ce376c2cc3355c8;
  953. const $6cc32821e9371a1c$export$16ce288f89fa631c = $6cc32821e9371a1c$export$f6f243521332502d;
  954. const $6cc32821e9371a1c$export$a98f0dcb43a68a25 = $6cc32821e9371a1c$export$ea2200c9eee416b3;
  955. const $6cc32821e9371a1c$export$371ab307eab489c0 = $6cc32821e9371a1c$export$69bd225e9817f6d0;
  956. const $6cc32821e9371a1c$export$c3468e2714d175fa = $6cc32821e9371a1c$export$a2593e23056970a3;
  957. const $6cc32821e9371a1c$export$1ff3c3f08ae963c0 = $6cc32821e9371a1c$export$1cec7dcdd713e220;
  958. const $6cc32821e9371a1c$export$21b07c8f274aebd5 = $6cc32821e9371a1c$export$bcdda4773debf5fa;
  959. const $6cc32821e9371a1c$export$d7a01e11500dfb6f = $6cc32821e9371a1c$export$71bdb9d1e2909932;
  960. const $6cc32821e9371a1c$export$2ea8a7a591ac5eac = $6cc32821e9371a1c$export$5fbbb3ba7297405f;
  961. const $6cc32821e9371a1c$export$6d4de93b380beddf = $6cc32821e9371a1c$export$e7142ab31822bde6;
  962. export {$6cc32821e9371a1c$export$4027731b685e72eb as createMenuScope, $6cc32821e9371a1c$export$d9b273488cd8ce6f as Menu, $6cc32821e9371a1c$export$9fa5ebd18bee4d43 as MenuAnchor, $6cc32821e9371a1c$export$793392f970497feb as MenuPortal, $6cc32821e9371a1c$export$479f0f2f71193efe as MenuContent, $6cc32821e9371a1c$export$22a631d1f72787bb as MenuGroup, $6cc32821e9371a1c$export$dd37bec0e8a99143 as MenuLabel, $6cc32821e9371a1c$export$2ce376c2cc3355c8 as MenuItem, $6cc32821e9371a1c$export$f6f243521332502d as MenuCheckboxItem, $6cc32821e9371a1c$export$ea2200c9eee416b3 as MenuRadioGroup, $6cc32821e9371a1c$export$69bd225e9817f6d0 as MenuRadioItem, $6cc32821e9371a1c$export$a2593e23056970a3 as MenuItemIndicator, $6cc32821e9371a1c$export$1cec7dcdd713e220 as MenuSeparator, $6cc32821e9371a1c$export$bcdda4773debf5fa as MenuArrow, $6cc32821e9371a1c$export$71bdb9d1e2909932 as MenuSub, $6cc32821e9371a1c$export$5fbbb3ba7297405f as MenuSubTrigger, $6cc32821e9371a1c$export$e7142ab31822bde6 as MenuSubContent, $6cc32821e9371a1c$export$be92b6f5f03c0fe9 as Root, $6cc32821e9371a1c$export$b688253958b8dfe7 as Anchor, $6cc32821e9371a1c$export$602eac185826482c as Portal, $6cc32821e9371a1c$export$7c6e2c02157bb7d2 as Content, $6cc32821e9371a1c$export$eb2fcfdbd7ba97d4 as Group, $6cc32821e9371a1c$export$b04be29aa201d4f5 as Label, $6cc32821e9371a1c$export$6d08773d2e66f8f2 as Item, $6cc32821e9371a1c$export$16ce288f89fa631c as CheckboxItem, $6cc32821e9371a1c$export$a98f0dcb43a68a25 as RadioGroup, $6cc32821e9371a1c$export$371ab307eab489c0 as RadioItem, $6cc32821e9371a1c$export$c3468e2714d175fa as ItemIndicator, $6cc32821e9371a1c$export$1ff3c3f08ae963c0 as Separator, $6cc32821e9371a1c$export$21b07c8f274aebd5 as Arrow, $6cc32821e9371a1c$export$d7a01e11500dfb6f as Sub, $6cc32821e9371a1c$export$2ea8a7a591ac5eac as SubTrigger, $6cc32821e9371a1c$export$6d4de93b380beddf as SubContent};
  963. //# sourceMappingURL=index.mjs.map