@tamagui/menu 1.138.0 → 1.138.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 (124) hide show
  1. package/dist/cjs/createMenu.cjs +952 -0
  2. package/dist/cjs/createMenu.js +751 -0
  3. package/dist/cjs/createMenu.js.map +6 -0
  4. package/dist/cjs/createMenu.native.js +1136 -0
  5. package/dist/cjs/createMenu.native.js.map +1 -0
  6. package/dist/cjs/createNativeMenu/createNativeMenu.android.js +261 -0
  7. package/dist/cjs/createNativeMenu/createNativeMenu.android.js.map +6 -0
  8. package/dist/cjs/createNativeMenu/createNativeMenu.cjs +47 -0
  9. package/dist/cjs/createNativeMenu/createNativeMenu.ios.js +373 -0
  10. package/dist/cjs/createNativeMenu/createNativeMenu.ios.js.map +6 -0
  11. package/dist/cjs/createNativeMenu/createNativeMenu.js +42 -0
  12. package/dist/cjs/createNativeMenu/createNativeMenu.js.map +6 -0
  13. package/dist/cjs/createNativeMenu/createNativeMenu.native.js +356 -0
  14. package/dist/cjs/createNativeMenu/createNativeMenu.native.js.map +1 -0
  15. package/dist/cjs/createNativeMenu/createNativeMenuTypes.cjs +16 -0
  16. package/dist/cjs/createNativeMenu/createNativeMenuTypes.js +14 -0
  17. package/dist/cjs/createNativeMenu/createNativeMenuTypes.js.map +6 -0
  18. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js +19 -0
  19. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js.map +1 -0
  20. package/dist/cjs/createNativeMenu/index.cjs +19 -0
  21. package/dist/cjs/createNativeMenu/index.js +16 -0
  22. package/dist/cjs/createNativeMenu/index.js.map +6 -0
  23. package/dist/cjs/createNativeMenu/index.native.js +22 -0
  24. package/dist/cjs/createNativeMenu/index.native.js.map +1 -0
  25. package/dist/cjs/createNativeMenu/utils.cjs +68 -0
  26. package/dist/cjs/createNativeMenu/utils.js +66 -0
  27. package/dist/cjs/createNativeMenu/utils.js.map +6 -0
  28. package/dist/cjs/createNativeMenu/utils.native.js +94 -0
  29. package/dist/cjs/createNativeMenu/utils.native.js.map +1 -0
  30. package/dist/cjs/createNativeMenu/withNativeMenu.cjs +45 -0
  31. package/dist/cjs/createNativeMenu/withNativeMenu.js +35 -0
  32. package/dist/cjs/createNativeMenu/withNativeMenu.js.map +6 -0
  33. package/dist/cjs/createNativeMenu/withNativeMenu.native.js +49 -0
  34. package/dist/cjs/createNativeMenu/withNativeMenu.native.js.map +1 -0
  35. package/dist/esm/createMenu.js +757 -0
  36. package/dist/esm/createMenu.js.map +6 -0
  37. package/dist/esm/createMenu.mjs +916 -0
  38. package/dist/esm/createMenu.mjs.map +1 -0
  39. package/dist/esm/createMenu.native.js +1097 -0
  40. package/dist/esm/createMenu.native.js.map +1 -0
  41. package/dist/esm/createNativeMenu/createNativeMenu.android.js +251 -0
  42. package/dist/esm/createNativeMenu/createNativeMenu.android.js.map +6 -0
  43. package/dist/esm/createNativeMenu/createNativeMenu.ios.js +363 -0
  44. package/dist/esm/createNativeMenu/createNativeMenu.ios.js.map +6 -0
  45. package/dist/esm/createNativeMenu/createNativeMenu.js +26 -0
  46. package/dist/esm/createNativeMenu/createNativeMenu.js.map +6 -0
  47. package/dist/esm/createNativeMenu/createNativeMenu.mjs +24 -0
  48. package/dist/esm/createNativeMenu/createNativeMenu.mjs.map +1 -0
  49. package/dist/esm/createNativeMenu/createNativeMenu.native.js +330 -0
  50. package/dist/esm/createNativeMenu/createNativeMenu.native.js.map +1 -0
  51. package/dist/esm/createNativeMenu/createNativeMenuTypes.js +1 -0
  52. package/dist/esm/createNativeMenu/createNativeMenuTypes.js.map +6 -0
  53. package/dist/esm/createNativeMenu/createNativeMenuTypes.mjs +2 -0
  54. package/dist/esm/createNativeMenu/createNativeMenuTypes.mjs.map +1 -0
  55. package/dist/esm/createNativeMenu/createNativeMenuTypes.native.js +2 -0
  56. package/dist/esm/createNativeMenu/createNativeMenuTypes.native.js.map +1 -0
  57. package/dist/esm/createNativeMenu/index.js +3 -0
  58. package/dist/esm/createNativeMenu/index.js.map +6 -0
  59. package/dist/esm/createNativeMenu/index.mjs +3 -0
  60. package/dist/esm/createNativeMenu/index.mjs.map +1 -0
  61. package/dist/esm/createNativeMenu/index.native.js +3 -0
  62. package/dist/esm/createNativeMenu/index.native.js.map +1 -0
  63. package/dist/esm/createNativeMenu/utils.js +47 -0
  64. package/dist/esm/createNativeMenu/utils.js.map +6 -0
  65. package/dist/esm/createNativeMenu/utils.mjs +29 -0
  66. package/dist/esm/createNativeMenu/utils.mjs.map +1 -0
  67. package/dist/esm/createNativeMenu/utils.native.js +52 -0
  68. package/dist/esm/createNativeMenu/utils.native.js.map +1 -0
  69. package/dist/esm/createNativeMenu/withNativeMenu.js +20 -0
  70. package/dist/esm/createNativeMenu/withNativeMenu.js.map +6 -0
  71. package/dist/esm/createNativeMenu/withNativeMenu.mjs +22 -0
  72. package/dist/esm/createNativeMenu/withNativeMenu.mjs.map +1 -0
  73. package/dist/esm/createNativeMenu/withNativeMenu.native.js +23 -0
  74. package/dist/esm/createNativeMenu/withNativeMenu.native.js.map +1 -0
  75. package/dist/jsx/createMenu.js +757 -0
  76. package/dist/jsx/createMenu.js.map +6 -0
  77. package/dist/jsx/createMenu.mjs +916 -0
  78. package/dist/jsx/createMenu.mjs.map +1 -0
  79. package/dist/jsx/createMenu.native.js +1136 -0
  80. package/dist/jsx/createMenu.native.js.map +1 -0
  81. package/dist/jsx/createNativeMenu/createNativeMenu.android.js +261 -0
  82. package/dist/jsx/createNativeMenu/createNativeMenu.android.js.map +6 -0
  83. package/dist/jsx/createNativeMenu/createNativeMenu.ios.js +373 -0
  84. package/dist/jsx/createNativeMenu/createNativeMenu.ios.js.map +6 -0
  85. package/dist/jsx/createNativeMenu/createNativeMenu.js +26 -0
  86. package/dist/jsx/createNativeMenu/createNativeMenu.js.map +6 -0
  87. package/dist/jsx/createNativeMenu/createNativeMenu.mjs +24 -0
  88. package/dist/jsx/createNativeMenu/createNativeMenu.mjs.map +1 -0
  89. package/dist/jsx/createNativeMenu/createNativeMenu.native.js +356 -0
  90. package/dist/jsx/createNativeMenu/createNativeMenu.native.js.map +1 -0
  91. package/dist/jsx/createNativeMenu/createNativeMenuTypes.js +1 -0
  92. package/dist/jsx/createNativeMenu/createNativeMenuTypes.js.map +6 -0
  93. package/dist/jsx/createNativeMenu/createNativeMenuTypes.mjs +2 -0
  94. package/dist/jsx/createNativeMenu/createNativeMenuTypes.mjs.map +1 -0
  95. package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js +19 -0
  96. package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js.map +1 -0
  97. package/dist/jsx/createNativeMenu/index.js +3 -0
  98. package/dist/jsx/createNativeMenu/index.js.map +6 -0
  99. package/dist/jsx/createNativeMenu/index.mjs +3 -0
  100. package/dist/jsx/createNativeMenu/index.mjs.map +1 -0
  101. package/dist/jsx/createNativeMenu/index.native.js +22 -0
  102. package/dist/jsx/createNativeMenu/index.native.js.map +1 -0
  103. package/dist/jsx/createNativeMenu/utils.js +47 -0
  104. package/dist/jsx/createNativeMenu/utils.js.map +6 -0
  105. package/dist/jsx/createNativeMenu/utils.mjs +29 -0
  106. package/dist/jsx/createNativeMenu/utils.mjs.map +1 -0
  107. package/dist/jsx/createNativeMenu/utils.native.js +94 -0
  108. package/dist/jsx/createNativeMenu/utils.native.js.map +1 -0
  109. package/dist/jsx/createNativeMenu/withNativeMenu.js +20 -0
  110. package/dist/jsx/createNativeMenu/withNativeMenu.js.map +6 -0
  111. package/dist/jsx/createNativeMenu/withNativeMenu.mjs +22 -0
  112. package/dist/jsx/createNativeMenu/withNativeMenu.mjs.map +1 -0
  113. package/dist/jsx/createNativeMenu/withNativeMenu.native.js +49 -0
  114. package/dist/jsx/createNativeMenu/withNativeMenu.native.js.map +1 -0
  115. package/package.json +6 -6
  116. package/types/createMenu.d.ts.map +1 -0
  117. package/types/createNativeMenu/createNativeMenu.android.d.ts.map +1 -0
  118. package/types/createNativeMenu/createNativeMenu.d.ts.map +1 -0
  119. package/types/createNativeMenu/createNativeMenu.ios.d.ts.map +1 -0
  120. package/types/createNativeMenu/createNativeMenu.native.d.ts.map +1 -0
  121. package/types/createNativeMenu/createNativeMenuTypes.d.ts.map +1 -0
  122. package/types/createNativeMenu/index.d.ts.map +1 -0
  123. package/types/createNativeMenu/utils.d.ts.map +1 -0
  124. package/types/createNativeMenu/withNativeMenu.d.ts.map +1 -0
