@tamagui/create-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 (113) hide show
  1. package/dist/cjs/createBaseMenu.cjs +1033 -1247
  2. package/dist/cjs/createBaseMenu.native.cjs +1217 -0
  3. package/dist/cjs/createBaseMenu.native.js +1155 -1387
  4. package/dist/cjs/createBaseMenu.native.js.map +1 -1
  5. package/dist/cjs/createNativeMenu/createNativeMenu.cjs +346 -377
  6. package/dist/cjs/createNativeMenu/createNativeMenu.native.cjs +439 -0
  7. package/dist/cjs/createNativeMenu/createNativeMenu.native.js +405 -439
  8. package/dist/cjs/createNativeMenu/createNativeMenu.native.js.map +1 -1
  9. package/dist/cjs/createNativeMenu/createNativeMenuTypes.cjs +10 -11
  10. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.cjs +19 -0
  11. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js +10 -10
  12. package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js.map +1 -1
  13. package/dist/cjs/createNativeMenu/utils.cjs +76 -86
  14. package/dist/cjs/createNativeMenu/utils.native.cjs +107 -0
  15. package/dist/cjs/createNativeMenu/utils.native.js +82 -92
  16. package/dist/cjs/createNativeMenu/utils.native.js.map +1 -1
  17. package/dist/cjs/createNativeMenu/withNativeMenu.cjs +27 -35
  18. package/dist/cjs/createNativeMenu/withNativeMenu.native.cjs +42 -0
  19. package/dist/cjs/createNativeMenu/withNativeMenu.native.js +27 -34
  20. package/dist/cjs/createNativeMenu/withNativeMenu.native.js.map +1 -1
  21. package/dist/cjs/index.cjs +9 -20
  22. package/dist/cjs/index.native.cjs +23 -0
  23. package/dist/cjs/index.native.js +10 -20
  24. package/dist/cjs/index.native.js.map +1 -1
  25. package/dist/esm/createBaseMenu.mjs +1021 -1225
  26. package/dist/esm/createBaseMenu.mjs.map +1 -1
  27. package/dist/esm/createBaseMenu.native.js +1144 -1367
  28. package/dist/esm/createBaseMenu.native.js.map +1 -1
  29. package/dist/esm/createNativeMenu/createNativeMenu.mjs +332 -353
  30. package/dist/esm/createNativeMenu/createNativeMenu.mjs.map +1 -1
  31. package/dist/esm/createNativeMenu/createNativeMenu.native.js +392 -417
  32. package/dist/esm/createNativeMenu/createNativeMenu.native.js.map +1 -1
  33. package/dist/esm/createNativeMenu/createNativeMenuTypes.mjs +0 -2
  34. package/dist/esm/createNativeMenu/createNativeMenuTypes.native.js +0 -2
  35. package/dist/esm/createNativeMenu/utils.mjs +55 -57
  36. package/dist/esm/createNativeMenu/utils.mjs.map +1 -1
  37. package/dist/esm/createNativeMenu/utils.native.js +62 -65
  38. package/dist/esm/createNativeMenu/utils.native.js.map +1 -1
  39. package/dist/esm/createNativeMenu/withNativeMenu.mjs +14 -17
  40. package/dist/esm/createNativeMenu/withNativeMenu.mjs.map +1 -1
  41. package/dist/esm/createNativeMenu/withNativeMenu.native.js +15 -18
  42. package/dist/esm/createNativeMenu/withNativeMenu.native.js.map +1 -1
  43. package/dist/esm/index.js +5 -6
  44. package/dist/esm/index.mjs +5 -6
  45. package/dist/esm/index.native.js +5 -6
  46. package/dist/jsx/createBaseMenu.mjs +1021 -1225
  47. package/dist/jsx/createBaseMenu.mjs.map +1 -1
  48. package/dist/jsx/createBaseMenu.native.cjs +1217 -0
  49. package/dist/jsx/createBaseMenu.native.js +1155 -1387
  50. package/dist/jsx/createBaseMenu.native.js.map +1 -1
  51. package/dist/jsx/createNativeMenu/createNativeMenu.mjs +332 -353
  52. package/dist/jsx/createNativeMenu/createNativeMenu.mjs.map +1 -1
  53. package/dist/jsx/createNativeMenu/createNativeMenu.native.cjs +439 -0
  54. package/dist/jsx/createNativeMenu/createNativeMenu.native.js +405 -439
  55. package/dist/jsx/createNativeMenu/createNativeMenu.native.js.map +1 -1
  56. package/dist/jsx/createNativeMenu/createNativeMenuTypes.mjs +0 -2
  57. package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.cjs +19 -0
  58. package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js +10 -10
  59. package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js.map +1 -1
  60. package/dist/jsx/createNativeMenu/utils.mjs +55 -57
  61. package/dist/jsx/createNativeMenu/utils.mjs.map +1 -1
  62. package/dist/jsx/createNativeMenu/utils.native.cjs +107 -0
  63. package/dist/jsx/createNativeMenu/utils.native.js +82 -92
  64. package/dist/jsx/createNativeMenu/utils.native.js.map +1 -1
  65. package/dist/jsx/createNativeMenu/withNativeMenu.mjs +14 -17
  66. package/dist/jsx/createNativeMenu/withNativeMenu.mjs.map +1 -1
  67. package/dist/jsx/createNativeMenu/withNativeMenu.native.cjs +42 -0
  68. package/dist/jsx/createNativeMenu/withNativeMenu.native.js +27 -34
  69. package/dist/jsx/createNativeMenu/withNativeMenu.native.js.map +1 -1
  70. package/dist/jsx/index.js +5 -6
  71. package/dist/jsx/index.mjs +5 -6
  72. package/dist/jsx/index.native.cjs +23 -0
  73. package/dist/jsx/index.native.js +10 -20
  74. package/dist/jsx/index.native.js.map +1 -1
  75. package/package.json +23 -22
  76. package/src/createBaseMenu.tsx +211 -231
  77. package/src/createNativeMenu/createNativeMenuTypes.ts +0 -6
  78. package/src/createNativeMenu/utils.tsx +6 -6
  79. package/src/createNativeMenu/withNativeMenu.tsx +1 -2
  80. package/src/index.tsx +0 -1
  81. package/types/createBaseMenu.d.ts +38 -126
  82. package/types/createBaseMenu.d.ts.map +1 -1
  83. package/types/createNativeMenu/createNativeMenu.d.ts +1 -1
  84. package/types/createNativeMenu/createNativeMenu.d.ts.map +1 -1
  85. package/types/createNativeMenu/createNativeMenuTypes.d.ts +0 -6
  86. package/types/createNativeMenu/createNativeMenuTypes.d.ts.map +1 -1
  87. package/types/createNativeMenu/utils.d.ts +5 -5
  88. package/types/createNativeMenu/utils.d.ts.map +1 -1
  89. package/types/createNativeMenu/withNativeMenu.d.ts.map +1 -1
  90. package/types/index.d.ts +0 -1
  91. package/types/index.d.ts.map +1 -1
  92. package/dist/cjs/MenuPredefined.cjs +0 -191
  93. package/dist/cjs/MenuPredefined.native.js +0 -194
  94. package/dist/cjs/MenuPredefined.native.js.map +0 -1
  95. package/dist/esm/MenuPredefined.mjs +0 -166
  96. package/dist/esm/MenuPredefined.mjs.map +0 -1
  97. package/dist/esm/MenuPredefined.native.js +0 -166
  98. package/dist/esm/MenuPredefined.native.js.map +0 -1
  99. package/dist/esm/createNativeMenu/createNativeMenuTypes.mjs.map +0 -1
  100. package/dist/esm/createNativeMenu/createNativeMenuTypes.native.js.map +0 -1
  101. package/dist/esm/index.js.map +0 -1
  102. package/dist/esm/index.mjs.map +0 -1
  103. package/dist/esm/index.native.js.map +0 -1
  104. package/dist/jsx/MenuPredefined.mjs +0 -166
  105. package/dist/jsx/MenuPredefined.mjs.map +0 -1
  106. package/dist/jsx/MenuPredefined.native.js +0 -194
  107. package/dist/jsx/MenuPredefined.native.js.map +0 -1
  108. package/dist/jsx/createNativeMenu/createNativeMenuTypes.mjs.map +0 -1
  109. package/dist/jsx/index.js.map +0 -1
  110. package/dist/jsx/index.mjs.map +0 -1
  111. package/src/MenuPredefined.tsx +0 -204
  112. package/types/MenuPredefined.d.ts +0 -31
  113. package/types/MenuPredefined.d.ts.map +0 -1
