@beyondcorp/beyond-ui-native 0.1.1 → 0.1.3
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/{chunk-2B6HTSGM.mjs → chunk-RNHEGFYR.mjs} +16 -2
- package/dist/chunk-RNHEGFYR.mjs.map +1 -0
- package/dist/index.d.mts +2 -145
- package/dist/index.d.ts +2 -145
- package/dist/index.js +37 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -8
- package/dist/index.mjs.map +1 -1
- package/dist/preset-BmUHLoAa.d.mts +274 -0
- package/dist/preset-BmUHLoAa.d.ts +274 -0
- package/dist/preset.d.mts +1 -117
- package/dist/preset.d.ts +1 -117
- package/dist/preset.js +19 -3
- package/dist/preset.js.map +1 -1
- package/dist/preset.mjs +5 -3
- package/package.json +11 -5
- package/src/components/accordion/accordion.tsx +245 -0
- package/src/components/accordion/index.ts +1 -0
- package/src/components/alert/alert.tsx +118 -0
- package/src/components/alert/index.ts +1 -0
- package/src/components/avatar/avatar.tsx +125 -0
- package/src/components/avatar/index.ts +1 -0
- package/src/components/badge/badge.tsx +89 -0
- package/src/components/badge/index.ts +1 -0
- package/src/components/bottom-sheet/bottom-sheet.tsx +336 -0
- package/src/components/bottom-sheet/index.ts +1 -0
- package/src/components/button/button.tsx +172 -0
- package/src/components/button/index.ts +1 -0
- package/src/components/card/card.tsx +121 -0
- package/src/components/card/index.ts +1 -0
- package/src/components/checkbox/checkbox.tsx +100 -0
- package/src/components/checkbox/index.ts +1 -0
- package/src/components/data-table/data-table.tsx +277 -0
- package/src/components/data-table/index.ts +1 -0
- package/src/components/dialog/dialog.tsx +278 -0
- package/src/components/dialog/index.ts +1 -0
- package/src/components/input/index.ts +1 -0
- package/src/components/input/input.tsx +130 -0
- package/src/components/radio/index.ts +1 -0
- package/src/components/radio/radio.tsx +117 -0
- package/src/components/select/index.ts +1 -0
- package/src/components/select/select.tsx +375 -0
- package/src/components/separator/index.ts +1 -0
- package/src/components/separator/separator.tsx +28 -0
- package/src/components/skeleton/index.ts +1 -0
- package/src/components/skeleton/skeleton.tsx +43 -0
- package/src/components/spinner/index.ts +1 -0
- package/src/components/spinner/spinner.tsx +46 -0
- package/src/components/stats-card/index.ts +1 -0
- package/src/components/stats-card/stats-card.tsx +92 -0
- package/src/components/switch/index.ts +1 -0
- package/src/components/switch/switch.tsx +80 -0
- package/src/components/tabs/index.ts +1 -0
- package/src/components/tabs/tabs.tsx +172 -0
- package/src/components/text/heading.tsx +50 -0
- package/src/components/text/index.ts +2 -0
- package/src/components/text/text.tsx +62 -0
- package/src/components/textarea/index.ts +1 -0
- package/src/components/textarea/textarea.tsx +87 -0
- package/src/components/toast/index.ts +2 -0
- package/src/components/toast/toast.tsx +136 -0
- package/src/components/toast/types.ts +32 -0
- package/src/index.ts +42 -0
- package/src/primitives/box.tsx +25 -0
- package/src/primitives/index.ts +2 -0
- package/src/primitives/pressable.tsx +49 -0
- package/src/providers/BeyondUIProvider.tsx +100 -0
- package/src/templates/auth/ForgotPasswordTemplate.tsx +132 -0
- package/src/templates/auth/SignInTemplate.tsx +213 -0
- package/src/templates/auth/SignUpTemplate.tsx +233 -0
- package/src/templates/auth/index.ts +3 -0
- package/src/templates/dashboard/DashboardTemplate.tsx +205 -0
- package/src/templates/dashboard/index.ts +1 -0
- package/src/templates/index.ts +3 -0
- package/src/templates/settings/SettingsTemplate.tsx +226 -0
- package/src/templates/settings/index.ts +1 -0
- package/src/theme/preset.ts +45 -0
- package/src/theme/tokens.ts +144 -0
- package/src/types/nativewind-env.d.ts +26 -0
- package/src/utilities/accessibility.ts +43 -0
- package/src/utilities/cn.ts +9 -0
- package/src/utilities/index.ts +2 -0
- package/dist/chunk-2B6HTSGM.mjs.map +0 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, Text, Image as NativeImage, type ImageProps, type ViewProps } from "react-native";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { cn } from "../../utilities/cn";
|
|
5
|
+
|
|
6
|
+
export const avatarVariants = cva(
|
|
7
|
+
"relative flex shrink-0 overflow-hidden rounded-full items-center justify-center bg-neutral-200 dark:bg-neutral-800",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
size: {
|
|
11
|
+
sm: "h-8 w-8",
|
|
12
|
+
md: "h-10 w-10",
|
|
13
|
+
lg: "h-14 w-14",
|
|
14
|
+
xl: "h-20 w-20",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
size: "md",
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export const avatarTextVariants = cva("font-semibold text-neutral-700 dark:text-neutral-300", {
|
|
24
|
+
variants: {
|
|
25
|
+
size: {
|
|
26
|
+
sm: "text-xs",
|
|
27
|
+
md: "text-sm",
|
|
28
|
+
lg: "text-lg",
|
|
29
|
+
xl: "text-2xl",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
defaultVariants: {
|
|
33
|
+
size: "md",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
interface AvatarContextValue {
|
|
38
|
+
size: "sm" | "md" | "lg" | "xl";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const AvatarContext = React.createContext<AvatarContextValue>({ size: "md" });
|
|
42
|
+
|
|
43
|
+
export interface AvatarProps
|
|
44
|
+
extends ViewProps,
|
|
45
|
+
VariantProps<typeof avatarVariants> {
|
|
46
|
+
className?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function Avatar({
|
|
50
|
+
className,
|
|
51
|
+
size = "md",
|
|
52
|
+
children,
|
|
53
|
+
...props
|
|
54
|
+
}: AvatarProps) {
|
|
55
|
+
const currentSize = size ?? "md";
|
|
56
|
+
return (
|
|
57
|
+
<AvatarContext.Provider value={{ size: currentSize }}>
|
|
58
|
+
<View
|
|
59
|
+
className={cn(avatarVariants({ size: currentSize }), className)}
|
|
60
|
+
{...props}
|
|
61
|
+
>
|
|
62
|
+
{children}
|
|
63
|
+
</View>
|
|
64
|
+
</AvatarContext.Provider>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
Avatar.displayName = "Avatar";
|
|
68
|
+
|
|
69
|
+
export interface AvatarImageProps extends ImageProps {
|
|
70
|
+
className?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function AvatarImage({ className, ...props }: AvatarImageProps) {
|
|
74
|
+
const [hasError, setHasError] = React.useState(false);
|
|
75
|
+
|
|
76
|
+
if (hasError) return null;
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<NativeImage
|
|
80
|
+
onError={() => setHasError(true)}
|
|
81
|
+
className={cn("h-full w-full rounded-full object-cover", className)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
AvatarImage.displayName = "Avatar.Image";
|
|
87
|
+
|
|
88
|
+
export interface AvatarFallbackProps extends ViewProps {
|
|
89
|
+
children?: React.ReactNode;
|
|
90
|
+
text?: string;
|
|
91
|
+
className?: string;
|
|
92
|
+
textClassName?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function AvatarFallback({
|
|
96
|
+
children,
|
|
97
|
+
text,
|
|
98
|
+
className,
|
|
99
|
+
textClassName,
|
|
100
|
+
...props
|
|
101
|
+
}: AvatarFallbackProps) {
|
|
102
|
+
const { size } = React.useContext(AvatarContext);
|
|
103
|
+
const content = text ?? children;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<View
|
|
107
|
+
className={cn(
|
|
108
|
+
"h-full w-full items-center justify-center rounded-full bg-neutral-200 dark:bg-neutral-800",
|
|
109
|
+
className
|
|
110
|
+
)}
|
|
111
|
+
{...props}
|
|
112
|
+
>
|
|
113
|
+
{typeof content === "string" ? (
|
|
114
|
+
<Text
|
|
115
|
+
className={cn(avatarTextVariants({ size }), textClassName)}
|
|
116
|
+
>
|
|
117
|
+
{content}
|
|
118
|
+
</Text>
|
|
119
|
+
) : (
|
|
120
|
+
content
|
|
121
|
+
)}
|
|
122
|
+
</View>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
AvatarFallback.displayName = "Avatar.Fallback";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./avatar";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, Text, type ViewProps } from "react-native";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { cn } from "../../utilities/cn";
|
|
5
|
+
|
|
6
|
+
export const badgeVariants = cva(
|
|
7
|
+
"inline-flex flex-row items-center justify-center rounded-full self-start",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
primary: "bg-primary-600 dark:bg-primary-500",
|
|
12
|
+
secondary: "bg-secondary-600 dark:bg-secondary-500",
|
|
13
|
+
danger: "bg-danger-600 dark:bg-danger-500",
|
|
14
|
+
destructive: "bg-danger-600 dark:bg-danger-500",
|
|
15
|
+
success: "bg-success-600 dark:bg-success-500",
|
|
16
|
+
warning: "bg-warning-600 dark:bg-warning-500",
|
|
17
|
+
outline: "border border-neutral-300 dark:border-neutral-700 bg-transparent",
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
sm: "px-2 py-0.5",
|
|
21
|
+
md: "px-2.5 py-1",
|
|
22
|
+
lg: "px-3.5 py-1.5",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "primary",
|
|
27
|
+
size: "md",
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const badgeTextVariants = cva("font-semibold text-center", {
|
|
33
|
+
variants: {
|
|
34
|
+
variant: {
|
|
35
|
+
primary: "text-white",
|
|
36
|
+
secondary: "text-white",
|
|
37
|
+
danger: "text-white",
|
|
38
|
+
destructive: "text-white",
|
|
39
|
+
success: "text-white",
|
|
40
|
+
warning: "text-white",
|
|
41
|
+
outline: "text-neutral-700 dark:text-neutral-300",
|
|
42
|
+
},
|
|
43
|
+
size: {
|
|
44
|
+
sm: "text-[10px]",
|
|
45
|
+
md: "text-xs",
|
|
46
|
+
lg: "text-sm",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
variant: "primary",
|
|
51
|
+
size: "md",
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export interface BadgeProps
|
|
56
|
+
extends ViewProps,
|
|
57
|
+
VariantProps<typeof badgeVariants> {
|
|
58
|
+
children?: React.ReactNode;
|
|
59
|
+
className?: string;
|
|
60
|
+
textClassName?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function Badge({
|
|
64
|
+
children,
|
|
65
|
+
variant = "primary",
|
|
66
|
+
size = "md",
|
|
67
|
+
className,
|
|
68
|
+
textClassName,
|
|
69
|
+
...props
|
|
70
|
+
}: BadgeProps) {
|
|
71
|
+
return (
|
|
72
|
+
<View
|
|
73
|
+
className={cn(badgeVariants({ variant, size }), className)}
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
{typeof children === "string" || typeof children === "number" ? (
|
|
77
|
+
<Text
|
|
78
|
+
className={cn(badgeTextVariants({ variant, size }), textClassName)}
|
|
79
|
+
>
|
|
80
|
+
{children}
|
|
81
|
+
</Text>
|
|
82
|
+
) : (
|
|
83
|
+
children
|
|
84
|
+
)}
|
|
85
|
+
</View>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Badge.displayName = "Badge";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./badge";
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Modal,
|
|
4
|
+
View,
|
|
5
|
+
Pressable,
|
|
6
|
+
Animated,
|
|
7
|
+
PanResponder,
|
|
8
|
+
Dimensions,
|
|
9
|
+
type ViewProps,
|
|
10
|
+
type PressableProps,
|
|
11
|
+
} from "react-native";
|
|
12
|
+
import { cn } from "../../utilities/cn";
|
|
13
|
+
import { Text } from "../text/text";
|
|
14
|
+
import { Heading } from "../text/heading";
|
|
15
|
+
|
|
16
|
+
interface BottomSheetContextValue {
|
|
17
|
+
open: boolean;
|
|
18
|
+
setOpen: (open: boolean) => void;
|
|
19
|
+
closeSheet: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const BottomSheetContext = React.createContext<BottomSheetContextValue | null>(null);
|
|
23
|
+
|
|
24
|
+
function useBottomSheetContext() {
|
|
25
|
+
const context = React.useContext(BottomSheetContext);
|
|
26
|
+
if (!context) {
|
|
27
|
+
throw new Error("BottomSheet components must be used within a BottomSheet");
|
|
28
|
+
}
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface BottomSheetProps {
|
|
33
|
+
open?: boolean;
|
|
34
|
+
defaultOpen?: boolean;
|
|
35
|
+
onOpenChange?: (open: boolean) => void;
|
|
36
|
+
children: React.ReactNode;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const BottomSheet: React.FC<BottomSheetProps> = ({
|
|
40
|
+
open: controlledOpen,
|
|
41
|
+
defaultOpen = false,
|
|
42
|
+
onOpenChange,
|
|
43
|
+
children,
|
|
44
|
+
}) => {
|
|
45
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
|
|
46
|
+
const isControlled = controlledOpen !== undefined;
|
|
47
|
+
const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
|
|
48
|
+
|
|
49
|
+
const setOpen = React.useCallback(
|
|
50
|
+
(nextOpen: boolean) => {
|
|
51
|
+
if (!isControlled) {
|
|
52
|
+
setUncontrolledOpen(nextOpen);
|
|
53
|
+
}
|
|
54
|
+
onOpenChange?.(nextOpen);
|
|
55
|
+
},
|
|
56
|
+
[isControlled, onOpenChange]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const closeSheet = React.useCallback(() => {
|
|
60
|
+
setOpen(false);
|
|
61
|
+
}, [setOpen]);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<BottomSheetContext.Provider value={{ open: isOpen, setOpen, closeSheet }}>
|
|
65
|
+
{children}
|
|
66
|
+
</BottomSheetContext.Provider>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// --- BottomSheetTrigger ---
|
|
71
|
+
|
|
72
|
+
export interface BottomSheetTriggerProps extends PressableProps {
|
|
73
|
+
asChild?: boolean;
|
|
74
|
+
className?: string;
|
|
75
|
+
children: React.ReactNode;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const BottomSheetTrigger = React.forwardRef<View, BottomSheetTriggerProps>(
|
|
79
|
+
({ asChild, children, onPress, ...props }, ref) => {
|
|
80
|
+
const { setOpen } = useBottomSheetContext();
|
|
81
|
+
|
|
82
|
+
const handlePress = (e: any) => {
|
|
83
|
+
setOpen(true);
|
|
84
|
+
onPress?.(e);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
if (asChild && React.isValidElement(children)) {
|
|
88
|
+
return React.cloneElement(children as React.ReactElement<any>, {
|
|
89
|
+
ref,
|
|
90
|
+
onPress: handlePress,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<Pressable ref={ref} onPress={handlePress} {...props}>
|
|
96
|
+
{children}
|
|
97
|
+
</Pressable>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
BottomSheetTrigger.displayName = "BottomSheetTrigger";
|
|
102
|
+
|
|
103
|
+
// --- BottomSheetContent ---
|
|
104
|
+
|
|
105
|
+
export interface BottomSheetContentProps extends ViewProps {
|
|
106
|
+
className?: string;
|
|
107
|
+
children: React.ReactNode;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const BottomSheetContent = React.forwardRef<View, BottomSheetContentProps>(
|
|
111
|
+
({ className, children, ...props }, ref) => {
|
|
112
|
+
const { open, closeSheet } = useBottomSheetContext();
|
|
113
|
+
const screenHeight = Dimensions.get("window").height;
|
|
114
|
+
|
|
115
|
+
const translateY = React.useRef(new Animated.Value(screenHeight)).current;
|
|
116
|
+
const backdropOpacity = React.useRef(new Animated.Value(0)).current;
|
|
117
|
+
|
|
118
|
+
React.useEffect(() => {
|
|
119
|
+
if (open) {
|
|
120
|
+
Animated.parallel([
|
|
121
|
+
Animated.spring(translateY, {
|
|
122
|
+
toValue: 0,
|
|
123
|
+
useNativeDriver: true,
|
|
124
|
+
bounciness: 4,
|
|
125
|
+
}),
|
|
126
|
+
Animated.timing(backdropOpacity, {
|
|
127
|
+
toValue: 1,
|
|
128
|
+
duration: 250,
|
|
129
|
+
useNativeDriver: true,
|
|
130
|
+
}),
|
|
131
|
+
]).start();
|
|
132
|
+
} else {
|
|
133
|
+
Animated.parallel([
|
|
134
|
+
Animated.timing(translateY, {
|
|
135
|
+
toValue: screenHeight,
|
|
136
|
+
duration: 200,
|
|
137
|
+
useNativeDriver: true,
|
|
138
|
+
}),
|
|
139
|
+
Animated.timing(backdropOpacity, {
|
|
140
|
+
toValue: 0,
|
|
141
|
+
duration: 200,
|
|
142
|
+
useNativeDriver: true,
|
|
143
|
+
}),
|
|
144
|
+
]).start();
|
|
145
|
+
}
|
|
146
|
+
}, [open, translateY, backdropOpacity, screenHeight]);
|
|
147
|
+
|
|
148
|
+
// PanResponder for drag down to dismiss
|
|
149
|
+
const panResponder = React.useRef(
|
|
150
|
+
PanResponder.create({
|
|
151
|
+
onStartShouldSetPanResponder: () => true,
|
|
152
|
+
onMoveShouldSetPanResponder: (_, gestureState) => gestureState.dy > 5,
|
|
153
|
+
onPanResponderMove: (_, gestureState) => {
|
|
154
|
+
if (gestureState.dy > 0) {
|
|
155
|
+
translateY.setValue(gestureState.dy);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
onPanResponderRelease: (_, gestureState) => {
|
|
159
|
+
if (gestureState.dy > 120 || gestureState.vy > 0.8) {
|
|
160
|
+
closeSheet();
|
|
161
|
+
} else {
|
|
162
|
+
Animated.spring(translateY, {
|
|
163
|
+
toValue: 0,
|
|
164
|
+
useNativeDriver: true,
|
|
165
|
+
bounciness: 4,
|
|
166
|
+
}).start();
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
})
|
|
170
|
+
).current;
|
|
171
|
+
|
|
172
|
+
if (!open) return null;
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<Modal
|
|
176
|
+
transparent
|
|
177
|
+
visible={open}
|
|
178
|
+
animationType="none"
|
|
179
|
+
onRequestClose={closeSheet}
|
|
180
|
+
statusBarTranslucent
|
|
181
|
+
>
|
|
182
|
+
<View className="flex-1 justify-end">
|
|
183
|
+
{/* Backdrop */}
|
|
184
|
+
<Animated.View
|
|
185
|
+
style={{ opacity: backdropOpacity }}
|
|
186
|
+
className="absolute inset-0 bg-black/60"
|
|
187
|
+
>
|
|
188
|
+
<Pressable className="flex-1" onPress={closeSheet} />
|
|
189
|
+
</Animated.View>
|
|
190
|
+
|
|
191
|
+
{/* Sheet Container */}
|
|
192
|
+
<Animated.View
|
|
193
|
+
ref={ref}
|
|
194
|
+
style={{ transform: [{ translateY }] }}
|
|
195
|
+
className={cn(
|
|
196
|
+
"w-full bg-card rounded-t-3xl border-t border-border shadow-2xl pt-2 pb-8 px-6 max-h-[85%]",
|
|
197
|
+
className
|
|
198
|
+
)}
|
|
199
|
+
{...props}
|
|
200
|
+
>
|
|
201
|
+
{/* Drag Handle Bar */}
|
|
202
|
+
<View {...panResponder.panHandlers} className="w-full py-2 items-center">
|
|
203
|
+
<View className="w-12 h-1.5 rounded-full bg-muted/40" />
|
|
204
|
+
</View>
|
|
205
|
+
|
|
206
|
+
{children}
|
|
207
|
+
</Animated.View>
|
|
208
|
+
</View>
|
|
209
|
+
</Modal>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
BottomSheetContent.displayName = "BottomSheetContent";
|
|
214
|
+
|
|
215
|
+
// --- BottomSheetHeader ---
|
|
216
|
+
|
|
217
|
+
export interface BottomSheetHeaderProps extends ViewProps {
|
|
218
|
+
className?: string;
|
|
219
|
+
children: React.ReactNode;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const BottomSheetHeader = React.forwardRef<View, BottomSheetHeaderProps>(
|
|
223
|
+
({ className, children, ...props }, ref) => (
|
|
224
|
+
<View ref={ref} className={cn("mb-4 gap-1", className)} {...props}>
|
|
225
|
+
{children}
|
|
226
|
+
</View>
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
BottomSheetHeader.displayName = "BottomSheetHeader";
|
|
230
|
+
|
|
231
|
+
// --- BottomSheetTitle ---
|
|
232
|
+
|
|
233
|
+
export interface BottomSheetTitleProps {
|
|
234
|
+
className?: string;
|
|
235
|
+
children: React.ReactNode;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export const BottomSheetTitle: React.FC<BottomSheetTitleProps> = ({
|
|
239
|
+
className,
|
|
240
|
+
children,
|
|
241
|
+
}) => {
|
|
242
|
+
return (
|
|
243
|
+
<Heading level={4} className={cn("text-xl font-bold text-foreground", className)}>
|
|
244
|
+
{children}
|
|
245
|
+
</Heading>
|
|
246
|
+
);
|
|
247
|
+
};
|
|
248
|
+
BottomSheetTitle.displayName = "BottomSheetTitle";
|
|
249
|
+
|
|
250
|
+
// --- BottomSheetDescription ---
|
|
251
|
+
|
|
252
|
+
export interface BottomSheetDescriptionProps {
|
|
253
|
+
className?: string;
|
|
254
|
+
children: React.ReactNode;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export const BottomSheetDescription: React.FC<BottomSheetDescriptionProps> = ({
|
|
258
|
+
className,
|
|
259
|
+
children,
|
|
260
|
+
}) => {
|
|
261
|
+
return (
|
|
262
|
+
<Text className={cn("text-sm text-muted", className)}>
|
|
263
|
+
{children}
|
|
264
|
+
</Text>
|
|
265
|
+
);
|
|
266
|
+
};
|
|
267
|
+
BottomSheetDescription.displayName = "BottomSheetDescription";
|
|
268
|
+
|
|
269
|
+
// --- BottomSheetBody ---
|
|
270
|
+
|
|
271
|
+
export interface BottomSheetBodyProps extends ViewProps {
|
|
272
|
+
className?: string;
|
|
273
|
+
children: React.ReactNode;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export const BottomSheetBody = React.forwardRef<View, BottomSheetBodyProps>(
|
|
277
|
+
({ className, children, ...props }, ref) => (
|
|
278
|
+
<View ref={ref} className={cn("py-2", className)} {...props}>
|
|
279
|
+
{children}
|
|
280
|
+
</View>
|
|
281
|
+
)
|
|
282
|
+
);
|
|
283
|
+
BottomSheetBody.displayName = "BottomSheetBody";
|
|
284
|
+
|
|
285
|
+
// --- BottomSheetFooter ---
|
|
286
|
+
|
|
287
|
+
export interface BottomSheetFooterProps extends ViewProps {
|
|
288
|
+
className?: string;
|
|
289
|
+
children: React.ReactNode;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export const BottomSheetFooter = React.forwardRef<View, BottomSheetFooterProps>(
|
|
293
|
+
({ className, children, ...props }, ref) => (
|
|
294
|
+
<View
|
|
295
|
+
ref={ref}
|
|
296
|
+
className={cn("mt-6 flex-row items-center justify-end gap-3", className)}
|
|
297
|
+
{...props}
|
|
298
|
+
>
|
|
299
|
+
{children}
|
|
300
|
+
</View>
|
|
301
|
+
)
|
|
302
|
+
);
|
|
303
|
+
BottomSheetFooter.displayName = "BottomSheetFooter";
|
|
304
|
+
|
|
305
|
+
// --- BottomSheetClose ---
|
|
306
|
+
|
|
307
|
+
export interface BottomSheetCloseProps extends PressableProps {
|
|
308
|
+
asChild?: boolean;
|
|
309
|
+
className?: string;
|
|
310
|
+
children: React.ReactNode;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export const BottomSheetClose = React.forwardRef<View, BottomSheetCloseProps>(
|
|
314
|
+
({ asChild, children, onPress, ...props }, ref) => {
|
|
315
|
+
const { closeSheet } = useBottomSheetContext();
|
|
316
|
+
|
|
317
|
+
const handlePress = (e: any) => {
|
|
318
|
+
closeSheet();
|
|
319
|
+
onPress?.(e);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
if (asChild && React.isValidElement(children)) {
|
|
323
|
+
return React.cloneElement(children as React.ReactElement<any>, {
|
|
324
|
+
ref,
|
|
325
|
+
onPress: handlePress,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return (
|
|
330
|
+
<Pressable ref={ref} onPress={handlePress} {...props}>
|
|
331
|
+
{children}
|
|
332
|
+
</Pressable>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
BottomSheetClose.displayName = "BottomSheetClose";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./bottom-sheet";
|