@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,224 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
View,
|
|
5
|
+
Text,
|
|
6
|
+
type PressableProps,
|
|
7
|
+
type ViewStyle,
|
|
8
|
+
} from "react-native";
|
|
9
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
11
|
+
import { Loading } from "@/components/Loading";
|
|
12
|
+
import { Badge as BadgeComponent } from "@/components/Badge";
|
|
13
|
+
|
|
14
|
+
interface ButtonProps extends Omit<PressableProps, "children">, VariantProps<typeof buttonVariants> {
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
containerStyle?: ViewStyle;
|
|
17
|
+
iconRight?: ReactNode;
|
|
18
|
+
iconLeft?: ReactNode;
|
|
19
|
+
badge?: number | string;
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
alert?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ICON_ONLY_SIZES: Record<"sm" | "md" | "lg" | "xl", string> = {
|
|
25
|
+
sm: "h-8 min-h-8 w-8",
|
|
26
|
+
md: "h-10 min-h-10 w-10",
|
|
27
|
+
lg: "h-12 min-h-12 w-12",
|
|
28
|
+
xl: "h-14 min-h-14 w-14",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const badgeSizeMap: Record<"sm" | "md" | "lg" | "xl", "sm" | "md" | "lg" | "xl"> = {
|
|
32
|
+
sm: "sm",
|
|
33
|
+
md: "md",
|
|
34
|
+
lg: "md",
|
|
35
|
+
xl: "lg",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const ALERT_DOT_SIZES: Record<"sm" | "md" | "lg" | "xl", number> = {
|
|
39
|
+
sm: 8,
|
|
40
|
+
md: 10,
|
|
41
|
+
lg: 10,
|
|
42
|
+
xl: 12,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const buttonVariants = cva(
|
|
46
|
+
"flex-row items-center justify-center gap-2 rounded-pill font-semibold",
|
|
47
|
+
{
|
|
48
|
+
variants: {
|
|
49
|
+
variant: {
|
|
50
|
+
regular:
|
|
51
|
+
"bg-primary-background-fill active:bg-primary-background-fill-emphasis disabled:bg-gray-background-fill-muted",
|
|
52
|
+
"regular-soft":
|
|
53
|
+
"bg-primary-background-soft active:bg-primary-background-soft-emphasis disabled:bg-gray-background-soft-muted",
|
|
54
|
+
"regular-basic":
|
|
55
|
+
"bg-transparent active:bg-primary-background-soft-emphasis disabled:bg-transparent",
|
|
56
|
+
emphasis:
|
|
57
|
+
"bg-secondary-background-fill active:bg-secondary-background-fill-emphasis disabled:bg-gray-background-fill-muted",
|
|
58
|
+
"emphasis-soft":
|
|
59
|
+
"bg-secondary-background-soft active:bg-secondary-background-soft-emphasis disabled:bg-gray-background-soft-muted",
|
|
60
|
+
"emphasis-basic":
|
|
61
|
+
"bg-transparent active:bg-secondary-background-soft-emphasis disabled:bg-transparent",
|
|
62
|
+
error:
|
|
63
|
+
"bg-red-background-fill active:bg-red-background-fill-emphasis disabled:bg-gray-background-fill-muted",
|
|
64
|
+
"error-soft":
|
|
65
|
+
"bg-red-background-soft active:bg-red-background-soft-emphasis disabled:bg-gray-background-soft-muted",
|
|
66
|
+
"error-basic":
|
|
67
|
+
"bg-transparent active:bg-red-background-soft-emphasis disabled:bg-transparent",
|
|
68
|
+
warning:
|
|
69
|
+
"bg-yellow-background-fill active:bg-yellow-background-fill-emphasis disabled:bg-gray-background-fill-muted",
|
|
70
|
+
"warning-soft":
|
|
71
|
+
"bg-yellow-background-soft active:bg-yellow-background-soft-emphasis disabled:bg-gray-background-soft-muted",
|
|
72
|
+
"warning-basic":
|
|
73
|
+
"bg-transparent active:bg-yellow-background-soft-emphasis disabled:bg-transparent",
|
|
74
|
+
success:
|
|
75
|
+
"bg-green-background-fill active:bg-green-background-fill-emphasis disabled:bg-gray-background-fill-muted",
|
|
76
|
+
"success-soft":
|
|
77
|
+
"bg-green-background-soft active:bg-green-background-soft-emphasis disabled:bg-gray-background-soft-muted",
|
|
78
|
+
"success-basic":
|
|
79
|
+
"bg-transparent active:bg-green-background-soft-emphasis disabled:bg-transparent",
|
|
80
|
+
outlined:
|
|
81
|
+
"border border-gray-stroke-muted bg-transparent active:bg-gray-50 disabled:border-gray-stroke-muted",
|
|
82
|
+
gradient:
|
|
83
|
+
"bg-primary active:opacity-90 disabled:bg-gray-background-fill-muted",
|
|
84
|
+
medbrain:
|
|
85
|
+
"bg-surface-card border-2 border-secondary active:bg-secondary-background-soft disabled:bg-gray-background-fill-muted disabled:border-transparent",
|
|
86
|
+
},
|
|
87
|
+
size: {
|
|
88
|
+
sm: "min-h-8 min-w-8 px-3 py-1",
|
|
89
|
+
md: "min-h-10 min-w-10 px-3.5 py-2",
|
|
90
|
+
lg: "min-h-12 min-w-12 px-4 py-3",
|
|
91
|
+
xl: "min-h-14 min-w-14 px-[18px] py-3.5",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
defaultVariants: {
|
|
95
|
+
variant: "regular",
|
|
96
|
+
size: "md",
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const buttonTextVariants = cva("font-semibold shrink-0", {
|
|
102
|
+
variants: {
|
|
103
|
+
variant: {
|
|
104
|
+
regular: "text-primary-foreground-onfill disabled:text-gray-foreground-onfill",
|
|
105
|
+
"regular-soft": "text-primary-foreground disabled:text-gray-foreground-muted",
|
|
106
|
+
"regular-basic": "text-primary-foreground disabled:text-gray-foreground-muted",
|
|
107
|
+
emphasis: "text-secondary-foreground-onfill disabled:text-gray-foreground-onfill",
|
|
108
|
+
"emphasis-soft": "text-secondary-foreground disabled:text-gray-foreground-muted",
|
|
109
|
+
"emphasis-basic": "text-secondary-foreground disabled:text-gray-foreground-muted",
|
|
110
|
+
error: "text-red-foreground-onfill disabled:text-gray-foreground-onfill",
|
|
111
|
+
"error-soft": "text-red-foreground disabled:text-gray-foreground-muted",
|
|
112
|
+
"error-basic": "text-red-foreground disabled:text-gray-foreground-muted",
|
|
113
|
+
warning: "text-yellow-foreground-onfill disabled:text-gray-foreground-onfill",
|
|
114
|
+
"warning-soft": "text-yellow-foreground disabled:text-gray-foreground-muted",
|
|
115
|
+
"warning-basic": "text-yellow-foreground disabled:text-gray-foreground-muted",
|
|
116
|
+
success: "text-green-foreground-onfill disabled:text-gray-foreground-onfill",
|
|
117
|
+
"success-soft": "text-green-foreground disabled:text-gray-foreground-muted",
|
|
118
|
+
"success-basic": "text-green-foreground disabled:text-gray-foreground-muted",
|
|
119
|
+
outlined: "text-foreground disabled:text-gray-foreground-muted",
|
|
120
|
+
gradient: "text-white disabled:text-gray-foreground-onfill",
|
|
121
|
+
medbrain: "text-secondary disabled:text-gray-foreground-onfill",
|
|
122
|
+
},
|
|
123
|
+
size: {
|
|
124
|
+
sm: "text-xs",
|
|
125
|
+
md: "text-sm",
|
|
126
|
+
lg: "text-md",
|
|
127
|
+
xl: "text-lg",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
defaultVariants: {
|
|
131
|
+
variant: "regular",
|
|
132
|
+
size: "md",
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
function shouldShowBadge(value: number | string | undefined) {
|
|
137
|
+
return value != null && value !== 0 && value !== "" && value !== "0";
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function Button({
|
|
141
|
+
className,
|
|
142
|
+
containerStyle,
|
|
143
|
+
variant = "regular",
|
|
144
|
+
size = "md",
|
|
145
|
+
iconRight,
|
|
146
|
+
iconLeft,
|
|
147
|
+
badge,
|
|
148
|
+
loading = false,
|
|
149
|
+
alert,
|
|
150
|
+
disabled,
|
|
151
|
+
children,
|
|
152
|
+
...props
|
|
153
|
+
}: ButtonProps) {
|
|
154
|
+
const resolvedSize = size ?? "md";
|
|
155
|
+
const resolvedVariant = variant ?? "regular";
|
|
156
|
+
const isIconOnly = !children && !alert && (!!iconLeft || !!iconRight);
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<View style={[{ position: "relative" }, containerStyle]}>
|
|
160
|
+
{shouldShowBadge(badge) && (
|
|
161
|
+
<View className="absolute -right-2 -top-1 z-10">
|
|
162
|
+
<BadgeComponent size={badgeSizeMap[resolvedSize]} variant="regular">
|
|
163
|
+
{String(badge)}
|
|
164
|
+
</BadgeComponent>
|
|
165
|
+
</View>
|
|
166
|
+
)}
|
|
167
|
+
|
|
168
|
+
<Pressable
|
|
169
|
+
disabled={disabled || loading}
|
|
170
|
+
accessibilityRole="button"
|
|
171
|
+
accessibilityState={{ disabled: disabled || loading, busy: loading }}
|
|
172
|
+
className={cn(
|
|
173
|
+
buttonVariants({ variant, size }),
|
|
174
|
+
isIconOnly && ICON_ONLY_SIZES[resolvedSize],
|
|
175
|
+
className
|
|
176
|
+
)}
|
|
177
|
+
{...props}
|
|
178
|
+
>
|
|
179
|
+
{loading ? (
|
|
180
|
+
<>
|
|
181
|
+
<View className="absolute">
|
|
182
|
+
<Loading size={resolvedSize === "sm" ? 16 : resolvedSize === "xl" ? 24 : 20} />
|
|
183
|
+
</View>
|
|
184
|
+
<View className="opacity-0 flex-row items-center gap-2">
|
|
185
|
+
{iconLeft}
|
|
186
|
+
{children != null && (
|
|
187
|
+
<Text className={cn(buttonTextVariants({ variant: resolvedVariant, size }))}>
|
|
188
|
+
{children}
|
|
189
|
+
</Text>
|
|
190
|
+
)}
|
|
191
|
+
{iconRight}
|
|
192
|
+
</View>
|
|
193
|
+
</>
|
|
194
|
+
) : (
|
|
195
|
+
<>
|
|
196
|
+
{alert ? (
|
|
197
|
+
<View className="relative mr-1 flex-row items-center">
|
|
198
|
+
<View
|
|
199
|
+
className="rounded-full opacity-75"
|
|
200
|
+
style={{
|
|
201
|
+
width: ALERT_DOT_SIZES[resolvedSize],
|
|
202
|
+
height: ALERT_DOT_SIZES[resolvedSize],
|
|
203
|
+
backgroundColor: alert,
|
|
204
|
+
}}
|
|
205
|
+
/>
|
|
206
|
+
</View>
|
|
207
|
+
) : (
|
|
208
|
+
iconLeft
|
|
209
|
+
)}
|
|
210
|
+
{children != null && (
|
|
211
|
+
<Text className={cn(buttonTextVariants({ variant: resolvedVariant, size }))}>
|
|
212
|
+
{children}
|
|
213
|
+
</Text>
|
|
214
|
+
)}
|
|
215
|
+
{iconRight}
|
|
216
|
+
</>
|
|
217
|
+
)}
|
|
218
|
+
</Pressable>
|
|
219
|
+
</View>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export { Button, buttonVariants, buttonTextVariants };
|
|
224
|
+
export type { ButtonProps };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import * as CheckboxPrimitive from "@rn-primitives/checkbox";
|
|
3
|
+
import { Check, RemoveMinus } from "@medway-ui/icons/native";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
interface CheckboxProps extends Omit<CheckboxPrimitive.RootProps, "checked" | "disabled" | "onCheckedChange"> {
|
|
8
|
+
checked?: boolean;
|
|
9
|
+
defaultChecked?: boolean;
|
|
10
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
size?: "sm" | "md" | "lg";
|
|
13
|
+
variant?: "regular";
|
|
14
|
+
uncheckIcon?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ICON_SIZES: Record<"sm" | "md" | "lg", number> = {
|
|
18
|
+
sm: 12,
|
|
19
|
+
md: 16,
|
|
20
|
+
lg: 20,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const checkboxVariants = cva(
|
|
24
|
+
"items-center justify-center rounded-sm border-2 shrink-0",
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
variant: {
|
|
28
|
+
regular: "bg-surface-card border-gray-stroke-muted",
|
|
29
|
+
},
|
|
30
|
+
size: {
|
|
31
|
+
sm: "h-4 w-4",
|
|
32
|
+
md: "h-5 w-5",
|
|
33
|
+
lg: "h-6 w-6",
|
|
34
|
+
},
|
|
35
|
+
checked: {
|
|
36
|
+
true: "bg-primary-background-fill border-primary-background-fill",
|
|
37
|
+
false: "",
|
|
38
|
+
},
|
|
39
|
+
disabled: {
|
|
40
|
+
true: "bg-gray-background-soft-muted border-gray-stroke-muted",
|
|
41
|
+
false: "",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
defaultVariants: {
|
|
45
|
+
variant: "regular",
|
|
46
|
+
size: "md",
|
|
47
|
+
checked: false,
|
|
48
|
+
disabled: false,
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
function Checkbox({
|
|
54
|
+
className,
|
|
55
|
+
size = "md",
|
|
56
|
+
variant,
|
|
57
|
+
uncheckIcon,
|
|
58
|
+
checked,
|
|
59
|
+
defaultChecked = false,
|
|
60
|
+
onCheckedChange,
|
|
61
|
+
disabled,
|
|
62
|
+
...props
|
|
63
|
+
}: CheckboxProps) {
|
|
64
|
+
const resolvedSize = size ?? "md";
|
|
65
|
+
const iconSize = ICON_SIZES[resolvedSize];
|
|
66
|
+
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
|
67
|
+
const isControlled = checked !== undefined;
|
|
68
|
+
const isChecked = isControlled ? checked : internalChecked;
|
|
69
|
+
|
|
70
|
+
const handleCheckedChange = (val: boolean) => {
|
|
71
|
+
if (!isControlled) setInternalChecked(val);
|
|
72
|
+
onCheckedChange?.(val);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<CheckboxPrimitive.Root
|
|
77
|
+
checked={isChecked}
|
|
78
|
+
onCheckedChange={handleCheckedChange}
|
|
79
|
+
disabled={disabled}
|
|
80
|
+
className={cn(
|
|
81
|
+
checkboxVariants({ size, variant, checked: isChecked, disabled: disabled ?? false }),
|
|
82
|
+
className
|
|
83
|
+
)}
|
|
84
|
+
{...props}
|
|
85
|
+
>
|
|
86
|
+
<CheckboxPrimitive.Indicator className="items-center justify-center">
|
|
87
|
+
{uncheckIcon ? (
|
|
88
|
+
<RemoveMinus
|
|
89
|
+
size={iconSize}
|
|
90
|
+
strokeWidth={2.6}
|
|
91
|
+
className="text-primary-foreground-onfill"
|
|
92
|
+
/>
|
|
93
|
+
) : (
|
|
94
|
+
<Check
|
|
95
|
+
size={iconSize}
|
|
96
|
+
strokeWidth={2.6}
|
|
97
|
+
className="text-primary-foreground-onfill"
|
|
98
|
+
/>
|
|
99
|
+
)}
|
|
100
|
+
</CheckboxPrimitive.Indicator>
|
|
101
|
+
</CheckboxPrimitive.Root>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { Checkbox, checkboxVariants };
|
|
106
|
+
export type { CheckboxProps };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { type ReactNode, isValidElement, cloneElement, type ReactElement } from "react";
|
|
2
|
+
import { View, Text, 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
|
+
interface DialogContainerProps extends DialogPrimitive.ContentProps {
|
|
9
|
+
showCloseButton?: boolean;
|
|
10
|
+
overlayClassName?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface DialogHeaderProps extends ViewProps {
|
|
14
|
+
separator?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface DialogFooterProps extends ViewProps {
|
|
18
|
+
separator?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface DialogTitleProps extends DialogPrimitive.TitleProps {
|
|
22
|
+
iconLeft?: ReactNode;
|
|
23
|
+
iconRight?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function Dialog({ ...props }: DialogPrimitive.RootProps) {
|
|
27
|
+
return <DialogPrimitive.Root {...props} />;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function DialogTrigger({ ...props }: DialogPrimitive.TriggerProps) {
|
|
31
|
+
return <DialogPrimitive.Trigger {...props} />;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function DialogPortal({ ...props }: DialogPrimitive.PortalProps) {
|
|
35
|
+
return <DialogPrimitive.Portal {...props} />;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function DialogClose({ ...props }: DialogPrimitive.CloseProps) {
|
|
39
|
+
return <DialogPrimitive.Close {...props} />;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function DialogOverlay({ className, ...props }: DialogPrimitive.OverlayProps) {
|
|
43
|
+
return (
|
|
44
|
+
<DialogPrimitive.Overlay
|
|
45
|
+
className={cn("absolute inset-0 bg-black/50", className)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function DialogContainer({
|
|
52
|
+
className,
|
|
53
|
+
overlayClassName,
|
|
54
|
+
children,
|
|
55
|
+
showCloseButton = true,
|
|
56
|
+
...props
|
|
57
|
+
}: DialogContainerProps) {
|
|
58
|
+
return (
|
|
59
|
+
<DialogPrimitive.Portal>
|
|
60
|
+
<DialogPrimitive.Overlay
|
|
61
|
+
className={cn("absolute inset-0 items-center justify-center bg-black/50", overlayClassName)}
|
|
62
|
+
>
|
|
63
|
+
<DialogPrimitive.Content
|
|
64
|
+
className={cn(
|
|
65
|
+
"relative flex-col max-h-[90%] w-full max-w-[calc(100%-2rem)] rounded-xl bg-background shadow-lg overflow-hidden",
|
|
66
|
+
className
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
>
|
|
70
|
+
{children}
|
|
71
|
+
{showCloseButton && (
|
|
72
|
+
<DialogPrimitive.Close className="absolute right-3 top-3 rounded-pill p-1.5 active:bg-gray-background-soft">
|
|
73
|
+
<CloseMd size={16} className="text-gray-foreground" />
|
|
74
|
+
</DialogPrimitive.Close>
|
|
75
|
+
)}
|
|
76
|
+
</DialogPrimitive.Content>
|
|
77
|
+
</DialogPrimitive.Overlay>
|
|
78
|
+
</DialogPrimitive.Portal>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function DialogContent({
|
|
83
|
+
containerClassName,
|
|
84
|
+
className,
|
|
85
|
+
children,
|
|
86
|
+
}: {
|
|
87
|
+
containerClassName?: string;
|
|
88
|
+
className?: string;
|
|
89
|
+
children: ReactNode;
|
|
90
|
+
}) {
|
|
91
|
+
return (
|
|
92
|
+
<ScrollView
|
|
93
|
+
className={cn("flex-1", containerClassName)}
|
|
94
|
+
contentContainerStyle={{ flexGrow: 1 }}
|
|
95
|
+
>
|
|
96
|
+
<View className={cn("px-8 py-6", className)}>
|
|
97
|
+
{children}
|
|
98
|
+
</View>
|
|
99
|
+
</ScrollView>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function DialogHeader({ className, separator = false, children, ...props }: DialogHeaderProps) {
|
|
104
|
+
return (
|
|
105
|
+
<>
|
|
106
|
+
<View className={cn("flex-col gap-2 px-8 pt-8 pb-4", className)} {...props}>
|
|
107
|
+
{children}
|
|
108
|
+
</View>
|
|
109
|
+
{separator && <Separator />}
|
|
110
|
+
</>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function DialogFooter({ className, separator = false, children, ...props }: DialogFooterProps) {
|
|
115
|
+
return (
|
|
116
|
+
<>
|
|
117
|
+
{separator && <Separator />}
|
|
118
|
+
<View
|
|
119
|
+
className={cn("flex-col gap-2 px-8 py-6", className)}
|
|
120
|
+
{...props}
|
|
121
|
+
>
|
|
122
|
+
{children}
|
|
123
|
+
</View>
|
|
124
|
+
</>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function DialogTitle({ className, iconLeft, iconRight, children, ...props }: DialogTitleProps) {
|
|
129
|
+
const renderIcon = (icon: ReactNode) => {
|
|
130
|
+
if (isValidElement(icon)) {
|
|
131
|
+
return cloneElement(icon as ReactElement<{ size?: number; strokeWidth?: number }>, {
|
|
132
|
+
size: 32,
|
|
133
|
+
strokeWidth: 2.2,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return icon;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<DialogPrimitive.Title
|
|
141
|
+
className={cn("flex-row items-center gap-3", className)}
|
|
142
|
+
{...props}
|
|
143
|
+
>
|
|
144
|
+
{iconLeft && renderIcon(iconLeft)}
|
|
145
|
+
<Text className="text-title-md font-semibold leading-title-md text-content-title flex-1">
|
|
146
|
+
{children as string}
|
|
147
|
+
</Text>
|
|
148
|
+
{iconRight && renderIcon(iconRight)}
|
|
149
|
+
</DialogPrimitive.Title>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function DialogDescription({ className, ...props }: DialogPrimitive.DescriptionProps) {
|
|
154
|
+
return (
|
|
155
|
+
<DialogPrimitive.Description
|
|
156
|
+
className={cn("text-md leading-md text-content-paragraph", className)}
|
|
157
|
+
{...props}
|
|
158
|
+
/>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export {
|
|
163
|
+
Dialog,
|
|
164
|
+
DialogClose,
|
|
165
|
+
DialogContainer,
|
|
166
|
+
DialogContent,
|
|
167
|
+
DialogDescription,
|
|
168
|
+
DialogFooter,
|
|
169
|
+
DialogHeader,
|
|
170
|
+
DialogOverlay,
|
|
171
|
+
DialogPortal,
|
|
172
|
+
DialogTitle,
|
|
173
|
+
DialogTrigger,
|
|
174
|
+
};
|
|
175
|
+
export type { DialogContainerProps, DialogHeaderProps, DialogFooterProps, DialogTitleProps };
|