@beyondcorp/beyond-ui-native 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/index.js +78 -61
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +78 -61
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +11 -5
  6. package/src/components/accordion/accordion.tsx +245 -0
  7. package/src/components/accordion/index.ts +1 -0
  8. package/src/components/alert/alert.tsx +118 -0
  9. package/src/components/alert/index.ts +1 -0
  10. package/src/components/avatar/avatar.tsx +125 -0
  11. package/src/components/avatar/index.ts +1 -0
  12. package/src/components/badge/badge.tsx +89 -0
  13. package/src/components/badge/index.ts +1 -0
  14. package/src/components/bottom-sheet/bottom-sheet.tsx +336 -0
  15. package/src/components/bottom-sheet/index.ts +1 -0
  16. package/src/components/button/button.tsx +172 -0
  17. package/src/components/button/index.ts +1 -0
  18. package/src/components/card/card.tsx +121 -0
  19. package/src/components/card/index.ts +1 -0
  20. package/src/components/checkbox/checkbox.tsx +100 -0
  21. package/src/components/checkbox/index.ts +1 -0
  22. package/src/components/data-table/data-table.tsx +276 -0
  23. package/src/components/data-table/index.ts +1 -0
  24. package/src/components/dialog/dialog.tsx +278 -0
  25. package/src/components/dialog/index.ts +1 -0
  26. package/src/components/input/index.ts +1 -0
  27. package/src/components/input/input.tsx +130 -0
  28. package/src/components/radio/index.ts +1 -0
  29. package/src/components/radio/radio.tsx +117 -0
  30. package/src/components/select/index.ts +1 -0
  31. package/src/components/select/select.tsx +377 -0
  32. package/src/components/separator/index.ts +1 -0
  33. package/src/components/separator/separator.tsx +28 -0
  34. package/src/components/skeleton/index.ts +1 -0
  35. package/src/components/skeleton/skeleton.tsx +43 -0
  36. package/src/components/spinner/index.ts +1 -0
  37. package/src/components/spinner/spinner.tsx +46 -0
  38. package/src/components/stats-card/index.ts +1 -0
  39. package/src/components/stats-card/stats-card.tsx +92 -0
  40. package/src/components/switch/index.ts +1 -0
  41. package/src/components/switch/switch.tsx +80 -0
  42. package/src/components/tabs/index.ts +1 -0
  43. package/src/components/tabs/tabs.tsx +172 -0
  44. package/src/components/text/heading.tsx +50 -0
  45. package/src/components/text/index.ts +2 -0
  46. package/src/components/text/text.tsx +62 -0
  47. package/src/components/textarea/index.ts +1 -0
  48. package/src/components/textarea/textarea.tsx +87 -0
  49. package/src/components/toast/index.ts +2 -0
  50. package/src/components/toast/toast.tsx +136 -0
  51. package/src/components/toast/types.ts +32 -0
  52. package/src/index.ts +42 -0
  53. package/src/primitives/box.tsx +25 -0
  54. package/src/primitives/index.ts +2 -0
  55. package/src/primitives/pressable.tsx +49 -0
  56. package/src/providers/BeyondUIProvider.tsx +119 -0
  57. package/src/templates/auth/ForgotPasswordTemplate.tsx +132 -0
  58. package/src/templates/auth/SignInTemplate.tsx +213 -0
  59. package/src/templates/auth/SignUpTemplate.tsx +233 -0
  60. package/src/templates/auth/index.ts +3 -0
  61. package/src/templates/dashboard/DashboardTemplate.tsx +204 -0
  62. package/src/templates/dashboard/index.ts +1 -0
  63. package/src/templates/index.ts +3 -0
  64. package/src/templates/settings/SettingsTemplate.tsx +226 -0
  65. package/src/templates/settings/index.ts +1 -0
  66. package/src/theme/preset.ts +45 -0
  67. package/src/theme/tokens.ts +144 -0
  68. package/src/types/nativewind-env.d.ts +26 -0
  69. package/src/utilities/accessibility.ts +43 -0
  70. package/src/utilities/cn.ts +9 -0
  71. package/src/utilities/index.ts +2 -0
