@retray-dev/ui-kit 3.1.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/COMPONENTS.md +1792 -659
  2. package/README.md +8 -7
  3. package/dist/index.d.mts +269 -89
  4. package/dist/index.d.ts +269 -89
  5. package/dist/index.js +1034 -312
  6. package/dist/index.mjs +1031 -314
  7. package/package.json +3 -2
  8. package/src/components/Accordion/Accordion.tsx +1 -1
  9. package/src/components/AlertBanner/AlertBanner.tsx +50 -45
  10. package/src/components/Avatar/Avatar.tsx +61 -17
  11. package/src/components/Badge/Badge.tsx +17 -15
  12. package/src/components/Button/Button.tsx +31 -42
  13. package/src/components/Card/Card.tsx +4 -4
  14. package/src/components/CategoryStrip/CategoryStrip.tsx +185 -0
  15. package/src/components/CategoryStrip/index.ts +2 -0
  16. package/src/components/Checkbox/Checkbox.tsx +44 -16
  17. package/src/components/Chip/Chip.tsx +1 -1
  18. package/src/components/ConfirmDialog/ConfirmDialog.tsx +4 -4
  19. package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +1 -0
  20. package/src/components/CurrencyInput/CurrencyInput.tsx +6 -4
  21. package/src/components/EmptyState/EmptyState.tsx +9 -9
  22. package/src/components/IconButton/IconButton.tsx +74 -34
  23. package/src/components/Input/Input.tsx +15 -13
  24. package/src/components/LabelValue/LabelValue.tsx +1 -1
  25. package/src/components/ListItem/ListItem.tsx +5 -5
  26. package/src/components/MediaCard/MediaCard.tsx +249 -0
  27. package/src/components/MediaCard/index.ts +2 -0
  28. package/src/components/Pressable/Pressable.tsx +100 -0
  29. package/src/components/Pressable/index.ts +1 -0
  30. package/src/components/Progress/Progress.tsx +14 -7
  31. package/src/components/RadioGroup/RadioGroup.tsx +1 -1
  32. package/src/components/Select/Select.tsx +5 -5
  33. package/src/components/Sheet/Sheet.tsx +3 -9
  34. package/src/components/Skeleton/Skeleton.tsx +34 -7
  35. package/src/components/Slider/Slider.tsx +2 -2
  36. package/src/components/Spinner/Spinner.tsx +1 -1
  37. package/src/components/Switch/Switch.tsx +31 -4
  38. package/src/components/Tabs/Tabs.tsx +63 -45
  39. package/src/components/Text/Text.tsx +59 -10
  40. package/src/components/Textarea/Textarea.tsx +4 -3
  41. package/src/components/Toast/Toast.tsx +77 -36
  42. package/src/components/Toggle/Toggle.tsx +3 -3
  43. package/src/index.ts +8 -2
  44. package/src/theme/ThemeProvider.tsx +11 -10
  45. package/src/theme/colorUtils.ts +80 -0
  46. package/src/theme/colors.ts +76 -35
  47. package/src/theme/index.ts +2 -2
  48. package/src/theme/types.ts +27 -13
  49. package/src/tokens.ts +150 -13
  50. package/src/utils/hover.ts +25 -0
package/dist/index.js CHANGED
@@ -33,61 +33,125 @@ var RNSlider__default = /*#__PURE__*/_interopDefault(RNSlider);
33
33
 
34
34
  // src/theme/ThemeProvider.tsx
35
35
 
36
+ // src/theme/colorUtils.ts
37
+ function hexToRgb(hex) {
38
+ const clean = hex.replace("#", "");
39
+ const full = clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean;
40
+ if (full.length !== 6) return null;
41
+ return {
42
+ r: parseInt(full.slice(0, 2), 16),
43
+ g: parseInt(full.slice(2, 4), 16),
44
+ b: parseInt(full.slice(4, 6), 16)
45
+ };
46
+ }
47
+ function componentToHex(c) {
48
+ return Math.round(Math.max(0, Math.min(255, c))).toString(16).padStart(2, "0");
49
+ }
50
+ function rgbToHex(r, g, b) {
51
+ return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
52
+ }
53
+ function withAlphaOnWhite(hex, alpha) {
54
+ const rgb = hexToRgb(hex);
55
+ if (!rgb) return hex;
56
+ const r = rgb.r * alpha + 255 * (1 - alpha);
57
+ const g = rgb.g * alpha + 255 * (1 - alpha);
58
+ const b = rgb.b * alpha + 255 * (1 - alpha);
59
+ return rgbToHex(r, g, b);
60
+ }
61
+ function withAlphaOnDark(hex, alpha, bgHex = "#0f0f0f") {
62
+ const rgb = hexToRgb(hex);
63
+ const bg = hexToRgb(bgHex);
64
+ if (!rgb || !bg) return hex;
65
+ const r = rgb.r * alpha + bg.r * (1 - alpha);
66
+ const g = rgb.g * alpha + bg.g * (1 - alpha);
67
+ const b = rgb.b * alpha + bg.b * (1 - alpha);
68
+ return rgbToHex(r, g, b);
69
+ }
70
+ function mixWithBackground(fgHex, bgHex, opacity) {
71
+ const fg = hexToRgb(fgHex);
72
+ const bg = hexToRgb(bgHex);
73
+ if (!fg || !bg) return fgHex;
74
+ const r = fg.r * opacity + bg.r * (1 - opacity);
75
+ const g = fg.g * opacity + bg.g * (1 - opacity);
76
+ const b = fg.b * opacity + bg.b * (1 - opacity);
77
+ return rgbToHex(r, g, b);
78
+ }
79
+ function lighten(hex, amount) {
80
+ return withAlphaOnWhite(hex, 1 - amount);
81
+ }
82
+ function darken(hex, amount) {
83
+ const rgb = hexToRgb(hex);
84
+ if (!rgb) return hex;
85
+ return rgbToHex(rgb.r * (1 - amount), rgb.g * (1 - amount), rgb.b * (1 - amount));
86
+ }
87
+
36
88
  // src/theme/colors.ts
37
89
  var defaultLight = {
38
90
  background: "#ffffff",
39
- foreground: "#171717",
91
+ foreground: "#222222",
92
+ // Airbnb ink — deep near-black, never pure black
40
93
  card: "#ffffff",
41
- cardForeground: "#171717",
42
94
  primary: "#1a1a1a",
95
+ // Near-black primary — clean, premium default
43
96
  primaryForeground: "#ffffff",
44
- secondary: "#f1f1f1",
45
- secondaryForeground: "#171717",
46
- muted: "#f1f1f1",
47
- mutedForeground: "#a2a2a2",
48
- accent: "#e4e4e4",
49
- accentForeground: "#171717",
50
- destructive: "#ef4444",
97
+ border: "#dddddd",
98
+ // Airbnb hairline — light, airy
99
+ destructive: "#e53935",
51
100
  destructiveForeground: "#ffffff",
52
- border: "#e5e5e5",
53
- input: "#e5e5e5",
54
- ring: "#1a1a1a",
55
101
  success: "#1a7a45",
56
102
  successForeground: "#ffffff",
57
- destructiveTint: "#fff5f5",
58
- destructiveBorder: "#fecaca",
59
- successTint: "#f0fdf4",
60
- successBorder: "#bbf7d0"
103
+ warning: "#e67e00",
104
+ warningForeground: "#ffffff"
61
105
  };
62
106
  var defaultDark = {
63
107
  background: "#0f0f0f",
64
108
  foreground: "#fafafa",
65
109
  card: "#1c1c1c",
66
- cardForeground: "#fafafa",
67
110
  primary: "#fafafa",
68
111
  primaryForeground: "#0f0f0f",
69
- secondary: "#272727",
70
- secondaryForeground: "#fafafa",
71
- muted: "#272727",
72
- mutedForeground: "#9a9a9a",
73
- accent: "#2e2e2e",
74
- accentForeground: "#fafafa",
75
- destructive: "#dc2626",
76
- destructiveForeground: "#ffffff",
77
112
  border: "#303030",
78
- input: "#2a2a2a",
79
- ring: "#fafafa",
80
- success: "#166534",
113
+ destructive: "#ef5350",
114
+ destructiveForeground: "#ffffff",
115
+ success: "#2e7d52",
81
116
  successForeground: "#ffffff",
82
- destructiveTint: "#3b0a0a",
83
- destructiveBorder: "#7f1d1d",
84
- successTint: "#052e16",
85
- successBorder: "#166534"
117
+ warning: "#f57c00",
118
+ warningForeground: "#ffffff"
86
119
  };
120
+ function deriveColors(t, scheme) {
121
+ const dark = scheme === "dark";
122
+ const bg = t.background;
123
+ const foregroundSubtle = mixWithBackground(t.foreground, bg, 0.55);
124
+ const foregroundMuted = mixWithBackground(t.foreground, bg, 0.38);
125
+ const surface = dark ? lighten(bg, -0.06) : darken(bg, 0.04);
126
+ const surfaceStrong = dark ? lighten(bg, -0.12) : darken(bg, 0.08);
127
+ const destructiveTint = dark ? withAlphaOnDark(t.destructive, 0.15, bg) : withAlphaOnWhite(t.destructive, 0.08);
128
+ const destructiveBorder = dark ? withAlphaOnDark(t.destructive, 0.45, bg) : withAlphaOnWhite(t.destructive, 0.3);
129
+ const successTint = dark ? withAlphaOnDark(t.success, 0.15, bg) : withAlphaOnWhite(t.success, 0.08);
130
+ const successBorder = dark ? withAlphaOnDark(t.success, 0.45, bg) : withAlphaOnWhite(t.success, 0.3);
131
+ const warningTint = dark ? withAlphaOnDark(t.warning, 0.15, bg) : withAlphaOnWhite(t.warning, 0.08);
132
+ const warningBorder = dark ? withAlphaOnDark(t.warning, 0.45, bg) : withAlphaOnWhite(t.warning, 0.3);
133
+ return {
134
+ ...t,
135
+ foregroundSubtle,
136
+ foregroundMuted,
137
+ surface,
138
+ surfaceStrong,
139
+ destructiveTint,
140
+ destructiveBorder,
141
+ successTint,
142
+ successBorder,
143
+ warningTint,
144
+ warningBorder,
145
+ ring: t.primary,
146
+ // focus ring always = primary
147
+ input: t.border
148
+ // input border always = border
149
+ };
150
+ }
87
151
 
88
152
  // src/theme/ThemeProvider.tsx
89
153
  var ThemeContext = React25.createContext({
90
- colors: defaultLight,
154
+ colors: deriveColors(defaultLight, "light"),
91
155
  colorScheme: "light"
92
156
  });
