@tamagui/create-menu 2.0.0-rc.4 → 2.0.0-rc.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/MenuPredefined.cjs +159 -157
- package/dist/cjs/MenuPredefined.native.js +159 -157
- package/dist/cjs/MenuPredefined.native.js.map +1 -1
- package/dist/cjs/createBaseMenu.cjs +1144 -933
- package/dist/cjs/createBaseMenu.native.js +1266 -1100
- package/dist/cjs/createBaseMenu.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/createNativeMenu.cjs +282 -159
- package/dist/cjs/createNativeMenu/createNativeMenu.native.js +390 -268
- package/dist/cjs/createNativeMenu/createNativeMenu.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.cjs +7 -5
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js +7 -5
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/utils.cjs +85 -42
- package/dist/cjs/createNativeMenu/utils.native.js +83 -58
- package/dist/cjs/createNativeMenu/utils.native.js.map +1 -1
- package/dist/cjs/createNativeMenu/withNativeMenu.cjs +27 -17
- package/dist/cjs/createNativeMenu/withNativeMenu.native.js +22 -14
- package/dist/cjs/createNativeMenu/withNativeMenu.native.js.map +1 -1
- package/dist/cjs/index.cjs +15 -12
- package/dist/cjs/index.native.js +15 -12
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/MenuPredefined.mjs +144 -144
- package/dist/esm/MenuPredefined.mjs.map +1 -1
- package/dist/esm/MenuPredefined.native.js +144 -144
- package/dist/esm/MenuPredefined.native.js.map +1 -1
- package/dist/esm/createBaseMenu.mjs +1104 -895
- package/dist/esm/createBaseMenu.mjs.map +1 -1
- package/dist/esm/createBaseMenu.native.js +1226 -1062
- package/dist/esm/createBaseMenu.native.js.map +1 -1
- package/dist/esm/createNativeMenu/createNativeMenu.mjs +255 -134
- package/dist/esm/createNativeMenu/createNativeMenu.mjs.map +1 -1
- package/dist/esm/createNativeMenu/createNativeMenu.native.js +336 -216
- package/dist/esm/createNativeMenu/createNativeMenu.native.js.map +1 -1
- package/dist/esm/createNativeMenu/utils.mjs +58 -17
- package/dist/esm/createNativeMenu/utils.mjs.map +1 -1
- package/dist/esm/createNativeMenu/utils.native.js +57 -34
- package/dist/esm/createNativeMenu/utils.native.js.map +1 -1
- package/dist/esm/createNativeMenu/withNativeMenu.mjs +13 -5
- package/dist/esm/createNativeMenu/withNativeMenu.mjs.map +1 -1
- package/dist/esm/createNativeMenu/withNativeMenu.native.js +8 -2
- package/dist/esm/createNativeMenu/withNativeMenu.native.js.map +1 -1
- package/dist/esm/index.js +5 -6
- package/dist/esm/index.js.map +1 -6
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/jsx/MenuPredefined.mjs +144 -144
- package/dist/jsx/MenuPredefined.mjs.map +1 -1
- package/dist/jsx/MenuPredefined.native.js +159 -157
- package/dist/jsx/MenuPredefined.native.js.map +1 -1
- package/dist/jsx/createBaseMenu.mjs +1104 -895
- package/dist/jsx/createBaseMenu.mjs.map +1 -1
- package/dist/jsx/createBaseMenu.native.js +1266 -1100
- package/dist/jsx/createBaseMenu.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/createNativeMenu.mjs +255 -134
- package/dist/jsx/createNativeMenu/createNativeMenu.mjs.map +1 -1
- package/dist/jsx/createNativeMenu/createNativeMenu.native.js +390 -268
- package/dist/jsx/createNativeMenu/createNativeMenu.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.native.js +7 -5
- package/dist/jsx/createNativeMenu/utils.mjs +58 -17
- package/dist/jsx/createNativeMenu/utils.mjs.map +1 -1
- package/dist/jsx/createNativeMenu/utils.native.js +83 -58
- package/dist/jsx/createNativeMenu/utils.native.js.map +1 -1
- package/dist/jsx/createNativeMenu/withNativeMenu.mjs +13 -5
- package/dist/jsx/createNativeMenu/withNativeMenu.mjs.map +1 -1
- package/dist/jsx/createNativeMenu/withNativeMenu.native.js +22 -14
- package/dist/jsx/createNativeMenu/withNativeMenu.native.js.map +1 -1
- package/dist/jsx/index.js +5 -6
- package/dist/jsx/index.js.map +1 -6
- package/dist/jsx/index.mjs +2 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +15 -12
- package/dist/jsx/index.native.js.map +1 -1
- package/package.json +25 -27
- package/src/MenuPredefined.tsx +1 -1
- package/src/createBaseMenu.tsx +359 -271
- package/src/createNativeMenu/createNativeMenu.tsx +383 -222
- package/src/createNativeMenu/createNativeMenuTypes.ts +20 -20
- package/src/createNativeMenu/withNativeMenu.tsx +5 -3
- package/src/index.tsx +3 -5
- package/types/createBaseMenu.d.ts +121 -35
- package/types/createBaseMenu.d.ts.map +1 -1
- package/types/createNativeMenu/createNativeMenu.d.ts +21 -21
- package/types/createNativeMenu/createNativeMenu.d.ts.map +1 -1
- package/types/createNativeMenu/createNativeMenuTypes.d.ts +20 -20
- package/types/createNativeMenu/createNativeMenuTypes.d.ts.map +1 -1
- package/types/createNativeMenu/withNativeMenu.d.ts +3 -3
- package/types/createNativeMenu/withNativeMenu.d.ts.map +1 -1
- package/types/index.d.ts +3 -2
- package/types/index.d.ts.map +1 -1
- package/dist/cjs/MenuPredefined.js +0 -168
- package/dist/cjs/MenuPredefined.js.map +0 -6
- package/dist/cjs/createBaseMenu.js +0 -832
- package/dist/cjs/createBaseMenu.js.map +0 -6
- package/dist/cjs/createNativeMenu/createNativeMenu.js +0 -177
- package/dist/cjs/createNativeMenu/createNativeMenu.js.map +0 -6
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.js +0 -14
- package/dist/cjs/createNativeMenu/createNativeMenuTypes.js.map +0 -6
- package/dist/cjs/createNativeMenu/index.cjs +0 -19
- package/dist/cjs/createNativeMenu/index.js +0 -16
- package/dist/cjs/createNativeMenu/index.js.map +0 -6
- package/dist/cjs/createNativeMenu/index.native.js +0 -22
- package/dist/cjs/createNativeMenu/index.native.js.map +0 -1
- package/dist/cjs/createNativeMenu/utils.js +0 -66
- package/dist/cjs/createNativeMenu/utils.js.map +0 -6
- package/dist/cjs/createNativeMenu/withNativeMenu.js +0 -30
- package/dist/cjs/createNativeMenu/withNativeMenu.js.map +0 -6
- package/dist/cjs/index.js +0 -23
- package/dist/cjs/index.js.map +0 -6
- package/dist/esm/MenuPredefined.js +0 -154
- package/dist/esm/MenuPredefined.js.map +0 -6
- package/dist/esm/createBaseMenu.js +0 -838
- package/dist/esm/createBaseMenu.js.map +0 -6
- package/dist/esm/createNativeMenu/createNativeMenu.js +0 -156
- package/dist/esm/createNativeMenu/createNativeMenu.js.map +0 -6
- package/dist/esm/createNativeMenu/createNativeMenuTypes.js +0 -1
- package/dist/esm/createNativeMenu/createNativeMenuTypes.js.map +0 -6
- package/dist/esm/createNativeMenu/index.js +0 -3
- package/dist/esm/createNativeMenu/index.js.map +0 -6
- package/dist/esm/createNativeMenu/index.mjs +0 -3
- package/dist/esm/createNativeMenu/index.mjs.map +0 -1
- package/dist/esm/createNativeMenu/index.native.js +0 -3
- package/dist/esm/createNativeMenu/index.native.js.map +0 -1
- package/dist/esm/createNativeMenu/utils.js +0 -47
- package/dist/esm/createNativeMenu/utils.js.map +0 -6
- package/dist/esm/createNativeMenu/withNativeMenu.js +0 -15
- package/dist/esm/createNativeMenu/withNativeMenu.js.map +0 -6
- package/dist/jsx/MenuPredefined.js +0 -154
- package/dist/jsx/MenuPredefined.js.map +0 -6
- package/dist/jsx/createBaseMenu.js +0 -838
- package/dist/jsx/createBaseMenu.js.map +0 -6
- package/dist/jsx/createNativeMenu/createNativeMenu.js +0 -156
- package/dist/jsx/createNativeMenu/createNativeMenu.js.map +0 -6
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.js +0 -1
- package/dist/jsx/createNativeMenu/createNativeMenuTypes.js.map +0 -6
- package/dist/jsx/createNativeMenu/index.js +0 -3
- package/dist/jsx/createNativeMenu/index.js.map +0 -6
- package/dist/jsx/createNativeMenu/index.mjs +0 -3
- package/dist/jsx/createNativeMenu/index.mjs.map +0 -1
- package/dist/jsx/createNativeMenu/index.native.js +0 -22
- package/dist/jsx/createNativeMenu/index.native.js.map +0 -1
- package/dist/jsx/createNativeMenu/utils.js +0 -47
- package/dist/jsx/createNativeMenu/utils.js.map +0 -6
- package/dist/jsx/createNativeMenu/withNativeMenu.js +0 -15
- package/dist/jsx/createNativeMenu/withNativeMenu.js.map +0 -6
- package/src/createNativeMenu/index.tsx +0 -7
- package/types/createNativeMenu/index.d.ts +0 -4
- package/types/createNativeMenu/index.d.ts.map +0 -1
|
@@ -1,194 +1,254 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* createNativeMenu -
|
|
2
|
+
* createNativeMenu - native menu implementation for React Native
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Web: returns empty stub components (withNativeMenu uses the web components instead)
|
|
5
|
+
* Native: lazily resolves Zeego at render time so importing the package doesn't warn/error
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getZeego,
|
|
10
|
+
NativeMenuContext,
|
|
11
|
+
unstable_claimExternalPressOwnership,
|
|
12
|
+
unstable_releaseExternalPressOwnership,
|
|
13
|
+
} from '@tamagui/native'
|
|
9
14
|
import { isWeb, withStaticProperties, isIos } from '@tamagui/web'
|
|
10
15
|
import type { FC } from 'react'
|
|
11
16
|
import React from 'react'
|
|
12
17
|
import type {
|
|
13
18
|
ContextMenuPreviewProps,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
NativeContextMenuAuxiliaryProps,
|
|
20
|
+
NativeMenuArrowProps,
|
|
21
|
+
NativeMenuCheckboxItemProps,
|
|
22
|
+
NativeMenuContentProps,
|
|
23
|
+
NativeMenuGroupProps,
|
|
24
|
+
NativeMenuItemIconProps,
|
|
25
|
+
NativeMenuItemImageProps,
|
|
26
|
+
NativeMenuItemIndicatorProps,
|
|
27
|
+
NativeMenuItemProps,
|
|
28
|
+
NativeMenuItemSubtitleProps,
|
|
29
|
+
NativeMenuItemTitleProps,
|
|
30
|
+
NativeMenuLabelProps,
|
|
31
|
+
NativeMenuProps,
|
|
32
|
+
NativeMenuSeparatorProps,
|
|
33
|
+
NativeMenuSubContentProps,
|
|
34
|
+
NativeMenuSubProps,
|
|
35
|
+
NativeMenuSubTriggerProps,
|
|
30
36
|
MenuTriggerProps,
|
|
31
37
|
} from './createNativeMenuTypes'
|
|
32
38
|
|
|
39
|
+
// zeego module shape (DropdownMenu / ContextMenu both share this)
|
|
40
|
+
type ZeegoMenuModule = {
|
|
41
|
+
Root: FC<Record<string, unknown>>
|
|
42
|
+
Trigger: FC<MenuTriggerProps>
|
|
43
|
+
Content: FC<NativeMenuContentProps>
|
|
44
|
+
Item: FC<NativeMenuItemProps>
|
|
45
|
+
ItemTitle: FC<NativeMenuItemTitleProps>
|
|
46
|
+
ItemSubtitle: FC<NativeMenuItemSubtitleProps>
|
|
47
|
+
ItemIcon: FC<NativeMenuItemIconProps>
|
|
48
|
+
ItemImage: FC<NativeMenuItemImageProps>
|
|
49
|
+
ItemIndicator: FC<NativeMenuItemIndicatorProps>
|
|
50
|
+
Group: FC<NativeMenuGroupProps>
|
|
51
|
+
Label: FC<NativeMenuLabelProps>
|
|
52
|
+
Separator: FC<NativeMenuSeparatorProps>
|
|
53
|
+
Sub: FC<NativeMenuSubProps>
|
|
54
|
+
SubTrigger: FC<NativeMenuSubTriggerProps>
|
|
55
|
+
SubContent: FC<NativeMenuSubContentProps>
|
|
56
|
+
CheckboxItem: FC<NativeMenuCheckboxItemProps>
|
|
57
|
+
Preview: FC<ContextMenuPreviewProps>
|
|
58
|
+
Auxiliary: FC<NativeContextMenuAuxiliaryProps>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// component types we recognize via displayName matching
|
|
62
|
+
type MappedComponentType =
|
|
63
|
+
| 'SubContent'
|
|
64
|
+
| 'SubTrigger'
|
|
65
|
+
| 'Content'
|
|
66
|
+
| 'Sub'
|
|
67
|
+
| 'Group'
|
|
68
|
+
| 'CheckboxItem'
|
|
69
|
+
|
|
70
|
+
const MAPPED_TYPES: MappedComponentType[] = [
|
|
71
|
+
'SubContent',
|
|
72
|
+
'SubTrigger',
|
|
73
|
+
'Content',
|
|
74
|
+
'Sub',
|
|
75
|
+
'Group',
|
|
76
|
+
'CheckboxItem',
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
// types whose children get recursively transformed
|
|
80
|
+
const CONTAINER_TYPES: MappedComponentType[] = ['SubContent', 'Content', 'Sub', 'Group']
|
|
81
|
+
|
|
82
|
+
type ComponentMap = Pick<
|
|
83
|
+
ZeegoMenuModule,
|
|
84
|
+
'SubContent' | 'Content' | 'Sub' | 'Group' | 'SubTrigger'
|
|
85
|
+
>
|
|
86
|
+
|
|
87
|
+
type TriggerPressBoundaryHandlers = {
|
|
88
|
+
claim(debugName?: string | null): void
|
|
89
|
+
release(debugName?: string | null): void
|
|
90
|
+
}
|
|
91
|
+
|
|
33
92
|
export type NativeMenuComponents = {
|
|
34
|
-
Menu: FC<
|
|
93
|
+
Menu: FC<NativeMenuProps> & {
|
|
35
94
|
Trigger: FC<MenuTriggerProps>
|
|
36
|
-
Content: FC<
|
|
37
|
-
Item: FC<
|
|
38
|
-
ItemTitle: FC<
|
|
39
|
-
ItemSubtitle: FC<
|
|
40
|
-
SubTrigger: FC<
|
|
41
|
-
Group: FC<
|
|
42
|
-
ItemIcon: FC<
|
|
43
|
-
Separator: FC<
|
|
44
|
-
CheckboxItem: FC<
|
|
45
|
-
ItemIndicator: FC<
|
|
46
|
-
ItemImage: FC<
|
|
47
|
-
Label: FC<
|
|
48
|
-
Arrow: FC<
|
|
49
|
-
Sub: FC<
|
|
50
|
-
SubContent: FC<
|
|
95
|
+
Content: FC<NativeMenuContentProps>
|
|
96
|
+
Item: FC<NativeMenuItemProps>
|
|
97
|
+
ItemTitle: FC<NativeMenuItemTitleProps>
|
|
98
|
+
ItemSubtitle: FC<NativeMenuItemSubtitleProps>
|
|
99
|
+
SubTrigger: FC<NativeMenuSubTriggerProps>
|
|
100
|
+
Group: FC<NativeMenuGroupProps>
|
|
101
|
+
ItemIcon: FC<NativeMenuItemIconProps>
|
|
102
|
+
Separator: FC<NativeMenuSeparatorProps>
|
|
103
|
+
CheckboxItem: FC<NativeMenuCheckboxItemProps>
|
|
104
|
+
ItemIndicator: FC<NativeMenuItemIndicatorProps>
|
|
105
|
+
ItemImage: FC<NativeMenuItemImageProps>
|
|
106
|
+
Label: FC<NativeMenuLabelProps>
|
|
107
|
+
Arrow: FC<NativeMenuArrowProps>
|
|
108
|
+
Sub: FC<NativeMenuSubProps>
|
|
109
|
+
SubContent: FC<NativeMenuSubContentProps>
|
|
51
110
|
Preview: FC<ContextMenuPreviewProps>
|
|
52
111
|
Portal: FC<{ children: React.ReactNode }>
|
|
53
112
|
RadioGroup: FC<{ children: React.ReactNode }>
|
|
54
113
|
RadioItem: FC<{ children: React.ReactNode }>
|
|
55
|
-
Auxiliary: FC<
|
|
114
|
+
Auxiliary: FC<NativeContextMenuAuxiliaryProps>
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// shared helpers (stateless, no need to recreate per call)
|
|
119
|
+
|
|
120
|
+
function getComponentType(displayName: string): MappedComponentType | null {
|
|
121
|
+
for (const type of MAPPED_TYPES) {
|
|
122
|
+
if (displayName === type || displayName.includes(`(${type})`)) {
|
|
123
|
+
return type
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function isItemLike(props: Record<string, unknown>, displayName: string): boolean {
|
|
130
|
+
if (getComponentType(displayName)) return false
|
|
131
|
+
return 'onSelect' in props || 'textValue' in props
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isPortalLike(displayName: string): boolean {
|
|
135
|
+
return displayName === 'Portal' || displayName.includes('Portal')
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function isTriggerLike(displayName: string): boolean {
|
|
139
|
+
return displayName === 'Trigger' || displayName.includes('(Trigger)')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function composeHandlers<T extends (...args: any[]) => void>(first?: T, second?: T) {
|
|
143
|
+
return (...args: Parameters<T>) => {
|
|
144
|
+
first?.(...args)
|
|
145
|
+
second?.(...args)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function getTriggerDebugName(
|
|
150
|
+
menuType: 'ContextMenu' | 'Menu',
|
|
151
|
+
props: Record<string, any>
|
|
152
|
+
) {
|
|
153
|
+
const childProps =
|
|
154
|
+
React.isValidElement(props.children) && props.children.props
|
|
155
|
+
? (props.children.props as Record<string, any>)
|
|
156
|
+
: null
|
|
157
|
+
|
|
158
|
+
const prefix = menuType === 'ContextMenu' ? 'ContextMenuTrigger' : 'MenuTrigger'
|
|
159
|
+
const detail =
|
|
160
|
+
childProps?.testID ??
|
|
161
|
+
childProps?.accessibilityLabel ??
|
|
162
|
+
(typeof props.textValue === 'string' ? props.textValue : null)
|
|
163
|
+
|
|
164
|
+
return [prefix, detail].filter(Boolean).join(':') || prefix
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// stub used for web — never actually rendered, just needs to exist for withNativeMenu fallback
|
|
168
|
+
const emptyStub = (() => null) as FC<any>
|
|
169
|
+
|
|
170
|
+
function createWebStubs(): NativeMenuComponents {
|
|
171
|
+
return {
|
|
172
|
+
Menu: withStaticProperties(emptyStub as FC<NativeMenuProps>, {
|
|
173
|
+
Trigger: emptyStub as FC<MenuTriggerProps>,
|
|
174
|
+
Content: emptyStub as FC<NativeMenuContentProps>,
|
|
175
|
+
Item: emptyStub as FC<NativeMenuItemProps>,
|
|
176
|
+
ItemTitle: emptyStub as FC<NativeMenuItemTitleProps>,
|
|
177
|
+
ItemSubtitle: emptyStub as FC<NativeMenuItemSubtitleProps>,
|
|
178
|
+
SubTrigger: emptyStub as FC<NativeMenuSubTriggerProps>,
|
|
179
|
+
Group: emptyStub as FC<NativeMenuGroupProps>,
|
|
180
|
+
ItemIcon: emptyStub as FC<NativeMenuItemIconProps>,
|
|
181
|
+
Separator: emptyStub as FC<NativeMenuSeparatorProps>,
|
|
182
|
+
CheckboxItem: emptyStub as FC<NativeMenuCheckboxItemProps>,
|
|
183
|
+
ItemIndicator: emptyStub as FC<NativeMenuItemIndicatorProps>,
|
|
184
|
+
ItemImage: emptyStub as FC<NativeMenuItemImageProps>,
|
|
185
|
+
Label: emptyStub as FC<NativeMenuLabelProps>,
|
|
186
|
+
Arrow: emptyStub as FC<NativeMenuArrowProps>,
|
|
187
|
+
Sub: emptyStub as FC<NativeMenuSubProps>,
|
|
188
|
+
SubContent: emptyStub as FC<NativeMenuSubContentProps>,
|
|
189
|
+
Preview: emptyStub as FC<ContextMenuPreviewProps>,
|
|
190
|
+
Portal: emptyStub as FC<{ children: React.ReactNode }>,
|
|
191
|
+
RadioGroup: emptyStub as FC<{ children: React.ReactNode }>,
|
|
192
|
+
RadioItem: emptyStub as FC<{ children: React.ReactNode }>,
|
|
193
|
+
Auxiliary: emptyStub as FC<NativeContextMenuAuxiliaryProps>,
|
|
194
|
+
}),
|
|
56
195
|
}
|
|
57
196
|
}
|
|
58
197
|
|
|
59
198
|
export const createNativeMenu = (
|
|
60
199
|
MenuType: 'ContextMenu' | 'Menu'
|
|
61
200
|
): NativeMenuComponents => {
|
|
62
|
-
// On web, return empty stubs - withNativeMenu will use the web components passed to it
|
|
63
201
|
if (isWeb) {
|
|
64
|
-
|
|
65
|
-
const Trigger = {} as FC<MenuTriggerProps>
|
|
66
|
-
const Content = {} as FC<MenuContentProps>
|
|
67
|
-
const Preview = {} as FC<ContextMenuPreviewProps>
|
|
68
|
-
const Item = {} as FC<MenuItemProps>
|
|
69
|
-
const ItemIcon = {} as FC<MenuItemIconProps>
|
|
70
|
-
const ItemImage = {} as FC<MenuItemImageProps>
|
|
71
|
-
const SubTrigger = {} as FC<MenuSubTriggerProps>
|
|
72
|
-
const ItemTitle = {} as FC<MenuItemTitleProps>
|
|
73
|
-
const ItemSubtitle = {} as FC<MenuItemSubtitleProps>
|
|
74
|
-
const Group = {} as FC<MenuGroupProps>
|
|
75
|
-
const Separator = {} as FC<MenuSeparatorProps>
|
|
76
|
-
const CheckboxItem = {} as FC<MenuCheckboxItemProps>
|
|
77
|
-
const ItemIndicator = {} as FC<MenuItemIndicatorProps>
|
|
78
|
-
const Label = {} as FC<MenuLabelProps>
|
|
79
|
-
const Arrow = {} as FC<MenuArrowProps>
|
|
80
|
-
const Sub = {} as FC<MenuSubProps>
|
|
81
|
-
const SubContent = {} as FC<MenuSubContentProps>
|
|
82
|
-
const Portal = {} as FC<{ children: React.ReactNode }>
|
|
83
|
-
const RadioGroup = {} as FC<{ children: React.ReactNode }>
|
|
84
|
-
const RadioItem = {} as FC<{ children: React.ReactNode }>
|
|
85
|
-
const Auxiliary = {} as FC<any>
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
Menu: withStaticProperties(Menu, {
|
|
89
|
-
Trigger,
|
|
90
|
-
Content,
|
|
91
|
-
Item,
|
|
92
|
-
ItemTitle,
|
|
93
|
-
ItemSubtitle,
|
|
94
|
-
SubTrigger,
|
|
95
|
-
Group,
|
|
96
|
-
ItemIcon,
|
|
97
|
-
Separator,
|
|
98
|
-
CheckboxItem,
|
|
99
|
-
ItemIndicator,
|
|
100
|
-
ItemImage,
|
|
101
|
-
Label,
|
|
102
|
-
Arrow,
|
|
103
|
-
Sub,
|
|
104
|
-
SubContent,
|
|
105
|
-
Preview,
|
|
106
|
-
Portal,
|
|
107
|
-
RadioGroup,
|
|
108
|
-
RadioItem,
|
|
109
|
-
Auxiliary,
|
|
110
|
-
}),
|
|
111
|
-
}
|
|
202
|
+
return createWebStubs()
|
|
112
203
|
}
|
|
113
204
|
|
|
114
205
|
// ===========================================
|
|
115
|
-
//
|
|
206
|
+
// native implementation — lazily resolves zeego
|
|
116
207
|
// ===========================================
|
|
117
208
|
|
|
118
|
-
const zeego = getZeego()
|
|
119
|
-
if (!zeego.isEnabled) {
|
|
120
|
-
console.warn(
|
|
121
|
-
`Warning: Must call import '@tamagui/native/setup-zeego' at your app entry point to use native menus`
|
|
122
|
-
)
|
|
123
|
-
return { Menu: {} as any }
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const { DropdownMenu: ZeegoDropdownMenu, ContextMenu: ZeegoContextMenu } = zeego.state
|
|
127
|
-
|
|
128
209
|
const isContextMenu = MenuType === 'ContextMenu'
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
* Get component type from displayName (handles styled wrappers)
|
|
145
|
-
*/
|
|
146
|
-
const getComponentType = (displayName: string): string | null => {
|
|
147
|
-
// Check in specific order (SubContent before Content, SubTrigger before Trigger)
|
|
148
|
-
for (const type of [
|
|
149
|
-
'SubContent',
|
|
150
|
-
'SubTrigger',
|
|
151
|
-
'Content',
|
|
152
|
-
'Sub',
|
|
153
|
-
'Group',
|
|
154
|
-
'CheckboxItem',
|
|
155
|
-
]) {
|
|
156
|
-
if (displayName === type || displayName.includes(`(${type})`)) {
|
|
157
|
-
return type
|
|
210
|
+
const isAndroid = !isIos && !isWeb
|
|
211
|
+
|
|
212
|
+
// cached after first successful resolve
|
|
213
|
+
let resolved: { menu: ZeegoMenuModule; componentMap: ComponentMap } | null = null
|
|
214
|
+
let warned = false
|
|
215
|
+
|
|
216
|
+
function resolve(): typeof resolved {
|
|
217
|
+
if (resolved) return resolved
|
|
218
|
+
const zeego = getZeego()
|
|
219
|
+
if (!zeego.isEnabled) {
|
|
220
|
+
if (!warned) {
|
|
221
|
+
warned = true
|
|
222
|
+
console.warn(
|
|
223
|
+
`Warning: Must call import '@tamagui/native/setup-zeego' at your app entry point to use native menus`
|
|
224
|
+
)
|
|
158
225
|
}
|
|
226
|
+
return null
|
|
159
227
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
228
|
+
const menu = (
|
|
229
|
+
isContextMenu ? zeego.state.ContextMenu : zeego.state.DropdownMenu
|
|
230
|
+
) as ZeegoMenuModule
|
|
231
|
+
resolved = {
|
|
232
|
+
menu,
|
|
233
|
+
componentMap: {
|
|
234
|
+
SubContent: menu.SubContent,
|
|
235
|
+
Content: menu.Content,
|
|
236
|
+
Sub: menu.Sub,
|
|
237
|
+
Group: menu.Group,
|
|
238
|
+
SubTrigger: menu.SubTrigger,
|
|
239
|
+
},
|
|
170
240
|
}
|
|
171
|
-
return
|
|
241
|
+
return resolved
|
|
172
242
|
}
|
|
173
243
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return displayName === 'Portal' || displayName.includes('Portal')
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Transform children tree for Zeego compatibility:
|
|
183
|
-
* - Flatten Portal wrappers
|
|
184
|
-
* - Recurse into containers (Content, Sub, Group, SubContent)
|
|
185
|
-
* - Convert styled Items to Zeego Items
|
|
186
|
-
* - Reverse children on iOS only for DropdownMenu at Content/SubContent level
|
|
187
|
-
*/
|
|
188
|
-
const transformForZeego = (
|
|
244
|
+
// transform children tree for zeego compatibility
|
|
245
|
+
function transformChildren(
|
|
246
|
+
menu: ZeegoMenuModule,
|
|
247
|
+
map: ComponentMap,
|
|
189
248
|
children: React.ReactNode,
|
|
190
|
-
shouldReverseOnIos = false
|
|
191
|
-
|
|
249
|
+
shouldReverseOnIos = false,
|
|
250
|
+
triggerBoundaryHandlers?: TriggerPressBoundaryHandlers
|
|
251
|
+
): React.ReactNode {
|
|
192
252
|
const result: React.ReactNode[] = []
|
|
193
253
|
|
|
194
254
|
React.Children.forEach(children, (child) => {
|
|
@@ -197,49 +257,89 @@ export const createNativeMenu = (
|
|
|
197
257
|
return
|
|
198
258
|
}
|
|
199
259
|
|
|
200
|
-
const displayName = (child.type as
|
|
260
|
+
const displayName = (child.type as { displayName?: string })?.displayName || ''
|
|
201
261
|
const props = child.props as Record<string, any>
|
|
202
262
|
|
|
203
|
-
//
|
|
204
|
-
if (
|
|
205
|
-
const
|
|
206
|
-
|
|
263
|
+
// flatten portal wrappers
|
|
264
|
+
if (isPortalLike(displayName)) {
|
|
265
|
+
const inner = transformChildren(
|
|
266
|
+
menu,
|
|
267
|
+
map,
|
|
268
|
+
props.children as React.ReactNode,
|
|
269
|
+
false,
|
|
270
|
+
triggerBoundaryHandlers
|
|
271
|
+
)
|
|
272
|
+
React.Children.forEach(inner, (c) => result.push(c))
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// flatten ScrollView (native passthrough — children need to be visible to zeego)
|
|
277
|
+
if (displayName.includes('ScrollView')) {
|
|
278
|
+
const inner = transformChildren(
|
|
279
|
+
menu,
|
|
280
|
+
map,
|
|
281
|
+
props.children as React.ReactNode,
|
|
282
|
+
false,
|
|
283
|
+
triggerBoundaryHandlers
|
|
284
|
+
)
|
|
285
|
+
React.Children.forEach(inner, (c) => result.push(c))
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (isTriggerLike(displayName)) {
|
|
290
|
+
const debugName = getTriggerDebugName(MenuType, props)
|
|
291
|
+
const claim = () => triggerBoundaryHandlers?.claim(debugName)
|
|
292
|
+
const release = () => triggerBoundaryHandlers?.release(debugName)
|
|
293
|
+
|
|
294
|
+
result.push(
|
|
295
|
+
React.cloneElement(child, {
|
|
296
|
+
onTouchStart: composeHandlers(claim, props.onTouchStart),
|
|
297
|
+
onTouchEnd: composeHandlers(props.onTouchEnd, release),
|
|
298
|
+
onTouchCancel: composeHandlers(props.onTouchCancel, release),
|
|
299
|
+
onResponderGrant: composeHandlers(claim, props.onResponderGrant),
|
|
300
|
+
onResponderRelease: composeHandlers(props.onResponderRelease, release),
|
|
301
|
+
onResponderTerminate: composeHandlers(props.onResponderTerminate, release),
|
|
302
|
+
onPressIn: composeHandlers(claim, props.onPressIn),
|
|
303
|
+
onPressOut: composeHandlers(props.onPressOut, release),
|
|
304
|
+
} as any)
|
|
305
|
+
)
|
|
207
306
|
return
|
|
208
307
|
}
|
|
209
308
|
|
|
210
|
-
// Handle known component types (containers, SubTrigger, CheckboxItem)
|
|
211
309
|
const componentType = getComponentType(displayName)
|
|
212
310
|
|
|
213
|
-
//
|
|
311
|
+
// normalize checkbox checked/value props
|
|
214
312
|
if (componentType === 'CheckboxItem') {
|
|
215
|
-
const {
|
|
216
|
-
|
|
313
|
+
const {
|
|
314
|
+
checked,
|
|
315
|
+
onCheckedChange,
|
|
316
|
+
value,
|
|
317
|
+
onValueChange,
|
|
318
|
+
children: cbChildren,
|
|
319
|
+
...rest
|
|
320
|
+
} = props as Record<string, any>
|
|
217
321
|
|
|
218
322
|
const finalValue = value ?? (checked ? 'on' : 'off')
|
|
219
323
|
const finalOnValueChange =
|
|
220
324
|
onValueChange ??
|
|
221
325
|
(onCheckedChange && ((v: string) => onCheckedChange(v === 'on')))
|
|
222
326
|
|
|
223
|
-
const cleanChildren = React.Children.map(
|
|
224
|
-
if (!React.isValidElement(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (childDisplayName.includes('ItemIndicator')) {
|
|
229
|
-
return null
|
|
230
|
-
}
|
|
231
|
-
return child
|
|
327
|
+
const cleanChildren = React.Children.map(cbChildren, (c) => {
|
|
328
|
+
if (!React.isValidElement(c)) return c
|
|
329
|
+
const dn = (c.type as { displayName?: string })?.displayName || ''
|
|
330
|
+
if (dn.includes('ItemIndicator')) return null
|
|
331
|
+
return c
|
|
232
332
|
})
|
|
233
333
|
|
|
234
334
|
result.push(
|
|
235
335
|
React.createElement(
|
|
236
|
-
|
|
336
|
+
menu.CheckboxItem,
|
|
237
337
|
{
|
|
238
338
|
...rest,
|
|
239
339
|
key: child.key,
|
|
240
340
|
value: finalValue,
|
|
241
341
|
onValueChange: finalOnValueChange,
|
|
242
|
-
},
|
|
342
|
+
} as any,
|
|
243
343
|
cleanChildren
|
|
244
344
|
)
|
|
245
345
|
)
|
|
@@ -248,41 +348,44 @@ export const createNativeMenu = (
|
|
|
248
348
|
|
|
249
349
|
if (componentType) {
|
|
250
350
|
const { children: childChildren, ...restProps } = props
|
|
251
|
-
const isContainer = CONTAINER_TYPES.includes(componentType)
|
|
252
|
-
|
|
253
|
-
const shouldReverseChildren =
|
|
351
|
+
const isContainer = (CONTAINER_TYPES as string[]).includes(componentType)
|
|
352
|
+
const shouldReverse =
|
|
254
353
|
componentType === 'Content' || componentType === 'SubContent'
|
|
255
354
|
result.push(
|
|
256
355
|
React.createElement(
|
|
257
|
-
|
|
258
|
-
{ ...restProps, key: child.key },
|
|
356
|
+
map[componentType as keyof ComponentMap],
|
|
357
|
+
{ ...restProps, key: child.key } as any,
|
|
259
358
|
isContainer
|
|
260
|
-
?
|
|
359
|
+
? transformChildren(
|
|
360
|
+
menu,
|
|
361
|
+
map,
|
|
362
|
+
childChildren as React.ReactNode,
|
|
363
|
+
shouldReverse,
|
|
364
|
+
triggerBoundaryHandlers
|
|
365
|
+
)
|
|
261
366
|
: childChildren
|
|
262
367
|
)
|
|
263
368
|
)
|
|
264
369
|
return
|
|
265
370
|
}
|
|
266
371
|
|
|
267
|
-
//
|
|
372
|
+
// convert Item-like components to zeego Items
|
|
268
373
|
if (isItemLike(props, displayName)) {
|
|
269
374
|
const { children: itemChildren, ...itemProps } = props
|
|
270
375
|
result.push(
|
|
271
376
|
React.createElement(
|
|
272
|
-
|
|
273
|
-
{ ...itemProps, key: child.key },
|
|
377
|
+
menu.Item,
|
|
378
|
+
{ ...itemProps, key: child.key } as any,
|
|
274
379
|
itemChildren
|
|
275
380
|
)
|
|
276
381
|
)
|
|
277
382
|
return
|
|
278
383
|
}
|
|
279
384
|
|
|
280
|
-
// Pass through everything else
|
|
281
385
|
result.push(child)
|
|
282
386
|
})
|
|
283
387
|
|
|
284
|
-
// iOS DropdownMenu
|
|
285
|
-
// Only reverse for Menu component, not ContextMenu
|
|
388
|
+
// iOS DropdownMenu displays items in reverse order
|
|
286
389
|
if (isIos && shouldReverseOnIos && !isContextMenu) {
|
|
287
390
|
result.reverse()
|
|
288
391
|
}
|
|
@@ -290,31 +393,39 @@ export const createNativeMenu = (
|
|
|
290
393
|
return result
|
|
291
394
|
}
|
|
292
395
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
396
|
+
// lazy wrapper — resolves the zeego component on first render
|
|
397
|
+
function lazyZeego<P extends Record<string, any>>(
|
|
398
|
+
name: keyof ZeegoMenuModule,
|
|
399
|
+
displayName?: string
|
|
400
|
+
): FC<P> {
|
|
401
|
+
const Comp: FC<P> = (props) => {
|
|
402
|
+
const z = resolve()
|
|
403
|
+
if (!z) return null
|
|
404
|
+
return React.createElement(z.menu[name] as FC<any>, props)
|
|
405
|
+
}
|
|
406
|
+
Comp.displayName = displayName || name
|
|
407
|
+
return Comp
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const Trigger = lazyZeego<MenuTriggerProps>('Trigger')
|
|
411
|
+
const Content = lazyZeego<NativeMenuContentProps>('Content')
|
|
412
|
+
const Item = lazyZeego<NativeMenuItemProps>('Item')
|
|
413
|
+
const ItemTitle = lazyZeego<NativeMenuItemTitleProps>('ItemTitle')
|
|
414
|
+
const ItemSubtitle = lazyZeego<NativeMenuItemSubtitleProps>('ItemSubtitle')
|
|
415
|
+
const ItemIcon = lazyZeego<NativeMenuItemIconProps>('ItemIcon')
|
|
416
|
+
const ItemImage = lazyZeego<NativeMenuItemImageProps>('ItemImage')
|
|
417
|
+
const ItemIndicator = lazyZeego<NativeMenuItemIndicatorProps>('ItemIndicator')
|
|
418
|
+
const Group = lazyZeego<NativeMenuGroupProps>('Group')
|
|
419
|
+
const Label = lazyZeego<NativeMenuLabelProps>('Label')
|
|
420
|
+
const Separator = lazyZeego<NativeMenuSeparatorProps>('Separator')
|
|
421
|
+
const Sub = lazyZeego<NativeMenuSubProps>('Sub')
|
|
422
|
+
const SubTrigger = lazyZeego<NativeMenuSubTriggerProps>('SubTrigger')
|
|
423
|
+
const SubContent = lazyZeego<NativeMenuSubContentProps>('SubContent')
|
|
296
424
|
|
|
297
|
-
// Direct Zeego pass-throughs with proper types
|
|
298
|
-
const Trigger: FC<MenuTriggerProps> = ZeegoMenu.Trigger
|
|
299
|
-
const Content: FC<MenuContentProps> = ZeegoMenu.Content
|
|
300
|
-
const Item: FC<MenuItemProps> = ZeegoMenu.Item
|
|
301
|
-
const ItemTitle: FC<MenuItemTitleProps> = ZeegoMenu.ItemTitle
|
|
302
|
-
const ItemSubtitle: FC<MenuItemSubtitleProps> = ZeegoMenu.ItemSubtitle
|
|
303
|
-
const ItemIcon: FC<MenuItemIconProps> = ZeegoMenu.ItemIcon
|
|
304
|
-
const ItemImage: FC<MenuItemImageProps> = ZeegoMenu.ItemImage
|
|
305
|
-
const ItemIndicator: FC<MenuItemIndicatorProps> = ZeegoMenu.ItemIndicator
|
|
306
|
-
const Group: FC<MenuGroupProps> = ZeegoMenu.Group
|
|
307
|
-
const Label: FC<MenuLabelProps> = ZeegoMenu.Label
|
|
308
|
-
const Separator: FC<MenuSeparatorProps> = ZeegoMenu.Separator
|
|
309
|
-
const Sub: FC<MenuSubProps> = ZeegoMenu.Sub
|
|
310
|
-
const SubTrigger: FC<MenuSubTriggerProps> = ZeegoMenu.SubTrigger
|
|
311
|
-
const SubContent: FC<MenuSubContentProps> = ZeegoMenu.SubContent
|
|
312
|
-
|
|
313
|
-
// Custom components
|
|
314
425
|
const Portal: FC<{ children: React.ReactNode }> = ({ children }) => <>{children}</>
|
|
315
426
|
Portal.displayName = 'Portal'
|
|
316
427
|
|
|
317
|
-
const Arrow: FC<
|
|
428
|
+
const Arrow: FC<NativeMenuArrowProps> = () => null
|
|
318
429
|
Arrow.displayName = 'Arrow'
|
|
319
430
|
|
|
320
431
|
const RadioGroup: FC<{ children: React.ReactNode }> = ({ children }) => <>{children}</>
|
|
@@ -322,36 +433,86 @@ export const createNativeMenu = (
|
|
|
322
433
|
|
|
323
434
|
const RadioItem: FC<{ children: React.ReactNode }> = ({ children }) => <>{children}</>
|
|
324
435
|
RadioItem.displayName = `${MenuType}RadioItem`
|
|
325
|
-
|
|
326
|
-
const CheckboxItem: FC<
|
|
436
|
+
|
|
437
|
+
const CheckboxItem: FC<NativeMenuCheckboxItemProps> = () => null
|
|
327
438
|
CheckboxItem.displayName = 'CheckboxItem'
|
|
328
439
|
|
|
329
|
-
// Context menu specific
|
|
330
440
|
const Preview: FC<ContextMenuPreviewProps> = isContextMenu
|
|
331
|
-
?
|
|
441
|
+
? lazyZeego<ContextMenuPreviewProps>('Preview', `${MenuType}Preview`)
|
|
332
442
|
: () => null
|
|
333
443
|
Preview.displayName = `${MenuType}Preview`
|
|
334
444
|
|
|
335
|
-
const Auxiliary: FC<
|
|
336
|
-
?
|
|
445
|
+
const Auxiliary: FC<NativeContextMenuAuxiliaryProps> = isContextMenu
|
|
446
|
+
? lazyZeego<NativeContextMenuAuxiliaryProps>('Auxiliary', `${MenuType}Auxiliary`)
|
|
337
447
|
: () => null
|
|
338
448
|
Auxiliary.displayName = `${MenuType}Auxiliary`
|
|
339
449
|
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
450
|
+
// on Android, provide NativeMenuContext so components use Gesture.Manual()
|
|
451
|
+
// instead of Gesture.Tap() (which sends ACTION_CANCEL to MenuView)
|
|
452
|
+
const Menu: FC<NativeMenuProps> = ({ children, onOpenChange, onOpenWillChange }) => {
|
|
453
|
+
const triggerOwnerRef = React.useRef<object | null>(null)
|
|
454
|
+
const claimTriggerBoundary = React.useCallback((debugName?: string | null) => {
|
|
455
|
+
if (triggerOwnerRef.current) {
|
|
456
|
+
unstable_releaseExternalPressOwnership(triggerOwnerRef.current, debugName)
|
|
457
|
+
}
|
|
458
|
+
triggerOwnerRef.current = unstable_claimExternalPressOwnership(debugName)
|
|
459
|
+
}, [])
|
|
460
|
+
|
|
461
|
+
const releaseTriggerBoundary = React.useCallback((debugName?: string | null) => {
|
|
462
|
+
if (!triggerOwnerRef.current) return
|
|
463
|
+
unstable_releaseExternalPressOwnership(triggerOwnerRef.current, debugName)
|
|
464
|
+
triggerOwnerRef.current = null
|
|
465
|
+
}, [])
|
|
466
|
+
|
|
467
|
+
React.useEffect(() => releaseTriggerBoundary, [releaseTriggerBoundary])
|
|
468
|
+
|
|
469
|
+
const z = resolve()
|
|
470
|
+
if (!z) return null
|
|
471
|
+
|
|
472
|
+
const handleOpenChange = React.useCallback(
|
|
473
|
+
(isOpen: boolean) => {
|
|
474
|
+
if (!isOpen) {
|
|
475
|
+
releaseTriggerBoundary()
|
|
476
|
+
}
|
|
477
|
+
onOpenChange?.(isOpen)
|
|
478
|
+
},
|
|
479
|
+
[onOpenChange, releaseTriggerBoundary]
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
const handleOpenWillChange = React.useCallback(
|
|
483
|
+
(willOpen: boolean) => {
|
|
484
|
+
if (!willOpen) {
|
|
485
|
+
releaseTriggerBoundary()
|
|
486
|
+
}
|
|
487
|
+
onOpenWillChange?.(willOpen)
|
|
488
|
+
},
|
|
489
|
+
[onOpenWillChange, releaseTriggerBoundary]
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
const rootProps: Record<string, unknown> = { onOpenChange: handleOpenChange }
|
|
343
493
|
if (isContextMenu && onOpenWillChange) {
|
|
344
|
-
rootProps.onOpenWillChange =
|
|
494
|
+
rootProps.onOpenWillChange = handleOpenWillChange
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const content = (
|
|
498
|
+
<z.menu.Root {...rootProps}>
|
|
499
|
+
{transformChildren(z.menu, z.componentMap, children, false, {
|
|
500
|
+
claim: claimTriggerBoundary,
|
|
501
|
+
release: releaseTriggerBoundary,
|
|
502
|
+
})}
|
|
503
|
+
</z.menu.Root>
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
if (isAndroid) {
|
|
507
|
+
return (
|
|
508
|
+
<NativeMenuContext.Provider value={true}>{content}</NativeMenuContext.Provider>
|
|
509
|
+
)
|
|
345
510
|
}
|
|
346
511
|
|
|
347
|
-
return
|
|
512
|
+
return content
|
|
348
513
|
}
|
|
349
514
|
Menu.displayName = MenuType
|
|
350
515
|
|
|
351
|
-
// ===========================================
|
|
352
|
-
// Export
|
|
353
|
-
// ===========================================
|
|
354
|
-
|
|
355
516
|
return {
|
|
356
517
|
Menu: withStaticProperties(Menu, {
|
|
357
518
|
Trigger,
|