@@ -1,372 +1,351 @@
1
- import { getNativeMenuAdapter, NativeMenuContext, unstable_claimExternalPressOwnership, unstable_releaseExternalPressOwnership } from "@tamagui/native";
2
- import { isWeb, withStaticProperties, isIos } from "@tamagui/web";
1
+ import { NativeMenuContext, getNativeMenuAdapter, unstable_claimExternalPressOwnership, unstable_releaseExternalPressOwnership } from "@tamagui/native";
2
+ import { isIos, isWeb, withStaticProperties } from "@tamagui/web";
3
3
  import React from "react";
4
4
  import { Fragment, jsx } from "react/jsx-runtime";
5
- const MAPPED_TYPES = ["SubContent", "SubTrigger", "Content", "Sub", "Group", "Item", "ItemTitle", "ItemSubtitle", "ItemIcon", "ItemImage", "ItemIndicator", "Label", "Separator", "CheckboxItem", "Preview", "Auxiliary"];
6
- const CONTAINER_TYPES = ["SubContent", "SubTrigger", "Content", "Sub", "Group", "Item"];
5
+
6
+ const MAPPED_TYPES = [
7
+ "SubContent",
8
+ "SubTrigger",
9
+ "Content",
10
+ "Sub",
11
+ "Group",
12
+ "Item",
13
+ "ItemTitle",
14
+ "ItemSubtitle",
15
+ "ItemIcon",
16
+ "ItemImage",
17
+ "ItemIndicator",
18
+ "Label",
19
+ "Separator",
20
+ "CheckboxItem",
21
+ "Preview",
22
+ "Auxiliary"
23
+ ];
24
+ const CONTAINER_TYPES = [
25
+ "SubContent",
26
+ "SubTrigger",
27
+ "Content",
28
+ "Sub",
29
+ "Group",
30
+ "Item"
31
+ ];
7
32
  function getComponentType(displayName) {
8
- for (const type of MAPPED_TYPES) {
9
- if (displayName === type || displayName === `Menu${type}` || displayName === `ContextMenu${type}` || displayName.includes(`(${type})`)) {
10
- return type;
11
- }
12
- }
13
- return null;
33
+ for (const type of MAPPED_TYPES) {
34
+ if (displayName === type || displayName === `Menu${type}` || displayName === `ContextMenu${type}` || displayName.includes(`(${type})`)) {
35
+ return type;
36
+ }
37
+ }
38
+ return null;
14
39
  }