93
157
  function ThemeProvider({ children, theme, colorScheme = "system" }) {
@@ -96,7 +160,8 @@ function ThemeProvider({ children, theme, colorScheme = "system" }) {
96
160
  const colors = React25.useMemo(() => {
97
161
  const base = resolvedScheme === "dark" ? defaultDark : defaultLight;
98
162
  const override = resolvedScheme === "dark" ? theme?.dark : theme?.light;
99
- return override ? { ...base, ...override } : base;
163
+ const merged = override ? { ...base, ...override } : base;
164
+ return deriveColors(merged, resolvedScheme);
100
165
  }, [resolvedScheme, theme]);
101
166
  return /* @__PURE__ */ React25__default.default.createElement(ThemeContext.Provider, { value: { colors, colorScheme: resolvedScheme } }, children);
102
167
  }
@@ -176,17 +241,194 @@ function renderIcon(name, size, color) {
176
241
  return React25__default.default.createElement(Icon, { name, size, color });
177
242
  }
178
243
 
244
+ // src/tokens.ts
245
+ var SPACING = {
246
+ xxs: 2,
247
+ xs: 4,
248
+ sm: 8,
249
+ md: 12,
250
+ base: 16,
251
+ lg: 24,
252
+ xl: 32,
253
+ xxl: 48,
254
+ section: 64
255
+ };
256
+ var ICON_SIZES = {
257
+ sm: 14,
258
+ md: 18,
259
+ lg: 22,
260
+ xl: 28,
261
+ "2xl": 32
262
+ };
263
+ var RADIUS = {
264
+ none: 0,
265
+ xs: 4,
266
+ sm: 8,
267
+ md: 14,
268
+ lg: 20,
269
+ xl: 32,
270
+ full: 9999
271
+ };
272
+ var SHADOWS = {
273
+ sm: {
274
+ shadowColor: "#000",
275
+ shadowOffset: { width: 0, height: 1 },
276
+ shadowOpacity: 0.06,
277
+ shadowRadius: 4,
278
+ elevation: 2
279
+ },
280
+ md: {
281
+ shadowColor: "#000",
282
+ shadowOffset: { width: 0, height: 2 },
283
+ shadowOpacity: 0.1,
284
+ shadowRadius: 8,
285
+ elevation: 5
286
+ },
287
+ lg: {
288
+ shadowColor: "#000",
289
+ shadowOffset: { width: 0, height: 6 },
290
+ shadowOpacity: 0.16,
291
+ shadowRadius: 16,
292
+ elevation: 10
293
+ },
294
+ xl: {
295
+ shadowColor: "#000",
296
+ shadowOffset: { width: 0, height: 12 },
297
+ shadowOpacity: 0.24,
298
+ shadowRadius: 24,
299
+ elevation: 18
300
+ }
301
+ };
302
+ var BREAKPOINTS = {
303
+ wide: 700
304
+ };
305
+ var TYPOGRAPHY = {
306
+ "display-hero": {
307
+ fontFamily: "Poppins-Bold",
308
+ fontSize: 64,
309
+ fontWeight: "700",
310
+ lineHeight: 70,
311
+ letterSpacing: -1
312
+ },
313
+ "display-xl": {
314
+ fontFamily: "Poppins-Bold",
315
+ fontSize: 28,
316
+ fontWeight: "700",
317
+ lineHeight: 40,
318
+ letterSpacing: 0
319
+ },
320
+ "display-lg": {
321
+ fontFamily: "Poppins-Medium",
322
+ fontSize: 22,
323
+ fontWeight: "500",
324
+ lineHeight: 26,
325
+ letterSpacing: -0.44
326
+ },
327
+ "display-md": {
328
+ fontFamily: "Poppins-Bold",
329
+ fontSize: 21,
330
+ fontWeight: "700",
331
+ lineHeight: 30,
332
+ letterSpacing: 0
333
+ },
334
+ "display-sm": {
335
+ fontFamily: "Poppins-SemiBold",
336
+ fontSize: 20,
337
+ fontWeight: "600",
338
+ lineHeight: 24,
339
+ letterSpacing: -0.18
340
+ },
341
+ "title-md": {
342
+ fontFamily: "Poppins-SemiBold",
343
+ fontSize: 16,
344
+ fontWeight: "600",
345
+ lineHeight: 20,
346
+ letterSpacing: 0
347
+ },
348
+ "title-sm": {
349
+ fontFamily: "Poppins-Medium",
350
+ fontSize: 16,
351
+ fontWeight: "500",
352
+ lineHeight: 20,
353
+ letterSpacing: 0
354
+ },
355
+ "body-md": {
356
+ fontFamily: "Poppins-Regular",
357
+ fontSize: 16,
358
+ fontWeight: "400",
359
+ lineHeight: 24,
360
+ letterSpacing: 0
361
+ },
362
+ "body-sm": {
363
+ fontFamily: "Poppins-Regular",
364
+ fontSize: 14,
365
+ fontWeight: "400",
366
+ lineHeight: 20,
367
+ letterSpacing: 0
368
+ },
369
+ caption: {
370
+ fontFamily: "Poppins-Medium",
371
+ fontSize: 14,
372
+ fontWeight: "500",
373
+ lineHeight: 18,
374
+ letterSpacing: 0
375
+ },
376
+ "caption-sm": {
377
+ fontFamily: "Poppins-Regular",
378
+ fontSize: 13,
379
+ fontWeight: "400",
380
+ lineHeight: 16,
381
+ letterSpacing: 0
382
+ },
383
+ "badge-text": {
384
+ fontFamily: "Poppins-SemiBold",
385
+ fontSize: 11,
386
+ fontWeight: "600",
387
+ lineHeight: 13,
388
+ letterSpacing: 0
389
+ },
390
+ "micro-label": {
391
+ fontFamily: "Poppins-Bold",
392
+ fontSize: 12,
393
+ fontWeight: "700",
394
+ lineHeight: 16,
395
+ letterSpacing: 0
396
+ },
397
+ "uppercase-tag": {
398
+ fontFamily: "Poppins-Bold",
399
+ fontSize: 8,
400
+ fontWeight: "700",
401
+ lineHeight: 10,
402
+ letterSpacing: 0.32,
403
+ textTransform: "uppercase"
404
+ },
405
+ "button-lg": {
406
+ fontFamily: "Poppins-Medium",
407
+ fontSize: 16,
408
+ fontWeight: "500",
409
+ lineHeight: 20,
410
+ letterSpacing: 0
411
+ },
412
+ "button-sm": {
413
+ fontFamily: "Poppins-Medium",
414
+ fontSize: 14,
415
+ fontWeight: "500",
416
+ lineHeight: 18,
417
+ letterSpacing: 0
418
+ }
419
+ };
420
+
179
421
  // src/components/Button/Button.tsx
180
422
  var nativeDriver = reactNative.Platform.OS !== "web";
181
423
  var containerSizeStyles = {
182
- sm: { paddingHorizontal: s(12), paddingVertical: vs(10), minHeight: 44 },
183
- md: { paddingHorizontal: s(16), paddingVertical: vs(10), minHeight: 44 },
184
- lg: { paddingHorizontal: s(20), paddingVertical: vs(12), minHeight: 48 }
424
+ sm: { paddingHorizontal: s(16), paddingVertical: vs(10), minHeight: 40 },
425
+ md: { paddingHorizontal: s(24), paddingVertical: vs(14), minHeight: 48 },
426
+ lg: { paddingHorizontal: s(28), paddingVertical: vs(16), minHeight: 56 }
185
427
  };
186
428
  var labelSizeStyles = {
187
- sm: { fontSize: ms(13) },
188
- md: { fontSize: ms(15) },
189
- lg: { fontSize: ms(16) }
429
+ sm: { ...TYPOGRAPHY["button-sm"], fontSize: ms(TYPOGRAPHY["button-sm"].fontSize) },
430
+ md: { ...TYPOGRAPHY["button-lg"], fontSize: ms(TYPOGRAPHY["button-lg"].fontSize) },
431
+ lg: { ...TYPOGRAPHY["button-lg"], fontSize: ms(TYPOGRAPHY["button-lg"].fontSize + 1) }
190
432
  };
191
433
  var iconSizeMap = { sm: 16, md: 18, lg: 20 };
192
434
  function Button({
@@ -209,12 +451,7 @@ function Button({
209
451
  const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
210
452
  const handlePressIn = () => {
211
453
  if (isDisabled) return;
212
- reactNative.Animated.spring(scale2, {
213
- toValue: 0.95,
214
- useNativeDriver: nativeDriver,
215
- speed: 40,
216
- bounciness: 0
217
- }).start();
454
+ reactNative.Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver, speed: 40, bounciness: 0 }).start();
218
455
  };
219
456
  const handlePressOut = () => {
220
457
  reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver, speed: 40, bounciness: 4 }).start();
@@ -225,20 +462,18 @@ function Button({
225
462
  };
226
463
  const containerVariantStyle = {
227
464
  primary: { backgroundColor: colors.primary },
228
- secondary: { backgroundColor: colors.secondary },
229
- outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.border },
230
- ghost: { backgroundColor: "transparent" },
465
+ secondary: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.primary },
466
+ text: { backgroundColor: "transparent" },
231
467
  destructive: { backgroundColor: colors.destructive }
232
468
  }[variant];
233
469
  const labelVariantStyle = {
234
470
  primary: { color: colors.primaryForeground },
235
- secondary: { color: colors.secondaryForeground },
236
- outline: { color: colors.foreground },
237
- ghost: { color: colors.foreground },
471
+ secondary: { color: colors.primary },
472
+ text: { color: colors.foreground },
238
473
  destructive: { color: colors.destructiveForeground }
239
474
  }[variant];
240
475
  const effectiveIcon = iconName ? renderIcon(iconName, iconSizeMap[size], iconColor ?? labelVariantStyle.color) : typeof icon === "function" ? icon({ label, size, variant }) : icon;
241
- const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" || variant === "secondary" ? colors.primaryForeground : colors.foreground;
476
+ const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.foreground;
242
477
  return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: [fullWidth && styles.fullWidth, { transform: [{ scale: scale2 }] }] }, /* @__PURE__ */ React25__default.default.createElement(
243
478
  reactNative.TouchableOpacity,
244
479
  {
@@ -258,12 +493,20 @@ function Button({
258
493
  onPressOut: handlePressOut,
259
494
  ...props
260
495
  },
261
- loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0], allowFontScaling: true }, label), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon))
496
+ loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React25__default.default.createElement(
497
+ reactNative.Text,
498
+ {
499
+ style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
500
+ allowFontScaling: true
501
+ },
502
+ label
503
+ ), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon))
262
504
  ));
263
505
  }
264
506
  var styles = reactNative.StyleSheet.create({
265
507
  base: {
266
- borderRadius: 8,
508
+ borderRadius: RADIUS.xl,
509
+ // 32px — pill-shaped primary CTA (Airbnb spec)
267
510
  alignItems: "center",
268
511
  justifyContent: "center",
269
512
  flexDirection: "row"
@@ -272,18 +515,18 @@ var styles = reactNative.StyleSheet.create({
272
515
  width: "100%"
273
516
  },
274
517
  disabled: {
275
- opacity: 0.5
518
+ opacity: 0.45
276
519
  },
277
520
  label: {
278
- fontFamily: "Poppins-SemiBold"
521
+ fontFamily: "Poppins-Medium"
279
522
  },
280
523
  labelWithIcon: {
281
- marginHorizontal: s(8)
524
+ marginHorizontal: s(6)
282
525
  }
283
526
  });
284
527
  var nativeDriver2 = reactNative.Platform.OS !== "web";
285
528
  var sizeMap = {
286
- sm: { container: s(40), icon: 18 },
529
+ sm: { container: s(32), icon: 16 },
287
530
  md: { container: s(44), icon: 20 },
288
531
  lg: { container: s(52), icon: 24 }
289
532
  };
@@ -294,6 +537,7 @@ function IconButton({
294
537
  variant = "primary",
295
538
  size = "md",
296
539
  loading = false,
540
+ badge,
297
541
  disabled,
298
542
  style,
299
543
  onPress,
@@ -304,20 +548,10 @@ function IconButton({
304
548
  const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
305
549
  const handlePressIn = () => {
306
550
  if (isDisabled) return;
307
- reactNative.Animated.spring(scale2, {
308
- toValue: 0.95,
309
- useNativeDriver: nativeDriver2,
310
- speed: 40,
311
- bounciness: 0
312
- }).start();
551
+ reactNative.Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver2, speed: 40, bounciness: 0 }).start();
313
552
  };
314
553
  const handlePressOut = () => {
315
- reactNative.Animated.spring(scale2, {
316
- toValue: 1,
317
- useNativeDriver: nativeDriver2,
318
- speed: 40,
319
- bounciness: 4
320
- }).start();
554
+ reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver2, speed: 40, bounciness: 4 }).start();
321
555
  };
322
556
  const handlePress = (e) => {
323
557
  impactLight();
@@ -325,22 +559,25 @@ function IconButton({
325
559
  };
326
560
  const containerVariantStyle = {
327
561
  primary: { backgroundColor: colors.primary },
328
- secondary: { backgroundColor: colors.secondary },
562
+ secondary: { backgroundColor: colors.surface },
329
563
  outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.border },
330
- ghost: { backgroundColor: "transparent" },
564
+ text: { backgroundColor: "transparent" },
331
565
  destructive: { backgroundColor: colors.destructive }
332
566
  }[variant];
333
567
  const defaultIconColor = {
334
568
  primary: colors.primaryForeground,
335
- secondary: colors.secondaryForeground,
569
+ secondary: colors.foreground,
336
570
  outline: colors.foreground,
337
- ghost: colors.foreground,
571
+ text: colors.foreground,
338
572
  destructive: colors.destructiveForeground
339
573
  }[variant];
340
- const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" || variant === "secondary" ? colors.primaryForeground : colors.foreground;
574
+ const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.foreground;
341
575
  const { container: containerSize, icon: iconSize } = sizeMap[size];
342
576
  const resolvedIcon = iconName ? renderIcon(iconName, iconSize, iconColor ?? defaultIconColor) : icon;
343
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { transform: [{ scale: scale2 }] } }, /* @__PURE__ */ React25__default.default.createElement(
577
+ const showBadge = badge !== void 0 && badge !== false && badge !== 0;
578
+ const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
579
+ const showCount = typeof badge === "number" && badge > 0;
580
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: [styles2.wrapper, { transform: [{ scale: scale2 }] }] }, /* @__PURE__ */ React25__default.default.createElement(
344
581
  reactNative.TouchableOpacity,
345
582
  {
346
583
  style: [
@@ -359,33 +596,93 @@ function IconButton({
359
596
  ...props
360
597
  },
361
598
  loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
362
- ));
599
+ ), showBadge && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [
600
+ styles2.badge,
601
+ { backgroundColor: colors.primary },
602
+ showCount ? styles2.badgeCount : styles2.badgeDot
603
+ ] }, showCount && /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles2.badgeText, { color: colors.primaryForeground }] }, badgeCount)));
363
604
  }
364
605
  var styles2 = reactNative.StyleSheet.create({
606
+ wrapper: {
607
+ alignSelf: "flex-start"
608
+ },
365
609
  base: {
366
- borderRadius: 999,
610
+ borderRadius: 9999,
367
611
  alignItems: "center",
368
612
  justifyContent: "center"
369
613
  },
370
614
  disabled: {
371
- opacity: 0.5
615
+ opacity: 0.45
616
+ },
617
+ badge: {
618
+ position: "absolute",
619
+ top: -2,
620
+ right: -2,
621
+ alignItems: "center",
622
+ justifyContent: "center"
623
+ },
624
+ badgeDot: {
625
+ width: 8,
626
+ height: 8,
627
+ borderRadius: 9999
628
+ },
629
+ badgeCount: {
630
+ minWidth: 16,
631
+ height: 16,
632
+ borderRadius: 9999,
633
+ paddingHorizontal: 3
634
+ },
635
+ badgeText: {
636
+ fontFamily: "Poppins-Bold",
637
+ fontSize: ms(9),
638
+ lineHeight: 14
372
639
  }
373
640
  });
