@beyondcorp/beyond-ui-native 0.0.0-stage → 0.1.1

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 CHANGED
@@ -1,3 +1,213 @@
1
- # Temporary Holding Version
1
+ # @beyondcorp/beyond-ui-native
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > A NativeWind-first, accessible, TypeScript-first React Native component library by Beyond Softwares.
4
+
5
+ Built as the mobile counterpart to [`@beyondcorp/beyond-ui`](https://github.com/beyondcorp/beyond-ui), Beyond UI Native brings unified design tokens, accessible primitives, compound components, reusable screen templates, and production-ready mobile patterns to React Native and Expo.
6
+
7
+ ---
8
+
9
+ ## Highlights
10
+
11
+ - ⚡ **NativeWind v4-first**: Style universal mobile components using intuitive Tailwind CSS classes.
12
+ - ♿ **Accessible by default**: Built on top of `@rn-primitives` (headless Radix primitives for React Native) and dedicated a11y helpers for screen readers, focus states, and ARIA roles.
13
+ - 🎨 **Design Token Parity**: Synchronized 50–950 shade scales (`primary`, `secondary`, `danger`/`destructive`, `success`, `warning`, `neutral`), semantic dark/light mode tokens, and border radii matching the Beyond UI web ecosystem.
14
+ - 🧩 **Compound Components**: Highly composable APIs for Dialogs, Bottom Sheets, Accordions, Tabs, Selects, Cards, and Alerts.
15
+ - 📱 **Screen Templates**: Ready-to-use production mobile screen templates for Authentication (Sign In, Sign Up, Forgot Password), Dashboard Overview, and Profile/Settings.
16
+ - 🔔 **Built-in Toast & Portals**: Zero-configuration overlay portals and animated toast banners with `useToast()`.
17
+ - 📦 **Dual Module Formats**: Pre-bundled ESM (`.mjs`), CommonJS (`.js`), and full TypeScript definitions (`.d.ts`, `.d.mts`).
18
+
19
+ ---
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ # In your Expo or React Native app:
25
+ npm install @beyondcorp/beyond-ui-native
26
+ npx expo install nativewind tailwindcss react-native-reanimated
27
+ ```
28
+
29
+ ### 1. Configure Tailwind Preset
30
+
31
+ Add the Beyond UI Native preset to your `tailwind.config.js`:
32
+
33
+ ```javascript
34
+ // tailwind.config.js
35
+ module.exports = {
36
+ content: [
37
+ "./app/**/*.{js,jsx,ts,tsx}",
38
+ "./src/**/*.{js,jsx,ts,tsx}",
39
+ "./node_modules/@beyondcorp/beyond-ui-native/dist/**/*.{js,mjs}",
40
+ ],
41
+ presets: [
42
+ require("nativewind/preset"),
43
+ require("@beyondcorp/beyond-ui-native/preset"),
44
+ ],
45
+ theme: {
46
+ extend: {},
47
+ },
48
+ plugins: [],
49
+ };
50
+ ```
51
+
52
+ ### 2. Wrap App with `BeyondUIProvider`
53
+
54
+ ```tsx
55
+ import React from "react";
56
+ import { BeyondUIProvider } from "@beyondcorp/beyond-ui-native";
57
+ import { MainNavigator } from "./navigation";
58
+
59
+ export default function App() {
60
+ return (
61
+ <BeyondUIProvider defaultColorScheme="system">
62
+ <MainNavigator />
63
+ </BeyondUIProvider>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Component Catalogue
71
+
72
+ ### 1. Primitives & Layout
73
+ - **`Box`**: Polymorphic container with forwarded ref, NativeWind class support, and accessibility props.
74
+ - **`Pressable`**: Interactive touch target with built-in press feedback (`opacity`, `scale`, `none`).
75
+ - **`Separator`**: Accessible horizontal and vertical layout divider.
76
+
77
+ ### 2. Typography
78
+ - **`Heading`**: Semantic header (`h1` through `h6`, or numeric levels 1–6).
79
+ - **`Text`**: Body text supporting variants (`body`, `muted`, `caption`, `lead`, `error`).
80
+
81
+ ### 3. Actions & Forms
82
+ - **`Button`**: Variants (`primary`, `secondary`, `destructive`, `danger`, `outline`, `ghost`, `link`), sizes (`sm`, `md`, `lg`, `xl`), and loading spinners.
83
+ - **`Input`**: Text input with `leftIcon`/`rightIcon`, `leftElement`/`rightElement`, error messaging, and helper text.
84
+ - **`Textarea`**: Multiline text input with border focus states and validation styling.
85
+ - **`Select`**: Mobile-optimized picker with trigger, searchable options sheet, checkmark selection, and compound parts (`SelectTrigger`, `SelectContent`, `SelectItem`, `SelectValue`).
86
+ - **`Switch`**: Smooth toggle switch with dark mode theme support.
87
+ - **`Checkbox`**: Accessible checkbox with check indicator.
88
+ - **`RadioGroup` & `Radio`**: Single-select radio group.
89
+
90
+ ### 4. Overlays & Feedback
91
+ - **`Dialog`**: Compound modal dialog (`DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter`, `DialogClose`).
92
+ - **`BottomSheet`**: Slide-up sheet modal with drag-down-to-dismiss gesture, backdrop scrim, handle bar, header, and body.
93
+ - **`Accordion`**: Expandable accordion sections (`AccordionItem`, `AccordionTrigger`, `AccordionContent`) supporting single or multiple items.
94
+ - **`Toast`**: Context-driven animated notifications via `useToast()` (`toast.success()`, `toast.error()`, `toast.warning()`, `toast.info()`).
95
+ - **`Alert`**: Status alert banner (`AlertTitle`, `AlertDescription`).
96
+ - **`Spinner`**: Animated activity indicator.
97
+ - **`Skeleton`**: Pulsing placeholder for asynchronous data loading.
98
+
99
+ ### 5. Data Display
100
+ - **`Card`**: Compound card container (`CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`).
101
+ - **`Badge`**: Status badge supporting `primary`, `secondary`, `success`, `warning`, `danger`, and `outline`.
102
+ - **`Avatar`**: User avatar with automatic fallback initials (`AvatarImage`, `AvatarFallback`).
103
+ - **`StatsCard`**: Metrics card with trend percentage indicator, icon, and description.
104
+ - **`DataTable`**: Mobile-responsive data table and card list with search filter, sortable columns, and pagination.
105
+ - **`Tabs`**: Segmented tab control (`TabsList`, `TabsTrigger`, `TabsContent`).
106
+
107
+ ---
108
+
109
+ ## Production Screen Templates
110
+
111
+ Beyond UI Native includes ready-to-use, fully functional mobile screen templates under `@beyondcorp/beyond-ui-native`:
112
+
113
+ ```tsx
114
+ import {
115
+ SignInTemplate,
116
+ SignUpTemplate,
117
+ ForgotPasswordTemplate,
118
+ DashboardTemplate,
119
+ SettingsTemplate,
120
+ } from "@beyondcorp/beyond-ui-native";
121
+ ```
122
+
123
+ ### Sign In Screen
124
+ ```tsx
125
+ <SignInTemplate
126
+ title="Welcome Back"
127
+ subtitle="Sign in to your Beyond account"
128
+ onSubmit={({ email, password, rememberMe }) => handleLogin(email, password)}
129
+ onForgotPassword={() => navigation.navigate("ForgotPassword")}
130
+ onSignUpPress={() => navigation.navigate("SignUp")}
131
+ onGooglePress={handleGoogleLogin}
132
+ onApplePress={handleAppleLogin}
133
+ />
134
+ ```
135
+
136
+ ### Dashboard Screen
137
+ ```tsx
138
+ <DashboardTemplate
139
+ userName="Mark"
140
+ userRole="Principal Engineer"
141
+ metrics={[
142
+ { id: "1", title: "Revenue", value: "$48,500", trend: { direction: "up", value: "+14.2%", label: "this month" } },
143
+ { id: "2", title: "Active Users", value: "12,400", trend: { direction: "up", value: "+6.8%", label: "growth" } },
144
+ ]}
145
+ quickActions={[
146
+ { id: "1", label: "New Project", icon: "🚀", onPress: () => {} },
147
+ { id: "2", label: "Export", icon: "📊", onPress: () => {} },
148
+ ]}
149
+ recentActivities={[
150
+ { id: "1", title: "New Order #1084", subtitle: "2 items", timestamp: "5m ago", amount: "$149.00", status: { label: "Completed", variant: "success" } },
151
+ ]}
152
+ />
153
+ ```
154
+
155
+ ### Settings & Profile Screen
156
+ ```tsx
157
+ <SettingsTemplate
158
+ user={{ name: "Mark Otto", email: "mark@beyondsoftwares.com", plan: "Enterprise" }}
159
+ pushNotifications={pushEnabled}
160
+ onTogglePushNotifications={setPushEnabled}
161
+ isDarkMode={colorScheme === "dark"}
162
+ onToggleDarkMode={toggleColorScheme}
163
+ onLogout={handleLogout}
164
+ onDeleteAccount={handleDeleteAccount}
165
+ />
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Monorepo Architecture
171
+
172
+ ```
173
+ beyond-ui-native/
174
+ ├── packages/
175
+ │ └── beyond-ui-native/ # The npm package (@beyondcorp/beyond-ui-native)
176
+ │ ├── src/
177
+ │ │ ├── components/ # 20+ production UI components
178
+ │ │ ├── primitives/ # Box, Pressable layout primitives
179
+ │ │ ├── templates/ # Auth, Dashboard, Settings templates
180
+ │ │ ├── providers/ # BeyondUIProvider & Portal host
181
+ │ │ ├── theme/ # Design tokens & Tailwind preset
182
+ │ │ └── utilities/ # cn (clsx + tailwind-merge) & a11y helpers
183
+ │ ├── tests/ # Automated test suite
184
+ │ └── tsup.config.ts # ESM, CJS & DTS rollup
185
+ ├── apps/
186
+ │ └── example/ # Expo SDK 52 interactive showcase app
187
+ └── .github/
188
+ └── workflows/ # CI & Release automation pipelines
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Scripts
194
+
195
+ ```bash
196
+ # Build the component library
197
+ npm run build
198
+
199
+ # Run TypeScript typechecks
200
+ npm run typecheck
201
+
202
+ # Run unit test suite
203
+ npm test
204
+
205
+ # Start the Expo example application
206
+ npm run example:start
207
+ ```
208
+
209
+ ---
210
+
211
+ ## License
212
+
213
+ MIT © Beyond Softwares
@@ -0,0 +1,178 @@
1
+ // src/theme/tokens.ts
2
+ var tokens = {
3
+ colors: {
4
+ primary: {
5
+ 50: "#eff6ff",
6
+ 100: "#dbeafe",
7
+ 200: "#bfdbfe",
8
+ 300: "#93c5fd",
9
+ 400: "#60a5fa",
10
+ 500: "#3b82f6",
11
+ 600: "#2563eb",
12
+ 700: "#1d4ed8",
13
+ 800: "#1e40af",
14
+ 900: "#1e3a8a",
15
+ 950: "#172554",
16
+ DEFAULT: "#2563eb"
17
+ },
18
+ secondary: {
19
+ 50: "#f8fafc",
20
+ 100: "#f1f5f9",
21
+ 200: "#e2e8f0",
22
+ 300: "#cbd5e1",
23
+ 400: "#94a3b8",
24
+ 500: "#64748b",
25
+ 600: "#475569",
26
+ 700: "#334155",
27
+ 800: "#1e293b",
28
+ 900: "#0f172a",
29
+ 950: "#020617",
30
+ DEFAULT: "#475569"
31
+ },
32
+ danger: {
33
+ 50: "#fef2f2",
34
+ 100: "#fee2e2",
35
+ 200: "#fecaca",
36
+ 300: "#fca5a5",
37
+ 400: "#f87171",
38
+ 500: "#ef4444",
39
+ 600: "#dc2626",
40
+ 700: "#b91c1c",
41
+ 800: "#991b1b",
42
+ 900: "#7f1d1d",
43
+ 950: "#450a0a",
44
+ DEFAULT: "#dc2626"
45
+ },
46
+ // Alias for shadcn / React Native convention compatibility
47
+ destructive: {
48
+ 50: "#fef2f2",
49
+ 100: "#fee2e2",
50
+ 200: "#fecaca",
51
+ 300: "#fca5a5",
52
+ 400: "#f87171",
53
+ 500: "#ef4444",
54
+ 600: "#dc2626",
55
+ 700: "#b91c1c",
56
+ 800: "#991b1b",
57
+ 900: "#7f1d1d",
58
+ 950: "#450a0a",
59
+ DEFAULT: "#dc2626"
60
+ },
61
+ success: {
62
+ 50: "#f0fdf4",
63
+ 100: "#dcfce7",
64
+ 200: "#bbf7d0",
65
+ 300: "#86efac",
66
+ 400: "#4ade80",
67
+ 500: "#22c55e",
68
+ 600: "#16a34a",
69
+ 700: "#15803d",
70
+ 800: "#166534",
71
+ 900: "#14532d",
72
+ 950: "#052e16",
73
+ DEFAULT: "#16a34a"
74
+ },
75
+ warning: {
76
+ 50: "#fffbeb",
77
+ 100: "#fef3c7",
78
+ 200: "#fde68a",
79
+ 300: "#fcd34d",
80
+ 400: "#fbbf24",
81
+ 500: "#f59e0b",
82
+ 600: "#d97706",
83
+ 700: "#b45309",
84
+ 800: "#92400e",
85
+ 900: "#78350f",
86
+ 950: "#451a03",
87
+ DEFAULT: "#d97706"
88
+ },
89
+ neutral: {
90
+ 50: "#f9fafb",
91
+ 100: "#f3f4f6",
92
+ 200: "#e5e7eb",
93
+ 300: "#d1d5db",
94
+ 400: "#9ca3af",
95
+ 500: "#6b7280",
96
+ 600: "#4b5563",
97
+ 700: "#374151",
98
+ 800: "#1f2937",
99
+ 900: "#111827",
100
+ 950: "#030712"
101
+ },
102
+ semantic: {
103
+ light: {
104
+ background: "#ffffff",
105
+ foreground: "#0f172a",
106
+ card: "#ffffff",
107
+ cardForeground: "#0f172a",
108
+ muted: "#f8fafc",
109
+ mutedForeground: "#64748b",
110
+ border: "#e2e8f0",
111
+ input: "#e2e8f0"
112
+ },
113
+ dark: {
114
+ background: "#090d16",
115
+ foreground: "#f8fafc",
116
+ card: "#0f172a",
117
+ cardForeground: "#f8fafc",
118
+ muted: "#1e293b",
119
+ mutedForeground: "#94a3b8",
120
+ border: "#334155",
121
+ input: "#334155"
122
+ }
123
+ }
124
+ },
125
+ radius: {
126
+ none: 0,
127
+ sm: 6,
128
+ md: 10,
129
+ lg: 14,
130
+ xl: 20,
131
+ "2xl": 28,
132
+ full: 9999
133
+ },
134
+ spacing: {
135
+ xs: 4,
136
+ sm: 8,
137
+ md: 12,
138
+ lg: 16,
139
+ xl: 24,
140
+ "2xl": 32,
141
+ "3xl": 48
142
+ }
143
+ };
144
+
145
+ // src/theme/preset.ts
146
+ var beyondUIPreset = {
147
+ darkMode: "class",
148
+ theme: {
149
+ extend: {
150
+ colors: {
151
+ primary: tokens.colors.primary,
152
+ secondary: tokens.colors.secondary,
153
+ danger: tokens.colors.danger,
154
+ destructive: tokens.colors.destructive,
155
+ success: tokens.colors.success,
156
+ warning: tokens.colors.warning,
157
+ neutral: tokens.colors.neutral
158
+ },
159
+ borderRadius: {
160
+ none: "0px",
161
+ sm: `${tokens.radius.sm}px`,
162
+ md: `${tokens.radius.md}px`,
163
+ lg: `${tokens.radius.lg}px`,
164
+ xl: `${tokens.radius.xl}px`,
165
+ "2xl": `${tokens.radius["2xl"]}px`,
166
+ full: "9999px"
167
+ }
168
+ }
169
+ }
170
+ };
171
+ var preset_default = beyondUIPreset;
172
+
173
+ export {
174
+ tokens,
175
+ beyondUIPreset,
176
+ preset_default
177
+ };
178
+ //# sourceMappingURL=chunk-2B6HTSGM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme/tokens.ts","../src/theme/preset.ts"],"sourcesContent":["export const tokens = {\n colors: {\n primary: {\n 50: \"#eff6ff\",\n 100: \"#dbeafe\",\n 200: \"#bfdbfe\",\n 300: \"#93c5fd\",\n 400: \"#60a5fa\",\n 500: \"#3b82f6\",\n 600: \"#2563eb\",\n 700: \"#1d4ed8\",\n 800: \"#1e40af\",\n 900: \"#1e3a8a\",\n 950: \"#172554\",\n DEFAULT: \"#2563eb\",\n },\n secondary: {\n 50: \"#f8fafc\",\n 100: \"#f1f5f9\",\n 200: \"#e2e8f0\",\n 300: \"#cbd5e1\",\n 400: \"#94a3b8\",\n 500: \"#64748b\",\n 600: \"#475569\",\n 700: \"#334155\",\n 800: \"#1e293b\",\n 900: \"#0f172a\",\n 950: \"#020617\",\n DEFAULT: \"#475569\",\n },\n danger: {\n 50: \"#fef2f2\",\n 100: \"#fee2e2\",\n 200: \"#fecaca\",\n 300: \"#fca5a5\",\n 400: \"#f87171\",\n 500: \"#ef4444\",\n 600: \"#dc2626\",\n 700: \"#b91c1c\",\n 800: \"#991b1b\",\n 900: \"#7f1d1d\",\n 950: \"#450a0a\",\n DEFAULT: \"#dc2626\",\n },\n // Alias for shadcn / React Native convention compatibility\n destructive: {\n 50: \"#fef2f2\",\n 100: \"#fee2e2\",\n 200: \"#fecaca\",\n 300: \"#fca5a5\",\n 400: \"#f87171\",\n 500: \"#ef4444\",\n 600: \"#dc2626\",\n 700: \"#b91c1c\",\n 800: \"#991b1b\",\n 900: \"#7f1d1d\",\n 950: \"#450a0a\",\n DEFAULT: \"#dc2626\",\n },\n success: {\n 50: \"#f0fdf4\",\n 100: \"#dcfce7\",\n 200: \"#bbf7d0\",\n 300: \"#86efac\",\n 400: \"#4ade80\",\n 500: \"#22c55e\",\n 600: \"#16a34a\",\n 700: \"#15803d\",\n 800: \"#166534\",\n 900: \"#14532d\",\n 950: \"#052e16\",\n DEFAULT: \"#16a34a\",\n },\n warning: {\n 50: \"#fffbeb\",\n 100: \"#fef3c7\",\n 200: \"#fde68a\",\n 300: \"#fcd34d\",\n 400: \"#fbbf24\",\n 500: \"#f59e0b\",\n 600: \"#d97706\",\n 700: \"#b45309\",\n 800: \"#92400e\",\n 900: \"#78350f\",\n 950: \"#451a03\",\n DEFAULT: \"#d97706\",\n },\n neutral: {\n 50: \"#f9fafb\",\n 100: \"#f3f4f6\",\n 200: \"#e5e7eb\",\n 300: \"#d1d5db\",\n 400: \"#9ca3af\",\n 500: \"#6b7280\",\n 600: \"#4b5563\",\n 700: \"#374151\",\n 800: \"#1f2937\",\n 900: \"#111827\",\n 950: \"#030712\",\n },\n semantic: {\n light: {\n background: \"#ffffff\",\n foreground: \"#0f172a\",\n card: \"#ffffff\",\n cardForeground: \"#0f172a\",\n muted: \"#f8fafc\",\n mutedForeground: \"#64748b\",\n border: \"#e2e8f0\",\n input: \"#e2e8f0\",\n },\n dark: {\n background: \"#090d16\",\n foreground: \"#f8fafc\",\n card: \"#0f172a\",\n cardForeground: \"#f8fafc\",\n muted: \"#1e293b\",\n mutedForeground: \"#94a3b8\",\n border: \"#334155\",\n input: \"#334155\",\n },\n },\n },\n radius: {\n none: 0,\n sm: 6,\n md: 10,\n lg: 14,\n xl: 20,\n \"2xl\": 28,\n full: 9999,\n },\n spacing: {\n xs: 4,\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n \"2xl\": 32,\n \"3xl\": 48,\n },\n} as const;\n\nexport type BeyondUITokens = typeof tokens;\n","import { tokens } from \"./tokens\";\n\nexport const beyondUIPreset = {\n darkMode: \"class\",\n theme: {\n extend: {\n colors: {\n primary: tokens.colors.primary,\n secondary: tokens.colors.secondary,\n danger: tokens.colors.danger,\n destructive: tokens.colors.destructive,\n success: tokens.colors.success,\n warning: tokens.colors.warning,\n neutral: tokens.colors.neutral,\n },\n borderRadius: {\n none: \"0px\",\n sm: `${tokens.radius.sm}px`,\n md: `${tokens.radius.md}px`,\n lg: `${tokens.radius.lg}px`,\n xl: `${tokens.radius.xl}px`,\n \"2xl\": `${tokens.radius[\"2xl\"]}px`,\n full: \"9999px\",\n },\n },\n },\n};\n\nexport default beyondUIPreset;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,35 @@
1
+ // src/utilities/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // src/utilities/accessibility.ts
9
+ function getAccessibilityProps(options = {}) {
10
+ const { label, hint, role, disabled, selected, checked, busy, expanded } = options;
11
+ const state = {};
12
+ if (disabled !== void 0) state.disabled = disabled;
13
+ if (selected !== void 0) state.selected = selected;
14
+ if (checked !== void 0) state.checked = checked;
15
+ if (busy !== void 0) state.busy = busy;
16
+ if (expanded !== void 0) state.expanded = expanded;
17
+ const hasState = Object.keys(state).length > 0;
18
+ return {
19
+ accessible: true,
20
+ ...label ? { accessibilityLabel: label } : {},
21
+ ...hint ? { accessibilityHint: hint } : {},
22
+ ...role ? { accessibilityRole: role } : {},
23
+ ...hasState ? { accessibilityState: state } : {}
24
+ };
25
+ }
26
+ function joinA11yLabels(...parts) {
27
+ return parts.filter(Boolean).join(", ");
28
+ }
29
+
30
+ export {
31
+ cn,
32
+ getAccessibilityProps,
33
+ joinA11yLabels
34
+ };
35
+ //# sourceMappingURL=chunk-UTNW3LJA.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utilities/cn.ts","../src/utilities/accessibility.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merges class names with tailwind-merge to avoid style collisions in NativeWind.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import type { AccessibilityRole, AccessibilityState } from \"react-native\";\n\nexport interface AccessibilityPropsOptions {\n label?: string;\n hint?: string;\n role?: AccessibilityRole;\n disabled?: boolean;\n selected?: boolean;\n checked?: boolean | \"mixed\";\n busy?: boolean;\n expanded?: boolean;\n}\n\n/**\n * Helper to construct accessible props for React Native components.\n */\nexport function getAccessibilityProps(options: AccessibilityPropsOptions = {}) {\n const { label, hint, role, disabled, selected, checked, busy, expanded } = options;\n\n const state: AccessibilityState = {};\n if (disabled !== undefined) state.disabled = disabled;\n if (selected !== undefined) state.selected = selected;\n if (checked !== undefined) state.checked = checked;\n if (busy !== undefined) state.busy = busy;\n if (expanded !== undefined) state.expanded = expanded;\n\n const hasState = Object.keys(state).length > 0;\n\n return {\n accessible: true,\n ...(label ? { accessibilityLabel: label } : {}),\n ...(hint ? { accessibilityHint: hint } : {}),\n ...(role ? { accessibilityRole: role } : {}),\n ...(hasState ? { accessibilityState: state } : {}),\n };\n}\n\n/**\n * Format a visually hidden text string or accessibility label from parts.\n */\nexport function joinA11yLabels(...parts: (string | undefined | null | false)[]): string {\n return parts.filter(Boolean).join(\", \");\n}\n"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,eAAe;AAKjB,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ACQO,SAAS,sBAAsB,UAAqC,CAAC,GAAG;AAC7E,QAAM,EAAE,OAAO,MAAM,MAAM,UAAU,UAAU,SAAS,MAAM,SAAS,IAAI;AAE3E,QAAM,QAA4B,CAAC;AACnC,MAAI,aAAa,OAAW,OAAM,WAAW;AAC7C,MAAI,aAAa,OAAW,OAAM,WAAW;AAC7C,MAAI,YAAY,OAAW,OAAM,UAAU;AAC3C,MAAI,SAAS,OAAW,OAAM,OAAO;AACrC,MAAI,aAAa,OAAW,OAAM,WAAW;AAE7C,QAAM,WAAW,OAAO,KAAK,KAAK,EAAE,SAAS;AAE7C,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,GAAI,QAAQ,EAAE,oBAAoB,MAAM,IAAI,CAAC;AAAA,IAC7C,GAAI,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAAA,IAC1C,GAAI,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;AAAA,IAC1C,GAAI,WAAW,EAAE,oBAAoB,MAAM,IAAI,CAAC;AAAA,EAClD;AACF;AAKO,SAAS,kBAAkB,OAAsD;AACtF,SAAO,MAAM,OAAO,OAAO,EAAE,KAAK,IAAI;AACxC;","names":[]}