@retray-dev/ui-kit 4.0.0 → 5.2.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 +1806 -663
  2. package/README.md +14 -10
  3. package/dist/index.d.mts +274 -85
  4. package/dist/index.d.ts +274 -85
  5. package/dist/index.js +1048 -321
  6. package/dist/index.mjs +1046 -324
  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 +9 -9
  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 +35 -15
  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,9 @@ function Sheet({
1757
2159
  title,
1758
2160
  description,
1759
2161
  children,
1760
- style
2162
+ style,
2163
+ scrollable,
2164
+ maxHeight
1761
2165
  }) {
1762
2166
  const { colors } = useTheme();
1763
2167
  const ref = React25.useRef(null);
@@ -1778,6 +2182,8 @@ function Sheet({
1778
2182
  pressBehavior: "close"
1779
2183
  }
1780
2184
  );
2185
+ const headerNode = 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;
2186
+ const useScroll = scrollable || !!maxHeight;
1781
2187
  return /* @__PURE__ */ React25__default.default.createElement(
1782
2188
  bottomSheet.BottomSheetModal,
1783
2189
  {
@@ -1789,7 +2195,7 @@ function Sheet({
1789
2195
  handleIndicatorStyle: [styles21.handle, { backgroundColor: colors.border }],
1790
2196
  enablePanDownToClose: true
1791
2197
  },
1792
- /* @__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)
2198
+ /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: maxHeight ? { maxHeight } : void 0 }, useScroll ? /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetScrollView, { contentContainerStyle: [styles21.content, style] }, headerNode, children) : /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: [styles21.content, style] }, headerNode, children))
1793
2199
  );
1794
2200
  }
1795
2201
  var styles21 = reactNative.StyleSheet.create({
@@ -1888,14 +2294,14 @@ function Select({
1888
2294
  {
1889
2295
  style: [
1890
2296
  styles22.triggerText,
1891
- { color: selected ? colors.foreground : colors.mutedForeground }
2297
+ { color: selected ? colors.foreground : colors.foregroundMuted }
1892
2298
  ],
1893
2299
  numberOfLines: 1,
1894
2300
  allowFontScaling: true
1895
2301
  },
1896
2302
  selected?.label ?? placeholder
1897
2303
  ),
1898
- /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-down", size: 20, color: colors.mutedForeground })
2304
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-down", size: 20, color: colors.foregroundMuted })
1899
2305
  )) : null, isIOS ? /* @__PURE__ */ React25__default.default.createElement(
1900
2306
  reactNative.Modal,
1901
2307
  {
@@ -1912,7 +2318,7 @@ function Select({
1912
2318
  onValueChange: (val) => setPendingValue(val),
1913
2319
  itemStyle: { color: colors.foreground }
1914
2320
  },
1915
- !value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.mutedForeground, enabled: false }) : null,
2321
+ !value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.foregroundMuted, enabled: false }) : null,
1916
2322
  options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
1917
2323
  picker.Picker.Item,
1918
2324
  {
@@ -1920,7 +2326,7 @@ function Select({
1920
2326
  label: o.label,
1921
2327
  value: o.value,
1922
2328
  enabled: !o.disabled,
1923
- color: o.disabled ? colors.mutedForeground : colors.foreground
2329
+ color: o.disabled ? colors.foregroundMuted : colors.foreground
1924
2330
  }
1925
2331
  ))
1926
2332
  ))
@@ -1964,7 +2370,7 @@ function Select({
1964
2370
  styles22.webPicker,
1965
2371
  {
1966
2372
  borderColor: error ? colors.destructive : colors.border,
1967
- color: selected ? colors.foreground : colors.mutedForeground,
2373
+ color: selected ? colors.foreground : colors.foregroundMuted,
1968
2374
  backgroundColor: colors.background,
1969
2375
  opacity: disabled ? 0.45 : 1
1970
2376
  }
@@ -2099,22 +2505,42 @@ function ToastNotification({ item, onDismiss }) {
2099
2505
  }));
2100
2506
  const variant = item.variant ?? "default";
2101
2507
  const bgColor = {
2102
- default: colors.foreground,
2508
+ default: colors.card,
2509
+ destructive: colors.destructiveTint,
2510
+ success: colors.successTint,
2511
+ warning: colors.warningTint
2512
+ }[variant];
2513
+ const borderColor = {
2514
+ default: colors.border,
2103
2515
  destructive: colors.destructiveBorder,
2104
- success: colors.successBorder
2516
+ success: colors.successBorder,
2517
+ warning: colors.warningBorder
2105
2518
  }[variant];
2106
- const textColor = {
2107
- default: colors.background,
2108
- destructive: "#991b1b",
2109
- success: "#166534"
2519
+ const accentColor = {
2520
+ default: colors.primary,
2521
+ destructive: colors.destructive,
2522
+ success: colors.success,
2523
+ warning: colors.warning
2110
2524
  }[variant];
2111
- const borderColor = textColor;
2112
- 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 });
2113
- const leftIcon = item.iconName ? renderIcon(item.iconName, 22, item.iconColor ?? textColor) : item.icon ?? defaultIcon;
2114
- 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 }))));
2115
- }
2116
- function ToastProvider({ children }) {
2117
- const [toasts, setToasts] = React25.useState([]);
2525
+ const titleColor = variant === "default" ? colors.foreground : accentColor;
2526
+ const descColor = variant === "default" ? colors.foregroundMuted : accentColor;
2527
+ 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 });
2528
+ const leftIcon = item.iconName ? renderIcon(item.iconName, 16, item.iconColor ?? accentColor) : item.icon ?? defaultIcon;
2529
+ 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(
2530
+ reactNative.TouchableOpacity,
2531
+ {
2532
+ onPress: () => {
2533
+ item.action.onPress();
2534
+ onDismiss();
2535
+ },
2536
+ style: styles23.actionButton,
2537
+ touchSoundDisabled: true
2538
+ },
2539
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.actionLabel, { color: accentColor }], allowFontScaling: true }, item.action.label)
2540
+ ), /* @__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 }))));
2541
+ }
2542
+ function ToastProvider({ children }) {
2543
+ const [toasts, setToasts] = React25.useState([]);
2118
2544
  const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
2119
2545
  const toast = React25.useCallback((item) => {
2120
2546
  const id = Math.random().toString(36).slice(2);
@@ -2122,6 +2548,8 @@ function ToastProvider({ children }) {
2122
2548
  notificationSuccess();
2123
2549
  } else if (item.variant === "destructive") {
2124
2550
  notificationError();
2551
+ } else if (item.variant === "warning") {
2552
+ notificationError();
2125
2553
  } else {
2126
2554
  impactLight();
2127
2555
  }
@@ -2148,38 +2576,52 @@ var styles23 = reactNative.StyleSheet.create({
2148
2576
  },
2149
2577
  toast: {
2150
2578
  flexDirection: "row",
2151
- alignItems: "center",
2152
- borderRadius: ms(12),
2153
- borderWidth: 1,
2154
- paddingHorizontal: s(14),
2155
- paddingVertical: vs(12),
2579
+ alignItems: "flex-start",
2580
+ borderRadius: ms(10),
2581
+ borderWidth: 0.5,
2582
+ paddingHorizontal: s(12),
2583
+ paddingVertical: vs(10),
2156
2584
  shadowColor: "#000",
2157
- shadowOffset: { width: 0, height: 3 },
2158
- shadowOpacity: 0.1,
2159
- shadowRadius: 8,
2160
- elevation: 5
2585
+ shadowOffset: { width: 0, height: 2 },
2586
+ shadowOpacity: 0.06,
2587
+ shadowRadius: 4,
2588
+ elevation: 3
2161
2589
  },
2162
2590
  toastContent: {
2163
2591
  flex: 1,
2164
- gap: vs(4)
2592
+ gap: vs(2)
2165
2593
  },
2166
2594
  leftIconContainer: {
2167
- width: s(28),
2595
+ marginTop: vs(1),
2168
2596
  alignItems: "center",
2169
2597
  justifyContent: "center",
2170
2598
  marginRight: s(10)
2171
2599
  },
2172
2600
  toastTitle: {
2173
- fontFamily: "Poppins-SemiBold",
2174
- fontSize: ms(15)
2601
+ fontFamily: "Poppins-Medium",
2602
+ fontSize: ms(13),
2603
+ lineHeight: ms(18)
2175
2604
  },
2176
2605
  toastDescription: {
2177
2606
  fontFamily: "Poppins-Regular",
2178
- fontSize: ms(14)
2607
+ fontSize: ms(12),
2608
+ lineHeight: ms(17),
2609
+ opacity: 0.85
2179
2610
  },
2180
- dismissButton: {
2181
- padding: s(8),
2611
+ actionButton: {
2612
+ paddingHorizontal: s(8),
2613
+ paddingVertical: vs(4),
2182
2614
  marginLeft: s(4)
2615
+ },
2616
+ actionLabel: {
2617
+ fontFamily: "Poppins-Medium",
2618
+ fontSize: ms(12),
2619
+ textDecorationLine: "underline"
2620
+ },
2621
+ dismissButton: {
2622
+ padding: s(6),
2623
+ marginLeft: s(2),
2624
+ marginTop: vs(0)
2183
2625
  }
2184
2626
  });
2185
2627
  function formatCurrency(raw, separator) {
@@ -2213,7 +2655,7 @@ function CurrencyInput({
2213
2655
  onChangeValue?.(isNaN(raw) ? 0 : raw);
2214
2656
  };
2215
2657
  const inputStyle = size === "large" ? { fontFamily: "Poppins-Regular", fontSize: ms(36) } : { fontFamily: "Poppins-Regular" };
2216
- const dollarIcon = renderIcon("dollar-sign", size === "large" ? 24 : 16, colors.mutedForeground);
2658
+ const dollarIcon = renderIcon("dollar-sign", size === "large" ? 24 : 16, colors.foregroundMuted);
2217
2659
  const displayValue = value && prefix && value.startsWith(prefix) ? value.slice(prefix.length) : value;
2218
2660
  return /* @__PURE__ */ React25__default.default.createElement(
2219
2661
  Input,
@@ -2228,7 +2670,7 @@ function CurrencyInput({
2228
2670
  editable,
2229
2671
  prefix: dollarIcon,
2230
2672
  containerStyle,
2231
- inputWrapperStyle: size === "large" ? { paddingVertical: 10 } : void 0,
2673
+ inputWrapperStyle: size === "large" ? { paddingVertical: vs(16), minHeight: 72 } : void 0,
2232
2674
  style: [inputStyle, style]
2233
2675
  }
2234
2676
  );
@@ -2254,7 +2696,8 @@ var styles24 = reactNative.StyleSheet.create({
2254
2696
  container: {},
2255
2697
  amount: {
2256
2698
  fontFamily: "Poppins-Bold",
2257
- fontSize: ms(56)
2699
+ fontSize: ms(56),
2700
+ letterSpacing: -2
2258
2701
  }
2259
2702
  });
2260
2703
  var nativeDriver10 = reactNative.Platform.OS !== "web";
@@ -2304,7 +2747,7 @@ function ListItem({
2304
2747
  onPress?.();
2305
2748
  };
2306
2749
  const effectiveLeft = leftIcon ? renderIcon(leftIcon, 24, leftIconColor ?? colors.foreground) : leftRender ?? icon;
2307
- const effectiveRight = rightIcon ? renderIcon(rightIcon, 24, rightIconColor ?? colors.mutedForeground) : rightRender ?? trailing;
2750
+ const effectiveRight = rightIcon ? renderIcon(rightIcon, 24, rightIconColor ?? colors.foregroundMuted) : rightRender ?? trailing;
2308
2751
  const cardStyle = variant === "card" ? {
2309
2752
  backgroundColor: colors.card,
2310
2753
  borderRadius: 12,
@@ -2339,7 +2782,7 @@ function ListItem({
2339
2782
  ), subtitle ? /* @__PURE__ */ React25__default.default.createElement(
2340
2783
  reactNative.Text,
2341
2784
  {
2342
- style: [styles25.subtitle, { color: colors.mutedForeground }, subtitleStyle],
2785
+ style: [styles25.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
2343
2786
  numberOfLines: 2,
2344
2787
  allowFontScaling: true
2345
2788
  },
@@ -2347,7 +2790,7 @@ function ListItem({
2347
2790
  ) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(
2348
2791
  reactNative.Text,
2349
2792
  {
2350
- style: [styles25.caption, { color: colors.mutedForeground }, captionStyle],
2793
+ style: [styles25.caption, { color: colors.foregroundMuted }, captionStyle],
2351
2794
  numberOfLines: 1,
2352
2795
  allowFontScaling: true
2353
2796
  },
@@ -2356,11 +2799,11 @@ function ListItem({
2356
2799
  effectiveRight !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof effectiveRight === "string" ? /* @__PURE__ */ React25__default.default.createElement(
2357
2800
  reactNative.Text,
2358
2801
  {
2359
- style: [styles25.rightText, { color: colors.mutedForeground }],
2802
+ style: [styles25.rightText, { color: colors.foregroundMuted }],
2360
2803
  allowFontScaling: true
2361
2804
  },
2362
2805
  effectiveRight
2363
- ) : effectiveRight) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.mutedForeground }) : null
2806
+ ) : effectiveRight) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.foregroundMuted }) : null
2364
2807
  ), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(
2365
2808
  reactNative.View,
2366
2809
  {
@@ -2462,7 +2905,7 @@ function Chip({ label, selected = false, onPress, icon, iconName, style }) {
2462
2905
  };
2463
2906
  const backgroundColor = pressAnim.interpolate({
2464
2907
  inputRange: [0, 1],
2465
- outputRange: [colors.secondary, colors.primary]
2908
+ outputRange: [colors.surface, colors.primary]
2466
2909
  });
2467
2910
  const textColor = pressAnim.interpolate({
2468
2911
  inputRange: [0, 1],
@@ -2584,16 +3027,7 @@ function ConfirmDialog({
2584
3027
  handleIndicatorStyle: [styles27.handle, { backgroundColor: colors.border }],
2585
3028
  enablePanDownToClose: true
2586
3029
  },
2587
- /* @__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(
2588
- Button,
2589
- {
2590
- label: cancelLabel,
2591
- variant: "outline",
2592
- fullWidth: true,
2593
- onPress: onCancel,
2594
- icon: /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: 15, color: colors.foreground })
2595
- }
2596
- ), /* @__PURE__ */ React25__default.default.createElement(
3030
+ /* @__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(
2597
3031
  Button,
2598
3032
  {
2599
3033
  label: confirmLabel,
@@ -2609,6 +3043,15 @@ function ConfirmDialog({
2609
3043
  }
2610
3044
  )
2611
3045
  }
3046
+ ), /* @__PURE__ */ React25__default.default.createElement(
3047
+ Button,
3048
+ {
3049
+ label: cancelLabel,
3050
+ variant: "secondary",
3051
+ fullWidth: true,
3052
+ onPress: onCancel,
3053
+ icon: /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: 15, color: colors.foreground })
3054
+ }
2612
3055
  )))
2613
3056
  );
2614
3057
  }
@@ -2644,7 +3087,7 @@ var styles27 = reactNative.StyleSheet.create({
2644
3087
  });
2645
3088
  function LabelValue({ label, value, style }) {
2646
3089
  const { colors } = useTheme();
2647
- 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);
3090
+ 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);
2648
3091
  }