374
641
  var variantStyles = {
375
- h1: { fontFamily: "Poppins-Bold", fontSize: ms(40), lineHeight: mvs(52) },
376
- h2: { fontFamily: "Poppins-Bold", fontSize: ms(28), lineHeight: mvs(36) },
377
- h3: { fontFamily: "Poppins-SemiBold", fontSize: ms(22), lineHeight: mvs(30) },
378
- body: { fontFamily: "Poppins-Regular", fontSize: ms(17), lineHeight: mvs(26) },
379
- caption: { fontFamily: "Poppins-Regular", fontSize: ms(13), lineHeight: mvs(20) },
380
- label: { fontFamily: "Poppins-Medium", fontSize: ms(15), lineHeight: mvs(22) }
642
+ "display-hero": { ...TYPOGRAPHY["display-hero"], fontSize: ms(TYPOGRAPHY["display-hero"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-hero"].lineHeight) },
643
+ "display-xl": { ...TYPOGRAPHY["display-xl"], fontSize: ms(TYPOGRAPHY["display-xl"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-xl"].lineHeight) },
644
+ "display-lg": { ...TYPOGRAPHY["display-lg"], fontSize: ms(TYPOGRAPHY["display-lg"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-lg"].lineHeight) },
645
+ "display-md": { ...TYPOGRAPHY["display-md"], fontSize: ms(TYPOGRAPHY["display-md"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-md"].lineHeight) },
646
+ "display-sm": { ...TYPOGRAPHY["display-sm"], fontSize: ms(TYPOGRAPHY["display-sm"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-sm"].lineHeight) },
647
+ "title-md": { ...TYPOGRAPHY["title-md"], fontSize: ms(TYPOGRAPHY["title-md"].fontSize), lineHeight: mvs(TYPOGRAPHY["title-md"].lineHeight) },
648
+ "title-sm": { ...TYPOGRAPHY["title-sm"], fontSize: ms(TYPOGRAPHY["title-sm"].fontSize), lineHeight: mvs(TYPOGRAPHY["title-sm"].lineHeight) },
649
+ "body-md": { ...TYPOGRAPHY["body-md"], fontSize: ms(TYPOGRAPHY["body-md"].fontSize), lineHeight: mvs(TYPOGRAPHY["body-md"].lineHeight) },
650
+ "body-sm": { ...TYPOGRAPHY["body-sm"], fontSize: ms(TYPOGRAPHY["body-sm"].fontSize), lineHeight: mvs(TYPOGRAPHY["body-sm"].lineHeight) },
651
+ caption: { ...TYPOGRAPHY["caption"], fontSize: ms(TYPOGRAPHY["caption"].fontSize), lineHeight: mvs(TYPOGRAPHY["caption"].lineHeight) },
652
+ "caption-sm": { ...TYPOGRAPHY["caption-sm"], fontSize: ms(TYPOGRAPHY["caption-sm"].fontSize), lineHeight: mvs(TYPOGRAPHY["caption-sm"].lineHeight) },
653
+ "badge-text": { ...TYPOGRAPHY["badge-text"], fontSize: ms(TYPOGRAPHY["badge-text"].fontSize), lineHeight: mvs(TYPOGRAPHY["badge-text"].lineHeight) },
654
+ "micro-label": { ...TYPOGRAPHY["micro-label"], fontSize: ms(TYPOGRAPHY["micro-label"].fontSize), lineHeight: mvs(TYPOGRAPHY["micro-label"].lineHeight) },
655
+ "uppercase-tag": { ...TYPOGRAPHY["uppercase-tag"], fontSize: ms(TYPOGRAPHY["uppercase-tag"].fontSize), lineHeight: mvs(TYPOGRAPHY["uppercase-tag"].lineHeight) },
656
+ "button-lg": { ...TYPOGRAPHY["button-lg"], fontSize: ms(TYPOGRAPHY["button-lg"].fontSize), lineHeight: mvs(TYPOGRAPHY["button-lg"].lineHeight) },
657
+ "button-sm": { ...TYPOGRAPHY["button-sm"], fontSize: ms(TYPOGRAPHY["button-sm"].fontSize), lineHeight: mvs(TYPOGRAPHY["button-sm"].lineHeight) }
381
658
  };
382
- function Text2({ variant = "body", color, style, children, ...props }) {
659
+ var defaultColorVariant = {
660
+ "display-hero": "foreground",
661
+ "display-xl": "foreground",
662
+ "display-lg": "foreground",
663
+ "display-md": "foreground",
664
+ "display-sm": "foreground",
665
+ "title-md": "foreground",
666
+ "title-sm": "foreground",
667
+ "body-md": "foregroundSubtle",
668
+ // running text — slightly softer
669
+ "body-sm": "foregroundSubtle",
670
+ caption: "foregroundMuted",
671
+ "caption-sm": "foregroundMuted",
672
+ "badge-text": "foreground",
673
+ "micro-label": "foreground",
674
+ "uppercase-tag": "foregroundMuted",
675
+ "button-lg": "foreground",
676
+ "button-sm": "foreground"
677
+ };
678
+ function Text3({ variant = "body-md", color, style, children, ...props }) {
383
679
  const { colors } = useTheme();
384
- const defaultColor = variant === "caption" ? colors.mutedForeground : colors.foreground;
680
+ const colorKey = defaultColorVariant[variant] ?? "foreground";
681
+ const resolvedColor = color ?? colors[colorKey];
385
682
  return /* @__PURE__ */ React25__default.default.createElement(
386
683
  reactNative.Text,
387
684
  {
388
- style: [variantStyles[variant], { color: color ?? defaultColor }, style],
685
+ style: [variantStyles[variant], { color: resolvedColor }, style],
389
686
  allowFontScaling: true,
390
687
  ...props
391
688
  },
@@ -399,21 +696,21 @@ function Input({ label, error, hint, prefix, suffix, prefixStyle, suffixStyle, p
399
696
  const [showPassword, setShowPassword] = React25.useState(false);
400
697
  const isPassword = type === "password";
401
698
  const effectiveSecure = isPassword ? !showPassword : secureTextEntry;
402
- const effectivePrefix = prefixIcon ? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.mutedForeground) : prefix;
403
- const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { onPress: () => setShowPassword(!showPassword), style: styles3.passwordToggle, activeOpacity: 0.6 }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.mutedForeground })) : suffixIcon ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.mutedForeground) : suffix;
699
+ const effectivePrefix = prefixIcon ? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.foregroundMuted) : prefix;
700
+ const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { onPress: () => setShowPassword(!showPassword), style: styles3.passwordToggle, activeOpacity: 0.6 }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.foregroundMuted })) : suffixIcon ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted) : suffix;
404
701
  return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles3.container, containerStyle] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React25__default.default.createElement(
405
702
  reactNative.View,
406
703
  {
407
704
  style: [
408
705
  styles3.inputWrapper,
409
706
  {
410
- borderColor: error ? colors.destructive : focused ? colors.ring ?? colors.primary : colors.border,
707
+ borderColor: error ? colors.destructive : focused ? colors.primary : colors.border,
411
708
  backgroundColor: colors.background
412
709
  },
413
710
  inputWrapperStyle
414
711
  ]
415
712
  },
416
- effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.prefixText, { color: colors.mutedForeground }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles3.prefixContainer }, effectivePrefix) : null,
713
+ effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.prefixText, { color: colors.foregroundMuted }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles3.prefixContainer }, effectivePrefix) : null,
417
714
  /* @__PURE__ */ React25__default.default.createElement(
418
715
  reactNative.TextInput,
419
716
  {
@@ -433,14 +730,14 @@ function Input({ label, error, hint, prefix, suffix, prefixStyle, suffixStyle, p
433
730
  setFocused(false);
434
731
  onBlur?.(e);
435
732
  },
436
- placeholderTextColor: colors.mutedForeground,
733
+ placeholderTextColor: colors.foregroundMuted,
437
734
  allowFontScaling: true,
438
735
  secureTextEntry: effectiveSecure,
439
736
  ...props
440
737
  }
441
738
  ),
442
- effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.suffixText, { color: colors.mutedForeground }, suffixStyle], allowFontScaling: true }, effectiveSuffix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles3.suffixContainer }, effectiveSuffix) : null
443
- ), error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.helperText, { color: colors.mutedForeground }], allowFontScaling: true }, hint) : null);
739
+ effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.suffixText, { color: colors.foregroundMuted }, suffixStyle], allowFontScaling: true }, effectiveSuffix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles3.suffixContainer }, effectiveSuffix) : null
740
+ ), error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
444
741
  }
445
742
  var styles3 = reactNative.StyleSheet.create({
446
743
  container: {
@@ -448,21 +745,24 @@ var styles3 = reactNative.StyleSheet.create({
448
745
  },
449
746
  label: {
450
747
  fontFamily: "Poppins-Medium",
451
- fontSize: ms(13)
748
+ fontSize: ms(14)
749
+ // caption size for input labels
452
750
  },
453
751
  inputWrapper: {
454
752
  flexDirection: "row",
455
753
  alignItems: "center",
456
- borderWidth: 1,
457
- borderRadius: ms(8),
754
+ borderWidth: 2,
755
+ borderRadius: 8,
458
756
  paddingHorizontal: s(14),
459
- paddingVertical: vs(11)
757
+ paddingVertical: vs(11),
758
+ minHeight: 48
460
759
  },
461
760
  input: {
462
761
  fontFamily: "Poppins-Regular",
463
762
  flex: 1,
464
- fontSize: ms(15),
465
- paddingVertical: 0
763
+ fontSize: ms(16),
764
+ paddingVertical: vs(2),
765
+ includeFontPadding: false
466
766
  },
467
767
  prefixContainer: {
468
768
  marginRight: s(8)
@@ -508,23 +808,25 @@ function Badge({ label, children, variant = "default", size = "md", icon, iconNa
508
808
  const { colors } = useTheme();
509
809
  const containerStyle = {
510
810
  default: { backgroundColor: colors.primary },
511
- secondary: { backgroundColor: colors.secondary },
811
+ secondary: { backgroundColor: colors.surface },
512
812
  destructive: { backgroundColor: colors.destructive },
513
813
  outline: { backgroundColor: "transparent", borderWidth: 1, borderColor: colors.border },
514
814
  success: { backgroundColor: colors.success },
515
- warning: { backgroundColor: "#f59e0b" },
815
+ warning: { backgroundColor: colors.warning },
516
816
  successOutline: { backgroundColor: colors.successTint, borderWidth: 1, borderColor: colors.successBorder },
517
- destructiveOutline: { backgroundColor: colors.destructiveTint, borderWidth: 1, borderColor: colors.destructiveBorder }
817
+ destructiveOutline: { backgroundColor: colors.destructiveTint, borderWidth: 1, borderColor: colors.destructiveBorder },
818
+ warningOutline: { backgroundColor: colors.warningTint, borderWidth: 1, borderColor: colors.warningBorder }
518
819
  }[variant];
519
820
  const textColor = {
520
821
  default: colors.primaryForeground,
521
- secondary: colors.secondaryForeground,
822
+ secondary: colors.foreground,
522
823
  destructive: colors.destructiveForeground,
523
824
  outline: colors.foreground,
524
825
  success: colors.successForeground,
525
- warning: "#ffffff",
826
+ warning: colors.warningForeground,
526
827
  successOutline: colors.success,
527
- destructiveOutline: colors.destructive
828
+ destructiveOutline: colors.destructive,
829
+ warningOutline: colors.warning
528
830
  }[variant];
529
831
  const effectiveIcon = iconName ? renderIcon(iconName, sizeIconSize[size], iconColor ?? textColor) : icon;
530
832
  const content = children ?? label;
@@ -585,7 +887,7 @@ function Card({ children, variant = "elevated", onPress, style }) {
585
887
  elevation: 0
586
888
  },
587
889
  filled: {
588
- backgroundColor: colors.accent,
890
+ backgroundColor: colors.surfaceStrong,
589
891
  borderColor: colors.border,
590
892
  shadowOpacity: 0,
591
893
  elevation: 0
@@ -612,11 +914,11 @@ function CardHeader({ children, style }) {
612
914
  }
613
915
  function CardTitle({ children, style }) {
614
916
  const { colors } = useTheme();
615
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles5.title, { color: colors.cardForeground }, style], allowFontScaling: true }, children);
917
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles5.title, { color: colors.foreground }, style], allowFontScaling: true }, children);
616
918
  }
617
919
  function CardDescription({ children, style }) {
618
920
  const { colors } = useTheme();
619
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles5.description, { color: colors.mutedForeground }, style], allowFontScaling: true }, children);
921
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles5.description, { color: colors.foregroundMuted }, style], allowFontScaling: true }, children);
620
922
  }
621
923
  function CardContent({ children, style }) {
622
924
  return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles5.content, style] }, children);
@@ -626,7 +928,8 @@ function CardFooter({ children, style }) {
626
928
  }