@@ -0,0 +1,226 @@
1
+ import * as React from "react";
2
+ import {
3
+ View,
4
+ ScrollView,
5
+ Pressable,
6
+ type ViewProps,
7
+ } from "react-native";
8
+ import { cn } from "../../utilities/cn";
9
+ import { Text } from "../../components/text/text";
10
+ import { Heading } from "../../components/text/heading";
11
+ import { Avatar, AvatarFallback, AvatarImage } from "../../components/avatar/avatar";
12
+ import { Badge } from "../../components/badge/badge";
13
+ import { Card } from "../../components/card/card";
14
+ import { Switch } from "../../components/switch/switch";
15
+ import { Button } from "../../components/button/button";
16
+ import { Separator } from "../../components/separator/separator";
17
+
18
+ export interface SettingsTemplateProps extends ViewProps {
19
+ user: {
20
+ name: string;
21
+ email: string;
22
+ avatarUrl?: string;
23
+ plan?: string;
24
+ };
25
+ pushNotifications?: boolean;
26
+ onTogglePushNotifications?: (val: boolean) => void;
27
+ emailNotifications?: boolean;
28
+ onToggleEmailNotifications?: (val: boolean) => void;
29
+ isDarkMode?: boolean;
30
+ onToggleDarkMode?: (val: boolean) => void;
31
+ biometricsEnabled?: boolean;
32
+ onToggleBiometrics?: (val: boolean) => void;
33
+ onEditProfile?: () => void;
34
+ onChangePassword?: () => void;
35
+ onViewTerms?: () => void;
36
+ onViewPrivacy?: () => void;
37
+ onLogout?: () => void;
38
+ onDeleteAccount?: () => void;
39
+ className?: string;
40
+ }
41
+
42
+ export const SettingsTemplate: React.FC<SettingsTemplateProps> = ({
43
+ user,
44
+ pushNotifications = true,
45
+ onTogglePushNotifications,
46
+ emailNotifications = true,
47
+ onToggleEmailNotifications,
48
+ isDarkMode = false,
49
+ onToggleDarkMode,
50
+ biometricsEnabled = false,
51
+ onToggleBiometrics,
52
+ onEditProfile,
53
+ onChangePassword,
54
+ onViewTerms,
55
+ onViewPrivacy,
56
+ onLogout,
57
+ onDeleteAccount,
58
+ className,
59
+ ...props
60
+ }) => {
61
+ return (
62
+ <ScrollView
63
+ {...props}
64
+ style={[{ flex: 1 }, (props as any).style]}
65
+ className={cn("flex-1 bg-background", className)}
66
+ contentContainerStyle={{ paddingBottom: 40 }}
67
+ showsVerticalScrollIndicator={false}
68
+ >
69
+ <View className="px-6 pt-6 gap-6">
70
+ <Heading level={2} className="text-2xl font-bold text-foreground">
71
+ Settings & Profile
72
+ </Heading>
73
+
74
+ {/* User Card */}
75
+ <Card className="p-4 flex-row items-center gap-4">
76
+ <Avatar size="lg">
77
+ {user.avatarUrl && <AvatarImage source={{ uri: user.avatarUrl }} />}
78
+ <AvatarFallback text={user.name.slice(0, 2).toUpperCase()} />
79
+ </Avatar>
80
+ <View className="flex-1">
81
+ <View className="flex-row items-center gap-2">
82
+ <Text className="text-base font-bold text-foreground">{user.name}</Text>
83
+ {user.plan && (
84
+ <Badge variant="primary" size="sm">
85
+ {user.plan}
86
+ </Badge>
87
+ )}
88
+ </View>
89
+ <Text className="text-xs text-muted">{user.email}</Text>
90
+ </View>
91
+ {onEditProfile && (
92
+ <Button variant="outline" size="sm" onPress={onEditProfile}>
93
+ Edit
94
+ </Button>
95
+ )}
96
+ </Card>
97
+
98
+ {/* Preferences Section */}
99
+ <View className="gap-2">
100
+ <Text className="text-xs font-bold text-muted uppercase tracking-wider px-1">
101
+ Preferences
102
+ </Text>
103
+ <Card className="divide-y divide-border/50">
104
+ <View className="p-4 flex-row items-center justify-between">
105
+ <View className="pr-4 flex-1">
106
+ <Text className="text-sm font-semibold text-foreground">
107
+ Push Notifications
108
+ </Text>
109
+ <Text className="text-xs text-muted">
110
+ Receive real-time alerts on your mobile device
111
+ </Text>
112
+ </View>
113
+ <Switch
114
+ checked={pushNotifications}
115
+ onCheckedChange={onTogglePushNotifications}
116
+ />
117
+ </View>
118
+
119
+ <View className="p-4 flex-row items-center justify-between">
120
+ <View className="pr-4 flex-1">
121
+ <Text className="text-sm font-semibold text-foreground">
122
+ Email Notifications
123
+ </Text>
124
+ <Text className="text-xs text-muted">
125
+ Weekly digests and activity summaries
126
+ </Text>
127
+ </View>
128
+ <Switch
129
+ checked={emailNotifications}
130
+ onCheckedChange={onToggleEmailNotifications}
131
+ />
132
+ </View>
133
+
134
+ <View className="p-4 flex-row items-center justify-between">
135
+ <View className="pr-4 flex-1">
136
+ <Text className="text-sm font-semibold text-foreground">Dark Theme</Text>
137
+ <Text className="text-xs text-muted">
138
+ Enable high contrast dark mode appearance
139
+ </Text>
140
+ </View>
141
+ <Switch checked={isDarkMode} onCheckedChange={onToggleDarkMode} />
142
+ </View>
143
+
144
+ <View className="p-4 flex-row items-center justify-between">
145
+ <View className="pr-4 flex-1">
146
+ <Text className="text-sm font-semibold text-foreground">
147
+ Biometric Login
148
+ </Text>
149
+ <Text className="text-xs text-muted">
150
+ Use Face ID or fingerprint to authenticate
151
+ </Text>
152
+ </View>
153
+ <Switch
154
+ checked={biometricsEnabled}
155
+ onCheckedChange={onToggleBiometrics}
156
+ />
157
+ </View>
158
+ </Card>
159
+ </View>
160
+
161
+ {/* Security & Account Links */}
162
+ <View className="gap-2">
163
+ <Text className="text-xs font-bold text-muted uppercase tracking-wider px-1">
164
+ Account & Security
165
+ </Text>
166
+ <Card className="divide-y divide-border/50">
167
+ {onChangePassword && (
168
+ <Pressable
169
+ onPress={onChangePassword}
170
+ className="p-4 flex-row items-center justify-between active:bg-muted/10"
171
+ >
172
+ <Text className="text-sm font-semibold text-foreground">
173
+ Change Password
174
+ </Text>
175
+ <Text className="text-muted text-xs">›</Text>
176
+ </Pressable>
177
+ )}
178
+
179
+ {onViewTerms && (
180
+ <Pressable
181
+ onPress={onViewTerms}
182
+ className="p-4 flex-row items-center justify-between active:bg-muted/10"
183
+ >
184
+ <Text className="text-sm font-semibold text-foreground">
185
+ Terms of Service
186
+ </Text>
187
+ <Text className="text-muted text-xs">›</Text>
188
+ </Pressable>
189
+ )}
190
+
191
+ {onViewPrivacy && (
192
+ <Pressable
193
+ onPress={onViewPrivacy}
194
+ className="p-4 flex-row items-center justify-between active:bg-muted/10"
195
+ >
196
+ <Text className="text-sm font-semibold text-foreground">
197
+ Privacy Policy
198
+ </Text>
199
+ <Text className="text-muted text-xs">›</Text>
200
+ </Pressable>
201
+ )}
202
+ </Card>
203
+ </View>
204
+
205
+ {/* Danger Zone */}
206
+ <View className="gap-3 pt-2">
207
+ {onLogout && (
208
+ <Button variant="outline" size="lg" onPress={onLogout}>
209
+ Log Out
210
+ </Button>
211
+ )}
212
+
213
+ {onDeleteAccount && (
214
+ <Button
215
+ variant="destructive"
216
+ size="lg"
217
+ onPress={onDeleteAccount}
218
+ >
219
+ Delete Account
220
+ </Button>
221
+ )}
222
+ </View>
223
+ </View>
224
+ </ScrollView>
225
+ );
226
+ };
@@ -0,0 +1 @@
1
+ export * from "./SettingsTemplate";
@@ -0,0 +1,45 @@
1
+ import { tokens } from "./tokens";
2
+
3
+ export { tokens };
4
+
5
+ export const beyondUIPreset = {
6
+ darkMode: "class",
7
+ theme: {
8
+ extend: {
9
+ colors: {
10
+ primary: tokens.colors.primary,
11
+ secondary: tokens.colors.secondary,
12
+ danger: tokens.colors.danger,
13
+ destructive: tokens.colors.destructive,
14
+ success: tokens.colors.success,
15
+ warning: tokens.colors.warning,
16
+ neutral: tokens.colors.neutral,
17
+ background: tokens.colors.semantic.light.background,
18
+ foreground: tokens.colors.semantic.light.foreground,
19
+ card: {
20
+ DEFAULT: tokens.colors.semantic.light.card,
21
+ foreground: tokens.colors.semantic.light.cardForeground,
22
+ },
23
+ cardForeground: tokens.colors.semantic.light.cardForeground,
24
+ muted: {
25
+ DEFAULT: tokens.colors.semantic.light.mutedForeground,
26
+ foreground: tokens.colors.semantic.light.mutedForeground,
27
+ },
28
+ mutedForeground: tokens.colors.semantic.light.mutedForeground,
29
+ border: tokens.colors.semantic.light.border,
30
+ input: tokens.colors.semantic.light.input,
31
+ },
32
+ borderRadius: {
33
+ none: "0px",
34
+ sm: `${tokens.radius.sm}px`,
35
+ md: `${tokens.radius.md}px`,
36
+ lg: `${tokens.radius.lg}px`,
37
+ xl: `${tokens.radius.xl}px`,
38
+ "2xl": `${tokens.radius["2xl"]}px`,
39
+ full: "9999px",
40
+ },
41
+ },
42
+ },
43
+ };
44
+
45
+ export default beyondUIPreset;
@@ -0,0 +1,144 @@
1
+ export const tokens = {
2
+ colors: {
3
+ primary: {
4
+ 50: "#eff6ff",
5
+ 100: "#dbeafe",
6
+ 200: "#bfdbfe",
7
+ 300: "#93c5fd",
8
+ 400: "#60a5fa",
9
+ 500: "#3b82f6",
10
+ 600: "#2563eb",
11
+ 700: "#1d4ed8",
12
+ 800: "#1e40af",
13
+ 900: "#1e3a8a",
14
+ 950: "#172554",
15
+ DEFAULT: "#2563eb",
16
+ },
17
+ secondary: {
18
+ 50: "#f8fafc",
19
+ 100: "#f1f5f9",
20
+ 200: "#e2e8f0",
21
+ 300: "#cbd5e1",
22
+ 400: "#94a3b8",
23
+ 500: "#64748b",
24
+ 600: "#475569",
25
+ 700: "#334155",
26
+ 800: "#1e293b",
27
+ 900: "#0f172a",
28
+ 950: "#020617",
29
+ DEFAULT: "#475569",
30
+ },
31
+ danger: {
32
+ 50: "#fef2f2",
33
+ 100: "#fee2e2",
34
+ 200: "#fecaca",
35
+ 300: "#fca5a5",
36
+ 400: "#f87171",
37
+ 500: "#ef4444",
38
+ 600: "#dc2626",
39
+ 700: "#b91c1c",
40
+ 800: "#991b1b",
41
+ 900: "#7f1d1d",
42
+ 950: "#450a0a",
43
+ DEFAULT: "#dc2626",
44
+ },
45
+ // Alias for shadcn / React Native convention compatibility
46
+ destructive: {
47
+ 50: "#fef2f2",
48
+ 100: "#fee2e2",
49
+ 200: "#fecaca",
50
+ 300: "#fca5a5",
51
+ 400: "#f87171",
52
+ 500: "#ef4444",
53
+ 600: "#dc2626",
54
+ 700: "#b91c1c",
55
+ 800: "#991b1b",
56
+ 900: "#7f1d1d",
57
+ 950: "#450a0a",
58
+ DEFAULT: "#dc2626",
59
+ },
60
+ success: {
61
+ 50: "#f0fdf4",
62
+ 100: "#dcfce7",
63
+ 200: "#bbf7d0",
64
+ 300: "#86efac",
65
+ 400: "#4ade80",
66
+ 500: "#22c55e",
67
+ 600: "#16a34a",
68
+ 700: "#15803d",
69
+ 800: "#166534",
70
+ 900: "#14532d",
71
+ 950: "#052e16",
72
+ DEFAULT: "#16a34a",
73
+ },
74
+ warning: {
75
+ 50: "#fffbeb",
76
+ 100: "#fef3c7",
77
+ 200: "#fde68a",
78
+ 300: "#fcd34d",
79
+ 400: "#fbbf24",
80
+ 500: "#f59e0b",
81
+ 600: "#d97706",
82
+ 700: "#b45309",
83
+ 800: "#92400e",
84
+ 900: "#78350f",
85
+ 950: "#451a03",
86
+ DEFAULT: "#d97706",
87
+ },
88
+ neutral: {
89
+ 50: "#f9fafb",
90
+ 100: "#f3f4f6",
91
+ 200: "#e5e7eb",
92
+ 300: "#d1d5db",
93
+ 400: "#9ca3af",
94
+ 500: "#6b7280",
95
+ 600: "#4b5563",
96
+ 700: "#374151",
97
+ 800: "#1f2937",
98
+ 900: "#111827",
99
+ 950: "#030712",
100
+ },
101
+ semantic: {
102
+ light: {
103
+ background: "#ffffff",
104
+ foreground: "#0f172a",
105
+ card: "#ffffff",
106
+ cardForeground: "#0f172a",
107
+ muted: "#f8fafc",
108
+ mutedForeground: "#64748b",
109
+ border: "#e2e8f0",
110
+ input: "#e2e8f0",
111
+ },
112
+ dark: {
113
+ background: "#090d16",
114
+ foreground: "#f8fafc",
115
+ card: "#0f172a",
116
+ cardForeground: "#f8fafc",
117
+ muted: "#1e293b",
118
+ mutedForeground: "#94a3b8",
119
+ border: "#334155",
120
+ input: "#334155",
121
+ },
122
+ },
123
+ },
124
+ radius: {
125
+ none: 0,
126
+ sm: 6,
127
+ md: 10,
128
+ lg: 14,
129
+ xl: 20,
130
+ "2xl": 28,
131
+ full: 9999,
132
+ },
133
+ spacing: {
134
+ xs: 4,
135
+ sm: 8,
136
+ md: 12,
137
+ lg: 16,
138
+ xl: 24,
139
+ "2xl": 32,
140
+ "3xl": 48,
141
+ },
142
+ } as const;
143
+
144
+ export type BeyondUITokens = typeof tokens;
@@ -0,0 +1,26 @@
1
+ /// <reference types="nativewind/types" />
2
+
3
+ import "react-native";
4
+
5
+ declare module "react-native" {
6
+ interface ViewProps {
7
+ className?: string;
8
+ }
9
+ interface TextProps {
10
+ className?: string;
11
+ }
12
+ interface TextInputProps {
13
+ className?: string;
14
+ placeholderClassName?: string;
15
+ }
16
+ interface PressableProps {
17
+ className?: string;
18
+ }
19
+ interface ScrollViewProps {
20
+ className?: string;
21
+ contentContainerClassName?: string;
22
+ }
23
+ interface ImageProps {
24
+ className?: string;
25
+ }
26
+ }
@@ -0,0 +1,43 @@
1
+ import type { AccessibilityRole, AccessibilityState } from "react-native";
2
+
3
+ export interface AccessibilityPropsOptions {
4
+ label?: string;
5
+ hint?: string;
6
+ role?: AccessibilityRole;
7
+ disabled?: boolean;
8
+ selected?: boolean;
9
+ checked?: boolean | "mixed";
10
+ busy?: boolean;
11
+ expanded?: boolean;
12
+ }
13
+
14
+ /**
15
+ * Helper to construct accessible props for React Native components.
16
+ */
17
+ export function getAccessibilityProps(options: AccessibilityPropsOptions = {}) {
18
+ const { label, hint, role, disabled, selected, checked, busy, expanded } = options;
19
+
20
+ const state: AccessibilityState = {};
21
+ if (disabled !== undefined) state.disabled = disabled;
22
+ if (selected !== undefined) state.selected = selected;
23
+ if (checked !== undefined) state.checked = checked;
24
+ if (busy !== undefined) state.busy = busy;
25
+ if (expanded !== undefined) state.expanded = expanded;
26
+
27
+ const hasState = Object.keys(state).length > 0;
28
+
29
+ return {
30
+ accessible: true,
31
+ ...(label ? { accessibilityLabel: label } : {}),
32
+ ...(hint ? { accessibilityHint: hint } : {}),
33
+ ...(role ? { accessibilityRole: role } : {}),
34
+ ...(hasState ? { accessibilityState: state } : {}),
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Format a visually hidden text string or accessibility label from parts.
40
+ */
41
+ export function joinA11yLabels(...parts: (string | undefined | null | false)[]): string {
42
+ return parts.filter(Boolean).join(", ");
43
+ }
@@ -0,0 +1,9 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ /**
5
+ * Merges class names with tailwind-merge to avoid style collisions in NativeWind.
6
+ */
7
+ export function cn(...inputs: ClassValue[]): string {
8
+ return twMerge(clsx(inputs));
9
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./cn";
2
+ export * from "./accessibility";