@frosted-ui/react-native 0.0.1-canary.100

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 (207) hide show
  1. package/README.md +160 -0
  2. package/dist/components/accordion.d.ts +21 -0
  3. package/dist/components/accordion.d.ts.map +1 -0
  4. package/dist/components/accordion.js +94 -0
  5. package/dist/components/accordion.js.map +1 -0
  6. package/dist/components/alert-dialog.d.ts +67 -0
  7. package/dist/components/alert-dialog.d.ts.map +1 -0
  8. package/dist/components/alert-dialog.js +170 -0
  9. package/dist/components/alert-dialog.js.map +1 -0
  10. package/dist/components/aspect-ratio.d.ts +4 -0
  11. package/dist/components/aspect-ratio.d.ts.map +1 -0
  12. package/dist/components/aspect-ratio.js +4 -0
  13. package/dist/components/aspect-ratio.js.map +1 -0
  14. package/dist/components/avatar.d.ts +23 -0
  15. package/dist/components/avatar.d.ts.map +1 -0
  16. package/dist/components/avatar.js +128 -0
  17. package/dist/components/avatar.js.map +1 -0
  18. package/dist/components/badge.d.ts +15 -0
  19. package/dist/components/badge.d.ts.map +1 -0
  20. package/dist/components/badge.js +81 -0
  21. package/dist/components/badge.js.map +1 -0
  22. package/dist/components/button.d.ts +14 -0
  23. package/dist/components/button.d.ts.map +1 -0
  24. package/dist/components/button.js +81 -0
  25. package/dist/components/button.js.map +1 -0
  26. package/dist/components/callout.d.ts +23 -0
  27. package/dist/components/callout.d.ts.map +1 -0
  28. package/dist/components/callout.js +128 -0
  29. package/dist/components/callout.js.map +1 -0
  30. package/dist/components/card.d.ts +9 -0
  31. package/dist/components/card.d.ts.map +1 -0
  32. package/dist/components/card.js +41 -0
  33. package/dist/components/card.js.map +1 -0
  34. package/dist/components/checkbox.d.ts +12 -0
  35. package/dist/components/checkbox.d.ts.map +1 -0
  36. package/dist/components/checkbox.js +100 -0
  37. package/dist/components/checkbox.js.map +1 -0
  38. package/dist/components/circular-progress.d.ts +21 -0
  39. package/dist/components/circular-progress.d.ts.map +1 -0
  40. package/dist/components/circular-progress.js +78 -0
  41. package/dist/components/circular-progress.js.map +1 -0
  42. package/dist/components/code.d.ts +18 -0
  43. package/dist/components/code.d.ts.map +1 -0
  44. package/dist/components/code.js +83 -0
  45. package/dist/components/code.js.map +1 -0
  46. package/dist/components/context-menu.d.ts +65 -0
  47. package/dist/components/context-menu.d.ts.map +1 -0
  48. package/dist/components/context-menu.js +441 -0
  49. package/dist/components/context-menu.js.map +1 -0
  50. package/dist/components/dialog.d.ts +49 -0
  51. package/dist/components/dialog.d.ts.map +1 -0
  52. package/dist/components/dialog.js +141 -0
  53. package/dist/components/dialog.js.map +1 -0
  54. package/dist/components/dropdown-menu.d.ts +65 -0
  55. package/dist/components/dropdown-menu.d.ts.map +1 -0
  56. package/dist/components/dropdown-menu.js +441 -0
  57. package/dist/components/dropdown-menu.js.map +1 -0
  58. package/dist/components/heading.d.ts +15 -0
  59. package/dist/components/heading.d.ts.map +1 -0
  60. package/dist/components/heading.js +8 -0
  61. package/dist/components/heading.js.map +1 -0
  62. package/dist/components/hover-card.d.ts +24 -0
  63. package/dist/components/hover-card.d.ts.map +1 -0
  64. package/dist/components/hover-card.js +49 -0
  65. package/dist/components/hover-card.js.map +1 -0
  66. package/dist/components/icon-button.d.ts +14 -0
  67. package/dist/components/icon-button.d.ts.map +1 -0
  68. package/dist/components/icon-button.js +81 -0
  69. package/dist/components/icon-button.js.map +1 -0
  70. package/dist/components/icon.d.ts +27 -0
  71. package/dist/components/icon.d.ts.map +1 -0
  72. package/dist/components/icon.js +30 -0
  73. package/dist/components/icon.js.map +1 -0
  74. package/dist/components/index.d.ts +37 -0
  75. package/dist/components/index.d.ts.map +1 -0
  76. package/dist/components/index.js +49 -0
  77. package/dist/components/index.js.map +1 -0
  78. package/dist/components/label.d.ts +8 -0
  79. package/dist/components/label.d.ts.map +1 -0
  80. package/dist/components/label.js +26 -0
  81. package/dist/components/label.js.map +1 -0
  82. package/dist/components/link.d.ts +19 -0
  83. package/dist/components/link.d.ts.map +1 -0
  84. package/dist/components/link.js +68 -0
  85. package/dist/components/link.js.map +1 -0
  86. package/dist/components/list.d.ts +37 -0
  87. package/dist/components/list.d.ts.map +1 -0
  88. package/dist/components/list.js +112 -0
  89. package/dist/components/list.js.map +1 -0
  90. package/dist/components/native-only-animated-view.d.ts +219 -0
  91. package/dist/components/native-only-animated-view.d.ts.map +1 -0
  92. package/dist/components/native-only-animated-view.js +26 -0
  93. package/dist/components/native-only-animated-view.js.map +1 -0
  94. package/dist/components/popover.d.ts +24 -0
  95. package/dist/components/popover.d.ts.map +1 -0
  96. package/dist/components/popover.js +52 -0
  97. package/dist/components/popover.js.map +1 -0
  98. package/dist/components/progress.d.ts +14 -0
  99. package/dist/components/progress.d.ts.map +1 -0
  100. package/dist/components/progress.js +52 -0
  101. package/dist/components/progress.js.map +1 -0
  102. package/dist/components/radio-group.d.ts +18 -0
  103. package/dist/components/radio-group.d.ts.map +1 -0
  104. package/dist/components/radio-group.js +122 -0
  105. package/dist/components/radio-group.js.map +1 -0
  106. package/dist/components/segmented-control.d.ts +21 -0
  107. package/dist/components/segmented-control.d.ts.map +1 -0
  108. package/dist/components/segmented-control.js +113 -0
  109. package/dist/components/segmented-control.js.map +1 -0
  110. package/dist/components/select.d.ts +58 -0
  111. package/dist/components/select.d.ts.map +1 -0
  112. package/dist/components/select.js +491 -0
  113. package/dist/components/select.js.map +1 -0
  114. package/dist/components/separator.d.ts +12 -0
  115. package/dist/components/separator.d.ts.map +1 -0
  116. package/dist/components/separator.js +47 -0
  117. package/dist/components/separator.js.map +1 -0
  118. package/dist/components/skeleton.d.ts +28 -0
  119. package/dist/components/skeleton.d.ts.map +1 -0
  120. package/dist/components/skeleton.js +137 -0
  121. package/dist/components/skeleton.js.map +1 -0
  122. package/dist/components/slider.d.ts +30 -0
  123. package/dist/components/slider.d.ts.map +1 -0
  124. package/dist/components/slider.js +248 -0
  125. package/dist/components/slider.js.map +1 -0
  126. package/dist/components/spinner.d.ts +17 -0
  127. package/dist/components/spinner.d.ts.map +1 -0
  128. package/dist/components/spinner.js +199 -0
  129. package/dist/components/spinner.js.map +1 -0
  130. package/dist/components/switch.d.ts +12 -0
  131. package/dist/components/switch.d.ts.map +1 -0
  132. package/dist/components/switch.js +188 -0
  133. package/dist/components/switch.js.map +1 -0
  134. package/dist/components/tabs.d.ts +26 -0
  135. package/dist/components/tabs.d.ts.map +1 -0
  136. package/dist/components/tabs.js +125 -0
  137. package/dist/components/tabs.js.map +1 -0
  138. package/dist/components/text-area.d.ts +16 -0
  139. package/dist/components/text-area.d.ts.map +1 -0
  140. package/dist/components/text-area.js +121 -0
  141. package/dist/components/text-area.js.map +1 -0
  142. package/dist/components/text-field.d.ts +35 -0
  143. package/dist/components/text-field.d.ts.map +1 -0
  144. package/dist/components/text-field.js +300 -0
  145. package/dist/components/text-field.js.map +1 -0
  146. package/dist/components/text.d.ts +23 -0
  147. package/dist/components/text.d.ts.map +1 -0
  148. package/dist/components/text.js +44 -0
  149. package/dist/components/text.js.map +1 -0
  150. package/dist/components/tooltip.d.ts +24 -0
  151. package/dist/components/tooltip.d.ts.map +1 -0
  152. package/dist/components/tooltip.js +63 -0
  153. package/dist/components/tooltip.js.map +1 -0
  154. package/dist/index.d.ts +9 -0
  155. package/dist/index.d.ts.map +1 -0
  156. package/dist/index.js +18 -0
  157. package/dist/index.js.map +1 -0
  158. package/dist/lib/button-styles.d.ts +13 -0
  159. package/dist/lib/button-styles.d.ts.map +1 -0
  160. package/dist/lib/button-styles.js +115 -0
  161. package/dist/lib/button-styles.js.map +1 -0
  162. package/dist/lib/color-utils.d.ts +26 -0
  163. package/dist/lib/color-utils.d.ts.map +1 -0
  164. package/dist/lib/color-utils.js +48 -0
  165. package/dist/lib/color-utils.js.map +1 -0
  166. package/dist/lib/dialog-styles.d.ts +42 -0
  167. package/dist/lib/dialog-styles.d.ts.map +1 -0
  168. package/dist/lib/dialog-styles.js +162 -0
  169. package/dist/lib/dialog-styles.js.map +1 -0
  170. package/dist/lib/full-window-overlay.d.ts +11 -0
  171. package/dist/lib/full-window-overlay.d.ts.map +1 -0
  172. package/dist/lib/full-window-overlay.js +16 -0
  173. package/dist/lib/full-window-overlay.js.map +1 -0
  174. package/dist/lib/panel-styles.d.ts +32 -0
  175. package/dist/lib/panel-styles.d.ts.map +1 -0
  176. package/dist/lib/panel-styles.js +96 -0
  177. package/dist/lib/panel-styles.js.map +1 -0
  178. package/dist/lib/text-input-styles.d.ts +36 -0
  179. package/dist/lib/text-input-styles.d.ts.map +1 -0
  180. package/dist/lib/text-input-styles.js +88 -0
  181. package/dist/lib/text-input-styles.js.map +1 -0
  182. package/dist/lib/theme-context.d.ts +80 -0
  183. package/dist/lib/theme-context.d.ts.map +1 -0
  184. package/dist/lib/theme-context.js +97 -0
  185. package/dist/lib/theme-context.js.map +1 -0
  186. package/dist/lib/theme-tokens.d.ts +222 -0
  187. package/dist/lib/theme-tokens.d.ts.map +1 -0
  188. package/dist/lib/theme-tokens.js +158 -0
  189. package/dist/lib/theme-tokens.js.map +1 -0
  190. package/dist/lib/theme.d.ts +40 -0
  191. package/dist/lib/theme.d.ts.map +1 -0
  192. package/dist/lib/theme.js +194 -0
  193. package/dist/lib/theme.js.map +1 -0
  194. package/dist/lib/types.d.ts +18 -0
  195. package/dist/lib/types.d.ts.map +1 -0
  196. package/dist/lib/types.js +2 -0
  197. package/dist/lib/types.js.map +1 -0
  198. package/dist/lib/use-theme-tokens.d.ts +593 -0
  199. package/dist/lib/use-theme-tokens.d.ts.map +1 -0
  200. package/dist/lib/use-theme-tokens.js +44 -0
  201. package/dist/lib/use-theme-tokens.js.map +1 -0
  202. package/docs/llm/COLOR_SYSTEM.md +799 -0
  203. package/docs/llm/COMPONENTS.md +1329 -0
  204. package/docs/llm/DESIGN_PATTERNS.md +2567 -0
  205. package/docs/llm/README.md +118 -0
  206. package/docs/llm/TYPOGRAPHY.md +516 -0
  207. package/package.json +106 -0