627
929
  var styles5 = reactNative.StyleSheet.create({
628
930
  card: {
629
- borderRadius: ms(12),
931
+ borderRadius: 14,
932
+ // RADIUS.md — Airbnb property card spec
630
933
  borderWidth: 1
631
934
  },
632
935
  header: {
@@ -695,7 +998,7 @@ function Spinner({ size = "md", color, label, ...props }) {
695
998
  return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles7.wrapper }, /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: sizeMap2[size], color: color ?? colors.primary, ...props }), /* @__PURE__ */ React25__default.default.createElement(
696
999
  reactNative.Text,
697
1000
  {
698
- style: [styles7.label, { color: colors.mutedForeground, fontSize: labelFontSize[size] }],
1001
+ style: [styles7.label, { color: colors.foregroundMuted, fontSize: labelFontSize[size] }],
699
1002
  allowFontScaling: true
700
1003
  },
701
1004
  label
@@ -713,18 +1016,21 @@ var styles7 = reactNative.StyleSheet.create({
713
1016
  lineHeight: mvs(18)
714
1017
  }
715
1018
  });
716
- function Skeleton({ width = "100%", height = 16, borderRadius = 6, style }) {
1019
+ function Skeleton({
1020
+ width = "100%",
1021
+ height = 16,
1022
+ borderRadius = 6,
1023
+ preset = "base",
1024
+ diameter = 40,
1025
+ style
1026
+ }) {
717
1027
  const { colors, colorScheme } = useTheme();
718
1028
  const shimmerAnim = React25.useRef(new reactNative.Animated.Value(0)).current;
719
1029
  const [containerWidth, setContainerWidth] = React25.useState(300);
720
1030
  const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(255,255,255,0.7)";
721
1031
  React25.useEffect(() => {
722
1032
  const animation = reactNative.Animated.loop(
723
- reactNative.Animated.timing(shimmerAnim, {
724
- toValue: 1,
725
- duration: 1200,
726
- useNativeDriver: true
727
- })
1033
+ reactNative.Animated.timing(shimmerAnim, { toValue: 1, duration: 1200, useNativeDriver: true })
728
1034
  );
729
1035
  animation.start();
730
1036
  return () => animation.stop();
@@ -733,12 +1039,15 @@ function Skeleton({ width = "100%", height = 16, borderRadius = 6, style }) {
733
1039
  inputRange: [0, 1],
734
1040
  outputRange: [-containerWidth, containerWidth]
735
1041
  });
1042
+ const resolvedWidth = preset === "circle" ? s(diameter) : preset === "text" ? "60%" : width;
1043
+ const resolvedHeight = preset === "circle" ? s(diameter) : preset === "text" ? 14 : height;
1044
+ const resolvedRadius = preset === "circle" ? 9999 : preset === "text" ? 4 : borderRadius;
736
1045
  return /* @__PURE__ */ React25__default.default.createElement(
737
1046
  reactNative.View,
738
1047
  {
739
1048
  style: [
740
1049
  styles8.base,
741
- { width, height, borderRadius, backgroundColor: colors.muted },
1050
+ { width: resolvedWidth, height: resolvedHeight, borderRadius: resolvedRadius, backgroundColor: colors.surface },
742
1051
  style
743
1052
  ],
744
1053
  onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width)
@@ -771,19 +1080,32 @@ var fontSizeMap = {
771
1080
  lg: ms(22),
772
1081
  xl: ms(28)
773
1082
  };
774
- function Avatar({ src, fallback, size = "md", style }) {
1083
+ var statusSizeMap = {
1084
+ sm: 8,
1085
+ md: 10,
1086
+ lg: 13,
1087
+ xl: 16
1088
+ };
1089
+ function Avatar({ src, fallback, size = "md", status, style }) {
775
1090
  const { colors } = useTheme();
776
1091
  const [imageError, setImageError] = React25.useState(false);
777
1092
  const dimension = sizeMap3[size];
778
1093
  const showFallback = !src || imageError;
1094
+ const statusSize = statusSizeMap[size];
1095
+ const statusColor = {
1096
+ online: "#22c55e",
1097
+ offline: "transparent",
1098
+ busy: colors.destructive,
1099
+ away: colors.warning
1100
+ };
779
1101
  const containerStyle = {
780
1102
  width: dimension,
781
1103
  height: dimension,
782
1104
  borderRadius: dimension / 2,
783
- backgroundColor: colors.muted,
1105
+ backgroundColor: colors.surface,
784
1106
  overflow: "hidden"
785
1107
  };
786
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles9.base, containerStyle, style] }, !showFallback ? /* @__PURE__ */ React25__default.default.createElement(
1108
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles9.wrapper, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles9.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React25__default.default.createElement(
787
1109
  reactNative.Image,
788
1110
  {
789
1111
  source: { uri: src },
@@ -793,64 +1115,86 @@ function Avatar({ src, fallback, size = "md", style }) {
793
1115
  ) : /* @__PURE__ */ React25__default.default.createElement(
794
1116
  reactNative.Text,
795
1117
  {
796
- style: [styles9.fallback, { color: colors.mutedForeground, fontSize: fontSizeMap[size] }],
1118
+ style: [styles9.fallback, { color: colors.foregroundMuted, fontSize: fontSizeMap[size] }],
797
1119
  allowFontScaling: true
798
1120
  },
799
1121
  fallback?.slice(0, 2).toUpperCase() ?? "?"
1122
+ )), status && /* @__PURE__ */ React25__default.default.createElement(
1123
+ reactNative.View,
1124
+ {
1125
+ style: [
1126
+ styles9.statusDot,
1127
+ {
1128
+ width: statusSize,
1129
+ height: statusSize,
1130
+ borderRadius: statusSize / 2,
1131
+ backgroundColor: statusColor[status],
1132
+ borderWidth: status === "offline" ? 2 : 1.5,
1133
+ borderColor: status === "offline" ? colors.border : colors.background
1134
+ }
1135
+ ]
1136
+ }
800
1137
  ));
801
1138
  }
802
1139
  var styles9 = reactNative.StyleSheet.create({
1140
+ wrapper: {
1141
+ alignSelf: "flex-start",
1142
+ position: "relative"
1143
+ },
803
1144
  base: {
804
1145
  alignItems: "center",
805
1146
  justifyContent: "center"
806
1147
  },
807
1148
  fallback: {
808
1149
  fontFamily: "Poppins-Medium"
1150
+ },
1151
+ statusDot: {
1152
+ position: "absolute",
1153
+ bottom: 0,
1154
+ right: 0
809
1155
  }
810
1156
  });
811
1157
  function AlertBanner({ title, description, variant = "default", icon, iconName, iconColor, style }) {
812
1158
  const { colors } = useTheme();
813
- const bgColor = variant === "destructive" ? colors.destructiveBorder : variant === "success" ? colors.successBorder : colors.card;
814
- const textColor = variant === "destructive" ? "#991b1b" : variant === "success" ? "#166534" : colors.foreground;
815
- const borderColor = textColor;
816
- const defaultIcon = variant === "success" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: 18, color: textColor }) : variant === "destructive" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "error-outline", size: 20, color: textColor }) : /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: 18, color: textColor });
817
- const effectiveIcon = iconName ? renderIcon(iconName, 18, iconColor ?? textColor) : icon ?? defaultIcon;
818
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles10.container, { backgroundColor: bgColor, borderColor }, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles10.header }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles10.icon }, effectiveIcon), title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles10.title, { color: textColor }], allowFontScaling: true }, title) : null), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles10.description, { color: textColor, opacity: 0.85 }], allowFontScaling: true }, description) : null);
1159
+ const bgColor = variant === "destructive" ? colors.destructiveTint : variant === "success" ? colors.successTint : variant === "warning" ? colors.warningTint : colors.card;
1160
+ const borderColor = variant === "destructive" ? colors.destructiveBorder : variant === "success" ? colors.successBorder : variant === "warning" ? colors.warningBorder : colors.border;
1161
+ const accentColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : variant === "warning" ? colors.warning : colors.primary;
1162
+ const titleColor = variant === "default" ? colors.foreground : accentColor;
1163
+ const descColor = variant === "default" ? colors.foregroundMuted : accentColor;
1164
+ const defaultIcon = variant === "success" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: 16, color: accentColor }) : variant === "destructive" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "error-outline", size: 17, color: accentColor }) : variant === "warning" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "warning-amber", size: 17, color: accentColor }) : /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: 16, color: accentColor });
1165
+ const effectiveIcon = iconName ? renderIcon(iconName, 16, iconColor ?? accentColor) : icon ?? defaultIcon;
1166
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles10.container, { backgroundColor: bgColor, borderColor }, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles10.iconSlot }, effectiveIcon), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles10.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles10.title, { color: titleColor }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles10.description, { color: descColor }], allowFontScaling: true }, description) : null));
819
1167
  }
820
1168
  var styles10 = reactNative.StyleSheet.create({
821
1169
  container: {
822
- borderWidth: 1,
823
- borderRadius: ms(12),
824
- paddingHorizontal: s(14),
825
- paddingVertical: vs(12),
826
- gap: vs(8),
827
- shadowColor: "#000",
828
- shadowOffset: { width: 0, height: 3 },
829
- shadowOpacity: 0.1,
830
- shadowRadius: 8,
831
- elevation: 5
832
- },
833
- header: {
834
1170
  flexDirection: "row",
835
- alignItems: "center",
1171
+ alignItems: "flex-start",
1172
+ borderWidth: 0.5,
1173
+ borderRadius: 10,
1174
+ paddingHorizontal: s(12),
1175
+ paddingVertical: vs(10),
836
1176
  gap: s(10)
837
1177
  },
838
- icon: {
839
- marginTop: 0
1178
+ iconSlot: {
1179
+ marginTop: vs(1)
1180
+ },
1181
+ content: {
1182
+ flex: 1,
1183
+ gap: vs(2)
840
1184
  },
841
1185
  title: {
842
- fontFamily: "Poppins-Bold",
843
- fontSize: ms(15),
844
- lineHeight: mvs(20),
845
- flex: 1
1186
+ fontFamily: "Poppins-Medium",
1187
+ fontSize: ms(13),
1188
+ lineHeight: ms(18)
846
1189
  },
847
1190
  description: {
848
1191
  fontFamily: "Poppins-Regular",
849
- fontSize: ms(14),
850
- lineHeight: mvs(20)
1192
+ fontSize: ms(12),
1193
+ lineHeight: ms(17),
1194
+ opacity: 0.85
851
1195
  }
852
1196
  });
853
- function Progress({ value = 0, max = 100, style }) {
1197
+ function Progress({ value = 0, max = 100, variant = "default", style }) {
854
1198
  const { colors } = useTheme();
855
1199
  const percent = Math.min(Math.max(value / max * 100, 0), 100);
856
1200
  const [trackWidth, setTrackWidth] = React25.useState(0);
@@ -864,16 +1208,17 @@ function Progress({ value = 0, max = 100, style }) {
864
1208
  bounciness: 0
865
1209
  }).start();
866
1210
  }, [percent, trackWidth]);
1211
+ const indicatorColor = variant === "success" ? colors.success : variant === "warning" ? colors.warning : variant === "destructive" ? colors.destructive : colors.primary;
867
1212
  return /* @__PURE__ */ React25__default.default.createElement(
868
1213
  reactNative.View,
869
1214
  {
870
- style: [styles11.track, { backgroundColor: colors.muted }, style],
1215
+ style: [styles11.track, { backgroundColor: colors.surface }, style],
871
1216
  onLayout: (e) => setTrackWidth(e.nativeEvent.layout.width)
872
1217
  },
873
1218
  /* @__PURE__ */ React25__default.default.createElement(
874
1219
  reactNative.Animated.View,
875
1220
  {
876
- style: [styles11.indicator, { width: animatedWidth, backgroundColor: colors.primary }]
1221
+ style: [styles11.indicator, { width: animatedWidth, backgroundColor: indicatorColor }]
877
1222
  }
878
1223
  )
879
1224
  );
@@ -881,19 +1226,19 @@ function Progress({ value = 0, max = 100, style }) {
881
1226
  var styles11 = reactNative.StyleSheet.create({
882
1227
  track: {
883
1228
  height: vs(8),
884
- borderRadius: 999,
1229
+ borderRadius: 9999,
885
1230
  overflow: "hidden",
886
1231
  width: "100%"
887
1232
  },
888
1233
  indicator: {
889
1234
  height: "100%",
890
- borderRadius: 999
1235
+ borderRadius: 9999
891
1236
  }
892
1237
  });
893
1238
  function EmptyState({ icon, iconName, iconColor, title, description, action, size = "default", style }) {
894
1239
  const { colors } = useTheme();
895
1240
  const isCompact = size === "compact";
896
- const effectiveIcon = iconName ? renderIcon(iconName, isCompact ? 32 : 48, iconColor ?? colors.mutedForeground) : icon;
1241
+ const effectiveIcon = iconName ? renderIcon(iconName, isCompact ? 32 : 48, iconColor ?? colors.foregroundMuted) : icon;
897
1242
  return /* @__PURE__ */ React25__default.default.createElement(
898
1243
  reactNative.View,
899
1244
  {
@@ -910,7 +1255,7 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, siz
910
1255
  style: [
911
1256
  styles12.iconWrapper,
912
1257
  isCompact && styles12.iconWrapperCompact,
913
- { backgroundColor: colors.muted }
1258
+ { backgroundColor: colors.surface }
914
1259
  ]
915
1260
  },
916
1261
  effectiveIcon
@@ -922,7 +1267,7 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, siz
922
1267
  allowFontScaling: true
923
1268
  },
924
1269
  title
925
- ), description && !isCompact ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles12.description, { color: colors.mutedForeground }], allowFontScaling: true }, description) : null),
1270
+ ), description && !isCompact ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles12.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null),
926
1271
  action && !isCompact ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles12.action }, action) : null
