@tamagui/menu 2.7.7 → 3.0.0-beta.643.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/cjs/Menu.cjs +152 -174
  2. package/dist/cjs/Menu.native.cjs +181 -0
  3. package/dist/cjs/Menu.native.js +161 -182
  4. package/dist/cjs/Menu.native.js.map +1 -1
  5. package/dist/cjs/createNonNativeMenu.cjs +324 -369
  6. package/dist/cjs/createNonNativeMenu.native.cjs +375 -0
  7. package/dist/cjs/createNonNativeMenu.native.js +345 -387
  8. package/dist/cjs/createNonNativeMenu.native.js.map +1 -1
  9. package/dist/cjs/index.cjs +15 -29
  10. package/dist/cjs/index.native.cjs +29 -0
  11. package/dist/cjs/index.native.js +16 -29
  12. package/dist/cjs/index.native.js.map +1 -1
  13. package/dist/esm/Menu.mjs +136 -148
  14. package/dist/esm/Menu.mjs.map +1 -1
  15. package/dist/esm/Menu.native.js +146 -158
  16. package/dist/esm/Menu.native.js.map +1 -1
  17. package/dist/esm/createNonNativeMenu.mjs +308 -345
  18. package/dist/esm/createNonNativeMenu.mjs.map +1 -1
  19. package/dist/esm/createNonNativeMenu.native.js +330 -365
  20. package/dist/esm/createNonNativeMenu.native.js.map +1 -1
  21. package/dist/esm/index.js +3 -12
  22. package/dist/esm/index.js.map +1 -1
  23. package/dist/esm/index.mjs +3 -12
  24. package/dist/esm/index.mjs.map +1 -1
  25. package/dist/esm/index.native.js +3 -12
  26. package/dist/esm/index.native.js.map +1 -1
  27. package/dist/jsx/Menu.mjs +136 -148
  28. package/dist/jsx/Menu.mjs.map +1 -1
  29. package/dist/jsx/Menu.native.cjs +181 -0
  30. package/dist/jsx/Menu.native.js +161 -182
  31. package/dist/jsx/Menu.native.js.map +1 -1
  32. package/dist/jsx/createNonNativeMenu.mjs +308 -345
  33. package/dist/jsx/createNonNativeMenu.mjs.map +1 -1
  34. package/dist/jsx/createNonNativeMenu.native.cjs +375 -0
  35. package/dist/jsx/createNonNativeMenu.native.js +345 -387
  36. package/dist/jsx/createNonNativeMenu.native.js.map +1 -1
  37. package/dist/jsx/index.js +3 -12
  38. package/dist/jsx/index.js.map +1 -1
  39. package/dist/jsx/index.mjs +3 -12
  40. package/dist/jsx/index.mjs.map +1 -1
  41. package/dist/jsx/index.native.cjs +29 -0
  42. package/dist/jsx/index.native.js +16 -29
  43. package/dist/jsx/index.native.js.map +1 -1
  44. package/package.json +11 -10
  45. package/src/Menu.tsx +3 -7
  46. package/src/createNonNativeMenu.tsx +55 -49
  47. package/src/index.tsx +1 -13
  48. package/types/Menu.d.ts +127 -73
  49. package/types/Menu.d.ts.map +1 -1
  50. package/types/createNonNativeMenu.d.ts +111 -106
  51. package/types/createNonNativeMenu.d.ts.map +1 -1
  52. package/types/index.d.ts +126 -71
  53. package/types/index.d.ts.map +1 -1
@@ -1,358 +1,321 @@
1
+ import { createStyledHOC } from "@tamagui/core";
1
2
  import { createBaseMenu } from "@tamagui/create-menu";
2
3
  import { usePopperContextSlow } from "@tamagui/popper";
3
4
  import { ScrollView } from "@tamagui/scroll-view";
4
5
  import { useControllableState } from "@tamagui/use-controllable-state";