@@ -0,0 +1,916 @@
1
+ import { Animate } from "@tamagui/animate";
2
+ import { AnimatePresence as Presence } from "@tamagui/animate-presence";
3
+ import { createCollection } from "@tamagui/collection";
4
+ import { Text, composeEventHandlers, composeRefs, createStyledContext, useComposedRefs } from "@tamagui/core";
5
+ import { Dismissable as DismissableLayer, dispatchDiscreteCustomEvent } from "@tamagui/dismissable";
6
+ import { useFocusGuards } from "@tamagui/focus-guard";
7
+ import { FocusScope } from "@tamagui/focus-scope";
8
+ import * as PopperPrimitive from "@tamagui/popper";
9
+ import { Portal as PortalPrimitive } from "@tamagui/portal";
10
+ import { RemoveScroll } from "@tamagui/remove-scroll";
11
+ import { RovingFocusGroup } from "@tamagui/roving-focus";
12
+ import { ThemeableStack, YStack } from "@tamagui/stacks";
13
+ import { useCallbackRef } from "@tamagui/use-callback-ref";
14
+ import { useDirection } from "@tamagui/use-direction";
15
+ import { isAndroid, isWeb, withStaticProperties } from "@tamagui/web";
16
+ import * as React from "react";
17
+ import { useId } from "react";
18
+ import { MenuPredefinied } from "./Menu.mjs";
19
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
+ const SELECTION_KEYS = ["Enter", " "],
21
+ FIRST_KEYS = ["ArrowDown", "PageUp", "Home"],
22
+ LAST_KEYS = ["ArrowUp", "PageDown", "End"],
23
+ FIRST_LAST_KEYS = [...FIRST_KEYS, ...LAST_KEYS],
24
+ SUB_OPEN_KEYS = {
25
+ ltr: [...SELECTION_KEYS, "ArrowRight"],
26
+ rtl: [...SELECTION_KEYS, "ArrowLeft"]
27
+ },
28
+ SUB_CLOSE_KEYS = {
29
+ ltr: ["ArrowLeft"],
30
+ rtl: ["ArrowRight"]
31
+ },
32
+ MENU_NAME = "Menu",
33
+ [Collection, useCollection] = createCollection(MENU_NAME),
34
+ {
35
+ Provider: MenuProvider,
36
+ useStyledContext: useMenuContext
37
+ } = createStyledContext(),
38
+ {
39
+ Provider: MenuRootProvider,
40
+ useStyledContext: useMenuRootContext
41
+ } = createStyledContext(),
42
+ MENU_CONTEXT = "MenuContext",
43
+ {
44
+ Provider: NativePropProvider,
45
+ useStyledContext: useNativeProp
46
+ } = createStyledContext({
47
+ native: !1
48
+ });
49
+ function createMenu({
50
+ Item: _Item = MenuPredefinied.MenuItem,
51
+ Title: _Title = MenuPredefinied.Title,
52
+ SubTitle: _SubTitle = MenuPredefinied.SubTitle,
53
+ Image: _Image = MenuPredefinied.MenuImage,
54
+ Icon: _Icon = MenuPredefinied.MenuIcon,
55
+ Indicator: _Indicator = MenuPredefinied.MenuIndicator,
56
+ Separator: _Separator = MenuPredefinied.MenuSeparator,
57
+ MenuGroup: _MenuGroup = MenuPredefinied.MenuGroup,
58
+ Label: _Label = MenuPredefinied.MenuLabel
59
+ }) {
60
+ const MenuComp = props => {
61
+ const {
62
+ scope,
63
+ open = !1,
64
+ children,
65
+ dir,
66
+ onOpenChange,
67
+ modal = !0,
68
+ ...rest
69
+ } = props,
70
+ [content, setContent] = React.useState(null),
71
+ isUsingKeyboardRef = React.useRef(!1),
72
+ handleOpenChange = useCallbackRef(onOpenChange),
73
+ direction = useDirection(dir);
74
+ return isWeb && React.useEffect(() => {
75
+ const handleKeyDown = () => {
76
+ isUsingKeyboardRef.current = !0, document.addEventListener("pointerdown", handlePointer, {
77
+ capture: !0,
78
+ once: !0
79
+ }), document.addEventListener("pointermove", handlePointer, {
80
+ capture: !0,
81
+ once: !0
82
+ });
83
+ },
84
+ handlePointer = () => isUsingKeyboardRef.current = !1;
85
+ return document.addEventListener("keydown", handleKeyDown, {
86
+ capture: !0
87
+ }), () => {
88
+ document.removeEventListener("keydown", handleKeyDown, {
89
+ capture: !0
90
+ }), document.removeEventListener("pointerdown", handlePointer, {
91
+ capture: !0
92
+ }), document.removeEventListener("pointermove", handlePointer, {
93
+ capture: !0
94
+ });
95
+ };
96
+ }, []), /* @__PURE__ */jsx(PopperPrimitive.Popper, {
97
+ scope: scope || MENU_CONTEXT,
98
+ ...rest,
99
+ children: /* @__PURE__ */jsx(MenuProvider, {
100
+ scope,
101
+ open,
102
+ onOpenChange: handleOpenChange,
103
+ content,
104
+ onContentChange: setContent,
105
+ children: /* @__PURE__ */jsx(NativePropProvider, {
106
+ native: !1,
107
+ scope,
108
+ children: /* @__PURE__ */jsx(MenuRootProvider, {
109
+ scope,
110
+ onClose: React.useCallback(() => handleOpenChange(!1), [handleOpenChange]),
111
+ isUsingKeyboardRef,
112
+ dir: direction,
113
+ modal,
114
+ children: /* @__PURE__ */jsx(MenuSubProvider, {
115
+ scope,
116
+ children
117
+ })
118
+ })
119
+ })
120
+ })
121
+ });
122
+ },
123
+ RepropagateMenuAndMenuRootProvider = props => {
124
+ const {
125
+ scope,
126
+ menuContext,
127
+ rootContext,
128
+ popperContext,
129
+ menuSubContext,
130
+ children
131
+ } = props;
132
+ return /* @__PURE__ */jsx(PopperPrimitive.PopperProvider, {
133
+ ...popperContext,
134
+ scope: scope || MENU_CONTEXT,
135
+ children: /* @__PURE__ */jsx(NativePropProvider, {
136
+ native: !1,
137
+ scope,
138
+ children: /* @__PURE__ */jsx(MenuProvider, {
139
+ scope,
140
+ ...menuContext,
141
+ children: /* @__PURE__ */jsx(MenuRootProvider, {
142
+ scope,
143
+ ...rootContext,
144
+ children: menuSubContext ? /* @__PURE__ */jsx(MenuSubProvider, {
145
+ scope,
146
+ ...menuSubContext,
147
+ children
148
+ }) : children
149
+ })
150
+ })
151
+ })
152
+ });
153
+ };
154
+ MenuComp.displayName = MENU_NAME;
155
+ const ANCHOR_NAME = "MenuAnchor",
156
+ MenuAnchor = props => /* @__PURE__ */jsx(PopperPrimitive.PopperAnchor, {
157
+ scope: MENU_CONTEXT,
158
+ ...props
159
+ });
160
+ MenuAnchor.displayName = ANCHOR_NAME;
161
+ const PORTAL_NAME = "MenuPortal",
162
+ {
163
+ Provider: PortalProvider,
164
+ useStyledContext: usePortalContext
165
+ } = createStyledContext(void 0, "Portal"),
166
+ MenuPortal = props => {
167
+ const {
168
+ scope,
169
+ forceMount,
170
+ zIndex,
171
+ children
172
+ // TODO removed
173
+ // host
174
+ } = props,
175
+ menuContext = useMenuContext(scope),
176
+ rootContext = useMenuRootContext(scope),
177
+ popperContext = PopperPrimitive.usePopperContext(scope || MENU_CONTEXT),
178
+ menuSubContext = useMenuSubContext(scope),
179
+ content = isAndroid ? /* @__PURE__ */jsx(RepropagateMenuAndMenuRootProvider, {
180
+ menuContext,
181
+ rootContext,
182
+ popperContext,
183
+ menuSubContext,
184
+ scope,
185
+ children
186
+ }) : children;
187
+ return /* @__PURE__ */jsx(Animate, {
188
+ type: "presence",
189
+ present: forceMount || menuContext.open,
190
+ children: /* @__PURE__ */jsx(PortalPrimitive, {
191
+ host,
192
+ children: /* @__PURE__ */jsx(Fragment, {
193
+ children: /* @__PURE__ */jsx(PortalProvider, {
194
+ scope,
195
+ forceMount,
196
+ children: /* @__PURE__ */jsxs(YStack, {
197
+ zIndex: zIndex || 100,
198
+ fullscreen: !0,
199
+ children: [!!menuContext.open && !isWeb && /* @__PURE__ */jsx(YStack, {
200
+ fullscreen: !0,
201
+ onPress: () => menuContext.onOpenChange(!menuContext.open)
202
+ }), content]
203
+ })
204
+ })
205
+ })
206
+ })
207
+ });
208
+ };
209
+ MenuPortal.displayName = PORTAL_NAME;
210
+ const CONTENT_NAME = "MenuContent",
211
+ {
212
+ Provider: MenuContentProvider,
213
+ useStyledContext: useMenuContentContext
214
+ } = createStyledContext(),
215
+ MenuContent = React.forwardRef((props, forwardedRef) => {
216
+ const portalContext = usePortalContext(props.scope),
217
+ {
218
+ forceMount = portalContext.forceMount,
219
+ ...contentProps
220
+ } = props,
221
+ rootContext = useMenuRootContext(props.scope);
222
+ return /* @__PURE__ */jsx(Collection.Provider, {
223
+ scope: props.scope || MENU_CONTEXT,
224
+ children: /* @__PURE__ */jsx(Collection.Slot, {
225
+ scope: props.scope || MENU_CONTEXT,
226
+ children: rootContext.modal ? /* @__PURE__ */jsx(MenuRootContentModal, {
227
+ ...contentProps,
228
+ ref: forwardedRef
229
+ }) : /* @__PURE__ */jsx(MenuRootContentNonModal, {
230
+ ...contentProps,
231
+ ref: forwardedRef
232
+ })
233
+ })
234
+ });
235
+ }),
236
+ MenuRootContentModal = React.forwardRef((props, forwardedRef) => {
237
+ const context = useMenuContext(props.scope),
238
+ ref = React.useRef(null),
239
+ composedRefs = useComposedRefs(forwardedRef, ref);
240
+ return /* @__PURE__ */jsx(MenuContentImpl, {
241
+ ...props,
242
+ ref: composedRefs,
243
+ trapFocus: context.open,
244
+ disableOutsidePointerEvents: context.open,
245
+ disableOutsideScroll: !0,
246
+ onFocusOutside: composeEventHandlers(props.onFocusOutside, event => event.preventDefault(), {
247
+ checkDefaultPrevented: !1
248
+ }),
249
+ onDismiss: () => context.onOpenChange(!1)
250
+ });
251
+ }),
252
+ MenuRootContentNonModal = React.forwardRef((props, forwardedRef) => {
253
+ const context = useMenuContext(props.scope);
254
+ return /* @__PURE__ */jsx(MenuContentImpl, {
255
+ ...props,
256
+ ref: forwardedRef,
257
+ trapFocus: !1,
258
+ disableOutsidePointerEvents: !1,
259
+ disableOutsideScroll: !1,
260
+ onDismiss: () => context.onOpenChange(!1)
261
+ });
262
+ }),
263
+ Fragment2 = React.forwardRef((props, ref) => props.children),
264
+ MenuContentImpl = React.forwardRef((props, forwardedRef) => {
265
+ const {
266
+ scope = MENU_CONTEXT,
267
+ loop = !1,
268
+ trapFocus,
269
+ onOpenAutoFocus,
270
+ onCloseAutoFocus,
271
+ disableOutsidePointerEvents,
272
+ onEntryFocus,
273
+ onEscapeKeyDown,
274
+ onPointerDownOutside,
275
+ onFocusOutside,
276
+ onInteractOutside,
277
+ onDismiss,
278
+ disableOutsideScroll,
279
+ unstyled = process.env.TAMAGUI_HEADLESS === "1",
280
+ ...contentProps
281
+ } = props,
282
+ context = useMenuContext(scope),
283
+ rootContext = useMenuRootContext(scope),
284
+ getItems = useCollection(scope),
285
+ [currentItemId, setCurrentItemId] = React.useState(null),
286
+ contentRef = React.useRef(null),
287
+ composedRefs = useComposedRefs(forwardedRef, contentRef, context.onContentChange),
288
+ timerRef = React.useRef(0),
289
+ searchRef = React.useRef(""),
290
+ pointerGraceTimerRef = React.useRef(0),
291
+ pointerGraceIntentRef = React.useRef(null),
292
+ pointerDirRef = React.useRef("right"),
293
+ lastPointerXRef = React.useRef(0),
294
+ handleTypeaheadSearch = key => {
295
+ const search = searchRef.current + key,
296
+ items = getItems().filter(item => !item.disabled),
297
+ currentItem = document.activeElement,
298
+ currentMatch = items.find(item => item.ref.current === currentItem)?.textValue,
299
+ values = items.map(item => item.textValue),
300
+ nextMatch = getNextMatch(values, search, currentMatch),
301
+ newItem = items.find(item => item.textValue === nextMatch)?.ref.current;
302
+ (function updateSearch(value) {
303
+ searchRef.current = value, clearTimeout(timerRef.current), value !== "" && (timerRef.current = setTimeout(() => updateSearch(""), 1e3));
304
+ })(search), newItem && setTimeout(() => newItem.focus());
305
+ };
306
+ React.useEffect(() => () => clearTimeout(timerRef.current), []), isWeb && useFocusGuards();
307
+ const isPointerMovingToSubmenu = React.useCallback(event => pointerDirRef.current === pointerGraceIntentRef.current?.side && isPointerInGraceArea(event, pointerGraceIntentRef.current?.area), []),
308
+ content = /* @__PURE__ */jsx(PopperPrimitive.PopperContent, {
309
+ role: "menu",
310
+ ...(!unstyled && {
311
+ elevation: 30,
312
+ paddingVertical: "$2",
313
+ backgroundColor: "$background",
314
+ borderColor: "$borderColor",
315
+ outlineWidth: 0
316
+ }),
317
+ "aria-orientation": "vertical",
318
+ "data-state": getOpenState(context.open),
319
+ "data-tamagui-menu-content": "",
320
+ dir: rootContext.dir,
321
+ scope: scope || MENU_CONTEXT,
322
+ ...contentProps,
323
+ ref: composedRefs,
324
+ className: contentProps.animation ? void 0 : contentProps.className,
325
+ ...(isWeb ? {
326
+ onKeyDown: composeEventHandlers(
327
+ //@ts-ignore
328
+ contentProps.onKeyDown, event => {
329
+ const isKeyDownInside = event.target.closest("[data-tamagui-menu-content]") === event.currentTarget,
330
+ isModifierKey = event.ctrlKey || event.altKey || event.metaKey,
331
+ isCharacterKey = event.key.length === 1;
332
+ isKeyDownInside && (event.key === "Tab" && event.preventDefault(), !isModifierKey && isCharacterKey && handleTypeaheadSearch(event.key));
333
+ const content2 = contentRef.current;
334
+ if (event.target !== content2 || !FIRST_LAST_KEYS.includes(event.key)) return;
335
+ event.preventDefault();
336
+ const candidateNodes = getItems().filter(item => !item.disabled).map(item => item.ref.current);
337
+ LAST_KEYS.includes(event.key) && candidateNodes.reverse(), focusFirst(candidateNodes);
338
+ }),
339
+ // @ts-ignore
340
+ onBlur: composeEventHandlers(props.onBlur, event => {
341
+ event.currentTarget?.contains(event.target) || (clearTimeout(timerRef.current), searchRef.current = "");
342
+ }),
343
+ onPointerMove: composeEventHandlers(
344
+ // @ts-ignore
345
+ props.onPointerMove,
346
+ // @ts-ignore
347
+ whenMouse(event => {
348
+ const target = event.target,
349
+ pointerXHasChanged = lastPointerXRef.current !== event.clientX;
350
+ if (event.currentTarget?.contains(target) && pointerXHasChanged) {
351
+ const newDir = event.clientX > lastPointerXRef.current ? "right" : "left";
352
+ pointerDirRef.current = newDir, lastPointerXRef.current = event.clientX;
353
+ }
354
+ }))
355
+ } : {})
356
+ });
357
+ return /* @__PURE__ */jsx(MenuContentProvider, {
358
+ scope,
359
+ searchRef,
360
+ onItemEnter: React.useCallback(event => {
361
+ isPointerMovingToSubmenu(event) && event.preventDefault();
362
+ }, [isPointerMovingToSubmenu]),
363
+ onItemLeave: React.useCallback(event => {
364
+ isPointerMovingToSubmenu(event) || (contentRef.current?.focus(), setCurrentItemId(null));
365
+ }, [isPointerMovingToSubmenu]),
366
+ onTriggerLeave: React.useCallback(event => {
367
+ isPointerMovingToSubmenu(event) && event.preventDefault();
368
+ }, [isPointerMovingToSubmenu]),
369
+ pointerGraceTimerRef,
370
+ onPointerGraceIntentChange: React.useCallback(intent => {
371
+ pointerGraceIntentRef.current = intent;
372
+ }, []),
373
+ children: /* @__PURE__ */jsx(RemoveScroll, {
374
+ enabled: disableOutsideScroll,
375
+ children: /* @__PURE__ */jsx(FocusScope, {
376
+ asChild: !1,
377
+ trapped: trapFocus,
378
+ onMountAutoFocus: composeEventHandlers(onOpenAutoFocus, event => {
379
+ event.preventDefault(), contentRef.current?.focus();
380
+ }),
381
+ onUnmountAutoFocus: onCloseAutoFocus,
382
+ children: /* @__PURE__ */jsx(DismissableLayer, {
383
+ disableOutsidePointerEvents,
384
+ onEscapeKeyDown,
385
+ onPointerDownOutside,
386
+ onFocusOutside,
387
+ onInteractOutside,
388
+ onDismiss,
389
+ asChild: !0,
390
+ children: /* @__PURE__ */jsx(RovingFocusGroup, {
391
+ asChild: !0,
392
+ __scopeRovingFocusGroup: scope || MENU_CONTEXT,
393
+ dir: rootContext.dir,
394
+ orientation: "vertical",
395
+ loop,
396
+ currentTabStopId: currentItemId,
397
+ onCurrentTabStopIdChange: setCurrentItemId,
398
+ onEntryFocus: composeEventHandlers(onEntryFocus, event => {
399
+ rootContext.isUsingKeyboardRef.current || event.preventDefault();
400
+ }),
401
+ children: content
402
+ })
403
+ })
404
+ })
405
+ })
406
+ });
407
+ });
408
+ MenuContent.displayName = CONTENT_NAME;
409
+ const ITEM_NAME = "MenuItem",
410
+ ITEM_SELECT = "menu.itemSelect",
411
+ MenuItem = ThemeableStack.styleable((props, forwardedRef) => {
412
+ const {
413
+ disabled = !1,
414
+ onSelect,
415
+ children,
416
+ ...itemProps
417
+ } = props,
418
+ ref = React.useRef(null),
419
+ rootContext = useMenuRootContext(props.scope),
420
+ contentContext = useMenuContentContext(props.scope),
421
+ composedRefs = useComposedRefs(forwardedRef, ref),
422
+ isPointerDownRef = React.useRef(!1),
423
+ handleSelect = () => {
424
+ const menuItem = ref.current;
425
+ if (!disabled && menuItem) if (isWeb) {
426
+ const itemSelectEvent = new CustomEvent(ITEM_SELECT, {
427
+ bubbles: !0,
428
+ cancelable: !0
429
+ });
430
+ menuItem.addEventListener(ITEM_SELECT, event => onSelect?.(event), {
431
+ once: !0
432
+ }), dispatchDiscreteCustomEvent(menuItem, itemSelectEvent), itemSelectEvent.defaultPrevented ? isPointerDownRef.current = !1 : rootContext.onClose();
433
+ } else onSelect?.({
434
+ target: menuItem
435
+ }), isPointerDownRef.current = !1, rootContext.onClose();
436
+ },
437
+ content = typeof children == "string" ? /* @__PURE__ */jsx(Text, {
438
+ children
439
+ }) : children;
440
+ return /* @__PURE__ */jsx(MenuItemImpl, {
441
+ outlineStyle: "none",
442
+ ...itemProps,
443
+ ref: composedRefs,
444
+ disabled,
445
+ onPress: composeEventHandlers(props.onPress, handleSelect),
446
+ onPointerDown: event => {
447
+ props.onPointerDown?.(event), isPointerDownRef.current = !0;
448
+ },
449
+ onPointerUp: composeEventHandlers(props.onPointerUp, event => {
450
+ isWeb && (isPointerDownRef.current || event.currentTarget?.click());
451
+ }),
452
+ ...(isWeb ? {
453
+ onKeyDown: composeEventHandlers(
454
+ // @ts-ignore
455
+ props.onKeyDown, event => {
456
+ const isTypingAhead = contentContext.searchRef.current !== "";
457
+ disabled || isTypingAhead && event.key === " " || SELECTION_KEYS.includes(event.key) && (event.currentTarget?.click(), event.preventDefault());
458
+ })
459
+ } : {}),
460
+ children: content
461
+ });
462
+ }),
463
+ MenuItemImpl = React.forwardRef((props, forwardedRef) => {
464
+ const {
465
+ scope,
466
+ disabled = !1,
467
+ textValue,
468
+ unstyled = process.env.TAMAGUI_HEADLESS === "1",
469
+ ...itemProps
470
+ } = props,
471
+ contentContext = useMenuContentContext(scope),
472
+ ref = React.useRef(null),
473
+ composedRefs = useComposedRefs(forwardedRef, ref),
474
+ [isFocused, setIsFocused] = React.useState(!1),
475
+ [textContent, setTextContent] = React.useState("");
476
+ return isWeb && React.useEffect(() => {
477
+ const menuItem = ref.current;
478
+ menuItem && setTextContent((menuItem.textContent ?? "").trim());
479
+ }, [itemProps.children]), /* @__PURE__ */jsx(Collection.ItemSlot, {
480
+ scope: scope || MENU_CONTEXT,
481
+ disabled,
482
+ textValue: textValue ?? textContent,
483
+ children: /* @__PURE__ */jsx(RovingFocusGroup.Item, {
484
+ asChild: !0,
485
+ __scopeRovingFocusGroup: scope || MENU_CONTEXT,
486
+ focusable: !disabled,
487
+ ...(!unstyled && {
488
+ flexDirection: "row",
489
+ alignItems: "center"
490
+ }),
491
+ ...itemProps,
492
+ children: /* @__PURE__ */jsx(_Item, {
493
+ ...(!unstyled && {
494
+ hoverTheme: !0,
495
+ pressTheme: !0,
496
+ focusTheme: !0,
497
+ paddingVertical: "$2",
498
+ paddingHorizontal: "$4",
499
+ width: "100%"
500
+ }),
501
+ componentName: ITEM_NAME,
502
+ role: "menuitem",
503
+ "data-highlighted": isFocused ? "" : void 0,
504
+ "aria-disabled": disabled || void 0,
505
+ "data-disabled": disabled ? "" : void 0,
506
+ ...itemProps,
507
+ ref: composedRefs,
508
+ onPointerMove: composeEventHandlers(props.onPointerMove,
509
+ // @ts-ignore
510
+ whenMouse(event => {
511
+ disabled ? contentContext.onItemLeave(event) : (contentContext.onItemEnter(event), event.defaultPrevented || event.currentTarget.focus());
512
+ })),
513
+ onPointerLeave: composeEventHandlers(
514
+ // @ts-ignore
515
+ props.onPointerLeave,
516
+ // @ts-ignore
517
+ whenMouse(event => contentContext.onItemLeave(event))),
518
+ onFocus: composeEventHandlers(props.onFocus, () => setIsFocused(!0)),
519
+ onBlur: composeEventHandlers(props.onBlur, () => setIsFocused(!1))
520
+ })
521
+ })
522
+ });
523
+ });
524
+ MenuItem.displayName = ITEM_NAME;
525
+ const ITEM_TITLE_NAME = "MenuItemTitle",
526
+ MenuItemTitle = _Title.styleable((props, forwardedRef) => /* @__PURE__ */jsx(_Title, {
527
+ ...props,
528
+ ref: forwardedRef
529
+ }));
530
+ MenuItemTitle.displayName = ITEM_TITLE_NAME;
531
+ const ITEM_SUB_TITLE_NAME = "MenuItemSubTitle",
532
+ MenuItemSubTitle = _SubTitle.styleable((props, forwardedRef) => /* @__PURE__ */jsx(_SubTitle, {
533
+ ...props,
534
+ ref: forwardedRef
535
+ }));
536
+ MenuItemSubTitle.displayName = ITEM_SUB_TITLE_NAME;
537
+ const ITEM_IMAGE = "MenuItemImage",
538
+ MenuItemImage = React.forwardRef((props, forwardedRef) => /* @__PURE__ */jsx(_Image, {
539
+ ...props,
540
+ ref: forwardedRef
541
+ }));
542
+ MenuItemImage.displayName = ITEM_IMAGE;
543
+ const ITEM_ICON = "MenuItemIcon",
544
+ MenuItemIcon = _Icon.styleable((props, forwardedRef) => /* @__PURE__ */jsx(_Icon, {
545
+ ...props,
546
+ ref: forwardedRef
547
+ }));
548
+ MenuItemIcon.displayName = ITEM_ICON;
549
+ const CHECKBOX_ITEM_NAME = "MenuCheckboxItem",
550
+ MenuCheckboxItem = ThemeableStack.styleable((props, forwardedRef) => {
551
+ const {
552
+ checked = !1,
553
+ onCheckedChange,
554
+ ...checkboxItemProps
555
+ } = props;
556
+ return /* @__PURE__ */jsx(ItemIndicatorProvider, {
557
+ scope: props.scope,
558
+ checked,
559
+ children: /* @__PURE__ */jsx(MenuItem, {
560
+ componentName: CHECKBOX_ITEM_NAME,
561
+ role: isWeb ? "menuitemcheckbox" : "menuitem",
562
+ "aria-checked": isIndeterminate(checked) ? "mixed" : checked,
563
+ ...checkboxItemProps,
564
+ ref: forwardedRef,
565
+ "data-state": getCheckedState(checked),
566
+ onSelect: composeEventHandlers(checkboxItemProps.onSelect, () => onCheckedChange?.(isIndeterminate(checked) ? !0 : !checked), {
567
+ checkDefaultPrevented: !1
568
+ })
569
+ })
570
+ });
571
+ });
572
+ MenuCheckboxItem.displayName = CHECKBOX_ITEM_NAME;
573
+ const RADIO_GROUP_NAME = "MenuRadioGroup",
574
+ {
575
+ Provider: RadioGroupProvider,
576
+ useStyledContext: useRadioGroupContext
577
+ } = createStyledContext(),
578
+ MenuRadioGroup = _MenuGroup.styleable((props, forwardedRef) => {
579
+ const {
580
+ value,
581
+ onValueChange,
582
+ scope,
583
+ ...groupProps
584
+ } = props,
585
+ handleValueChange = useCallbackRef(onValueChange);
586
+ return /* @__PURE__ */jsx(RadioGroupProvider, {
587
+ scope,
588
+ value,
589
+ onValueChange: handleValueChange,
590
+ children: /* @__PURE__ */jsx(_MenuGroup, {
591
+ componentName: RADIO_GROUP_NAME,
592
+ ...groupProps,
593
+ ref: forwardedRef
594
+ })
595
+ });
596
+ });
597
+ MenuRadioGroup.displayName = RADIO_GROUP_NAME;
598
+ const RADIO_ITEM_NAME = "MenuRadioItem",
599
+ MenuRadioItem = ThemeableStack.styleable((props, forwardedRef) => {
600
+ const {
601
+ value,
602
+ ...radioItemProps
603
+ } = props,
604
+ context = useRadioGroupContext(props.scope),
605
+ checked = value === context.value;
606
+ return /* @__PURE__ */jsx(ItemIndicatorProvider, {
607
+ scope: props.scope,
608
+ checked,
609
+ children: /* @__PURE__ */jsx(MenuItem, {
610
+ componentName: RADIO_ITEM_NAME,
611
+ ...radioItemProps,
612
+ "aria-checked": checked,
613
+ ref: forwardedRef,
614
+ role: isWeb ? "menuitemradio" : "menuitem",
615
+ "data-state": getCheckedState(checked),
616
+ onSelect: composeEventHandlers(radioItemProps.onSelect, () => context.onValueChange?.(value), {
617
+ checkDefaultPrevented: !1
618
+ })
619
+ })
620
+ });
621
+ });
622
+ MenuRadioItem.displayName = RADIO_ITEM_NAME;
623
+ const ITEM_INDICATOR_NAME = "MenuItemIndicator",
624
+ {
625
+ Provider: ItemIndicatorProvider,
626
+ useStyledContext: useItemIndicatorContext
627
+ } = createStyledContext(),
628
+ MenuItemIndicator = _Indicator.styleable((props, forwardedRef) => {
629
+ const {
630
+ scope,
631
+ forceMount,
632
+ ...itemIndicatorProps
633
+ } = props,
634
+ indicatorContext = useItemIndicatorContext(scope);
635
+ return /* @__PURE__ */jsx(Presence, {
636
+ children: forceMount || isIndeterminate(indicatorContext.checked) || indicatorContext.checked === !0 ? /* @__PURE__ */jsx(_Indicator, {
637
+ componentName: ITEM_INDICATOR_NAME,
638
+ tag: "span",
639
+ ...itemIndicatorProps,
640
+ ref: forwardedRef,
641
+ "data-state": getCheckedState(indicatorContext.checked)
642
+ }) : null
643
+ });
644
+ });
645
+ MenuItemIndicator.displayName = ITEM_INDICATOR_NAME;
646
+ const MenuArrow = React.forwardRef(function (props, forwardedRef) {
647
+ const {
648
+ scope,
649
+ unstyled = process.env.TAMAGUI_HEADLESS === "1",
650
+ ...rest
651
+ } = props;
652
+ return /* @__PURE__ */jsx(PopperPrimitive.PopperArrow, {
653
+ scope: scope || MENU_CONTEXT,
654
+ componentName: "PopperArrow",
655
+ ...(!unstyled && {
656
+ backgroundColor: "$background"
657
+ }),
658
+ ...rest,
659
+ ref: forwardedRef
660
+ });
661
+ }),
662
+ SUB_NAME = "MenuSub",
663
+ {
664
+ Provider: MenuSubProvider,
665
+ useStyledContext: useMenuSubContext
666
+ } = createStyledContext(),
667
+ MenuSub = props => {
668
+ const {
669
+ scope,
670
+ children,
671
+ open = !1,
672
+ onOpenChange,
673
+ ...rest
674
+ } = props,
675
+ parentMenuContext = useMenuContext(scope),
676
+ [trigger, setTrigger] = React.useState(null),
677
+ [content, setContent] = React.useState(null),
678
+ handleOpenChange = useCallbackRef(onOpenChange);
679
+ return React.useEffect(() => (parentMenuContext.open === !1 && handleOpenChange(!1), () => handleOpenChange(!1)), [parentMenuContext.open, handleOpenChange]), /* @__PURE__ */jsx(PopperPrimitive.Popper, {
680
+ ...rest,
681
+ scope: scope || MENU_CONTEXT,
682
+ children: /* @__PURE__ */jsx(MenuProvider, {
683
+ scope,
684
+ open,
685
+ onOpenChange: handleOpenChange,
686
+ content,
687
+ onContentChange: setContent,
688
+ children: /* @__PURE__ */jsx(MenuSubProvider, {
689
+ scope,
690
+ contentId: useId(),
691
+ triggerId: useId(),
692
+ trigger,
693
+ onTriggerChange: setTrigger,
694
+ children
695
+ })
696
+ })
697
+ });
698
+ };
699
+ MenuSub.displayName = SUB_NAME;
700
+ const SUB_TRIGGER_NAME = "MenuSubTrigger",
701
+ MenuSubTrigger = YStack.styleable((props, forwardedRef) => {
702
+ const context = useMenuContext(props.scope),
703
+ rootContext = useMenuRootContext(props.scope),
704
+ subContext = useMenuSubContext(props.scope),
705
+ contentContext = useMenuContentContext(props.scope),
706
+ openTimerRef = React.useRef(null),
707
+ {
708
+ pointerGraceTimerRef,
709
+ onPointerGraceIntentChange
710
+ } = contentContext,
711
+ clearOpenTimer = React.useCallback(() => {
712
+ openTimerRef.current && window.clearTimeout(openTimerRef.current), openTimerRef.current = null;
713
+ }, []);
714
+ return React.useEffect(() => clearOpenTimer, [clearOpenTimer]), React.useEffect(() => {
715
+ const pointerGraceTimer = pointerGraceTimerRef.current;
716
+ return () => {
717
+ window.clearTimeout(pointerGraceTimer), onPointerGraceIntentChange(null);
718
+ };
719
+ }, [pointerGraceTimerRef, onPointerGraceIntentChange]), /* @__PURE__ */jsx(MenuAnchor, {
720
+ componentName: SUB_TRIGGER_NAME,
721
+ asChild: !0,
722
+ scope: props.scope || MENU_CONTEXT,
723
+ children: /* @__PURE__ */jsx(MenuItemImpl, {
724
+ id: subContext.triggerId,
725
+ "aria-haspopup": "menu",
726
+ "aria-expanded": context.open,
727
+ "aria-controls": subContext.contentId,
728
+ "data-state": getOpenState(context.open),
729
+ outlineStyle: "none",
730
+ ...props,
731
+ ref: composeRefs(forwardedRef, subContext.onTriggerChange),
732
+ onPress: event => {
733
+ props.onPress?.(event), !(props.disabled || event.defaultPrevented) && (isWeb && event.currentTarget.focus(), context.open || context.onOpenChange(!0));
734
+ },
735
+ onPointerMove: composeEventHandlers(props.onPointerMove,
736
+ // @ts-ignore
737
+ whenMouse(event => {
738
+ contentContext.onItemEnter(event), !event.defaultPrevented && !props.disabled && !context.open && !openTimerRef.current && (contentContext.onPointerGraceIntentChange(null), openTimerRef.current = window.setTimeout(() => {
739
+ context.onOpenChange(!0), clearOpenTimer();
740
+ }, 100));
741
+ })),
742
+ onPointerLeave: composeEventHandlers(props.onPointerLeave,
743
+ // @ts-ignore
744
+ whenMouse(event => {
745
+ clearOpenTimer();
746
+ const contentRect = context.content?.getBoundingClientRect();
747
+ if (contentRect) {
748
+ const side = context.content?.dataset.side,
749
+ rightSide = side === "right",
750
+ bleed = rightSide ? -5 : 5,
751
+ contentNearEdge = contentRect[rightSide ? "left" : "right"],
752
+ contentFarEdge = contentRect[rightSide ? "right" : "left"];
753
+ contentContext.onPointerGraceIntentChange({
754
+ area: [
755
+ // Apply a bleed on clientX to ensure that our exit point is
756
+ // consistently within polygon bounds
757
+ {
758
+ x: event.clientX + bleed,
759
+ y: event.clientY
760
+ }, {
761
+ x: contentNearEdge,
762
+ y: contentRect.top
763
+ }, {
764
+ x: contentFarEdge,
765
+ y: contentRect.top
766
+ }, {
767
+ x: contentFarEdge,
768
+ y: contentRect.bottom
769
+ }, {
770
+ x: contentNearEdge,
771
+ y: contentRect.bottom
772
+ }],
773
+ side
774
+ }), window.clearTimeout(pointerGraceTimerRef.current), pointerGraceTimerRef.current = window.setTimeout(() => contentContext.onPointerGraceIntentChange(null), 300);
775
+ } else {
776
+ if (contentContext.onTriggerLeave(event), event.defaultPrevented) return;
777
+ contentContext.onPointerGraceIntentChange(null);
778
+ }
779
+ })),
780
+ ...(isWeb ? {
781
+ onKeyDown: composeEventHandlers(
782
+ // @ts-ignore
783
+ props.onKeyDown, event => {
784
+ const isTypingAhead = contentContext.searchRef.current !== "";
785
+ props.disabled || isTypingAhead && event.key === " " || SUB_OPEN_KEYS[rootContext.dir].includes(event.key) && (context.onOpenChange(!0), context.content?.focus(), event.preventDefault());
786
+ })
787
+ } : null)
788
+ })
789
+ });
790
+ });
791
+ MenuSubTrigger.displayName = SUB_TRIGGER_NAME;
792
+ const SUB_CONTENT_NAME = "MenuSubContent",
793
+ MenuSubContent = React.forwardRef((props, forwardedRef) => {
794
+ const portalContext = usePortalContext(props.scope),
795
+ {
796
+ forceMount = portalContext.forceMount,
797
+ ...subContentProps
798
+ } = props,
799
+ context = useMenuContext(props.scope),
800
+ rootContext = useMenuRootContext(props.scope),
801
+ subContext = useMenuSubContext(props.scope),
802
+ ref = React.useRef(null),
803
+ composedRefs = useComposedRefs(forwardedRef, ref);
804
+ return /* @__PURE__ */jsx(Collection.Provider, {
805
+ scope: props.scope || MENU_CONTEXT,
806
+ children: /* @__PURE__ */jsx(Collection.Slot, {
807
+ scope: props.scope || MENU_CONTEXT,
808
+ children: /* @__PURE__ */jsx(MenuContentImpl, {
809
+ id: subContext.contentId,
810
+ "aria-labelledby": subContext.triggerId,
811
+ ...subContentProps,
812
+ ref: composedRefs,
813
+ "data-side": rootContext.dir === "rtl" ? "left" : "right",
814
+ disableOutsidePointerEvents: !1,
815
+ disableOutsideScroll: !1,
816
+ trapFocus: !1,
817
+ onOpenAutoFocus: event => {
818
+ rootContext.isUsingKeyboardRef.current && ref.current?.focus(), event.preventDefault();
819
+ },
820
+ onCloseAutoFocus: event => event.preventDefault(),
821
+ onFocusOutside: composeEventHandlers(props.onFocusOutside, event => {
822
+ event.target !== subContext.trigger && context.onOpenChange(!1);
823
+ }),
824
+ onEscapeKeyDown: composeEventHandlers(props.onEscapeKeyDown, event => {
825
+ rootContext.onClose(), event.preventDefault();
826
+ }),
827
+ ...(isWeb ? {
828
+ // @ts-ignore
829
+ onKeyDown: composeEventHandlers(
830
+ // @ts-ignore
831
+ props.onKeyDown, event => {
832
+ const isKeyDownInside = event.currentTarget.contains(event.target),
833
+ isCloseKey = SUB_CLOSE_KEYS[rootContext.dir].includes(event.key);
834
+ isKeyDownInside && isCloseKey && (context.onOpenChange(!1), subContext.trigger?.focus(), event.preventDefault());
835
+ })
836
+ } : null)
837
+ })
838
+ })
839
+ });
840
+ });
841
+ return MenuSubContent.displayName = SUB_CONTENT_NAME, {
842
+ Menu: withStaticProperties(MenuComp, {
843
+ Anchor: MenuAnchor,
844
+ Portal: MenuPortal,
845
+ Content: MenuContent,
846
+ Group: _MenuGroup,
847
+ Label: _Label,
848
+ Item: MenuItem,
849
+ CheckboxItem: MenuCheckboxItem,
850
+ RadioGroup: MenuRadioGroup,
851
+ RadioItem: MenuRadioItem,
852
+ ItemIndicator: MenuItemIndicator,
853
+ Separator: _Separator,
854
+ Arrow: MenuArrow,
855
+ Sub: MenuSub,
856
+ SubTrigger: MenuSubTrigger,
857
+ SubContent: MenuSubContent,
858
+ ItemTitle: MenuItemTitle,
859
+ ItemSubtitle: MenuItemSubTitle,
860
+ ItemImage: MenuItemImage,
861
+ ItemIcon: MenuItemIcon
862
+ })
863
+ };
864
+ }
865
+ function getOpenState(open) {
866
+ return open ? "open" : "closed";
867
+ }
868
+ function isIndeterminate(checked) {
869
+ return checked === "indeterminate";
870
+ }
871
+ function getCheckedState(checked) {
872
+ return isIndeterminate(checked) ? "indeterminate" : checked ? "checked" : "unchecked";
873
+ }
874
+ function focusFirst(candidates) {
875
+ const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
876
+ for (const candidate of candidates) if (candidate === PREVIOUSLY_FOCUSED_ELEMENT || (candidate.focus(), document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT)) return;
877
+ }
878
+ function wrapArray(array, startIndex) {
879
+ return array.map((_, index) => array[(startIndex + index) % array.length]);
880
+ }
881
+ function getNextMatch(values, search, currentMatch) {
882
+ const normalizedSearch = search.length > 1 && Array.from(search).every(char => char === search[0]) ? search[0] : search,
883
+ currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
884
+ let wrappedValues = wrapArray(values, Math.max(currentMatchIndex, 0));
885
+ normalizedSearch.length === 1 && (wrappedValues = wrappedValues.filter(v => v !== currentMatch));
886
+ const nextMatch = wrappedValues.find(value => value.toLowerCase().startsWith(normalizedSearch.toLowerCase()));
887
+ return nextMatch !== currentMatch ? nextMatch : void 0;
888
+ }
889
+ function isPointInPolygon(point, polygon) {
890
+ const {
891
+ x,
892
+ y
893
+ } = point;
894
+ let inside = !1;
895
+ for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
896
+ const xi = polygon[i].x,
897
+ yi = polygon[i].y,
898
+ xj = polygon[j].x,
899
+ yj = polygon[j].y;
900
+ yi > y != yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi && (inside = !inside);
901
+ }
902
+ return inside;
903
+ }
904
+ function isPointerInGraceArea(event, area) {
905
+ if (!area) return !1;
906
+ const cursorPos = {
907
+ x: event.clientX,
908
+ y: event.clientY
909
+ };
910
+ return isPointInPolygon(cursorPos, area);
911
+ }
912
+ function whenMouse(handler) {
913
+ return event => event.pointerType === "mouse" ? handler(event) : void 0;
914
+ }
915
+ export { NativePropProvider, createMenu, useNativeProp };
916
+ //# sourceMappingURL=createMenu.mjs.map