927
1272
  );
928
1273
  }
@@ -941,16 +1286,16 @@ var styles12 = reactNative.StyleSheet.create({
941
1286
  gap: vs(10)
942
1287
  },
943
1288
  iconWrapper: {
944
- width: s(48),
945
- height: s(48),
946
- borderRadius: ms(12),
1289
+ width: s(80),
1290
+ height: s(80),
1291
+ borderRadius: ms(20),
947
1292
  alignItems: "center",
948
1293
  justifyContent: "center"
949
1294
  },
950
1295
  iconWrapperCompact: {
951
- width: s(36),
952
- height: s(36),
953
- borderRadius: ms(8)
1296
+ width: s(56),
1297
+ height: s(56),
1298
+ borderRadius: ms(14)
954
1299
  },
955
1300
  textWrapper: {
956
1301
  alignItems: "center",
@@ -1014,11 +1359,11 @@ function Textarea({
1014
1359
  setFocused(false);
1015
1360
  onBlur?.(e);
1016
1361
  },
1017
- placeholderTextColor: colors.mutedForeground,
1362
+ placeholderTextColor: colors.foregroundMuted,
1018
1363
  allowFontScaling: true,
1019
1364
  ...props
1020
1365
  }
1021
- ), error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles13.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles13.helperText, { color: colors.mutedForeground }], allowFontScaling: true }, hint) : null);
1366
+ ), error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles13.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles13.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
1022
1367
  }
1023
1368
  var styles13 = reactNative.StyleSheet.create({
1024
1369
  container: {
@@ -1030,11 +1375,12 @@ var styles13 = reactNative.StyleSheet.create({
1030
1375
  },
1031
1376
  input: {
1032
1377
  fontFamily: "Poppins-Regular",
1033
- borderWidth: 1,
1378
+ borderWidth: 2,
1034
1379
  borderRadius: ms(8),
1035
1380
  paddingHorizontal: s(14),
1036
1381
  paddingVertical: vs(11),
1037
- fontSize: ms(15)
1382
+ fontSize: ms(15),
1383
+ includeFontPadding: false
1038
1384
  },
1039
1385
  helperText: {
1040
1386
  fontFamily: "Poppins-Regular",
@@ -1051,6 +1397,30 @@ function Checkbox({
1051
1397
  }) {
1052
1398
  const { colors } = useTheme();
1053
1399
  const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
1400
+ const bgOpacity = React25.useRef(new reactNative.Animated.Value(checked ? 1 : 0)).current;
1401
+ const checkOpacity = React25.useRef(new reactNative.Animated.Value(checked ? 1 : 0)).current;
1402
+ React25.useEffect(() => {
1403
+ reactNative.Animated.parallel([
1404
+ reactNative.Animated.timing(bgOpacity, {
1405
+ toValue: checked ? 1 : 0,
1406
+ duration: 150,
1407
+ useNativeDriver: false
1408
+ }),
1409
+ reactNative.Animated.timing(checkOpacity, {
1410
+ toValue: checked ? 1 : 0,
1411
+ duration: 120,
1412
+ useNativeDriver: false
1413
+ })
1414
+ ]).start();
1415
+ }, [checked, bgOpacity, checkOpacity]);
1416
+ const borderColor = bgOpacity.interpolate({
1417
+ inputRange: [0, 1],
1418
+ outputRange: [colors.border, colors.primary]
1419
+ });
1420
+ const backgroundColor = bgOpacity.interpolate({
1421
+ inputRange: [0, 1],
1422
+ outputRange: ["transparent", colors.primary]
1423
+ });
1054
1424
  const handlePressIn = () => {
1055
1425
  if (disabled) return;
1056
1426
  reactNative.Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver4, speed: 40, bounciness: 0 }).start();
@@ -1072,25 +1442,24 @@ function Checkbox({
1072
1442
  activeOpacity: 1,
1073
1443
  touchSoundDisabled: true
1074
1444
  },
1075
- /* @__PURE__ */ React25__default.default.createElement(
1445
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { transform: [{ scale: scale2 }] } }, /* @__PURE__ */ React25__default.default.createElement(
1076
1446
  reactNative.Animated.View,
1077
1447
  {
1078
1448
  style: [
1079
1449
  styles14.box,
1080
1450
  {
1081
- borderColor: checked ? colors.primary : colors.border,
1082
- backgroundColor: checked ? colors.primary : "transparent",
1083
- opacity: disabled ? 0.45 : 1,
1084
- transform: [{ scale: scale2 }]
1451
+ borderColor,
1452
+ backgroundColor,
1453
+ opacity: disabled ? 0.45 : 1
1085
1454
  }
1086
1455
  ]
1087
1456
  },
1088
- checked ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles14.checkmark, { borderColor: colors.primaryForeground }] }) : null
1089
- ),
1457
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { opacity: checkOpacity } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles14.checkmark, { borderColor: colors.primaryForeground }] }))
1458
+ )),
1090
1459
  label ? /* @__PURE__ */ React25__default.default.createElement(
1091
1460
  reactNative.Text,
1092
1461
  {
1093
- style: [styles14.label, { color: disabled ? colors.mutedForeground : colors.foreground }],
1462
+ style: [styles14.label, { color: disabled ? colors.foregroundMuted : colors.foreground }],
1094
1463
  allowFontScaling: true
1095
1464
  },
1096
1465
  label
@@ -1130,10 +1499,13 @@ var TRACK_HEIGHT = s(30);
1130
1499
  var THUMB_SIZE = s(24);
1131
1500
  var THUMB_OFFSET = s(3);
1132
1501
  var THUMB_TRAVEL = TRACK_WIDTH - THUMB_SIZE - THUMB_OFFSET * 2;
1502
+ var ICON_SIZE = s(13);
1133
1503
  function Switch({ checked = false, onCheckedChange, disabled, style }) {
1134
1504
  const { colors } = useTheme();
1135
1505
  const translateX = React25.useRef(new reactNative.Animated.Value(checked ? THUMB_TRAVEL : 0)).current;
1136
1506
  const trackOpacity = React25.useRef(new reactNative.Animated.Value(checked ? 1 : 0)).current;
1507
+ const checkOpacity = React25.useRef(new reactNative.Animated.Value(checked ? 1 : 0)).current;
1508
+ const crossOpacity = React25.useRef(new reactNative.Animated.Value(checked ? 0 : 1)).current;
1137
1509
  React25.useEffect(() => {
1138
1510
  reactNative.Animated.parallel([
1139
1511
  reactNative.Animated.spring(translateX, {
@@ -1145,12 +1517,22 @@ function Switch({ checked = false, onCheckedChange, disabled, style }) {
1145
1517
  toValue: checked ? 1 : 0,
1146
1518
  duration: 150,
1147
1519
  useNativeDriver: false
1520
+ }),
1521
+ reactNative.Animated.timing(checkOpacity, {
1522
+ toValue: checked ? 1 : 0,
1523
+ duration: 120,
1524
+ useNativeDriver: true
1525
+ }),
1526
+ reactNative.Animated.timing(crossOpacity, {
1527
+ toValue: checked ? 0 : 1,
1528
+ duration: 120,
1529
+ useNativeDriver: true
1148
1530
  })
1149
1531
  ]).start();
1150
- }, [checked, translateX, trackOpacity]);
1532
+ }, [checked, translateX, trackOpacity, checkOpacity, crossOpacity]);
1151
1533
  const trackColor = trackOpacity.interpolate({
1152
1534
  inputRange: [0, 1],
1153
- outputRange: [colors.muted, colors.primary]
1535
+ outputRange: [colors.surface, colors.primary]
1154
1536
  });
1155
1537
  return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [{ opacity: disabled ? 0.45 : 1 }, style] }, /* @__PURE__ */ React25__default.default.createElement(
1156
1538
  reactNative.TouchableOpacity,
@@ -1171,7 +1553,9 @@ function Switch({ checked = false, onCheckedChange, disabled, style }) {
1171
1553
  styles15.thumb,
1172
1554
  { backgroundColor: colors.primaryForeground, transform: [{ translateX }] }
1173
1555
  ]
1174
- }
1556
+ },
1557
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: [styles15.iconWrapper, { opacity: checkOpacity }] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "check", size: ICON_SIZE, color: colors.primary })),
1558
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: [styles15.iconWrapper, { opacity: crossOpacity }] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: ICON_SIZE, color: colors.foregroundMuted }))
1175
1559
  ))
1176
1560
  ));
1177
1561
  }
@@ -1195,7 +1579,12 @@ var styles15 = reactNative.StyleSheet.create({
1195
1579
  shadowOffset: { width: 0, height: 1 },
1196
1580
  shadowOpacity: 0.15,
1197
1581
  shadowRadius: 2,
1198
- elevation: 2
1582
+ elevation: 2,
1583
+ alignItems: "center",
1584
+ justifyContent: "center"
1585
+ },
1586
+ iconWrapper: {
1587
+ position: "absolute"
1199
1588
  }
1200
1589
  });
1201
1590
  var nativeDriver6 = reactNative.Platform.OS !== "web";
@@ -1245,7 +1634,7 @@ function Toggle({
1245
1634
  });
1246
1635
  const backgroundColor = pressAnim.interpolate({
1247
1636
  inputRange: [0, 1],
1248
- outputRange: ["transparent", colors.accent]
1637
+ outputRange: ["transparent", colors.surfaceStrong]
1249
1638
  });
1250
1639
  const textColor = pressAnim.interpolate({
1251
1640
  inputRange: [0, 1],
@@ -1264,10 +1653,10 @@ function Toggle({
1264
1653
  if (active) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, active);
1265
1654
  return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: iconSize, color: colors.primary });
1266
1655
  }
1267
- if (iconName) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, renderIcon(iconName, iconSize, iconColor ?? colors.mutedForeground));
1656
+ if (iconName) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, renderIcon(iconName, iconSize, iconColor ?? colors.foregroundMuted));
1268
1657
  const custom = renderProp(icon);
1269
1658
  if (custom) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, custom);
1270
- return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "circle", size: iconSize, color: colors.mutedForeground });
1659
+ return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "circle", size: iconSize, color: colors.foregroundMuted });
1271
1660
  };