@@ -0,0 +1,141 @@
1
+ import { Heading } from '../components/heading';
2
+ import { Text } from '../components/text';
3
+ import { getDialogBackdropStyle, getDialogContentStyle, getDialogDescriptionSize, getDialogOverlayStyle, getDialogSizeStyles, getDialogTitleSize, } from '../lib/dialog-styles';
4
+ import { useThemeTokens } from '../lib/use-theme-tokens';
5
+ import * as DialogPrimitive from '@rn-primitives/dialog';
6
+ import * as React from 'react';
7
+ import { Platform, Pressable, StyleSheet, useWindowDimensions, View, } from 'react-native';
8
+ import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
9
+ import { FullWindowOverlay as RNFullWindowOverlay } from 'react-native-screens';
10
+ const DialogContentContext = React.createContext({
11
+ size: '3',
12
+ });
13
+ // ============================================================================
14
+ // Components
15
+ // ============================================================================
16
+ const FullWindowOverlay = Platform.OS === 'ios' ? RNFullWindowOverlay : React.Fragment;
17
+ const DialogRoot = (props) => <DialogPrimitive.Root {...props}/>;
18
+ DialogRoot.displayName = 'Dialog.Root';
19
+ const DialogTrigger = (props) => <DialogPrimitive.Trigger {...props} asChild/>;
20
+ DialogTrigger.displayName = 'Dialog.Trigger';
21
+ const DialogClose = (props) => <DialogPrimitive.Close {...props} asChild/>;
22
+ DialogClose.displayName = 'Dialog.Close';
23
+ // Overlay
24
+ function DialogOverlay({ children, ...props }) {
25
+ const overlayStyle = getDialogOverlayStyle();
26
+ const backdropStyle = getDialogBackdropStyle();
27
+ if (Platform.OS === 'web') {
28
+ return (<FullWindowOverlay>
29
+ <DialogPrimitive.Overlay style={overlayStyle} {...props}>
30
+ <View style={backdropStyle} pointerEvents="none"/>
31
+ {children}
32
+ </DialogPrimitive.Overlay>
33
+ </FullWindowOverlay>);
34
+ }
35
+ // Native: Use Pressable as direct child with asChild to handle onPress for dismissal
36
+ // The Pressable receives onPress from the primitive to close the dialog when backdrop is tapped
37
+ const nativeBackdropStyle = getDialogBackdropStyle();
38
+ return (<FullWindowOverlay>
39
+ <DialogPrimitive.Overlay {...props} asChild>
40
+ <Pressable style={overlayStyle}>
41
+ {/* Animated backdrop */}
42
+ <Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(150)} style={nativeBackdropStyle} pointerEvents="none"/>
43
+ {/* Animated content */}
44
+ <Animated.View entering={FadeIn.duration(200)} exiting={FadeOut.duration(150)}>
45
+ {children}
46
+ </Animated.View>
47
+ </Pressable>
48
+ </DialogPrimitive.Overlay>
49
+ </FullWindowOverlay>);
50
+ }
51
+ DialogOverlay.displayName = 'Dialog.Overlay';
52
+ function DialogContent({ size = '3', portalHost, children, style, ...props }) {
53
+ const { colors, isDark } = useThemeTokens();
54
+ const { width: windowWidth } = useWindowDimensions();
55
+ const contentStyle = getDialogContentStyle(size, colors, isDark, windowWidth, style);
56
+ const contextValue = React.useMemo(() => ({ size }), [size]);
57
+ // On web, flatten styles to avoid "indexed property setter" error
58
+ const finalStyle = Platform.OS === 'web'
59
+ ? StyleSheet.flatten([
60
+ contentStyle,
61
+ { animation: 'fui-dialog-content-show 400ms cubic-bezier(0.16, 1, 0.3, 1)' },
62
+ style,
63
+ ])
64
+ : [contentStyle, style];
65
+ return (<DialogPrimitive.Portal hostName={portalHost}>
66
+ <DialogOverlay>
67
+ <DialogPrimitive.Content style={finalStyle} {...props}>
68
+ <DialogContentContext.Provider value={contextValue}>
69
+ {children}
70
+ </DialogContentContext.Provider>
71
+ </DialogPrimitive.Content>
72
+ </DialogOverlay>
73
+ </DialogPrimitive.Portal>);
74
+ }
75
+ DialogContent.displayName = 'Dialog.Content';
76
+ function DialogTitle({ size: sizeProp, style, ...props }) {
77
+ const { size: contextSize } = React.useContext(DialogContentContext);
78
+ const size = sizeProp ?? getDialogTitleSize(contextSize);
79
+ const sizeStyles = getDialogSizeStyles(contextSize);
80
+ return (<View style={{ marginBottom: sizeStyles.titleMarginBottom }}>
81
+ <DialogPrimitive.Title asChild>
82
+ <Heading size={size} style={style} {...props}/>
83
+ </DialogPrimitive.Title>
84
+ </View>);
85
+ }
86
+ DialogTitle.displayName = 'Dialog.Title';
87
+ function DialogDescription({ size: sizeProp, style, ...props }) {
88
+ const { size: contextSize } = React.useContext(DialogContentContext);
89
+ const size = sizeProp ?? getDialogDescriptionSize(contextSize);
90
+ const sizeStyles = getDialogSizeStyles(contextSize);
91
+ return (<View style={{ marginBottom: sizeStyles.descriptionMarginBottom }}>
92
+ <DialogPrimitive.Description asChild>
93
+ <Text size={size} style={style} {...props}/>
94
+ </DialogPrimitive.Description>
95
+ </View>);
96
+ }
97
+ DialogDescription.displayName = 'Dialog.Description';
98
+ // Inject CSS keyframes for web animations
99
+ if (Platform.OS === 'web' && typeof document !== 'undefined') {
100
+ const styleId = 'frosted-ui-dialog-keyframes';
101
+ if (!document.getElementById(styleId)) {
102
+ const styleEl = document.createElement('style');
103
+ styleEl.id = styleId;
104
+ styleEl.textContent = `
105
+ @keyframes fui-dialog-content-show {
106
+ from {
107
+ opacity: 0;
108
+ transform: translateY(5px) scale(0.97);
109
+ }
110
+ to {
111
+ opacity: 1;
112
+ transform: translateY(0px) scale(1);
113
+ }
114
+ }
115
+ @keyframes fui-dialog-content-hide {
116
+ from {
117
+ opacity: 1;
118
+ transform: translateY(0px) scale(1);
119
+ }
120
+ to {
121
+ opacity: 0;
122
+ transform: translateY(5px) scale(0.99);
123
+ }
124
+ }
125
+ `;
126
+ document.head.appendChild(styleEl);
127
+ }
128
+ }
129
+ // ============================================================================
130
+ // Exports
131
+ // ============================================================================
132
+ const Dialog = Object.assign(DialogRoot, {
133
+ Root: DialogRoot,
134
+ Trigger: DialogTrigger,
135
+ Content: DialogContent,
136
+ Title: DialogTitle,
137
+ Description: DialogDescription,
138
+ Close: DialogClose,
139
+ });
140
+ export { Dialog };
141
+ //# sourceMappingURL=dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../src/components/dialog.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { Color } from '../lib/types';
2
+ import * as DropdownMenuPrimitive from '@rn-primitives/dropdown-menu';
3
+ import * as React from 'react';
4
+ type DropdownMenuSize = '1' | '2' | '3';
5
+ type DropdownMenuVariant = 'solid' | 'soft';
6
+ type DropdownMenuRootProps = DropdownMenuPrimitive.RootProps & {
7
+ size?: DropdownMenuSize;
8
+ variant?: DropdownMenuVariant;
9
+ color?: Color;
10
+ };
11
+ declare function DropdownMenuRoot({ size, variant, color, ...props }: DropdownMenuRootProps): React.JSX.Element;
12
+ type DropdownMenuTriggerProps = DropdownMenuPrimitive.TriggerProps;
13
+ declare function DropdownMenuTrigger(props: DropdownMenuTriggerProps): React.JSX.Element;
14
+ type DropdownMenuContentProps = Omit<DropdownMenuPrimitive.ContentProps, 'children'> & {
15
+ portalHost?: string;
16
+ children?: React.ReactNode;
17
+ };
18
+ declare function DropdownMenuContent({ portalHost, children, ...props }: DropdownMenuContentProps): React.JSX.Element;
19
+ type DropdownMenuItemProps = Omit<DropdownMenuPrimitive.ItemProps, 'children'> & {
20
+ color?: Color;
21
+ children?: React.ReactNode;
22
+ };
23
+ declare function DropdownMenuItem({ children, disabled, color, ...props }: DropdownMenuItemProps): React.JSX.Element;
24
+ type DropdownMenuCheckboxItemProps = Omit<DropdownMenuPrimitive.CheckboxItemProps, 'children'> & {
25
+ children?: React.ReactNode;
26
+ };
27
+ declare function DropdownMenuCheckboxItem({ children, disabled, ...props }: DropdownMenuCheckboxItemProps): React.JSX.Element;
28
+ type DropdownMenuRadioGroupProps = DropdownMenuPrimitive.RadioGroupProps;
29
+ declare function DropdownMenuRadioGroup(props: DropdownMenuRadioGroupProps): React.JSX.Element;
30
+ type DropdownMenuRadioItemProps = Omit<DropdownMenuPrimitive.RadioItemProps, 'children'> & {
31
+ children?: React.ReactNode;
32
+ };
33
+ declare function DropdownMenuRadioItem({ children, disabled, ...props }: DropdownMenuRadioItemProps): React.JSX.Element;
34
+ type DropdownMenuLabelProps = DropdownMenuPrimitive.LabelProps;
35
+ declare function DropdownMenuLabel({ children, ...props }: DropdownMenuLabelProps): React.JSX.Element;
36
+ type DropdownMenuSeparatorProps = DropdownMenuPrimitive.SeparatorProps;
37
+ declare function DropdownMenuSeparator(props: DropdownMenuSeparatorProps): React.JSX.Element;
38
+ type DropdownMenuGroupProps = DropdownMenuPrimitive.GroupProps;
39
+ declare function DropdownMenuGroup(props: DropdownMenuGroupProps): React.JSX.Element;
40
+ type DropdownMenuSubProps = DropdownMenuPrimitive.SubProps;
41
+ declare function DropdownMenuSub(props: DropdownMenuSubProps): React.JSX.Element;
42
+ type DropdownMenuSubTriggerProps = Omit<DropdownMenuPrimitive.SubTriggerProps, 'children'> & {
43
+ children?: React.ReactNode;
44
+ };
45
+ declare function DropdownMenuSubTrigger({ children, disabled, ...props }: DropdownMenuSubTriggerProps): React.JSX.Element;
46
+ type DropdownMenuSubContentProps = DropdownMenuPrimitive.SubContentProps;
47
+ declare function DropdownMenuSubContent(props: DropdownMenuSubContentProps): React.JSX.Element;
48
+ declare const DropdownMenu: {
49
+ Root: typeof DropdownMenuRoot;
50
+ Trigger: typeof DropdownMenuTrigger;
51
+ Content: typeof DropdownMenuContent;
52
+ Item: typeof DropdownMenuItem;
53
+ CheckboxItem: typeof DropdownMenuCheckboxItem;
54
+ RadioGroup: typeof DropdownMenuRadioGroup;
55
+ RadioItem: typeof DropdownMenuRadioItem;
56
+ Label: typeof DropdownMenuLabel;
57
+ Separator: typeof DropdownMenuSeparator;
58
+ Group: typeof DropdownMenuGroup;
59
+ Sub: typeof DropdownMenuSub;
60
+ SubTrigger: typeof DropdownMenuSubTrigger;
61
+ SubContent: typeof DropdownMenuSubContent;
62
+ };
63
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuRoot, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, };
64
+ export type { DropdownMenuCheckboxItemProps, DropdownMenuContentProps, DropdownMenuGroupProps, DropdownMenuItemProps, DropdownMenuLabelProps, DropdownMenuRadioGroupProps, DropdownMenuRadioItemProps, DropdownMenuRootProps, DropdownMenuSeparatorProps, DropdownMenuSize, DropdownMenuSubContentProps, DropdownMenuSubProps, DropdownMenuSubTriggerProps, DropdownMenuTriggerProps, DropdownMenuVariant, };
65
+ //# sourceMappingURL=dropdown-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../src/components/dropdown-menu.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,441 @@
1
+ import { NativeOnlyAnimatedView } from '../components/native-only-animated-view';
2
+ import { Text, TextStyleContext } from '../components/text';
3
+ import { useThemeTokens } from '../lib/use-theme-tokens';
4
+ import * as DropdownMenuPrimitive from '@rn-primitives/dropdown-menu';
5
+ import * as React from 'react';
6
+ import { Platform, ScrollView, StyleSheet, useWindowDimensions, View, } from 'react-native';
7
+ import { FadeIn, FadeOut } from 'react-native-reanimated';
8
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
9
+ import { FullWindowOverlay as RNFullWindowOverlay } from 'react-native-screens';
10
+ import Svg, { Path } from 'react-native-svg';
11
+ // ============================================================================
12
+ // Custom icons matching web version
13
+ // ============================================================================
14
+ function DropdownMenuCheckIcon({ size, color }) {
15
+ return (<Svg width={size} height={size} viewBox="0 0 9 9" fill={color}>
16
+ <Path fillRule="evenodd" clipRule="evenodd" d="M8.53547 0.62293C8.88226 0.849446 8.97976 1.3142 8.75325 1.66099L4.5083 8.1599C4.38833 8.34356 4.19397 8.4655 3.9764 8.49358C3.75883 8.52167 3.53987 8.45309 3.3772 8.30591L0.616113 5.80777C0.308959 5.52987 0.285246 5.05559 0.563148 4.74844C0.84105 4.44128 1.31533 4.41757 1.62249 4.69547L3.73256 6.60459L7.49741 0.840706C7.72393 0.493916 8.18868 0.396414 8.53547 0.62293Z"/>
17
+ </Svg>);
18
+ }
19
+ function DropdownMenuChevronRightIcon({ size, color }) {
20
+ return (<Svg width={size} height={size} viewBox="0 0 9 9" fill="none" stroke={color} strokeWidth={1.5}>
21
+ <Path d="M3 1.5L6 4.5L3 7.5"/>
22
+ </Svg>);
23
+ }
24
+ const DropdownMenuContext = React.createContext({
25
+ size: '2',
26
+ variant: 'solid',
27
+ hasIndicators: false,
28
+ });
29
+ // ============================================================================
30
+ // Size/Style helpers (similar to Select)
31
+ // ============================================================================
32
+ function getMenuSizeStyles(size) {
33
+ return {
34
+ contentPadding: 4, // --space-1
35
+ contentBorderRadius: size === '1' ? 8 : size === '2' ? 10 : 12,
36
+ itemHeight: size === '1' ? 24 : size === '2' ? 32 : 40,
37
+ itemPaddingLeft: size === '1' ? 8 : size === '2' ? 10 : 12,
38
+ itemPaddingRight: size === '1' ? 8 : size === '2' ? 10 : 12,
39
+ itemBorderRadius: size === '1' ? 4 : size === '2' ? 6 : 8,
40
+ // For checkbox/radio items, use larger left padding
41
+ itemIndicatorPaddingLeft: size === '1' ? 24 : size === '2' ? 26 : 28,
42
+ iconSize: size === '1' ? 8 : size === '2' ? 10 : 12,
43
+ itemFontSize: size === '1' ? '1' : size === '2' ? '2' : '3',
44
+ labelFontSize: size === '1' ? '0' : size === '2' ? '1' : '2',
45
+ };
46
+ }
47
+ function DropdownMenuRoot({ size = '2', variant = 'solid', color, ...props }) {
48
+ const contextValue = React.useMemo(() => ({ size, variant, color }), [size, variant, color]);
49
+ return (<DropdownMenuContext.Provider value={contextValue}>
50
+ <DropdownMenuPrimitive.Root {...props}/>
51
+ </DropdownMenuContext.Provider>);
52
+ }
53
+ function DropdownMenuTrigger(props) {
54
+ return <DropdownMenuPrimitive.Trigger {...props}/>;
55
+ }
56
+ // ============================================================================
57
+ // DropdownMenu.Content
58
+ // ============================================================================
59
+ const FullWindowOverlay = Platform.OS === 'ios' ? RNFullWindowOverlay : React.Fragment;
60
+ function DropdownMenuContent({ portalHost, children, ...props }) {
61
+ const { size, variant, color } = React.useContext(DropdownMenuContext);
62
+ const { colors, isDark } = useThemeTokens();
63
+ const { height: windowHeight } = useWindowDimensions();
64
+ const safeAreaInsets = useSafeAreaInsets();
65
+ const sizeStyles = getMenuSizeStyles(size);
66
+ // Calculate available height for native
67
+ const nativeMaxHeight = Math.max(150, windowHeight - safeAreaInsets.top - safeAreaInsets.bottom - 100);
68
+ // Insets for collision detection
69
+ const contentInsets = {
70
+ top: safeAreaInsets.top + 8,
71
+ bottom: safeAreaInsets.bottom + 8,
72
+ left: safeAreaInsets.left + 8,
73
+ right: safeAreaInsets.right + 8,
74
+ };
75
+ // Detect if content has checkbox or radio items to adjust padding for all items
76
+ const hasIndicators = React.useMemo(() => {
77
+ let found = false;
78
+ React.Children.forEach(children, (child) => {
79
+ if (React.isValidElement(child)) {
80
+ if (child.type === DropdownMenuCheckboxItem ||
81
+ child.type === DropdownMenuRadioItem ||
82
+ child.type === DropdownMenuRadioGroup) {
83
+ found = true;
84
+ }
85
+ }
86
+ });
87
+ return found;
88
+ }, [children]);
89
+ // Re-provide context inside portal with hasIndicators
90
+ const contextValue = React.useMemo(() => ({ size, variant, color, hasIndicators }), [size, variant, color, hasIndicators]);
91
+ const backgroundColor = variant === 'solid' ? colors.panelSolid : colors.panelTranslucent;
92
+ return (<DropdownMenuPrimitive.Portal hostName={portalHost}>
93
+ <FullWindowOverlay>
94
+ <DropdownMenuPrimitive.Overlay style={Platform.select({ native: StyleSheet.absoluteFill })}>
95
+ <DropdownMenuContext.Provider value={contextValue}>
96
+ <TextStyleContext.Provider value={{ size: '2', weight: 'regular', color: 'gray' }}>
97
+ <NativeOnlyAnimatedView entering={FadeIn} exiting={FadeOut}>
98
+ <DropdownMenuPrimitive.Content align="start" sideOffset={4} insets={Platform.OS !== 'web' ? contentInsets : undefined} style={{
99
+ backgroundColor,
100
+ borderRadius: sizeStyles.contentBorderRadius,
101
+ minWidth: 128,
102
+ ...Platform.select({
103
+ web: {
104
+ boxShadow: isDark
105
+ ? `0 0 0 1px ${colors.palettes.gray.a6}, 0 12px 60px ${colors.palettes.black.a5}, 0 12px 32px -16px ${colors.palettes.black.a7}`
106
+ : `0 0 0 1px ${colors.palettes.gray.a5}, 0 12px 60px ${colors.palettes.black.a3}, 0 12px 32px -16px ${colors.palettes.gray.a5}`,
107
+ backdropFilter: variant === 'soft'
108
+ ? 'saturate(1.8) blur(20px) contrast(1.05) brightness(1.05)'
109
+ : undefined,
110
+ overflow: 'hidden',
111
+ },
112
+ default: {
113
+ maxHeight: nativeMaxHeight,
114
+ borderWidth: 1,
115
+ borderColor: isDark ? colors.palettes.gray.a6 : colors.palettes.gray.a5,
116
+ shadowColor: '#000000',
117
+ shadowOpacity: isDark ? 0.3 : 0.15,
118
+ shadowOffset: { width: 0, height: 12 },
119
+ shadowRadius: 30,
120
+ elevation: 12,
121
+ },
122
+ }),
123
+ }} {...props}>
124
+ {Platform.OS === 'web' ? (<View style={{
125
+ padding: sizeStyles.contentPadding,
126
+ maxHeight: 'var(--radix-dropdown-menu-content-available-height)',
127
+ overflow: 'auto',
128
+ }}>
129
+ {children}
130
+ </View>) : (<ScrollView style={{ maxHeight: nativeMaxHeight - sizeStyles.contentPadding * 2 - 2 }} contentContainerStyle={{ padding: sizeStyles.contentPadding }} showsVerticalScrollIndicator bounces={false}>
131
+ {children}
132
+ </ScrollView>)}
133
+ </DropdownMenuPrimitive.Content>
134
+ </NativeOnlyAnimatedView>
135
+ </TextStyleContext.Provider>
136
+ </DropdownMenuContext.Provider>
137
+ </DropdownMenuPrimitive.Overlay>
138
+ </FullWindowOverlay>
139
+ </DropdownMenuPrimitive.Portal>);
140
+ }
141
+ function DropdownMenuItem({ children, disabled, color, ...props }) {
142
+ const { size, hasIndicators } = React.useContext(DropdownMenuContext);
143
+ const { colors } = useThemeTokens();
144
+ const [hovered, setHovered] = React.useState(false);
145
+ const [pressed, setPressed] = React.useState(false);
146
+ const sizeStyles = getMenuSizeStyles(size);
147
+ // Resolve accent color for colored items (like danger -> red)
148
+ const resolvedColor = color === 'danger'
149
+ ? 'red'
150
+ : color === 'success'
151
+ ? 'green'
152
+ : color === 'warning'
153
+ ? 'yellow'
154
+ : color === 'info'
155
+ ? 'blue'
156
+ : color;
157
+ const accentPalette = resolvedColor
158
+ ? colors.palettes[resolvedColor] || colors.palettes.gray
159
+ : null;
160
+ const isHighlighted = hovered || pressed;
161
+ // Background color on highlight
162
+ const highlightBg = accentPalette ? accentPalette.a5 : colors.palettes.gray.a4;
163
+ // Text color
164
+ const textColor = disabled
165
+ ? colors.palettes.gray.a8
166
+ : accentPalette
167
+ ? isHighlighted
168
+ ? (accentPalette['12'] ?? accentPalette.a11)
169
+ : accentPalette.a11
170
+ : colors.palettes.gray['12'];
171
+ // Use indicator padding when menu has checkbox/radio items
172
+ const paddingLeft = hasIndicators
173
+ ? sizeStyles.itemIndicatorPaddingLeft
174
+ : sizeStyles.itemPaddingLeft;
175
+ const itemStyle = React.useMemo(() => ({
176
+ flexDirection: 'row',
177
+ alignItems: 'center',
178
+ justifyContent: 'space-between',
179
+ height: sizeStyles.itemHeight,
180
+ paddingLeft,
181
+ paddingRight: sizeStyles.itemPaddingRight,
182
+ borderRadius: sizeStyles.itemBorderRadius,
183
+ backgroundColor: isHighlighted ? highlightBg : undefined,
184
+ ...Platform.select({
185
+ web: {
186
+ cursor: disabled ? 'not-allowed' : 'default',
187
+ userSelect: 'none',
188
+ outline: 'none',
189
+ },
190
+ }),
191
+ }), [sizeStyles, paddingLeft, isHighlighted, highlightBg, disabled]);
192
+ // Web-specific hover handlers
193
+ const webHoverProps = Platform.OS === 'web'
194
+ ? {
195
+ onMouseEnter: () => setHovered(true),
196
+ onMouseLeave: () => setHovered(false),
197
+ }
198
+ : {};
199
+ return (<DropdownMenuPrimitive.Item disabled={disabled} onHoverIn={Platform.OS !== 'web' ? () => setHovered(true) : undefined} onHoverOut={Platform.OS !== 'web' ? () => setHovered(false) : undefined} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} style={itemStyle} {...webHoverProps} {...props}>
200
+ <Text size={sizeStyles.itemFontSize} style={{ color: textColor }}>
201
+ {children}
202
+ </Text>
203
+ </DropdownMenuPrimitive.Item>);
204
+ }
205
+ function DropdownMenuCheckboxItem({ children, disabled, ...props }) {
206
+ const { size } = React.useContext(DropdownMenuContext);
207
+ const { colors } = useThemeTokens();
208
+ const [hovered, setHovered] = React.useState(false);
209
+ const [pressed, setPressed] = React.useState(false);
210
+ const sizeStyles = getMenuSizeStyles(size);
211
+ const isHighlighted = hovered || pressed;
212
+ const highlightBg = colors.palettes.gray.a4;
213
+ const textColor = disabled ? colors.palettes.gray.a8 : colors.palettes.gray['12'];
214
+ const itemStyle = React.useMemo(() => ({
215
+ flexDirection: 'row',
216
+ alignItems: 'center',
217
+ height: sizeStyles.itemHeight,
218
+ paddingLeft: sizeStyles.itemIndicatorPaddingLeft,
219
+ paddingRight: sizeStyles.itemPaddingRight,
220
+ borderRadius: sizeStyles.itemBorderRadius,
221
+ backgroundColor: isHighlighted ? highlightBg : undefined,
222
+ position: 'relative',
223
+ ...Platform.select({
224
+ web: {
225
+ cursor: disabled ? 'not-allowed' : 'default',
226
+ userSelect: 'none',
227
+ outline: 'none',
228
+ },
229
+ }),
230
+ }), [sizeStyles, isHighlighted, highlightBg, disabled]);
231
+ const webHoverProps = Platform.OS === 'web'
232
+ ? {
233
+ onMouseEnter: () => setHovered(true),
234
+ onMouseLeave: () => setHovered(false),
235
+ }
236
+ : {};
237
+ return (<DropdownMenuPrimitive.CheckboxItem disabled={disabled} onHoverIn={Platform.OS !== 'web' ? () => setHovered(true) : undefined} onHoverOut={Platform.OS !== 'web' ? () => setHovered(false) : undefined} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} style={itemStyle} {...webHoverProps} {...props}>
238
+ <DropdownMenuPrimitive.ItemIndicator style={{
239
+ position: 'absolute',
240
+ left: 0,
241
+ width: sizeStyles.itemIndicatorPaddingLeft,
242
+ alignItems: 'center',
243
+ justifyContent: 'center',
244
+ }}>
245
+ <DropdownMenuCheckIcon size={sizeStyles.iconSize} color={textColor}/>
246
+ </DropdownMenuPrimitive.ItemIndicator>
247
+ <Text size={sizeStyles.itemFontSize} style={{ color: textColor }}>
248
+ {children}
249
+ </Text>
250
+ </DropdownMenuPrimitive.CheckboxItem>);
251
+ }
252
+ function DropdownMenuRadioGroup(props) {
253
+ return <DropdownMenuPrimitive.RadioGroup {...props}/>;
254
+ }
255
+ function DropdownMenuRadioItem({ children, disabled, ...props }) {
256
+ const { size } = React.useContext(DropdownMenuContext);
257
+ const { colors } = useThemeTokens();
258
+ const [hovered, setHovered] = React.useState(false);
259
+ const [pressed, setPressed] = React.useState(false);
260
+ const sizeStyles = getMenuSizeStyles(size);
261
+ const isHighlighted = hovered || pressed;
262
+ const highlightBg = colors.palettes.gray.a4;
263
+ const textColor = disabled ? colors.palettes.gray.a8 : colors.palettes.gray['12'];
264
+ const itemStyle = React.useMemo(() => ({
265
+ flexDirection: 'row',
266
+ alignItems: 'center',
267
+ height: sizeStyles.itemHeight,
268
+ paddingLeft: sizeStyles.itemIndicatorPaddingLeft,
269
+ paddingRight: sizeStyles.itemPaddingRight,
270
+ borderRadius: sizeStyles.itemBorderRadius,
271
+ backgroundColor: isHighlighted ? highlightBg : undefined,
272
+ position: 'relative',
273
+ ...Platform.select({
274
+ web: {
275
+ cursor: disabled ? 'not-allowed' : 'default',
276
+ userSelect: 'none',
277
+ outline: 'none',
278
+ },
279
+ }),
280
+ }), [sizeStyles, isHighlighted, highlightBg, disabled]);
281
+ const webHoverProps = Platform.OS === 'web'
282
+ ? {
283
+ onMouseEnter: () => setHovered(true),
284
+ onMouseLeave: () => setHovered(false),
285
+ }
286
+ : {};
287
+ return (<DropdownMenuPrimitive.RadioItem disabled={disabled} onHoverIn={Platform.OS !== 'web' ? () => setHovered(true) : undefined} onHoverOut={Platform.OS !== 'web' ? () => setHovered(false) : undefined} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} style={itemStyle} {...webHoverProps} {...props}>
288
+ <DropdownMenuPrimitive.ItemIndicator style={{
289
+ position: 'absolute',
290
+ left: 0,
291
+ width: sizeStyles.itemIndicatorPaddingLeft,
292
+ alignItems: 'center',
293
+ justifyContent: 'center',
294
+ }}>
295
+ <DropdownMenuCheckIcon size={sizeStyles.iconSize} color={textColor}/>
296
+ </DropdownMenuPrimitive.ItemIndicator>
297
+ <Text size={sizeStyles.itemFontSize} style={{ color: textColor }}>
298
+ {children}
299
+ </Text>
300
+ </DropdownMenuPrimitive.RadioItem>);
301
+ }
302
+ function DropdownMenuLabel({ children, ...props }) {
303
+ const { size, hasIndicators } = React.useContext(DropdownMenuContext);
304
+ const { colors } = useThemeTokens();
305
+ const sizeStyles = getMenuSizeStyles(size);
306
+ // Use indicator padding when menu has checkbox/radio items
307
+ const paddingLeft = hasIndicators
308
+ ? sizeStyles.itemIndicatorPaddingLeft
309
+ : sizeStyles.itemPaddingLeft;
310
+ return (<View style={{
311
+ flexDirection: 'row',
312
+ alignItems: 'center',
313
+ height: sizeStyles.itemHeight,
314
+ paddingLeft,
315
+ paddingRight: sizeStyles.itemPaddingRight,
316
+ ...Platform.select({
317
+ web: {
318
+ cursor: 'default',
319
+ userSelect: 'none',
320
+ },
321
+ }),
322
+ }}>
323
+ <Text size={sizeStyles.labelFontSize} weight="semi-bold" style={{ color: colors.palettes.gray.a10 }} {...props}>
324
+ {children}
325
+ </Text>
326
+ </View>);
327
+ }
328
+ function DropdownMenuSeparator(props) {
329
+ const { size } = React.useContext(DropdownMenuContext);
330
+ const { colors } = useThemeTokens();
331
+ const sizeStyles = getMenuSizeStyles(size);
332
+ return (<DropdownMenuPrimitive.Separator style={{
333
+ height: 1,
334
+ backgroundColor: colors.palettes.gray.a6,
335
+ marginVertical: 4,
336
+ marginHorizontal: -sizeStyles.contentPadding + 1,
337
+ }} {...props}/>);
338
+ }
339
+ function DropdownMenuGroup(props) {
340
+ return <DropdownMenuPrimitive.Group {...props}/>;
341
+ }
342
+ function DropdownMenuSub(props) {
343
+ return <DropdownMenuPrimitive.Sub {...props}/>;
344
+ }
345
+ function DropdownMenuSubTrigger({ children, disabled, ...props }) {
346
+ const { size, hasIndicators } = React.useContext(DropdownMenuContext);
347
+ const { colors } = useThemeTokens();
348
+ const [hovered, setHovered] = React.useState(false);
349
+ const [pressed, setPressed] = React.useState(false);
350
+ const sizeStyles = getMenuSizeStyles(size);
351
+ const isHighlighted = hovered || pressed;
352
+ const highlightBg = colors.palettes.gray.a4;
353
+ const textColor = disabled ? colors.palettes.gray.a8 : colors.palettes.gray['12'];
354
+ // Use indicator padding when menu has checkbox/radio items
355
+ const paddingLeft = hasIndicators
356
+ ? sizeStyles.itemIndicatorPaddingLeft
357
+ : sizeStyles.itemPaddingLeft;
358
+ const itemStyle = React.useMemo(() => ({
359
+ flexDirection: 'row',
360
+ alignItems: 'center',
361
+ justifyContent: 'space-between',
362
+ height: sizeStyles.itemHeight,
363
+ paddingLeft,
364
+ paddingRight: sizeStyles.itemPaddingRight,
365
+ borderRadius: sizeStyles.itemBorderRadius,
366
+ backgroundColor: isHighlighted ? highlightBg : undefined,
367
+ ...Platform.select({
368
+ web: {
369
+ cursor: disabled ? 'not-allowed' : 'default',
370
+ userSelect: 'none',
371
+ outline: 'none',
372
+ },
373
+ }),
374
+ }), [sizeStyles, paddingLeft, isHighlighted, highlightBg, disabled]);
375
+ const webHoverProps = Platform.OS === 'web'
376
+ ? {
377
+ onMouseEnter: () => setHovered(true),
378
+ onMouseLeave: () => setHovered(false),
379
+ }
380
+ : {};
381
+ return (<DropdownMenuPrimitive.SubTrigger disabled={disabled} onHoverIn={Platform.OS !== 'web' ? () => setHovered(true) : undefined} onHoverOut={Platform.OS !== 'web' ? () => setHovered(false) : undefined} onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)} style={itemStyle} {...webHoverProps} {...props}>
382
+ <Text size={sizeStyles.itemFontSize} style={{ color: textColor }}>
383
+ {children}
384
+ </Text>
385
+ <DropdownMenuChevronRightIcon size={sizeStyles.iconSize} color={textColor}/>
386
+ </DropdownMenuPrimitive.SubTrigger>);
387
+ }
388
+ function DropdownMenuSubContent(props) {
389
+ const { size, variant } = React.useContext(DropdownMenuContext);
390
+ const { colors, isDark } = useThemeTokens();
391
+ const sizeStyles = getMenuSizeStyles(size);
392
+ const backgroundColor = variant === 'solid' ? colors.panelSolid : colors.panelTranslucent;
393
+ return (<NativeOnlyAnimatedView entering={FadeIn} exiting={FadeOut}>
394
+ <DropdownMenuPrimitive.SubContent style={{
395
+ backgroundColor,
396
+ borderRadius: sizeStyles.contentBorderRadius,
397
+ minWidth: 128,
398
+ padding: sizeStyles.contentPadding,
399
+ ...Platform.select({
400
+ web: {
401
+ boxShadow: isDark
402
+ ? `0 0 0 1px ${colors.palettes.gray.a6}, 0 12px 60px ${colors.palettes.black.a5}, 0 12px 32px -16px ${colors.palettes.black.a7}`
403
+ : `0 0 0 1px ${colors.palettes.gray.a5}, 0 12px 60px ${colors.palettes.black.a3}, 0 12px 32px -16px ${colors.palettes.gray.a5}`,
404
+ backdropFilter: variant === 'soft'
405
+ ? 'saturate(1.8) blur(20px) contrast(1.05) brightness(1.05)'
406
+ : undefined,
407
+ overflow: 'hidden',
408
+ },
409
+ default: {
410
+ borderWidth: 1,
411
+ borderColor: isDark ? colors.palettes.gray.a6 : colors.palettes.gray.a5,
412
+ shadowColor: '#000000',
413
+ shadowOpacity: isDark ? 0.3 : 0.15,
414
+ shadowOffset: { width: 0, height: 12 },
415
+ shadowRadius: 30,
416
+ elevation: 12,
417
+ },
418
+ }),
419
+ }} {...props}/>
420
+ </NativeOnlyAnimatedView>);
421
+ }
422
+ // ============================================================================
423
+ // Exports
424
+ // ============================================================================
425
+ const DropdownMenu = {
426
+ Root: DropdownMenuRoot,
427
+ Trigger: DropdownMenuTrigger,
428
+ Content: DropdownMenuContent,
429
+ Item: DropdownMenuItem,
430
+ CheckboxItem: DropdownMenuCheckboxItem,
431
+ RadioGroup: DropdownMenuRadioGroup,
432
+ RadioItem: DropdownMenuRadioItem,
433
+ Label: DropdownMenuLabel,
434
+ Separator: DropdownMenuSeparator,
435
+ Group: DropdownMenuGroup,
436
+ Sub: DropdownMenuSub,
437
+ SubTrigger: DropdownMenuSubTrigger,
438
+ SubContent: DropdownMenuSubContent,
439
+ };
440
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuRoot, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, };
441
+ //# sourceMappingURL=dropdown-menu.js.map