@munchi_oy/native-ui 0.1.0

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 (83) hide show
  1. package/dist/index.d.mts +568 -0
  2. package/dist/index.d.ts +568 -0
  3. package/dist/index.js +1 -0
  4. package/dist/index.mjs +1 -0
  5. package/global.css +53 -0
  6. package/nativewind-env.d.ts +2 -0
  7. package/package.json +88 -0
  8. package/src/MAlert.tsx +38 -0
  9. package/src/MAnimation.tsx +55 -0
  10. package/src/MAvatar.tsx +111 -0
  11. package/src/MBadge.tsx +72 -0
  12. package/src/MButton.tsx +90 -0
  13. package/src/MCard.tsx +15 -0
  14. package/src/MChevron.tsx +47 -0
  15. package/src/MConfirmation.tsx +68 -0
  16. package/src/MCountDown.tsx +120 -0
  17. package/src/MDateTimePicker.tsx +124 -0
  18. package/src/MDivider.tsx +69 -0
  19. package/src/MDrawerRightPanel.tsx +187 -0
  20. package/src/MDropdown.tsx +277 -0
  21. package/src/MInput.tsx +162 -0
  22. package/src/MLabel.tsx +3 -0
  23. package/src/MLucideIcon.tsx +21 -0
  24. package/src/MModal.tsx +287 -0
  25. package/src/MNativeAlert.tsx +33 -0
  26. package/src/MNumpad.tsx +520 -0
  27. package/src/MPicker.tsx +150 -0
  28. package/src/MPinPadKeys.tsx +104 -0
  29. package/src/MPortal.tsx +4 -0
  30. package/src/MProgressBar.tsx +74 -0
  31. package/src/MRadioGroup.tsx +4 -0
  32. package/src/MRequiredLabel.tsx +21 -0
  33. package/src/MResponsiveContainer.tsx +74 -0
  34. package/src/MSearch.tsx +138 -0
  35. package/src/MSelector.tsx +48 -0
  36. package/src/MSkeleton.tsx +3 -0
  37. package/src/MSwitch.tsx +13 -0
  38. package/src/MTable.tsx +17 -0
  39. package/src/MTabs.tsx +198 -0
  40. package/src/MText.tsx +51 -0
  41. package/src/MTimerUp.tsx +88 -0
  42. package/src/MToggle.tsx +51 -0
  43. package/src/constants.ts +19 -0
  44. package/src/hooks/useColorScheme.tsx +12 -0
  45. package/src/hooks/useIconColors.ts +19 -0
  46. package/src/index.ts +124 -0
  47. package/src/primitives/accordion.tsx +143 -0
  48. package/src/primitives/alert-dialog.tsx +181 -0
  49. package/src/primitives/alert.tsx +94 -0
  50. package/src/primitives/aspect-ratio.tsx +5 -0
  51. package/src/primitives/avatar.tsx +47 -0
  52. package/src/primitives/badge.tsx +57 -0
  53. package/src/primitives/button.tsx +92 -0
  54. package/src/primitives/card.tsx +86 -0
  55. package/src/primitives/checkbox.tsx +35 -0
  56. package/src/primitives/collapsible.tsx +9 -0
  57. package/src/primitives/context-menu.tsx +255 -0
  58. package/src/primitives/dialog.tsx +166 -0
  59. package/src/primitives/dropdown-menu.tsx +264 -0
  60. package/src/primitives/hover-card.tsx +45 -0
  61. package/src/primitives/input.tsx +25 -0
  62. package/src/primitives/label.tsx +33 -0
  63. package/src/primitives/menubar.tsx +266 -0
  64. package/src/primitives/navigation-menu.tsx +192 -0
  65. package/src/primitives/popover.tsx +46 -0
  66. package/src/primitives/progress.tsx +82 -0
  67. package/src/primitives/radio-group.tsx +42 -0
  68. package/src/primitives/select.tsx +192 -0
  69. package/src/primitives/separator.tsx +28 -0
  70. package/src/primitives/skeleton.tsx +39 -0
  71. package/src/primitives/switch.tsx +102 -0
  72. package/src/primitives/table.tsx +107 -0
  73. package/src/primitives/tabs.tsx +66 -0
  74. package/src/primitives/text.tsx +28 -0
  75. package/src/primitives/textarea.tsx +39 -0
  76. package/src/primitives/toggle-group.tsx +89 -0
  77. package/src/primitives/toggle.tsx +91 -0
  78. package/src/primitives/tooltip.tsx +40 -0
  79. package/src/primitives/typography.tsx +214 -0
  80. package/src/theme.ts +43 -0
  81. package/src/tokens.ts +7 -0
  82. package/src/utils.ts +14 -0
  83. package/tailwind.config.ts +112 -0