2649
3092
  var styles28 = reactNative.StyleSheet.create({
2650
3093
  container: {
@@ -2737,64 +3180,343 @@ var styles29 = reactNative.StyleSheet.create({
2737
3180
  minWidth: s(160)
2738
3181
  }
2739
3182
  });
3183
+ function useHover() {
3184
+ const [hovered, setHovered] = React25.useState(false);
3185
+ const onMouseEnter = React25.useCallback(() => setHovered(true), []);
3186
+ const onMouseLeave = React25.useCallback(() => setHovered(false), []);
3187
+ if (reactNative.Platform.OS !== "web") {
3188
+ return { hovered: false, hoverHandlers: {} };
3189
+ }
3190
+ return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
3191
+ }
2740
3192
 
2741
- // src/tokens.ts
2742
- var SPACING = {
2743
- xs: 4,
2744
- sm: 8,
2745
- md: 12,
2746
- lg: 16,
2747
- xl: 24,
2748
- "2xl": 32,
2749
- "3xl": 48
3193
+ // src/components/MediaCard/MediaCard.tsx
3194
+ var nativeDriver12 = reactNative.Platform.OS !== "web";
3195
+ var aspectRatioMap = {
3196
+ "1:1": 1,
3197
+ "4:3": 3 / 4,
3198
+ "16:9": 9 / 16,
3199
+ "4:5": 5 / 4,
3200
+ "3:2": 2 / 3
2750
3201
  };
2751
- var ICON_SIZES = {
2752
- sm: 14,
2753
- md: 18,
2754
- lg: 22,
2755
- xl: 28,
2756
- "2xl": 32
2757
- };
2758
- var RADIUS = {
2759
- sm: 4,
2760
- md: 8,
2761
- lg: 12,
2762
- xl: 16,
2763
- full: 9999
2764
- };
2765
- var SHADOWS = {
2766
- sm: {
2767
- shadowColor: "#000",
2768
- shadowOffset: { width: 0, height: 1 },
2769
- shadowOpacity: 0.08,
2770
- shadowRadius: 4,
2771
- elevation: 2
3202
+ function MediaCard({
3203
+ imageSource,
3204
+ aspectRatio = "4:3",
3205
+ badge,
3206
+ actionIcon,
3207
+ actionIconName,
3208
+ actionActive = false,
3209
+ onActionPress,
3210
+ title,
3211
+ subtitle,
3212
+ caption,
3213
+ onPress,
3214
+ style,
3215
+ imageStyle,
3216
+ footer
3217
+ }) {
3218
+ const { colors } = useTheme();
3219
+ const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
3220
+ const { hovered, hoverHandlers } = useHover();
3221
+ const handlePressIn = () => {
3222
+ if (!onPress) return;
3223
+ reactNative.Animated.spring(scale2, { toValue: 0.98, useNativeDriver: nativeDriver12, speed: 40, bounciness: 0 }).start();
3224
+ };
3225
+ const handlePressOut = () => {
3226
+ if (!onPress) return;
3227
+ reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver12, speed: 40, bounciness: 4 }).start();
3228
+ };
3229
+ const handlePress = () => {
3230
+ if (!onPress) return;
3231
+ impactLight();
3232
+ onPress();
3233
+ };
3234
+ const ratio = aspectRatioMap[aspectRatio];
3235
+ const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
3236
+ const cardContent = /* @__PURE__ */ React25__default.default.createElement(
3237
+ reactNative.View,
3238
+ {
3239
+ style: [
3240
+ styles30.card,
3241
+ hovered && styles30.cardHovered,
3242
+ style
3243
+ ],
3244
+ ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
3245
+ },
3246
+ /* @__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(
3247
+ reactNative.Image,
3248
+ {
3249
+ source: imageSource,
3250
+ style: styles30.image,
3251
+ resizeMode: "cover"
3252
+ }
3253
+ ) : /* @__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(
3254
+ reactNative.TouchableOpacity,
3255
+ {
3256
+ style: [styles30.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
3257
+ onPress: () => {
3258
+ impactLight();
3259
+ onActionPress?.();
3260
+ },
3261
+ activeOpacity: 0.8,
3262
+ touchSoundDisabled: true
3263
+ },
3264
+ resolvedActionIcon
3265
+ )),
3266
+ (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)
3267
+ );
3268
+ if (onPress) {
3269
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { transform: [{ scale: scale2 }] } }, /* @__PURE__ */ React25__default.default.createElement(
3270
+ reactNative.TouchableOpacity,
3271
+ {
3272
+ onPress: handlePress,
3273
+ onPressIn: handlePressIn,
3274
+ onPressOut: handlePressOut,
3275
+ activeOpacity: 1,
3276
+ touchSoundDisabled: true
3277
+ },
3278
+ cardContent
3279
+ ));
3280
+ }
3281
+ return cardContent;
3282
+ }
3283
+ var styles30 = reactNative.StyleSheet.create({
3284
+ card: {
3285
+ borderRadius: RADIUS.md,
3286
+ // 14px — Airbnb property card spec
3287
+ overflow: "hidden",
3288
+ backgroundColor: "transparent"
2772
3289
  },
2773
- md: {
2774
- shadowColor: "#000",
2775
- shadowOffset: { width: 0, height: 3 },
2776
- shadowOpacity: 0.12,
2777
- shadowRadius: 8,
2778
- elevation: 5
3290
+ cardHovered: {
3291
+ // Web hover: lift shadow
3292
+ ...SHADOWS.md
2779
3293
  },
2780
- lg: {
2781
- shadowColor: "#000",
2782
- shadowOffset: { width: 0, height: 6 },
2783
- shadowOpacity: 0.2,
2784
- shadowRadius: 16,
2785
- elevation: 10
3294
+ imageContainer: {
3295
+ borderRadius: RADIUS.md,
3296
+ overflow: "hidden"
2786
3297
  },
2787
- xl: {
2788
- shadowColor: "#000",
2789
- shadowOffset: { width: 0, height: 12 },
2790
- shadowOpacity: 0.28,
2791
- shadowRadius: 24,
2792
- elevation: 18
3298
+ image: {
3299
+ width: "100%",
3300
+ height: "100%"
3301
+ },
3302
+ imagePlaceholder: {
3303
+ width: "100%",
3304
+ height: "100%"
3305
+ },
3306
+ badgeContainer: {
3307
+ position: "absolute",
3308
+ top: s(8),
3309
+ left: s(8)
3310
+ },
3311
+ actionButton: {
3312
+ position: "absolute",
3313
+ top: s(8),
3314
+ right: s(8),
3315
+ width: s(32),
3316
+ height: s(32),
3317
+ borderRadius: 9999,
3318
+ alignItems: "center",
3319
+ justifyContent: "center"
3320
+ },
3321
+ meta: {
3322
+ paddingTop: vs(8),
3323
+ gap: vs(2)
3324
+ },
3325
+ title: {
3326
+ fontFamily: "Poppins-SemiBold",
3327
+ fontSize: ms(14),
3328
+ lineHeight: mvs(20)
3329
+ },
3330
+ subtitle: {
3331
+ fontFamily: "Poppins-Regular",
3332
+ fontSize: ms(13),
3333
+ lineHeight: mvs(18)
3334
+ },
3335
+ caption: {
3336
+ fontFamily: "Poppins-Regular",
3337
+ fontSize: ms(12),
3338
+ lineHeight: mvs(16)
2793
3339
  }
2794
- };
2795
- var BREAKPOINTS = {
2796
- wide: 700
2797
- };
3340
+ });
3341
+ var nativeDriver13 = reactNative.Platform.OS !== "web";
3342
+ function CategoryChip({
3343
+ item,
3344
+ selected,
3345
+ onPress
3346
+ }) {
3347
+ const { colors } = useTheme();
3348
+ const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
3349
+ const handlePressIn = () => {
3350
+ reactNative.Animated.spring(scale2, { toValue: 0.95, useNativeDriver: nativeDriver13, speed: 40, bounciness: 0 }).start();
3351
+ };
3352
+ const handlePressOut = () => {
3353
+ reactNative.Animated.spring(scale2, { toValue: 1, useNativeDriver: nativeDriver13, speed: 40, bounciness: 4 }).start();
3354
+ };
3355
+ const bgColor = selected ? colors.primary : colors.surface;
3356
+ const textColor = selected ? colors.primaryForeground : colors.foregroundSubtle;
3357
+ const borderColor = selected ? colors.primary : colors.border;
3358
+ const resolvedIcon = typeof item.icon === "string" ? renderIcon(item.icon, 16, textColor) : item.icon ?? null;
3359
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Animated.View, { style: { transform: [{ scale: scale2 }] } }, /* @__PURE__ */ React25__default.default.createElement(
3360
+ reactNative.TouchableOpacity,
3361
+ {
3362
+ style: [
3363
+ styles31.chip,
3364
+ {
3365
+ backgroundColor: bgColor,
3366
+ borderColor
3367
+ }
3368
+ ],
3369
+ onPress,
3370
+ onPressIn: handlePressIn,
3371
+ onPressOut: handlePressOut,
3372
+ activeOpacity: 1,
3373
+ touchSoundDisabled: true
3374
+ },
3375
+ resolvedIcon && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles31.chipIcon }, resolvedIcon),
3376
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.chipLabel, { color: textColor }], allowFontScaling: true }, item.label),
3377
+ 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)))
3378
+ ));
3379
+ }
3380
+ function CategoryStrip({
3381
+ categories,
3382
+ value,
3383
+ onValueChange,
3384
+ multiSelect = false,
3385
+ style,
3386
+ itemStyle
3387
+ }) {
3388
+ const selected = Array.isArray(value) ? value : value ? [value] : [];
3389
+ const handlePress = (v) => {
3390
+ selectionAsync();
3391
+ if (multiSelect) {
3392
+ const current = Array.isArray(value) ? value : value ? [value] : [];
3393
+ const next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];
3394
+ onValueChange?.(next);
3395
+ } else {
3396
+ onValueChange?.(v === value ? "" : v);
3397
+ }
3398
+ };
3399
+ return /* @__PURE__ */ React25__default.default.createElement(
3400
+ reactNative.ScrollView,
3401
+ {
3402
+ horizontal: true,
3403
+ showsHorizontalScrollIndicator: false,
3404
+ contentContainerStyle: [styles31.container, style],
3405
+ style: styles31.scroll
3406
+ },
3407
+ categories.map((cat) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: cat.value, style: itemStyle }, /* @__PURE__ */ React25__default.default.createElement(
3408
+ CategoryChip,
3409
+ {
3410
+ item: cat,
3411
+ selected: selected.includes(cat.value),
3412
+ onPress: () => handlePress(cat.value)
3413
+ }
3414
+ )))
3415
+ );
3416
+ }
3417
+ var styles31 = reactNative.StyleSheet.create({
3418
+ scroll: {
3419
+ flexGrow: 0
3420
+ },
3421
+ container: {
3422
+ flexDirection: "row",
3423
+ gap: s(8),
3424
+ paddingHorizontal: s(4),
3425
+ paddingVertical: vs(4)
3426
+ },
3427
+ chip: {
3428
+ flexDirection: "row",
3429
+ alignItems: "center",
3430
+ borderRadius: RADIUS.full,
3431
+ borderWidth: 1,
3432
+ paddingHorizontal: s(14),
3433
+ paddingVertical: vs(8),
3434
+ gap: s(6)
3435
+ },
3436
+ chipIcon: {
3437
+ alignItems: "center",
3438
+ justifyContent: "center"
3439
+ },
3440
+ chipLabel: {
3441
+ fontFamily: "Poppins-Medium",
3442
+ fontSize: ms(13)
3443
+ },
3444
+ chipBadge: {
3445
+ minWidth: 16,
3446
+ height: 16,
3447
+ borderRadius: 9999,
3448
+ paddingHorizontal: 3,
3449
+ alignItems: "center",
3450
+ justifyContent: "center"
3451
+ },
3452
+ chipBadgeText: {
3453
+ fontFamily: "Poppins-Bold",
3454
+ fontSize: ms(9),
3455
+ lineHeight: 14
3456
+ }
3457
+ });
3458
+ var nativeDriver14 = reactNative.Platform.OS !== "web";
3459
+ function Pressable2({
3460
+ children,
3461
+ onPress,
3462
+ pressScale = 0.98,
3463
+ bounciness = 4,
3464
+ haptics = true,
3465
+ style,
3466
+ disabled,
3467
+ hoverScale = 1.02,
3468
+ ...touchableProps
3469
+ }) {
3470
+ const scale2 = React25.useRef(new reactNative.Animated.Value(1)).current;
3471
+ const { hovered, hoverHandlers } = useHover();
3472
+ const handlePressIn = () => {
3473
+ if (disabled) return;
3474
+ reactNative.Animated.spring(scale2, {
3475
+ toValue: pressScale,
3476
+ useNativeDriver: nativeDriver14,
3477
+ speed: 40,
3478
+ bounciness: 0
3479
+ }).start();
3480
+ };
3481
+ const handlePressOut = () => {
3482
+ if (disabled) return;
3483
+ reactNative.Animated.spring(scale2, {
3484
+ toValue: 1,
3485
+ useNativeDriver: nativeDriver14,
3486
+ speed: 40,
3487
+ bounciness
3488
+ }).start();
3489
+ };
3490
+ const handlePress = () => {
3491
+ if (disabled || !onPress) return;
3492
+ if (haptics) impactLight();
3493
+ onPress();
3494
+ };
3495
+ const hoverScaleValue = hovered && hoverScale !== 1 ? hoverScale : 1;
3496
+ return /* @__PURE__ */ React25__default.default.createElement(
3497
+ reactNative.Animated.View,
3498
+ {
3499
+ style: [
3500
+ { transform: [{ scale: reactNative.Animated.multiply(scale2, hoverScaleValue) }] },
3501
+ style
3502
+ ],
3503
+ ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
3504
+ },
3505
+ /* @__PURE__ */ React25__default.default.createElement(
3506
+ reactNative.TouchableOpacity,
3507
+ {
3508
+ onPress: handlePress,
3509
+ onPressIn: handlePressIn,
3510
+ onPressOut: handlePressOut,
3511
+ activeOpacity: 1,
3512
+ disabled,
3513
+ touchSoundDisabled: true,
3514
+ ...touchableProps
3515
+ },
3516
+ children
3517
+ )
3518
+ );
3519
+ }
2798
3520
 