1272
1661
  return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: [{ transform: [{ scale: scale2 }] }, disabled && styles16.disabled, style] }, /* @__PURE__ */ React25__default.default.createElement(
1273
1662
  reactNative.TouchableOpacity,
@@ -1364,7 +1753,7 @@ function RadioItem({
1364
1753
  {
1365
1754
  style: [
1366
1755
  styles17.label,
1367
- { color: option.disabled ? colors.mutedForeground : colors.foreground }
1756
+ { color: option.disabled ? colors.foregroundMuted : colors.foreground }
1368
1757
  ],
1369
1758
  allowFontScaling: true
1370
1759
  },
@@ -1426,7 +1815,8 @@ function TabTrigger({
1426
1815
  tab,
1427
1816
  isActive,
1428
1817
  onPress,
1429
- onLayout
1818
+ onLayout,
1819
+ variant
1430
1820
  }) {
1431
1821
  const { colors } = useTheme();
1432
1822
  const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
@@ -1436,10 +1826,15 @@ function TabTrigger({
1436
1826
  const handlePressOut = () => {
1437
1827
  reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver8, speed: 40, bounciness: 4 }).start();
1438
1828
  };
1829
+ const isUnderline = variant === "underline";
1439
1830
  return /* @__PURE__ */ React25__default.default.createElement(
1440
1831
  reactNative.TouchableOpacity,
1441
1832
  {
1442
- style: styles18.trigger,
1833
+ style: [
1834
+ styles18.trigger,
1835
+ isUnderline && styles18.triggerUnderline,
1836
+ isUnderline && isActive && { borderBottomColor: colors.primary }
1837
+ ],
1443
1838
  onPress,
1444
1839
  onPressIn: handlePressIn,
1445
1840
  onPressOut: handlePressOut,
@@ -1452,8 +1847,8 @@ function TabTrigger({
1452
1847
  {
1453
1848
  style: [
1454
1849
  styles18.triggerLabel,
1455
- { color: isActive ? colors.foreground : colors.mutedForeground },
1456
- isActive && styles18.activeTriggerLabel
1850
+ { color: isActive ? colors.foreground : colors.foregroundMuted },
1851
+ isActive && (isUnderline ? styles18.activeTriggerLabelUnderline : styles18.activeTriggerLabel)
1457
1852
  ],
1458
1853
  allowFontScaling: true
1459
1854
  },
@@ -1461,7 +1856,7 @@ function TabTrigger({
1461
1856
  )))
1462
1857
  );
1463
1858
  }
1464
- function Tabs({ tabs, value, onValueChange, children, style }) {
1859
+ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style }) {
1465
1860
  const [internal, setInternal] = React25.useState(tabs[0]?.value ?? "");
1466
1861
  const { colors } = useTheme();
1467
1862
  const active = value ?? internal;
@@ -1474,18 +1869,8 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
1474
1869
  if (!layout) return;
1475
1870
  if (animate) {
1476
1871
  reactNative.Animated.parallel([
1477
- reactNative.Animated.spring(pillX, {
1478
- toValue: layout.x,
1479
- useNativeDriver: false,
1480
- speed: 20,
1481
- bounciness: 0
1482
- }),
1483
- reactNative.Animated.spring(pillWidth, {
1484
- toValue: layout.width,
1485
- useNativeDriver: false,
1486
- speed: 20,
1487
- bounciness: 0
1488
- })
1872
+ reactNative.Animated.spring(pillX, { toValue: layout.x, useNativeDriver: false, speed: 20, bounciness: 0 }),
1873
+ reactNative.Animated.spring(pillWidth, { toValue: layout.width, useNativeDriver: false, speed: 20, bounciness: 0 })
1489
1874
  ]).start();
1490
1875
  } else {
1491
1876
  pillX.setValue(layout.x);
@@ -1493,16 +1878,16 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
1493
1878
  }
1494
1879
  };
1495
1880
  React25.useEffect(() => {
1496
- if (initialised.current) {
1497
- animatePill(active, true);
1498
- }
1881
+ if (initialised.current) animatePill(active, true);
1499
1882
  }, [active]);
1500
1883
  const handlePress = (v) => {
1501
1884
  selectionAsync();
1502
1885
  if (!value) setInternal(v);
1503
1886
  onValueChange?.(v);
1504
1887
  };
1505
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles18.list, { backgroundColor: colors.muted }] }, /* @__PURE__ */ React25__default.default.createElement(
1888
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [
1889
+ variant === "pill" ? [styles18.list, { backgroundColor: colors.surface }] : styles18.listUnderline
1890
+ ] }, variant === "pill" && /* @__PURE__ */ React25__default.default.createElement(
1506
1891
  reactNative.Animated.View,
1507
1892
  {
1508
1893
  style: [
@@ -1517,7 +1902,7 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
1517
1902
  borderRadius: 8,
1518
1903
  shadowColor: "#000",
1519
1904
  shadowOffset: { width: 0, height: 1 },
1520
- shadowOpacity: 0.1,
1905
+ shadowOpacity: 0.08,
1521
1906
  shadowRadius: 2,
1522
1907
  elevation: 2
1523
1908
  }
@@ -1530,6 +1915,7 @@ function Tabs({ tabs, value, onValueChange, children, style }) {
1530
1915
  tab,
1531
1916
  isActive: tab.value === active,
1532
1917
  onPress: () => handlePress(tab.value),
1918
+ variant,
1533
1919
  onLayout: (e) => {
1534
1920
  const { x, width } = e.nativeEvent.layout;
1535
1921
  tabLayouts.current[tab.value] = { x, width };
@@ -1548,20 +1934,32 @@ function TabsContent({ value, activeValue, children, style }) {
1548
1934
  var styles18 = reactNative.StyleSheet.create({
1549
1935
  list: {
1550
1936
  flexDirection: "row",
1551
- borderRadius: ms(12),
1937
+ borderRadius: 12,
1552
1938
  padding: s(4),
1553
1939
  gap: s(4)
1554
1940
  },
1941
+ listUnderline: {
1942
+ flexDirection: "row",
1943
+ borderBottomWidth: 1
1944
+ },
1555
1945
  pill: {},
1556
1946
  trigger: {
1557
1947
  flex: 1,
1558
1948
  paddingVertical: vs(7),
1559
1949
  paddingHorizontal: s(10),
1560
- borderRadius: ms(6),
1950
+ borderRadius: 8,
1561
1951
  alignItems: "center",
1562
1952
  justifyContent: "center",
1563
1953
  zIndex: 1
1564
1954
  },
1955
+ triggerUnderline: {
1956
+ flex: 0,
1957
+ paddingVertical: vs(12),
1958
+ paddingHorizontal: s(16),
1959
+ borderRadius: 0,
1960
+ borderBottomWidth: 2,
1961
+ borderBottomColor: "transparent"
1962
+ },
1565
1963
  triggerInner: {
1566
1964
  flexDirection: "row",
1567
1965
  alignItems: "center",
@@ -1574,6 +1972,10 @@ var styles18 = reactNative.StyleSheet.create({
1574
1972
  },
1575
1973
  activeTriggerLabel: {
1576
1974
  fontFamily: "Poppins-Medium"
1975
+ },
1976
+ activeTriggerLabelUnderline: {
1977
+ fontFamily: "Poppins-SemiBold",
1978
+ fontSize: ms(14)
1577
1979
  }
1578
1980
  });
1579
1981
  function AccordionItemComponent({
@@ -1616,7 +2018,7 @@ function AccordionItemComponent({
1616
2018
  }
1617
2019
  },
1618
2020
  /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles19.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger),
1619
- /* @__PURE__ */ React25__default.default.createElement(Animated11__default.default.View, { style: [styles19.chevron, rotationStyle] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.mutedForeground }))
2021
+ /* @__PURE__ */ React25__default.default.createElement(Animated11__default.default.View, { style: [styles19.chevron, rotationStyle] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
1620
2022
  ), /* @__PURE__ */ React25__default.default.createElement(Animated11__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React25__default.default.createElement(
1621
2023
  reactNative.View,
1622
2024
  {
@@ -1708,7 +2110,7 @@ function Slider({
1708
2110
  }
1709
2111
  onValueChange?.(v);
1710
2112
  };
1711
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles20.wrapper, style], accessibilityLabel }, label || showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles20.header }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.valueText, { color: colors.mutedForeground }], allowFontScaling: true }, formatValue2(value)) : null) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled ? styles20.disabled : void 0 }, /* @__PURE__ */ React25__default.default.createElement(
2113
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles20.wrapper, style], accessibilityLabel }, label || showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles20.header }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.valueText, { color: colors.foregroundMuted }], allowFontScaling: true }, formatValue2(value)) : null) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled ? styles20.disabled : void 0 }, /* @__PURE__ */ React25__default.default.createElement(
1712
2114
  RNSlider__default.default,
1713
2115
  {
1714
2116
  value,
@@ -1719,7 +2121,7 @@ function Slider({
1719
2121
  onValueChange: handleValueChange,
1720
2122
  onSlidingComplete,
1721
2123
  minimumTrackTintColor: colors.primary,
1722
- maximumTrackTintColor: colors.muted,
2124
+ maximumTrackTintColor: colors.surface,
1723
2125
  thumbTintColor: colors.primary,
1724
2126
  style: styles20.slider,
1725
2127
  accessibilityLabel
@@ -1757,7 +2159,6 @@ function Sheet({
1757
2159
  title,
1758
2160
  description,
1759
2161
  children,
1760
- snapPoints = ["50%"],
1761
2162
  style
1762
2163
  }) {
1763
2164
  const { colors } = useTheme();
@@ -1783,14 +2184,14 @@ function Sheet({
1783
2184
  bottomSheet.BottomSheetModal,
1784
2185
  {
1785
2186
  ref,
1786
- snapPoints,
2187
+ enableDynamicSizing: true,
1787
2188
  onDismiss: onClose,
1788
2189
  backdropComponent: renderBackdrop,
1789
2190
  backgroundStyle: [styles21.background, { backgroundColor: colors.card }],
1790
2191
  handleIndicatorStyle: [styles21.handle, { backgroundColor: colors.border }],
1791
2192
  enablePanDownToClose: true
1792
2193
  },
1793
- /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: [styles21.content, style] }, title || description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles21.header }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.title, { color: colors.cardForeground }], allowFontScaling: true }, title) : null, description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.description, { color: colors.mutedForeground }], allowFontScaling: true }, description) : null) : null, children)
2194
+ /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: [styles21.content, style] }, title || description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles21.header }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.title, { color: colors.foreground }], allowFontScaling: true }, title) : null, description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null) : null, children)
1794
2195
  );
1795
2196
  }
1796
2197
  var styles21 = reactNative.StyleSheet.create({
@@ -1889,14 +2290,14 @@ function Select({
1889
2290
  {
1890
2291
  style: [
1891
2292
  styles22.triggerText,
1892
- { color: selected ? colors.foreground : colors.mutedForeground }
2293
+ { color: selected ? colors.foreground : colors.foregroundMuted }
1893
2294
  ],
1894
2295
  numberOfLines: 1,
1895
2296
  allowFontScaling: true
1896
2297
  },
1897
2298
  selected?.label ?? placeholder
1898
2299
  ),
1899
- /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-down", size: 20, color: colors.mutedForeground })
2300
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-down", size: 20, color: colors.foregroundMuted })
1900
2301
  )) : null, isIOS ? /* @__PURE__ */ React25__default.default.createElement(
1901
2302
  reactNative.Modal,
1902
2303
  {
@@ -1913,7 +2314,7 @@ function Select({
1913
2314
  onValueChange: (val) => setPendingValue(val),
1914
2315
  itemStyle: { color: colors.foreground }
1915
2316
  },
1916
- !value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.mutedForeground, enabled: false }) : null,
2317
+ !value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.foregroundMuted, enabled: false }) : null,
1917
2318
  options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
1918
2319
  picker.Picker.Item,
1919
2320
  {
@@ -1921,7 +2322,7 @@ function Select({
1921
2322
  label: o.label,
1922
2323
  value: o.value,
1923
2324
  enabled: !o.disabled,
1924
- color: o.disabled ? colors.mutedForeground : colors.foreground
2325
+ color: o.disabled ? colors.foregroundMuted : colors.foreground
1925
2326
  }
1926
2327
  ))
1927
2328
  ))
@@ -1965,7 +2366,7 @@ function Select({
1965
2366
  styles22.webPicker,
1966
2367
  {
1967
2368
  borderColor: error ? colors.destructive : colors.border,
1968
- color: selected ? colors.foreground : colors.mutedForeground,
2369
+ color: selected ? colors.foreground : colors.foregroundMuted,
1969
2370
  backgroundColor: colors.background,
1970
2371
  opacity: disabled ? 0.45 : 1
1971
2372
  }
@@ -2100,19 +2501,39 @@ function ToastNotification({ item, onDismiss }) {
2100
2501
  }));
2101
2502
  const variant = item.variant ?? "default";
2102
2503
  const bgColor = {
2103
- default: colors.foreground,
2504
+ default: colors.card,
2505
+ destructive: colors.destructiveTint,
2506
+ success: colors.successTint,
2507
+ warning: colors.warningTint
2508
+ }[variant];
2509
+ const borderColor = {
2510
+ default: colors.border,
2104
2511
  destructive: colors.destructiveBorder,
2105
- success: colors.successBorder
2512
+ success: colors.successBorder,
2513
+ warning: colors.warningBorder
2106
2514
  }[variant];
2107
- const textColor = {
2108
- default: colors.background,
2109
- destructive: "#991b1b",
2110
- success: "#166534"
2515
+ const accentColor = {
2516
+ default: colors.primary,
2517
+ destructive: colors.destructive,
2518
+ success: colors.success,
2519
+ warning: colors.warning
2111
2520
  }[variant];
2112
- const borderColor = textColor;
2113
- const defaultIcon = variant === "success" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: 18, color: textColor }) : variant === "destructive" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: "exclamation-circle", size: 18, color: textColor }) : /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: 18, color: textColor });
2114
- const leftIcon = item.iconName ? renderIcon(item.iconName, 22, item.iconColor ?? textColor) : item.icon ?? defaultIcon;
2115
- return /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: panGesture }, /* @__PURE__ */ React25__default.default.createElement(Animated11__default.default.View, { style: [styles23.toast, { backgroundColor: bgColor, borderColor }, animatedStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles23.leftIconContainer }, leftIcon), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles23.toastContent }, item.title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.toastTitle, { color: textColor }], allowFontScaling: true }, item.title) : null, item.description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.toastDescription, { color: textColor, opacity: 0.85 }], allowFontScaling: true }, item.description) : null), /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { onPress: onDismiss, style: styles23.dismissButton, touchSoundDisabled: true }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: "close-circle", size: 18, color: textColor }))));
2521
+ const titleColor = variant === "default" ? colors.foreground : accentColor;
2522
+ const descColor = variant === "default" ? colors.foregroundMuted : accentColor;
2523
+ const defaultIcon = variant === "success" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: 16, color: accentColor }) : variant === "destructive" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: "exclamation-circle", size: 16, color: accentColor }) : variant === "warning" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "warning-amber", size: 17, color: accentColor }) : /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: 16, color: accentColor });
2524
+ const leftIcon = item.iconName ? renderIcon(item.iconName, 16, item.iconColor ?? accentColor) : item.icon ?? defaultIcon;
2525
+ return /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: panGesture }, /* @__PURE__ */ React25__default.default.createElement(Animated11__default.default.View, { style: [styles23.toast, { backgroundColor: bgColor, borderColor }, animatedStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles23.leftIconContainer }, leftIcon), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles23.toastContent }, item.title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.toastTitle, { color: titleColor }], allowFontScaling: true }, item.title) : null, item.description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.toastDescription, { color: descColor }], allowFontScaling: true }, item.description) : null), item.action && /* @__PURE__ */ React25__default.default.createElement(
2526
+ reactNative.TouchableOpacity,
2527
+ {
2528
+ onPress: () => {
2529
+ item.action.onPress();
2530
+ onDismiss();
2531
+ },
2532
+ style: styles23.actionButton,
2533
+ touchSoundDisabled: true
2534
+ },
2535
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.actionLabel, { color: accentColor }], allowFontScaling: true }, item.action.label)
2536
+ ), /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { onPress: onDismiss, style: styles23.dismissButton, touchSoundDisabled: true }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: "close-circle", size: 16, color: descColor }))));
2116
2537
  }
