@tamagui/create-menu 2.0.0-rc.9 → 2.0.0

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