2799
3521
  Object.defineProperty(exports, "BottomSheetModalProvider", {
2800
3522
  enumerable: true,
@@ -2812,6 +3534,7 @@ exports.CardDescription = CardDescription;
2812
3534
  exports.CardFooter = CardFooter;
2813
3535
  exports.CardHeader = CardHeader;
2814
3536
  exports.CardTitle = CardTitle;
3537
+ exports.CategoryStrip = CategoryStrip;
2815
3538
  exports.Checkbox = Checkbox;
2816
3539
  exports.Chip = Chip;
2817
3540
  exports.ChipGroup = ChipGroup;
@@ -2826,7 +3549,9 @@ exports.IconButton = IconButton;
2826
3549
  exports.Input = Input;
2827
3550
  exports.LabelValue = LabelValue;
2828
3551
  exports.ListItem = ListItem;
3552
+ exports.MediaCard = MediaCard;
2829
3553
  exports.MonthPicker = MonthPicker;
3554
+ exports.Pressable = Pressable2;
2830
3555
  exports.Progress = Progress;
2831
3556
  exports.RADIUS = RADIUS;
2832
3557
  exports.RadioGroup = RadioGroup;
@@ -2839,15 +3564,17 @@ exports.Skeleton = Skeleton;
2839
3564
  exports.Slider = Slider;
2840
3565
  exports.Spinner = Spinner;
2841
3566
  exports.Switch = Switch;
3567
+ exports.TYPOGRAPHY = TYPOGRAPHY;
2842
3568
  exports.Tabs = Tabs;
2843
3569
  exports.TabsContent = TabsContent;
2844
- exports.Text = Text2;
3570
+ exports.Text = Text3;
2845
3571
  exports.Textarea = Textarea;
2846
3572
  exports.ThemeProvider = ThemeProvider;
2847
3573
  exports.ToastProvider = ToastProvider;
2848
3574
  exports.Toggle = Toggle;
2849
3575
  exports.defaultDark = defaultDark;
2850
3576
  exports.defaultLight = defaultLight;
3577
+ exports.deriveColors = deriveColors;
2851
3578
  exports.renderIcon = renderIcon;
2852
3579
  exports.useTheme = useTheme;
2853
3580
  exports.useToast = useToast;