15
40
  function isItemLike(props, displayName) {
16
- if (getComponentType(displayName)) return false;
17
- return "onSelect" in props || "textValue" in props;
41
+ if (getComponentType(displayName)) return false;
42
+ return "onSelect" in props || "textValue" in props;
18
43
  }
19
44
  function isPortalLike(displayName) {
20
- return displayName === "Portal" || displayName.includes("Portal");
45
+ return displayName === "Portal" || displayName.includes("Portal");
21
46
  }
22
47
  function isTriggerLike(displayName) {
23
- return displayName === "Trigger" || displayName.includes("(Trigger)");
48
+ return displayName === "Trigger" || displayName.includes("(Trigger)");
24
49
  }
25
50
  function composeHandlers(first, second) {
26
- return (...args) => {
27
- first?.(...args);
28
- second?.(...args);
29
- };
51
+ return (...args) => {
52
+ first?.(...args);
53
+ second?.(...args);
54
+ };
30
55
  }
31
56
  function getTriggerDebugName(menuType, props) {
32
- const childProps = React.isValidElement(props.children) && props.children.props ? props.children.props : null;
33
- const prefix = menuType === "ContextMenu" ? "ContextMenuTrigger" : "MenuTrigger";
34
- const detail = childProps?.testID ?? childProps?.accessibilityLabel ?? (typeof props.textValue === "string" ? props.textValue : null);
35
- return [prefix, detail].filter(Boolean).join(":") || prefix;
57
+ const childProps = React.isValidElement(props.children) && props.children.props ? props.children.props : null;
58
+ const prefix = menuType === "ContextMenu" ? "ContextMenuTrigger" : "MenuTrigger";
59
+ const detail = childProps?.testID ?? childProps?.accessibilityLabel ?? (typeof props.textValue === "string" ? props.textValue : null);
60
+ return [prefix, detail].filter(Boolean).join(":") || prefix;
36
61
  }
37
- const emptyStub = () => null;
62
+ const emptyStub = (() => null);
38
63
  function createWebStubs() {
39
- return {
40
- Menu: withStaticProperties(emptyStub, {
41
- Trigger: emptyStub,
42
- Content: emptyStub,
43
- Item: emptyStub,
44
- ItemTitle: emptyStub,
45
- ItemSubtitle: emptyStub,
46
- SubTrigger: emptyStub,
47
- Group: emptyStub,
48
- ItemIcon: emptyStub,
49
- Separator: emptyStub,
50
- CheckboxItem: emptyStub,
51
- ItemIndicator: emptyStub,
52
- ItemImage: emptyStub,
53
- Label: emptyStub,
54
- Arrow: emptyStub,
55
- Sub: emptyStub,
56
- SubContent: emptyStub,
57
- Preview: emptyStub,
58
- Portal: emptyStub,
59
- RadioGroup: emptyStub,
60
- RadioItem: emptyStub,
61
- Auxiliary: emptyStub
62
- })
63
- };
64
+ return { Menu: withStaticProperties(emptyStub, {
65
+ Trigger: emptyStub,
66
+ Content: emptyStub,
67
+ Item: emptyStub,
68
+ ItemTitle: emptyStub,
69
+ ItemSubtitle: emptyStub,
70
+ SubTrigger: emptyStub,
71
+ Group: emptyStub,
72
+ ItemIcon: emptyStub,
73
+ Separator: emptyStub,
74
+ CheckboxItem: emptyStub,
75
+ ItemIndicator: emptyStub,
76
+ ItemImage: emptyStub,
77
+ Label: emptyStub,
78
+ Arrow: emptyStub,
79
+ Sub: emptyStub,
80
+ SubContent: emptyStub,
81
+ Preview: emptyStub,
82
+ Portal: emptyStub,
83
+ RadioGroup: emptyStub,
84
+ RadioItem: emptyStub,
85
+ Auxiliary: emptyStub
86
+ }) };
64
87
  }