5
- import { composeEventHandlers, composeRefs, createStyledContext, isAndroid, isWeb, Slot, styled, useEvent, useIsTouchDevice, View, withStaticProperties } from "@tamagui/web";
6
+ import { Slot, View, composeEventHandlers, composeRefs, createStyledContext, isAndroid, isWeb, styled, useEvent, useIsTouchDevice, withStaticProperties } from "@tamagui/web";
6
7
  import * as React from "react";
7
8
  import { useId } from "react";
8
9
  import { jsx } from "react/jsx-runtime";
10
+
9
11
  const DROPDOWN_MENU_CONTEXT = "MenuContext";
10
12
  function useMenuTriggerSetup(open) {
11
- const triggerStateSettersRef = React.useRef(/* @__PURE__ */new Map());
12
- const activeTriggerIdRef = React.useRef(null);
13
- const setActiveTrigger = useEvent(id => {
14
- const prevId = activeTriggerIdRef.current;
15
- if (prevId === id) return;
16
- if (prevId) {
17
- triggerStateSettersRef.current.get(prevId)?.(false);
18
- }
19
- activeTriggerIdRef.current = id;
20
- if (id && open) {
21
- triggerStateSettersRef.current.get(id)?.(true);
22
- }
23
- });
24
- const registerTrigger = useEvent((id, setOpenState) => {
25
- triggerStateSettersRef.current.set(id, setOpenState);
26
- setOpenState(activeTriggerIdRef.current === id && open);
27
- });
28
- const unregisterTrigger = useEvent(id => {
29
- triggerStateSettersRef.current.delete(id);
30
- if (activeTriggerIdRef.current === id) {
31
- activeTriggerIdRef.current = null;
32
- }
33
- });
34
- React.useEffect(() => {
35
- if (!open) {
36
- setActiveTrigger(null);
37
- return;
38
- }
39
- const activeId = activeTriggerIdRef.current;
40
- if (activeId) {
41
- triggerStateSettersRef.current.get(activeId)?.(true);
42
- }
43
- }, [open, setActiveTrigger]);
44
- return {
45
- setActiveTrigger,
46
- registerTrigger,
47
- unregisterTrigger
48
- };
13
+ const triggerStateSettersRef = React.useRef(/* @__PURE__ */ new Map());
14
+ const activeTriggerIdRef = React.useRef(null);
15
+ const setActiveTrigger = useEvent((id) => {
16
+ const prevId = activeTriggerIdRef.current;
17
+ if (prevId === id) return;
18
+ if (prevId) {
19
+ triggerStateSettersRef.current.get(prevId)?.(false);
20
+ }
21
+ activeTriggerIdRef.current = id;
22
+ if (id && open) {
23
+ triggerStateSettersRef.current.get(id)?.(true);
24
+ }
25
+ });
26
+ const registerTrigger = useEvent((id, setOpenState) => {
27
+ triggerStateSettersRef.current.set(id, setOpenState);
28
+ setOpenState(activeTriggerIdRef.current === id && open);
29
+ });
30
+ const unregisterTrigger = useEvent((id) => {
31
+ triggerStateSettersRef.current.delete(id);
32
+ if (activeTriggerIdRef.current === id) {
33
+ activeTriggerIdRef.current = null;
34
+ }
35
+ });
36
+ React.useEffect(() => {
37
+ if (!open) {
38
+ setActiveTrigger(null);
39
+ return;
40
+ }
41
+ const activeId = activeTriggerIdRef.current;
42
+ if (activeId) {
43
+ triggerStateSettersRef.current.get(activeId)?.(true);
44
+ }
45
+ }, [open, setActiveTrigger]);
46
+ return {
47
+ setActiveTrigger,
48
+ registerTrigger,
49
+ unregisterTrigger
50
+ };
49
51
  }
