@medway-ui/native 1.0.2
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/README.md +153 -0
- package/lib/commonjs/components/Alert.js +206 -0
- package/lib/commonjs/components/Alert.js.map +1 -0
- package/lib/commonjs/components/AlertDialog.js +273 -0
- package/lib/commonjs/components/AlertDialog.js.map +1 -0
- package/lib/commonjs/components/Badge.js +94 -0
- package/lib/commonjs/components/Badge.js.map +1 -0
- package/lib/commonjs/components/Button.js +181 -0
- package/lib/commonjs/components/Button.js.map +1 -0
- package/lib/commonjs/components/Checkbox.js +91 -0
- package/lib/commonjs/components/Checkbox.js.map +1 -0
- package/lib/commonjs/components/Dialog.js +164 -0
- package/lib/commonjs/components/Dialog.js.map +1 -0
- package/lib/commonjs/components/Input.js +364 -0
- package/lib/commonjs/components/Input.js.map +1 -0
- package/lib/commonjs/components/Label.js +90 -0
- package/lib/commonjs/components/Label.js.map +1 -0
- package/lib/commonjs/components/Loading.js +49 -0
- package/lib/commonjs/components/Loading.js.map +1 -0
- package/lib/commonjs/components/Popover.js +54 -0
- package/lib/commonjs/components/Popover.js.map +1 -0
- package/lib/commonjs/components/RadioGroup.js +72 -0
- package/lib/commonjs/components/RadioGroup.js.map +1 -0
- package/lib/commonjs/components/Select.js +234 -0
- package/lib/commonjs/components/Select.js.map +1 -0
- package/lib/commonjs/components/Separator.js +22 -0
- package/lib/commonjs/components/Separator.js.map +1 -0
- package/lib/commonjs/components/Sheet.js +148 -0
- package/lib/commonjs/components/Sheet.js.map +1 -0
- package/lib/commonjs/components/Switch.js +99 -0
- package/lib/commonjs/components/Switch.js.map +1 -0
- package/lib/commonjs/components/Tag.js +132 -0
- package/lib/commonjs/components/Tag.js.map +1 -0
- package/lib/commonjs/components/Toast.js +244 -0
- package/lib/commonjs/components/Toast.js.map +1 -0
- package/lib/commonjs/components/Tooltip.js +54 -0
- package/lib/commonjs/components/Tooltip.js.map +1 -0
- package/lib/commonjs/hooks/use-toast.js +136 -0
- package/lib/commonjs/hooks/use-toast.js.map +1 -0
- package/lib/commonjs/index.js +667 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/lib/utils.js +22 -0
- package/lib/commonjs/lib/utils.js.map +1 -0
- package/lib/commonjs/nativewind-env.d.js +3 -0
- package/lib/commonjs/nativewind-env.d.js.map +1 -0
- package/lib/module/components/Alert.js +195 -0
- package/lib/module/components/Alert.js.map +1 -0
- package/lib/module/components/AlertDialog.js +257 -0
- package/lib/module/components/AlertDialog.js.map +1 -0
- package/lib/module/components/Badge.js +90 -0
- package/lib/module/components/Badge.js.map +1 -0
- package/lib/module/components/Button.js +177 -0
- package/lib/module/components/Button.js.map +1 -0
- package/lib/module/components/Checkbox.js +86 -0
- package/lib/module/components/Checkbox.js.map +1 -0
- package/lib/module/components/Dialog.js +150 -0
- package/lib/module/components/Dialog.js.map +1 -0
- package/lib/module/components/Input.js +349 -0
- package/lib/module/components/Input.js.map +1 -0
- package/lib/module/components/Label.js +86 -0
- package/lib/module/components/Label.js.map +1 -0
- package/lib/module/components/Loading.js +45 -0
- package/lib/module/components/Loading.js.map +1 -0
- package/lib/module/components/Popover.js +47 -0
- package/lib/module/components/Popover.js.map +1 -0
- package/lib/module/components/RadioGroup.js +66 -0
- package/lib/module/components/RadioGroup.js.map +1 -0
- package/lib/module/components/Select.js +217 -0
- package/lib/module/components/Select.js.map +1 -0
- package/lib/module/components/Separator.js +19 -0
- package/lib/module/components/Separator.js.map +1 -0
- package/lib/module/components/Sheet.js +136 -0
- package/lib/module/components/Sheet.js.map +1 -0
- package/lib/module/components/Switch.js +94 -0
- package/lib/module/components/Switch.js.map +1 -0
- package/lib/module/components/Tag.js +128 -0
- package/lib/module/components/Tag.js.map +1 -0
- package/lib/module/components/Toast.js +233 -0
- package/lib/module/components/Toast.js.map +1 -0
- package/lib/module/components/Tooltip.js +47 -0
- package/lib/module/components/Tooltip.js.map +1 -0
- package/lib/module/hooks/use-toast.js +130 -0
- package/lib/module/hooks/use-toast.js.map +1 -0
- package/lib/module/index.js +41 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/lib/utils.js +18 -0
- package/lib/module/lib/utils.js.map +1 -0
- package/lib/module/nativewind-env.d.js +3 -0
- package/lib/module/nativewind-env.d.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/components/Alert.d.ts +36 -0
- package/lib/typescript/components/Alert.d.ts.map +1 -0
- package/lib/typescript/components/AlertDialog.d.ts +44 -0
- package/lib/typescript/components/AlertDialog.d.ts.map +1 -0
- package/lib/typescript/components/Badge.d.ts +17 -0
- package/lib/typescript/components/Badge.d.ts.map +1 -0
- package/lib/typescript/components/Button.d.ts +24 -0
- package/lib/typescript/components/Button.d.ts.map +1 -0
- package/lib/typescript/components/Checkbox.d.ts +20 -0
- package/lib/typescript/components/Checkbox.d.ts.map +1 -0
- package/lib/typescript/components/Dialog.d.ts +35 -0
- package/lib/typescript/components/Dialog.d.ts.map +1 -0
- package/lib/typescript/components/Input.d.ts +57 -0
- package/lib/typescript/components/Input.d.ts.map +1 -0
- package/lib/typescript/components/Label.d.ts +21 -0
- package/lib/typescript/components/Label.d.ts.map +1 -0
- package/lib/typescript/components/Loading.d.ts +9 -0
- package/lib/typescript/components/Loading.d.ts.map +1 -0
- package/lib/typescript/components/Popover.d.ts +11 -0
- package/lib/typescript/components/Popover.d.ts.map +1 -0
- package/lib/typescript/components/RadioGroup.d.ts +13 -0
- package/lib/typescript/components/RadioGroup.d.ts.map +1 -0
- package/lib/typescript/components/Select.d.ts +37 -0
- package/lib/typescript/components/Select.d.ts.map +1 -0
- package/lib/typescript/components/Separator.d.ts +9 -0
- package/lib/typescript/components/Separator.d.ts.map +1 -0
- package/lib/typescript/components/Sheet.d.ts +31 -0
- package/lib/typescript/components/Sheet.d.ts.map +1 -0
- package/lib/typescript/components/Switch.d.ts +18 -0
- package/lib/typescript/components/Switch.d.ts.map +1 -0
- package/lib/typescript/components/Tag.d.ts +17 -0
- package/lib/typescript/components/Tag.d.ts.map +1 -0
- package/lib/typescript/components/Toast.d.ts +42 -0
- package/lib/typescript/components/Toast.d.ts.map +1 -0
- package/lib/typescript/components/Tooltip.d.ts +14 -0
- package/lib/typescript/components/Tooltip.d.ts.map +1 -0
- package/lib/typescript/hooks/use-toast.d.ts +46 -0
- package/lib/typescript/hooks/use-toast.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +38 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/lib/utils.d.ts +3 -0
- package/lib/typescript/lib/utils.d.ts.map +1 -0
- package/package.json +111 -0
- package/src/components/Alert.tsx +185 -0
- package/src/components/AlertDialog.tsx +277 -0
- package/src/components/Badge.tsx +113 -0
- package/src/components/Button.tsx +224 -0
- package/src/components/Checkbox.tsx +106 -0
- package/src/components/Dialog.tsx +175 -0
- package/src/components/Input.tsx +439 -0
- package/src/components/Label.tsx +95 -0
- package/src/components/Loading.tsx +54 -0
- package/src/components/Popover.tsx +46 -0
- package/src/components/RadioGroup.tsx +62 -0
- package/src/components/Select.tsx +246 -0
- package/src/components/Separator.tsx +24 -0
- package/src/components/Sheet.tsx +165 -0
- package/src/components/Switch.tsx +138 -0
- package/src/components/Tag.tsx +116 -0
- package/src/components/Toast.tsx +265 -0
- package/src/components/Tooltip.tsx +49 -0
- package/src/hooks/use-toast.ts +144 -0
- package/src/index.ts +193 -0
- package/src/lib/utils.ts +63 -0
- package/src/nativewind-env.d.ts +1 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useMemo,
|
|
5
|
+
isValidElement,
|
|
6
|
+
cloneElement,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
type ReactElement,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { View, Text, type ViewProps, type TextProps } from "react-native";
|
|
11
|
+
import * as SelectPrimitive from "@rn-primitives/select";
|
|
12
|
+
import { Check, ChevronDown, ChevronUp } from "@medway-ui/icons/native";
|
|
13
|
+
import { cva } from "class-variance-authority";
|
|
14
|
+
import { cn } from "@/lib/utils";
|
|
15
|
+
|
|
16
|
+
type SelectSize = "md" | "lg";
|
|
17
|
+
|
|
18
|
+
interface SelectContextValue {
|
|
19
|
+
invalid: boolean;
|
|
20
|
+
size: SelectSize;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SelectProps extends SelectPrimitive.RootProps {
|
|
24
|
+
invalid?: boolean;
|
|
25
|
+
size?: SelectSize;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface SelectTriggerProps extends Omit<SelectPrimitive.TriggerProps, "children"> {
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface SelectItemProps extends SelectPrimitive.ItemProps {
|
|
33
|
+
icon?: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const selectVariants = cva(
|
|
37
|
+
"flex-row w-full items-center justify-between gap-2 rounded-md border-2 border-gray-stroke-muted bg-surface-card px-4",
|
|
38
|
+
{
|
|
39
|
+
variants: {
|
|
40
|
+
size: {
|
|
41
|
+
lg: "h-12 max-h-12",
|
|
42
|
+
md: "h-10 max-h-10",
|
|
43
|
+
},
|
|
44
|
+
invalid: {
|
|
45
|
+
true: "border-feedback-error-stroke",
|
|
46
|
+
false: "",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
size: "lg",
|
|
51
|
+
invalid: false,
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const SelectContext = createContext<SelectContextValue>({
|
|
57
|
+
invalid: false,
|
|
58
|
+
size: "lg",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
function Select({ invalid = false, size = "lg", ...props }: SelectProps) {
|
|
62
|
+
const ctx = useMemo(() => ({ invalid, size }), [invalid, size]);
|
|
63
|
+
return (
|
|
64
|
+
<SelectContext.Provider value={ctx}>
|
|
65
|
+
<SelectPrimitive.Root {...props} />
|
|
66
|
+
</SelectContext.Provider>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function SelectWrapper({ className, ...props }: ViewProps) {
|
|
71
|
+
return <View className={cn("relative flex-col gap-2", className)} {...props} />;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function SelectTrigger({ className, children, ...props }: SelectTriggerProps) {
|
|
75
|
+
const { invalid, size } = useContext(SelectContext);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<SelectPrimitive.Trigger
|
|
79
|
+
className={cn(selectVariants({ size, invalid }), className)}
|
|
80
|
+
{...props}
|
|
81
|
+
>
|
|
82
|
+
{children}
|
|
83
|
+
<ChevronDown
|
|
84
|
+
size={size === "lg" ? 24 : 20}
|
|
85
|
+
strokeWidth={1.6}
|
|
86
|
+
className="text-gray-foreground shrink-0"
|
|
87
|
+
/>
|
|
88
|
+
</SelectPrimitive.Trigger>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function SelectValue({ className, placeholder, ...props }: SelectPrimitive.ValueProps) {
|
|
93
|
+
const { size } = useContext(SelectContext);
|
|
94
|
+
return (
|
|
95
|
+
<SelectPrimitive.Value
|
|
96
|
+
className={cn(
|
|
97
|
+
"text-gray-foreground flex-1",
|
|
98
|
+
size === "lg" ? "text-md" : "text-sm",
|
|
99
|
+
className
|
|
100
|
+
)}
|
|
101
|
+
placeholder={placeholder}
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function SelectContent({ className, children, ...props }: SelectPrimitive.ContentProps) {
|
|
108
|
+
return (
|
|
109
|
+
<SelectPrimitive.Portal>
|
|
110
|
+
<SelectPrimitive.Overlay className="absolute inset-0 bg-black/20">
|
|
111
|
+
<SelectPrimitive.Content
|
|
112
|
+
className={cn(
|
|
113
|
+
"z-50 min-w-48 overflow-hidden rounded-md border border-gray-stroke-muted bg-surface-elevated shadow-lg",
|
|
114
|
+
className
|
|
115
|
+
)}
|
|
116
|
+
{...props}
|
|
117
|
+
>
|
|
118
|
+
<SelectScrollUpButton />
|
|
119
|
+
<SelectPrimitive.Viewport className="p-1">
|
|
120
|
+
{children}
|
|
121
|
+
</SelectPrimitive.Viewport>
|
|
122
|
+
<SelectScrollDownButton />
|
|
123
|
+
</SelectPrimitive.Content>
|
|
124
|
+
</SelectPrimitive.Overlay>
|
|
125
|
+
</SelectPrimitive.Portal>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function SelectGroup({ ...props }: SelectPrimitive.GroupProps) {
|
|
130
|
+
return <SelectPrimitive.Group {...props} />;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function SelectHeader({ className, ...props }: SelectPrimitive.LabelProps) {
|
|
134
|
+
return (
|
|
135
|
+
<SelectPrimitive.Label
|
|
136
|
+
className={cn("px-2 py-2 text-xs font-medium text-gray-foreground-muted", className)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function SelectItem({ className, children, icon, label, ...props }: SelectItemProps) {
|
|
143
|
+
const { size } = useContext(SelectContext);
|
|
144
|
+
const resolvedLabel = label ?? (typeof children === "string" ? children : "");
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<SelectPrimitive.Item
|
|
148
|
+
label={resolvedLabel}
|
|
149
|
+
className={cn(
|
|
150
|
+
"relative flex-row w-full items-center rounded px-2 gap-3",
|
|
151
|
+
size === "lg" ? "py-2" : "py-1.5",
|
|
152
|
+
"active:bg-secondary-background-soft-emphasis",
|
|
153
|
+
className
|
|
154
|
+
)}
|
|
155
|
+
{...props}
|
|
156
|
+
>
|
|
157
|
+
{icon && (
|
|
158
|
+
<View className="shrink-0 items-center justify-center text-gray-foreground">
|
|
159
|
+
{isValidElement(icon)
|
|
160
|
+
? cloneElement(icon as ReactElement<{ strokeWidth?: number }>, { strokeWidth: 1.6 })
|
|
161
|
+
: icon}
|
|
162
|
+
</View>
|
|
163
|
+
)}
|
|
164
|
+
<SelectPrimitive.ItemText className="flex-1 text-sm font-medium text-gray-foreground" />
|
|
165
|
+
<SelectPrimitive.ItemIndicator className="absolute right-2 h-3.5 w-3.5 items-center justify-center">
|
|
166
|
+
<Check size={14} strokeWidth={1.6} className="text-secondary-foreground" />
|
|
167
|
+
</SelectPrimitive.ItemIndicator>
|
|
168
|
+
</SelectPrimitive.Item>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function SelectSeparator({ className, ...props }: SelectPrimitive.SeparatorProps) {
|
|
173
|
+
return (
|
|
174
|
+
<SelectPrimitive.Separator
|
|
175
|
+
className={cn("-mx-1 my-1 h-px bg-gray-stroke-muted", className)}
|
|
176
|
+
{...props}
|
|
177
|
+
/>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function SelectScrollUpButton({ className, ...props }: SelectPrimitive.ScrollUpButtonProps) {
|
|
182
|
+
return (
|
|
183
|
+
<SelectPrimitive.ScrollUpButton
|
|
184
|
+
className={cn("items-center justify-center py-1", className)}
|
|
185
|
+
{...props}
|
|
186
|
+
>
|
|
187
|
+
<ChevronUp size={16} strokeWidth={1.6} className="text-gray-foreground" />
|
|
188
|
+
</SelectPrimitive.ScrollUpButton>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function SelectScrollDownButton({ className, ...props }: SelectPrimitive.ScrollDownButtonProps) {
|
|
193
|
+
return (
|
|
194
|
+
<SelectPrimitive.ScrollDownButton
|
|
195
|
+
className={cn("items-center justify-center py-1", className)}
|
|
196
|
+
{...props}
|
|
197
|
+
>
|
|
198
|
+
<ChevronDown size={16} strokeWidth={1.6} className="text-gray-foreground" />
|
|
199
|
+
</SelectPrimitive.ScrollDownButton>
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function SelectText({ className, ...props }: TextProps) {
|
|
204
|
+
const { invalid } = useContext(SelectContext);
|
|
205
|
+
return (
|
|
206
|
+
<Text
|
|
207
|
+
className={cn(
|
|
208
|
+
"-mt-1 text-xs",
|
|
209
|
+
invalid ? "text-feedback-error-foreground" : "text-gray-foreground",
|
|
210
|
+
className
|
|
211
|
+
)}
|
|
212
|
+
{...props}
|
|
213
|
+
/>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function SelectLabel({ children, disabled = false }: { children?: ReactNode; disabled?: boolean }) {
|
|
218
|
+
return (
|
|
219
|
+
<Text
|
|
220
|
+
className={cn(
|
|
221
|
+
"text-xs font-medium text-gray-foreground",
|
|
222
|
+
disabled ? "text-gray-foreground-muted" : ""
|
|
223
|
+
)}
|
|
224
|
+
>
|
|
225
|
+
{children}
|
|
226
|
+
</Text>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export {
|
|
231
|
+
Select,
|
|
232
|
+
SelectContent,
|
|
233
|
+
SelectGroup,
|
|
234
|
+
SelectHeader,
|
|
235
|
+
SelectItem,
|
|
236
|
+
SelectLabel,
|
|
237
|
+
SelectScrollDownButton,
|
|
238
|
+
SelectScrollUpButton,
|
|
239
|
+
SelectSeparator,
|
|
240
|
+
SelectText,
|
|
241
|
+
SelectTrigger,
|
|
242
|
+
SelectValue,
|
|
243
|
+
SelectWrapper,
|
|
244
|
+
selectVariants,
|
|
245
|
+
};
|
|
246
|
+
export type { SelectProps, SelectItemProps, SelectSize };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { View, type ViewProps, type AccessibilityRole } from "react-native";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
interface SeparatorProps extends ViewProps {
|
|
5
|
+
orientation?: "horizontal" | "vertical";
|
|
6
|
+
decorative?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function Separator({ className, orientation = "horizontal", decorative = true, ...props }: SeparatorProps) {
|
|
10
|
+
return (
|
|
11
|
+
<View
|
|
12
|
+
accessibilityRole={decorative ? undefined : ("separator" as AccessibilityRole)}
|
|
13
|
+
className={cn(
|
|
14
|
+
"shrink-0 bg-gray-stroke-muted",
|
|
15
|
+
orientation === "horizontal" ? "h-px w-full" : "w-px h-full",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Separator };
|
|
24
|
+
export type { SeparatorProps };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { View, ScrollView, type ViewProps } from "react-native";
|
|
3
|
+
import * as DialogPrimitive from "@rn-primitives/dialog";
|
|
4
|
+
import { CloseMd } from "@medway-ui/icons/native";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { Separator } from "@/components/Separator";
|
|
7
|
+
|
|
8
|
+
type SheetSide = "top" | "right" | "bottom" | "left";
|
|
9
|
+
|
|
10
|
+
interface SheetContainerProps extends DialogPrimitive.ContentProps {
|
|
11
|
+
side?: SheetSide;
|
|
12
|
+
showCloseButton?: boolean;
|
|
13
|
+
overlayClassName?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface SheetHeaderProps extends ViewProps {
|
|
17
|
+
separator?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface SheetFooterProps extends ViewProps {
|
|
21
|
+
separator?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const overlayPositionMap: Record<SheetSide, string> = {
|
|
25
|
+
bottom: "absolute inset-0 justify-end",
|
|
26
|
+
top: "absolute inset-0 justify-start",
|
|
27
|
+
left: "absolute inset-0 items-start",
|
|
28
|
+
right: "absolute inset-0 items-end",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const contentSizeMap: Record<SheetSide, string> = {
|
|
32
|
+
bottom: "w-full max-h-[90%] rounded-t-xl",
|
|
33
|
+
top: "w-full max-h-[90%] rounded-b-xl",
|
|
34
|
+
left: "h-full max-w-[80%] rounded-r-xl",
|
|
35
|
+
right: "h-full max-w-[80%] rounded-l-xl",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const closeButtonPositionMap: Record<SheetSide, string> = {
|
|
39
|
+
bottom: "absolute right-3 top-3",
|
|
40
|
+
top: "absolute right-3 bottom-3",
|
|
41
|
+
left: "absolute right-3 top-3",
|
|
42
|
+
right: "absolute left-3 top-3",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function Sheet({ ...props }: DialogPrimitive.RootProps) {
|
|
46
|
+
return <DialogPrimitive.Root {...props} />;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function SheetTrigger({ ...props }: DialogPrimitive.TriggerProps) {
|
|
50
|
+
return <DialogPrimitive.Trigger {...props} />;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function SheetClose({ ...props }: DialogPrimitive.CloseProps) {
|
|
54
|
+
return <DialogPrimitive.Close {...props} />;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function SheetContainer({
|
|
58
|
+
className,
|
|
59
|
+
overlayClassName,
|
|
60
|
+
children,
|
|
61
|
+
side = "bottom",
|
|
62
|
+
showCloseButton = true,
|
|
63
|
+
...props
|
|
64
|
+
}: SheetContainerProps) {
|
|
65
|
+
return (
|
|
66
|
+
<DialogPrimitive.Portal>
|
|
67
|
+
<DialogPrimitive.Overlay
|
|
68
|
+
className={cn("bg-black/50", overlayPositionMap[side], overlayClassName)}
|
|
69
|
+
>
|
|
70
|
+
<DialogPrimitive.Content
|
|
71
|
+
className={cn(
|
|
72
|
+
"relative flex-col bg-background shadow-lg overflow-hidden",
|
|
73
|
+
contentSizeMap[side],
|
|
74
|
+
className
|
|
75
|
+
)}
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
{showCloseButton && (
|
|
80
|
+
<DialogPrimitive.Close
|
|
81
|
+
className={cn(
|
|
82
|
+
closeButtonPositionMap[side],
|
|
83
|
+
"rounded-pill p-1.5 active:bg-gray-background-soft"
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
<CloseMd size={16} className="text-gray-foreground" />
|
|
87
|
+
</DialogPrimitive.Close>
|
|
88
|
+
)}
|
|
89
|
+
</DialogPrimitive.Content>
|
|
90
|
+
</DialogPrimitive.Overlay>
|
|
91
|
+
</DialogPrimitive.Portal>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function SheetContent({
|
|
96
|
+
containerClassName,
|
|
97
|
+
className,
|
|
98
|
+
children,
|
|
99
|
+
}: {
|
|
100
|
+
containerClassName?: string;
|
|
101
|
+
className?: string;
|
|
102
|
+
children: ReactNode;
|
|
103
|
+
}) {
|
|
104
|
+
return (
|
|
105
|
+
<ScrollView
|
|
106
|
+
className={cn("flex-1", containerClassName)}
|
|
107
|
+
contentContainerStyle={{ flexGrow: 1 }}
|
|
108
|
+
>
|
|
109
|
+
<View className={cn("px-6 py-4", className)}>{children}</View>
|
|
110
|
+
</ScrollView>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function SheetHeader({ className, separator = false, children, ...props }: SheetHeaderProps) {
|
|
115
|
+
return (
|
|
116
|
+
<>
|
|
117
|
+
<View className={cn("flex-col gap-2 px-6 pt-6 pb-4", className)} {...props}>
|
|
118
|
+
{children}
|
|
119
|
+
</View>
|
|
120
|
+
{separator && <Separator />}
|
|
121
|
+
</>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function SheetFooter({ className, separator = false, children, ...props }: SheetFooterProps) {
|
|
126
|
+
return (
|
|
127
|
+
<>
|
|
128
|
+
{separator && <Separator />}
|
|
129
|
+
<View className={cn("flex-col gap-2 px-6 py-5", className)} {...props}>
|
|
130
|
+
{children}
|
|
131
|
+
</View>
|
|
132
|
+
</>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function SheetTitle({ className, ...props }: DialogPrimitive.TitleProps) {
|
|
137
|
+
return (
|
|
138
|
+
<DialogPrimitive.Title
|
|
139
|
+
className={cn("text-title-md font-semibold leading-title-md text-content-title", className)}
|
|
140
|
+
{...props}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function SheetDescription({ className, ...props }: DialogPrimitive.DescriptionProps) {
|
|
146
|
+
return (
|
|
147
|
+
<DialogPrimitive.Description
|
|
148
|
+
className={cn("text-md leading-md text-content-paragraph", className)}
|
|
149
|
+
{...props}
|
|
150
|
+
/>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
Sheet,
|
|
156
|
+
SheetClose,
|
|
157
|
+
SheetContainer,
|
|
158
|
+
SheetContent,
|
|
159
|
+
SheetDescription,
|
|
160
|
+
SheetFooter,
|
|
161
|
+
SheetHeader,
|
|
162
|
+
SheetTitle,
|
|
163
|
+
SheetTrigger,
|
|
164
|
+
};
|
|
165
|
+
export type { SheetContainerProps, SheetHeaderProps, SheetFooterProps, SheetSide };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { useState, useEffect, type ReactNode } from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import * as SwitchPrimitive from "@rn-primitives/switch";
|
|
4
|
+
import Animated, {
|
|
5
|
+
useSharedValue,
|
|
6
|
+
useAnimatedStyle,
|
|
7
|
+
withTiming,
|
|
8
|
+
Easing,
|
|
9
|
+
} from "react-native-reanimated";
|
|
10
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
|
|
13
|
+
interface SwitchProps extends Omit<SwitchPrimitive.RootProps, "checked" | "onCheckedChange">, VariantProps<typeof switchVariants> {
|
|
14
|
+
checked?: boolean;
|
|
15
|
+
defaultChecked?: boolean;
|
|
16
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
17
|
+
checkedIcon?: ReactNode;
|
|
18
|
+
uncheckedIcon?: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const THUMB_SIZES: Record<"sm" | "md" | "lg", number> = {
|
|
22
|
+
sm: 8,
|
|
23
|
+
md: 12,
|
|
24
|
+
lg: 16,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const THUMB_TRANSLATE: Record<"sm" | "md" | "lg", number> = {
|
|
28
|
+
sm: 11,
|
|
29
|
+
md: 15,
|
|
30
|
+
lg: 19,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const switchVariants = cva(
|
|
34
|
+
"rounded-full border-2 items-center shrink-0",
|
|
35
|
+
{
|
|
36
|
+
variants: {
|
|
37
|
+
variant: {
|
|
38
|
+
regular: "",
|
|
39
|
+
},
|
|
40
|
+
size: {
|
|
41
|
+
sm: "h-4 w-6",
|
|
42
|
+
md: "h-5 w-8",
|
|
43
|
+
lg: "h-6 w-10",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
defaultVariants: {
|
|
47
|
+
variant: "regular",
|
|
48
|
+
size: "md",
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
function Switch({
|
|
54
|
+
className,
|
|
55
|
+
size = "md",
|
|
56
|
+
variant,
|
|
57
|
+
checkedIcon,
|
|
58
|
+
uncheckedIcon,
|
|
59
|
+
checked,
|
|
60
|
+
defaultChecked,
|
|
61
|
+
onCheckedChange,
|
|
62
|
+
disabled,
|
|
63
|
+
...props
|
|
64
|
+
}: SwitchProps) {
|
|
65
|
+
const resolvedSize = size ?? "md";
|
|
66
|
+
const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);
|
|
67
|
+
const isControlled = checked !== undefined;
|
|
68
|
+
const isChecked = isControlled ? (checked ?? false) : internalChecked;
|
|
69
|
+
|
|
70
|
+
const translateX = useSharedValue(isChecked ? THUMB_TRANSLATE[resolvedSize] : 2);
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
translateX.value = withTiming(
|
|
74
|
+
isChecked ? THUMB_TRANSLATE[resolvedSize] : 2,
|
|
75
|
+
{ duration: 180, easing: Easing.out(Easing.ease) }
|
|
76
|
+
);
|
|
77
|
+
}, [isChecked, resolvedSize, translateX]);
|
|
78
|
+
|
|
79
|
+
const thumbStyle = useAnimatedStyle(() => ({
|
|
80
|
+
transform: [{ translateX: translateX.value }],
|
|
81
|
+
}));
|
|
82
|
+
|
|
83
|
+
const hasIcons = checkedIcon || uncheckedIcon;
|
|
84
|
+
const thumbSize = THUMB_SIZES[resolvedSize];
|
|
85
|
+
|
|
86
|
+
const handleCheckedChange = (val: boolean) => {
|
|
87
|
+
if (!isControlled) setInternalChecked(val);
|
|
88
|
+
onCheckedChange?.(val);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<SwitchPrimitive.Root
|
|
93
|
+
checked={isChecked}
|
|
94
|
+
onCheckedChange={handleCheckedChange}
|
|
95
|
+
disabled={disabled}
|
|
96
|
+
className={cn(
|
|
97
|
+
switchVariants({ size, variant }),
|
|
98
|
+
disabled
|
|
99
|
+
? "bg-gray-background-soft-muted border-gray-stroke-muted"
|
|
100
|
+
: isChecked
|
|
101
|
+
? "bg-primary-background-fill border-transparent"
|
|
102
|
+
: "bg-surface-card border-gray-stroke-muted",
|
|
103
|
+
className
|
|
104
|
+
)}
|
|
105
|
+
{...props}
|
|
106
|
+
>
|
|
107
|
+
<Animated.View
|
|
108
|
+
style={[
|
|
109
|
+
thumbStyle,
|
|
110
|
+
{
|
|
111
|
+
width: thumbSize,
|
|
112
|
+
height: thumbSize,
|
|
113
|
+
borderRadius: thumbSize / 2,
|
|
114
|
+
},
|
|
115
|
+
]}
|
|
116
|
+
className={cn(
|
|
117
|
+
disabled
|
|
118
|
+
? "bg-gray-background-fill-muted"
|
|
119
|
+
: hasIcons
|
|
120
|
+
? "bg-transparent"
|
|
121
|
+
: isChecked
|
|
122
|
+
? "bg-primary-foreground-onfill"
|
|
123
|
+
: "bg-gray-foreground-muted"
|
|
124
|
+
)}
|
|
125
|
+
>
|
|
126
|
+
{hasIcons && (
|
|
127
|
+
<View className="flex-1 items-center justify-center">
|
|
128
|
+
{isChecked && checkedIcon}
|
|
129
|
+
{!isChecked && uncheckedIcon}
|
|
130
|
+
</View>
|
|
131
|
+
)}
|
|
132
|
+
</Animated.View>
|
|
133
|
+
</SwitchPrimitive.Root>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { Switch, switchVariants };
|
|
138
|
+
export type { SwitchProps };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { type ReactNode, type ReactElement } from "react";
|
|
2
|
+
import { View, Text, type ViewProps } from "react-native";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
interface TagProps extends ViewProps, VariantProps<typeof tagVariants> {
|
|
7
|
+
icon?: ReactElement;
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const tagVariants = cva(
|
|
12
|
+
"flex-row items-center justify-center rounded-md px-2 py-1 gap-1.5 max-h-6 overflow-hidden shrink-0",
|
|
13
|
+
{
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
regular: "bg-primary-background-fill",
|
|
17
|
+
"regular-soft": "bg-primary-background-soft",
|
|
18
|
+
"regular-basic": "bg-transparent",
|
|
19
|
+
emphasis: "bg-secondary-background-fill",
|
|
20
|
+
"emphasis-soft": "bg-secondary-background-soft",
|
|
21
|
+
"emphasis-basic": "bg-transparent",
|
|
22
|
+
gray: "bg-gray-background-fill",
|
|
23
|
+
"gray-soft": "bg-gray-background-soft",
|
|
24
|
+
"gray-basic": "bg-transparent",
|
|
25
|
+
success: "bg-green-background-fill",
|
|
26
|
+
"success-soft": "bg-green-background-soft",
|
|
27
|
+
"success-basic": "bg-transparent",
|
|
28
|
+
error: "bg-red-background-fill",
|
|
29
|
+
"error-soft": "bg-red-background-soft",
|
|
30
|
+
"error-basic": "bg-transparent",
|
|
31
|
+
warning: "bg-yellow-background-fill",
|
|
32
|
+
"warning-soft": "bg-yellow-background-soft",
|
|
33
|
+
"warning-basic": "bg-transparent",
|
|
34
|
+
cm: "bg-cm-background-fill",
|
|
35
|
+
"cm-soft": "bg-cm-background-soft",
|
|
36
|
+
"cm-basic": "bg-transparent",
|
|
37
|
+
go: "bg-go-background-fill",
|
|
38
|
+
"go-soft": "bg-go-background-soft",
|
|
39
|
+
"go-basic": "bg-transparent",
|
|
40
|
+
cir: "bg-cir-background-fill",
|
|
41
|
+
"cir-soft": "bg-cir-background-soft",
|
|
42
|
+
"cir-basic": "bg-transparent",
|
|
43
|
+
ped: "bg-ped-background-fill",
|
|
44
|
+
"ped-soft": "bg-ped-background-soft",
|
|
45
|
+
"ped-basic": "bg-transparent",
|
|
46
|
+
prev: "bg-prev-background-fill",
|
|
47
|
+
"prev-soft": "bg-prev-background-soft",
|
|
48
|
+
"prev-basic": "bg-transparent",
|
|
49
|
+
ia: "bg-secondary-background-fill",
|
|
50
|
+
"ia-soft": "bg-secondary-background-soft",
|
|
51
|
+
"ia-basic": "bg-transparent",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
defaultVariants: { variant: "regular" },
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const tagTextVariants = cva("text-xs font-semibold", {
|
|
59
|
+
variants: {
|
|
60
|
+
variant: {
|
|
61
|
+
regular: "text-primary-foreground-onfill",
|
|
62
|
+
"regular-soft": "text-primary-foreground",
|
|
63
|
+
"regular-basic": "text-primary-foreground",
|
|
64
|
+
emphasis: "text-secondary-foreground-onfill",
|
|
65
|
+
"emphasis-soft": "text-secondary-foreground",
|
|
66
|
+
"emphasis-basic": "text-secondary-foreground",
|
|
67
|
+
gray: "text-gray-foreground-onfill",
|
|
68
|
+
"gray-soft": "text-gray-foreground",
|
|
69
|
+
"gray-basic": "text-gray-foreground",
|
|
70
|
+
success: "text-green-foreground-onfill",
|
|
71
|
+
"success-soft": "text-green-foreground",
|
|
72
|
+
"success-basic": "text-green-foreground",
|
|
73
|
+
error: "text-red-foreground-onfill",
|
|
74
|
+
"error-soft": "text-red-foreground",
|
|
75
|
+
"error-basic": "text-red-foreground",
|
|
76
|
+
warning: "text-yellow-foreground-onfill",
|
|
77
|
+
"warning-soft": "text-yellow-foreground",
|
|
78
|
+
"warning-basic": "text-yellow-foreground",
|
|
79
|
+
cm: "text-cm-foreground-onfill",
|
|
80
|
+
"cm-soft": "text-cm-foreground",
|
|
81
|
+
"cm-basic": "text-cm-foreground",
|
|
82
|
+
go: "text-go-foreground-onfill",
|
|
83
|
+
"go-soft": "text-go-foreground",
|
|
84
|
+
"go-basic": "text-go-foreground",
|
|
85
|
+
cir: "text-cir-foreground-onfill",
|
|
86
|
+
"cir-soft": "text-cir-foreground",
|
|
87
|
+
"cir-basic": "text-cir-foreground",
|
|
88
|
+
ped: "text-ped-foreground-onfill",
|
|
89
|
+
"ped-soft": "text-ped-foreground",
|
|
90
|
+
"ped-basic": "text-ped-foreground",
|
|
91
|
+
prev: "text-prev-foreground-onfill",
|
|
92
|
+
"prev-soft": "text-prev-foreground",
|
|
93
|
+
"prev-basic": "text-prev-foreground",
|
|
94
|
+
ia: "text-primary-foreground-onfill",
|
|
95
|
+
"ia-soft": "text-secondary-foreground",
|
|
96
|
+
"ia-basic": "text-secondary-foreground",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
defaultVariants: { variant: "regular" },
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
function TagIcon({ icon }: { icon?: ReactNode }) {
|
|
103
|
+
return <View className="w-3.5 h-3.5 items-center justify-center">{icon}</View>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function Tag({ className, variant, icon, children, ...props }: TagProps) {
|
|
107
|
+
return (
|
|
108
|
+
<View className={cn(tagVariants({ variant }), className)} {...props}>
|
|
109
|
+
{icon && <TagIcon icon={icon} />}
|
|
110
|
+
<Text className={cn(tagTextVariants({ variant }))}>{children}</Text>
|
|
111
|
+
</View>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export { Tag, tagVariants, tagTextVariants };
|
|
116
|
+
export type { TagProps };
|