@react-native-reusables/cli 0.0.9 → 0.0.10

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 (136) hide show
  1. package/dist/generated/components/primitives/accordion/accordion.tsx +216 -0
  2. package/dist/generated/components/primitives/accordion/accordion.web.tsx +295 -0
  3. package/dist/generated/components/primitives/accordion/index.ts +1 -0
  4. package/dist/generated/components/primitives/accordion/types.ts +45 -0
  5. package/dist/generated/components/primitives/alert-dialog/alert-dialog.tsx +237 -0
  6. package/dist/generated/components/primitives/alert-dialog/alert-dialog.web.tsx +256 -0
  7. package/dist/generated/components/primitives/alert-dialog/index.ts +1 -0
  8. package/dist/generated/components/primitives/alert-dialog/types.ts +48 -0
  9. package/dist/generated/components/primitives/aspect-ratio.tsx +23 -0
  10. package/dist/generated/components/primitives/avatar/ types.ts +10 -0
  11. package/dist/generated/components/primitives/avatar/index.tsx +95 -0
  12. package/dist/generated/components/primitives/checkbox/checkbox.tsx +101 -0
  13. package/dist/generated/components/primitives/checkbox/checkbox.web.tsx +114 -0
  14. package/dist/generated/components/primitives/checkbox/index.ts +1 -0
  15. package/dist/generated/components/primitives/checkbox/types.ts +11 -0
  16. package/dist/generated/components/primitives/collapsible/collapsible.tsx +119 -0
  17. package/dist/generated/components/primitives/collapsible/collapsible.web.tsx +157 -0
  18. package/dist/generated/components/primitives/collapsible/index.ts +1 -0
  19. package/dist/generated/components/primitives/collapsible/types.ts +18 -0
  20. package/dist/generated/components/primitives/context-menu/context-menu.tsx +626 -0
  21. package/dist/generated/components/primitives/context-menu/context-menu.web.tsx +504 -0
  22. package/dist/generated/components/primitives/context-menu/index.ts +1 -0
  23. package/dist/generated/components/primitives/context-menu/types.ts +82 -0
  24. package/dist/generated/components/primitives/dialog/dialog.tsx +211 -0
  25. package/dist/generated/components/primitives/dialog/dialog.web.tsx +197 -0
  26. package/dist/generated/components/primitives/dialog/index.ts +1 -0
  27. package/dist/generated/components/primitives/dialog/types.ts +60 -0
  28. package/dist/generated/components/primitives/dropdown-menu/dropdown-menu.tsx +584 -0
  29. package/dist/generated/components/primitives/dropdown-menu/dropdown-menu.web.tsx +521 -0
  30. package/dist/generated/components/primitives/dropdown-menu/index.ts +1 -0
  31. package/dist/generated/components/primitives/dropdown-menu/types.ts +71 -0
  32. package/dist/generated/components/primitives/hooks/index.ts +3 -0
  33. package/dist/generated/components/primitives/hooks/useAugmentedRef.tsx +29 -0
  34. package/dist/generated/components/primitives/hooks/useControllableState.tsx +75 -0
  35. package/dist/generated/components/primitives/hooks/useRelativePosition.tsx +227 -0
  36. package/dist/generated/components/primitives/hover-card/hover-card.tsx +271 -0
  37. package/dist/generated/components/primitives/hover-card/hover-card.web.tsx +145 -0
  38. package/dist/generated/components/primitives/hover-card/index.ts +1 -0
  39. package/dist/generated/components/primitives/hover-card/types.ts +42 -0
  40. package/dist/generated/components/primitives/label/index.ts +1 -0
  41. package/dist/generated/components/primitives/label/label.tsx +31 -0
  42. package/dist/generated/components/primitives/label/label.web.tsx +36 -0
  43. package/dist/generated/components/primitives/label/types.ts +15 -0
  44. package/dist/generated/components/primitives/menubar/index.ts +1 -0
  45. package/dist/generated/components/primitives/menubar/menubar.tsx +624 -0
  46. package/dist/generated/components/primitives/menubar/menubar.web.tsx +543 -0
  47. package/dist/generated/components/primitives/menubar/types.ts +76 -0
  48. package/dist/generated/components/primitives/navigation-menu/index.ts +1 -0
  49. package/dist/generated/components/primitives/navigation-menu/navigation-menu.tsx +315 -0
  50. package/dist/generated/components/primitives/navigation-menu/navigation-menu.web.tsx +264 -0
  51. package/dist/generated/components/primitives/navigation-menu/types.ts +49 -0
  52. package/dist/generated/components/primitives/popover/index.ts +1 -0
  53. package/dist/generated/components/primitives/popover/popover.tsx +286 -0
  54. package/dist/generated/components/primitives/popover/popover.web.tsx +179 -0
  55. package/dist/generated/components/primitives/popover/types.ts +30 -0
  56. package/dist/generated/components/primitives/portal.tsx +67 -0
  57. package/dist/generated/components/primitives/progress/index.ts +1 -0
  58. package/dist/generated/components/primitives/progress/progress.tsx +59 -0
  59. package/dist/generated/components/primitives/progress/progress.web.tsx +36 -0
  60. package/dist/generated/components/primitives/progress/types.ts +7 -0
  61. package/dist/generated/components/primitives/radio-group/index.ts +1 -0
  62. package/dist/generated/components/primitives/radio-group/radio-group.tsx +116 -0
  63. package/dist/generated/components/primitives/radio-group/radio-group.web.tsx +78 -0
  64. package/dist/generated/components/primitives/radio-group/types.ts +15 -0
  65. package/dist/generated/components/primitives/select/index.ts +1 -0
  66. package/dist/generated/components/primitives/select/select.tsx +455 -0
  67. package/dist/generated/components/primitives/select/select.web.tsx +319 -0
  68. package/dist/generated/components/primitives/select/types.ts +87 -0
  69. package/dist/generated/components/primitives/separator/ types.ts +6 -0
  70. package/dist/generated/components/primitives/separator/index.tsx +23 -0
  71. package/dist/generated/components/primitives/slider/index.ts +1 -0
  72. package/dist/generated/components/primitives/slider/slider.tsx +89 -0
  73. package/dist/generated/components/primitives/slider/slider.web.tsx +67 -0
  74. package/dist/generated/components/primitives/slider/types.ts +24 -0
  75. package/dist/generated/components/primitives/slot.tsx +187 -0
  76. package/dist/generated/components/primitives/switch/index.ts +1 -0
  77. package/dist/generated/components/primitives/switch/switch.tsx +65 -0
  78. package/dist/generated/components/primitives/switch/switch.web.tsx +67 -0
  79. package/dist/generated/components/primitives/switch/types.ts +11 -0
  80. package/dist/generated/components/primitives/table.tsx +55 -0
  81. package/dist/generated/components/primitives/tabs/index.ts +1 -0
  82. package/dist/generated/components/primitives/tabs/tabs.tsx +133 -0
  83. package/dist/generated/components/primitives/tabs/tabs.web.tsx +97 -0
  84. package/dist/generated/components/primitives/tabs/types.ts +24 -0
  85. package/dist/generated/components/primitives/toast/ types.ts +7 -0
  86. package/dist/generated/components/primitives/toast/index.tsx +128 -0
  87. package/dist/generated/components/primitives/toggle/index.ts +1 -0
  88. package/dist/generated/components/primitives/toggle/toggle.tsx +37 -0
  89. package/dist/generated/components/primitives/toggle/toggle.web.tsx +26 -0
  90. package/dist/generated/components/primitives/toggle/types.ts +7 -0
  91. package/dist/generated/components/primitives/toggle-group/index.ts +1 -0
  92. package/dist/generated/components/primitives/toggle-group/toggle-group.tsx +125 -0
  93. package/dist/generated/components/primitives/toggle-group/toggle-group.web.tsx +124 -0
  94. package/dist/generated/components/primitives/toggle-group/types.ts +37 -0
  95. package/dist/generated/components/primitives/toolbar/index.ts +1 -0
  96. package/dist/generated/components/primitives/toolbar/toolbar.tsx +125 -0
  97. package/dist/generated/components/primitives/toolbar/toolbar.web.tsx +129 -0
  98. package/dist/generated/components/primitives/toolbar/types.ts +39 -0
  99. package/dist/generated/components/primitives/tooltip/index.ts +1 -0
  100. package/dist/generated/components/primitives/tooltip/tooltip.tsx +271 -0
  101. package/dist/generated/components/primitives/tooltip/tooltip.web.tsx +167 -0
  102. package/dist/generated/components/primitives/tooltip/types.ts +44 -0
  103. package/dist/generated/components/primitives/types.ts +105 -0
  104. package/dist/generated/components/primitives/utils.ts +61 -0
  105. package/dist/generated/components/ui/accordion.tsx +127 -0
  106. package/dist/generated/components/ui/alert-dialog.tsx +167 -0
  107. package/dist/generated/components/ui/aspect-ratio.tsx +5 -0
  108. package/dist/generated/components/ui/avatar.tsx +44 -0
  109. package/dist/generated/components/ui/badge.tsx +51 -0
  110. package/dist/generated/components/ui/button.tsx +88 -0
  111. package/dist/generated/components/ui/card.tsx +67 -0
  112. package/dist/generated/components/ui/checkbox.tsx +34 -0
  113. package/dist/generated/components/ui/collapsible.tsx +9 -0
  114. package/dist/generated/components/ui/context-menu.tsx +244 -0
  115. package/dist/generated/components/ui/dialog.tsx +150 -0
  116. package/dist/generated/components/ui/dropdown-menu.tsx +244 -0
  117. package/dist/generated/components/ui/hover-card.tsx +45 -0
  118. package/dist/generated/components/ui/input.tsx +26 -0
  119. package/dist/generated/components/ui/label.tsx +28 -0
  120. package/dist/generated/components/ui/menubar.tsx +260 -0
  121. package/dist/generated/components/ui/navigation-menu.tsx +177 -0
  122. package/dist/generated/components/ui/popover.tsx +39 -0
  123. package/dist/generated/components/ui/radio-group.tsx +38 -0
  124. package/dist/generated/components/ui/select.tsx +181 -0
  125. package/dist/generated/components/ui/separator.tsx +23 -0
  126. package/dist/generated/components/ui/skeleton.tsx +39 -0
  127. package/dist/generated/components/ui/switch.tsx +97 -0
  128. package/dist/generated/components/ui/table.tsx +99 -0
  129. package/dist/generated/components/ui/tabs.tsx +65 -0
  130. package/dist/generated/components/ui/text.tsx +24 -0
  131. package/dist/generated/components/ui/textarea.tsx +28 -0
  132. package/dist/generated/components/ui/toggle-group.tsx +86 -0
  133. package/dist/generated/components/ui/toggle.tsx +85 -0
  134. package/dist/generated/components/ui/tooltip.tsx +36 -0
  135. package/dist/generated/components/ui/typography.tsx +204 -0
  136. package/package.json +8 -8
