@titan-design/react-ui 0.0.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/dist/index.mjs ADDED
@@ -0,0 +1,4412 @@
1
+ import { semanticColorsDark, getHoverColors, getValidatedElevation, getBaseSurfaceColor, getElevationSurface, getElevationShadow, neumorphicShadows } from './chunk-NA3EES23.mjs';
2
+ export { buttonSizes, componentElevationRanges, createFlatShadow, createPressedHoverShadow, createPressedShadow, createRaisedHoverShadow, createRaisedShadow, darkThemeCSSVars, darken, discreteRainbow, elevationSystem, getBaseSurfaceColor, getDiscreteRainbowColor, getElevationConfig, getElevationShadow, getElevationSurface, getHoverColors, getSemanticColors, getThemeCSSVars, getValidatedElevation, gluestackConfig, hexToRgb, hsvToRgb, isDark, lightThemeCSSVars, lighten, neumorphicShadows, primitiveBorderRadius, primitiveBreakpoints, primitiveColors, primitiveShadows, primitiveSpacing, primitiveTypography, primitiveZIndex, rgbToHex, rgbToHsv, semanticColorsDark, semanticColorsLight, semanticTypography, shadowColors } from './chunk-NA3EES23.mjs';
3
+ import { Pressable, ActivityIndicator, Text, View, TextInput, StyleSheet, Platform, Image, Modal as Modal$1, ScrollView } from 'react-native';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+ import React24, { forwardRef, useState, createContext, useMemo, useContext, useRef, useCallback, useEffect, useSyncExternalStore } from 'react';
8
+
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+ var statusColors = {
13
+ success: {
14
+ subtle: "bg-status-success-subtle",
15
+ outline: "border-2 border-status-success bg-transparent",
16
+ solid: "bg-status-success",
17
+ icon: "text-status-success",
18
+ text: "text-status-success"
19
+ },
20
+ info: {
21
+ subtle: "bg-status-info-subtle",
22
+ outline: "border-2 border-status-info bg-transparent",
23
+ solid: "bg-status-info",
24
+ icon: "text-status-info",
25
+ text: "text-status-info"
26
+ },
27
+ warning: {
28
+ subtle: "bg-status-warning-subtle",
29
+ outline: "border-2 border-status-warning bg-transparent",
30
+ solid: "bg-status-warning",
31
+ icon: "text-status-warning",
32
+ text: "text-status-warning"
33
+ },
34
+ error: {
35
+ subtle: "bg-status-error-subtle",
36
+ outline: "border-2 border-status-error bg-transparent",
37
+ solid: "bg-status-error",
38
+ icon: "text-status-error",
39
+ text: "text-status-error"
40
+ }
41
+ };
42
+ var defaultIcons = {
43
+ success: "\u2713",
44
+ info: "\u2139",
45
+ warning: "\u26A0",
46
+ error: "\u2715"
47
+ };
48
+ function Alert({
49
+ status = "info",
50
+ variant = "subtle",
51
+ icon,
52
+ showIcon = true,
53
+ onClose,
54
+ className,
55
+ children,
56
+ ...props
57
+ }) {
58
+ const colors = statusColors[status];
59
+ const isSolid = variant === "solid";
60
+ return /* @__PURE__ */ jsxs(
61
+ View,
62
+ {
63
+ accessibilityRole: "alert",
64
+ className: cn(
65
+ "flex-row items-start p-4 rounded-lg",
66
+ colors[variant],
67
+ className
68
+ ),
69
+ ...props,
70
+ children: [
71
+ showIcon && /* @__PURE__ */ jsx(View, { className: "mr-3 mt-0.5", children: icon || /* @__PURE__ */ jsx(
72
+ Text,
73
+ {
74
+ className: cn(
75
+ "text-lg font-bold",
76
+ isSolid ? "text-white" : colors.icon
77
+ ),
78
+ children: defaultIcons[status]
79
+ }
80
+ ) }),
81
+ /* @__PURE__ */ jsx(View, { className: "flex-1", children }),
82
+ onClose && /* @__PURE__ */ jsx(
83
+ Pressable,
84
+ {
85
+ onPress: onClose,
86
+ accessibilityRole: "button",
87
+ accessibilityLabel: "Close alert",
88
+ className: "ml-2 p-1 rounded web:hover:bg-black/10 active:bg-black/20",
89
+ children: /* @__PURE__ */ jsx(Text, { className: cn("text-lg", isSolid ? "text-white/70" : "text-text-secondary"), children: "\xD7" })
90
+ }
91
+ )
92
+ ]
93
+ }
94
+ );
95
+ }
96
+ function AlertTitle({ children, className }) {
97
+ return /* @__PURE__ */ jsx(Text, { className: cn("font-semibold text-text-primary mb-1", className), children });
98
+ }
99
+ function AlertDescription({ children, className }) {
100
+ return /* @__PURE__ */ jsx(Text, { className: cn("text-sm text-text-secondary", className), children });
101
+ }
102
+ var variantStyles = {
103
+ solid: {
104
+ primary: "bg-brand-primary active:bg-brand-primary-dark active:scale-[0.98] web:hover:bg-brand-primary-dark web:active:scale-[0.98]",
105
+ secondary: "bg-brand-secondary active:bg-brand-secondary-dark active:scale-[0.98] web:hover:bg-brand-secondary-dark web:active:scale-[0.98]",
106
+ success: "bg-status-success active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]",
107
+ error: "bg-status-error active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]",
108
+ warning: "bg-status-warning active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]",
109
+ info: "bg-status-info active:opacity-90 active:scale-[0.98] web:hover:opacity-90 web:active:scale-[0.98]"
110
+ },
111
+ outline: {
112
+ primary: "border-2 border-brand-primary bg-transparent active:bg-brand-primary-subtle active:scale-[0.98] web:hover:bg-brand-primary-subtle web:active:scale-[0.98]",
113
+ secondary: "border-2 border-brand-secondary bg-transparent active:bg-brand-secondary-subtle active:scale-[0.98] web:hover:bg-brand-secondary-subtle web:active:scale-[0.98]",
114
+ success: "border-2 border-status-success bg-transparent active:bg-status-success-subtle active:scale-[0.98] web:hover:bg-status-success-subtle web:active:scale-[0.98]",
115
+ error: "border-2 border-status-error bg-transparent active:bg-status-error-subtle active:scale-[0.98] web:hover:bg-status-error-subtle web:active:scale-[0.98]",
116
+ warning: "border-2 border-status-warning bg-transparent active:bg-status-warning-subtle active:scale-[0.98] web:hover:bg-status-warning-subtle web:active:scale-[0.98]",
117
+ info: "border-2 border-status-info bg-transparent active:bg-status-info-subtle active:scale-[0.98] web:hover:bg-status-info-subtle web:active:scale-[0.98]"
118
+ },
119
+ ghost: {
120
+ primary: "bg-transparent active:bg-brand-primary-subtle active:scale-[0.98] web:hover:bg-brand-primary-subtle web:active:scale-[0.98]",
121
+ secondary: "bg-transparent active:bg-brand-secondary-subtle active:scale-[0.98] web:hover:bg-brand-secondary-subtle web:active:scale-[0.98]",
122
+ success: "bg-transparent active:bg-status-success-subtle active:scale-[0.98] web:hover:bg-status-success-subtle web:active:scale-[0.98]",
123
+ error: "bg-transparent active:bg-status-error-subtle active:scale-[0.98] web:hover:bg-status-error-subtle web:active:scale-[0.98]",
124
+ warning: "bg-transparent active:bg-status-warning-subtle active:scale-[0.98] web:hover:bg-status-warning-subtle web:active:scale-[0.98]",
125
+ info: "bg-transparent active:bg-status-info-subtle active:scale-[0.98] web:hover:bg-status-info-subtle web:active:scale-[0.98]"
126
+ },
127
+ link: {
128
+ primary: "bg-transparent",
129
+ secondary: "bg-transparent",
130
+ success: "bg-transparent",
131
+ error: "bg-transparent",
132
+ warning: "bg-transparent",
133
+ info: "bg-transparent"
134
+ }
135
+ };
136
+ var textStyles = {
137
+ solid: {
138
+ primary: "text-white",
139
+ secondary: "text-white",
140
+ success: "text-white",
141
+ error: "text-white",
142
+ warning: "text-white",
143
+ info: "text-white"
144
+ },
145
+ outline: {
146
+ primary: "text-brand-primary",
147
+ secondary: "text-brand-secondary",
148
+ success: "text-status-success",
149
+ error: "text-status-error",
150
+ warning: "text-status-warning",
151
+ info: "text-status-info"
152
+ },
153
+ ghost: {
154
+ primary: "text-brand-primary",
155
+ secondary: "text-brand-secondary",
156
+ success: "text-status-success",
157
+ error: "text-status-error",
158
+ warning: "text-status-warning",
159
+ info: "text-status-info"
160
+ },
161
+ link: {
162
+ primary: "text-brand-primary web:hover:underline",
163
+ secondary: "text-brand-secondary web:hover:underline",
164
+ success: "text-status-success web:hover:underline",
165
+ error: "text-status-error web:hover:underline",
166
+ warning: "text-status-warning web:hover:underline",
167
+ info: "text-status-info web:hover:underline"
168
+ }
169
+ };
170
+ var sizeStyles = {
171
+ sm: "px-4 py-1.5 min-h-[32px]",
172
+ md: "px-5 py-2 min-h-[40px]",
173
+ lg: "px-6 py-2.5 min-h-[48px]"
174
+ };
175
+ var iconButtonSizeStyles = {
176
+ sm: "w-8 h-8 p-0",
177
+ md: "w-10 h-10 p-0",
178
+ lg: "w-12 h-12 p-0"
179
+ };
180
+ var textSizeStyles = {
181
+ sm: "text-sm",
182
+ md: "text-sm",
183
+ lg: "text-base"
184
+ };
185
+ var Button = forwardRef(function Button2({
186
+ variant = "solid",
187
+ size = "md",
188
+ color = "primary",
189
+ isIconButton = false,
190
+ isDisabled = false,
191
+ isLoading = false,
192
+ loadingText,
193
+ fullWidth = false,
194
+ className,
195
+ children,
196
+ ...props
197
+ }, ref) {
198
+ const disabled = isDisabled || isLoading;
199
+ return /* @__PURE__ */ jsxs(
200
+ Pressable,
201
+ {
202
+ ref,
203
+ disabled,
204
+ accessibilityRole: "button",
205
+ accessibilityState: { disabled },
206
+ className: cn(
207
+ // Base styles
208
+ "flex-row items-center justify-center rounded-md transition-all duration-150",
209
+ // Variant + color styles
210
+ variantStyles[variant][color],
211
+ // Size styles (icon button vs regular)
212
+ isIconButton ? iconButtonSizeStyles[size] : sizeStyles[size],
213
+ // Full width
214
+ fullWidth && "w-full",
215
+ // Disabled styles - more refined
216
+ disabled && "opacity-40 cursor-not-allowed active:scale-100 web:active:scale-100",
217
+ // Link variant has no padding
218
+ variant === "link" && "px-0 py-0 min-h-0",
219
+ className
220
+ ),
221
+ ...props,
222
+ children: [
223
+ isLoading && /* @__PURE__ */ jsx(
224
+ ActivityIndicator,
225
+ {
226
+ size: "small",
227
+ color: variant === "solid" ? semanticColorsDark["on-brand-primary"] : void 0,
228
+ className: "mr-2"
229
+ }
230
+ ),
231
+ isLoading && loadingText ? /* @__PURE__ */ jsx(
232
+ Text,
233
+ {
234
+ className: cn(
235
+ "font-semibold",
236
+ textSizeStyles[size],
237
+ textStyles[variant][color]
238
+ ),
239
+ children: loadingText
240
+ }
241
+ ) : children
242
+ ]
243
+ }
244
+ );
245
+ });
246
+ function ButtonText({ children, className }) {
247
+ return /* @__PURE__ */ jsx(Text, { className: cn("font-semibold text-inherit", className), children });
248
+ }
249
+ function ButtonIcon({ as: Icon, size = 16, className }) {
250
+ return /* @__PURE__ */ jsx(Icon, { size, className: cn("text-inherit", className) });
251
+ }
252
+ function ButtonSpinner({ className }) {
253
+ return /* @__PURE__ */ jsx(ActivityIndicator, { size: "small", className: cn("text-inherit", className) });
254
+ }
255
+ var sizeStyles2 = {
256
+ sm: "h-8 px-3 text-sm",
257
+ md: "h-10 px-4 text-base",
258
+ lg: "h-12 px-4 text-lg"
259
+ };
260
+ var multilineSizeStyles = {
261
+ sm: "min-h-[80px] px-3 py-2 text-sm",
262
+ md: "min-h-[100px] px-4 py-3 text-base",
263
+ lg: "min-h-[120px] px-4 py-3 text-lg"
264
+ };
265
+ var variantStyles2 = {
266
+ outline: {
267
+ base: "border border-border-input rounded-md bg-transparent",
268
+ hover: "web:hover:border-border-input-hover",
269
+ focus: "border-border-input-focus",
270
+ error: "border-border-input-error"
271
+ },
272
+ filled: {
273
+ base: "border border-transparent rounded-md bg-surface-input",
274
+ hover: "web:hover:border-border-input-hover",
275
+ focus: "border-border-input-focus bg-transparent",
276
+ error: "border-border-input-error"
277
+ },
278
+ underline: {
279
+ base: "border-b border-border-input rounded-none bg-transparent",
280
+ hover: "web:hover:border-border-input-hover",
281
+ focus: "border-border-input-focus",
282
+ error: "border-border-input-error"
283
+ }
284
+ };
285
+ var Input = forwardRef(function Input2({
286
+ size = "md",
287
+ variant = "outline",
288
+ isDisabled = false,
289
+ isInvalid = false,
290
+ isReadOnly = false,
291
+ isRequired = false,
292
+ multiline = false,
293
+ numberOfLines = 4,
294
+ label,
295
+ helperText,
296
+ errorMessage,
297
+ leftElement,
298
+ rightElement,
299
+ className,
300
+ inputClassName,
301
+ onFocus,
302
+ onBlur,
303
+ ...props
304
+ }, ref) {
305
+ const [isFocused, setIsFocused] = useState(false);
306
+ const handleFocus = (e) => {
307
+ setIsFocused(true);
308
+ onFocus?.(e);
309
+ };
310
+ const handleBlur = (e) => {
311
+ setIsFocused(false);
312
+ onBlur?.(e);
313
+ };
314
+ const showError = isInvalid && errorMessage;
315
+ const showHelper = !showError && helperText;
316
+ return /* @__PURE__ */ jsxs(View, { className: cn("w-full", className), children: [
317
+ label && /* @__PURE__ */ jsxs(Text, { className: "mb-1.5 text-sm font-medium text-text-primary", children: [
318
+ label,
319
+ isRequired && /* @__PURE__ */ jsx(Text, { className: "text-status-error ml-0.5", children: "*" })
320
+ ] }),
321
+ /* @__PURE__ */ jsxs(
322
+ View,
323
+ {
324
+ className: cn(
325
+ "flex-row transition-colors duration-150",
326
+ multiline ? "items-start" : "items-center",
327
+ variantStyles2[variant].base,
328
+ !isDisabled && !isInvalid && variantStyles2[variant].hover,
329
+ isFocused && variantStyles2[variant].focus,
330
+ isInvalid && variantStyles2[variant].error,
331
+ isDisabled && "opacity-40 cursor-not-allowed"
332
+ ),
333
+ children: [
334
+ leftElement && /* @__PURE__ */ jsx(View, { className: cn("pl-3 pr-1", multiline && "pt-3"), children: leftElement }),
335
+ /* @__PURE__ */ jsx(
336
+ TextInput,
337
+ {
338
+ ref,
339
+ editable: !isDisabled && !isReadOnly,
340
+ accessibilityLabel: label,
341
+ accessibilityState: {
342
+ disabled: isDisabled
343
+ },
344
+ multiline,
345
+ numberOfLines: multiline ? numberOfLines : 1,
346
+ textAlignVertical: multiline ? "top" : "center",
347
+ placeholderTextColor: "var(--color-text-tertiary)",
348
+ onFocus: handleFocus,
349
+ onBlur: handleBlur,
350
+ className: cn(
351
+ "flex-1 text-text-primary",
352
+ multiline ? multilineSizeStyles[size] : sizeStyles2[size],
353
+ leftElement && "pl-1",
354
+ rightElement && "pr-1",
355
+ inputClassName
356
+ ),
357
+ ...props
358
+ }
359
+ ),
360
+ rightElement && /* @__PURE__ */ jsx(View, { className: cn("pl-1 pr-3", multiline && "pt-3"), children: rightElement })
361
+ ]
362
+ }
363
+ ),
364
+ showHelper && /* @__PURE__ */ jsx(Text, { className: "mt-1.5 text-xs text-text-secondary", children: helperText }),
365
+ showError && /* @__PURE__ */ jsx(Text, { className: "mt-1.5 text-xs text-status-error", children: errorMessage })
366
+ ] });
367
+ });
368
+ function InputGroup({ children, className }) {
369
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-col gap-4", className), children });
370
+ }
371
+ var PasswordInput = forwardRef(function PasswordInput2({ showIcon, hideIcon, ...props }, ref) {
372
+ const [isVisible, setIsVisible] = useState(false);
373
+ const toggleVisibility = () => setIsVisible(!isVisible);
374
+ const defaultShowIcon = /* @__PURE__ */ jsxs(View, { className: "w-5 h-5 items-center justify-center", children: [
375
+ /* @__PURE__ */ jsx(View, { className: "w-3 h-3 rounded-full border-2 border-text-secondary" }),
376
+ /* @__PURE__ */ jsx(View, { className: "absolute w-1.5 h-1.5 rounded-full bg-text-secondary" })
377
+ ] });
378
+ const defaultHideIcon = /* @__PURE__ */ jsxs(View, { className: "w-5 h-5 items-center justify-center", children: [
379
+ /* @__PURE__ */ jsx(View, { className: "w-3 h-3 rounded-full border-2 border-text-secondary" }),
380
+ /* @__PURE__ */ jsx(View, { className: "absolute w-1.5 h-1.5 rounded-full bg-text-secondary" }),
381
+ /* @__PURE__ */ jsx(View, { className: "absolute w-5 h-0.5 bg-text-secondary rotate-45" })
382
+ ] });
383
+ return /* @__PURE__ */ jsx(
384
+ Input,
385
+ {
386
+ ref,
387
+ secureTextEntry: !isVisible,
388
+ rightElement: /* @__PURE__ */ jsx(
389
+ Pressable,
390
+ {
391
+ onPress: toggleVisibility,
392
+ accessibilityRole: "button",
393
+ accessibilityLabel: isVisible ? "Hide password" : "Show password",
394
+ className: "p-1 rounded active:opacity-70",
395
+ children: isVisible ? hideIcon || defaultHideIcon : showIcon || defaultShowIcon
396
+ }
397
+ ),
398
+ ...props
399
+ }
400
+ );
401
+ });
402
+ function getTheme() {
403
+ if (typeof document === "undefined") return "dark";
404
+ return document.documentElement.classList.contains("light") ? "light" : "dark";
405
+ }
406
+ var listeners = [];
407
+ function subscribe(listener) {
408
+ listeners = [...listeners, listener];
409
+ if (typeof document !== "undefined" && listeners.length === 1) {
410
+ const observer = new MutationObserver((mutations) => {
411
+ for (const mutation of mutations) {
412
+ if (mutation.type === "attributes" && mutation.attributeName === "class") {
413
+ listeners.forEach((l) => l());
414
+ }
415
+ }
416
+ });
417
+ observer.observe(document.documentElement, {
418
+ attributes: true,
419
+ attributeFilter: ["class"]
420
+ });
421
+ subscribe._observer = observer;
422
+ }
423
+ return () => {
424
+ listeners = listeners.filter((l) => l !== listener);
425
+ if (listeners.length === 0 && subscribe._observer) {
426
+ subscribe._observer.disconnect();
427
+ subscribe._observer = null;
428
+ }
429
+ };
430
+ }
431
+ function getSnapshot() {
432
+ return getTheme();
433
+ }
434
+ function getServerSnapshot() {
435
+ return "dark";
436
+ }
437
+ function useTheme() {
438
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
439
+ }
440
+ var variantStyles3 = {
441
+ elevated: "",
442
+ // Will be set dynamically via elevation system
443
+ outline: "border-2 border-border-strong",
444
+ // Thicker border with stronger contrast
445
+ filled: ""
446
+ // Will be set dynamically via elevation system
447
+ };
448
+ function Card({
449
+ variant = "elevated",
450
+ elevation = 2,
451
+ isInteractive = false,
452
+ isLoading = false,
453
+ onPress,
454
+ borderColor,
455
+ bgColor,
456
+ className,
457
+ children,
458
+ style,
459
+ skeletonHasHeader = true,
460
+ skeletonHasFooter = false,
461
+ skeletonContentLines = 3,
462
+ ...props
463
+ }) {
464
+ const isClickable = isInteractive || !!onPress;
465
+ const [isHovered, setIsHovered] = useState(false);
466
+ const theme = useTheme();
467
+ const elevationLevel = useMemo(() => {
468
+ const validated = getValidatedElevation("card", elevation);
469
+ if (variant === "outline") {
470
+ return 1;
471
+ }
472
+ return validated;
473
+ }, [variant, elevation]);
474
+ const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme]);
475
+ const surfaceColor = useMemo(() => {
476
+ if (variant === "outline" && theme === "light") {
477
+ return "#FAFAFA";
478
+ }
479
+ return getElevationSurface(baseColor, elevationLevel, theme);
480
+ }, [baseColor, elevationLevel, theme, variant]);
481
+ const shadowStyle = useMemo(() => {
482
+ const shouldHover = isHovered && isClickable;
483
+ return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
484
+ }, [baseColor, elevationLevel, theme, isHovered, isClickable]);
485
+ const cardContent = isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
486
+ skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
487
+ /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
488
+ /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
489
+ ] }),
490
+ /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
491
+ View,
492
+ {
493
+ className: cn(
494
+ "h-4 bg-interactive-disabled rounded",
495
+ i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
496
+ )
497
+ },
498
+ i
499
+ )) }),
500
+ skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
501
+ ] }) : children;
502
+ const baseClassName = cn(
503
+ "rounded-lg overflow-hidden relative",
504
+ // Apply variant styles, but only use default border color if no custom borderColor
505
+ variant === "outline" ? borderColor ? "border-2" : variantStyles3[variant] : variantStyles3[variant],
506
+ // Remove Tailwind shadow classes - we're using elevation shadows via style prop
507
+ isClickable && "web:cursor-pointer web:transition-all web:duration-150",
508
+ isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
509
+ isLoading && "pointer-events-none animate-pulse",
510
+ className
511
+ );
512
+ const mergedStyle = useMemo(() => {
513
+ const elevationStyle = {
514
+ backgroundColor: bgColor || surfaceColor,
515
+ ...shadowStyle
516
+ };
517
+ if (borderColor) {
518
+ elevationStyle.borderColor = borderColor;
519
+ }
520
+ if (!style) return elevationStyle;
521
+ return [style, elevationStyle];
522
+ }, [style, surfaceColor, shadowStyle, borderColor, bgColor]);
523
+ if (isClickable) {
524
+ return /* @__PURE__ */ jsx(
525
+ Pressable,
526
+ {
527
+ onPress,
528
+ onHoverIn: () => setIsHovered(true),
529
+ onHoverOut: () => setIsHovered(false),
530
+ accessibilityRole: "button",
531
+ className: baseClassName,
532
+ style: mergedStyle,
533
+ ...props,
534
+ children: cardContent
535
+ }
536
+ );
537
+ }
538
+ return /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: cardContent });
539
+ }
540
+ function CardHeader({ children, className }) {
541
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-6", className), children });
542
+ }
543
+ function CardTitle({ children, className }) {
544
+ return /* @__PURE__ */ jsx(
545
+ Text,
546
+ {
547
+ accessibilityRole: "header",
548
+ className: cn("text-lg font-semibold text-text-primary font-heading", className),
549
+ children
550
+ }
551
+ );
552
+ }
553
+ function CardDescription({ children, className }) {
554
+ return /* @__PURE__ */ jsx(Text, { className: cn("mt-1.5 text-sm text-text-secondary", className), children });
555
+ }
556
+ function CardContent({ children, className }) {
557
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4", className), children });
558
+ }
559
+ function CardFooter({ children, className }) {
560
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
561
+ }
562
+ function CardSkeleton({
563
+ hasHeader = true,
564
+ hasFooter = false,
565
+ contentLines = 3,
566
+ className
567
+ }) {
568
+ return /* @__PURE__ */ jsxs(Card, { variant: "elevated", elevation: 2, className: cn("animate-pulse", className), children: [
569
+ hasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
570
+ /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
571
+ /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
572
+ ] }),
573
+ /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: contentLines }).map((_, i) => /* @__PURE__ */ jsx(
574
+ View,
575
+ {
576
+ className: cn(
577
+ "h-4 bg-interactive-disabled rounded",
578
+ i < contentLines - 1 ? "mb-2 w-full" : "w-4/5"
579
+ )
580
+ },
581
+ i
582
+ )) }),
583
+ hasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
584
+ ] });
585
+ }
586
+ var variantColorStyles = {
587
+ solid: {
588
+ default: "bg-border-strong text-text-inverse",
589
+ primary: "bg-brand-primary text-text-inverse",
590
+ secondary: "bg-brand-secondary text-text-inverse",
591
+ success: "bg-status-success text-text-inverse",
592
+ error: "bg-status-error text-text-inverse",
593
+ warning: "bg-status-warning text-text-inverse",
594
+ info: "bg-status-info text-text-inverse"
595
+ },
596
+ subtle: {
597
+ default: "bg-surface-raised text-text-secondary",
598
+ primary: "bg-brand-primary-subtle text-brand-primary",
599
+ secondary: "bg-brand-secondary-subtle text-brand-secondary",
600
+ success: "bg-status-success-subtle text-status-success",
601
+ error: "bg-status-error-subtle text-status-error",
602
+ warning: "bg-status-warning-subtle text-status-warning",
603
+ info: "bg-status-info-subtle text-status-info"
604
+ },
605
+ outline: {
606
+ default: "border border-border-strong text-text-secondary",
607
+ primary: "border border-brand-primary text-brand-primary",
608
+ secondary: "border border-brand-secondary text-brand-secondary",
609
+ success: "border border-status-success text-status-success",
610
+ error: "border border-status-error text-status-error",
611
+ warning: "border border-status-warning text-status-warning",
612
+ info: "border border-status-info text-status-info"
613
+ }
614
+ };
615
+ var sizeStyles3 = {
616
+ sm: "px-1.5 py-0.5 text-xs",
617
+ md: "px-2 py-0.5 text-xs",
618
+ lg: "px-2.5 py-1 text-sm"
619
+ };
620
+ function Badge({
621
+ variant = "subtle",
622
+ color = "default",
623
+ size = "md",
624
+ className,
625
+ children,
626
+ ...props
627
+ }) {
628
+ return /* @__PURE__ */ jsx(
629
+ View,
630
+ {
631
+ className: cn(
632
+ "inline-flex items-center justify-center rounded-full font-medium",
633
+ variantColorStyles[variant][color],
634
+ sizeStyles3[size],
635
+ className
636
+ ),
637
+ ...props,
638
+ children: typeof children === "string" ? /* @__PURE__ */ jsx(Text, { className: "text-inherit font-medium", children }) : children
639
+ }
640
+ );
641
+ }
642
+ function BadgeText({ children, className }) {
643
+ return /* @__PURE__ */ jsx(Text, { className: cn("text-inherit font-medium", className), children });
644
+ }
645
+ var sizeMap = {
646
+ sm: "small",
647
+ md: "small",
648
+ lg: "large",
649
+ xl: "large"
650
+ };
651
+ var colorMap = {
652
+ primary: "#5048E5",
653
+ secondary: "#10B981",
654
+ white: "#FFFFFF",
655
+ default: "#6B7280"
656
+ };
657
+ var containerSizes = {
658
+ sm: "w-4 h-4",
659
+ md: "w-6 h-6",
660
+ lg: "w-8 h-8",
661
+ xl: "w-12 h-12"
662
+ };
663
+ function Spinner({
664
+ size = "md",
665
+ color = "primary",
666
+ label = "Loading",
667
+ className,
668
+ ...props
669
+ }) {
670
+ return /* @__PURE__ */ jsx(
671
+ View,
672
+ {
673
+ accessibilityRole: "progressbar",
674
+ accessibilityLabel: label,
675
+ className: cn("items-center justify-center", containerSizes[size], className),
676
+ ...props,
677
+ children: /* @__PURE__ */ jsx(
678
+ ActivityIndicator,
679
+ {
680
+ size: sizeMap[size],
681
+ color: colorMap[color]
682
+ }
683
+ )
684
+ }
685
+ );
686
+ }
687
+ var sizeStyles4 = {
688
+ xs: { container: "w-6 h-6", text: "text-xs", image: "w-6 h-6" },
689
+ sm: { container: "w-8 h-8", text: "text-xs", image: "w-8 h-8" },
690
+ md: { container: "w-10 h-10", text: "text-sm", image: "w-10 h-10" },
691
+ lg: { container: "w-12 h-12", text: "text-base", image: "w-12 h-12" },
692
+ xl: { container: "w-16 h-16", text: "text-lg", image: "w-16 h-16" },
693
+ "2xl": { container: "w-20 h-20", text: "text-xl", image: "w-20 h-20" }
694
+ };
695
+ function Avatar({
696
+ size = "md",
697
+ source,
698
+ fallback,
699
+ alt,
700
+ className,
701
+ ...props
702
+ }) {
703
+ const styles2 = sizeStyles4[size];
704
+ const hasImage = source !== void 0;
705
+ return /* @__PURE__ */ jsx(
706
+ View,
707
+ {
708
+ accessibilityRole: "image",
709
+ accessibilityLabel: alt || fallback || "Avatar",
710
+ className: cn(
711
+ "items-center justify-center rounded-full overflow-hidden",
712
+ "bg-border-strong",
713
+ styles2.container,
714
+ className
715
+ ),
716
+ ...props,
717
+ children: hasImage ? /* @__PURE__ */ jsx(
718
+ Image,
719
+ {
720
+ source,
721
+ className: cn("rounded-full", styles2.image),
722
+ accessibilityLabel: alt
723
+ }
724
+ ) : fallback ? /* @__PURE__ */ jsx(Text, { className: cn("font-semibold text-text-primary", styles2.text), children: fallback }) : /* @__PURE__ */ jsx(View, { className: "w-full h-full bg-surface-raised" })
725
+ }
726
+ );
727
+ }
728
+ var badgeColors = {
729
+ success: "bg-status-success",
730
+ error: "bg-status-error",
731
+ warning: "bg-status-warning",
732
+ default: "bg-border-strong"
733
+ };
734
+ function AvatarBadge({ color = "success", className }) {
735
+ return /* @__PURE__ */ jsx(
736
+ View,
737
+ {
738
+ className: cn(
739
+ "absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-surface-base",
740
+ badgeColors[color],
741
+ className
742
+ )
743
+ }
744
+ );
745
+ }
746
+ function AvatarGroup({
747
+ children,
748
+ max,
749
+ size = "md",
750
+ className
751
+ }) {
752
+ const childArray = React24.Children.toArray(children);
753
+ const visibleChildren = max ? childArray.slice(0, max) : childArray;
754
+ const remainingCount = max ? Math.max(0, childArray.length - max) : 0;
755
+ return /* @__PURE__ */ jsxs(View, { className: cn("flex-row", className), children: [
756
+ visibleChildren.map((child, index) => /* @__PURE__ */ jsx(
757
+ View,
758
+ {
759
+ className: cn(
760
+ "border-2 border-surface-base rounded-full",
761
+ index > 0 && "-ml-2"
762
+ ),
763
+ children: React24.isValidElement(child) ? React24.cloneElement(child, { size }) : child
764
+ },
765
+ index
766
+ )),
767
+ remainingCount > 0 && /* @__PURE__ */ jsx(
768
+ View,
769
+ {
770
+ className: cn(
771
+ "border-2 border-surface-base rounded-full -ml-2",
772
+ "items-center justify-center bg-surface-raised",
773
+ sizeStyles4[size].container
774
+ ),
775
+ children: /* @__PURE__ */ jsxs(Text, { className: cn("font-semibold text-text-secondary", sizeStyles4[size].text), children: [
776
+ "+",
777
+ remainingCount
778
+ ] })
779
+ }
780
+ )
781
+ ] });
782
+ }
783
+ function Divider({
784
+ orientation = "horizontal",
785
+ className,
786
+ ...props
787
+ }) {
788
+ return /* @__PURE__ */ jsx(
789
+ View,
790
+ {
791
+ accessibilityRole: "none",
792
+ className: cn(
793
+ "bg-divider",
794
+ orientation === "horizontal" ? "h-px w-full" : "w-px h-full",
795
+ className
796
+ ),
797
+ ...props
798
+ }
799
+ );
800
+ }
801
+ var sizeStyles5 = {
802
+ sm: { box: "w-4 h-4", icon: "w-2.5 h-2.5", label: "text-sm" },
803
+ md: { box: "w-5 h-5", icon: "w-3 h-3", label: "text-base" },
804
+ lg: { box: "w-6 h-6", icon: "w-3.5 h-3.5", label: "text-lg" }
805
+ };
806
+ var Checkbox = forwardRef(function Checkbox2({
807
+ isChecked = false,
808
+ isIndeterminate = false,
809
+ isDisabled = false,
810
+ isInvalid = false,
811
+ size = "md",
812
+ label,
813
+ helperText,
814
+ value,
815
+ onCheckedChange,
816
+ className,
817
+ ...props
818
+ }, ref) {
819
+ const styles2 = sizeStyles5[size];
820
+ const handlePress = () => {
821
+ if (!isDisabled) {
822
+ onCheckedChange?.(!isChecked);
823
+ }
824
+ };
825
+ return /* @__PURE__ */ jsxs(
826
+ Pressable,
827
+ {
828
+ ref,
829
+ disabled: isDisabled,
830
+ onPress: handlePress,
831
+ accessibilityRole: "checkbox",
832
+ accessibilityState: {
833
+ checked: isIndeterminate ? "mixed" : isChecked,
834
+ disabled: isDisabled
835
+ },
836
+ accessibilityLabel: label,
837
+ className: cn(
838
+ "flex-row items-start gap-2",
839
+ isDisabled && "opacity-50",
840
+ className
841
+ ),
842
+ ...props,
843
+ children: [
844
+ /* @__PURE__ */ jsxs(
845
+ View,
846
+ {
847
+ className: cn(
848
+ "items-center justify-center rounded border-2 transition-colors",
849
+ styles2.box,
850
+ isChecked || isIndeterminate ? "bg-brand-primary border-brand-primary" : "bg-transparent border-border-default",
851
+ isInvalid && "border-status-error",
852
+ !isDisabled && "web:hover:border-brand-primary"
853
+ ),
854
+ children: [
855
+ isChecked && !isIndeterminate && /* @__PURE__ */ jsx(View, { className: cn("bg-white rounded-sm", styles2.icon), children: /* @__PURE__ */ jsx(Text, { className: "text-brand-primary font-bold text-center leading-none", children: "\u2713" }) }),
856
+ isIndeterminate && /* @__PURE__ */ jsx(View, { className: cn("bg-white h-0.5 w-2/3 rounded") })
857
+ ]
858
+ }
859
+ ),
860
+ (label || helperText) && /* @__PURE__ */ jsxs(View, { className: "flex-1", children: [
861
+ label && /* @__PURE__ */ jsx(Text, { className: cn("text-text-primary font-medium", styles2.label), children: label }),
862
+ helperText && /* @__PURE__ */ jsx(Text, { className: "text-xs text-text-secondary mt-0.5", children: helperText })
863
+ ] })
864
+ ]
865
+ }
866
+ );
867
+ });
868
+ function CheckboxGroup({
869
+ children,
870
+ label,
871
+ orientation = "vertical",
872
+ className
873
+ }) {
874
+ return /* @__PURE__ */ jsxs(View, { className: cn("gap-1", className), children: [
875
+ label && /* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-text-primary mb-2", children: label }),
876
+ /* @__PURE__ */ jsx(
877
+ View,
878
+ {
879
+ className: cn(
880
+ orientation === "vertical" ? "flex-col gap-2" : "flex-row gap-4"
881
+ ),
882
+ children
883
+ }
884
+ )
885
+ ] });
886
+ }
887
+ var sizeStyles6 = {
888
+ sm: { track: "w-8 h-4", thumb: "w-3 h-3", translate: "translate-x-4" },
889
+ md: { track: "w-10 h-5", thumb: "w-4 h-4", translate: "translate-x-5" },
890
+ lg: { track: "w-12 h-6", thumb: "w-5 h-5", translate: "translate-x-6" }
891
+ };
892
+ var Switch = forwardRef(function Switch2({
893
+ isChecked = false,
894
+ isDisabled = false,
895
+ size = "md",
896
+ label,
897
+ labelPosition = "right",
898
+ onCheckedChange,
899
+ className,
900
+ ...props
901
+ }, ref) {
902
+ const styles2 = sizeStyles6[size];
903
+ const handlePress = () => {
904
+ if (!isDisabled) {
905
+ onCheckedChange?.(!isChecked);
906
+ }
907
+ };
908
+ const switchElement = /* @__PURE__ */ jsx(
909
+ View,
910
+ {
911
+ className: cn(
912
+ "rounded-full p-0.5 transition-colors",
913
+ styles2.track,
914
+ isChecked ? "bg-brand-primary" : "bg-border-strong"
915
+ ),
916
+ children: /* @__PURE__ */ jsx(
917
+ View,
918
+ {
919
+ className: cn(
920
+ "rounded-full bg-white shadow-sm transition-transform",
921
+ styles2.thumb,
922
+ isChecked && styles2.translate
923
+ )
924
+ }
925
+ )
926
+ }
927
+ );
928
+ return /* @__PURE__ */ jsxs(
929
+ Pressable,
930
+ {
931
+ ref,
932
+ disabled: isDisabled,
933
+ onPress: handlePress,
934
+ accessibilityRole: "switch",
935
+ accessibilityState: { checked: isChecked, disabled: isDisabled },
936
+ accessibilityLabel: label,
937
+ className: cn(
938
+ "flex-row items-center gap-2",
939
+ isDisabled && "opacity-50",
940
+ className
941
+ ),
942
+ ...props,
943
+ children: [
944
+ label && labelPosition === "left" && /* @__PURE__ */ jsx(Text, { className: "text-text-primary font-medium", children: label }),
945
+ switchElement,
946
+ label && labelPosition === "right" && /* @__PURE__ */ jsx(Text, { className: "text-text-primary font-medium", children: label })
947
+ ]
948
+ }
949
+ );
950
+ });
951
+ var ModalContext = createContext({ size: "md", scrollBehavior: "outside" });
952
+ var sizeStyles7 = {
953
+ xs: "max-w-xs",
954
+ sm: "max-w-sm",
955
+ md: "max-w-md",
956
+ lg: "max-w-lg",
957
+ xl: "max-w-xl",
958
+ full: "max-w-full m-4"
959
+ };
960
+ function Modal({
961
+ isOpen,
962
+ onClose,
963
+ size = "md",
964
+ scrollBehavior = "outside",
965
+ closeOnOverlayClick = true,
966
+ backdropBlur = false,
967
+ backdropClassName,
968
+ animationType = "fade",
969
+ children,
970
+ ...props
971
+ }) {
972
+ const handleBackdropPress = () => {
973
+ if (closeOnOverlayClick && onClose) {
974
+ onClose();
975
+ }
976
+ };
977
+ const backdropContent = /* @__PURE__ */ jsx(
978
+ Pressable,
979
+ {
980
+ onPress: handleBackdropPress,
981
+ className: cn(
982
+ "flex-1 items-center justify-center",
983
+ backdropBlur ? "bg-black/30 web:backdrop-blur-sm" : "bg-black/50",
984
+ backdropClassName
985
+ ),
986
+ children
987
+ }
988
+ );
989
+ return /* @__PURE__ */ jsx(ModalContext.Provider, { value: { onClose, size, scrollBehavior }, children: /* @__PURE__ */ jsx(
990
+ Modal$1,
991
+ {
992
+ visible: isOpen,
993
+ transparent: true,
994
+ animationType,
995
+ onRequestClose: onClose,
996
+ ...props,
997
+ children: scrollBehavior === "outside" ? /* @__PURE__ */ jsx(
998
+ ScrollView,
999
+ {
1000
+ contentContainerStyle: { flexGrow: 1 },
1001
+ keyboardShouldPersistTaps: "handled",
1002
+ children: backdropContent
1003
+ }
1004
+ ) : backdropContent
1005
+ }
1006
+ ) });
1007
+ }
1008
+ function ModalContent({ children, className }) {
1009
+ const { size } = useContext(ModalContext);
1010
+ return /* @__PURE__ */ jsx(
1011
+ Pressable,
1012
+ {
1013
+ onPress: (e) => e.stopPropagation(),
1014
+ children: /* @__PURE__ */ jsx(
1015
+ View,
1016
+ {
1017
+ className: cn(
1018
+ "bg-surface-elevated rounded-lg shadow-xl w-full",
1019
+ sizeStyles7[size],
1020
+ className
1021
+ ),
1022
+ children
1023
+ }
1024
+ )
1025
+ }
1026
+ );
1027
+ }
1028
+ function ModalHeader({ children, className }) {
1029
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-row items-center justify-between px-6 py-4 border-b border-divider", className), children });
1030
+ }
1031
+ function ModalTitle({ children, className }) {
1032
+ return /* @__PURE__ */ jsx(
1033
+ Text,
1034
+ {
1035
+ accessibilityRole: "header",
1036
+ className: cn("text-lg font-semibold text-text-primary font-heading", className),
1037
+ children
1038
+ }
1039
+ );
1040
+ }
1041
+ function ModalCloseButton({ className }) {
1042
+ const { onClose } = useContext(ModalContext);
1043
+ return /* @__PURE__ */ jsx(
1044
+ Pressable,
1045
+ {
1046
+ onPress: onClose,
1047
+ accessibilityRole: "button",
1048
+ accessibilityLabel: "Close modal",
1049
+ className: cn(
1050
+ "p-1 rounded-md web:hover:bg-interactive-hover active:bg-interactive-active",
1051
+ className
1052
+ ),
1053
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary text-xl leading-none", children: "\xD7" })
1054
+ }
1055
+ );
1056
+ }
1057
+ function ModalBody({ children, maxHeight, className }) {
1058
+ const { scrollBehavior } = useContext(ModalContext);
1059
+ if (scrollBehavior === "inside") {
1060
+ return /* @__PURE__ */ jsx(
1061
+ ScrollView,
1062
+ {
1063
+ className: cn("px-6 py-4", className),
1064
+ style: maxHeight ? { maxHeight } : void 0,
1065
+ showsVerticalScrollIndicator: true,
1066
+ children
1067
+ }
1068
+ );
1069
+ }
1070
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4", className), children });
1071
+ }
1072
+ function ModalFooter({ children, className }) {
1073
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-row items-center justify-end gap-2 px-6 py-4 border-t border-divider", className), children });
1074
+ }
1075
+ function Skeleton({
1076
+ variant = "text",
1077
+ animation = "pulse",
1078
+ width,
1079
+ height,
1080
+ borderRadius,
1081
+ className,
1082
+ style,
1083
+ ...props
1084
+ }) {
1085
+ const variantStyles5 = {
1086
+ text: "h-4 rounded",
1087
+ circle: "rounded-full",
1088
+ rect: "",
1089
+ rounded: "rounded-lg"
1090
+ };
1091
+ const animationStyles = {
1092
+ pulse: "animate-pulse",
1093
+ shimmer: "animate-shimmer",
1094
+ // Note: requires custom animation in Tailwind config
1095
+ none: ""
1096
+ };
1097
+ let finalWidth = width;
1098
+ let finalHeight = height;
1099
+ if (variant === "circle") {
1100
+ if (width && !height) finalHeight = width;
1101
+ if (height && !width) finalWidth = height;
1102
+ }
1103
+ return /* @__PURE__ */ jsx(
1104
+ View,
1105
+ {
1106
+ accessibilityRole: "none",
1107
+ accessibilityLabel: "Loading...",
1108
+ className: cn(
1109
+ "bg-interactive-disabled",
1110
+ variantStyles5[variant],
1111
+ animationStyles[animation],
1112
+ className
1113
+ ),
1114
+ style: [
1115
+ {
1116
+ ...finalWidth !== void 0 && { width: finalWidth },
1117
+ ...finalHeight !== void 0 && { height: finalHeight },
1118
+ ...borderRadius !== void 0 && { borderRadius }
1119
+ },
1120
+ style
1121
+ ],
1122
+ ...props
1123
+ }
1124
+ );
1125
+ }
1126
+ function SkeletonText({
1127
+ lines = 3,
1128
+ lastLineWidth = "60%",
1129
+ gap = 8,
1130
+ animation = "pulse",
1131
+ className
1132
+ }) {
1133
+ return /* @__PURE__ */ jsx(View, { className: cn("gap-2", className), style: { gap }, children: Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ jsx(
1134
+ Skeleton,
1135
+ {
1136
+ variant: "text",
1137
+ animation,
1138
+ width: i === lines - 1 ? lastLineWidth : "100%"
1139
+ },
1140
+ i
1141
+ )) });
1142
+ }
1143
+ function SkeletonCircle({
1144
+ size = 40,
1145
+ animation = "pulse",
1146
+ className
1147
+ }) {
1148
+ return /* @__PURE__ */ jsx(
1149
+ Skeleton,
1150
+ {
1151
+ variant: "circle",
1152
+ width: size,
1153
+ height: size,
1154
+ animation,
1155
+ className
1156
+ }
1157
+ );
1158
+ }
1159
+ function SkeletonCard({
1160
+ hasImage = true,
1161
+ imageHeight = 160,
1162
+ lines = 3,
1163
+ animation = "pulse",
1164
+ className
1165
+ }) {
1166
+ return /* @__PURE__ */ jsxs(View, { className: cn("rounded-lg overflow-hidden bg-surface-elevated", className), children: [
1167
+ hasImage && /* @__PURE__ */ jsx(
1168
+ Skeleton,
1169
+ {
1170
+ variant: "rect",
1171
+ width: "100%",
1172
+ height: imageHeight,
1173
+ animation
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ jsxs(View, { className: "p-4 gap-3", children: [
1177
+ /* @__PURE__ */ jsx(Skeleton, { variant: "text", width: "70%", animation }),
1178
+ /* @__PURE__ */ jsx(SkeletonText, { lines, animation })
1179
+ ] })
1180
+ ] });
1181
+ }
1182
+ function SkeletonListItem({
1183
+ hasAvatar = true,
1184
+ avatarSize = 40,
1185
+ lines = 2,
1186
+ animation = "pulse",
1187
+ className
1188
+ }) {
1189
+ return /* @__PURE__ */ jsxs(View, { className: cn("flex-row items-center gap-3 p-3", className), children: [
1190
+ hasAvatar && /* @__PURE__ */ jsx(SkeletonCircle, { size: avatarSize, animation }),
1191
+ /* @__PURE__ */ jsx(View, { className: "flex-1", children: /* @__PURE__ */ jsx(SkeletonText, { lines, animation }) })
1192
+ ] });
1193
+ }
1194
+ var TabsContext = createContext({
1195
+ activeIndex: 0,
1196
+ setActiveIndex: () => {
1197
+ },
1198
+ variant: "line",
1199
+ orientation: "horizontal"
1200
+ });
1201
+ function Tabs({
1202
+ defaultIndex = 0,
1203
+ index,
1204
+ onChange,
1205
+ variant = "line",
1206
+ orientation = "horizontal",
1207
+ className,
1208
+ children,
1209
+ ...props
1210
+ }) {
1211
+ const [internalIndex, setInternalIndex] = useState(defaultIndex);
1212
+ const activeIndex = index ?? internalIndex;
1213
+ const setActiveIndex = (newIndex) => {
1214
+ if (index === void 0) {
1215
+ setInternalIndex(newIndex);
1216
+ }
1217
+ onChange?.(newIndex);
1218
+ };
1219
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { activeIndex, setActiveIndex, variant, orientation }, children: /* @__PURE__ */ jsx(
1220
+ View,
1221
+ {
1222
+ className: cn(
1223
+ orientation === "vertical" ? "flex-row" : "flex-col",
1224
+ className
1225
+ ),
1226
+ ...props,
1227
+ children
1228
+ }
1229
+ ) });
1230
+ }
1231
+ function TabList({ children, className }) {
1232
+ const { variant, orientation } = useContext(TabsContext);
1233
+ const variantStyles5 = {
1234
+ line: orientation === "horizontal" ? "border-b border-border-default" : "border-r border-border-default",
1235
+ enclosed: "bg-surface-raised rounded-lg p-1",
1236
+ "soft-rounded": "bg-surface-raised rounded-full p-1"
1237
+ };
1238
+ const content = /* @__PURE__ */ jsx(
1239
+ View,
1240
+ {
1241
+ className: cn(
1242
+ orientation === "horizontal" ? "flex-row" : "flex-col",
1243
+ variantStyles5[variant],
1244
+ className
1245
+ ),
1246
+ children: React24.Children.map(children, (child, index) => {
1247
+ if (React24.isValidElement(child)) {
1248
+ return React24.cloneElement(child, { index });
1249
+ }
1250
+ return child;
1251
+ })
1252
+ }
1253
+ );
1254
+ if (orientation === "horizontal") {
1255
+ return /* @__PURE__ */ jsx(
1256
+ ScrollView,
1257
+ {
1258
+ horizontal: true,
1259
+ showsHorizontalScrollIndicator: false,
1260
+ contentContainerStyle: { flexGrow: 1 },
1261
+ children: content
1262
+ }
1263
+ );
1264
+ }
1265
+ return content;
1266
+ }
1267
+ function Tab({
1268
+ index = 0,
1269
+ isDisabled = false,
1270
+ className,
1271
+ children
1272
+ }) {
1273
+ const { activeIndex, setActiveIndex, variant, orientation } = useContext(TabsContext);
1274
+ const isActive = activeIndex === index;
1275
+ const baseStyles = "font-medium text-sm transition-colors";
1276
+ const variantStyles5 = {
1277
+ line: cn(
1278
+ "px-4 py-2",
1279
+ orientation === "horizontal" ? "-mb-px border-b-2" : "-mr-px border-r-2",
1280
+ isActive ? "border-brand-primary text-brand-primary" : "border-transparent text-text-secondary web:hover:text-text-primary"
1281
+ ),
1282
+ enclosed: cn(
1283
+ "px-4 py-2 rounded-md",
1284
+ isActive ? "bg-surface-elevated text-text-primary shadow-sm" : "text-text-secondary web:hover:text-text-primary"
1285
+ ),
1286
+ "soft-rounded": cn(
1287
+ "px-4 py-2 rounded-full",
1288
+ isActive ? "bg-brand-primary text-white" : "text-text-secondary web:hover:text-text-primary"
1289
+ )
1290
+ };
1291
+ return /* @__PURE__ */ jsx(
1292
+ Pressable,
1293
+ {
1294
+ accessibilityRole: "tab",
1295
+ accessibilityState: { selected: isActive, disabled: isDisabled },
1296
+ disabled: isDisabled,
1297
+ onPress: () => setActiveIndex(index),
1298
+ className: cn(
1299
+ baseStyles,
1300
+ variantStyles5[variant],
1301
+ isDisabled && "opacity-50 cursor-not-allowed",
1302
+ className
1303
+ ),
1304
+ children: /* @__PURE__ */ jsx(
1305
+ Text,
1306
+ {
1307
+ className: cn(
1308
+ "font-medium",
1309
+ isActive ? variant === "soft-rounded" ? "text-white" : "text-text-primary" : "text-text-secondary"
1310
+ ),
1311
+ children
1312
+ }
1313
+ )
1314
+ }
1315
+ );
1316
+ }
1317
+ function TabPanels({ children, className }) {
1318
+ const { activeIndex } = useContext(TabsContext);
1319
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-1", className), children: React24.Children.map(children, (child, index) => {
1320
+ if (React24.isValidElement(child) && index === activeIndex) {
1321
+ return child;
1322
+ }
1323
+ return null;
1324
+ }) });
1325
+ }
1326
+ function TabPanel({ children, className }) {
1327
+ return /* @__PURE__ */ jsx(View, { className: cn("py-4", className), children });
1328
+ }
1329
+ var colorStyles = {
1330
+ default: {
1331
+ solid: "bg-neutral-600 text-white",
1332
+ subtle: "bg-neutral-100 text-neutral-700 dark:bg-neutral-800 dark:text-neutral-200",
1333
+ outline: "border border-neutral-300 dark:border-neutral-600 text-neutral-700 dark:text-neutral-200"
1334
+ },
1335
+ primary: {
1336
+ solid: "bg-brand-primary text-white",
1337
+ subtle: "bg-brand-primary-subtle text-brand-primary",
1338
+ outline: "border border-brand-primary text-brand-primary"
1339
+ },
1340
+ secondary: {
1341
+ solid: "bg-brand-secondary text-white",
1342
+ subtle: "bg-brand-secondary-subtle text-brand-secondary",
1343
+ outline: "border border-brand-secondary text-brand-secondary"
1344
+ },
1345
+ success: {
1346
+ solid: "bg-status-success text-white",
1347
+ subtle: "bg-status-success-subtle text-status-success",
1348
+ outline: "border border-status-success text-status-success"
1349
+ },
1350
+ error: {
1351
+ solid: "bg-status-error text-white",
1352
+ subtle: "bg-status-error-subtle text-status-error",
1353
+ outline: "border border-status-error text-status-error"
1354
+ },
1355
+ warning: {
1356
+ solid: "bg-status-warning text-white",
1357
+ subtle: "bg-status-warning-subtle text-status-warning",
1358
+ outline: "border border-status-warning text-status-warning"
1359
+ },
1360
+ info: {
1361
+ solid: "bg-status-info text-white",
1362
+ subtle: "bg-status-info-subtle text-status-info",
1363
+ outline: "border border-status-info text-status-info"
1364
+ }
1365
+ };
1366
+ var sizeStyles8 = {
1367
+ sm: { container: "px-2 py-0.5 rounded", text: "text-xs", deleteButton: "ml-1 -mr-0.5" },
1368
+ md: { container: "px-3 py-1 rounded-md", text: "text-sm", deleteButton: "ml-1.5 -mr-1" },
1369
+ lg: { container: "px-4 py-1.5 rounded-md", text: "text-base", deleteButton: "ml-2 -mr-1" }
1370
+ };
1371
+ function Chip({
1372
+ variant = "subtle",
1373
+ color = "default",
1374
+ size = "md",
1375
+ leftElement,
1376
+ onDelete,
1377
+ onPress,
1378
+ isDisabled = false,
1379
+ className,
1380
+ children,
1381
+ ...props
1382
+ }) {
1383
+ const sizes = sizeStyles8[size];
1384
+ const isClickable = !!onPress;
1385
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1386
+ leftElement && /* @__PURE__ */ jsx(View, { className: "mr-1.5", children: leftElement }),
1387
+ /* @__PURE__ */ jsx(Text, { className: cn("font-medium", sizes.text), children }),
1388
+ onDelete && /* @__PURE__ */ jsx(
1389
+ Pressable,
1390
+ {
1391
+ onPress: (e) => {
1392
+ e.stopPropagation?.();
1393
+ onDelete();
1394
+ },
1395
+ accessibilityRole: "button",
1396
+ accessibilityLabel: "Remove",
1397
+ disabled: isDisabled,
1398
+ className: cn(
1399
+ sizes.deleteButton,
1400
+ "rounded-full p-0.5 web:hover:bg-black/10 active:bg-black/20"
1401
+ ),
1402
+ children: /* @__PURE__ */ jsx(Text, { className: "text-xs leading-none", children: "\xD7" })
1403
+ }
1404
+ )
1405
+ ] });
1406
+ const baseClassName = cn(
1407
+ "flex-row items-center",
1408
+ sizes.container,
1409
+ colorStyles[color][variant],
1410
+ isClickable && "web:cursor-pointer web:hover:opacity-80 active:opacity-70",
1411
+ isDisabled && "opacity-50 cursor-not-allowed",
1412
+ className
1413
+ );
1414
+ if (isClickable) {
1415
+ return /* @__PURE__ */ jsx(
1416
+ Pressable,
1417
+ {
1418
+ onPress,
1419
+ disabled: isDisabled,
1420
+ accessibilityRole: "button",
1421
+ className: baseClassName,
1422
+ ...props,
1423
+ children: content
1424
+ }
1425
+ );
1426
+ }
1427
+ return /* @__PURE__ */ jsx(View, { className: baseClassName, ...props, children: content });
1428
+ }
1429
+ var colorStyles2 = {
1430
+ default: "text-text-link",
1431
+ primary: "text-brand-primary",
1432
+ secondary: "text-brand-secondary",
1433
+ inherit: ""
1434
+ };
1435
+ var underlineStyles = {
1436
+ always: "underline",
1437
+ hover: "no-underline web:hover:underline",
1438
+ none: "no-underline"
1439
+ };
1440
+ function Link({
1441
+ href,
1442
+ underline = "hover",
1443
+ color = "default",
1444
+ isExternal = false,
1445
+ onPress,
1446
+ isDisabled = false,
1447
+ className,
1448
+ children,
1449
+ ...props
1450
+ }) {
1451
+ const handlePress = () => {
1452
+ if (isDisabled) return;
1453
+ onPress?.();
1454
+ };
1455
+ return /* @__PURE__ */ jsx(
1456
+ Pressable,
1457
+ {
1458
+ onPress: handlePress,
1459
+ disabled: isDisabled,
1460
+ accessibilityRole: "link",
1461
+ accessibilityHint: isExternal ? "Opens in new window" : void 0,
1462
+ children: /* @__PURE__ */ jsxs(
1463
+ Text,
1464
+ {
1465
+ className: cn(
1466
+ "font-medium",
1467
+ colorStyles2[color],
1468
+ underlineStyles[underline],
1469
+ isDisabled && "opacity-50 cursor-not-allowed",
1470
+ "web:cursor-pointer active:opacity-70",
1471
+ className
1472
+ ),
1473
+ ...props,
1474
+ children: [
1475
+ children,
1476
+ isExternal && " \u2197"
1477
+ ]
1478
+ }
1479
+ )
1480
+ }
1481
+ );
1482
+ }
1483
+ function Tooltip({
1484
+ label,
1485
+ children,
1486
+ placement = "top",
1487
+ openDelay = 0,
1488
+ closeDelay = 0,
1489
+ hasArrow = true,
1490
+ isDisabled = false,
1491
+ className,
1492
+ ...props
1493
+ }) {
1494
+ const [isVisible, setIsVisible] = useState(false);
1495
+ const openTimeoutRef = useRef(null);
1496
+ const closeTimeoutRef = useRef(null);
1497
+ const clearTimeouts = () => {
1498
+ if (openTimeoutRef.current) clearTimeout(openTimeoutRef.current);
1499
+ if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
1500
+ };
1501
+ const show = () => {
1502
+ if (isDisabled) return;
1503
+ clearTimeouts();
1504
+ if (openDelay > 0) {
1505
+ openTimeoutRef.current = setTimeout(() => setIsVisible(true), openDelay);
1506
+ } else {
1507
+ setIsVisible(true);
1508
+ }
1509
+ };
1510
+ const hide = () => {
1511
+ clearTimeouts();
1512
+ if (closeDelay > 0) {
1513
+ closeTimeoutRef.current = setTimeout(() => setIsVisible(false), closeDelay);
1514
+ } else {
1515
+ setIsVisible(false);
1516
+ }
1517
+ };
1518
+ const arrowStyles2 = {
1519
+ top: "bottom-0 left-1/2 -translate-x-1/2 translate-y-full border-l-transparent border-r-transparent border-b-transparent border-t-neutral-800",
1520
+ "top-start": "bottom-0 left-4 translate-y-full border-l-transparent border-r-transparent border-b-transparent border-t-neutral-800",
1521
+ "top-end": "bottom-0 right-4 translate-y-full border-l-transparent border-r-transparent border-b-transparent border-t-neutral-800",
1522
+ bottom: "top-0 left-1/2 -translate-x-1/2 -translate-y-full border-l-transparent border-r-transparent border-t-transparent border-b-neutral-800",
1523
+ "bottom-start": "top-0 left-4 -translate-y-full border-l-transparent border-r-transparent border-t-transparent border-b-neutral-800",
1524
+ "bottom-end": "top-0 right-4 -translate-y-full border-l-transparent border-r-transparent border-t-transparent border-b-neutral-800",
1525
+ left: "right-0 top-1/2 translate-x-full -translate-y-1/2 border-t-transparent border-b-transparent border-r-transparent border-l-neutral-800",
1526
+ right: "left-0 top-1/2 -translate-x-full -translate-y-1/2 border-t-transparent border-b-transparent border-l-transparent border-r-neutral-800"
1527
+ };
1528
+ const tooltipPositionStyles = {
1529
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
1530
+ "top-start": "bottom-full left-0 mb-2",
1531
+ "top-end": "bottom-full right-0 mb-2",
1532
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
1533
+ "bottom-start": "top-full left-0 mt-2",
1534
+ "bottom-end": "top-full right-0 mt-2",
1535
+ left: "right-full top-1/2 -translate-y-1/2 mr-2",
1536
+ right: "left-full top-1/2 -translate-y-1/2 ml-2"
1537
+ };
1538
+ return /* @__PURE__ */ jsxs(View, { className: "relative", ...props, children: [
1539
+ /* @__PURE__ */ jsx(
1540
+ Pressable,
1541
+ {
1542
+ onHoverIn: show,
1543
+ onHoverOut: hide,
1544
+ onLongPress: show,
1545
+ onPressOut: hide,
1546
+ delayLongPress: 500,
1547
+ children
1548
+ }
1549
+ ),
1550
+ isVisible && /* @__PURE__ */ jsx(
1551
+ View,
1552
+ {
1553
+ className: cn(
1554
+ "absolute z-50",
1555
+ tooltipPositionStyles[placement],
1556
+ className
1557
+ ),
1558
+ pointerEvents: "none",
1559
+ children: /* @__PURE__ */ jsxs(View, { className: "bg-neutral-800 px-3 py-2 rounded-md shadow-lg max-w-xs", children: [
1560
+ /* @__PURE__ */ jsx(Text, { className: "text-white text-sm", children: label }),
1561
+ hasArrow && /* @__PURE__ */ jsx(
1562
+ View,
1563
+ {
1564
+ className: cn(
1565
+ "absolute w-0 h-0 border-4",
1566
+ arrowStyles2[placement]
1567
+ )
1568
+ }
1569
+ )
1570
+ ] })
1571
+ }
1572
+ )
1573
+ ] });
1574
+ }
1575
+ var CollapseContext = createContext({
1576
+ isOpen: false,
1577
+ toggle: () => {
1578
+ }
1579
+ });
1580
+ function Collapse({
1581
+ defaultIsOpen = false,
1582
+ isOpen: controlledIsOpen,
1583
+ onToggle,
1584
+ className,
1585
+ children,
1586
+ ...props
1587
+ }) {
1588
+ const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen);
1589
+ const isOpen = controlledIsOpen ?? internalIsOpen;
1590
+ const toggle = () => {
1591
+ const newState = !isOpen;
1592
+ if (controlledIsOpen === void 0) {
1593
+ setInternalIsOpen(newState);
1594
+ }
1595
+ onToggle?.(newState);
1596
+ };
1597
+ return /* @__PURE__ */ jsx(CollapseContext.Provider, { value: { isOpen, toggle }, children: /* @__PURE__ */ jsx(View, { className: cn("w-full", className), ...props, children }) });
1598
+ }
1599
+ function CollapseButton({ children, className }) {
1600
+ const { isOpen, toggle } = useContext(CollapseContext);
1601
+ return /* @__PURE__ */ jsxs(
1602
+ Pressable,
1603
+ {
1604
+ onPress: toggle,
1605
+ accessibilityRole: "button",
1606
+ accessibilityState: { expanded: isOpen },
1607
+ className: cn(
1608
+ "flex-row items-center justify-between py-3 px-4",
1609
+ "web:hover:bg-interactive-hover active:bg-interactive-active rounded-lg",
1610
+ className
1611
+ ),
1612
+ children: [
1613
+ children,
1614
+ /* @__PURE__ */ jsx(Text, { className: cn("text-text-secondary transition-transform", isOpen && "rotate-180"), children: "\u25BC" })
1615
+ ]
1616
+ }
1617
+ );
1618
+ }
1619
+ function CollapseContent({ children, className }) {
1620
+ const { isOpen } = useContext(CollapseContext);
1621
+ if (!isOpen) return null;
1622
+ return /* @__PURE__ */ jsx(View, { className: cn("overflow-hidden", className), children });
1623
+ }
1624
+ var AccordionContext = createContext({
1625
+ openIndices: /* @__PURE__ */ new Set(),
1626
+ toggleIndex: () => {
1627
+ },
1628
+ allowMultiple: false
1629
+ });
1630
+ function Accordion({
1631
+ allowMultiple = false,
1632
+ defaultIndex = [],
1633
+ className,
1634
+ children,
1635
+ ...props
1636
+ }) {
1637
+ const [openIndices, setOpenIndices] = useState(new Set(defaultIndex));
1638
+ const toggleIndex = (index) => {
1639
+ setOpenIndices((prev) => {
1640
+ const newSet = new Set(prev);
1641
+ if (newSet.has(index)) {
1642
+ newSet.delete(index);
1643
+ } else {
1644
+ if (!allowMultiple) {
1645
+ newSet.clear();
1646
+ }
1647
+ newSet.add(index);
1648
+ }
1649
+ return newSet;
1650
+ });
1651
+ };
1652
+ return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { openIndices, toggleIndex, allowMultiple }, children: /* @__PURE__ */ jsx(View, { className: cn("w-full divide-y divide-border-default", className), ...props, children: React24.Children.map(children, (child, index) => {
1653
+ if (React24.isValidElement(child)) {
1654
+ return React24.cloneElement(child, { index });
1655
+ }
1656
+ return child;
1657
+ }) }) });
1658
+ }
1659
+ function AccordionItem({ index = 0, children, className }) {
1660
+ const { openIndices, toggleIndex } = useContext(AccordionContext);
1661
+ const isOpen = openIndices.has(index);
1662
+ return /* @__PURE__ */ jsx(View, { className, children: React24.Children.map(children, (child) => {
1663
+ if (React24.isValidElement(child)) {
1664
+ return React24.cloneElement(child, {
1665
+ isOpen,
1666
+ onToggle: () => toggleIndex(index)
1667
+ });
1668
+ }
1669
+ return child;
1670
+ }) });
1671
+ }
1672
+ function AccordionButton({
1673
+ isOpen = false,
1674
+ onToggle,
1675
+ children,
1676
+ className
1677
+ }) {
1678
+ return /* @__PURE__ */ jsxs(
1679
+ Pressable,
1680
+ {
1681
+ onPress: onToggle,
1682
+ accessibilityRole: "button",
1683
+ accessibilityState: { expanded: isOpen },
1684
+ className: cn(
1685
+ "flex-row items-center justify-between py-4 px-1",
1686
+ "web:hover:bg-interactive-hover active:bg-interactive-active",
1687
+ className
1688
+ ),
1689
+ children: [
1690
+ /* @__PURE__ */ jsx(Text, { className: "text-text-primary font-medium", children }),
1691
+ /* @__PURE__ */ jsx(Text, { className: cn("text-text-secondary transition-transform", isOpen && "rotate-180"), children: "\u25BC" })
1692
+ ]
1693
+ }
1694
+ );
1695
+ }
1696
+ function AccordionPanel({ isOpen = false, children, className }) {
1697
+ if (!isOpen) return null;
1698
+ return /* @__PURE__ */ jsx(View, { className: cn("pb-4 px-1", className), children });
1699
+ }
1700
+ function Breadcrumbs({
1701
+ separator = "/",
1702
+ maxItems,
1703
+ className,
1704
+ children,
1705
+ ...props
1706
+ }) {
1707
+ const items = React24.Children.toArray(children);
1708
+ let displayItems = items;
1709
+ if (maxItems && items.length > maxItems) {
1710
+ const firstItem = items[0];
1711
+ const lastItems = items.slice(-Math.floor(maxItems / 2));
1712
+ displayItems = [
1713
+ firstItem,
1714
+ /* @__PURE__ */ jsx(BreadcrumbEllipsis, {}, "ellipsis"),
1715
+ ...lastItems
1716
+ ];
1717
+ }
1718
+ return /* @__PURE__ */ jsx(
1719
+ View,
1720
+ {
1721
+ accessibilityRole: "none",
1722
+ className: cn("flex-row items-center flex-wrap", className),
1723
+ ...props,
1724
+ children: displayItems.map((child, index) => /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", children: [
1725
+ child,
1726
+ index < displayItems.length - 1 && /* @__PURE__ */ jsx(Text, { className: "mx-2 text-text-tertiary text-sm", children: separator })
1727
+ ] }, index))
1728
+ }
1729
+ );
1730
+ }
1731
+ function BreadcrumbItem({
1732
+ href,
1733
+ isCurrentPage = false,
1734
+ onPress,
1735
+ className,
1736
+ children
1737
+ }) {
1738
+ if (isCurrentPage) {
1739
+ return /* @__PURE__ */ jsx(
1740
+ Text,
1741
+ {
1742
+ accessibilityRole: "text",
1743
+ "aria-current": "page",
1744
+ className: cn("text-sm font-medium text-text-primary", className),
1745
+ children
1746
+ }
1747
+ );
1748
+ }
1749
+ return /* @__PURE__ */ jsx(
1750
+ Pressable,
1751
+ {
1752
+ onPress,
1753
+ accessibilityRole: "link",
1754
+ accessibilityHint: href,
1755
+ children: /* @__PURE__ */ jsx(
1756
+ Text,
1757
+ {
1758
+ className: cn(
1759
+ "text-sm text-text-secondary",
1760
+ "web:hover:text-text-primary web:hover:underline",
1761
+ "active:opacity-70",
1762
+ className
1763
+ ),
1764
+ children
1765
+ }
1766
+ )
1767
+ }
1768
+ );
1769
+ }
1770
+ function BreadcrumbEllipsis() {
1771
+ return /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-tertiary", children: "..." });
1772
+ }
1773
+ var PopoverContext = createContext({
1774
+ isOpen: false,
1775
+ setIsOpen: () => {
1776
+ },
1777
+ placement: "bottom"
1778
+ });
1779
+ function Popover({
1780
+ placement = "bottom",
1781
+ isOpen: controlledIsOpen,
1782
+ onOpenChange,
1783
+ closeOnClickOutside = true,
1784
+ className,
1785
+ children,
1786
+ ...props
1787
+ }) {
1788
+ const [internalIsOpen, setInternalIsOpen] = useState(false);
1789
+ const isOpen = controlledIsOpen ?? internalIsOpen;
1790
+ const setIsOpen = (open) => {
1791
+ if (controlledIsOpen === void 0) {
1792
+ setInternalIsOpen(open);
1793
+ }
1794
+ onOpenChange?.(open);
1795
+ };
1796
+ return /* @__PURE__ */ jsx(PopoverContext.Provider, { value: { isOpen, setIsOpen, placement }, children: /* @__PURE__ */ jsx(View, { className: cn("relative", className), ...props, children }) });
1797
+ }
1798
+ function PopoverTrigger({ children, className }) {
1799
+ const { isOpen, setIsOpen } = useContext(PopoverContext);
1800
+ return /* @__PURE__ */ jsx(
1801
+ Pressable,
1802
+ {
1803
+ onPress: () => setIsOpen(!isOpen),
1804
+ accessibilityRole: "button",
1805
+ accessibilityState: { expanded: isOpen },
1806
+ className,
1807
+ children
1808
+ }
1809
+ );
1810
+ }
1811
+ function PopoverContent({ children, className }) {
1812
+ const { isOpen, setIsOpen, placement } = useContext(PopoverContext);
1813
+ if (!isOpen) return null;
1814
+ const placementStyles3 = {
1815
+ top: "bottom-full left-0 mb-2",
1816
+ bottom: "top-full left-0 mt-2",
1817
+ left: "right-full top-0 mr-2",
1818
+ right: "left-full top-0 ml-2"
1819
+ };
1820
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1821
+ /* @__PURE__ */ jsx(
1822
+ Pressable,
1823
+ {
1824
+ onPress: () => setIsOpen(false),
1825
+ className: "fixed inset-0 z-40",
1826
+ style: { position: "absolute" }
1827
+ }
1828
+ ),
1829
+ /* @__PURE__ */ jsx(
1830
+ View,
1831
+ {
1832
+ className: cn(
1833
+ "absolute z-50 min-w-[200px]",
1834
+ "bg-surface-elevated rounded-lg shadow-lg border border-border-default",
1835
+ "p-4",
1836
+ placementStyles3[placement],
1837
+ className
1838
+ ),
1839
+ children
1840
+ }
1841
+ )
1842
+ ] });
1843
+ }
1844
+ function PopoverCloseButton({ children, className }) {
1845
+ const { setIsOpen } = useContext(PopoverContext);
1846
+ return /* @__PURE__ */ jsx(
1847
+ Pressable,
1848
+ {
1849
+ onPress: () => setIsOpen(false),
1850
+ accessibilityRole: "button",
1851
+ accessibilityLabel: "Close popover",
1852
+ className: cn("p-1", className),
1853
+ children
1854
+ }
1855
+ );
1856
+ }
1857
+ var MenuContext = createContext({
1858
+ isOpen: false,
1859
+ setIsOpen: () => {
1860
+ },
1861
+ closeMenu: () => {
1862
+ }
1863
+ });
1864
+ function Menu({
1865
+ isOpen: controlledIsOpen,
1866
+ onOpenChange,
1867
+ className,
1868
+ children,
1869
+ ...props
1870
+ }) {
1871
+ const [internalIsOpen, setInternalIsOpen] = useState(false);
1872
+ const isOpen = controlledIsOpen ?? internalIsOpen;
1873
+ const setIsOpen = (open) => {
1874
+ if (controlledIsOpen === void 0) {
1875
+ setInternalIsOpen(open);
1876
+ }
1877
+ onOpenChange?.(open);
1878
+ };
1879
+ const closeMenu = () => setIsOpen(false);
1880
+ return /* @__PURE__ */ jsx(MenuContext.Provider, { value: { isOpen, setIsOpen, closeMenu }, children: /* @__PURE__ */ jsx(View, { className: cn("relative", className), ...props, children }) });
1881
+ }
1882
+ function MenuTrigger({ children, className }) {
1883
+ const { isOpen, setIsOpen } = useContext(MenuContext);
1884
+ return /* @__PURE__ */ jsx(
1885
+ Pressable,
1886
+ {
1887
+ onPress: () => setIsOpen(!isOpen),
1888
+ accessibilityRole: "button",
1889
+ accessibilityState: { expanded: isOpen },
1890
+ className,
1891
+ children
1892
+ }
1893
+ );
1894
+ }
1895
+ function MenuList({ children, className }) {
1896
+ const { isOpen, setIsOpen } = useContext(MenuContext);
1897
+ if (!isOpen) return null;
1898
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1899
+ /* @__PURE__ */ jsx(
1900
+ Pressable,
1901
+ {
1902
+ onPress: () => setIsOpen(false),
1903
+ className: "fixed inset-0 z-40",
1904
+ style: { position: "absolute" }
1905
+ }
1906
+ ),
1907
+ /* @__PURE__ */ jsx(
1908
+ View,
1909
+ {
1910
+ className: cn(
1911
+ "absolute z-50 top-full left-0 mt-1 min-w-[160px]",
1912
+ "bg-surface-elevated rounded-lg shadow-lg border border-border-default",
1913
+ "py-1 overflow-hidden",
1914
+ className
1915
+ ),
1916
+ accessibilityRole: "menu",
1917
+ children
1918
+ }
1919
+ )
1920
+ ] });
1921
+ }
1922
+ function MenuItem({
1923
+ onPress,
1924
+ isDisabled = false,
1925
+ isDestructive = false,
1926
+ icon,
1927
+ className,
1928
+ children
1929
+ }) {
1930
+ const { closeMenu } = useContext(MenuContext);
1931
+ const handlePress = () => {
1932
+ if (isDisabled) return;
1933
+ onPress?.();
1934
+ closeMenu();
1935
+ };
1936
+ return /* @__PURE__ */ jsxs(
1937
+ Pressable,
1938
+ {
1939
+ onPress: handlePress,
1940
+ disabled: isDisabled,
1941
+ accessibilityRole: "menuitem",
1942
+ accessibilityState: { disabled: isDisabled },
1943
+ className: cn(
1944
+ "flex-row items-center px-4 py-2",
1945
+ "web:hover:bg-interactive-hover active:bg-interactive-active",
1946
+ isDisabled && "opacity-50 cursor-not-allowed",
1947
+ className
1948
+ ),
1949
+ children: [
1950
+ icon && /* @__PURE__ */ jsx(View, { className: "mr-3", children: icon }),
1951
+ /* @__PURE__ */ jsx(
1952
+ Text,
1953
+ {
1954
+ className: cn(
1955
+ "text-sm",
1956
+ isDestructive ? "text-status-error" : "text-text-primary"
1957
+ ),
1958
+ children
1959
+ }
1960
+ )
1961
+ ]
1962
+ }
1963
+ );
1964
+ }
1965
+ function MenuDivider({ className }) {
1966
+ return /* @__PURE__ */ jsx(View, { className: cn("h-px bg-border-default my-1", className) });
1967
+ }
1968
+ function MenuGroup({ label, children, className }) {
1969
+ return /* @__PURE__ */ jsxs(View, { className, children: [
1970
+ label && /* @__PURE__ */ jsx(Text, { className: "px-4 py-2 text-xs font-semibold text-text-secondary uppercase", children: label }),
1971
+ children
1972
+ ] });
1973
+ }
1974
+ var SelectContext = createContext({
1975
+ value: null,
1976
+ isMulti: false,
1977
+ isOpen: false,
1978
+ setIsOpen: () => {
1979
+ },
1980
+ selectValue: () => {
1981
+ },
1982
+ isSelected: () => false
1983
+ });
1984
+ function Select({
1985
+ value,
1986
+ values = [],
1987
+ onChange,
1988
+ onChangeMulti,
1989
+ isMulti = false,
1990
+ placeholder = "Select...",
1991
+ isDisabled = false,
1992
+ isInvalid = false,
1993
+ options,
1994
+ className,
1995
+ ...props
1996
+ }) {
1997
+ const [isOpen, setIsOpen] = useState(false);
1998
+ const selectValue = (val) => {
1999
+ if (isMulti) {
2000
+ const newValues = values.includes(val) ? values.filter((v) => v !== val) : [...values, val];
2001
+ onChangeMulti?.(newValues);
2002
+ } else {
2003
+ onChange?.(val);
2004
+ setIsOpen(false);
2005
+ }
2006
+ };
2007
+ const isSelected = (val) => {
2008
+ if (isMulti) {
2009
+ return values.includes(val);
2010
+ }
2011
+ return value === val;
2012
+ };
2013
+ const getDisplayValue = () => {
2014
+ if (isMulti) {
2015
+ if (values.length === 0) return placeholder;
2016
+ if (values.length === 1) {
2017
+ return options.find((o) => o.value === values[0])?.label || placeholder;
2018
+ }
2019
+ return `${values.length} selected`;
2020
+ }
2021
+ if (value === null || value === void 0) return placeholder;
2022
+ return options.find((o) => o.value === value)?.label || placeholder;
2023
+ };
2024
+ const clearValue = () => {
2025
+ if (isMulti) {
2026
+ onChangeMulti?.([]);
2027
+ } else {
2028
+ onChange?.(null);
2029
+ }
2030
+ };
2031
+ const hasValue = isMulti ? values.length > 0 : value !== null && value !== void 0;
2032
+ return /* @__PURE__ */ jsx(SelectContext.Provider, { value: { value, isMulti, isOpen, setIsOpen, selectValue, isSelected }, children: /* @__PURE__ */ jsxs(View, { className: cn("relative w-full", className), ...props, children: [
2033
+ /* @__PURE__ */ jsxs(
2034
+ Pressable,
2035
+ {
2036
+ onPress: () => !isDisabled && setIsOpen(!isOpen),
2037
+ disabled: isDisabled,
2038
+ accessibilityRole: "combobox",
2039
+ accessibilityState: { expanded: isOpen, disabled: isDisabled },
2040
+ className: cn(
2041
+ "flex-row items-center justify-between px-4 py-2.5 rounded-md border",
2042
+ "bg-surface-base",
2043
+ isInvalid ? "border-border-input-error" : "border-border-input",
2044
+ !isDisabled && !isInvalid && "web:hover:border-border-input-hover",
2045
+ isOpen && "border-border-input-focus",
2046
+ isDisabled && "opacity-50 cursor-not-allowed"
2047
+ ),
2048
+ children: [
2049
+ /* @__PURE__ */ jsx(
2050
+ Text,
2051
+ {
2052
+ className: cn(
2053
+ "flex-1",
2054
+ hasValue ? "text-text-primary" : "text-text-tertiary"
2055
+ ),
2056
+ children: getDisplayValue()
2057
+ }
2058
+ ),
2059
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center gap-2", children: [
2060
+ hasValue && /* @__PURE__ */ jsx(
2061
+ Pressable,
2062
+ {
2063
+ onPress: (e) => {
2064
+ e.stopPropagation?.();
2065
+ clearValue();
2066
+ },
2067
+ className: "p-1",
2068
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary text-xs", children: "\xD7" })
2069
+ }
2070
+ ),
2071
+ /* @__PURE__ */ jsx(Text, { className: cn("text-text-secondary", isOpen && "rotate-180"), children: "\u25BC" })
2072
+ ] })
2073
+ ]
2074
+ }
2075
+ ),
2076
+ isOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
2077
+ /* @__PURE__ */ jsx(
2078
+ Pressable,
2079
+ {
2080
+ onPress: () => setIsOpen(false),
2081
+ className: "fixed inset-0 z-40",
2082
+ style: { position: "absolute" }
2083
+ }
2084
+ ),
2085
+ /* @__PURE__ */ jsx(
2086
+ View,
2087
+ {
2088
+ className: cn(
2089
+ "absolute z-50 top-full left-0 right-0 mt-1",
2090
+ "bg-surface-elevated rounded-md shadow-lg border border-border-default",
2091
+ "max-h-60 overflow-hidden"
2092
+ ),
2093
+ children: /* @__PURE__ */ jsx(ScrollView, { className: "py-1", children: options.map((option) => /* @__PURE__ */ jsx(SelectOption, { option }, option.value)) })
2094
+ }
2095
+ )
2096
+ ] })
2097
+ ] }) });
2098
+ }
2099
+ function SelectOption({ option }) {
2100
+ const { selectValue, isSelected, isMulti } = useContext(SelectContext);
2101
+ const selected = isSelected(option.value);
2102
+ return /* @__PURE__ */ jsxs(
2103
+ Pressable,
2104
+ {
2105
+ onPress: () => !option.isDisabled && selectValue(option.value),
2106
+ disabled: option.isDisabled,
2107
+ accessibilityRole: isMulti ? "checkbox" : "option",
2108
+ accessibilityState: { selected, disabled: option.isDisabled },
2109
+ className: cn(
2110
+ "flex-row items-center px-4 py-2",
2111
+ "web:hover:bg-interactive-hover active:bg-interactive-active",
2112
+ selected && "bg-interactive-selected",
2113
+ option.isDisabled && "opacity-50 cursor-not-allowed"
2114
+ ),
2115
+ children: [
2116
+ isMulti && /* @__PURE__ */ jsx(
2117
+ View,
2118
+ {
2119
+ className: cn(
2120
+ "w-4 h-4 mr-3 rounded border",
2121
+ selected ? "bg-brand-primary border-brand-primary" : "border-border-strong"
2122
+ ),
2123
+ children: selected && /* @__PURE__ */ jsx(Text, { className: "text-white text-xs text-center", children: "\u2713" })
2124
+ }
2125
+ ),
2126
+ /* @__PURE__ */ jsx(Text, { className: cn("text-sm", selected && !isMulti ? "text-brand-primary font-medium" : "text-text-primary"), children: option.label })
2127
+ ]
2128
+ }
2129
+ );
2130
+ }
2131
+ var ToolbarButtonContext = createContext({
2132
+ isOpen: false,
2133
+ setIsOpen: () => {
2134
+ }
2135
+ });
2136
+ var BUTTON_BG = "#3C3C3C";
2137
+ var MENU_BG = "#2C2C2C";
2138
+ var hoverColors = getHoverColors(BUTTON_BG, "medium");
2139
+ var sizeStyles9 = {
2140
+ sm: "px-2 py-1 min-h-[26px]",
2141
+ md: "px-2.5 py-1 min-h-[30px]",
2142
+ lg: "px-3 py-1.5 min-h-[36px]"
2143
+ };
2144
+ var textSizeStyles2 = {
2145
+ sm: "text-xs",
2146
+ md: "text-sm",
2147
+ lg: "text-base"
2148
+ };
2149
+ function ToolbarButton({
2150
+ label,
2151
+ icon,
2152
+ isActive,
2153
+ isDisabled = false,
2154
+ size = "md",
2155
+ variant = "neumorphic",
2156
+ tooltip,
2157
+ showLabel = true,
2158
+ onPress,
2159
+ menuContent,
2160
+ className,
2161
+ children,
2162
+ ...props
2163
+ }) {
2164
+ const [isOpen, setIsOpen] = useState(false);
2165
+ const [isHovered, setIsHovered] = useState(false);
2166
+ const handlePress = useCallback(() => {
2167
+ if (isDisabled) return;
2168
+ if (menuContent) {
2169
+ setIsOpen((prev) => !prev);
2170
+ }
2171
+ onPress?.();
2172
+ }, [isDisabled, menuContent, onPress]);
2173
+ const handleClose = useCallback(() => {
2174
+ setIsOpen(false);
2175
+ }, []);
2176
+ const selected = isActive === void 0 ? isOpen : isActive;
2177
+ const showActive = isActive !== false;
2178
+ const getIconColor = () => {
2179
+ if (isActive === true) return "#FF7900";
2180
+ return showActive ? "#FFFFFF" : "#D1D1D1";
2181
+ };
2182
+ const getNeumorphicStyle = () => {
2183
+ if (isDisabled) {
2184
+ return styles.disabledBg;
2185
+ }
2186
+ const shadows = neumorphicShadows.charcoal;
2187
+ if (showActive) {
2188
+ return {
2189
+ backgroundColor: isHovered ? hoverColors.pressed : BUTTON_BG,
2190
+ ...isHovered ? shadows.pressedHover.subtle : shadows.pressed.subtle
2191
+ };
2192
+ } else {
2193
+ return {
2194
+ backgroundColor: isHovered ? hoverColors.raised : BUTTON_BG,
2195
+ ...isHovered ? shadows.raisedHover.subtle : shadows.raised.subtle
2196
+ };
2197
+ }
2198
+ };
2199
+ return /* @__PURE__ */ jsx(ToolbarButtonContext.Provider, { value: { isOpen, setIsOpen }, children: /* @__PURE__ */ jsxs(View, { className: "relative", ...props, children: [
2200
+ /* @__PURE__ */ jsxs(
2201
+ Pressable,
2202
+ {
2203
+ onPress: handlePress,
2204
+ onHoverIn: () => setIsHovered(true),
2205
+ onHoverOut: () => setIsHovered(false),
2206
+ disabled: isDisabled,
2207
+ accessibilityRole: "button",
2208
+ accessibilityState: { selected, disabled: isDisabled },
2209
+ accessibilityLabel: label,
2210
+ accessibilityHint: tooltip,
2211
+ className: cn(
2212
+ // Base styles
2213
+ "flex-row items-center justify-center rounded",
2214
+ "web:transition-all web:duration-150 web:cursor-pointer",
2215
+ // Size
2216
+ sizeStyles9[size],
2217
+ // Disabled
2218
+ isDisabled && "opacity-40 web:cursor-default web:pointer-events-none",
2219
+ className
2220
+ ),
2221
+ style: [
2222
+ variant === "neumorphic" && getNeumorphicStyle(),
2223
+ variant === "default" && {
2224
+ backgroundColor: showActive ? BUTTON_BG : "#6E6E6E"
2225
+ }
2226
+ ],
2227
+ children: [
2228
+ icon && /* @__PURE__ */ jsx(View, { className: "w-5 h-5 items-center justify-center", children: React24.isValidElement(icon) ? React24.cloneElement(icon, {
2229
+ size: 20,
2230
+ width: 20,
2231
+ height: 20,
2232
+ color: getIconColor(),
2233
+ style: {
2234
+ color: getIconColor(),
2235
+ width: 20,
2236
+ height: 20
2237
+ }
2238
+ }) : icon }),
2239
+ showLabel && /* @__PURE__ */ jsx(
2240
+ Text,
2241
+ {
2242
+ className: cn(
2243
+ "font-bold",
2244
+ textSizeStyles2[size],
2245
+ icon && "ml-2",
2246
+ showActive ? "text-white" : "text-[#D1D1D1]"
2247
+ ),
2248
+ numberOfLines: 1,
2249
+ children: label
2250
+ }
2251
+ )
2252
+ ]
2253
+ }
2254
+ ),
2255
+ menuContent && isOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
2256
+ /* @__PURE__ */ jsx(
2257
+ Pressable,
2258
+ {
2259
+ onPress: handleClose,
2260
+ style: StyleSheet.absoluteFill,
2261
+ className: "z-40"
2262
+ }
2263
+ ),
2264
+ /* @__PURE__ */ jsx(
2265
+ View,
2266
+ {
2267
+ className: cn(
2268
+ "absolute z-50 top-full left-0 mt-1",
2269
+ "rounded-lg shadow-lg border border-border-default",
2270
+ "min-w-[150px] overflow-hidden",
2271
+ `bg-[${MENU_BG}]`
2272
+ ),
2273
+ children: menuContent
2274
+ }
2275
+ )
2276
+ ] })
2277
+ ] }) });
2278
+ }
2279
+ var styles = StyleSheet.create({
2280
+ // Disabled - flat gray background, no shadows
2281
+ disabledBg: {
2282
+ backgroundColor: "rgba(255, 255, 255, 0.12)",
2283
+ ...Platform.select({
2284
+ web: { boxShadow: "none" },
2285
+ default: { shadowOpacity: 0, elevation: 0 }
2286
+ })
2287
+ }
2288
+ });
2289
+ var gapStyles = {
2290
+ none: "gap-0",
2291
+ sm: "gap-1",
2292
+ md: "gap-2"
2293
+ };
2294
+ function ToolbarButtonGroup({
2295
+ orientation = "horizontal",
2296
+ gap = "sm",
2297
+ className,
2298
+ children,
2299
+ ...props
2300
+ }) {
2301
+ return /* @__PURE__ */ jsx(
2302
+ View,
2303
+ {
2304
+ className: cn(
2305
+ orientation === "horizontal" ? "flex-row" : "flex-col",
2306
+ gapStyles[gap],
2307
+ "items-center",
2308
+ className
2309
+ ),
2310
+ accessibilityRole: "toolbar",
2311
+ ...props,
2312
+ children
2313
+ }
2314
+ );
2315
+ }
2316
+ function useToolbarButton() {
2317
+ return useContext(ToolbarButtonContext);
2318
+ }
2319
+ var RadioGroupContext = createContext(null);
2320
+ var gapStyles2 = {
2321
+ sm: "gap-2",
2322
+ md: "gap-3",
2323
+ lg: "gap-4"
2324
+ };
2325
+ function RadioGroup({
2326
+ value,
2327
+ onChange,
2328
+ name,
2329
+ isDisabled = false,
2330
+ size = "md",
2331
+ color = "primary",
2332
+ orientation = "vertical",
2333
+ gap = "md",
2334
+ label,
2335
+ className,
2336
+ children,
2337
+ ...props
2338
+ }) {
2339
+ return /* @__PURE__ */ jsx(RadioGroupContext.Provider, { value: { value, onChange, name, isDisabled, size, color }, children: /* @__PURE__ */ jsxs(
2340
+ View,
2341
+ {
2342
+ className: cn(className),
2343
+ accessibilityRole: "radiogroup",
2344
+ accessibilityLabel: label,
2345
+ ...props,
2346
+ children: [
2347
+ label && /* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-text-primary mb-2", children: label }),
2348
+ /* @__PURE__ */ jsx(
2349
+ View,
2350
+ {
2351
+ className: cn(
2352
+ orientation === "horizontal" ? "flex-row flex-wrap" : "flex-col",
2353
+ gapStyles2[gap]
2354
+ ),
2355
+ children
2356
+ }
2357
+ )
2358
+ ]
2359
+ }
2360
+ ) });
2361
+ }
2362
+ var sizeConfig = {
2363
+ sm: { outer: "w-4 h-4", inner: "w-2 h-2", text: "text-sm" },
2364
+ md: { outer: "w-5 h-5", inner: "w-2.5 h-2.5", text: "text-base" },
2365
+ lg: { outer: "w-6 h-6", inner: "w-3 h-3", text: "text-lg" }
2366
+ };
2367
+ var colorStyles3 = {
2368
+ primary: { checked: "border-brand-primary bg-brand-primary", unchecked: "border-border-strong" },
2369
+ secondary: { checked: "border-brand-secondary bg-brand-secondary", unchecked: "border-border-strong" },
2370
+ success: { checked: "border-status-success bg-status-success", unchecked: "border-border-strong" },
2371
+ error: { checked: "border-status-error bg-status-error", unchecked: "border-border-strong" }
2372
+ };
2373
+ function Radio({
2374
+ value,
2375
+ isDisabled: radioDisabled,
2376
+ size: radioSize,
2377
+ color: radioColor,
2378
+ className,
2379
+ children,
2380
+ ...props
2381
+ }) {
2382
+ const context = useContext(RadioGroupContext);
2383
+ if (!context) {
2384
+ throw new Error("Radio must be used within a RadioGroup");
2385
+ }
2386
+ const { value: selectedValue, onChange, isDisabled: groupDisabled, size: groupSize, color: groupColor } = context;
2387
+ const isDisabled = radioDisabled ?? groupDisabled ?? false;
2388
+ const size = radioSize ?? groupSize ?? "md";
2389
+ const color = radioColor ?? groupColor ?? "primary";
2390
+ const isChecked = selectedValue === value;
2391
+ const { outer, inner, text } = sizeConfig[size];
2392
+ const { checked, unchecked } = colorStyles3[color];
2393
+ const handlePress = () => {
2394
+ if (!isDisabled) {
2395
+ onChange(value);
2396
+ }
2397
+ };
2398
+ return /* @__PURE__ */ jsxs(
2399
+ Pressable,
2400
+ {
2401
+ onPress: handlePress,
2402
+ disabled: isDisabled,
2403
+ accessibilityRole: "radio",
2404
+ accessibilityState: { checked: isChecked, disabled: isDisabled },
2405
+ className: cn(
2406
+ "flex-row items-center",
2407
+ isDisabled && "opacity-50",
2408
+ className
2409
+ ),
2410
+ ...props,
2411
+ children: [
2412
+ /* @__PURE__ */ jsx(
2413
+ View,
2414
+ {
2415
+ className: cn(
2416
+ "rounded-full border-2 items-center justify-center",
2417
+ "transition-colors duration-150",
2418
+ outer,
2419
+ isChecked ? checked : unchecked,
2420
+ !isDisabled && !isChecked && "web:hover:border-brand-primary"
2421
+ ),
2422
+ children: isChecked && /* @__PURE__ */ jsx(View, { className: cn("rounded-full bg-white", inner) })
2423
+ }
2424
+ ),
2425
+ children && /* @__PURE__ */ jsx(Text, { className: cn("ml-2 text-text-primary", text), children })
2426
+ ]
2427
+ }
2428
+ );
2429
+ }
2430
+ var sizeStyles10 = {
2431
+ left: {
2432
+ sm: "w-64",
2433
+ md: "w-80",
2434
+ lg: "w-96",
2435
+ xl: "w-[480px]",
2436
+ full: "w-full"
2437
+ },
2438
+ right: {
2439
+ sm: "w-64",
2440
+ md: "w-80",
2441
+ lg: "w-96",
2442
+ xl: "w-[480px]",
2443
+ full: "w-full"
2444
+ },
2445
+ top: {
2446
+ sm: "h-32",
2447
+ md: "h-48",
2448
+ lg: "h-64",
2449
+ xl: "h-96",
2450
+ full: "h-full"
2451
+ },
2452
+ bottom: {
2453
+ sm: "h-32",
2454
+ md: "h-48",
2455
+ lg: "h-64",
2456
+ xl: "h-96",
2457
+ full: "h-full"
2458
+ }
2459
+ };
2460
+ var placementStyles = {
2461
+ left: "left-0 top-0 bottom-0 h-full",
2462
+ right: "right-0 top-0 bottom-0 h-full",
2463
+ top: "top-0 left-0 right-0 w-full",
2464
+ bottom: "bottom-0 left-0 right-0 w-full"
2465
+ };
2466
+ function Drawer({
2467
+ isOpen,
2468
+ onClose,
2469
+ placement = "right",
2470
+ size = "md",
2471
+ closeOnOverlayClick = true,
2472
+ showCloseButton = true,
2473
+ title,
2474
+ className,
2475
+ children,
2476
+ ...props
2477
+ }) {
2478
+ if (!isOpen) return null;
2479
+ const handleOverlayPress = () => {
2480
+ if (closeOnOverlayClick) {
2481
+ onClose();
2482
+ }
2483
+ };
2484
+ return /* @__PURE__ */ jsx(
2485
+ Modal$1,
2486
+ {
2487
+ visible: isOpen,
2488
+ transparent: true,
2489
+ animationType: "fade",
2490
+ onRequestClose: onClose,
2491
+ children: /* @__PURE__ */ jsxs(View, { className: "flex-1", children: [
2492
+ /* @__PURE__ */ jsx(
2493
+ Pressable,
2494
+ {
2495
+ onPress: handleOverlayPress,
2496
+ className: "absolute inset-0 bg-black/50"
2497
+ }
2498
+ ),
2499
+ /* @__PURE__ */ jsxs(
2500
+ View,
2501
+ {
2502
+ className: cn(
2503
+ "absolute bg-surface-elevated shadow-2xl",
2504
+ placementStyles[placement],
2505
+ sizeStyles10[placement][size],
2506
+ className
2507
+ ),
2508
+ accessibilityRole: "dialog",
2509
+ ...props,
2510
+ children: [
2511
+ (title || showCloseButton) && /* @__PURE__ */ jsxs(View, { className: "flex-row items-center justify-between px-4 py-3 border-b border-border-default", children: [
2512
+ title && /* @__PURE__ */ jsx(Text, { className: "text-lg font-semibold text-text-primary", children: title }),
2513
+ showCloseButton && /* @__PURE__ */ jsx(
2514
+ Pressable,
2515
+ {
2516
+ onPress: onClose,
2517
+ className: "p-2 -m-2 rounded-full web:hover:bg-interactive-hover",
2518
+ accessibilityLabel: "Close drawer",
2519
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary text-xl", children: "\xD7" })
2520
+ }
2521
+ )
2522
+ ] }),
2523
+ /* @__PURE__ */ jsx(View, { className: "flex-1", children })
2524
+ ]
2525
+ }
2526
+ )
2527
+ ] })
2528
+ }
2529
+ );
2530
+ }
2531
+ function DrawerHeader({ className, children, ...props }) {
2532
+ return /* @__PURE__ */ jsx(
2533
+ View,
2534
+ {
2535
+ className: cn("px-4 py-3 border-b border-border-default", className),
2536
+ ...props,
2537
+ children
2538
+ }
2539
+ );
2540
+ }
2541
+ function DrawerBody({ scrollable = true, className, children, ...props }) {
2542
+ if (scrollable) {
2543
+ return /* @__PURE__ */ jsx(
2544
+ ScrollView,
2545
+ {
2546
+ className: cn("flex-1 p-4", className),
2547
+ ...props,
2548
+ children
2549
+ }
2550
+ );
2551
+ }
2552
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-1 p-4", className), ...props, children });
2553
+ }
2554
+ function DrawerFooter({ className, children, ...props }) {
2555
+ return /* @__PURE__ */ jsx(
2556
+ View,
2557
+ {
2558
+ className: cn(
2559
+ "flex-row items-center justify-end gap-3",
2560
+ "px-4 py-3 border-t border-border-default",
2561
+ className
2562
+ ),
2563
+ ...props,
2564
+ children
2565
+ }
2566
+ );
2567
+ }
2568
+ var colorVarMap = {
2569
+ primary: "var(--color-brand-primary)",
2570
+ secondary: "var(--color-brand-secondary)",
2571
+ success: "var(--color-status-success)",
2572
+ error: "var(--color-status-error)",
2573
+ warning: "var(--color-status-warning)",
2574
+ info: "var(--color-status-info)"
2575
+ };
2576
+ var sizeStyles11 = {
2577
+ sm: "h-1",
2578
+ md: "h-2",
2579
+ lg: "h-3"
2580
+ };
2581
+ var colorStyles4 = {
2582
+ primary: "bg-brand-primary",
2583
+ secondary: "bg-brand-secondary",
2584
+ success: "bg-status-success",
2585
+ error: "bg-status-error",
2586
+ warning: "bg-status-warning",
2587
+ info: "bg-status-info"
2588
+ };
2589
+ var trackColorStyles = {
2590
+ primary: "bg-brand-primary/20",
2591
+ secondary: "bg-brand-secondary/20",
2592
+ success: "bg-status-success/20",
2593
+ error: "bg-status-error/20",
2594
+ warning: "bg-status-warning/20",
2595
+ info: "bg-status-info/20"
2596
+ };
2597
+ function Progress({
2598
+ value = 0,
2599
+ max = 100,
2600
+ isIndeterminate = false,
2601
+ size = "md",
2602
+ color = "primary",
2603
+ showValue = false,
2604
+ formatValue = (v, m) => `${Math.round(v / m * 100)}%`,
2605
+ label,
2606
+ className,
2607
+ ...props
2608
+ }) {
2609
+ const percentage = Math.min(Math.max(value / max * 100, 0), 100);
2610
+ return /* @__PURE__ */ jsxs(View, { className: cn("w-full", className), ...props, children: [
2611
+ (label || showValue) && /* @__PURE__ */ jsxs(View, { className: "flex-row justify-between items-center mb-1", children: [
2612
+ label && /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-secondary", children: label }),
2613
+ showValue && !isIndeterminate && /* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-text-primary", children: formatValue(value, max) })
2614
+ ] }),
2615
+ /* @__PURE__ */ jsx(
2616
+ View,
2617
+ {
2618
+ className: cn(
2619
+ "w-full rounded-full overflow-hidden",
2620
+ trackColorStyles[color],
2621
+ sizeStyles11[size]
2622
+ ),
2623
+ accessibilityRole: "progressbar",
2624
+ accessibilityValue: {
2625
+ min: 0,
2626
+ max,
2627
+ now: isIndeterminate ? void 0 : value
2628
+ },
2629
+ children: /* @__PURE__ */ jsx(
2630
+ View,
2631
+ {
2632
+ className: cn(
2633
+ "h-full rounded-full",
2634
+ colorStyles4[color],
2635
+ isIndeterminate && "animate-pulse w-1/3"
2636
+ ),
2637
+ style: isIndeterminate ? void 0 : { width: `${percentage}%` }
2638
+ }
2639
+ )
2640
+ }
2641
+ )
2642
+ ] });
2643
+ }
2644
+ function CircularProgress({
2645
+ value = 0,
2646
+ max = 100,
2647
+ isIndeterminate = false,
2648
+ size = 48,
2649
+ strokeWidth = 4,
2650
+ color = "primary",
2651
+ showValue = false,
2652
+ formatValue = (v, m) => `${Math.round(v / m * 100)}%`,
2653
+ className,
2654
+ ...props
2655
+ }) {
2656
+ const percentage = Math.min(Math.max(value / max * 100, 0), 100);
2657
+ return /* @__PURE__ */ jsxs(
2658
+ View,
2659
+ {
2660
+ className: cn("items-center justify-center", className),
2661
+ style: { width: size, height: size },
2662
+ accessibilityRole: "progressbar",
2663
+ accessibilityValue: {
2664
+ min: 0,
2665
+ max,
2666
+ now: isIndeterminate ? void 0 : value
2667
+ },
2668
+ ...props,
2669
+ children: [
2670
+ /* @__PURE__ */ jsx(
2671
+ View,
2672
+ {
2673
+ className: cn(
2674
+ "absolute rounded-full border-4",
2675
+ "border-border-default"
2676
+ ),
2677
+ style: {
2678
+ width: size,
2679
+ height: size,
2680
+ borderWidth: strokeWidth
2681
+ }
2682
+ }
2683
+ ),
2684
+ /* @__PURE__ */ jsx(
2685
+ View,
2686
+ {
2687
+ className: cn(
2688
+ "absolute rounded-full",
2689
+ colorStyles4[color],
2690
+ isIndeterminate && "animate-spin"
2691
+ ),
2692
+ style: {
2693
+ width: size,
2694
+ height: size,
2695
+ borderWidth: strokeWidth,
2696
+ borderColor: "transparent",
2697
+ borderTopColor: colorVarMap[color],
2698
+ borderRightColor: percentage > 25 ? colorVarMap[color] : "transparent",
2699
+ borderBottomColor: percentage > 50 ? colorVarMap[color] : "transparent",
2700
+ borderLeftColor: percentage > 75 ? colorVarMap[color] : "transparent"
2701
+ }
2702
+ }
2703
+ ),
2704
+ showValue && !isIndeterminate && /* @__PURE__ */ jsx(Text, { className: "text-xs font-semibold text-text-primary", children: formatValue(value, max) })
2705
+ ]
2706
+ }
2707
+ );
2708
+ }
2709
+ var stepSizeStyles = {
2710
+ sm: { dot: "w-2 h-2", connector: "h-0.5" },
2711
+ md: { dot: "w-3 h-3", connector: "h-1" },
2712
+ lg: { dot: "w-4 h-4", connector: "h-1.5" }
2713
+ };
2714
+ function ProgressSteps({
2715
+ currentStep,
2716
+ totalSteps,
2717
+ color = "primary",
2718
+ size = "md",
2719
+ labels,
2720
+ className,
2721
+ ...props
2722
+ }) {
2723
+ const { dot, connector } = stepSizeStyles[size];
2724
+ return /* @__PURE__ */ jsxs(View, { className: cn("w-full", className), ...props, children: [
2725
+ /* @__PURE__ */ jsx(View, { className: "flex-row items-center", children: Array.from({ length: totalSteps }).map((_, index) => /* @__PURE__ */ jsxs(React24.Fragment, { children: [
2726
+ /* @__PURE__ */ jsx(
2727
+ View,
2728
+ {
2729
+ className: cn(
2730
+ "rounded-full",
2731
+ dot,
2732
+ index <= currentStep ? colorStyles4[color] : "bg-border-strong"
2733
+ )
2734
+ }
2735
+ ),
2736
+ index < totalSteps - 1 && /* @__PURE__ */ jsx(
2737
+ View,
2738
+ {
2739
+ className: cn(
2740
+ "flex-1 mx-1",
2741
+ connector,
2742
+ index < currentStep ? colorStyles4[color] : "bg-border-strong"
2743
+ )
2744
+ }
2745
+ )
2746
+ ] }, index)) }),
2747
+ labels && labels.length > 0 && /* @__PURE__ */ jsx(View, { className: "flex-row mt-2", children: labels.map((label, index) => /* @__PURE__ */ jsx(
2748
+ Text,
2749
+ {
2750
+ className: cn(
2751
+ "flex-1 text-xs text-center",
2752
+ index <= currentStep ? "text-text-primary font-medium" : "text-text-tertiary"
2753
+ ),
2754
+ children: label
2755
+ },
2756
+ index
2757
+ )) })
2758
+ ] });
2759
+ }
2760
+ var ToastContext = createContext(null);
2761
+ var toastIdCounter = 0;
2762
+ var positionStyles = {
2763
+ "top": "top-4 left-1/2 -translate-x-1/2",
2764
+ "top-right": "top-4 right-4",
2765
+ "top-left": "top-4 left-4",
2766
+ "bottom": "bottom-4 left-1/2 -translate-x-1/2",
2767
+ "bottom-right": "bottom-4 right-4",
2768
+ "bottom-left": "bottom-4 left-4"
2769
+ };
2770
+ function ToastProvider({
2771
+ position = "top-right",
2772
+ defaultDuration = 5e3,
2773
+ maxToasts = 5,
2774
+ children
2775
+ }) {
2776
+ const [toasts, setToasts] = useState([]);
2777
+ const addToast = useCallback((config) => {
2778
+ const id = `toast-${++toastIdCounter}`;
2779
+ const newToast = {
2780
+ id,
2781
+ duration: defaultDuration,
2782
+ isClosable: true,
2783
+ status: "info",
2784
+ ...config
2785
+ };
2786
+ setToasts((prev) => {
2787
+ const updated = [newToast, ...prev];
2788
+ return updated.slice(0, maxToasts);
2789
+ });
2790
+ return id;
2791
+ }, [defaultDuration, maxToasts]);
2792
+ const removeToast = useCallback((id) => {
2793
+ setToasts((prev) => prev.filter((t) => t.id !== id));
2794
+ }, []);
2795
+ const removeAllToasts = useCallback(() => {
2796
+ setToasts([]);
2797
+ }, []);
2798
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toasts, addToast, removeToast, removeAllToasts }, children: [
2799
+ children,
2800
+ /* @__PURE__ */ jsx(
2801
+ View,
2802
+ {
2803
+ className: cn(
2804
+ "fixed z-[9999] flex flex-col gap-2",
2805
+ positionStyles[position]
2806
+ ),
2807
+ pointerEvents: "box-none",
2808
+ children: toasts.map((toast) => /* @__PURE__ */ jsx(
2809
+ ToastItem,
2810
+ {
2811
+ ...toast,
2812
+ onClose: () => {
2813
+ removeToast(toast.id);
2814
+ toast.onClose?.();
2815
+ }
2816
+ },
2817
+ toast.id
2818
+ ))
2819
+ }
2820
+ )
2821
+ ] });
2822
+ }
2823
+ function useToast() {
2824
+ const context = useContext(ToastContext);
2825
+ if (!context) {
2826
+ throw new Error("useToast must be used within a ToastProvider");
2827
+ }
2828
+ return context;
2829
+ }
2830
+ var statusStyles = {
2831
+ success: {
2832
+ bg: "bg-status-success/10",
2833
+ border: "border-status-success",
2834
+ icon: "\u2713"
2835
+ },
2836
+ error: {
2837
+ bg: "bg-status-error/10",
2838
+ border: "border-status-error",
2839
+ icon: "\u2715"
2840
+ },
2841
+ warning: {
2842
+ bg: "bg-status-warning/10",
2843
+ border: "border-status-warning",
2844
+ icon: "\u26A0"
2845
+ },
2846
+ info: {
2847
+ bg: "bg-status-info/10",
2848
+ border: "border-status-info",
2849
+ icon: "\u2139"
2850
+ }
2851
+ };
2852
+ var iconColors = {
2853
+ success: "text-status-success",
2854
+ error: "text-status-error",
2855
+ warning: "text-status-warning",
2856
+ info: "text-status-info"
2857
+ };
2858
+ function ToastItem({
2859
+ id,
2860
+ title,
2861
+ description,
2862
+ status = "info",
2863
+ duration = 5e3,
2864
+ isClosable = true,
2865
+ onClose
2866
+ }) {
2867
+ const { bg, border, icon } = statusStyles[status];
2868
+ useEffect(() => {
2869
+ if (duration > 0) {
2870
+ const timer = setTimeout(onClose, duration);
2871
+ return () => clearTimeout(timer);
2872
+ }
2873
+ }, [duration, onClose]);
2874
+ return /* @__PURE__ */ jsx(
2875
+ View,
2876
+ {
2877
+ className: cn(
2878
+ "min-w-[280px] max-w-[400px] rounded-lg border-l-4 shadow-lg",
2879
+ "bg-surface-elevated",
2880
+ border
2881
+ ),
2882
+ accessibilityRole: "alert",
2883
+ children: /* @__PURE__ */ jsxs(View, { className: cn("flex-row items-start p-3", bg), children: [
2884
+ /* @__PURE__ */ jsx(View, { className: cn("w-6 h-6 items-center justify-center mr-3"), children: /* @__PURE__ */ jsx(Text, { className: cn("text-lg", iconColors[status]), children: icon }) }),
2885
+ /* @__PURE__ */ jsxs(View, { className: "flex-1", children: [
2886
+ /* @__PURE__ */ jsx(Text, { className: "text-sm font-semibold text-text-primary", children: title }),
2887
+ description && /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-secondary mt-0.5", children: description })
2888
+ ] }),
2889
+ isClosable && /* @__PURE__ */ jsx(
2890
+ Pressable,
2891
+ {
2892
+ onPress: onClose,
2893
+ className: "p-1 -m-1 rounded web:hover:bg-interactive-hover",
2894
+ accessibilityLabel: "Close toast",
2895
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary text-lg", children: "\xD7" })
2896
+ }
2897
+ )
2898
+ ] })
2899
+ }
2900
+ );
2901
+ }
2902
+ function Toast({
2903
+ title,
2904
+ description,
2905
+ status = "info",
2906
+ showIcon = true,
2907
+ isClosable = false,
2908
+ onClose,
2909
+ className,
2910
+ ...props
2911
+ }) {
2912
+ const { bg, border, icon } = statusStyles[status];
2913
+ return /* @__PURE__ */ jsx(
2914
+ View,
2915
+ {
2916
+ className: cn(
2917
+ "min-w-[280px] max-w-[400px] rounded-lg border-l-4 shadow-lg",
2918
+ "bg-surface-elevated",
2919
+ border,
2920
+ className
2921
+ ),
2922
+ accessibilityRole: "alert",
2923
+ ...props,
2924
+ children: /* @__PURE__ */ jsxs(View, { className: cn("flex-row items-start p-3", bg), children: [
2925
+ showIcon && /* @__PURE__ */ jsx(View, { className: "w-6 h-6 items-center justify-center mr-3", children: /* @__PURE__ */ jsx(Text, { className: cn("text-lg", iconColors[status]), children: icon }) }),
2926
+ /* @__PURE__ */ jsxs(View, { className: "flex-1", children: [
2927
+ /* @__PURE__ */ jsx(Text, { className: "text-sm font-semibold text-text-primary", children: title }),
2928
+ description && /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-secondary mt-0.5", children: description })
2929
+ ] }),
2930
+ isClosable && onClose && /* @__PURE__ */ jsx(
2931
+ Pressable,
2932
+ {
2933
+ onPress: onClose,
2934
+ className: "p-1 -m-1 rounded web:hover:bg-interactive-hover",
2935
+ accessibilityLabel: "Close toast",
2936
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary text-lg", children: "\xD7" })
2937
+ }
2938
+ )
2939
+ ] })
2940
+ }
2941
+ );
2942
+ }
2943
+ var defaultFilterFn = (option, inputValue) => {
2944
+ const searchLower = inputValue.toLowerCase();
2945
+ return option.label.toLowerCase().includes(searchLower) || (option.description?.toLowerCase().includes(searchLower) ?? false);
2946
+ };
2947
+ function Autocomplete({
2948
+ options,
2949
+ value,
2950
+ onChange,
2951
+ onInputChange,
2952
+ minChars = 0,
2953
+ placeholder = "Search...",
2954
+ label,
2955
+ helperText,
2956
+ errorMessage,
2957
+ isRequired = false,
2958
+ isDisabled = false,
2959
+ isLoading = false,
2960
+ isClearable = true,
2961
+ filterFn = defaultFilterFn,
2962
+ renderOption,
2963
+ noOptionsText = "No options found",
2964
+ loadingText = "Loading...",
2965
+ minCharsText,
2966
+ className,
2967
+ inputProps,
2968
+ ...props
2969
+ }) {
2970
+ const [inputValue, setInputValue] = useState("");
2971
+ const [isOpen, setIsOpen] = useState(false);
2972
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
2973
+ const selectedOption = useMemo(
2974
+ () => options.find((o) => o.value === value),
2975
+ [options, value]
2976
+ );
2977
+ const filteredOptions = useMemo(() => {
2978
+ if (inputValue.length < minChars) return [];
2979
+ return options.filter((option) => filterFn(option, inputValue));
2980
+ }, [options, inputValue, minChars, filterFn]);
2981
+ const handleInputChange = useCallback(
2982
+ (text) => {
2983
+ setInputValue(text);
2984
+ setIsOpen(true);
2985
+ setHighlightedIndex(-1);
2986
+ onInputChange?.(text);
2987
+ },
2988
+ [onInputChange]
2989
+ );
2990
+ const handleSelectOption = useCallback(
2991
+ (option) => {
2992
+ if (option.isDisabled) return;
2993
+ onChange?.(option.value);
2994
+ setInputValue(option.label);
2995
+ setIsOpen(false);
2996
+ },
2997
+ [onChange]
2998
+ );
2999
+ const handleClear = useCallback(() => {
3000
+ onChange?.(null);
3001
+ setInputValue("");
3002
+ setIsOpen(false);
3003
+ }, [onChange]);
3004
+ const handleFocus = useCallback(() => {
3005
+ setIsOpen(true);
3006
+ if (selectedOption && !inputValue) {
3007
+ setInputValue(selectedOption.label);
3008
+ }
3009
+ }, [selectedOption, inputValue]);
3010
+ const handleBlur = useCallback(() => {
3011
+ setTimeout(() => {
3012
+ setIsOpen(false);
3013
+ if (selectedOption) {
3014
+ setInputValue(selectedOption.label);
3015
+ } else {
3016
+ setInputValue("");
3017
+ }
3018
+ }, 200);
3019
+ }, [selectedOption]);
3020
+ const isInvalid = !!errorMessage;
3021
+ const showMinCharsMessage = inputValue.length > 0 && inputValue.length < minChars;
3022
+ const showNoResults = !isLoading && inputValue.length >= minChars && filteredOptions.length === 0;
3023
+ const showOptions = isOpen && !showMinCharsMessage && filteredOptions.length > 0;
3024
+ return /* @__PURE__ */ jsxs(View, { className: cn("w-full", className), ...props, children: [
3025
+ label && /* @__PURE__ */ jsxs(Text, { className: "text-sm font-medium text-text-primary mb-1", children: [
3026
+ label,
3027
+ isRequired && /* @__PURE__ */ jsx(Text, { className: "text-status-error ml-0.5", children: "*" })
3028
+ ] }),
3029
+ /* @__PURE__ */ jsxs(View, { className: "relative", children: [
3030
+ /* @__PURE__ */ jsxs(
3031
+ View,
3032
+ {
3033
+ className: cn(
3034
+ "flex-row items-center border rounded-md",
3035
+ "bg-surface-input",
3036
+ isInvalid ? "border-border-input-error" : "border-border-input",
3037
+ !isDisabled && !isInvalid && "focus-within:border-border-input-focus",
3038
+ isDisabled && "opacity-50"
3039
+ ),
3040
+ children: [
3041
+ /* @__PURE__ */ jsx(
3042
+ TextInput,
3043
+ {
3044
+ value: inputValue,
3045
+ onChangeText: handleInputChange,
3046
+ onFocus: handleFocus,
3047
+ onBlur: handleBlur,
3048
+ placeholder,
3049
+ editable: !isDisabled,
3050
+ className: cn(
3051
+ "flex-1 px-3 py-2 text-text-primary",
3052
+ "placeholder:text-text-tertiary"
3053
+ ),
3054
+ accessibilityLabel: label,
3055
+ ...inputProps
3056
+ }
3057
+ ),
3058
+ isClearable && value && !isDisabled && /* @__PURE__ */ jsx(
3059
+ Pressable,
3060
+ {
3061
+ onPress: handleClear,
3062
+ className: "p-2",
3063
+ accessibilityLabel: "Clear selection",
3064
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", children: "\xD7" })
3065
+ }
3066
+ ),
3067
+ isLoading && /* @__PURE__ */ jsx(View, { className: "p-2", children: /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary animate-spin", children: "\u27F3" }) })
3068
+ ]
3069
+ }
3070
+ ),
3071
+ isOpen && /* @__PURE__ */ jsx(
3072
+ View,
3073
+ {
3074
+ className: cn(
3075
+ "absolute z-50 top-full left-0 right-0 mt-1",
3076
+ "bg-surface-elevated rounded-md shadow-lg border border-border-default",
3077
+ "max-h-60 overflow-hidden"
3078
+ ),
3079
+ children: /* @__PURE__ */ jsxs(ScrollView, { className: "py-1", children: [
3080
+ showMinCharsMessage && /* @__PURE__ */ jsx(Text, { className: "px-3 py-2 text-sm text-text-tertiary", children: minCharsText || `Type at least ${minChars} characters` }),
3081
+ isLoading && /* @__PURE__ */ jsx(Text, { className: "px-3 py-2 text-sm text-text-tertiary", children: loadingText }),
3082
+ showNoResults && /* @__PURE__ */ jsx(Text, { className: "px-3 py-2 text-sm text-text-tertiary", children: noOptionsText }),
3083
+ showOptions && filteredOptions.map((option, index) => {
3084
+ const isHighlighted = index === highlightedIndex;
3085
+ const isSelected = option.value === value;
3086
+ if (renderOption) {
3087
+ return /* @__PURE__ */ jsx(
3088
+ Pressable,
3089
+ {
3090
+ onPress: () => handleSelectOption(option),
3091
+ disabled: option.isDisabled,
3092
+ children: renderOption(option, isHighlighted)
3093
+ },
3094
+ String(option.value)
3095
+ );
3096
+ }
3097
+ return /* @__PURE__ */ jsxs(
3098
+ Pressable,
3099
+ {
3100
+ onPress: () => handleSelectOption(option),
3101
+ disabled: option.isDisabled,
3102
+ className: cn(
3103
+ "px-3 py-2",
3104
+ isHighlighted && "bg-interactive-hover",
3105
+ isSelected && "bg-interactive-selected",
3106
+ option.isDisabled && "opacity-50",
3107
+ !option.isDisabled && "web:hover:bg-interactive-hover"
3108
+ ),
3109
+ children: [
3110
+ /* @__PURE__ */ jsx(
3111
+ Text,
3112
+ {
3113
+ className: cn(
3114
+ "text-sm",
3115
+ isSelected ? "text-brand-primary font-medium" : "text-text-primary"
3116
+ ),
3117
+ children: option.label
3118
+ }
3119
+ ),
3120
+ option.description && /* @__PURE__ */ jsx(Text, { className: "text-xs text-text-tertiary mt-0.5", children: option.description })
3121
+ ]
3122
+ },
3123
+ String(option.value)
3124
+ );
3125
+ })
3126
+ ] })
3127
+ }
3128
+ )
3129
+ ] }),
3130
+ (helperText || errorMessage) && /* @__PURE__ */ jsx(
3131
+ Text,
3132
+ {
3133
+ className: cn(
3134
+ "text-xs mt-1",
3135
+ isInvalid ? "text-status-error" : "text-text-tertiary"
3136
+ ),
3137
+ children: errorMessage || helperText
3138
+ }
3139
+ )
3140
+ ] });
3141
+ }
3142
+ var sizeStyles12 = {
3143
+ sm: { icon: "w-3.5 h-3.5 text-xs", text: "text-xs" },
3144
+ md: { icon: "w-4 h-4 text-sm", text: "text-sm" },
3145
+ lg: { icon: "w-5 h-5 text-base", text: "text-base" }
3146
+ };
3147
+ var colorStyles5 = {
3148
+ default: "text-text-tertiary",
3149
+ primary: "text-brand-primary",
3150
+ secondary: "text-text-secondary",
3151
+ muted: "text-text-tertiary opacity-60"
3152
+ };
3153
+ var iconMap = {
3154
+ help: "?",
3155
+ info: "\u2139",
3156
+ warning: "\u26A0"
3157
+ };
3158
+ var placementStyles2 = {
3159
+ top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
3160
+ bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
3161
+ left: "right-full top-1/2 -translate-y-1/2 mr-2",
3162
+ right: "left-full top-1/2 -translate-y-1/2 ml-2"
3163
+ };
3164
+ var arrowStyles = {
3165
+ top: "bottom-0 left-1/2 -translate-x-1/2 translate-y-full border-t-surface-elevated border-x-transparent border-b-transparent",
3166
+ bottom: "top-0 left-1/2 -translate-x-1/2 -translate-y-full border-b-surface-elevated border-x-transparent border-t-transparent",
3167
+ left: "right-0 top-1/2 -translate-y-1/2 translate-x-full border-l-surface-elevated border-y-transparent border-r-transparent",
3168
+ right: "left-0 top-1/2 -translate-y-1/2 -translate-x-full border-r-surface-elevated border-y-transparent border-l-transparent"
3169
+ };
3170
+ function HelpTip({
3171
+ content,
3172
+ size = "md",
3173
+ placement = "top",
3174
+ icon = "help",
3175
+ color = "default",
3176
+ isOpen: controlledIsOpen,
3177
+ hasArrow = true,
3178
+ maxWidth = 250,
3179
+ iconClassName,
3180
+ tooltipClassName,
3181
+ className,
3182
+ ...props
3183
+ }) {
3184
+ const [internalIsOpen, setInternalIsOpen] = useState(false);
3185
+ const isOpen = controlledIsOpen ?? internalIsOpen;
3186
+ const { icon: iconSize, text: textSize } = sizeStyles12[size];
3187
+ const handlePress = () => {
3188
+ if (controlledIsOpen === void 0) {
3189
+ setInternalIsOpen((prev) => !prev);
3190
+ }
3191
+ };
3192
+ const handleHoverIn = () => {
3193
+ if (controlledIsOpen === void 0) {
3194
+ setInternalIsOpen(true);
3195
+ }
3196
+ };
3197
+ const handleHoverOut = () => {
3198
+ if (controlledIsOpen === void 0) {
3199
+ setInternalIsOpen(false);
3200
+ }
3201
+ };
3202
+ return /* @__PURE__ */ jsxs(View, { className: cn("relative inline-flex", className), ...props, children: [
3203
+ /* @__PURE__ */ jsx(
3204
+ Pressable,
3205
+ {
3206
+ onPress: handlePress,
3207
+ onHoverIn: handleHoverIn,
3208
+ onHoverOut: handleHoverOut,
3209
+ accessibilityRole: "button",
3210
+ accessibilityLabel: "Show help information",
3211
+ accessibilityHint: typeof content === "string" ? content : void 0,
3212
+ className: cn(
3213
+ "items-center justify-center rounded-full",
3214
+ "border border-current",
3215
+ colorStyles5[color],
3216
+ iconSize,
3217
+ "web:hover:opacity-80 web:cursor-help",
3218
+ iconClassName
3219
+ ),
3220
+ children: /* @__PURE__ */ jsx(Text, { className: cn("font-semibold", iconSize, colorStyles5[color]), children: iconMap[icon] })
3221
+ }
3222
+ ),
3223
+ isOpen && /* @__PURE__ */ jsxs(
3224
+ View,
3225
+ {
3226
+ className: cn(
3227
+ "absolute z-50",
3228
+ "bg-surface-elevated rounded-lg shadow-lg",
3229
+ "border border-border-default",
3230
+ "px-3 py-2",
3231
+ placementStyles2[placement],
3232
+ tooltipClassName
3233
+ ),
3234
+ style: { maxWidth },
3235
+ children: [
3236
+ typeof content === "string" ? /* @__PURE__ */ jsx(Text, { className: cn("text-text-primary", textSize), children: content }) : content,
3237
+ hasArrow && /* @__PURE__ */ jsx(
3238
+ View,
3239
+ {
3240
+ className: cn(
3241
+ "absolute w-0 h-0",
3242
+ "border-4",
3243
+ arrowStyles[placement]
3244
+ )
3245
+ }
3246
+ )
3247
+ ]
3248
+ }
3249
+ )
3250
+ ] });
3251
+ }
3252
+ function LabelWithHelp({
3253
+ label,
3254
+ helpContent,
3255
+ isRequired = false,
3256
+ helpSize = "sm",
3257
+ className,
3258
+ ...props
3259
+ }) {
3260
+ return /* @__PURE__ */ jsxs(View, { className: cn("flex-row items-center gap-1", className), ...props, children: [
3261
+ /* @__PURE__ */ jsxs(Text, { className: "text-sm font-medium text-text-primary", children: [
3262
+ label,
3263
+ isRequired && /* @__PURE__ */ jsx(Text, { className: "text-status-error ml-0.5", children: "*" })
3264
+ ] }),
3265
+ /* @__PURE__ */ jsx(HelpTip, { content: helpContent, size: helpSize })
3266
+ ] });
3267
+ }
3268
+ var labelSizeStyles = {
3269
+ sm: "text-xs",
3270
+ md: "text-sm",
3271
+ lg: "text-base"
3272
+ };
3273
+ function FormField({
3274
+ label,
3275
+ isRequired = false,
3276
+ helperText,
3277
+ errorMessage,
3278
+ isDisabled = false,
3279
+ isReadOnly = false,
3280
+ helpContent,
3281
+ labelSize = "sm",
3282
+ orientation = "vertical",
3283
+ labelWidth,
3284
+ className,
3285
+ children,
3286
+ ...props
3287
+ }) {
3288
+ const isInvalid = !!errorMessage;
3289
+ const isHorizontal = orientation === "horizontal";
3290
+ const fieldId = React24.useId();
3291
+ const helperId = `${fieldId}-helper`;
3292
+ const errorId = `${fieldId}-error`;
3293
+ return /* @__PURE__ */ jsxs(
3294
+ View,
3295
+ {
3296
+ className: cn(
3297
+ "w-full",
3298
+ isHorizontal && "flex-row items-start",
3299
+ isDisabled && "opacity-50",
3300
+ className
3301
+ ),
3302
+ ...props,
3303
+ children: [
3304
+ label && /* @__PURE__ */ jsxs(
3305
+ View,
3306
+ {
3307
+ className: cn(
3308
+ "flex-row items-center",
3309
+ isHorizontal ? "pt-2" : "mb-1.5"
3310
+ ),
3311
+ style: isHorizontal && labelWidth ? { width: labelWidth } : void 0,
3312
+ children: [
3313
+ /* @__PURE__ */ jsxs(
3314
+ Text,
3315
+ {
3316
+ className: cn(
3317
+ "font-medium text-text-primary",
3318
+ labelSizeStyles[labelSize]
3319
+ ),
3320
+ children: [
3321
+ label,
3322
+ isRequired && /* @__PURE__ */ jsx(Text, { className: "text-status-error ml-0.5", children: "*" })
3323
+ ]
3324
+ }
3325
+ ),
3326
+ helpContent && /* @__PURE__ */ jsx(View, { className: "ml-1", children: /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary text-xs", children: "\u2139" }) })
3327
+ ]
3328
+ }
3329
+ ),
3330
+ /* @__PURE__ */ jsxs(View, { className: cn(isHorizontal && "flex-1"), children: [
3331
+ React24.Children.map(children, (child) => {
3332
+ if (React24.isValidElement(child)) {
3333
+ const childProps = child.props;
3334
+ return React24.cloneElement(child, {
3335
+ accessibilityHint: errorMessage || helperText || childProps.accessibilityHint,
3336
+ accessibilityState: {
3337
+ ...childProps.accessibilityState,
3338
+ disabled: isDisabled || childProps.accessibilityState?.disabled,
3339
+ ...isInvalid ? { invalid: true } : {}
3340
+ },
3341
+ isDisabled: isDisabled || childProps.isDisabled,
3342
+ isReadOnly: isReadOnly || childProps.isReadOnly,
3343
+ isInvalid: isInvalid || childProps.isInvalid
3344
+ });
3345
+ }
3346
+ return child;
3347
+ }),
3348
+ (helperText || errorMessage) && /* @__PURE__ */ jsx(
3349
+ Text,
3350
+ {
3351
+ id: isInvalid ? errorId : helperId,
3352
+ className: cn(
3353
+ "text-xs mt-1.5",
3354
+ isInvalid ? "text-status-error" : "text-text-tertiary"
3355
+ ),
3356
+ children: errorMessage || helperText
3357
+ }
3358
+ )
3359
+ ] })
3360
+ ]
3361
+ }
3362
+ );
3363
+ }
3364
+ function FormSection({
3365
+ title,
3366
+ description,
3367
+ className,
3368
+ children,
3369
+ ...props
3370
+ }) {
3371
+ return /* @__PURE__ */ jsxs(
3372
+ View,
3373
+ {
3374
+ className: cn("w-full", className),
3375
+ accessibilityRole: "group",
3376
+ accessibilityLabel: title,
3377
+ ...props,
3378
+ children: [
3379
+ (title || description) && /* @__PURE__ */ jsxs(View, { className: "mb-4", children: [
3380
+ title && /* @__PURE__ */ jsx(Text, { className: "text-lg font-semibold text-text-primary", children: title }),
3381
+ description && /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-secondary mt-1", children: description })
3382
+ ] }),
3383
+ /* @__PURE__ */ jsx(View, { className: "gap-4", children })
3384
+ ]
3385
+ }
3386
+ );
3387
+ }
3388
+ var alignStyles = {
3389
+ left: "justify-start",
3390
+ center: "justify-center",
3391
+ right: "justify-end",
3392
+ between: "justify-between"
3393
+ };
3394
+ function FormActions({
3395
+ align = "right",
3396
+ className,
3397
+ children,
3398
+ ...props
3399
+ }) {
3400
+ return /* @__PURE__ */ jsx(
3401
+ View,
3402
+ {
3403
+ className: cn(
3404
+ "flex-row items-center gap-3 pt-4",
3405
+ "border-t border-border-default mt-4",
3406
+ alignStyles[align],
3407
+ className
3408
+ ),
3409
+ ...props,
3410
+ children
3411
+ }
3412
+ );
3413
+ }
3414
+ var gapStyles3 = {
3415
+ sm: "gap-2",
3416
+ md: "gap-4",
3417
+ lg: "gap-6"
3418
+ };
3419
+ function FormRow({
3420
+ gap = "md",
3421
+ className,
3422
+ children,
3423
+ ...props
3424
+ }) {
3425
+ return /* @__PURE__ */ jsx(
3426
+ View,
3427
+ {
3428
+ className: cn("flex-row items-start", gapStyles3[gap], className),
3429
+ ...props,
3430
+ children
3431
+ }
3432
+ );
3433
+ }
3434
+ var variantStyles4 = {
3435
+ h1: "font-heading text-5xl font-bold leading-tight",
3436
+ h2: "font-heading text-4xl font-bold leading-tight",
3437
+ h3: "font-heading text-3xl font-bold leading-tight",
3438
+ h4: "font-heading text-2xl font-bold leading-tight",
3439
+ h5: "font-heading text-xl font-semibold leading-tight",
3440
+ h6: "font-heading text-lg font-semibold leading-tight",
3441
+ body1: "font-body text-base font-normal leading-normal",
3442
+ body2: "font-body text-sm font-normal leading-normal",
3443
+ subtitle1: "font-body text-base font-medium leading-relaxed",
3444
+ subtitle2: "font-body text-sm font-medium leading-normal",
3445
+ caption: "font-body text-xs font-normal leading-loose",
3446
+ overline: "font-body text-xs font-semibold uppercase tracking-widest leading-relaxed",
3447
+ button: "font-sans text-sm font-semibold leading-relaxed"
3448
+ };
3449
+ var colorStyles6 = {
3450
+ primary: "text-text-primary",
3451
+ secondary: "text-text-secondary",
3452
+ tertiary: "text-text-tertiary",
3453
+ disabled: "text-text-disabled",
3454
+ inverse: "text-text-inverse",
3455
+ success: "text-status-success",
3456
+ error: "text-status-error",
3457
+ warning: "text-status-warning",
3458
+ info: "text-status-info",
3459
+ inherit: ""
3460
+ // No color class, inherit from parent
3461
+ };
3462
+ var alignStyles2 = {
3463
+ left: "text-left",
3464
+ center: "text-center",
3465
+ right: "text-right",
3466
+ justify: "text-justify"
3467
+ };
3468
+ var headingVariants = ["h1", "h2", "h3", "h4", "h5", "h6"];
3469
+ var marginBottomStyles = {
3470
+ none: "",
3471
+ sm: "mb-1",
3472
+ md: "mb-2",
3473
+ lg: "mb-4"
3474
+ };
3475
+ function Typography({
3476
+ variant = "body1",
3477
+ color = "primary",
3478
+ align,
3479
+ truncate = false,
3480
+ noWrap = false,
3481
+ // deprecated, kept for backward compatibility
3482
+ marginBottom,
3483
+ gutterBottom = false,
3484
+ // deprecated, kept for backward compatibility
3485
+ maxLines,
3486
+ className,
3487
+ children,
3488
+ ...props
3489
+ }) {
3490
+ const isHeading = headingVariants.includes(variant);
3491
+ const shouldTruncate = truncate || noWrap;
3492
+ const mb = marginBottom || (gutterBottom ? "md" : "none");
3493
+ let numLines;
3494
+ if (maxLines) {
3495
+ numLines = maxLines;
3496
+ } else if (shouldTruncate) {
3497
+ numLines = 1;
3498
+ }
3499
+ return /* @__PURE__ */ jsx(
3500
+ Text,
3501
+ {
3502
+ accessibilityRole: isHeading ? "header" : "text",
3503
+ numberOfLines: numLines,
3504
+ className: cn(
3505
+ variantStyles4[variant],
3506
+ color !== "inherit" && colorStyles6[color],
3507
+ align && alignStyles2[align],
3508
+ shouldTruncate && "truncate",
3509
+ marginBottomStyles[mb],
3510
+ className
3511
+ ),
3512
+ ...props,
3513
+ children
3514
+ }
3515
+ );
3516
+ }
3517
+ function Heading({ level = 1, ...props }) {
3518
+ const variant = `h${level}`;
3519
+ return /* @__PURE__ */ jsx(Typography, { variant, ...props });
3520
+ }
3521
+ function Paragraph({ small = false, ...props }) {
3522
+ return /* @__PURE__ */ jsx(Typography, { variant: small ? "body2" : "body1", ...props });
3523
+ }
3524
+ function Caption(props) {
3525
+ return /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", ...props });
3526
+ }
3527
+ function Label(props) {
3528
+ return /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", ...props });
3529
+ }
3530
+ function Overline(props) {
3531
+ return /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", ...props });
3532
+ }
3533
+ var SidebarContext = createContext({
3534
+ isCollapsed: false
3535
+ });
3536
+ function Sidebar({
3537
+ isCollapsed = false,
3538
+ activeItem,
3539
+ onItemSelect,
3540
+ width = 256,
3541
+ collapsedWidth = 64,
3542
+ className,
3543
+ children,
3544
+ ...props
3545
+ }) {
3546
+ const currentWidth = isCollapsed ? collapsedWidth : width;
3547
+ return /* @__PURE__ */ jsx(SidebarContext.Provider, { value: { isCollapsed, activeItem, onItemSelect }, children: /* @__PURE__ */ jsx(
3548
+ View,
3549
+ {
3550
+ style: { width: currentWidth },
3551
+ className: cn(
3552
+ "h-full flex-col bg-surface-base border-r border-border-default transition-all duration-200",
3553
+ className
3554
+ ),
3555
+ ...props,
3556
+ children
3557
+ }
3558
+ ) });
3559
+ }
3560
+ function SidebarHeader({ children, className }) {
3561
+ return /* @__PURE__ */ jsx(View, { className: cn("px-4 py-4 border-b border-border-subtle", className), children });
3562
+ }
3563
+ function SidebarContent({ children, className }) {
3564
+ return /* @__PURE__ */ jsx(
3565
+ ScrollView,
3566
+ {
3567
+ className: cn("flex-1", className),
3568
+ showsVerticalScrollIndicator: false,
3569
+ children
3570
+ }
3571
+ );
3572
+ }
3573
+ function SidebarFooter({ children, className }) {
3574
+ return /* @__PURE__ */ jsx(View, { className: cn("px-2 py-4 border-t border-border-subtle", className), children });
3575
+ }
3576
+ function SidebarSection({ title, children, className }) {
3577
+ const { isCollapsed } = useContext(SidebarContext);
3578
+ return /* @__PURE__ */ jsxs(View, { className: cn("px-2 py-2", className), children: [
3579
+ title && !isCollapsed && /* @__PURE__ */ jsx(Text, { className: "px-3 py-2 text-xs font-semibold uppercase tracking-wider text-text-tertiary", children: title }),
3580
+ /* @__PURE__ */ jsx(View, { className: "gap-0.5", children })
3581
+ ] });
3582
+ }
3583
+ function SidebarItem({
3584
+ id,
3585
+ icon: Icon,
3586
+ label,
3587
+ badge,
3588
+ hasChildren,
3589
+ isExpanded,
3590
+ className,
3591
+ onPress,
3592
+ ...props
3593
+ }) {
3594
+ const { isCollapsed, activeItem, onItemSelect } = useContext(SidebarContext);
3595
+ const isActive = activeItem === id;
3596
+ const handlePress = (e) => {
3597
+ onItemSelect?.(id);
3598
+ onPress?.(e);
3599
+ };
3600
+ return /* @__PURE__ */ jsxs(
3601
+ Pressable,
3602
+ {
3603
+ accessibilityRole: "button",
3604
+ accessibilityState: { selected: isActive },
3605
+ accessibilityLabel: label,
3606
+ onPress: handlePress,
3607
+ className: cn(
3608
+ "flex-row items-center gap-3 px-3 py-2.5 rounded-md transition-colors",
3609
+ isActive ? "bg-brand-primary-subtle text-brand-primary" : "text-text-secondary web:hover:bg-interactive-hover active:bg-interactive-active",
3610
+ isCollapsed && "justify-center px-2",
3611
+ className
3612
+ ),
3613
+ ...props,
3614
+ children: [
3615
+ Icon && /* @__PURE__ */ jsx(
3616
+ Icon,
3617
+ {
3618
+ size: 20,
3619
+ className: cn(
3620
+ isActive ? "text-brand-primary" : "text-text-secondary"
3621
+ )
3622
+ }
3623
+ ),
3624
+ !isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
3625
+ /* @__PURE__ */ jsx(
3626
+ Text,
3627
+ {
3628
+ numberOfLines: 1,
3629
+ className: cn(
3630
+ "flex-1 text-sm font-medium",
3631
+ isActive ? "text-brand-primary" : "text-text-primary"
3632
+ ),
3633
+ children: label
3634
+ }
3635
+ ),
3636
+ badge && /* @__PURE__ */ jsx(View, { className: "ml-auto", children: badge }),
3637
+ hasChildren && /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary ml-1", children: isExpanded ? "\u25BC" : "\u25B6" })
3638
+ ] })
3639
+ ]
3640
+ }
3641
+ );
3642
+ }
3643
+ function SidebarDivider({ className }) {
3644
+ return /* @__PURE__ */ jsx(View, { className: cn("h-px mx-4 my-2 bg-border-subtle", className) });
3645
+ }
3646
+ var TableContext = createContext({
3647
+ sortDirection: null,
3648
+ selectedRows: /* @__PURE__ */ new Set(),
3649
+ selectable: false,
3650
+ allRowIds: []
3651
+ });
3652
+ function Table({
3653
+ sortColumn,
3654
+ sortDirection = null,
3655
+ onSort,
3656
+ selectedRows = /* @__PURE__ */ new Set(),
3657
+ onSelectRow,
3658
+ onSelectAll,
3659
+ selectable = false,
3660
+ rowIds = [],
3661
+ isLoading = false,
3662
+ loadingRowCount = 5,
3663
+ className,
3664
+ children,
3665
+ ...props
3666
+ }) {
3667
+ return /* @__PURE__ */ jsx(
3668
+ TableContext.Provider,
3669
+ {
3670
+ value: {
3671
+ sortColumn,
3672
+ sortDirection,
3673
+ onSort,
3674
+ selectedRows,
3675
+ onSelectRow,
3676
+ onSelectAll,
3677
+ selectable,
3678
+ allRowIds: rowIds
3679
+ },
3680
+ children: /* @__PURE__ */ jsx(View, { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx(View, { className: "w-full min-w-full", children: isLoading ? /* @__PURE__ */ jsx(TableLoadingSkeleton, { rowCount: loadingRowCount }) : children }) }) })
3681
+ }
3682
+ );
3683
+ }
3684
+ function TableHeader({ children, className }) {
3685
+ return /* @__PURE__ */ jsx(
3686
+ View,
3687
+ {
3688
+ accessibilityRole: "none",
3689
+ className: cn("bg-background-subtle rounded-t-lg", className),
3690
+ children
3691
+ }
3692
+ );
3693
+ }
3694
+ function TableBody({ children, className }) {
3695
+ return /* @__PURE__ */ jsx(View, { accessibilityRole: "none", className, children });
3696
+ }
3697
+ function TableRow({
3698
+ isSelected = false,
3699
+ isHoverable = true,
3700
+ className,
3701
+ children,
3702
+ ...props
3703
+ }) {
3704
+ return /* @__PURE__ */ jsx(
3705
+ View,
3706
+ {
3707
+ accessibilityRole: "none",
3708
+ className: cn(
3709
+ "flex-row border-b border-divider",
3710
+ isHoverable && "web:hover:bg-interactive-hover",
3711
+ isSelected && "bg-interactive-selected",
3712
+ className
3713
+ ),
3714
+ ...props,
3715
+ children
3716
+ }
3717
+ );
3718
+ }
3719
+ function TableHeaderCell({
3720
+ sortKey,
3721
+ align = "left",
3722
+ width,
3723
+ className,
3724
+ children,
3725
+ onPress,
3726
+ ...props
3727
+ }) {
3728
+ const { sortColumn, sortDirection, onSort } = useContext(TableContext);
3729
+ const isSorted = sortKey && sortColumn === sortKey;
3730
+ const isSortable = !!sortKey && !!onSort;
3731
+ const handlePress = (e) => {
3732
+ if (isSortable && sortKey) {
3733
+ onSort(sortKey);
3734
+ }
3735
+ onPress?.(e);
3736
+ };
3737
+ const alignStyles3 = {
3738
+ left: "justify-start",
3739
+ center: "justify-center",
3740
+ right: "justify-end"
3741
+ };
3742
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
3743
+ /* @__PURE__ */ jsx(
3744
+ Text,
3745
+ {
3746
+ className: cn(
3747
+ "text-xs font-semibold uppercase tracking-wider text-text-secondary",
3748
+ isSorted && "text-text-primary"
3749
+ ),
3750
+ children
3751
+ }
3752
+ ),
3753
+ isSortable && /* @__PURE__ */ jsx(Text, { className: cn("ml-1 text-xs", isSorted ? "text-text-primary" : "text-text-tertiary"), children: isSorted ? sortDirection === "asc" ? "\u2191" : "\u2193" : "\u2195" })
3754
+ ] });
3755
+ if (isSortable) {
3756
+ return /* @__PURE__ */ jsx(
3757
+ Pressable,
3758
+ {
3759
+ accessibilityRole: "button",
3760
+ accessibilityLabel: `Sort by ${children}`,
3761
+ onPress: handlePress,
3762
+ style: width ? { width } : { flex: 1 },
3763
+ className: cn(
3764
+ "flex-row items-center px-4 py-3",
3765
+ alignStyles3[align],
3766
+ "web:hover:bg-interactive-hover active:bg-interactive-active",
3767
+ className
3768
+ ),
3769
+ ...props,
3770
+ children: content
3771
+ }
3772
+ );
3773
+ }
3774
+ return /* @__PURE__ */ jsx(
3775
+ View,
3776
+ {
3777
+ style: width ? { width } : { flex: 1 },
3778
+ className: cn(
3779
+ "flex-row items-center px-4 py-3",
3780
+ alignStyles3[align],
3781
+ className
3782
+ ),
3783
+ children: content
3784
+ }
3785
+ );
3786
+ }
3787
+ function TableCell({
3788
+ align = "left",
3789
+ width,
3790
+ className,
3791
+ children,
3792
+ ...props
3793
+ }) {
3794
+ const alignStyles3 = {
3795
+ left: "items-start",
3796
+ center: "items-center",
3797
+ right: "items-end"
3798
+ };
3799
+ return /* @__PURE__ */ jsx(
3800
+ View,
3801
+ {
3802
+ style: width ? { width } : { flex: 1 },
3803
+ className: cn(
3804
+ "justify-center px-4 py-3.5",
3805
+ alignStyles3[align],
3806
+ className
3807
+ ),
3808
+ ...props,
3809
+ children: typeof children === "string" ? /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-primary", children }) : children
3810
+ }
3811
+ );
3812
+ }
3813
+ function TablePagination({
3814
+ page,
3815
+ pageSize,
3816
+ totalItems,
3817
+ pageSizeOptions = [10, 25, 50, 100],
3818
+ onPageChange,
3819
+ onPageSizeChange,
3820
+ className
3821
+ }) {
3822
+ const totalPages = Math.ceil(totalItems / pageSize);
3823
+ const startItem = page * pageSize + 1;
3824
+ const endItem = Math.min((page + 1) * pageSize, totalItems);
3825
+ const canGoPrevious = page > 0;
3826
+ const canGoNext = page < totalPages - 1;
3827
+ return /* @__PURE__ */ jsxs(
3828
+ View,
3829
+ {
3830
+ className: cn(
3831
+ "flex-row items-center justify-between px-4 py-3 border-t border-divider",
3832
+ className
3833
+ ),
3834
+ children: [
3835
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center gap-2", children: [
3836
+ /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-secondary", children: "Rows per page:" }),
3837
+ /* @__PURE__ */ jsx(View, { className: "flex-row gap-1", children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx(
3838
+ Pressable,
3839
+ {
3840
+ onPress: () => onPageSizeChange?.(size),
3841
+ className: cn(
3842
+ "px-2 py-1 rounded",
3843
+ pageSize === size ? "bg-brand-primary-subtle text-brand-primary" : "text-text-secondary web:hover:bg-interactive-hover"
3844
+ ),
3845
+ children: /* @__PURE__ */ jsx(
3846
+ Text,
3847
+ {
3848
+ className: cn(
3849
+ "text-sm font-medium",
3850
+ pageSize === size ? "text-brand-primary" : "text-text-secondary"
3851
+ ),
3852
+ children: size
3853
+ }
3854
+ )
3855
+ },
3856
+ size
3857
+ )) })
3858
+ ] }),
3859
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center gap-4", children: [
3860
+ /* @__PURE__ */ jsxs(Text, { className: "text-sm text-text-secondary", children: [
3861
+ startItem,
3862
+ "-",
3863
+ endItem,
3864
+ " of ",
3865
+ totalItems
3866
+ ] }),
3867
+ /* @__PURE__ */ jsxs(View, { className: "flex-row gap-1", children: [
3868
+ /* @__PURE__ */ jsx(
3869
+ Pressable,
3870
+ {
3871
+ disabled: !canGoPrevious,
3872
+ onPress: () => onPageChange(page - 1),
3873
+ accessibilityLabel: "Previous page",
3874
+ className: cn(
3875
+ "p-2 rounded",
3876
+ canGoPrevious ? "web:hover:bg-interactive-hover active:bg-interactive-active" : "opacity-50"
3877
+ ),
3878
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary", children: "\u2190" })
3879
+ }
3880
+ ),
3881
+ /* @__PURE__ */ jsx(
3882
+ Pressable,
3883
+ {
3884
+ disabled: !canGoNext,
3885
+ onPress: () => onPageChange(page + 1),
3886
+ accessibilityLabel: "Next page",
3887
+ className: cn(
3888
+ "p-2 rounded",
3889
+ canGoNext ? "web:hover:bg-interactive-hover active:bg-interactive-active" : "opacity-50"
3890
+ ),
3891
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary", children: "\u2192" })
3892
+ }
3893
+ )
3894
+ ] })
3895
+ ] })
3896
+ ]
3897
+ }
3898
+ );
3899
+ }
3900
+ function useTable({
3901
+ data,
3902
+ defaultPageSize = 10,
3903
+ defaultSortColumn,
3904
+ defaultSortDirection = null
3905
+ }) {
3906
+ const [page, setPage] = useState(0);
3907
+ const [pageSize, setPageSize] = useState(defaultPageSize);
3908
+ const [sortColumn, setSortColumn] = useState(defaultSortColumn);
3909
+ const [sortDirection, setSortDirection] = useState(defaultSortDirection);
3910
+ const sortedData = useMemo(() => {
3911
+ if (!sortColumn || !sortDirection) return data;
3912
+ return [...data].sort((a, b) => {
3913
+ const aVal = a[sortColumn];
3914
+ const bVal = b[sortColumn];
3915
+ if (aVal === bVal) return 0;
3916
+ if (aVal === null || aVal === void 0) return 1;
3917
+ if (bVal === null || bVal === void 0) return -1;
3918
+ const comparison = aVal < bVal ? -1 : 1;
3919
+ return sortDirection === "asc" ? comparison : -comparison;
3920
+ });
3921
+ }, [data, sortColumn, sortDirection]);
3922
+ const paginatedData = useMemo(() => {
3923
+ const start = page * pageSize;
3924
+ return sortedData.slice(start, start + pageSize);
3925
+ }, [sortedData, page, pageSize]);
3926
+ const handleSort = (column) => {
3927
+ if (sortColumn === column) {
3928
+ setSortDirection(
3929
+ (prev) => prev === "asc" ? "desc" : prev === "desc" ? null : "asc"
3930
+ );
3931
+ } else {
3932
+ setSortColumn(column);
3933
+ setSortDirection("asc");
3934
+ }
3935
+ setPage(0);
3936
+ };
3937
+ const handlePageSizeChange = (newSize) => {
3938
+ setPageSize(newSize);
3939
+ setPage(0);
3940
+ };
3941
+ return {
3942
+ sortedData,
3943
+ paginatedData,
3944
+ page,
3945
+ pageSize,
3946
+ totalItems: data.length,
3947
+ sortColumn,
3948
+ sortDirection,
3949
+ setPage,
3950
+ setPageSize: handlePageSizeChange,
3951
+ handleSort
3952
+ };
3953
+ }
3954
+ function TableLoadingSkeleton({ rowCount }) {
3955
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3956
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { isHoverable: false, children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx(View, { className: "flex-1 px-4 py-3", children: /* @__PURE__ */ jsx(View, { className: "h-4 w-20 bg-interactive-disabled rounded animate-pulse" }) }, i)) }) }),
3957
+ /* @__PURE__ */ jsx(TableBody, { children: Array.from({ length: rowCount }).map((_, rowIndex) => /* @__PURE__ */ jsx(TableRow, { isHoverable: false, children: [1, 2, 3, 4].map((colIndex) => /* @__PURE__ */ jsx(View, { className: "flex-1 px-4 py-3.5", children: /* @__PURE__ */ jsx(
3958
+ View,
3959
+ {
3960
+ className: "h-4 bg-interactive-disabled rounded animate-pulse",
3961
+ style: { width: `${50 + Math.random() * 40}%` }
3962
+ }
3963
+ ) }, colIndex)) }, rowIndex)) })
3964
+ ] });
3965
+ }
3966
+ function EmptyState({
3967
+ icon: Icon,
3968
+ title,
3969
+ description,
3970
+ action,
3971
+ className,
3972
+ ...props
3973
+ }) {
3974
+ return /* @__PURE__ */ jsxs(
3975
+ View,
3976
+ {
3977
+ className: cn(
3978
+ "items-center justify-center py-12 px-6",
3979
+ className
3980
+ ),
3981
+ ...props,
3982
+ children: [
3983
+ Icon && /* @__PURE__ */ jsx(View, { className: "mb-4 p-4 rounded-full bg-background-subtle", children: /* @__PURE__ */ jsx(Icon, { size: 32, className: "text-text-tertiary" }) }),
3984
+ /* @__PURE__ */ jsx(Text, { className: "text-lg font-semibold text-text-primary text-center mb-2", children: title }),
3985
+ description && /* @__PURE__ */ jsx(Text, { className: "text-sm text-text-secondary text-center max-w-xs mb-6", children: description }),
3986
+ action && /* @__PURE__ */ jsx(View, { className: "mt-2", children: action })
3987
+ ]
3988
+ }
3989
+ );
3990
+ }
3991
+ var StepperContext = createContext({
3992
+ activeStep: 0,
3993
+ orientation: "horizontal"
3994
+ });
3995
+ function Stepper({
3996
+ activeStep,
3997
+ orientation = "horizontal",
3998
+ className,
3999
+ children,
4000
+ ...props
4001
+ }) {
4002
+ return /* @__PURE__ */ jsx(StepperContext.Provider, { value: { activeStep, orientation }, children: /* @__PURE__ */ jsx(
4003
+ View,
4004
+ {
4005
+ className: cn(
4006
+ orientation === "horizontal" ? "flex-row items-center" : "flex-col",
4007
+ className
4008
+ ),
4009
+ ...props,
4010
+ children: React24.Children.map(children, (child, index) => {
4011
+ if (React24.isValidElement(child)) {
4012
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4013
+ React24.cloneElement(child, { index }),
4014
+ index < React24.Children.count(children) - 1 && /* @__PURE__ */ jsx(StepConnector, { index })
4015
+ ] });
4016
+ }
4017
+ return child;
4018
+ })
4019
+ }
4020
+ ) });
4021
+ }
4022
+ function StepConnector({ index }) {
4023
+ const { activeStep, orientation } = useContext(StepperContext);
4024
+ const isCompleted = index < activeStep;
4025
+ if (orientation === "horizontal") {
4026
+ return /* @__PURE__ */ jsx(
4027
+ View,
4028
+ {
4029
+ className: cn(
4030
+ "flex-1 h-0.5 mx-2",
4031
+ isCompleted ? "bg-brand-primary" : "bg-border-default"
4032
+ )
4033
+ }
4034
+ );
4035
+ }
4036
+ return /* @__PURE__ */ jsx(
4037
+ View,
4038
+ {
4039
+ className: cn(
4040
+ "w-0.5 h-8 ml-4 my-1",
4041
+ isCompleted ? "bg-brand-primary" : "bg-border-default"
4042
+ )
4043
+ }
4044
+ );
4045
+ }
4046
+ function Step({ index = 0, status, className, children }) {
4047
+ const { activeStep, orientation } = useContext(StepperContext);
4048
+ const derivedStatus = status || (index < activeStep ? "completed" : index === activeStep ? "active" : "upcoming");
4049
+ return /* @__PURE__ */ jsx(
4050
+ View,
4051
+ {
4052
+ className: cn(
4053
+ orientation === "horizontal" ? "items-center" : "flex-row items-start",
4054
+ className
4055
+ ),
4056
+ children: React24.Children.map(children, (child) => {
4057
+ if (React24.isValidElement(child)) {
4058
+ return React24.cloneElement(child, {
4059
+ status: derivedStatus,
4060
+ index
4061
+ });
4062
+ }
4063
+ return child;
4064
+ })
4065
+ }
4066
+ );
4067
+ }
4068
+ function StepIndicator({
4069
+ status = "upcoming",
4070
+ index = 0,
4071
+ icon,
4072
+ className
4073
+ }) {
4074
+ const statusStyles2 = {
4075
+ completed: "bg-brand-primary border-brand-primary",
4076
+ active: "bg-brand-primary border-brand-primary",
4077
+ upcoming: "bg-surface-base border-border-strong",
4078
+ error: "bg-status-error border-status-error"
4079
+ };
4080
+ return /* @__PURE__ */ jsx(
4081
+ View,
4082
+ {
4083
+ className: cn(
4084
+ "w-8 h-8 rounded-full border-2 items-center justify-center",
4085
+ statusStyles2[status],
4086
+ className
4087
+ ),
4088
+ children: icon || /* @__PURE__ */ jsx(
4089
+ Text,
4090
+ {
4091
+ className: cn(
4092
+ "text-sm font-semibold",
4093
+ status === "upcoming" ? "text-text-secondary" : "text-white"
4094
+ ),
4095
+ children: status === "completed" ? "\u2713" : index + 1
4096
+ }
4097
+ )
4098
+ }
4099
+ );
4100
+ }
4101
+ function StepLabel({ status = "upcoming", className, children }) {
4102
+ const { orientation } = useContext(StepperContext);
4103
+ return /* @__PURE__ */ jsx(
4104
+ Text,
4105
+ {
4106
+ className: cn(
4107
+ "text-sm font-medium",
4108
+ orientation === "horizontal" ? "mt-2" : "ml-3",
4109
+ status === "active" ? "text-text-primary" : status === "completed" ? "text-brand-primary" : status === "error" ? "text-status-error" : "text-text-secondary",
4110
+ className
4111
+ ),
4112
+ children
4113
+ }
4114
+ );
4115
+ }
4116
+ function StepContent({ status = "upcoming", className, children }) {
4117
+ if (status !== "active") return null;
4118
+ return /* @__PURE__ */ jsx(View, { className: cn("ml-11 mt-2 pb-4", className), children });
4119
+ }
4120
+ var colorStyles7 = {
4121
+ primary: "text-text-primary",
4122
+ secondary: "text-text-secondary",
4123
+ tertiary: "text-text-tertiary",
4124
+ inherit: ""
4125
+ };
4126
+ function formatDate(value, format, isUTC) {
4127
+ const date = value instanceof Date ? value : new Date(value);
4128
+ if (isNaN(date.getTime())) {
4129
+ return "Invalid Date";
4130
+ }
4131
+ if (format === "relative") {
4132
+ return getRelativeTime(date);
4133
+ }
4134
+ const options = {};
4135
+ switch (format) {
4136
+ case "date":
4137
+ options.year = "numeric";
4138
+ options.month = "2-digit";
4139
+ options.day = "2-digit";
4140
+ break;
4141
+ case "time":
4142
+ options.hour = "2-digit";
4143
+ options.minute = "2-digit";
4144
+ break;
4145
+ case "datetime":
4146
+ options.year = "numeric";
4147
+ options.month = "2-digit";
4148
+ options.day = "2-digit";
4149
+ options.hour = "2-digit";
4150
+ options.minute = "2-digit";
4151
+ break;
4152
+ case "short":
4153
+ options.month = "short";
4154
+ options.day = "numeric";
4155
+ break;
4156
+ case "medium":
4157
+ options.month = "short";
4158
+ options.day = "numeric";
4159
+ options.year = "numeric";
4160
+ break;
4161
+ case "long":
4162
+ options.month = "long";
4163
+ options.day = "numeric";
4164
+ options.year = "numeric";
4165
+ break;
4166
+ case "full":
4167
+ options.weekday = "long";
4168
+ options.month = "long";
4169
+ options.day = "numeric";
4170
+ options.year = "numeric";
4171
+ break;
4172
+ }
4173
+ if (isUTC) {
4174
+ options.timeZone = "UTC";
4175
+ }
4176
+ return new Intl.DateTimeFormat(void 0, options).format(date);
4177
+ }
4178
+ function getRelativeTime(date) {
4179
+ const now = /* @__PURE__ */ new Date();
4180
+ const diffMs = date.getTime() - now.getTime();
4181
+ const diffSecs = Math.round(diffMs / 1e3);
4182
+ const diffMins = Math.round(diffSecs / 60);
4183
+ const diffHours = Math.round(diffMins / 60);
4184
+ const diffDays = Math.round(diffHours / 24);
4185
+ const diffWeeks = Math.round(diffDays / 7);
4186
+ const diffMonths = Math.round(diffDays / 30);
4187
+ const diffYears = Math.round(diffDays / 365);
4188
+ if (typeof Intl !== "undefined" && Intl.RelativeTimeFormat) {
4189
+ const rtf = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
4190
+ if (Math.abs(diffSecs) < 60) {
4191
+ return rtf.format(diffSecs, "second");
4192
+ }
4193
+ if (Math.abs(diffMins) < 60) {
4194
+ return rtf.format(diffMins, "minute");
4195
+ }
4196
+ if (Math.abs(diffHours) < 24) {
4197
+ return rtf.format(diffHours, "hour");
4198
+ }
4199
+ if (Math.abs(diffDays) < 7) {
4200
+ return rtf.format(diffDays, "day");
4201
+ }
4202
+ if (Math.abs(diffWeeks) < 4) {
4203
+ return rtf.format(diffWeeks, "week");
4204
+ }
4205
+ if (Math.abs(diffMonths) < 12) {
4206
+ return rtf.format(diffMonths, "month");
4207
+ }
4208
+ return rtf.format(diffYears, "year");
4209
+ }
4210
+ const absSeconds = Math.abs(diffSecs);
4211
+ const isFuture = diffMs > 0;
4212
+ const prefix = isFuture ? "in " : "";
4213
+ const suffix = isFuture ? "" : " ago";
4214
+ if (absSeconds < 60) {
4215
+ return "just now";
4216
+ }
4217
+ if (Math.abs(diffMins) < 60) {
4218
+ const mins = Math.abs(diffMins);
4219
+ return `${prefix}${mins} minute${mins === 1 ? "" : "s"}${suffix}`;
4220
+ }
4221
+ if (Math.abs(diffHours) < 24) {
4222
+ const hours = Math.abs(diffHours);
4223
+ return `${prefix}${hours} hour${hours === 1 ? "" : "s"}${suffix}`;
4224
+ }
4225
+ if (Math.abs(diffDays) < 7) {
4226
+ const days = Math.abs(diffDays);
4227
+ return `${prefix}${days} day${days === 1 ? "" : "s"}${suffix}`;
4228
+ }
4229
+ if (Math.abs(diffWeeks) < 4) {
4230
+ const weeks = Math.abs(diffWeeks);
4231
+ return `${prefix}${weeks} week${weeks === 1 ? "" : "s"}${suffix}`;
4232
+ }
4233
+ if (Math.abs(diffMonths) < 12) {
4234
+ const months = Math.abs(diffMonths);
4235
+ return `${prefix}${months} month${months === 1 ? "" : "s"}${suffix}`;
4236
+ }
4237
+ const years = Math.abs(diffYears);
4238
+ return `${prefix}${years} year${years === 1 ? "" : "s"}${suffix}`;
4239
+ }
4240
+ function DateTime({
4241
+ value,
4242
+ format = "datetime",
4243
+ customFormat,
4244
+ isUTC = false,
4245
+ fallback = "-",
4246
+ color = "inherit",
4247
+ className,
4248
+ ...props
4249
+ }) {
4250
+ if (value === null || value === void 0) {
4251
+ return /* @__PURE__ */ jsx(Text, { className: cn(colorStyles7[color], className), ...props, children: fallback });
4252
+ }
4253
+ const formattedDate = formatDate(value, format, isUTC);
4254
+ return /* @__PURE__ */ jsx(Text, { className: cn(colorStyles7[color], className), ...props, children: formattedDate });
4255
+ }
4256
+ function formatDateTime(value, format = "datetime", isUTC = false, fallback = "-") {
4257
+ if (value === null || value === void 0) {
4258
+ return fallback;
4259
+ }
4260
+ return formatDate(value, format, isUTC);
4261
+ }
4262
+
4263
+ // src/utils/colors.ts
4264
+ function getStatusColor(status) {
4265
+ return `var(--color-status-${status})`;
4266
+ }
4267
+ function getResultColor(result) {
4268
+ return `var(--color-result-${result})`;
4269
+ }
4270
+ function alpha(color, opacity) {
4271
+ const clampedOpacity = Math.max(0, Math.min(1, opacity));
4272
+ if (color.startsWith("#")) {
4273
+ const hex = color.slice(1);
4274
+ let r, g, b;
4275
+ if (hex.length === 3) {
4276
+ r = parseInt(hex[0] + hex[0], 16);
4277
+ g = parseInt(hex[1] + hex[1], 16);
4278
+ b = parseInt(hex[2] + hex[2], 16);
4279
+ } else if (hex.length === 6) {
4280
+ r = parseInt(hex.slice(0, 2), 16);
4281
+ g = parseInt(hex.slice(2, 4), 16);
4282
+ b = parseInt(hex.slice(4, 6), 16);
4283
+ } else {
4284
+ return color;
4285
+ }
4286
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
4287
+ }
4288
+ const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
4289
+ if (rgbMatch) {
4290
+ const [, r, g, b] = rgbMatch;
4291
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
4292
+ }
4293
+ const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/);
4294
+ if (rgbaMatch) {
4295
+ const [, r, g, b] = rgbaMatch;
4296
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
4297
+ }
4298
+ return color;
4299
+ }
4300
+ function getLuminance(color) {
4301
+ if (!color.startsWith("#")) return "dark";
4302
+ const hex = color.slice(1);
4303
+ let r, g, b;
4304
+ if (hex.length === 3) {
4305
+ r = parseInt(hex[0] + hex[0], 16);
4306
+ g = parseInt(hex[1] + hex[1], 16);
4307
+ b = parseInt(hex[2] + hex[2], 16);
4308
+ } else if (hex.length === 6) {
4309
+ r = parseInt(hex.slice(0, 2), 16);
4310
+ g = parseInt(hex.slice(2, 4), 16);
4311
+ b = parseInt(hex.slice(4, 6), 16);
4312
+ } else {
4313
+ return "dark";
4314
+ }
4315
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
4316
+ return luminance > 0.5 ? "light" : "dark";
4317
+ }
4318
+ function getContrastText(backgroundColor) {
4319
+ return getLuminance(backgroundColor) === "light" ? "#000000" : "#FFFFFF";
4320
+ }
4321
+
4322
+ // src/utils/form.ts
4323
+ function getFieldValidationProps(state) {
4324
+ return {
4325
+ isInvalid: state.touched && state.hasError,
4326
+ errorMessage: state.touched && state.hasError ? state.errorMessage : void 0
4327
+ };
4328
+ }
4329
+ function createFieldId(label) {
4330
+ return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
4331
+ }
4332
+ function getFieldAriaProps(props) {
4333
+ const describedBy = [];
4334
+ if (props.helperText) {
4335
+ describedBy.push(`${props.id}-helper`);
4336
+ }
4337
+ if (props.isInvalid && props.errorMessage) {
4338
+ describedBy.push(`${props.id}-error`);
4339
+ }
4340
+ return {
4341
+ "aria-invalid": props.isInvalid || void 0,
4342
+ "aria-required": props.isRequired || void 0,
4343
+ "aria-describedby": describedBy.length > 0 ? describedBy.join(" ") : void 0
4344
+ };
4345
+ }
4346
+ function isValidEmail(email) {
4347
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4348
+ return emailRegex.test(email);
4349
+ }
4350
+ function hasMinLength(value, minLength) {
4351
+ return value.length >= minLength;
4352
+ }
4353
+ function hasMaxLength(value, maxLength) {
4354
+ return value.length <= maxLength;
4355
+ }
4356
+ function isEmpty(value) {
4357
+ if (value === null || value === void 0) return true;
4358
+ if (typeof value === "string") return value.trim() === "";
4359
+ if (Array.isArray(value)) return value.length === 0;
4360
+ return false;
4361
+ }
4362
+ var validationRules = {
4363
+ required: (value) => {
4364
+ if (isEmpty(value)) {
4365
+ return "This field is required";
4366
+ }
4367
+ return void 0;
4368
+ },
4369
+ email: (value) => {
4370
+ if (value && !isValidEmail(value)) {
4371
+ return "Please enter a valid email address";
4372
+ }
4373
+ return void 0;
4374
+ },
4375
+ minLength: (min) => (value) => {
4376
+ if (value && !hasMinLength(value, min)) {
4377
+ return `Must be at least ${min} characters`;
4378
+ }
4379
+ return void 0;
4380
+ },
4381
+ maxLength: (max) => (value) => {
4382
+ if (value && !hasMaxLength(value, max)) {
4383
+ return `Must be no more than ${max} characters`;
4384
+ }
4385
+ return void 0;
4386
+ },
4387
+ pattern: (regex, message) => (value) => {
4388
+ if (value && !regex.test(value)) {
4389
+ return message;
4390
+ }
4391
+ return void 0;
4392
+ },
4393
+ match: (otherValue, fieldName) => (value) => {
4394
+ if (value !== otherValue) {
4395
+ return `Must match ${fieldName}`;
4396
+ }
4397
+ return void 0;
4398
+ }
4399
+ };
4400
+ function composeValidators(...validators) {
4401
+ return (value) => {
4402
+ for (const validator of validators) {
4403
+ const error = validator(value);
4404
+ if (error) return error;
4405
+ }
4406
+ return void 0;
4407
+ };
4408
+ }
4409
+
4410
+ export { Accordion, AccordionButton, AccordionItem, AccordionPanel, Alert, AlertDescription, AlertTitle, Autocomplete, Avatar, AvatarBadge, AvatarGroup, Badge, BadgeText, BreadcrumbItem, Breadcrumbs, Button, ButtonIcon, ButtonSpinner, ButtonText, Caption, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Checkbox, CheckboxGroup, Chip, CircularProgress, Collapse, CollapseButton, CollapseContent, DateTime, Divider, Drawer, DrawerBody, DrawerFooter, DrawerHeader, EmptyState, FormActions, FormField, FormRow, FormSection, Heading, HelpTip, Input, InputGroup, Label, LabelWithHelp, Link, Menu, MenuDivider, MenuGroup, MenuItem, MenuList, MenuTrigger, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalTitle, Overline, Paragraph, PasswordInput, Popover, PopoverCloseButton, PopoverContent, PopoverTrigger, Progress, ProgressSteps, Radio, RadioGroup, Select, Sidebar, SidebarContent, SidebarDivider, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, Skeleton, SkeletonCard, SkeletonCircle, SkeletonListItem, SkeletonText, Spinner, Step, StepContent, StepIndicator, StepLabel, Stepper, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TablePagination, TableRow, Tabs, Toast, ToastProvider, ToolbarButton, ToolbarButtonGroup, Tooltip, Typography, alpha, cn, composeValidators, createFieldId, formatDateTime, getContrastText, getFieldAriaProps, getFieldValidationProps, getLuminance, getResultColor, getStatusColor, hasMaxLength, hasMinLength, isEmpty, isValidEmail, useTable, useToast, useToolbarButton, validationRules };
4411
+ //# sourceMappingURL=index.mjs.map
4412
+ //# sourceMappingURL=index.mjs.map