50
- function createNonNativeMenu(params) {
51
- const {
52
- Menu
53
- } = createBaseMenu(params);
54
- const DROPDOWN_MENU_NAME = "Menu";
55
- const {
56
- Provider: MenuProvider,
57
- useStyledContext: useMenuContext
58
- } = createStyledContext();
59
- const MenuComp = props => {
60
- const {
61
- scope,
62
- children,
63
- dir,
64
- open: openProp,
65
- defaultOpen,
66
- onOpenChange,
67
- modal = true,
68
- ...rest
69
- } = props;
70
- const triggerRef = React.useRef(null);
71
- const [open = false, setOpen] = useControllableState({
72
- prop: openProp,
73
- defaultProp: defaultOpen,
74
- onChange: onOpenChange
75
- });
76
- const openRef = React.useRef(open);
77
- openRef.current = open;
78
- const {
79
- setActiveTrigger,
80
- registerTrigger,
81
- unregisterTrigger
82
- } = useMenuTriggerSetup(open);
83
- return /* @__PURE__ */jsx(MenuProvider, {
84
- scope,
85
- triggerId: useId(),
86
- triggerRef,
87
- contentId: useId(),
88
- openRef,
89
- onOpenChange: React.useCallback(nextOpen => setOpen(nextOpen), [setOpen]),
90
- onOpenToggle: React.useCallback(() => setOpen(prevOpen => !prevOpen), [setOpen]),
91
- modal,
92
- setActiveTrigger,
93
- registerTrigger,
94
- unregisterTrigger,
95
- children: /* @__PURE__ */jsx(Menu, {
96
- scope: scope || DROPDOWN_MENU_CONTEXT,
97
- open,
98
- onOpenChange: setOpen,
99
- dir,
100
- modal,
101
- ...rest,
102
- children
103
- })
104
- });
105
- };
106
- MenuComp.displayName = DROPDOWN_MENU_NAME;
107
- const TRIGGER_NAME = "MenuTrigger";
108
- const MenuTriggerFrame = Menu.Anchor;
109
- const MenuTrigger = View.styleable((props, forwardedRef) => {
110
- const {
111
- scope,
112
- asChild,
113
- children,
114
- disabled = false,
115
- onKeydown,
116
- ...triggerProps
117
- } = props;
118
- const context = useMenuContext(scope);
119
- const popperCtx = usePopperContextSlow(scope || DROPDOWN_MENU_CONTEXT);
120
- const Comp = asChild ? Slot : View;
121
- const isTouchDevice = useIsTouchDevice();
122
- const triggerElRef = React.useRef(null);
123
- const triggerId = React.useId();
124
- const [triggerOpen, setTriggerOpen] = React.useState(false);
125
- const {
126
- registerTrigger,
127
- unregisterTrigger
128
- } = context;
129
- React.useEffect(() => {
130
- registerTrigger(triggerId, setTriggerOpen);
131
- return () => unregisterTrigger(triggerId);
132
- }, [registerTrigger, unregisterTrigger, triggerId]);
133
- const activateSelf = React.useCallback(() => {
134
- context.setActiveTrigger(triggerId);
135
- const el = triggerElRef.current;
136
- if (el) {
137
- context.triggerRef.current = el;
138
- if (el instanceof HTMLElement) {
139
- popperCtx.refs?.setReference(el);
140
- requestAnimationFrame(() => popperCtx.update?.());
141
- }
142
- }
143
- }, [context, triggerId, popperCtx]);
144
- const pressEvent = isWeb ? isTouchDevice ? "onClick" : "onPointerDown" : "onPress";
145
- return /* @__PURE__ */jsx(MenuTriggerFrame, {
146
- asChild: true,
147
- componentName: TRIGGER_NAME,
148
- scope: scope || DROPDOWN_MENU_CONTEXT,
149
- children: /* @__PURE__ */jsx(Comp, {
150
- role: "button",
151
- id: context.triggerId,
152
- "aria-haspopup": "menu",
153
- "aria-expanded": triggerOpen,
154
- "aria-controls": triggerOpen ? context.contentId : void 0,
155
- "data-state": triggerOpen ? "open" : "closed",
156
- "data-disabled": disabled ? "" : void 0,
157
- "aria-disabled": disabled || void 0,
158
- ref: composeRefs(forwardedRef, context.triggerRef, triggerElRef),
159
- ...{
160
- [pressEvent]: composeEventHandlers(
161
- //@ts-ignore
162
- props[pressEvent], event => {
163
- if (!disabled) {
164
- if (isWeb && event instanceof PointerEvent && event.button !== 0 && event.ctrlKey === true) return;
165
- if (context.openRef.current) {
166
- context.setActiveTrigger(null);
167
- } else {
168
- activateSelf();
169
- }
170
- context.onOpenToggle();
171
- if (!context.openRef.current) event.preventDefault();
172
- }
173
- })
174
- },
175
- ...(isWeb && {
176
- onKeyDown: composeEventHandlers(onKeydown, event => {
177
- if (disabled) return;
178
- if (["Enter", " "].includes(event.key)) {
179
- if (context.openRef.current) {
180
- context.setActiveTrigger(null);
181
- } else {
182
- activateSelf();
183
- }
184
- context.onOpenToggle();
185
- }
186
- if (event.key === "ArrowDown") {
187
- activateSelf();
188
- context.onOpenChange(true);
189
- }
190
- if (["Enter", " ", "ArrowDown"].includes(event.key)) event.preventDefault();
191
- })
192
- }),
193
- ...triggerProps,
194
- children
195
- })
196
- });
197
- });
198
- MenuTrigger.displayName = TRIGGER_NAME;
199
- const PORTAL_NAME = "MenuPortal";
200
- const MenuPortal = props => {
201
- const {
202
- scope,
203
- children,
204
- ...portalProps
205
- } = props;
206
- const context = isAndroid ? useMenuContext(scope) : null;
207
- const content = isAndroid ? /* @__PURE__ */jsx(MenuProvider, {
208
- ...context,
209
- children
210
- }) : children;
211
- return /* @__PURE__ */jsx(Menu.Portal, {
212
- scope: scope || DROPDOWN_MENU_CONTEXT,
213
- ...portalProps,
214
- children: content
215
- });
216
- };
217
- MenuPortal.displayName = PORTAL_NAME;
218
- const CONTENT_NAME = "MenuContent";
219
- const MenuContent = React.forwardRef((props, forwardedRef) => {
220
- const {
221
- scope,
222
- ...contentProps
223
- } = props;
224
- const context = useMenuContext(scope);
225
- const hasInteractedOutsideRef = React.useRef(false);
226
- return /* @__PURE__ */jsx(Menu.Content, {
227
- id: context.contentId,
228
- "aria-labelledby": context.triggerId,
229
- scope: scope || DROPDOWN_MENU_CONTEXT,
230
- ...contentProps,
231
- ref: forwardedRef,
232
- onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, event => {
233
- if (!hasInteractedOutsideRef.current) {
234
- requestAnimationFrame(() => {
235
- const activeEl = document.activeElement;
236
- if (!activeEl || activeEl === document.body) {
237
- context.triggerRef.current?.focus();
238
- }
239
- });
240
- }
241
- hasInteractedOutsideRef.current = false;
242
- event.preventDefault();
243
- }),
244
- onInteractOutside: composeEventHandlers(props.onInteractOutside, event => {
245
- const originalEvent = event.detail.originalEvent;
246
- const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
247
- const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
248
- if (!context.modal || isRightClick) hasInteractedOutsideRef.current = true;
249
- }),
250
- style: isWeb ? {
251
- ...props.style,
252
- ...{
253
- "--tamagui-menu-content-transform-origin": "var(--tamagui-popper-transform-origin)",
254
- "--tamagui-menu-content-available-width": "var(--tamagui-popper-available-width)",
255
- "--tamagui-menu-content-available-height": "var(--tamagui-popper-available-height)",
256
- "--tamagui-menu-trigger-width": "var(--tamagui-popper-anchor-width)",
257
- "--tamagui-menu-trigger-height": "var(--tamagui-popper-anchor-height)"
258
- }
259
- } : props.style
260
- });
261
- });
262
- MenuContent.displayName = CONTENT_NAME;
263
- const DROPDOWN_MENU_SUB_NAME = "MenuSub";
264
- const MenuSub = props => {
265
- const {
266
- scope,
267
- children,
268
- open: openProp,
269
- onOpenChange,
270
- defaultOpen,
271
- ...rest
272
- } = props;
273
- const [open = false, setOpen] = useControllableState({
274
- prop: openProp,
275
- defaultProp: defaultOpen,
276
- onChange: onOpenChange
277
- });
278
- return /* @__PURE__ */jsx(Menu.Sub, {
279
- scope: scope || DROPDOWN_MENU_CONTEXT,
280
- open,
281
- onOpenChange: setOpen,
282
- ...rest,
283
- children
284
- });
285
- };
286
- MenuSub.displayName = DROPDOWN_MENU_SUB_NAME;
287
- const SUB_CONTENT_NAME = "MenuSubContent";
288
- const MenuSubContent = React.forwardRef((props, forwardedRef) => {
289
- const {
290
- scope,
291
- ...subContentProps
292
- } = props;
293
- return /* @__PURE__ */jsx(Menu.SubContent, {
294
- scope: scope || DROPDOWN_MENU_CONTEXT,
295
- ...subContentProps,
296
- ref: forwardedRef,
297
- style: isWeb ? {
298
- ...props.style,
299
- ...{
300
- "--tamagui-menu-content-transform-origin": "var(--tamagui-popper-transform-origin)",
301
- "--tamagui-menu-content-available-width": "var(--tamagui-popper-available-width)",
302
- "--tamagui-menu-content-available-height": "var(--tamagui-popper-available-height)",
303
- "--tamagui-menu-trigger-width": "var(--tamagui-popper-anchor-width)",
304
- "--tamagui-menu-trigger-height": "var(--tamagui-popper-anchor-height)"
305
- }
306
- } : null
307
- });
308
- });
309
- MenuSubContent.displayName = SUB_CONTENT_NAME;
310
- const MenuScrollView = styled(ScrollView, {
311
- flexShrink: 1,
312
- alignSelf: "stretch",
313
- showsHorizontalScrollIndicator: false,
314
- showsVerticalScrollIndicator: false,
315
- "$platform-web": {
316
- maxHeight: "var(--tamagui-menu-content-available-height)"
317
- }
318
- });
319
- const Group = Menu.Group;
320
- const Label = Menu.Label;
321
- const Item = Menu.Item;
322
- const CheckboxItem = Menu.CheckboxItem;
323
- const RadioGroup = Menu.RadioGroup;
324
- const RadioItem = Menu.RadioItem;
325
- const ItemIndicator = Menu.ItemIndicator;
326
- const Separator = Menu.Separator;
327
- const Arrow = Menu.Arrow;
328
- const SubTrigger = Menu.SubTrigger;
329
- const ItemTitle = Menu.ItemTitle;
330
- const ItemSubtitle = Menu.ItemSubtitle;
331
- const ItemImage = Menu.ItemImage;
332
- const ItemIcon = Menu.ItemIcon;
333
- return withStaticProperties(MenuComp, {
334
- Root: MenuComp,
335
- Trigger: MenuTrigger,
336
- Portal: MenuPortal,
337
- Content: MenuContent,
338
- Group,
339
- Label,
340
- Item,
341
- CheckboxItem,
342
- RadioGroup,
343
- RadioItem,
344
- ItemIndicator,
345
- Separator,
346
- Arrow,
347
- Sub: MenuSub,
348
- SubTrigger,
349
- SubContent: MenuSubContent,
350
- ItemTitle,
351
- ItemSubtitle,
352
- ItemImage,
353
- ItemIcon,
354
- ScrollView: MenuScrollView
355
- });
52
+ function createNonNativeMenu() {
53
+ const { Menu } = createBaseMenu();
54
+ const DROPDOWN_MENU_NAME = "Menu";
55
+ const { Provider: MenuProvider, useStyledContext: useMenuContext } = createStyledContext();
56
+ const MenuComp = (props) => {
57
+ const { scope, children, dir, open: openProp, defaultOpen, onOpenChange, modal = true, ...rest } = props;
58
+ const triggerRef = React.useRef(null);
59
+ const [open = false, setOpen] = useControllableState({
60
+ prop: openProp,
61
+ defaultProp: defaultOpen,
62
+ onChange: onOpenChange
63
+ });
64
+ const openRef = React.useRef(open);
65
+ openRef.current = open;
66
+ const { setActiveTrigger, registerTrigger, unregisterTrigger } = useMenuTriggerSetup(open);
67
+ return /* @__PURE__ */ jsx(MenuProvider, {
68
+ scope,
69
+ triggerId: useId(),
70
+ triggerRef,
71
+ contentId: useId(),
72
+ openRef,
73
+ onOpenChange: React.useCallback((nextOpen) => setOpen(nextOpen), [setOpen]),
74
+ onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
75
+ modal,
76
+ setActiveTrigger,
77
+ registerTrigger,
78
+ unregisterTrigger,
79
+ children: /* @__PURE__ */ jsx(Menu, {
80
+ scope: scope || "MenuContext",
81
+ open,
82
+ onOpenChange: setOpen,
83
+ dir,
84
+ modal,
85
+ ...rest,
86
+ children
87
+ })
88
+ });
89
+ };
90
+ MenuComp.displayName = DROPDOWN_MENU_NAME;
91
+ const TRIGGER_NAME = "MenuTrigger";
92
+ const MenuTriggerFrame = Menu.Anchor;
93
+ const MenuTrigger = createStyledHOC(View, (props, forwardedRef) => {
94
+ const { scope, asChild, children, disabled = false, onKeydown, onKeyDown = onKeydown, ...triggerProps } = props;
95
+ const context = useMenuContext(scope);
96
+ const popperCtx = usePopperContextSlow(scope || "MenuContext");
97
+ const Comp = asChild ? Slot : View;
98
+ const isTouchDevice = useIsTouchDevice();
99
+ const triggerElRef = React.useRef(null);
100
+ const triggerId = React.useId();
101
+ const [triggerOpen, setTriggerOpen] = React.useState(false);
102
+ const { registerTrigger, unregisterTrigger } = context;
103
+ React.useEffect(() => {
104
+ registerTrigger(triggerId, setTriggerOpen);
105
+ return () => unregisterTrigger(triggerId);
106
+ }, [
107
+ registerTrigger,
108
+ unregisterTrigger,
109
+ triggerId
110
+ ]);
111
+ const activateSelf = React.useCallback(() => {
112
+ context.setActiveTrigger(triggerId);
113
+ const el = triggerElRef.current;
114
+ if (el) {
115
+ context.triggerRef.current = el;
116
+ if (el instanceof HTMLElement) {
117
+ popperCtx.refs?.setReference(el);
118
+ requestAnimationFrame(() => popperCtx.update?.());
119
+ }
120
+ }
121
+ }, [
122
+ context,
123
+ triggerId,
124
+ popperCtx
125
+ ]);
126
+ const pressEvent = isWeb ? isTouchDevice ? "onClick" : "onPointerDown" : "onPress";
127
+ return /* @__PURE__ */ jsx(MenuTriggerFrame, {
128
+ asChild: true,
129
+ className: `is_${TRIGGER_NAME}`,
130
+ scope: scope || "MenuContext",
131
+ children: /* @__PURE__ */ jsx(Comp, {
132
+ role: "button",
133
+ id: context.triggerId,
134
+ "aria-haspopup": "menu",
135
+ "aria-expanded": triggerOpen,
136
+ "aria-controls": triggerOpen ? context.contentId : void 0,
137
+ "data-state": triggerOpen ? "open" : "closed",
138
+ "data-disabled": disabled ? "" : void 0,
139
+ "aria-disabled": disabled || void 0,
140
+ ref: composeRefs(forwardedRef, context.triggerRef, triggerElRef),
141
+ ...triggerProps,
142
+ ...{ [pressEvent]: composeEventHandlers(props[pressEvent], (event) => {
143
+ if (!disabled) {
144
+ if (isWeb && event instanceof PointerEvent && event.button !== 0 && event.ctrlKey === true) return;
145
+ if (context.openRef.current) {
146
+ context.setActiveTrigger(null);
147
+ } else {
148
+ activateSelf();
149
+ }
150
+ context.onOpenToggle();
151
+ if (!context.openRef.current) event.preventDefault();
152
+ }
153
+ }) },
154
+ ...isWeb && { onKeyDown: composeEventHandlers(onKeyDown, (event) => {
155
+ if (disabled) return;
156
+ if (["Enter", " "].includes(event.key)) {
157
+ if (context.openRef.current) {
158
+ context.setActiveTrigger(null);
159
+ } else {
160
+ activateSelf();
161
+ }
162
+ context.onOpenToggle();
163
+ }
164
+ if (event.key === "ArrowDown") {
165
+ activateSelf();
166
+ context.onOpenChange(true);
167
+ }
168
+ if ([
169
+ "Enter",
170
+ " ",
171
+ "ArrowDown"
172
+ ].includes(event.key)) event.preventDefault();
173
+ }) },
174
+ children
175
+ })
176
+ });
177
+ });
178
+ MenuTrigger.displayName = TRIGGER_NAME;
179
+ const PORTAL_NAME = "MenuPortal";
180
+ const MenuPortal = (props) => {
181
+ const { scope, children, ...portalProps } = props;
182
+ const context = isAndroid ? useMenuContext(scope) : null;
183
+ const content = isAndroid ? /* @__PURE__ */ jsx(MenuProvider, {
184
+ ...context,
185
+ children
186
+ }) : children;
187
+ return /* @__PURE__ */ jsx(Menu.Portal, {
188
+ scope: scope || "MenuContext",
189
+ ...portalProps,
190
+ children: content
191
+ });
192
+ };
193
+ MenuPortal.displayName = PORTAL_NAME;
194
+ const CONTENT_NAME = "MenuContent";
195
+ const MenuContent = createStyledHOC(Menu.Content, (props, forwardedRef) => {
196
+ const { scope, ...contentProps } = props;
197
+ const context = useMenuContext(scope);
198
+ const hasInteractedOutsideRef = React.useRef(false);
199
+ return /* @__PURE__ */ jsx(Menu.Content, {
200
+ id: context.contentId,
201
+ "aria-labelledby": context.triggerId,
202
+ scope: scope || "MenuContext",
203
+ ...contentProps,
204
+ ref: forwardedRef,
205
+ onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {
206
+ if (!hasInteractedOutsideRef.current) {
207
+ requestAnimationFrame(() => {
208
+ const activeEl = document.activeElement;
209
+ if (!activeEl || activeEl === document.body) {
210
+ context.triggerRef.current?.focus();
211
+ }
212
+ });
213
+ }
214
+ hasInteractedOutsideRef.current = false;
215
+ event.cancel();
216
+ }),
217
+ onInteractOutside: composeEventHandlers(props.onInteractOutside, (event) => {
218
+ if (event.interaction !== "pointer" || !event.event) return;
219
+ const originalEvent = event.event;
220
+ const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
221
+ const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
222
+ if (!context.modal || isRightClick) hasInteractedOutsideRef.current = true;
223
+ }),
224
+ style: isWeb ? {
225
+ ...props.style,
226
+ ...{
227
+ "--tamagui-menu-content-transform-origin": "var(--tamagui-popper-transform-origin)",
228
+ "--tamagui-menu-content-available-width": "var(--tamagui-popper-available-width)",
229
+ "--tamagui-menu-content-available-height": "var(--tamagui-popper-available-height)",
230
+ "--tamagui-menu-trigger-width": "var(--tamagui-popper-anchor-width)",
231
+ "--tamagui-menu-trigger-height": "var(--tamagui-popper-anchor-height)"
232
+ }
233
+ } : props.style
234
+ });
235
+ });
236
+ MenuContent.displayName = CONTENT_NAME;
237
+ const DROPDOWN_MENU_SUB_NAME = "MenuSub";
238
+ const MenuSub = (props) => {
239
+ const { scope, children, open: openProp, onOpenChange, defaultOpen, ...rest } = props;
240
+ const [open = false, setOpen] = useControllableState({
241
+ prop: openProp,
242
+ defaultProp: defaultOpen,
243
+ onChange: onOpenChange
244
+ });
245
+ return /* @__PURE__ */ jsx(Menu.Sub, {
246
+ scope: scope || "MenuContext",
247
+ open,
248
+ onOpenChange: setOpen,
249
+ ...rest,
250
+ children
251
+ });
252
+ };
253
+ MenuSub.displayName = DROPDOWN_MENU_SUB_NAME;
254
+ const SUB_CONTENT_NAME = "MenuSubContent";
255
+ const MenuSubContent = createStyledHOC(Menu.SubContent, (props, forwardedRef) => {
256
+ const { scope, ...subContentProps } = props;
257
+ return /* @__PURE__ */ jsx(Menu.SubContent, {
258
+ scope: scope || "MenuContext",
259
+ ...subContentProps,
260
+ ref: forwardedRef,
261
+ style: isWeb ? {
262
+ ...props.style,
263
+ ...{
264
+ "--tamagui-menu-content-transform-origin": "var(--tamagui-popper-transform-origin)",
265
+ "--tamagui-menu-content-available-width": "var(--tamagui-popper-available-width)",
266
+ "--tamagui-menu-content-available-height": "var(--tamagui-popper-available-height)",
267
+ "--tamagui-menu-trigger-width": "var(--tamagui-popper-anchor-width)",
268
+ "--tamagui-menu-trigger-height": "var(--tamagui-popper-anchor-height)"
269
+ }
270
+ } : null
271
+ });
272
+ });
273
+ MenuSubContent.displayName = SUB_CONTENT_NAME;
274
+ const MenuScrollView = styled(ScrollView, {
275
+ flexShrink: 1,
276
+ alignSelf: "stretch",
277
+ maxHeight: "web:var(--tamagui-menu-content-available-height)",
278
+ showsHorizontalScrollIndicator: false,
279
+ showsVerticalScrollIndicator: false
280
+ });
281
+ const Group = Menu.Group;
282
+ const Label = Menu.Label;
283
+ const Item = Menu.Item;
284
+ const CheckboxItem = Menu.CheckboxItem;
285
+ const RadioGroup = Menu.RadioGroup;
286
+ const RadioItem = Menu.RadioItem;
287
+ const ItemIndicator = Menu.ItemIndicator;
288
+ const Separator = Menu.Separator;
289
+ const Arrow = Menu.Arrow;
290
+ const SubTrigger = Menu.SubTrigger;
291
+ const ItemTitle = Menu.ItemTitle;
292
+ const ItemSubtitle = Menu.ItemSubtitle;
293
+ const ItemImage = Menu.ItemImage;
294
+ const ItemIcon = Menu.ItemIcon;
295
+ return withStaticProperties(MenuComp, {
296
+ Root: MenuComp,
297
+ Trigger: MenuTrigger,
298
+ Portal: MenuPortal,
299
+ Content: MenuContent,
300
+ Group,
301
+ Label,
302
+ Item,
303
+ CheckboxItem,
304
+ RadioGroup,
305
+ RadioItem,
306
+ ItemIndicator,
307
+ Separator,
308
+ Arrow,
309
+ Sub: MenuSub,
310
+ SubTrigger,
311
+ SubContent: MenuSubContent,
312
+ ItemTitle,
313
+ ItemSubtitle,
314
+ ItemImage,
315
+ ItemIcon,
316
+ ScrollView: MenuScrollView
317
+ });
356
318
  }
319
+
357
320
  export { DROPDOWN_MENU_CONTEXT, createNonNativeMenu };
358
321
  //# sourceMappingURL=createNonNativeMenu.mjs.map