@@ -0,0 +1,266 @@
1
+ import * as MenubarPrimitive from "@rn-primitives/menubar";
2
+ import {
3
+ Check,
4
+ ChevronDown,
5
+ ChevronRight,
6
+ ChevronUp
7
+ } from "lucide-react-native";
8
+ import * as React from "react";
9
+ import { Platform, Text, type TextProps, View } from "react-native";
10
+ import { cn } from "../utils";
11
+ import { TextClassContext } from "./text";
12
+
13
+ const MenubarMenu = MenubarPrimitive.Menu;
14
+
15
+ const MenubarGroup = MenubarPrimitive.Group;
16
+
17
+ const MenubarPortal = MenubarPrimitive.Portal;
18
+
19
+ const MenubarSub = MenubarPrimitive.Sub;
20
+
21
+ const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
22
+
23
+ const Menubar = React.forwardRef<
24
+ MenubarPrimitive.RootRef,
25
+ MenubarPrimitive.RootProps
26
+ >(({ className, ...props }, ref) => (
27
+ <MenubarPrimitive.Root
28
+ ref={ref}
29
+ className={cn(
30
+ "flex flex-row h-10 native:h-12 items-center space-x-1 rounded-md border border-border bg-background p-1",
31
+ className
32
+ )}
33
+ {...props}
34
+ />
35
+ ));
36
+ Menubar.displayName = MenubarPrimitive.Root.displayName;
37
+
38
+ const MenubarTrigger = React.forwardRef<
39
+ MenubarPrimitive.TriggerRef,
40
+ MenubarPrimitive.TriggerProps
41
+ >(({ className, ...props }, ref) => {
42
+ const { value } = MenubarPrimitive.useRootContext();
43
+ const { value: itemValue } = MenubarPrimitive.useMenuContext();
44
+
45
+ return (
46
+ <MenubarPrimitive.Trigger
47
+ ref={ref}
48
+ className={cn(
49
+ "flex flex-row web:cursor-default web:select-none items-center rounded-sm px-3 py-1.5 text-sm native:h-10 native:px-5 native:py-0 font-medium web:outline-none web:focus:bg-accent active:bg-accent web:focus:text-accent-foreground",
50
+ value === itemValue && "bg-accent text-accent-foreground",
51
+ className
52
+ )}
53
+ {...props}
54
+ />
55
+ );
56
+ });
57
+ MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
58
+
59
+ const MenubarSubTrigger = React.forwardRef<
60
+ MenubarPrimitive.SubTriggerRef,
61
+ MenubarPrimitive.SubTriggerProps & {
62
+ inset?: boolean;
63
+ }
64
+ >(({ className, inset, children, ...props }, ref) => {
65
+ const { open } = MenubarPrimitive.useSubContext();
66
+ const Icon =
67
+ Platform.OS === "web" ? ChevronRight : open ? ChevronUp : ChevronDown;
68
+ return (
69
+ <TextClassContext.Provider
70
+ value={cn(
71
+ "select-none text-sm native:text-lg text-primary",
72
+ open && "native:text-accent-foreground"
73
+ )}
74
+ >
75
+ <MenubarPrimitive.SubTrigger
76
+ ref={ref}
77
+ className={cn(
78
+ "flex flex-row web:cursor-default web:select-none items-center gap-2 web:focus:bg-accent active:bg-accent web:hover:bg-accent rounded-sm px-2 py-1.5 native:py-2 web:outline-none",
79
+ open && "bg-accent",
80
+ inset && "pl-8",
81
+ className
82
+ )}
83
+ {...props}
84
+ >
85
+ <>{children}</>
86
+ <Icon size={18} className="ml-auto text-foreground" />
87
+ </MenubarPrimitive.SubTrigger>
88
+ </TextClassContext.Provider>
89
+ );
90
+ });
91
+ MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
92
+
93
+ const MenubarSubContent = React.forwardRef<
94
+ MenubarPrimitive.SubContentRef,
95
+ MenubarPrimitive.SubContentProps
96
+ >(({ className, ...props }, ref) => {
97
+ const { open } = MenubarPrimitive.useSubContext();
98
+ return (
99
+ <MenubarPrimitive.SubContent
100
+ ref={ref}
101
+ className={cn(
102
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border mt-1 border-border bg-popover p-1 shadow-md shadow-foreground/5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
103
+ open
104
+ ? "web:animate-in web:fade-in-0 web:zoom-in-95"
105
+ : "web:animate-out web:fade-out-0 web:zoom-out ",
106
+ className
107
+ )}
108
+ {...props}
109
+ />
110
+ );
111
+ });
112
+ MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
113
+
114
+ const MenubarContent = React.forwardRef<
115
+ MenubarPrimitive.ContentRef,
116
+ MenubarPrimitive.ContentProps & { portalHost?: string }
117
+ >(({ className, portalHost, ...props }, ref) => {
118
+ const { value } = MenubarPrimitive.useRootContext();
119
+ const { value: itemValue } = MenubarPrimitive.useMenuContext();
120
+ return (
121
+ <MenubarPrimitive.Portal hostName={portalHost}>
122
+ <MenubarPrimitive.Content
123
+ ref={ref}
124
+ className={cn(
125
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 shadow-md shadow-foreground/5",
126
+ value === itemValue
127
+ ? "web:animate-in web:fade-in-0 web:zoom-in-95"
128
+ : "web:animate-out web:fade-out-0 web:zoom-out-95",
129
+ className
130
+ )}
131
+ {...props}
132
+ />
133
+ </MenubarPrimitive.Portal>
134
+ );
135
+ });
136
+ MenubarContent.displayName = MenubarPrimitive.Content.displayName;
137
+
138
+ const MenubarItem = React.forwardRef<
139
+ MenubarPrimitive.ItemRef,
140
+ MenubarPrimitive.ItemProps & {
141
+ inset?: boolean;
142
+ }
143
+ >(({ className, inset, ...props }, ref) => (
144
+ <TextClassContext.Provider value="select-none text-sm native:text-lg text-popover-foreground web:group-focus:text-accent-foreground">
145
+ <MenubarPrimitive.Item
146
+ ref={ref}
147
+ className={cn(
148
+ "relative flex flex-row web:cursor-default items-center gap-2 rounded-sm px-2 py-1.5 native:py-2 web:outline-none web:focus:bg-accent active:bg-accent web:hover:bg-accent group",
149
+ inset && "pl-8",
150
+ props.disabled && "opacity-50 web:pointer-events-none",
151
+ className
152
+ )}
153
+ {...props}
154
+ />
155
+ </TextClassContext.Provider>
156
+ ));
157
+ MenubarItem.displayName = MenubarPrimitive.Item.displayName;
158
+
159
+ const MenubarCheckboxItem = React.forwardRef<
160
+ MenubarPrimitive.CheckboxItemRef,
161
+ MenubarPrimitive.CheckboxItemProps
162
+ >(({ className, children, checked, ...props }, ref) => (
163
+ <MenubarPrimitive.CheckboxItem
164
+ ref={ref}
165
+ className={cn(
166
+ "relative flex flex-row web:cursor-default items-center web:group rounded-sm py-1.5 native:py-2 pl-8 pr-2 web:outline-none web:focus:bg-accent active:bg-accent",
167
+ props.disabled && "web:pointer-events-none opacity-50",
168
+ className
169
+ )}
170
+ checked={checked}
171
+ {...props}
172
+ >
173
+ <View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
174
+ <MenubarPrimitive.ItemIndicator>
175
+ <Check size={14} strokeWidth={3} className="text-foreground" />
176
+ </MenubarPrimitive.ItemIndicator>
177
+ </View>
178
+ <>{children}</>
179
+ </MenubarPrimitive.CheckboxItem>
180
+ ));
181
+ MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
182
+
183
+ const MenubarRadioItem = React.forwardRef<
184
+ MenubarPrimitive.RadioItemRef,
185
+ MenubarPrimitive.RadioItemProps
186
+ >(({ className, children, ...props }, ref) => (
187
+ <MenubarPrimitive.RadioItem
188
+ ref={ref}
189
+ className={cn(
190
+ "relative flex flex-row web:cursor-default web:group items-center rounded-sm py-1.5 native:py-2 pl-8 pr-2 web:outline-none web:focus:bg-accent active:bg-accent",
191
+ props.disabled && "web:pointer-events-none opacity-50",
192
+ className
193
+ )}
194
+ {...props}
195
+ >
196
+ <View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
197
+ <MenubarPrimitive.ItemIndicator>
198
+ <View className="bg-foreground h-2 w-2 rounded-full" />
199
+ </MenubarPrimitive.ItemIndicator>
200
+ </View>
201
+ <>{children}</>
202
+ </MenubarPrimitive.RadioItem>
203
+ ));
204
+ MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
205
+
206
+ const MenubarLabel = React.forwardRef<
207
+ MenubarPrimitive.LabelRef,
208
+ MenubarPrimitive.LabelProps & {
209
+ inset?: boolean;
210
+ }
211
+ >(({ className, inset, ...props }, ref) => (
212
+ <MenubarPrimitive.Label
213
+ ref={ref}
214
+ className={cn(
215
+ "px-2 py-1.5 text-sm native:text-base font-semibold text-foreground web:cursor-default",
216
+ inset && "pl-8",
217
+ className
218
+ )}
219
+ {...props}
220
+ />
221
+ ));
222
+ MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
223
+
224
+ const MenubarSeparator = React.forwardRef<
225
+ MenubarPrimitive.SeparatorRef,
226
+ MenubarPrimitive.SeparatorProps
227
+ >(({ className, ...props }, ref) => (
228
+ <MenubarPrimitive.Separator
229
+ ref={ref}
230
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
231
+ {...props}
232
+ />
233
+ ));
234
+ MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
235
+
236
+ const MenubarShortcut = ({ className, ...props }: TextProps) => {
237
+ return (
238
+ <Text
239
+ className={cn(
240
+ "ml-auto text-xs native:text-sm tracking-widest text-muted-foreground",
241
+ className
242
+ )}
243
+ {...props}
244
+ />
245
+ );
246
+ };
247
+ MenubarShortcut.displayName = "MenubarShortcut";
248
+
249
+ export {
250
+ Menubar,
251
+ MenubarCheckboxItem,
252
+ MenubarContent,
253
+ MenubarGroup,
254
+ MenubarItem,
255
+ MenubarLabel,
256
+ MenubarMenu,
257
+ MenubarPortal,
258
+ MenubarRadioGroup,
259
+ MenubarRadioItem,
260
+ MenubarSeparator,
261
+ MenubarShortcut,
262
+ MenubarSub,
263
+ MenubarSubContent,
264
+ MenubarSubTrigger,
265
+ MenubarTrigger
266
+ };
@@ -0,0 +1,192 @@
1
+ import * as NavigationMenuPrimitive from "@rn-primitives/navigation-menu";
2
+ import { cva } from "class-variance-authority";
3
+ import { ChevronDown } from "lucide-react-native";
4
+ import * as React from "react";
5
+ import { Platform, View } from "react-native";
6
+ import Animated, {
7
+ Extrapolation,
8
+ FadeInLeft,
9
+ FadeOutLeft,
10
+ interpolate,
11
+ useAnimatedStyle,
12
+ useDerivedValue,
13
+ withTiming
14
+ } from "react-native-reanimated";
15
+ import { cn } from "../utils";
16
+
17
+ const NavigationMenu = React.forwardRef<
18
+ NavigationMenuPrimitive.RootRef,
19
+ NavigationMenuPrimitive.RootProps
20
+ >(({ className, children, ...props }, ref) => (
21
+ <NavigationMenuPrimitive.Root
22
+ ref={ref}
23
+ className={cn(
24
+ "relative z-10 flex flex-row max-w-max items-center justify-center",
25
+ className
26
+ )}
27
+ {...props}
28
+ >
29
+ {children}
30
+ {Platform.OS === "web" && <NavigationMenuViewport />}
31
+ </NavigationMenuPrimitive.Root>
32
+ ));
33
+ NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
34
+
35
+ const NavigationMenuList = React.forwardRef<
36
+ NavigationMenuPrimitive.ListRef,
37
+ NavigationMenuPrimitive.ListProps
38
+ >(({ className, ...props }, ref) => (
39
+ <NavigationMenuPrimitive.List
40
+ ref={ref}
41
+ className={cn(
42
+ "web:group flex flex-1 flex-row web:list-none items-center justify-center gap-1",
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ ));
48
+ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
49
+
50
+ const NavigationMenuItem = NavigationMenuPrimitive.Item;
51
+
52
+ const navigationMenuTriggerStyle = cva(
53
+ "web:group web:inline-flex flex-row h-10 native:h-12 native:px-3 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium web:transition-colors web:hover:bg-accent active:bg-accent web:hover:text-accent-foreground web:focus:bg-accent web:focus:text-accent-foreground web:focus:outline-none web:disabled:pointer-events-none disabled:opacity-50 web:data-[active]:bg-accent/50 web:data-[state=open]:bg-accent/50"
54
+ );
55
+
56
+ const NavigationMenuTrigger = React.forwardRef<
57
+ NavigationMenuPrimitive.TriggerRef,
58
+ NavigationMenuPrimitive.TriggerProps
59
+ >(({ className, children, ...props }, ref) => {
60
+ const { value } = NavigationMenuPrimitive.useRootContext();
61
+ const { value: itemValue } = NavigationMenuPrimitive.useItemContext();
62
+
63
+ const progress = useDerivedValue(() =>
64
+ value === itemValue
65
+ ? withTiming(1, { duration: 250 })
66
+ : withTiming(0, { duration: 200 })
67
+ );
68
+ const chevronStyle = useAnimatedStyle(() => ({
69
+ transform: [{ rotate: `${progress.value * 180}deg` }],
70
+ opacity: interpolate(progress.value, [0, 1], [1, 0.8], Extrapolation.CLAMP)
71
+ }));
72
+
73
+ return (
74
+ <NavigationMenuPrimitive.Trigger
75
+ ref={ref}
76
+ className={cn(
77
+ navigationMenuTriggerStyle(),
78
+ "web:group gap-1.5",
79
+ value === itemValue && "bg-accent",
80
+ className
81
+ )}
82
+ {...props}
83
+ >
84
+ <>{children}</>
85
+ <Animated.View style={chevronStyle}>
86
+ <ChevronDown
87
+ size={12}
88
+ className={cn(
89
+ "relative text-foreground h-3 w-3 web:transition web:duration-200"
90
+ )}
91
+ aria-hidden={true}
92
+ />
93
+ </Animated.View>
94
+ </NavigationMenuPrimitive.Trigger>
95
+ );
96
+ });
97
+ NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
98
+
99
+ const NavigationMenuContent = React.forwardRef<
100
+ NavigationMenuPrimitive.ContentRef,
101
+ NavigationMenuPrimitive.ContentProps & {
102
+ portalHost?: string;
103
+ }
104
+ >(({ className, children, portalHost, ...props }, ref) => {
105
+ const { value } = NavigationMenuPrimitive.useRootContext();
106
+ const { value: itemValue } = NavigationMenuPrimitive.useItemContext();
107
+ return (
108
+ <NavigationMenuPrimitive.Portal hostName={portalHost}>
109
+ <NavigationMenuPrimitive.Content
110
+ ref={ref}
111
+ className={cn(
112
+ "w-full native:border native:border-border native:rounded-lg native:shadow-lg native:bg-popover native:text-popover-foreground native:overflow-hidden",
113
+ value === itemValue
114
+ ? "web:animate-in web:fade-in web:slide-in-from-right-20"
115
+ : "web:animate-out web:fade-out web:slide-out-to-left-20",
116
+ className
117
+ )}
118
+ {...props}
119
+ >
120
+ <Animated.View
121
+ entering={Platform.OS !== "web" ? FadeInLeft : undefined}
122
+ exiting={Platform.OS !== "web" ? FadeOutLeft : undefined}
123
+ >
124
+ {children}
125
+ </Animated.View>
126
+ </NavigationMenuPrimitive.Content>
127
+ </NavigationMenuPrimitive.Portal>
128
+ );
129
+ });
130
+ NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
131
+
132
+ const NavigationMenuLink = NavigationMenuPrimitive.Link;
133
+
134
+ const NavigationMenuViewport = React.forwardRef<
135
+ NavigationMenuPrimitive.ViewportRef,
136
+ NavigationMenuPrimitive.ViewportProps
137
+ >(({ className, ...props }, ref) => {
138
+ return (
139
+ <View className={cn("absolute left-0 top-full flex justify-center")}>
140
+ <View
141
+ className={cn(
142
+ "web:origin-top-center relative mt-1.5 web:h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-lg web:animate-in web:zoom-in-90",
143
+ className
144
+ )}
145
+ ref={ref}
146
+ {...props}
147
+ >
148
+ <NavigationMenuPrimitive.Viewport />
149
+ </View>
150
+ </View>
151
+ );
152
+ });
153
+ NavigationMenuViewport.displayName =
154
+ NavigationMenuPrimitive.Viewport.displayName;
155
+
156
+ const NavigationMenuIndicator = React.forwardRef<
157
+ NavigationMenuPrimitive.IndicatorRef,
158
+ NavigationMenuPrimitive.IndicatorProps
159
+ >(({ className, ...props }, ref) => {
160
+ const { value } = NavigationMenuPrimitive.useRootContext();
161
+ const { value: itemValue } = NavigationMenuPrimitive.useItemContext();
162
+
163
+ return (
164
+ <NavigationMenuPrimitive.Indicator
165
+ ref={ref}
166
+ className={cn(
167
+ "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
168
+ value === itemValue
169
+ ? "web:animate-in web:fade-in"
170
+ : "web:animate-out web:fade-out",
171
+ className
172
+ )}
173
+ {...props}
174
+ >
175
+ <View className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md shadow-foreground/5" />
176
+ </NavigationMenuPrimitive.Indicator>
177
+ );
178
+ });
179
+ NavigationMenuIndicator.displayName =
180
+ NavigationMenuPrimitive.Indicator.displayName;
181
+
182
+ export {
183
+ NavigationMenu,
184
+ NavigationMenuContent,
185
+ NavigationMenuIndicator,
186
+ NavigationMenuItem,
187
+ NavigationMenuLink,
188
+ NavigationMenuList,
189
+ NavigationMenuTrigger,
190
+ navigationMenuTriggerStyle,
191
+ NavigationMenuViewport
192
+ };
@@ -0,0 +1,46 @@
1
+ import * as PopoverPrimitive from "@rn-primitives/popover";
2
+ import * as React from "react";
3
+ import { Platform, StyleSheet } from "react-native";
4
+ import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
5
+ import { cn } from "../utils";
6
+ import { TextClassContext } from "./text";
7
+
8
+ const Popover = PopoverPrimitive.Root;
9
+
10
+ const PopoverTrigger = PopoverPrimitive.Trigger;
11
+
12
+ const PopoverContent = React.forwardRef<
13
+ PopoverPrimitive.ContentRef,
14
+ PopoverPrimitive.ContentProps & { portalHost?: string }
15
+ >(
16
+ (
17
+ { className, align = "center", sideOffset = 4, portalHost, ...props },
18
+ ref
19
+ ) => {
20
+ return (
21
+ <PopoverPrimitive.Portal hostName={portalHost}>
22
+ <PopoverPrimitive.Overlay
23
+ style={Platform.OS !== "web" ? StyleSheet.absoluteFill : undefined}
24
+ >
25
+ <Animated.View entering={FadeIn.duration(200)} exiting={FadeOut}>
26
+ <TextClassContext.Provider value="text-popover-foreground">
27
+ <PopoverPrimitive.Content
28
+ ref={ref}
29
+ align={align}
30
+ sideOffset={sideOffset}
31
+ className={cn(
32
+ "z-50 w-72 rounded-md web:cursor-auto border border-border bg-popover p-4 shadow-md shadow-foreground/5 web:outline-none web:data-[side=bottom]:slide-in-from-top-2 web:data-[side=left]:slide-in-from-right-2 web:data-[side=right]:slide-in-from-left-2 web:data-[side=top]:slide-in-from-bottom-2 web:animate-in web:zoom-in-95 web:fade-in-0",
33
+ className
34
+ )}
35
+ {...props}
36
+ />
37
+ </TextClassContext.Provider>
38
+ </Animated.View>
39
+ </PopoverPrimitive.Overlay>
40
+ </PopoverPrimitive.Portal>
41
+ );
42
+ }
43
+ );
44
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
45
+
46
+ export { Popover, PopoverContent, PopoverTrigger };
@@ -0,0 +1,82 @@
1
+ import * as ProgressPrimitive from "@rn-primitives/progress";
2
+ import * as React from "react";
3
+ import { Platform, View, type ViewProps } from "react-native";
4
+ import Animated, {
5
+ Extrapolation,
6
+ interpolate,
7
+ useAnimatedStyle,
8
+ useDerivedValue,
9
+ withSpring
10
+ } from "react-native-reanimated";
11
+ import { cn } from "../utils";
12
+
13
+ const Progress = React.forwardRef<
14
+ ProgressPrimitive.RootRef,
15
+ ProgressPrimitive.RootProps & {
16
+ indicatorClassName?: ViewProps["className"];
17
+ }
18
+ >(({ className, value, indicatorClassName, ...props }, ref) => {
19
+ return (
20
+ <ProgressPrimitive.Root
21
+ ref={ref}
22
+ className={cn(
23
+ "relative h-4 w-full overflow-hidden rounded-full bg-secondary",
24
+ className
25
+ )}
26
+ {...props}
27
+ >
28
+ <Indicator value={value} className={indicatorClassName} />
29
+ </ProgressPrimitive.Root>
30
+ );
31
+ });
32
+ Progress.displayName = ProgressPrimitive.Root.displayName;
33
+
34
+ export { Progress };
35
+
36
+ function Indicator({
37
+ value,
38
+ className
39
+ }: {
40
+ value: number | undefined | null;
41
+ } & Pick<ViewProps, "className">) {
42
+ const progress = useDerivedValue(() => value ?? 0);
43
+
44
+ const indicator = useAnimatedStyle(() => {
45
+ return {
46
+ width: withSpring(
47
+ `${interpolate(
48
+ progress.value,
49
+ [0, 100],
50
+ [1, 100],
51
+ Extrapolation.CLAMP
52
+ )}%`,
53
+ { overshootClamping: true }
54
+ )
55
+ };
56
+ });
57
+
58
+ if (Platform.OS === "web") {
59
+ return (
60
+ <View
61
+ className={cn(
62
+ "h-full w-full flex-1 bg-primary web:transition-all",
63
+ className
64
+ )}
65
+ style={{ transform: `translateX(-${100 - (value ?? 0)}%)` }}
66
+ >
67
+ <ProgressPrimitive.Indicator
68
+ className={cn("h-full w-full", className)}
69
+ />
70
+ </View>
71
+ );
72
+ }
73
+
74
+ return (
75
+ <ProgressPrimitive.Indicator asChild>
76
+ <Animated.View
77
+ style={indicator}
78
+ className={cn("h-full bg-foreground", className)}
79
+ />
80
+ </ProgressPrimitive.Indicator>
81
+ );
82
+ }
@@ -0,0 +1,42 @@
1
+ import * as RadioGroupPrimitive from "@rn-primitives/radio-group";
2
+ import * as React from "react";
3
+ import { View } from "react-native";
4
+ import { cn } from "../utils";
5
+
6
+ const RadioGroup = React.forwardRef<
7
+ RadioGroupPrimitive.RootRef,
8
+ RadioGroupPrimitive.RootProps
9
+ >(({ className, ...props }, ref) => {
10
+ return (
11
+ <RadioGroupPrimitive.Root
12
+ className={cn("web:grid gap-2", className)}
13
+ {...props}
14
+ ref={ref}
15
+ />
16
+ );
17
+ });
18
+ RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
19
+
20
+ const RadioGroupItem = React.forwardRef<
21
+ RadioGroupPrimitive.ItemRef,
22
+ RadioGroupPrimitive.ItemProps
23
+ >(({ className, ...props }, ref) => {
24
+ return (
25
+ <RadioGroupPrimitive.Item
26
+ ref={ref}
27
+ className={cn(
28
+ "aspect-square h-4 w-4 native:h-5 native:w-5 rounded-full justify-center items-center border border-border web:ring-offset-background web:focus:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2",
29
+ props.disabled && "web:cursor-not-allowed opacity-50",
30
+ className
31
+ )}
32
+ {...props}
33
+ >
34
+ <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
35
+ <View className="aspect-square h-[9px] w-[9px] native:h-[10] native:w-[10] bg-primary rounded-full" />
36
+ </RadioGroupPrimitive.Indicator>
37
+ </RadioGroupPrimitive.Item>
38
+ );
39
+ });
40
+ RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
41
+
42
+ export { RadioGroup, RadioGroupItem };