65
- const createNativeMenu = MenuType => {
66
- if (isWeb) {
67
- return createWebStubs();
68
- }
69
- const isContextMenu = MenuType === "ContextMenu";
70
- const isAndroid = !isIos && !isWeb;
71
- let resolved = null;
72
- let warned = false;
73
- function resolve() {
74
- if (resolved) return resolved;
75
- const adapter = getNativeMenuAdapter();
76
- if (!adapter) {
77
- if (!warned) {
78
- warned = true;
79
- console.warn(`Warning: Register a native menu adapter before rendering Tamagui native menus`);
80
- }
81
- return null;
82
- }
83
- const menu = isContextMenu ? adapter.ContextMenu : adapter.Menu;
84
- resolved = {
85
- menu,
86
- componentMap: {
87
- SubContent: menu.SubContent,
88
- SubTrigger: menu.SubTrigger,
89
- Content: menu.Content,
90
- Sub: menu.Sub,
91
- Group: menu.Group,
92
- Item: menu.Item,
93
- ItemTitle: menu.ItemTitle,
94
- ItemSubtitle: menu.ItemSubtitle,
95
- ItemIcon: menu.ItemIcon,
96
- ItemImage: menu.ItemImage,
97
- ItemIndicator: menu.ItemIndicator,
98
- Label: menu.Label,
99
- Separator: menu.Separator,
100
- CheckboxItem: menu.CheckboxItem,
101
- Preview: menu.Preview,
102
- Auxiliary: menu.Auxiliary
103
- }
104
- };
105
- return resolved;
106
- }
107
- function transformChildren(menu, map, children, shouldReverseOnIos = false, triggerBoundaryHandlers, radioContext) {
108
- const result = [];
109
- React.Children.forEach(children, child => {
110
- if (!React.isValidElement(child)) {
111
- result.push(child);
112
- return;
113
- }
114
- const displayName = child.type?.displayName || "";
115
- const props = child.props;
116
- if (isPortalLike(displayName)) {
117
- const inner = transformChildren(menu, map, props.children, false, triggerBoundaryHandlers, radioContext);
118
- React.Children.forEach(inner, c => result.push(c));
119
- return;
120
- }
121
- if (displayName.includes("ScrollView")) {
122
- const inner = transformChildren(menu, map, props.children, false, triggerBoundaryHandlers, radioContext);
123
- React.Children.forEach(inner, c => result.push(c));
124
- return;
125
- }
126
- if (isTriggerLike(displayName)) {
127
- const debugName = getTriggerDebugName(MenuType, props);
128
- const claim = () => triggerBoundaryHandlers?.claim(debugName);
129
- const release = () => triggerBoundaryHandlers?.release(debugName);
130
- const {
131
- children: triggerChildren,
132
- ...triggerProps
133
- } = props;
134
- result.push(React.createElement(menu.Trigger, {
135
- ...triggerProps,
136
- key: child.key,
137
- onTouchStart: composeHandlers(claim, props.onTouchStart),
138
- onTouchEnd: composeHandlers(props.onTouchEnd, release),
139
- onTouchCancel: composeHandlers(props.onTouchCancel, release),
140
- onResponderGrant: composeHandlers(claim, props.onResponderGrant),
141
- onResponderRelease: composeHandlers(props.onResponderRelease, release),
142
- onResponderTerminate: composeHandlers(props.onResponderTerminate, release),
143
- onPressIn: composeHandlers(claim, props.onPressIn),
144
- onPressOut: composeHandlers(props.onPressOut, release)
145
- }, triggerChildren));
146
- return;
147
- }
148
- if (displayName.includes("RadioGroup")) {
149
- const {
150
- value: rgValue,
151
- onValueChange: rgOnValueChange,
152
- children: rgChildren,
153
- ...rest
154
- } = props;
155
- result.push(React.createElement(menu.Group, {
156
- ...rest,
157
- key: child.key
158
- }, transformChildren(menu, map, rgChildren, false, triggerBoundaryHandlers, {
159
- value: rgValue,
160
- onValueChange: rgOnValueChange
161
- })));
162
- return;
163
- }
164
- if (displayName.includes("RadioItem") && radioContext) {
165
- const {
166
- value: itemValue,
167
- children: rChildren,
168
- ...rest
169
- } = props;
170
- const cleanChildren = React.Children.map(rChildren, c => {
171
- if (!React.isValidElement(c)) return c;
172
- const dn = c.type?.displayName || "";
173
- if (dn.includes("ItemIndicator")) return null;
174
- return c;
175
- });
176
- result.push(React.createElement(menu.CheckboxItem, {
177
- ...rest,
178
- key: child.key,
179
- value: itemValue === radioContext.value ? "on" : "off",
180
- onValueChange: () => radioContext.onValueChange?.(itemValue)
181
- }, transformChildren(menu, map, cleanChildren, false, triggerBoundaryHandlers, radioContext)));
182
- return;
183
- }
184
- const componentType = getComponentType(displayName);
185
- if (componentType === "CheckboxItem") {
186
- const {
187
- checked,
188
- onCheckedChange,
189
- value,
190
- onValueChange,
191
- children: cbChildren,
192
- ...rest
193
- } = props;
194
- const finalValue = value ?? (checked ? "on" : "off");
195
- const finalOnValueChange = onValueChange ?? (onCheckedChange && (v => onCheckedChange(v === "on")));
196
- const cleanChildren = React.Children.map(cbChildren, c => {
197
- if (!React.isValidElement(c)) return c;
198
- const dn = c.type?.displayName || "";
199
- if (dn.includes("ItemIndicator")) return null;
200
- return c;
201
- });
202
- result.push(React.createElement(menu.CheckboxItem, {
203
- ...rest,
204
- key: child.key,
205
- value: finalValue,
206
- onValueChange: finalOnValueChange
207
- }, transformChildren(menu, map, cleanChildren, false, triggerBoundaryHandlers, radioContext)));
208
- return;
209
- }
210
- if (componentType) {
211
- const {
212
- children: childChildren,
213
- ...restProps
214
- } = props;
215
- const AdapterComponent = map[componentType];
216
- const isContainer = CONTAINER_TYPES.includes(componentType);
217
- const shouldReverse = componentType === "Content" || componentType === "SubContent";
218
- result.push(React.createElement(AdapterComponent, {
219
- ...restProps,
220
- key: child.key
221
- }, isContainer ? transformChildren(menu, map, childChildren, shouldReverse, triggerBoundaryHandlers, radioContext) : childChildren));
222
- return;
223
- }
224
- if (isItemLike(props, displayName)) {
225
- const {
226
- children: itemChildren,
227
- ...itemProps
228
- } = props;
229
- result.push(React.createElement(menu.Item, {
230
- ...itemProps,
231
- key: child.key
232
- }, transformChildren(menu, map, itemChildren, false, triggerBoundaryHandlers, radioContext)));
233
- return;
234
- }
235
- result.push(child);
236
- });
237
- if (isIos && shouldReverseOnIos && !isContextMenu) {
238
- result.reverse();
239
- }
240
- return result;
241
- }
242
- function lazyAdapter(name, displayName) {
243
- const Comp = props => {
244
- const z = resolve();
245
- if (!z) return null;
246
- return React.createElement(z.menu[name], props);
247
- };
248
- Comp.displayName = displayName || name;
249
- return Comp;
250
- }
251
- const Trigger = lazyAdapter("Trigger");
252
- const Content = lazyAdapter("Content");
253
- const Item = lazyAdapter("Item");
254
- const ItemTitle = lazyAdapter("ItemTitle");
255
- const ItemSubtitle = lazyAdapter("ItemSubtitle");
256
- const ItemIcon = lazyAdapter("ItemIcon");
257
- const ItemImage = lazyAdapter("ItemImage");
258
- const ItemIndicator = lazyAdapter("ItemIndicator");
259
- const Group = lazyAdapter("Group");
260
- const Label = lazyAdapter("Label");
261
- const Separator = lazyAdapter("Separator");
262
- const Sub = lazyAdapter("Sub");
263
- const SubTrigger = lazyAdapter("SubTrigger");
264
- const SubContent = lazyAdapter("SubContent");
265
- const Portal = ({
266
- children
267
- }) => /* @__PURE__ */jsx(Fragment, {
268
- children
269
- });
270
- Portal.displayName = "Portal";
271
- const Arrow = () => null;
272
- Arrow.displayName = "Arrow";
273
- const RadioGroup = ({
274
- children
275
- }) => /* @__PURE__ */jsx(Fragment, {
276
- children
277
- });
278
- RadioGroup.displayName = `${MenuType}RadioGroup`;
279
- const RadioItem = ({
280
- children
281
- }) => /* @__PURE__ */jsx(Fragment, {
282
- children
283
- });
284
- RadioItem.displayName = `${MenuType}RadioItem`;
285
- const CheckboxItem = () => null;
286
- CheckboxItem.displayName = "CheckboxItem";
287
- const Preview = isContextMenu ? lazyAdapter("Preview", `${MenuType}Preview`) : () => null;
288
- Preview.displayName = `${MenuType}Preview`;
289
- const Auxiliary = isContextMenu ? lazyAdapter("Auxiliary", `${MenuType}Auxiliary`) : () => null;
290
- Auxiliary.displayName = `${MenuType}Auxiliary`;
291
- const Menu = ({
292
- children,
293
- onOpenChange,
294
- onOpenWillChange
295
- }) => {
296
- const triggerOwnerRef = React.useRef(null);
297
- const claimTriggerBoundary = React.useCallback(debugName => {
298
- if (triggerOwnerRef.current) {
299
- unstable_releaseExternalPressOwnership(triggerOwnerRef.current, debugName);
300
- }
301
- triggerOwnerRef.current = unstable_claimExternalPressOwnership(debugName);
302
- }, []);
303
- const releaseTriggerBoundary = React.useCallback(debugName => {
304
- if (!triggerOwnerRef.current) return;
305
- unstable_releaseExternalPressOwnership(triggerOwnerRef.current, debugName);
306
- triggerOwnerRef.current = null;
307
- }, []);
308
- React.useEffect(() => releaseTriggerBoundary, [releaseTriggerBoundary]);
309
- const z = resolve();
310
- if (!z) return null;
311
- const handleOpenChange = React.useCallback(isOpen => {
312
- if (!isOpen) {
313
- releaseTriggerBoundary();
314
- }
315
- onOpenChange?.(isOpen);
316
- }, [onOpenChange, releaseTriggerBoundary]);
317
- const handleOpenWillChange = React.useCallback(willOpen => {
318
- if (!willOpen) {
319
- releaseTriggerBoundary();
320
- }
321
- onOpenWillChange?.(willOpen);
322
- }, [onOpenWillChange, releaseTriggerBoundary]);
323
- const rootProps = {
324
- onOpenChange: handleOpenChange
325
- };
326
- if (isContextMenu && onOpenWillChange) {
327
- rootProps.onOpenWillChange = handleOpenWillChange;
328
- }
329
- const content = /* @__PURE__ */jsx(z.menu.Root, {
330
- ...rootProps,
331
- children: transformChildren(z.menu, z.componentMap, children, false, {
332
- claim: claimTriggerBoundary,
333
- release: releaseTriggerBoundary
334
- })
335
- });
336
- if (isAndroid) {
337
- return /* @__PURE__ */jsx(NativeMenuContext.Provider, {
338
- value: true,
339
- children: content
340
- });
341
- }
342
- return content;
343
- };
344
- Menu.displayName = MenuType;
345
- return {
346
- Menu: withStaticProperties(Menu, {
347
- Trigger,
348
- Content,
349
- Item,
350
- ItemTitle,
351
- ItemSubtitle,
352
- ItemIcon,
353
- ItemImage,
354
- ItemIndicator,
355
- Group,
356
- Label,
357
- Separator,
358
- Sub,
359
- SubTrigger,
360
- SubContent,
361
- CheckboxItem,
362
- Portal,
363
- RadioGroup,
364
- RadioItem,
365
- Arrow,
366
- Preview,
367
- Auxiliary
368
- })
369
- };
88
+ const createNativeMenu = (MenuType) => {
89
+ if (isWeb) {
90
+ return createWebStubs();
91
+ }
92
+ const isContextMenu = MenuType === "ContextMenu";
93
+ const isAndroid = !isIos && !isWeb;
94
+ let resolved = null;
95
+ let warned = false;
96
+ function resolve() {
97
+ if (resolved) return resolved;
98
+ const adapter = getNativeMenuAdapter();
99
+ if (!adapter) {
100
+ if (!warned) {
101
+ warned = true;
102
+ console.warn(`Warning: Register a native menu adapter before rendering Tamagui native menus`);
103
+ }
104
+ return null;
105
+ }
106
+ const menu = isContextMenu ? adapter.ContextMenu : adapter.Menu;
107
+ resolved = {
108
+ menu,
109
+ componentMap: {
110
+ SubContent: menu.SubContent,
111
+ SubTrigger: menu.SubTrigger,
112
+ Content: menu.Content,
113
+ Sub: menu.Sub,
114
+ Group: menu.Group,
115
+ Item: menu.Item,
116
+ ItemTitle: menu.ItemTitle,
117
+ ItemSubtitle: menu.ItemSubtitle,
118
+ ItemIcon: menu.ItemIcon,
119
+ ItemImage: menu.ItemImage,
120
+ ItemIndicator: menu.ItemIndicator,
121
+ Label: menu.Label,
122
+ Separator: menu.Separator,
123
+ CheckboxItem: menu.CheckboxItem,
124
+ Preview: menu.Preview,
125
+ Auxiliary: menu.Auxiliary
126
+ }
127
+ };
128
+ return resolved;
129
+ }
130
+ function transformChildren(menu, map, children, shouldReverseOnIos = false, triggerBoundaryHandlers, radioContext) {
131
+ const result = [];
132
+ React.Children.forEach(children, (child) => {
133
+ if (!React.isValidElement(child)) {
134
+ result.push(child);
135
+ return;
136
+ }
137
+ const displayName = child.type?.displayName || "";
138
+ const props = child.props;
139
+ if (isPortalLike(displayName)) {
140
+ const inner = transformChildren(menu, map, props.children, false, triggerBoundaryHandlers, radioContext);
141
+ React.Children.forEach(inner, (c) => result.push(c));
142
+ return;
143
+ }
144
+ if (displayName.includes("ScrollView")) {
145
+ const inner = transformChildren(menu, map, props.children, false, triggerBoundaryHandlers, radioContext);
146
+ React.Children.forEach(inner, (c) => result.push(c));
147
+ return;
148
+ }
149
+ if (isTriggerLike(displayName)) {
150
+ const debugName = getTriggerDebugName(MenuType, props);
151
+ const claim = () => triggerBoundaryHandlers?.claim(debugName);
152
+ const release = () => triggerBoundaryHandlers?.release(debugName);
153
+ const { children: triggerChildren, ...triggerProps } = props;
154
+ result.push(React.createElement(menu.Trigger, {
155
+ ...triggerProps,
156
+ key: child.key,
157
+ onTouchStart: composeHandlers(claim, props.onTouchStart),
158
+ onTouchEnd: composeHandlers(props.onTouchEnd, release),
159
+ onTouchCancel: composeHandlers(props.onTouchCancel, release),
160
+ onResponderGrant: composeHandlers(claim, props.onResponderGrant),
161
+ onResponderRelease: composeHandlers(props.onResponderRelease, release),
162
+ onResponderTerminate: composeHandlers(props.onResponderTerminate, release),
163
+ onPressIn: composeHandlers(claim, props.onPressIn),
164
+ onPressOut: composeHandlers(props.onPressOut, release)
165
+ }, triggerChildren));
166
+ return;
167
+ }
168
+ if (displayName.includes("RadioGroup")) {
169
+ const { value: rgValue, onValueChange: rgOnValueChange, children: rgChildren, ...rest } = props;
170
+ result.push(React.createElement(menu.Group, {
171
+ ...rest,
172
+ key: child.key
173
+ }, transformChildren(menu, map, rgChildren, false, triggerBoundaryHandlers, {
174
+ value: rgValue,
175
+ onValueChange: rgOnValueChange
176
+ })));
177
+ return;
178
+ }
179
+ if (displayName.includes("RadioItem") && radioContext) {
180
+ const { value: itemValue, children: rChildren, ...rest } = props;
181
+ const cleanChildren = React.Children.map(rChildren, (c) => {
182
+ if (!React.isValidElement(c)) return c;
183
+ const dn = c.type?.displayName || "";
184
+ if (dn.includes("ItemIndicator")) return null;
185
+ return c;
186
+ });
187
+ result.push(React.createElement(menu.CheckboxItem, {
188
+ ...rest,
189
+ key: child.key,
190
+ value: itemValue === radioContext.value ? "on" : "off",
191
+ onValueChange: () => radioContext.onValueChange?.(itemValue)
192
+ }, transformChildren(menu, map, cleanChildren, false, triggerBoundaryHandlers, radioContext)));
193
+ return;
194
+ }
195
+ const componentType = getComponentType(displayName);
196
+ if (componentType === "CheckboxItem") {
197
+ const { checked, onCheckedChange, value, onValueChange, children: cbChildren, ...rest } = props;
198
+ const finalValue = value ?? (checked ? "on" : "off");
199
+ const finalOnValueChange = onValueChange ?? (onCheckedChange && ((v) => onCheckedChange(v === "on")));
200
+ const cleanChildren = React.Children.map(cbChildren, (c) => {
201
+ if (!React.isValidElement(c)) return c;
202
+ const dn = c.type?.displayName || "";
203
+ if (dn.includes("ItemIndicator")) return null;
204
+ return c;
205
+ });
206
+ result.push(React.createElement(menu.CheckboxItem, {
207
+ ...rest,
208
+ key: child.key,
209
+ value: finalValue,
210
+ onValueChange: finalOnValueChange
211
+ }, transformChildren(menu, map, cleanChildren, false, triggerBoundaryHandlers, radioContext)));
212
+ return;
213
+ }
214
+ if (componentType) {
215
+ const { children: childChildren, ...restProps } = props;
216
+ const AdapterComponent = map[componentType];
217
+ const isContainer = CONTAINER_TYPES.includes(componentType);
218
+ const shouldReverse = componentType === "Content" || componentType === "SubContent";
219
+ result.push(React.createElement(AdapterComponent, {
220
+ ...restProps,
221
+ key: child.key
222
+ }, isContainer ? transformChildren(menu, map, childChildren, shouldReverse, triggerBoundaryHandlers, radioContext) : childChildren));
223
+ return;
224
+ }
225
+ if (isItemLike(props, displayName)) {
226
+ const { children: itemChildren, ...itemProps } = props;
227
+ result.push(React.createElement(menu.Item, {
228
+ ...itemProps,
229
+ key: child.key
230
+ }, transformChildren(menu, map, itemChildren, false, triggerBoundaryHandlers, radioContext)));
231
+ return;
232
+ }
233
+ result.push(child);
234
+ });
235
+ if (isIos && shouldReverseOnIos && !isContextMenu) {
236
+ result.reverse();
237
+ }
238
+ return result;
239
+ }
240
+ function lazyAdapter(name, displayName) {
241
+ const Comp = (props) => {
242
+ const z = resolve();
243
+ if (!z) return null;
244
+ return React.createElement(z.menu[name], props);
245
+ };
246
+ Comp.displayName = displayName || name;
247
+ return Comp;
248
+ }
249
+ const Trigger = lazyAdapter("Trigger");
250
+ const Content = lazyAdapter("Content");
251
+ const Item = lazyAdapter("Item");
252
+ const ItemTitle = lazyAdapter("ItemTitle");
253
+ const ItemSubtitle = lazyAdapter("ItemSubtitle");
254
+ const ItemIcon = lazyAdapter("ItemIcon");
255
+ const ItemImage = lazyAdapter("ItemImage");
256
+ const ItemIndicator = lazyAdapter("ItemIndicator");
257
+ const Group = lazyAdapter("Group");
258
+ const Label = lazyAdapter("Label");
259
+ const Separator = lazyAdapter("Separator");
260
+ const Sub = lazyAdapter("Sub");
261
+ const SubTrigger = lazyAdapter("SubTrigger");
262
+ const SubContent = lazyAdapter("SubContent");
263
+ const Portal = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
264
+ Portal.displayName = "Portal";
265
+ const Arrow = () => null;
266
+ Arrow.displayName = "Arrow";
267
+ const RadioGroup = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
268
+ RadioGroup.displayName = `${MenuType}RadioGroup`;
269
+ const RadioItem = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
270
+ RadioItem.displayName = `${MenuType}RadioItem`;
271
+ const CheckboxItem = () => null;
272
+ CheckboxItem.displayName = "CheckboxItem";
273
+ const Preview = isContextMenu ? lazyAdapter("Preview", `${MenuType}Preview`) : () => null;
274
+ Preview.displayName = `${MenuType}Preview`;
275
+ const Auxiliary = isContextMenu ? lazyAdapter("Auxiliary", `${MenuType}Auxiliary`) : () => null;
276
+ Auxiliary.displayName = `${MenuType}Auxiliary`;
277
+ const Menu = ({ children, onOpenChange, onOpenWillChange }) => {
278
+ const triggerOwnerRef = React.useRef(null);
279
+ const claimTriggerBoundary = React.useCallback((debugName) => {
280
+ if (triggerOwnerRef.current) {
281
+ unstable_releaseExternalPressOwnership(triggerOwnerRef.current, debugName);
282
+ }
283
+ triggerOwnerRef.current = unstable_claimExternalPressOwnership(debugName);
284
+ }, []);
285
+ const releaseTriggerBoundary = React.useCallback((debugName) => {
286
+ if (!triggerOwnerRef.current) return;
287
+ unstable_releaseExternalPressOwnership(triggerOwnerRef.current, debugName);
288
+ triggerOwnerRef.current = null;
289
+ }, []);
290
+ React.useEffect(() => releaseTriggerBoundary, [releaseTriggerBoundary]);
291
+ const z = resolve();
292
+ if (!z) return null;
293
+ const handleOpenChange = React.useCallback((isOpen) => {
294
+ if (!isOpen) {
295
+ releaseTriggerBoundary();
296
+ }
297
+ onOpenChange?.(isOpen);
298
+ }, [onOpenChange, releaseTriggerBoundary]);
299
+ const handleOpenWillChange = React.useCallback((willOpen) => {
300
+ if (!willOpen) {
301
+ releaseTriggerBoundary();
302
+ }
303
+ onOpenWillChange?.(willOpen);
304
+ }, [onOpenWillChange, releaseTriggerBoundary]);
305
+ const rootProps = { onOpenChange: handleOpenChange };
306
+ if (isContextMenu && onOpenWillChange) {
307
+ rootProps.onOpenWillChange = handleOpenWillChange;
308
+ }
309
+ const content = /* @__PURE__ */ jsx(z.menu.Root, {
310
+ ...rootProps,
311
+ children: transformChildren(z.menu, z.componentMap, children, false, {
312
+ claim: claimTriggerBoundary,
313
+ release: releaseTriggerBoundary
314
+ })
315
+ });
316
+ if (isAndroid) {
317
+ return /* @__PURE__ */ jsx(NativeMenuContext.Provider, {
318
+ value: true,
319
+ children: content
320
+ });
321
+ }
322
+ return content;
323
+ };
324
+ Menu.displayName = MenuType;
325
+ return { Menu: withStaticProperties(Menu, {
326
+ Trigger,
327
+ Content,
328
+ Item,
329
+ ItemTitle,
330
+ ItemSubtitle,
331
+ ItemIcon,
332
+ ItemImage,
333
+ ItemIndicator,
334
+ Group,
335
+ Label,
336
+ Separator,
337
+ Sub,
338
+ SubTrigger,
339
+ SubContent,
340
+ CheckboxItem,
341
+ Portal,
342
+ RadioGroup,
343
+ RadioItem,
344
+ Arrow,
345
+ Preview,
346
+ Auxiliary
347
+ }) };
370
348
  };
349
+
371
350
  export { createNativeMenu };
372
351
  //# sourceMappingURL=createNativeMenu.mjs.map