@tamagui/create-menu 2.0.0-rc.4 → 2.0.0-rc.40

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