2117
2538
  function ToastProvider({ children }) {
2118
2539
  const [toasts, setToasts] = React25.useState([]);
@@ -2123,6 +2544,8 @@ function ToastProvider({ children }) {
2123
2544
  notificationSuccess();
2124
2545
  } else if (item.variant === "destructive") {
2125
2546
  notificationError();
2547
+ } else if (item.variant === "warning") {
2548
+ notificationError();
2126
2549
  } else {
2127
2550
  impactLight();
2128
2551
  }
@@ -2149,38 +2572,52 @@ var styles23 = reactNative.StyleSheet.create({
2149
2572
  },
2150
2573
  toast: {
2151
2574
  flexDirection: "row",
2152
- alignItems: "center",
2153
- borderRadius: ms(12),
2154
- borderWidth: 1,
2155
- paddingHorizontal: s(14),
2156
- paddingVertical: vs(12),
2575
+ alignItems: "flex-start",
2576
+ borderRadius: ms(10),
2577
+ borderWidth: 0.5,
2578
+ paddingHorizontal: s(12),
2579
+ paddingVertical: vs(10),
2157
2580
  shadowColor: "#000",
2158
- shadowOffset: { width: 0, height: 3 },
2159
- shadowOpacity: 0.1,
2160
- shadowRadius: 8,
2161
- elevation: 5
2581
+ shadowOffset: { width: 0, height: 2 },
2582
+ shadowOpacity: 0.06,
2583
+ shadowRadius: 4,
2584
+ elevation: 3
2162
2585
  },
2163
2586
  toastContent: {
2164
2587
  flex: 1,
2165
- gap: vs(4)
2588
+ gap: vs(2)
2166
2589
  },
2167
2590
  leftIconContainer: {
2168
- width: s(28),
2591
+ marginTop: vs(1),
2169
2592
  alignItems: "center",
2170
2593
  justifyContent: "center",
2171
2594
  marginRight: s(10)
2172
2595
  },
2173
2596
  toastTitle: {
2174
- fontFamily: "Poppins-SemiBold",
2175
- fontSize: ms(15)
2597
+ fontFamily: "Poppins-Medium",
2598
+ fontSize: ms(13),
2599
+ lineHeight: ms(18)
2176
2600
  },
2177
2601
  toastDescription: {
2178
2602
  fontFamily: "Poppins-Regular",
2179
- fontSize: ms(14)
2603
+ fontSize: ms(12),
2604
+ lineHeight: ms(17),
2605
+ opacity: 0.85
2180
2606
  },
2181
- dismissButton: {
2182
- padding: s(8),
2607
+ actionButton: {
2608
+ paddingHorizontal: s(8),
2609
+ paddingVertical: vs(4),
2183
2610
  marginLeft: s(4)
2611
+ },
2612
+ actionLabel: {
2613
+ fontFamily: "Poppins-Medium",
2614
+ fontSize: ms(12),
2615
+ textDecorationLine: "underline"
2616
+ },
2617
+ dismissButton: {
2618
+ padding: s(6),
2619
+ marginLeft: s(2),
2620
+ marginTop: vs(0)
2184
2621
  }
2185
2622
  });
2186
2623
  function formatCurrency(raw, separator) {
@@ -2214,7 +2651,7 @@ function CurrencyInput({
2214
2651
  onChangeValue?.(isNaN(raw) ? 0 : raw);
2215
2652
  };
2216
2653
  const inputStyle = size === "large" ? { fontFamily: "Poppins-Regular", fontSize: ms(36) } : { fontFamily: "Poppins-Regular" };
2217
- const dollarIcon = renderIcon("dollar-sign", size === "large" ? 24 : 16, colors.mutedForeground);
2654
+ const dollarIcon = renderIcon("dollar-sign", size === "large" ? 24 : 16, colors.foregroundMuted);
2218
2655
  const displayValue = value && prefix && value.startsWith(prefix) ? value.slice(prefix.length) : value;
2219
2656
  return /* @__PURE__ */ React25__default.default.createElement(
2220
2657
  Input,
@@ -2229,7 +2666,7 @@ function CurrencyInput({
2229
2666
  editable,
2230
2667
  prefix: dollarIcon,
2231
2668
  containerStyle,
2232
- inputWrapperStyle: size === "large" ? { paddingVertical: 10 } : void 0,
2669
+ inputWrapperStyle: size === "large" ? { paddingVertical: vs(16), minHeight: 72 } : void 0,
2233
2670
  style: [inputStyle, style]
2234
2671
  }
2235
2672
  );
@@ -2255,7 +2692,8 @@ var styles24 = reactNative.StyleSheet.create({
2255
2692
  container: {},
2256
2693
  amount: {
2257
2694
  fontFamily: "Poppins-Bold",
2258
- fontSize: ms(56)
2695
+ fontSize: ms(56),
2696
+ letterSpacing: -2
2259
2697
  }
2260
2698
  });
2261
2699
  var nativeDriver10 = reactNative.Platform.OS !== "web";
@@ -2305,7 +2743,7 @@ function ListItem({
2305
2743
  onPress?.();
2306
2744
  };
2307
2745
  const effectiveLeft = leftIcon ? renderIcon(leftIcon, 24, leftIconColor ?? colors.foreground) : leftRender ?? icon;
2308
- const effectiveRight = rightIcon ? renderIcon(rightIcon, 24, rightIconColor ?? colors.mutedForeground) : rightRender ?? trailing;
2746
+ const effectiveRight = rightIcon ? renderIcon(rightIcon, 24, rightIconColor ?? colors.foregroundMuted) : rightRender ?? trailing;
2309
2747
  const cardStyle = variant === "card" ? {
2310
2748
  backgroundColor: colors.card,
2311
2749
  borderRadius: 12,
@@ -2340,7 +2778,7 @@ function ListItem({
2340
2778
  ), subtitle ? /* @__PURE__ */ React25__default.default.createElement(
2341
2779
  reactNative.Text,
2342
2780
  {
2343
- style: [styles25.subtitle, { color: colors.mutedForeground }, subtitleStyle],
2781
+ style: [styles25.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
2344
2782
  numberOfLines: 2,
2345
2783
  allowFontScaling: true
2346
2784
  },
@@ -2348,7 +2786,7 @@ function ListItem({
2348
2786
  ) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(
2349
2787
  reactNative.Text,
2350
2788
  {
2351
- style: [styles25.caption, { color: colors.mutedForeground }, captionStyle],
2789
+ style: [styles25.caption, { color: colors.foregroundMuted }, captionStyle],
2352
2790
  numberOfLines: 1,
2353
2791
  allowFontScaling: true
2354
2792
  },
@@ -2357,11 +2795,11 @@ function ListItem({
2357
2795
  effectiveRight !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof effectiveRight === "string" ? /* @__PURE__ */ React25__default.default.createElement(
2358
2796
  reactNative.Text,
2359
2797
  {
2360
- style: [styles25.rightText, { color: colors.mutedForeground }],
2798
+ style: [styles25.rightText, { color: colors.foregroundMuted }],
2361
2799
  allowFontScaling: true
2362
2800
  },
2363
2801
  effectiveRight
2364
- ) : effectiveRight) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.mutedForeground }) : null
2802
+ ) : effectiveRight) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.foregroundMuted }) : null
2365
2803
  ), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(
2366
2804
  reactNative.View,
2367
2805
  {
@@ -2463,7 +2901,7 @@ function Chip({ label, selected = false, onPress, icon, iconName, style }) {
2463
2901
  };
2464
2902
  const backgroundColor = pressAnim.interpolate({
2465
2903
  inputRange: [0, 1],
2466
- outputRange: [colors.secondary, colors.primary]
2904
+ outputRange: [colors.surface, colors.primary]
2467
2905
  });
2468
2906
  const textColor = pressAnim.interpolate({
2469
2907
  inputRange: [0, 1],
@@ -2578,18 +3016,18 @@ function ConfirmDialog({
2578
3016
  bottomSheet.BottomSheetModal,
2579
3017
  {
2580
3018
  ref,
2581
- snapPoints: ["35%"],
3019
+ enableDynamicSizing: true,
2582
3020
  onDismiss: onCancel,
2583
3021
  backdropComponent: renderBackdrop,
2584
3022
  backgroundStyle: [styles27.background, { backgroundColor: colors.card }],
2585
3023
  handleIndicatorStyle: [styles27.handle, { backgroundColor: colors.border }],
2586
3024
  enablePanDownToClose: true
2587
3025
  },
2588
- /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: styles27.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles27.title, { color: colors.cardForeground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles27.description, { color: colors.mutedForeground }], allowFontScaling: true }, description) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles27.actions }, /* @__PURE__ */ React25__default.default.createElement(
3026
+ /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: styles27.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles27.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles27.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles27.actions }, /* @__PURE__ */ React25__default.default.createElement(
2589
3027
  Button,
2590
3028
  {
2591
3029
  label: cancelLabel,
2592
- variant: "outline",
3030
+ variant: "secondary",
2593
3031
  fullWidth: true,
2594
3032
  onPress: onCancel,
2595
3033
  icon: /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: 15, color: colors.foreground })
@@ -2645,7 +3083,7 @@ var styles27 = reactNative.StyleSheet.create({
2645
3083
  });
2646
3084
  function LabelValue({ label, value, style }) {
2647
3085
  const { colors } = useTheme();
2648
- return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.container, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.label, { color: colors.mutedForeground }], allowFontScaling: true }, label), typeof value === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
3086
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.container, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.label, { color: colors.foregroundMuted }], allowFontScaling: true }, label), typeof value === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
2649
3087
  }
2650
3088
  var styles28 = reactNative.StyleSheet.create({
2651
3089
  container: {
@@ -2738,64 +3176,343 @@ var styles29 = reactNative.StyleSheet.create({
2738
3176
  minWidth: s(160)
2739
3177
  }
2740
3178
  });
3179
+ function useHover() {
3180
+ const [hovered, setHovered] = React25.useState(false);
3181
+ const onMouseEnter = React25.useCallback(() => setHovered(true), []);
3182
+ const onMouseLeave = React25.useCallback(() => setHovered(false), []);
3183
+ if (reactNative.Platform.OS !== "web") {
3184
+ return { hovered: false, hoverHandlers: {} };
3185
+ }
3186
+ return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
3187
+ }
2741
3188
 
2742
- // src/tokens.ts
2743
- var SPACING = {
2744
- xs: 4,
2745
- sm: 8,
2746
- md: 12,
2747
- lg: 16,
2748
- xl: 24,
2749
- "2xl": 32,
2750
- "3xl": 48
2751
- };
2752
- var ICON_SIZES = {
2753
- sm: 14,
2754
- md: 18,
2755
- lg: 22,
2756
- xl: 28,
2757
- "2xl": 32
2758
- };
2759
- var RADIUS = {
2760
- sm: 4,
2761
- md: 8,
2762
- lg: 12,
2763
- xl: 16,
2764
- full: 9999
3189
+ // src/components/MediaCard/MediaCard.tsx
3190
+ var nativeDriver12 = reactNative.Platform.OS !== "web";
3191
+ var aspectRatioMap = {
3192
+ "1:1": 1,
3193
+ "4:3": 3 / 4,
3194
+ "16:9": 9 / 16,
3195
+ "4:5": 5 / 4,
3196
+ "3:2": 2 / 3
2765
3197
  };
2766
- var SHADOWS = {
2767
- sm: {
2768
- shadowColor: "#000",
2769
- shadowOffset: { width: 0, height: 1 },
2770
- shadowOpacity: 0.08,
2771
- shadowRadius: 4,
2772
- elevation: 2
3198
+ function MediaCard({
3199
+ imageSource,
3200
+ aspectRatio = "4:3",
3201
+ badge,
3202
+ actionIcon,
3203
+ actionIconName,
3204
+ actionActive = false,
3205
+ onActionPress,
3206
+ title,
3207
+ subtitle,
3208
+ caption,
3209
+ onPress,
3210
+ style,
3211
+ imageStyle,
3212
+ footer
3213
+ }) {
3214
+ const { colors } = useTheme();
3215
+ const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
3216
+ const { hovered, hoverHandlers } = useHover();
3217
+ const handlePressIn = () => {
3218
+ if (!onPress) return;
3219
+ reactNative.Animated.spring(scale2, { toValue: 0.98, useNativeDriver: nativeDriver12, speed: 40, bounciness: 0 }).start();
3220
+ };
3221
+ const handlePressOut = () => {
3222
+ if (!onPress) return;
3223
+ reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver12, speed: 40, bounciness: 4 }).start();
3224
+ };
3225
+ const handlePress = () => {
3226
+ if (!onPress) return;
3227
+ impactLight();
3228
+ onPress();
3229
+ };
3230
+ const ratio = aspectRatioMap[aspectRatio];
3231
+ const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
3232
+ const cardContent = /* @__PURE__ */ React25__default.default.createElement(
3233
+ reactNative.View,
3234
+ {
3235
+ style: [
3236
+ styles30.card,
3237
+ hovered && styles30.cardHovered,
3238
+ style
3239
+ ],
3240
+ ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
3241
+ },
3242
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles30.imageContainer, imageStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React25__default.default.createElement(
3243
+ reactNative.Image,
3244
+ {
3245
+ source: imageSource,
3246
+ style: styles30.image,
3247
+ resizeMode: "cover"
3248
+ }
3249
+ ) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles30.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles30.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React25__default.default.createElement(
3250
+ reactNative.TouchableOpacity,
3251
+ {
3252
+ style: [styles30.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
3253
+ onPress: () => {
3254
+ impactLight();
3255
+ onActionPress?.();
3256
+ },
3257
+ activeOpacity: 0.8,
3258
+ touchSoundDisabled: true
3259
+ },
3260
+ resolvedActionIcon
3261
+ )),
3262
+ (title || subtitle || caption || footer) && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles30.meta }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
3263
+ );
3264
+ if (onPress) {
3265
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { transform: [{ scale: scale2 }] } }, /* @__PURE__ */ React25__default.default.createElement(
3266
+ reactNative.TouchableOpacity,
3267
+ {
3268
+ onPress: handlePress,
3269
+ onPressIn: handlePressIn,
3270
+ onPressOut: handlePressOut,
3271
+ activeOpacity: 1,
3272
+ touchSoundDisabled: true
3273
+ },
3274
+ cardContent
3275
+ ));
3276
+ }
3277
+ return cardContent;
3278
+ }
3279
+ var styles30 = reactNative.StyleSheet.create({
3280
+ card: {
3281
+ borderRadius: RADIUS.md,
3282
+ // 14px — Airbnb property card spec
3283
+ overflow: "hidden",
3284
+ backgroundColor: "transparent"
2773
3285
  },
2774
- md: {
2775
- shadowColor: "#000",
2776
- shadowOffset: { width: 0, height: 3 },
2777
- shadowOpacity: 0.12,
2778
- shadowRadius: 8,
2779
- elevation: 5
3286
+ cardHovered: {
3287
+ // Web hover: lift shadow
3288
+ ...SHADOWS.md
2780
3289
  },
2781
- lg: {
2782
- shadowColor: "#000",
2783
- shadowOffset: { width: 0, height: 6 },
2784
- shadowOpacity: 0.2,
2785
- shadowRadius: 16,
2786
- elevation: 10
3290
+ imageContainer: {
3291
+ borderRadius: RADIUS.md,
3292
+ overflow: "hidden"
2787
3293
  },
2788
- xl: {
2789
- shadowColor: "#000",
2790
- shadowOffset: { width: 0, height: 12 },
2791
- shadowOpacity: 0.28,
2792
- shadowRadius: 24,
2793
- elevation: 18
3294
+ image: {
3295
+ width: "100%",
3296
+ height: "100%"
3297
+ },
3298
+ imagePlaceholder: {
3299
+ width: "100%",
3300
+ height: "100%"
3301
+ },
3302
+ badgeContainer: {
3303
+ position: "absolute",
3304
+ top: s(8),
3305
+ left: s(8)
3306
+ },
3307
+ actionButton: {
3308
+ position: "absolute",
3309
+ top: s(8),
3310
+ right: s(8),
3311
+ width: s(32),
3312
+ height: s(32),
3313
+ borderRadius: 9999,
3314
+ alignItems: "center",
3315
+ justifyContent: "center"
3316
+ },
3317
+ meta: {
3318
+ paddingTop: vs(8),
3319
+ gap: vs(2)
3320
+ },
3321
+ title: {
3322
+ fontFamily: "Poppins-SemiBold",
3323
+ fontSize: ms(14),
3324
+ lineHeight: mvs(20)
3325
+ },
3326
+ subtitle: {
3327
+ fontFamily: "Poppins-Regular",
3328
+ fontSize: ms(13),
3329
+ lineHeight: mvs(18)
3330
+ },
3331
+ caption: {
3332
+ fontFamily: "Poppins-Regular",
3333
+ fontSize: ms(12),
3334
+ lineHeight: mvs(16)
2794
3335
  }
2795
- };
2796
- var BREAKPOINTS = {
2797
- wide: 700
2798
- };
3336
+ });
3337
+ var nativeDriver13 = reactNative.Platform.OS !== "web";
3338
+ function CategoryChip({
3339
+ item,
3340
+ selected,
3341
+ onPress
3342
+ }) {
3343
+ const { colors } = useTheme();
3344
+ const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
3345
+ const handlePressIn = () => {
3346
+ reactNative.Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver13, speed: 40, bounciness: 0 }).start();
3347
+ };
3348
+ const handlePressOut = () => {
3349
+ reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver13, speed: 40, bounciness: 4 }).start();
3350
+ };
3351
+ const bgColor = selected ? colors.primary : colors.surface;
3352
+ const textColor = selected ? colors.primaryForeground : colors.foregroundSubtle;
3353
+ const borderColor = selected ? colors.primary : colors.border;
3354
+ const resolvedIcon = typeof item.icon === "string" ? renderIcon(item.icon, 16, textColor) : item.icon ?? null;
3355
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { transform: [{ scale: scale2 }] } }, /* @__PURE__ */ React25__default.default.createElement(
3356
+ reactNative.TouchableOpacity,
3357
+ {
3358
+ style: [
3359
+ styles31.chip,
3360
+ {
3361
+ backgroundColor: bgColor,
3362
+ borderColor
3363
+ }
3364
+ ],
3365
+ onPress,
3366
+ onPressIn: handlePressIn,
3367
+ onPressOut: handlePressOut,
3368
+ activeOpacity: 1,
3369
+ touchSoundDisabled: true
3370
+ },
3371
+ resolvedIcon && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles31.chipIcon }, resolvedIcon),
3372
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.chipLabel, { color: textColor }], allowFontScaling: true }, item.label),
3373
+ item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles31.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99)))
3374
+ ));
3375
+ }
3376
+ function CategoryStrip({
3377
+ categories,
3378
+ value,
3379
+ onValueChange,
3380
+ multiSelect = false,
3381
+ style,
3382
+ itemStyle
3383
+ }) {
3384
+ const selected = Array.isArray(value) ? value : value ? [value] : [];
3385
+ const handlePress = (v) => {
3386
+ selectionAsync();
3387
+ if (multiSelect) {
3388
+ const current = Array.isArray(value) ? value : value ? [value] : [];
3389
+ const next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];
3390
+ onValueChange?.(next);
3391
+ } else {
3392
+ onValueChange?.(v === value ? "" : v);
3393
+ }
3394
+ };
3395
+ return /* @__PURE__ */ React25__default.default.createElement(
3396
+ reactNative.ScrollView,
3397
+ {
3398
+ horizontal: true,
3399
+ showsHorizontalScrollIndicator: false,
3400
+ contentContainerStyle: [styles31.container, style],
3401
+ style: styles31.scroll
3402
+ },
3403
+ categories.map((cat) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: cat.value, style: itemStyle }, /* @__PURE__ */ React25__default.default.createElement(
3404
+ CategoryChip,
3405
+ {
3406
+ item: cat,
3407
+ selected: selected.includes(cat.value),
3408
+ onPress: () => handlePress(cat.value)
3409
+ }
3410
+ )))
3411
+ );
3412
+ }
3413
+ var styles31 = reactNative.StyleSheet.create({
3414
+ scroll: {
3415
+ flexGrow: 0
3416
+ },
3417
+ container: {
3418
+ flexDirection: "row",
3419
+ gap: s(8),
3420
+ paddingHorizontal: s(4),
3421
+ paddingVertical: vs(4)
3422
+ },
3423
+ chip: {
3424
+ flexDirection: "row",
3425
+ alignItems: "center",
3426
+ borderRadius: RADIUS.full,
3427
+ borderWidth: 1,
3428
+ paddingHorizontal: s(14),
3429
+ paddingVertical: vs(8),
3430
+ gap: s(6)
3431
+ },
3432
+ chipIcon: {
3433
+ alignItems: "center",
3434
+ justifyContent: "center"
3435
+ },
3436
+ chipLabel: {
3437
+ fontFamily: "Poppins-Medium",
3438
+ fontSize: ms(13)
3439
+ },
3440
+ chipBadge: {
3441
+ minWidth: 16,
3442
+ height: 16,
3443
+ borderRadius: 9999,
3444
+ paddingHorizontal: 3,
3445
+ alignItems: "center",
3446
+ justifyContent: "center"
3447
+ },
3448
+ chipBadgeText: {
3449
+ fontFamily: "Poppins-Bold",
3450
+ fontSize: ms(9),
3451
+ lineHeight: 14
3452
+ }
3453
+ });
3454
+ var nativeDriver14 = reactNative.Platform.OS !== "web";
3455
+ function Pressable2({
3456
+ children,
3457
+ onPress,
3458
+ pressScale = 0.98,
3459
+ bounciness = 4,
3460
+ haptics = true,
3461
+ style,
3462
+ disabled,
3463
+ hoverScale = 1.02,
3464
+ ...touchableProps
3465
+ }) {
3466
+ const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
3467
+ const { hovered, hoverHandlers } = useHover();
3468
+ const handlePressIn = () => {
3469
+ if (disabled) return;
3470
+ reactNative.Animated.spring(scale2, {
3471
+ toValue: pressScale,
3472
+ useNativeDriver: nativeDriver14,
3473
+ speed: 40,
3474
+ bounciness: 0
3475
+ }).start();
3476
+ };
3477
+ const handlePressOut = () => {
3478
+ if (disabled) return;
3479
+ reactNative.Animated.spring(scale2, {
3480
+ toValue: 1,
3481
+ useNativeDriver: nativeDriver14,
3482
+ speed: 40,
3483
+ bounciness
3484
+ }).start();
3485
+ };
3486
+ const handlePress = () => {
3487
+ if (disabled || !onPress) return;
3488
+ if (haptics) impactLight();
3489
+ onPress();
3490
+ };
3491
+ const hoverScaleValue = hovered && hoverScale !== 1 ? hoverScale : 1;
3492
+ return /* @__PURE__ */ React25__default.default.createElement(
3493
+ reactNative.Animated.View,
3494
+ {
3495
+ style: [
3496
+ { transform: [{ scale: reactNative.Animated.multiply(scale2, hoverScaleValue) }] },
3497
+ style
3498
+ ],
3499
+ ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
3500
+ },
3501
+ /* @__PURE__ */ React25__default.default.createElement(
3502
+ reactNative.TouchableOpacity,
3503
+ {
3504
+ onPress: handlePress,
3505
+ onPressIn: handlePressIn,
3506
+ onPressOut: handlePressOut,
3507
+ activeOpacity: 1,
3508
+ disabled,
3509
+ touchSoundDisabled: true,
3510
+ ...touchableProps
3511
+ },
3512
+ children
3513
+ )
3514
+ );
3515
+ }
2799
3516
 
