@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.
- package/dist/index.d.mts +568 -0
- package/dist/index.d.ts +568 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/global.css +53 -0
- package/nativewind-env.d.ts +2 -0
- package/package.json +88 -0
- package/src/MAlert.tsx +38 -0
- package/src/MAnimation.tsx +55 -0
- package/src/MAvatar.tsx +111 -0
- package/src/MBadge.tsx +72 -0
- package/src/MButton.tsx +90 -0
- package/src/MCard.tsx +15 -0
- package/src/MChevron.tsx +47 -0
- package/src/MConfirmation.tsx +68 -0
- package/src/MCountDown.tsx +120 -0
- package/src/MDateTimePicker.tsx +124 -0
- package/src/MDivider.tsx +69 -0
- package/src/MDrawerRightPanel.tsx +187 -0
- package/src/MDropdown.tsx +277 -0
- package/src/MInput.tsx +162 -0
- package/src/MLabel.tsx +3 -0
- package/src/MLucideIcon.tsx +21 -0
- package/src/MModal.tsx +287 -0
- package/src/MNativeAlert.tsx +33 -0
- package/src/MNumpad.tsx +520 -0
- package/src/MPicker.tsx +150 -0
- package/src/MPinPadKeys.tsx +104 -0
- package/src/MPortal.tsx +4 -0
- package/src/MProgressBar.tsx +74 -0
- package/src/MRadioGroup.tsx +4 -0
- package/src/MRequiredLabel.tsx +21 -0
- package/src/MResponsiveContainer.tsx +74 -0
- package/src/MSearch.tsx +138 -0
- package/src/MSelector.tsx +48 -0
- package/src/MSkeleton.tsx +3 -0
- package/src/MSwitch.tsx +13 -0
- package/src/MTable.tsx +17 -0
- package/src/MTabs.tsx +198 -0
- package/src/MText.tsx +51 -0
- package/src/MTimerUp.tsx +88 -0
- package/src/MToggle.tsx +51 -0
- package/src/constants.ts +19 -0
- package/src/hooks/useColorScheme.tsx +12 -0
- package/src/hooks/useIconColors.ts +19 -0
- package/src/index.ts +124 -0
- package/src/primitives/accordion.tsx +143 -0
- package/src/primitives/alert-dialog.tsx +181 -0
- package/src/primitives/alert.tsx +94 -0
- package/src/primitives/aspect-ratio.tsx +5 -0
- package/src/primitives/avatar.tsx +47 -0
- package/src/primitives/badge.tsx +57 -0
- package/src/primitives/button.tsx +92 -0
- package/src/primitives/card.tsx +86 -0
- package/src/primitives/checkbox.tsx +35 -0
- package/src/primitives/collapsible.tsx +9 -0
- package/src/primitives/context-menu.tsx +255 -0
- package/src/primitives/dialog.tsx +166 -0
- package/src/primitives/dropdown-menu.tsx +264 -0
- package/src/primitives/hover-card.tsx +45 -0
- package/src/primitives/input.tsx +25 -0
- package/src/primitives/label.tsx +33 -0
- package/src/primitives/menubar.tsx +266 -0
- package/src/primitives/navigation-menu.tsx +192 -0
- package/src/primitives/popover.tsx +46 -0
- package/src/primitives/progress.tsx +82 -0
- package/src/primitives/radio-group.tsx +42 -0
- package/src/primitives/select.tsx +192 -0
- package/src/primitives/separator.tsx +28 -0
- package/src/primitives/skeleton.tsx +39 -0
- package/src/primitives/switch.tsx +102 -0
- package/src/primitives/table.tsx +107 -0
- package/src/primitives/tabs.tsx +66 -0
- package/src/primitives/text.tsx +28 -0
- package/src/primitives/textarea.tsx +39 -0
- package/src/primitives/toggle-group.tsx +89 -0
- package/src/primitives/toggle.tsx +91 -0
- package/src/primitives/tooltip.tsx +40 -0
- package/src/primitives/typography.tsx +214 -0
- package/src/theme.ts +43 -0
- package/src/tokens.ts +7 -0
- package/src/utils.ts +14 -0
- 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 };
|