@@ -0,0 +1,584 @@
1
+ import * as React from 'react';
2
+ import {
3
+ BackHandler,
4
+ Pressable,
5
+ Text,
6
+ View,
7
+ type GestureResponderEvent,
8
+ type LayoutChangeEvent,
9
+ type LayoutRectangle,
10
+ } from 'react-native';
11
+ import { useRelativePosition, type LayoutPosition } from '@rnr/hooks';
12
+ import { Portal as RNPPortal } from '@rnr/portal';
13
+ import * as Slot from '@rnr/slot';
14
+ import type {
15
+ ForceMountable,
16
+ PositionedContentProps,
17
+ PressableRef,
18
+ SlottablePressableProps,
19
+ SlottableTextProps,
20
+ SlottableViewProps,
21
+ TextRef,
22
+ ViewRef,
23
+ } from '@rnr/types';
24
+ import type {
25
+ DropdownMenuCheckboxItemProps,
26
+ DropdownMenuItemProps,
27
+ DropdownMenuOverlayProps,
28
+ DropdownMenuPortalProps,
29
+ DropdownMenuRadioGroupProps,
30
+ DropdownMenuRadioItemProps,
31
+ DropdownMenuRootProps,
32
+ DropdownMenuSeparatorProps,
33
+ DropdownMenuSubProps,
34
+ DropdownMenuSubTriggerProps,
35
+ } from './types';
36
+
37
+ interface IRootContext extends DropdownMenuRootProps {
38
+ triggerPosition: LayoutPosition | null;
39
+ setTriggerPosition: (triggerPosition: LayoutPosition | null) => void;
40
+ contentLayout: LayoutRectangle | null;
41
+ setContentLayout: (contentLayout: LayoutRectangle | null) => void;
42
+ nativeID: string;
43
+ }
44
+
45
+ const RootContext = React.createContext<IRootContext | null>(null);
46
+
47
+ const Root = React.forwardRef<ViewRef, SlottableViewProps & DropdownMenuRootProps>(
48
+ ({ asChild, open, onOpenChange, ...viewProps }, ref) => {
49
+ const nativeID = React.useId();
50
+ const [triggerPosition, setTriggerPosition] = React.useState<LayoutPosition | null>(null);
51
+ const [contentLayout, setContentLayout] = React.useState<LayoutRectangle | null>(null);
52
+
53
+ const Component = asChild ? Slot.View : View;
54
+ return (
55
+ <RootContext.Provider
56
+ value={{
57
+ open,
58
+ onOpenChange,
59
+ contentLayout,
60
+ setContentLayout,
61
+ nativeID,
62
+ setTriggerPosition,
63
+ triggerPosition,
64
+ }}
65
+ >
66
+ <Component ref={ref} {...viewProps} />
67
+ </RootContext.Provider>
68
+ );
69
+ }
70
+ );
71
+
72
+ Root.displayName = 'RootNativeDropdownMenu';
73
+
74
+ function useRootContext() {
75
+ const context = React.useContext(RootContext);
76
+ if (!context) {
77
+ throw new Error(
78
+ 'DropdownMenu compound components cannot be rendered outside the DropdownMenu component'
79
+ );
80
+ }
81
+ return context;
82
+ }
83
+
84
+ const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>(
85
+ ({ asChild, onPress: onPressProp, disabled = false, ...props }, ref) => {
86
+ const triggerRef = React.useRef<View>(null);
87
+ const { open, onOpenChange, setTriggerPosition } = useRootContext();
88
+
89
+ React.useImperativeHandle(
90
+ ref,
91
+ () => {
92
+ if (!triggerRef.current) {
93
+ return new View({});
94
+ }
95
+ return triggerRef.current;
96
+ },
97
+ [triggerRef.current]
98
+ );
99
+
100
+ function onPress(ev: GestureResponderEvent) {
101
+ if (disabled) return;
102
+ triggerRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
103
+ setTriggerPosition({ width, pageX, pageY: pageY, height });
104
+ });
105
+ const newValue = !open;
106
+ onOpenChange(newValue);
107
+ onPressProp?.(ev);
108
+ }
109
+
110
+ const Component = asChild ? Slot.Pressable : Pressable;
111
+ return (
112
+ <Component
113
+ ref={triggerRef}
114
+ aria-disabled={disabled ?? undefined}
115
+ role='button'
116
+ onPress={onPress}
117
+ disabled={disabled ?? undefined}
118
+ aria-expanded={open}
119
+ {...props}
120
+ />
121
+ );
122
+ }
123
+ );
124
+
125
+ Trigger.displayName = 'TriggerNativeDropdownMenu';
126
+
127
+ /**
128
+ * @warning when using a custom `<PortalHost />`, you might have to adjust the Content's sideOffset to account for nav elements like headers.
129
+ */
130
+ function Portal({ forceMount, hostName, children }: DropdownMenuPortalProps) {
131
+ const value = useRootContext();
132
+
133
+ if (!value.triggerPosition) {
134
+ return null;
135
+ }
136
+
137
+ if (!forceMount) {
138
+ if (!value.open) {
139
+ return null;
140
+ }
141
+ }
142
+
143
+ return (
144
+ <RNPPortal hostName={hostName} name={`${value.nativeID}_portal`}>
145
+ <RootContext.Provider value={value}>{children}</RootContext.Provider>
146
+ </RNPPortal>
147
+ );
148
+ }
149
+
150
+ const Overlay = React.forwardRef<PressableRef, SlottablePressableProps & DropdownMenuOverlayProps>(
151
+ ({ asChild, forceMount, onPress: OnPressProp, closeOnPress = true, ...props }, ref) => {
152
+ const { open, onOpenChange, setContentLayout, setTriggerPosition } = useRootContext();
153
+
154
+ function onPress(ev: GestureResponderEvent) {
155
+ if (closeOnPress) {
156
+ setTriggerPosition(null);
157
+ setContentLayout(null);
158
+ onOpenChange(false);
159
+ }
160
+ OnPressProp?.(ev);
161
+ }
162
+
163
+ if (!forceMount) {
164
+ if (!open) {
165
+ return null;
166
+ }
167
+ }
168
+
169
+ const Component = asChild ? Slot.Pressable : Pressable;
170
+ return <Component ref={ref} onPress={onPress} {...props} />;
171
+ }
172
+ );
173
+
174
+ Overlay.displayName = 'OverlayNativeDropdownMenu';
175
+
176
+ /**
177
+ * @info `position`, `top`, `left`, and `maxWidth` style properties are controlled internally. Opt out of this behavior by setting `disablePositioningStyle` to `true`.
178
+ */
179
+ const Content = React.forwardRef<PressableRef, SlottablePressableProps & PositionedContentProps>(
180
+ (
181
+ {
182
+ asChild = false,
183
+ forceMount,
184
+ align = 'start',
185
+ side = 'bottom',
186
+ sideOffset = 0,
187
+ alignOffset = 0,
188
+ avoidCollisions = true,
189
+ onLayout: onLayoutProp,
190
+ insets,
191
+ style,
192
+ disablePositioningStyle,
193
+ ...props
194
+ },
195
+ ref
196
+ ) => {
197
+ const {
198
+ open,
199
+ onOpenChange,
200
+ nativeID,
201
+ triggerPosition,
202
+ setTriggerPosition,
203
+ contentLayout,
204
+ setContentLayout,
205
+ } = useRootContext();
206
+
207
+ React.useEffect(() => {
208
+ const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
209
+ setTriggerPosition(null);
210
+ setContentLayout(null);
211
+ onOpenChange(false);
212
+ return true;
213
+ });
214
+
215
+ return () => {
216
+ setContentLayout(null);
217
+ backHandler.remove();
218
+ };
219
+ }, []);
220
+
221
+ const positionStyle = useRelativePosition({
222
+ align,
223
+ avoidCollisions,
224
+ triggerPosition,
225
+ contentLayout,
226
+ alignOffset,
227
+ insets,
228
+ sideOffset,
229
+ side,
230
+ disablePositioningStyle,
231
+ });
232
+
233
+ function onLayout(event: LayoutChangeEvent) {
234
+ setContentLayout(event.nativeEvent.layout);
235
+ onLayoutProp?.(event);
236
+ }
237
+
238
+ if (!forceMount) {
239
+ if (!open) {
240
+ return null;
241
+ }
242
+ }
243
+
244
+ const Component = asChild ? Slot.Pressable : Pressable;
245
+ return (
246
+ <Component
247
+ ref={ref}
248
+ role='menu'
249
+ nativeID={nativeID}
250
+ aria-modal={true}
251
+ style={[positionStyle, style]}
252
+ onLayout={onLayout}
253
+ {...props}
254
+ />
255
+ );
256
+ }
257
+ );
258
+
259
+ Content.displayName = 'ContentNativeDropdownMenu';
260
+
261
+ const Item = React.forwardRef<PressableRef, SlottablePressableProps & DropdownMenuItemProps>(
262
+ (
263
+ { asChild, textValue, onPress: onPressProp, disabled = false, closeOnPress = true, ...props },
264
+ ref
265
+ ) => {
266
+ const { onOpenChange, setTriggerPosition, setContentLayout } = useRootContext();
267
+
268
+ function onPress(ev: GestureResponderEvent) {
269
+ if (closeOnPress) {
270
+ setTriggerPosition(null);
271
+ setContentLayout(null);
272
+ onOpenChange(false);
273
+ }
274
+ onPressProp?.(ev);
275
+ }
276
+
277
+ const Component = asChild ? Slot.Pressable : Pressable;
278
+ return (
279
+ <Component
280
+ ref={ref}
281
+ role='menuitem'
282
+ onPress={onPress}
283
+ disabled={disabled}
284
+ aria-valuetext={textValue}
285
+ aria-disabled={!!disabled}
286
+ accessibilityState={{ disabled: !!disabled }}
287
+ {...props}
288
+ />
289
+ );
290
+ }
291
+ );
292
+
293
+ Item.displayName = 'ItemNativeDropdownMenu';
294
+
295
+ const Group = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
296
+ const Component = asChild ? Slot.View : View;
297
+ return <Component ref={ref} role='group' {...props} />;
298
+ });
299
+
300
+ Group.displayName = 'GroupNativeDropdownMenu';
301
+
302
+ const Label = React.forwardRef<TextRef, SlottableTextProps>(({ asChild, ...props }, ref) => {
303
+ const Component = asChild ? Slot.Text : Text;
304
+ return <Component ref={ref} {...props} />;
305
+ });
306
+
307
+ Label.displayName = 'LabelNativeDropdownMenu';
308
+
309
+ type FormItemContext =
310
+ | { checked: boolean }
311
+ | {
312
+ value: string | undefined;
313
+ onValueChange: (value: string) => void;
314
+ };
315
+
316
+ const FormItemContext = React.createContext<FormItemContext | null>(null);
317
+
318
+ const CheckboxItem = React.forwardRef<
319
+ PressableRef,
320
+ SlottablePressableProps & DropdownMenuCheckboxItemProps
321
+ >(
322
+ (
323
+ {
324
+ asChild,
325
+ checked,
326
+ onCheckedChange,
327
+ textValue,
328
+ onPress: onPressProp,
329
+ closeOnPress = true,
330
+ disabled = false,
331
+ ...props
332
+ },
333
+ ref
334
+ ) => {
335
+ const { onOpenChange, setContentLayout, setTriggerPosition, nativeID } = useRootContext();
336
+
337
+ function onPress(ev: GestureResponderEvent) {
338
+ onCheckedChange(!checked);
339
+ if (closeOnPress) {
340
+ setTriggerPosition(null);
341
+ setContentLayout(null);
342
+ onOpenChange(false);
343
+ }
344
+ onPressProp?.(ev);
345
+ }
346
+
347
+ const Component = asChild ? Slot.Pressable : Pressable;
348
+ return (
349
+ <FormItemContext.Provider value={{ checked }}>
350
+ <Component
351
+ ref={ref}
352
+ key={`checkbox-${nativeID}-${checked}`}
353
+ role='checkbox'
354
+ aria-checked={checked}
355
+ onPress={onPress}
356
+ disabled={disabled}
357
+ aria-disabled={!!disabled}
358
+ aria-valuetext={textValue}
359
+ accessibilityState={{ disabled: !!disabled }}
360
+ {...props}
361
+ />
362
+ </FormItemContext.Provider>
363
+ );
364
+ }
365
+ );
366
+
367
+ CheckboxItem.displayName = 'CheckboxItemNativeDropdownMenu';
368
+
369
+ function useFormItemContext() {
370
+ const context = React.useContext(FormItemContext);
371
+ if (!context) {
372
+ throw new Error(
373
+ 'CheckboxItem or RadioItem compound components cannot be rendered outside of a CheckboxItem or RadioItem component'
374
+ );
375
+ }
376
+ return context;
377
+ }
378
+
379
+ const RadioGroup = React.forwardRef<ViewRef, SlottableViewProps & DropdownMenuRadioGroupProps>(
380
+ ({ asChild, value, onValueChange, ...props }, ref) => {
381
+ const Component = asChild ? Slot.View : View;
382
+ return (
383
+ <FormItemContext.Provider value={{ value, onValueChange }}>
384
+ <Component ref={ref} role='radiogroup' {...props} />
385
+ </FormItemContext.Provider>
386
+ );
387
+ }
388
+ );
389
+
390
+ RadioGroup.displayName = 'RadioGroupNativeDropdownMenu';
391
+
392
+ type BothFormItemContext = Exclude<FormItemContext, { checked: boolean }> & {
393
+ checked: boolean;
394
+ };
395
+
396
+ const RadioItemContext = React.createContext({} as { itemValue: string });
397
+
398
+ const RadioItem = React.forwardRef<
399
+ PressableRef,
400
+ SlottablePressableProps & DropdownMenuRadioItemProps
401
+ >(
402
+ (
403
+ {
404
+ asChild,
405
+ value: itemValue,
406
+ textValue,
407
+ onPress: onPressProp,
408
+ disabled = false,
409
+ closeOnPress = true,
410
+ ...props
411
+ },
412
+ ref
413
+ ) => {
414
+ const { onOpenChange, setContentLayout, setTriggerPosition } = useRootContext();
415
+
416
+ const { value, onValueChange } = useFormItemContext() as BothFormItemContext;
417
+ function onPress(ev: GestureResponderEvent) {
418
+ onValueChange(itemValue);
419
+ if (closeOnPress) {
420
+ setTriggerPosition(null);
421
+ setContentLayout(null);
422
+ onOpenChange(false);
423
+ }
424
+ onPressProp?.(ev);
425
+ }
426
+
427
+ const Component = asChild ? Slot.Pressable : Pressable;
428
+ return (
429
+ <RadioItemContext.Provider value={{ itemValue }}>
430
+ <Component
431
+ ref={ref}
432
+ onPress={onPress}
433
+ role='radio'
434
+ aria-checked={value === itemValue}
435
+ disabled={disabled ?? false}
436
+ accessibilityState={{
437
+ disabled: disabled ?? false,
438
+ checked: value === itemValue,
439
+ }}
440
+ aria-valuetext={textValue}
441
+ {...props}
442
+ />
443
+ </RadioItemContext.Provider>
444
+ );
445
+ }
446
+ );
447
+
448
+ RadioItem.displayName = 'RadioItemNativeDropdownMenu';
449
+
450
+ function useItemIndicatorContext() {
451
+ return React.useContext(RadioItemContext);
452
+ }
453
+
454
+ const ItemIndicator = React.forwardRef<ViewRef, SlottableViewProps & ForceMountable>(
455
+ ({ asChild, forceMount, ...props }, ref) => {
456
+ const { itemValue } = useItemIndicatorContext();
457
+ const { checked, value } = useFormItemContext() as BothFormItemContext;
458
+
459
+ if (!forceMount) {
460
+ if (itemValue == null && !checked) {
461
+ return null;
462
+ }
463
+ if (value !== itemValue) {
464
+ return null;
465
+ }
466
+ }
467
+ const Component = asChild ? Slot.View : View;
468
+ return <Component ref={ref} role='presentation' {...props} />;
469
+ }
470
+ );
471
+
472
+ ItemIndicator.displayName = 'ItemIndicatorNativeDropdownMenu';
473
+
474
+ const Separator = React.forwardRef<ViewRef, SlottableViewProps & DropdownMenuSeparatorProps>(
475
+ ({ asChild, decorative, ...props }, ref) => {
476
+ const Component = asChild ? Slot.View : View;
477
+ return <Component role={decorative ? 'presentation' : 'separator'} ref={ref} {...props} />;
478
+ }
479
+ );
480
+
481
+ Separator.displayName = 'SeparatorNativeDropdownMenu';
482
+
483
+ const SubContext = React.createContext<{
484
+ nativeID: string;
485
+ open: boolean;
486
+ onOpenChange: (value: boolean) => void;
487
+ } | null>(null);
488
+
489
+ const Sub = React.forwardRef<ViewRef, SlottableViewProps & DropdownMenuSubProps>(
490
+ ({ asChild, open, onOpenChange, ...props }, ref) => {
491
+ const nativeID = React.useId();
492
+
493
+ const Component = asChild ? Slot.View : View;
494
+ return (
495
+ <SubContext.Provider
496
+ value={{
497
+ nativeID,
498
+ open,
499
+ onOpenChange,
500
+ }}
501
+ >
502
+ <Component ref={ref} {...props} />
503
+ </SubContext.Provider>
504
+ );
505
+ }
506
+ );
507
+
508
+ Sub.displayName = 'SubNativeDropdownMenu';
509
+
510
+ function useSubContext() {
511
+ const context = React.useContext(SubContext);
512
+ if (!context) {
513
+ throw new Error('Sub compound components cannot be rendered outside of a Sub component');
514
+ }
515
+ return context;
516
+ }
517
+
518
+ const SubTrigger = React.forwardRef<
519
+ PressableRef,
520
+ SlottablePressableProps & DropdownMenuSubTriggerProps
521
+ >(({ asChild, textValue, onPress: onPressProp, disabled = false, ...props }, ref) => {
522
+ const { nativeID, open, onOpenChange } = useSubContext();
523
+
524
+ function onPress(ev: GestureResponderEvent) {
525
+ onOpenChange(!open);
526
+ onPressProp?.(ev);
527
+ }
528
+
529
+ const Component = asChild ? Slot.Pressable : Pressable;
530
+ return (
531
+ <Component
532
+ ref={ref}
533
+ aria-valuetext={textValue}
534
+ role='menuitem'
535
+ aria-expanded={open}
536
+ accessibilityState={{ expanded: open, disabled: !!disabled }}
537
+ nativeID={nativeID}
538
+ onPress={onPress}
539
+ disabled={disabled}
540
+ aria-disabled={!!disabled}
541
+ {...props}
542
+ />
543
+ );
544
+ });
545
+
546
+ SubTrigger.displayName = 'SubTriggerNativeDropdownMenu';
547
+
548
+ const SubContent = React.forwardRef<PressableRef, SlottablePressableProps & ForceMountable>(
549
+ ({ asChild = false, forceMount, ...props }, ref) => {
550
+ const { open, nativeID } = useSubContext();
551
+
552
+ if (!forceMount) {
553
+ if (!open) {
554
+ return null;
555
+ }
556
+ }
557
+
558
+ const Component = asChild ? Slot.Pressable : Pressable;
559
+ return <Component ref={ref} role='group' aria-labelledby={nativeID} {...props} />;
560
+ }
561
+ );
562
+
563
+ Content.displayName = 'ContentNativeDropdownMenu';
564
+
565
+ export {
566
+ CheckboxItem,
567
+ Content,
568
+ Group,
569
+ Item,
570
+ ItemIndicator,
571
+ Label,
572
+ Overlay,
573
+ Portal,
574
+ RadioGroup,
575
+ RadioItem,
576
+ Root,
577
+ Separator,
578
+ Sub,
579
+ SubContent,
580
+ SubTrigger,
581
+ Trigger,
582
+ useRootContext,
583
+ useSubContext,
584
+ };