2800
3517
  Object.defineProperty(exports, "BottomSheetModalProvider", {
2801
3518
  enumerable: true,
@@ -2813,6 +3530,7 @@ exports.CardDescription = CardDescription;
2813
3530
  exports.CardFooter = CardFooter;
2814
3531
  exports.CardHeader = CardHeader;
2815
3532
  exports.CardTitle = CardTitle;
3533
+ exports.CategoryStrip = CategoryStrip;
2816
3534
  exports.Checkbox = Checkbox;
2817
3535
  exports.Chip = Chip;
2818
3536
  exports.ChipGroup = ChipGroup;
@@ -2827,7 +3545,9 @@ exports.IconButton = IconButton;
2827
3545
  exports.Input = Input;
2828
3546
  exports.LabelValue = LabelValue;
2829
3547
  exports.ListItem = ListItem;
3548
+ exports.MediaCard = MediaCard;
2830
3549
  exports.MonthPicker = MonthPicker;
3550
+ exports.Pressable = Pressable2;
2831
3551
  exports.Progress = Progress;
2832
3552
  exports.RADIUS = RADIUS;
2833
3553
  exports.RadioGroup = RadioGroup;
@@ -2840,15 +3560,17 @@ exports.Skeleton = Skeleton;
2840
3560
  exports.Slider = Slider;
2841
3561
  exports.Spinner = Spinner;
2842
3562
  exports.Switch = Switch;
3563
+ exports.TYPOGRAPHY = TYPOGRAPHY;
2843
3564
  exports.Tabs = Tabs;
2844
3565
  exports.TabsContent = TabsContent;
2845
- exports.Text = Text2;
3566
+ exports.Text = Text3;
2846
3567
  exports.Textarea = Textarea;
2847
3568
  exports.ThemeProvider = ThemeProvider;
2848
3569
  exports.ToastProvider = ToastProvider;
2849
3570
  exports.Toggle = Toggle;
2850
3571
  exports.defaultDark = defaultDark;
2851
3572
  exports.defaultLight = defaultLight;
3573
+ exports.deriveColors = deriveColors;
2852
3574
  exports.renderIcon = renderIcon;
2853
3575
  exports.useTheme = useTheme;
2854
3576
  exports.useToast = useToast;