@retray-dev/ui-kit 12.1.0 → 13.0.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 (282) hide show
  1. package/COMPONENTS.md +183 -147
  2. package/CONSUMER.md +2 -2
  3. package/DESIGN.md +2 -2
  4. package/README.md +13 -8
  5. package/dist/Accordion.d.mts +6 -0
  6. package/dist/Accordion.d.ts +6 -0
  7. package/dist/Accordion.js +62 -208
  8. package/dist/Accordion.mjs +6 -5
  9. package/dist/AlertBanner.js +29 -151
  10. package/dist/AlertBanner.mjs +3 -3
  11. package/dist/AppHeader.js +37 -233
  12. package/dist/AppHeader.mjs +6 -7
  13. package/dist/Avatar.d.mts +17 -1
  14. package/dist/Avatar.d.ts +17 -1
  15. package/dist/Avatar.js +80 -113
  16. package/dist/Avatar.mjs +2 -2
  17. package/dist/Badge.js +24 -147
  18. package/dist/Badge.mjs +3 -3
  19. package/dist/Button.js +86 -274
  20. package/dist/Button.mjs +6 -6
  21. package/dist/Card.js +15 -198
  22. package/dist/Card.mjs +4 -5
  23. package/dist/CategoryStrip.d.mts +0 -5
  24. package/dist/CategoryStrip.d.ts +0 -5
  25. package/dist/CategoryStrip.js +47 -263
  26. package/dist/CategoryStrip.mjs +6 -6
  27. package/dist/Checkbox.js +15 -198
  28. package/dist/Checkbox.mjs +5 -5
  29. package/dist/Chip.js +44 -234
  30. package/dist/Chip.mjs +7 -6
  31. package/dist/ConfirmDialog.js +100 -296
  32. package/dist/ConfirmDialog.mjs +7 -7
  33. package/dist/CurrencyDisplay.js +1 -112
  34. package/dist/CurrencyDisplay.mjs +2 -2
  35. package/dist/CurrencyInput.js +35 -160
  36. package/dist/CurrencyInput.mjs +5 -5
  37. package/dist/DetailRow.js +25 -148
  38. package/dist/DetailRow.mjs +3 -3
  39. package/dist/EmptyState.js +87 -275
  40. package/dist/EmptyState.mjs +7 -7
  41. package/dist/ErrorBoundary.js +32 -197
  42. package/dist/ErrorBoundary.mjs +4 -4
  43. package/dist/Form.js +1 -112
  44. package/dist/Form.mjs +2 -2
  45. package/dist/HolographicCard.d.mts +0 -28
  46. package/dist/HolographicCard.d.ts +0 -28
  47. package/dist/HolographicCard.js +20 -130
  48. package/dist/HolographicCard.mjs +9 -32
  49. package/dist/IconButton.js +36 -232
  50. package/dist/IconButton.mjs +5 -6
  51. package/dist/IconPicker.js +222 -927
  52. package/dist/IconPicker.mjs +5 -5
  53. package/dist/ImageUpload.d.mts +5 -1
  54. package/dist/ImageUpload.d.ts +5 -1
  55. package/dist/ImageUpload.js +32 -215
  56. package/dist/ImageUpload.mjs +5 -6
  57. package/dist/ImageViewer.js +75 -264
  58. package/dist/ImageViewer.mjs +8 -8
  59. package/dist/Input.d.mts +1 -1
  60. package/dist/Input.d.ts +1 -1
  61. package/dist/Input.js +35 -160
  62. package/dist/Input.mjs +4 -4
  63. package/dist/LabelValue.js +24 -147
  64. package/dist/LabelValue.mjs +3 -3
  65. package/dist/ListGroup.js +1 -112
  66. package/dist/ListGroup.mjs +2 -2
  67. package/dist/ListItem.js +38 -233
  68. package/dist/ListItem.mjs +5 -6
  69. package/dist/MediaCard.d.mts +0 -14
  70. package/dist/MediaCard.d.ts +0 -14
  71. package/dist/MediaCard.js +69 -313
  72. package/dist/MediaCard.mjs +5 -6
  73. package/dist/MenuGroup.js +1 -112
  74. package/dist/MenuGroup.mjs +2 -2
  75. package/dist/MenuItem.js +36 -232
  76. package/dist/MenuItem.mjs +5 -6
  77. package/dist/MonthPicker.js +8 -161
  78. package/dist/MonthPicker.mjs +3 -3
  79. package/dist/NumberStepper.js +40 -236
  80. package/dist/NumberStepper.mjs +5 -6
  81. package/dist/PagerDots.d.mts +1 -1
  82. package/dist/PagerDots.d.ts +1 -1
  83. package/dist/PagerDots.js +69 -222
  84. package/dist/PagerDots.mjs +6 -5
  85. package/dist/Pressable.js +14 -85
  86. package/dist/Pressable.mjs +4 -4
  87. package/dist/PricingCard.js +94 -279
  88. package/dist/PricingCard.mjs +8 -8
  89. package/dist/Progress.js +3 -121
  90. package/dist/Progress.mjs +3 -3
  91. package/dist/RadioGroup.js +52 -263
  92. package/dist/RadioGroup.mjs +5 -5
  93. package/dist/RetrayProvider.d.mts +1 -1
  94. package/dist/RetrayProvider.d.ts +1 -1
  95. package/dist/RetrayProvider.js +5 -6
  96. package/dist/RetrayProvider.mjs +3 -3
  97. package/dist/Select.d.mts +2 -1
  98. package/dist/Select.d.ts +2 -1
  99. package/dist/Select.js +24 -230
  100. package/dist/Select.mjs +4 -5
  101. package/dist/SelectableCard.d.mts +27 -0
  102. package/dist/SelectableCard.d.ts +27 -0
  103. package/dist/SelectableCard.js +335 -0
  104. package/dist/SelectableCard.mjs +8 -0
  105. package/dist/SelectableGrid.d.mts +0 -21
  106. package/dist/SelectableGrid.d.ts +0 -21
  107. package/dist/SelectableGrid.js +49 -269
  108. package/dist/SelectableGrid.mjs +5 -6
  109. package/dist/Separator.js +1 -112
  110. package/dist/Separator.mjs +2 -2
  111. package/dist/Sheet.js +16 -163
  112. package/dist/Sheet.mjs +3 -3
  113. package/dist/SheetSelect.js +39 -234
  114. package/dist/SheetSelect.mjs +6 -6
  115. package/dist/Skeleton.d.mts +3 -1
  116. package/dist/Skeleton.d.ts +3 -1
  117. package/dist/Skeleton.js +7 -124
  118. package/dist/Skeleton.mjs +3 -3
  119. package/dist/Slider.js +6 -159
  120. package/dist/Slider.mjs +3 -3
  121. package/dist/Spinner.js +3 -114
  122. package/dist/Spinner.mjs +2 -2
  123. package/dist/Stats.d.mts +4 -1
  124. package/dist/Stats.d.ts +4 -1
  125. package/dist/Stats.js +60 -234
  126. package/dist/Stats.mjs +5 -6
  127. package/dist/Switch.js +24 -173
  128. package/dist/Switch.mjs +5 -4
  129. package/dist/TabBar.js +43 -198
  130. package/dist/TabBar.mjs +5 -4
  131. package/dist/Tabs.js +15 -197
  132. package/dist/Tabs.mjs +5 -5
  133. package/dist/Text.js +9 -128
  134. package/dist/Text.mjs +2 -2
  135. package/dist/Textarea.d.mts +2 -1
  136. package/dist/Textarea.d.ts +2 -1
  137. package/dist/Textarea.js +71 -217
  138. package/dist/Textarea.mjs +4 -4
  139. package/dist/Toast.js +1 -112
  140. package/dist/Toast.mjs +2 -2
  141. package/dist/Toggle.js +39 -234
  142. package/dist/Toggle.mjs +6 -6
  143. package/dist/{chunk-FFTYLPSB.mjs → chunk-2QOHHBJC.mjs} +13 -7
  144. package/dist/{chunk-BCWEHE34.mjs → chunk-2VIDP72N.mjs} +3 -3
  145. package/dist/{chunk-PGERH3P7.mjs → chunk-4NQFTHN3.mjs} +13 -7
  146. package/dist/{chunk-3N2M3WZL.mjs → chunk-4ZO5PTKF.mjs} +4 -4
  147. package/dist/{chunk-MYZ2EDYU.mjs → chunk-5MYNAAFE.mjs} +13 -17
  148. package/dist/{chunk-E7NEHHXV.mjs → chunk-62BBSSUF.mjs} +3 -3
  149. package/dist/{chunk-ISY26JQJ.mjs → chunk-6CR4S6W2.mjs} +3 -3
  150. package/dist/{chunk-FUVYSVGR.mjs → chunk-6QLBHUEG.mjs} +8 -7
  151. package/dist/chunk-ARONDO7M.mjs +40 -0
  152. package/dist/{chunk-3UYAZ7I4.mjs → chunk-AZV7KNJI.mjs} +3 -3
  153. package/dist/{chunk-HLMPMUK2.mjs → chunk-BTUW5LSG.mjs} +11 -8
  154. package/dist/chunk-BULKGOIZ.mjs +235 -0
  155. package/dist/{chunk-265G6A46.mjs → chunk-CBIZLRYH.mjs} +29 -12
  156. package/dist/chunk-CM2DG4MR.mjs +142 -0
  157. package/dist/{chunk-2I2AYECM.mjs → chunk-DBHSUUKU.mjs} +2 -2
  158. package/dist/{chunk-P64WHW4A.mjs → chunk-DE25XTVQ.mjs} +3 -3
  159. package/dist/{chunk-DI7CBDL6.mjs → chunk-E4EQSCKR.mjs} +5 -5
  160. package/dist/{chunk-357YO24D.mjs → chunk-EHGBHFMH.mjs} +9 -17
  161. package/dist/{chunk-GK4VRMNE.mjs → chunk-EROPDCB5.mjs} +24 -27
  162. package/dist/{chunk-XBAGGKLW.mjs → chunk-ERWJPVX7.mjs} +2 -2
  163. package/dist/{chunk-LRM4AVYY.mjs → chunk-ESQDPO5E.mjs} +7 -7
  164. package/dist/{chunk-EFLFRAHD.mjs → chunk-EW2FIDSM.mjs} +1 -1
  165. package/dist/{chunk-7HSILTC4.mjs → chunk-FTTI6T5Q.mjs} +4 -4
  166. package/dist/{chunk-X26S5EVZ.mjs → chunk-HUSSF6TF.mjs} +1 -1
  167. package/dist/chunk-IFYMBOEN.mjs +14 -0
  168. package/dist/{chunk-S3KJCPEJ.mjs → chunk-IGU223UM.mjs} +80 -4
  169. package/dist/chunk-IJCMPVW5.mjs +121 -0
  170. package/dist/{chunk-I4V5XZPS.mjs → chunk-ITG4JQM3.mjs} +4 -4
  171. package/dist/{chunk-F4V6XLP4.mjs → chunk-K3QX2M26.mjs} +11 -8
  172. package/dist/{chunk-V6NFJXKO.mjs → chunk-K7TKID3V.mjs} +8 -7
  173. package/dist/{chunk-ZHMSAYLT.mjs → chunk-KAGADD2O.mjs} +4 -4
  174. package/dist/{chunk-3GEYJ7I5.mjs → chunk-KC5QDYGZ.mjs} +4 -4
  175. package/dist/{chunk-HJ46DTJE.mjs → chunk-KPTY7UYQ.mjs} +1 -1
  176. package/dist/{chunk-EMUWGDWC.mjs → chunk-KSSVIFYR.mjs} +11 -12
  177. package/dist/chunk-L3YKPTJQ.mjs +119 -0
  178. package/dist/chunk-M53LC4Q7.mjs +35 -0
  179. package/dist/{chunk-NXI4YDZ2.mjs → chunk-MP7GLMIR.mjs} +17 -25
  180. package/dist/chunk-MZ6WRTD2.mjs +40 -0
  181. package/dist/chunk-NGEN2EES.mjs +581 -0
  182. package/dist/{chunk-JULSIZDM.mjs → chunk-OBV72JD4.mjs} +1 -1
  183. package/dist/{chunk-2A2LEFZG.mjs → chunk-PGQ6FMXS.mjs} +6 -5
  184. package/dist/{chunk-BQZE3HAW.mjs → chunk-PI6RULJX.mjs} +1 -1
  185. package/dist/{chunk-FA2KMTH5.mjs → chunk-RA6SAAFE.mjs} +9 -8
  186. package/dist/{chunk-FVTVCJAH.mjs → chunk-RRKM4MKB.mjs} +7 -7
  187. package/dist/{chunk-AKM4EPOT.mjs → chunk-S2VGME7X.mjs} +1 -1
  188. package/dist/{chunk-OULVKTWL.mjs → chunk-S44XWTTC.mjs} +35 -25
  189. package/dist/{chunk-QSFV2P7O.mjs → chunk-SZEKQAOY.mjs} +1 -1
  190. package/dist/{chunk-N4ZPVCJH.mjs → chunk-TETMEKZE.mjs} +9 -9
  191. package/dist/{chunk-2CBQKU7H.mjs → chunk-TMH263OK.mjs} +5 -4
  192. package/dist/{chunk-D3Y2T42P.mjs → chunk-U6DEBYU5.mjs} +10 -9
  193. package/dist/{chunk-4WFMPFZB.mjs → chunk-UOKFSFNJ.mjs} +2 -2
  194. package/dist/{chunk-WOEWGSTU.mjs → chunk-URIH43IJ.mjs} +13 -21
  195. package/dist/{chunk-JCZQOY4O.mjs → chunk-V2ZB2XNS.mjs} +16 -10
  196. package/dist/{chunk-P73V2EKS.mjs → chunk-WIPEDNSD.mjs} +7 -7
  197. package/dist/{chunk-BOVUP27T.mjs → chunk-XCIG6HT2.mjs} +6 -5
  198. package/dist/chunk-Y6YS33GM.mjs +131 -0
  199. package/dist/{chunk-5OLNXP3S.mjs → chunk-ZKDKKQCE.mjs} +29 -7
  200. package/dist/{chunk-DF6DU42P.mjs → chunk-ZTPYUU5C.mjs} +5 -5
  201. package/dist/{index-wt-orHUi.d.ts → index-CY34hxPN.d.mts} +1 -0
  202. package/dist/{index-wt-orHUi.d.mts → index-CY34hxPN.d.ts} +1 -0
  203. package/dist/index.d.mts +15 -74
  204. package/dist/index.d.ts +15 -74
  205. package/dist/index.js +1055 -1562
  206. package/dist/index.mjs +81 -84
  207. package/package.json +8 -10
  208. package/src/components/Accordion/Accordion.tsx +32 -9
  209. package/src/components/AlertBanner/AlertBanner.tsx +7 -6
  210. package/src/components/AppHeader/AppHeader.tsx +1 -1
  211. package/src/components/Avatar/Avatar.tsx +92 -1
  212. package/src/components/Avatar/index.ts +2 -2
  213. package/src/components/Badge/Badge.tsx +2 -2
  214. package/src/components/Button/Button.tsx +64 -57
  215. package/src/components/Card/Card.tsx +1 -0
  216. package/src/components/CategoryStrip/CategoryStrip.tsx +36 -49
  217. package/src/components/Chip/Chip.tsx +5 -4
  218. package/src/components/ConfirmDialog/ConfirmDialog.tsx +13 -6
  219. package/src/components/DetailRow/DetailRow.tsx +3 -3
  220. package/src/components/EmptyState/EmptyState.tsx +2 -2
  221. package/src/components/ErrorBoundary/ErrorBoundary.tsx +6 -6
  222. package/src/components/HolographicCard/HolographicCard.tsx +14 -95
  223. package/src/components/IconButton/IconButton.tsx +2 -2
  224. package/src/components/IconPicker/IconPicker.tsx +13 -12
  225. package/src/components/ImageUpload/ImageUpload.tsx +24 -28
  226. package/src/components/ImageViewer/ImageViewer.tsx +3 -3
  227. package/src/components/Input/Input.tsx +11 -5
  228. package/src/components/LabelValue/LabelValue.tsx +2 -2
  229. package/src/components/ListItem/ListItem.tsx +4 -4
  230. package/src/components/MediaCard/MediaCard.tsx +21 -59
  231. package/src/components/MenuItem/MenuItem.tsx +2 -2
  232. package/src/components/MonthPicker/MonthPicker.tsx +2 -2
  233. package/src/components/NumberStepper/NumberStepper.tsx +6 -6
  234. package/src/components/PagerDots/PagerDots.tsx +38 -28
  235. package/src/components/PricingCard/PricingCard.tsx +6 -6
  236. package/src/components/RadioGroup/RadioGroup.tsx +18 -31
  237. package/src/components/Select/Select.tsx +32 -39
  238. package/src/components/SelectableCard/SelectableCard.tsx +302 -0
  239. package/src/components/SelectableCard/index.ts +1 -0
  240. package/src/components/SelectableGrid/SelectableGrid.tsx +38 -72
  241. package/src/components/Sheet/Sheet.tsx +11 -4
  242. package/src/components/SheetSelect/SheetSelect.tsx +3 -3
  243. package/src/components/Skeleton/Skeleton.tsx +6 -3
  244. package/src/components/Spinner/Spinner.tsx +2 -2
  245. package/src/components/Stats/Stats.tsx +36 -8
  246. package/src/components/Switch/Switch.tsx +9 -6
  247. package/src/components/TabBar/TabBar.tsx +9 -8
  248. package/src/components/Text/Text.tsx +12 -1
  249. package/src/components/Textarea/Textarea.tsx +18 -32
  250. package/src/components/Toggle/Toggle.tsx +3 -3
  251. package/src/hooks/useConfirmDialog.ts +31 -42
  252. package/src/index.ts +4 -4
  253. package/src/theme/ThemeProvider.tsx +1 -4
  254. package/src/theme/colorUtils.ts +1 -72
  255. package/src/theme/colors.ts +47 -1
  256. package/src/theme/types.ts +6 -3
  257. package/src/utils/animations.ts +0 -47
  258. package/src/utils/curatedIcons.ts +93 -801
  259. package/src/utils/haptics.ts +13 -208
  260. package/src/utils/icons.ts +27 -91
  261. package/src/utils/pressable.ts +10 -61
  262. package/dist/VirtualList.d.mts +0 -19
  263. package/dist/VirtualList.d.ts +0 -19
  264. package/dist/VirtualList.js +0 -38
  265. package/dist/VirtualList.mjs +0 -2
  266. package/dist/chunk-3DKJ2GIC.mjs +0 -30
  267. package/dist/chunk-AQEVCEXV.mjs +0 -164
  268. package/dist/chunk-DOGIPOF5.mjs +0 -131
  269. package/dist/chunk-DVK4G2GT.mjs +0 -59
  270. package/dist/chunk-EJ7ZPXOH.mjs +0 -163
  271. package/dist/chunk-J6Q2YJEV.mjs +0 -134
  272. package/dist/chunk-JNVAIDLK.mjs +0 -136
  273. package/dist/chunk-KA7LTET3.mjs +0 -71
  274. package/dist/chunk-KHYX4IOM.mjs +0 -1114
  275. package/dist/chunk-NC5ZTR2Y.mjs +0 -32
  276. package/dist/chunk-YNROWHQJ.mjs +0 -46
  277. package/src/components/VirtualList/VirtualList.tsx +0 -60
  278. package/src/components/VirtualList/index.ts +0 -1
  279. package/src/utils/fontGuard.ts +0 -35
  280. package/src/utils/hover.ts +0 -25
  281. package/src/utils/useColorTransition.ts +0 -40
  282. package/src/utils/usePressScale.ts +0 -75
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var React54 = require('react');
4
4
  var reactNative = require('react-native');
5
+ var reactNativeEase = require('react-native-ease');
5
6
  var reactNativeSizeMatters = require('react-native-size-matters');
6
7
  var AntDesign = require('@expo/vector-icons/AntDesign');
7
8
  var Entypo = require('@expo/vector-icons/Entypo');
@@ -10,12 +11,12 @@ var FontAwesome5 = require('@expo/vector-icons/FontAwesome5');
10
11
  var MaterialIcons = require('@expo/vector-icons/MaterialIcons');
11
12
  var Ionicons = require('@expo/vector-icons/Ionicons');
12
13
  var pressto = require('pressto');
13
- var Animated12 = require('react-native-reanimated');
14
14
  var expoFont = require('expo-font');
15
15
  var bottomSheet = require('@gorhom/bottom-sheet');
16
- var reactNativeEase = require('react-native-ease');
17
16
  var vectorIcons = require('@expo/vector-icons');
17
+ var Animated6 = require('react-native-reanimated');
18
18
  var expoLinearGradient = require('expo-linear-gradient');
19
+ var expoImage = require('expo-image');
19
20
  var RNSlider = require('@react-native-community/slider');
20
21
  var reactNativeSafeAreaContext = require('react-native-safe-area-context');
21
22
  var picker = require('@react-native-picker/picker');
@@ -31,7 +32,7 @@ var Feather__default = /*#__PURE__*/_interopDefault(Feather);
31
32
  var FontAwesome5__default = /*#__PURE__*/_interopDefault(FontAwesome5);
32
33
  var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
33
34
  var Ionicons__default = /*#__PURE__*/_interopDefault(Ionicons);
34
- var Animated12__default = /*#__PURE__*/_interopDefault(Animated12);
35
+ var Animated6__default = /*#__PURE__*/_interopDefault(Animated6);
35
36
  var RNSlider__default = /*#__PURE__*/_interopDefault(RNSlider);
36
37
 
37
38
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -52,6 +53,13 @@ function hexToRgb(hex) {
52
53
  b: parseInt(full.slice(4, 6), 16)
53
54
  };
54
55
  }
56
+ function withAlpha(hex, alpha) {
57
+ const rgb = hexToRgb(hex);
58
+ if (!rgb) return hex;
59
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
60
+ }
61
+
62
+ // src/theme/colors.ts
55
63
  function componentToHex(c) {
56
64
  return Math.round(Math.max(0, Math.min(255, c))).toString(16).padStart(2, "0");
57
65
  }
@@ -92,13 +100,6 @@ function darken(hex, amount) {
92
100
  if (!rgb) return hex;
93
101
  return rgbToHex(rgb.r * (1 - amount), rgb.g * (1 - amount), rgb.b * (1 - amount));
94
102
  }
95
- function withAlpha(hex, alpha) {
96
- const rgb = hexToRgb(hex);
97
- if (!rgb) return hex;
98
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
99
- }
100
-
101
- // src/theme/colors.ts
102
103
  var defaultLight = {
103
104
  background: "#ffffff",
104
105
  foreground: "#1a1a1a",
@@ -144,6 +145,7 @@ function deriveColors(t, scheme) {
144
145
  const foregroundMuted = mixWithBackground(t.foreground, bg, 0.62);
145
146
  const surface = dark ? lighten(bg, -0.06) : darken(bg, 0.04);
146
147
  const surfaceStrong = dark ? lighten(bg, -0.12) : darken(bg, 0.08);
148
+ const skeleton = dark ? lighten(bg, -0.1) : darken(bg, 0.1);
147
149
  const destructiveTint = dark ? withAlphaOnDark(t.destructive, 0.15, bg) : withAlphaOnWhite(t.destructive, 0.08);
148
150
  const destructiveBorder = dark ? withAlphaOnDark(t.destructive, 0.45, bg) : withAlphaOnWhite(t.destructive, 0.3);
149
151
  const successTint = dark ? withAlphaOnDark(t.success, 0.15, bg) : withAlphaOnWhite(t.success, 0.08);
@@ -156,6 +158,7 @@ function deriveColors(t, scheme) {
156
158
  foregroundMuted,
157
159
  surface,
158
160
  surfaceStrong,
161
+ skeleton,
159
162
  destructiveTint,
160
163
  destructiveBorder,
161
164
  successTint,
@@ -172,10 +175,7 @@ function deriveColors(t, scheme) {
172
175
  }
173
176
 
174
177
  // src/theme/ThemeProvider.tsx
175
- var ThemeContext = React54.createContext({
176
- colors: deriveColors(defaultLight, "light"),
177
- colorScheme: "light"
178
- });
178
+ var ThemeContext = React54.createContext(void 0);
179
179
  function ThemeProvider({ children, theme, colorScheme = "system" }) {
180
180
  const systemScheme = reactNative.useColorScheme() ?? "light";
181
181
  const resolvedScheme = colorScheme === "system" ? systemScheme : colorScheme;
@@ -195,11 +195,11 @@ function useTheme() {
195
195
  return context;
196
196
  }
197
197
  var _haptics = null;
198
- var _hapticsLoaded = false;
198
+ var _loaded = false;
199
199
  async function getHaptics() {
200
200
  if (reactNative.Platform.OS === "web") return null;
201
- if (!_hapticsLoaded) {
202
- _hapticsLoaded = true;
201
+ if (!_loaded) {
202
+ _loaded = true;
203
203
  try {
204
204
  _haptics = await import('expo-haptics');
205
205
  } catch {
@@ -208,214 +208,60 @@ async function getHaptics() {
208
208
  }
209
209
  return _haptics;
210
210
  }
211
- var _pulsar = null;
212
- var _pulsarChecked = false;
213
- var _pulsarAvailable = false;
214
- function isPulsarNativeRegistered() {
215
- try {
216
- const g = globalThis;
217
- if (typeof g.__turboModuleProxy === "function") {
218
- return g.__turboModuleProxy("RNPulsar") != null;
219
- }
220
- return reactNative.NativeModules?.RNPulsar != null;
221
- } catch {
222
- return false;
223
- }
224
- }
225
- function getPulsar() {
226
- if (reactNative.Platform.OS === "web") return null;
227
- if (!_pulsarChecked) {
228
- _pulsarChecked = true;
229
- try {
230
- if (isPulsarNativeRegistered()) {
231
- _pulsar = __require("react-native-pulsar");
232
- _pulsarAvailable = true;
233
- }
234
- } catch {
235
- _pulsar = null;
236
- _pulsarAvailable = false;
237
- }
238
- }
239
- return _pulsarAvailable ? _pulsar : null;
240
- }
241
211
  function selectionAsync() {
242
- if (reactNative.Platform.OS === "web") return;
243
- getHaptics().then((h) => {
244
- if (h) {
245
- h.selectionAsync();
246
- } else {
247
- getPulsar()?.Presets.System.selection();
248
- }
249
- });
212
+ getHaptics().then((h) => h?.selectionAsync());
250
213
  }
251
214
  function impactLight() {
252
- if (reactNative.Platform.OS === "web") return;
253
- getHaptics().then((h) => {
254
- if (h) {
255
- h.impactAsync(h.ImpactFeedbackStyle.Light);
256
- } else {
257
- getPulsar()?.Presets.System.impactLight();
258
- }
259
- });
215
+ getHaptics().then((h) => h?.impactAsync(h.ImpactFeedbackStyle.Light));
260
216
  }
261
217
  function impactMedium() {
262
- if (reactNative.Platform.OS === "web") return;
263
- getHaptics().then((h) => {
264
- if (h) {
265
- h.impactAsync(h.ImpactFeedbackStyle.Medium);
266
- } else {
267
- getPulsar()?.Presets.System.impactMedium();
268
- }
269
- });
218
+ getHaptics().then((h) => h?.impactAsync(h.ImpactFeedbackStyle.Medium));
270
219
  }
271
220
  function impactHeavy() {
272
- if (reactNative.Platform.OS === "web") return;
273
- getHaptics().then((h) => {
274
- if (h) {
275
- h.impactAsync(h.ImpactFeedbackStyle.Heavy);
276
- } else {
277
- getPulsar()?.Presets.System.impactHeavy();
278
- }
279
- });
221
+ getHaptics().then((h) => h?.impactAsync(h.ImpactFeedbackStyle.Heavy));
280
222
  }
281
223
  function notificationSuccess() {
282
- if (reactNative.Platform.OS === "web") return;
283
- getHaptics().then((h) => {
284
- if (h) {
285
- h.notificationAsync(h.NotificationFeedbackType.Success);
286
- } else {
287
- getPulsar()?.Presets.System.notificationSuccess();
288
- }
289
- });
224
+ getHaptics().then((h) => h?.notificationAsync(h.NotificationFeedbackType.Success));
290
225
  }
291
226
  function notificationError() {
292
- if (reactNative.Platform.OS === "web") return;
293
- getHaptics().then((h) => {
294
- if (h) {
295
- h.notificationAsync(h.NotificationFeedbackType.Error);
296
- } else {
297
- getPulsar()?.Presets.System.notificationError();
298
- }
299
- });
227
+ getHaptics().then((h) => h?.notificationAsync(h.NotificationFeedbackType.Error));
300
228
  }
301
229
  function notificationWarning() {
302
- if (reactNative.Platform.OS === "web") return;
303
- getHaptics().then((h) => {
304
- if (h) {
305
- h.notificationAsync(h.NotificationFeedbackType.Warning);
306
- } else {
307
- getPulsar()?.Presets.System.notificationWarning();
308
- }
309
- });
230
+ getHaptics().then((h) => h?.notificationAsync(h.NotificationFeedbackType.Warning));
310
231
  }
311
- var richHaptics = {
312
- /** Hammer strike — strong confirmation feedback. */
313
- hammer: () => {
314
- if (reactNative.Platform.OS === "web") return;
315
- const p = getPulsar();
316
- if (p) p.Presets.hammer();
317
- else impactHeavy();
318
- },
319
- /** Pulse — rhythmic feedback for toggles or state changes. */
320
- pulse: () => {
321
- if (reactNative.Platform.OS === "web") return;
322
- const p = getPulsar();
323
- if (p) p.Presets.pulse();
324
- else selectionAsync();
325
- },
326
- /** Buzz — continuous vibration for attention. */
327
- buzz: () => {
328
- if (reactNative.Platform.OS === "web") return;
329
- const p = getPulsar();
330
- if (p) p.Presets.buzz();
331
- else impactMedium();
332
- },
333
- /** Flick — crisp click feedback. */
334
- flick: () => {
335
- if (reactNative.Platform.OS === "web") return;
336
- const p = getPulsar();
337
- if (p) p.Presets.flick();
338
- else selectionAsync();
339
- },
340
- /** Soft — gentle, subtle feedback. */
341
- soft: () => {
342
- if (reactNative.Platform.OS === "web") return;
343
- const p = getPulsar();
344
- if (p) p.Presets.System.impactSoft();
345
- else impactLight();
346
- },
347
- /** Rigid — firm, solid feedback. */
348
- rigid: () => {
349
- if (reactNative.Platform.OS === "web") return;
350
- const p = getPulsar();
351
- if (p) p.Presets.System.impactRigid();
352
- else impactMedium();
353
- }
354
- };
355
232
  var isWeb = reactNative.Platform.OS === "web";
356
233
  var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
357
234
  var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
358
235
  var ms = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateScale;
359
236
  var mvs = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateVerticalScale;
360
- var glyphMapOf = (mod) => mod.glyphMap ?? {};
361
237
  var ALL_FAMILIES = [
362
- { name: "Ionicons", component: Ionicons__default.default, getGlyphMap: () => glyphMapOf(Ionicons__default.default) },
363
- { name: "MaterialIcons", component: MaterialIcons__default.default, getGlyphMap: () => glyphMapOf(MaterialIcons__default.default) },
364
- { name: "FontAwesome5", component: FontAwesome5__default.default, getGlyphMap: () => glyphMapOf(FontAwesome5__default.default) },
365
- { name: "Entypo", component: Entypo__default.default, getGlyphMap: () => glyphMapOf(Entypo__default.default) },
366
- { name: "AntDesign", component: AntDesign__default.default, getGlyphMap: () => glyphMapOf(AntDesign__default.default) },
367
- { name: "Feather", component: Feather__default.default, getGlyphMap: () => glyphMapOf(Feather__default.default) }
238
+ { name: "Feather", component: Feather__default.default },
239
+ { name: "AntDesign", component: AntDesign__default.default },
240
+ { name: "Entypo", component: Entypo__default.default },
241
+ { name: "FontAwesome5", component: FontAwesome5__default.default },
242
+ { name: "MaterialIcons", component: MaterialIcons__default.default },
243
+ { name: "Ionicons", component: Ionicons__default.default }
368
244
  ];
369
- var activeFamilies = ALL_FAMILIES;
370
- var resolvedCache = null;
371
- function configureIconFamilies(families) {
372
- const order = families.map((n) => ALL_FAMILIES.find((f) => f.name === n)).filter((f) => f !== void 0);
373
- activeFamilies = order.length > 0 ? order : ALL_FAMILIES;
374
- resolvedCache = null;
375
- }
376
- function buildCache(families) {
377
- const cache = /* @__PURE__ */ new Map();
378
- for (const family of families ?? activeFamilies) {
379
- const glyphMap = family.getGlyphMap();
380
- for (const iconName of Object.keys(glyphMap)) {
381
- cache.set(iconName, family);
245
+ var glyphCacheInitialized = false;
246
+ function ensureGlyphCache() {
247
+ if (glyphCacheInitialized) return;
248
+ glyphCacheInitialized = true;
249
+ for (const entry of ALL_FAMILIES) {
250
+ try {
251
+ entry.glyphMap = entry.component.glyphMap;
252
+ } catch {
253
+ entry.glyphMap = {};
382
254
  }
383
255
  }
384
- return cache;
385
- }
386
- function resolveFamily(name) {
387
- if (!resolvedCache) {
388
- resolvedCache = buildCache();
389
- }
390
- return resolvedCache.get(name) ?? null;
391
- }
392
- var cachedIconNames = null;
393
- function getValidIconNames(families) {
394
- if (families && families.length > 0) {
395
- const tempFamilies = families.map((n) => ALL_FAMILIES.find((f) => f.name === n)).filter((f) => f !== void 0);
396
- if (tempFamilies.length === 0) return [];
397
- const cache = buildCache(tempFamilies);
398
- return Array.from(cache.keys());
399
- }
400
- if (!cachedIconNames) {
401
- const cache = buildCache();
402
- cachedIconNames = Array.from(cache.keys());
403
- }
404
- return cachedIconNames;
405
256
  }
406
257
  function Icon({ name, size, color, family }) {
407
- let resolved = null;
408
- if (family) {
409
- resolved = ALL_FAMILIES.find((f) => f.name === family) ?? null;
410
- } else {
411
- resolved = resolveFamily(name);
412
- }
413
- if (!resolved) return null;
414
- const Component = resolved.component;
415
- return React54__default.default.createElement(Component, { name, size, color });
416
- }
417
- function renderIcon(name, size, color) {
418
- return React54__default.default.createElement(Icon, { name, size, color });
258
+ ensureGlyphCache();
259
+ const entry = family ? ALL_FAMILIES.find((f) => f.name === family) : ALL_FAMILIES.find((f) => {
260
+ const glyphMap = f.glyphMap;
261
+ return glyphMap ? name in glyphMap : false;
262
+ });
263
+ if (!entry) return null;
264
+ return React54__default.default.createElement(entry.component, { name, size, color });
419
265
  }
420
266
 
421
267
  // src/tokens.ts
@@ -607,35 +453,25 @@ var TYPOGRAPHY = {
607
453
  letterSpacing: 0
608
454
  }
609
455
  };
456
+ var makePressable = (scale2) => pressto.createAnimatedPressable((progress) => {
457
+ "worklet";
458
+ return { transform: [{ scale: 1 - (1 - scale2) * progress }] };
459
+ });
460
+ var PressableButton = makePressable(0.95);
461
+ var PressableCard = makePressable(0.98);
462
+ var PressableRow = makePressable(0.97);
463
+ var PressableChip = makePressable(0.94);
464
+ var PressableTab = makePressable(0.95);
465
+
466
+ // src/utils/animations.ts
610
467
  var SPRINGS = {
611
- /** Tight, premium press feel — Buttons, Toggle, Tabs triggers. */
612
- pressIn: { stiffness: 600, damping: 35, mass: 0.8 },
613
- pressOut: { stiffness: 280, damping: 22, mass: 0.8 },
614
- /** Slightly softer for larger surfaces — Card, ListItem, MenuItem. */
615
- surfacePressIn: { stiffness: 380, damping: 30, mass: 0.95 },
616
- surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 },
617
- /** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
618
468
  glide: { stiffness: 380, damping: 38, mass: 1 }};
619
469
  var TIMINGS = {
620
- /** Color/opacity transitions on toggles, checkboxes, switches. */
621
470
  state: { duration: 160 },
622
- /** Focus ring on inputs. */
623
- focusIn: { duration: 140 },
624
- focusOut: { duration: 100 },
625
- /** Accordion / collapsible content. */
626
471
  expand: { duration: 240 },
627
472
  collapse: { duration: 200 },
628
- /** Skeleton shimmer cycle (full pass). */
629
473
  shimmer: { duration: 1400 }
630
474
  };
631
- var EASINGS = {
632
- /** Material-style ease-out — natural deceleration for state changes. */
633
- standard: Animated12.Easing.bezier(0.2, 0, 0, 1),
634
- /** Strong ease-out for expanding surfaces (Accordion open). */
635
- expand: Animated12.Easing.bezier(0.23, 1, 0.32, 1),
636
- /** Quick ease-in for collapsing. */
637
- collapse: Animated12.Easing.in(Animated12.Easing.ease)
638
- };
639
475
  var COLOR_TRANSITION = {
640
476
  type: "timing",
641
477
  duration: TIMINGS.state.duration,
@@ -653,36 +489,7 @@ var SPRING_ELASTIC = {
653
489
  mass: 0.7
654
490
  };
655
491
  var PRESS_SCALE = {
656
- button: 0.95,
657
- card: 0.98,
658
- row: 0.97,
659
- chip: 0.94
660
- };
661
- var PressableButton = pressto.createAnimatedPressable((progress) => {
662
- "worklet";
663
- const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
664
- return { transform: [{ scale: scale2 }] };
665
- });
666
- var PressableCard = pressto.createAnimatedPressable((progress) => {
667
- "worklet";
668
- const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
669
- return { transform: [{ scale: scale2 }] };
670
- });
671
- var PressableRow = pressto.createAnimatedPressable((progress) => {
672
- "worklet";
673
- const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
674
- return { transform: [{ scale: scale2 }] };
675
- });
676
- var PressableChip = pressto.createAnimatedPressable((progress) => {
677
- "worklet";
678
- const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
679
- return { transform: [{ scale: scale2 }] };
680
- });
681
- var PressableTab = pressto.createAnimatedPressable((progress) => {
682
- "worklet";
683
- const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
684
- return { transform: [{ scale: scale2 }] };
685
- });
492
+ card: 0.98};
686
493
 
687
494
  // src/components/Button/Button.tsx
688
495
  var containerSizeStyles = {
@@ -719,38 +526,25 @@ function ButtonBase({
719
526
  impactMedium();
720
527
  onPress?.();
721
528
  };
722
- const containerVariantStyle = {
723
- primary: { backgroundColor: colors.primary },
724
- secondary: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.primary },
725
- text: { backgroundColor: "transparent" },
726
- destructive: { backgroundColor: colors.destructive }
727
- }[variant];
728
- const labelVariantStyle = {
729
- primary: { color: colors.primaryForeground },
730
- secondary: { color: colors.primary },
731
- // AUDIT FIX: was colors.foreground — visually indistinguishable from plain text,
732
- // no affordance that it's a CTA. Now uses accentResolved so text-only buttons
733
- // carry the brand voltage. Falls back to primary when no accent is defined.
734
- text: { color: colors.accentResolved },
735
- destructive: { color: colors.destructiveForeground }
529
+ const isSecondary = variant === "secondary";
530
+ const borderWidth = isSecondary ? 1.5 : 0;
531
+ const animateBgColor = isDisabled ? { primary: colors.surface, secondary: "transparent", text: "transparent", destructive: colors.surface }[variant] : { primary: colors.primary, secondary: "transparent", text: "transparent", destructive: colors.destructive }[variant];
532
+ const animateBorderColor = isDisabled ? isSecondary ? colors.border : "transparent" : isSecondary ? colors.primary : "transparent";
533
+ const labelColor = isDisabled ? colors.foregroundMuted : {
534
+ primary: colors.primaryForeground,
535
+ secondary: colors.primary,
536
+ text: colors.accentResolved,
537
+ destructive: colors.destructiveForeground
736
538
  }[variant];
737
- const textColor = iconColor ?? labelVariantStyle.color;
738
- const effectiveIcon = iconName ? renderIcon(iconName, iconSizeMap[size], textColor) : typeof icon === "function" ? icon({ label, size, variant, color: textColor }) : icon;
739
- const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.accentResolved;
539
+ const textColor = iconColor ?? labelColor;
540
+ const effectiveIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: iconSizeMap[size], color: textColor }) : typeof icon === "function" ? icon({ label, size, variant, color: textColor }) : icon;
541
+ const spinnerColor = isDisabled ? colors.foregroundMuted : variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.accentResolved;
740
542
  const styleArray = Array.isArray(style) ? style : style ? [style] : [];
741
543
  const flatStyle = reactNative.StyleSheet.flatten(styleArray);
742
544
  const { flex, ...restStyle } = flatStyle || {};
743
545
  return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [fullWidth && styles.fullWidth, flex !== void 0 && { flex }] }, /* @__PURE__ */ React54__default.default.createElement(
744
546
  PressableButton,
745
547
  {
746
- style: [
747
- styles.base,
748
- containerVariantStyle,
749
- containerSizeStyles[size],
750
- fullWidth && styles.fullWidth,
751
- isDisabled && styles.disabled,
752
- restStyle
753
- ],
754
548
  enabled: !isDisabled,
755
549
  onPress: handlePress,
756
550
  rippleColor: "transparent",
@@ -761,23 +555,37 @@ function ButtonBase({
761
555
  accessibilityHint,
762
556
  accessibilityState: { disabled: isDisabled, busy: loading }
763
557
  },
764
- loading ? /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, /* @__PURE__ */ React54__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React54__default.default.createElement(
765
- reactNative.Text,
766
- {
767
- style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
768
- allowFontScaling: true,
769
- numberOfLines: 1
770
- },
771
- label
772
- )) : /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React54__default.default.createElement(
773
- reactNative.Text,
558
+ /* @__PURE__ */ React54__default.default.createElement(
559
+ reactNativeEase.EaseView,
774
560
  {
775
- style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
776
- allowFontScaling: true,
777
- numberOfLines: 1
561
+ style: [
562
+ styles.base,
563
+ containerSizeStyles[size],
564
+ { borderWidth },
565
+ fullWidth && styles.fullWidth,
566
+ restStyle
567
+ ],
568
+ animate: { backgroundColor: animateBgColor, borderColor: animateBorderColor },
569
+ transition: COLOR_TRANSITION
778
570
  },
779
- label
780
- ), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, effectiveIcon))
571
+ loading ? /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, /* @__PURE__ */ React54__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React54__default.default.createElement(
572
+ reactNative.Text,
573
+ {
574
+ style: [styles.label, { color: labelColor }, labelSizeStyles[size], styles.labelLoading],
575
+ allowFontScaling: true,
576
+ numberOfLines: 1
577
+ },
578
+ label
579
+ )) : /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React54__default.default.createElement(
580
+ reactNative.Text,
581
+ {
582
+ style: [styles.label, { color: labelColor }, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
583
+ allowFontScaling: true,
584
+ numberOfLines: 1
585
+ },
586
+ label
587
+ ), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, effectiveIcon))
588
+ )
781
589
  ));
782
590
  }
783
591
  var Button = React54__default.default.memo(ButtonBase);
@@ -791,9 +599,6 @@ var styles = reactNative.StyleSheet.create({
791
599
  fullWidth: {
792
600
  width: "100%"
793
601
  },
794
- disabled: {
795
- opacity: 0.45
796
- },
797
602
  label: {
798
603
  fontFamily: "Sohne-Medium",
799
604
  flexShrink: 1
@@ -882,7 +687,7 @@ function IconButtonBase({
882
687
  }[variant];
883
688
  const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.foreground;
884
689
  const { container: containerSize, icon: iconSize } = sizeMap[size];
885
- const resolvedIcon = iconName ? renderIcon(iconName, iconSize, iconColor ?? defaultIconColor) : icon;
690
+ const resolvedIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: iconSize, color: iconColor ?? defaultIconColor }) : icon;
886
691
  const showBadge = badge !== void 0 && badge !== false && badge !== 0;
887
692
  const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
888
693
  const showCount = typeof badge === "number" && badge > 0;
@@ -950,22 +755,6 @@ var styles3 = reactNative.StyleSheet.create({
950
755
  lineHeight: 14
951
756
  }
952
757
  });
953
- var warned = false;
954
- function warnIfFontsMissing() {
955
- if (warned) return;
956
- if (typeof __DEV__ !== "undefined" && !__DEV__) return;
957
- warned = true;
958
- try {
959
- if (!expoFont.isLoaded("Sohne-Regular")) {
960
- console.warn(
961
- "[retray-ui-kit] Sohne fonts are not loaded \u2014 text will fall back to the system font. Load them at your app root before rendering any UI kit component:\n\n import { useFonts } from 'expo-font'\n import { SohneFontNames } from '@retray-dev/ui-kit/fonts'\n // Copy the SohneFonts boilerplate from CONSUMER.md into your App.tsx\n\n const [fontsLoaded] = useFonts(SohneFonts)\n if (!fontsLoaded) return null\n"
962
- );
963
- }
964
- } catch {
965
- }
966
- }
967
-
968
- // src/components/Text/Text.tsx
969
758
  var variantStyles = {
970
759
  "display-hero": { ...TYPOGRAPHY["display-hero"], fontSize: ms(TYPOGRAPHY["display-hero"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-hero"].lineHeight) },
971
760
  "display-xl": { ...TYPOGRAPHY["display-xl"], fontSize: ms(TYPOGRAPHY["display-xl"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-xl"].lineHeight) },
@@ -1003,6 +792,14 @@ var defaultColorVariant = {
1003
792
  "button-lg": "foreground",
1004
793
  "button-sm": "foreground"
1005
794
  };
795
+ var fontWarned = false;
796
+ function warnIfFontsMissing() {
797
+ if (fontWarned || typeof __DEV__ === "undefined" || !__DEV__) return;
798
+ fontWarned = true;
799
+ if (!expoFont.isLoaded("Sohne-Regular")) {
800
+ console.warn("[retray-ui-kit] Sohne fonts not loaded \u2014 text falls back to system font.");
801
+ }
802
+ }
1006
803
  function TextBase({ variant = "body-md", color, style, uppercase, children, ...props }) {
1007
804
  warnIfFontsMissing();
1008
805
  const { colors } = useTheme();
@@ -1020,14 +817,16 @@ function TextBase({ variant = "body-md", color, style, uppercase, children, ...p
1020
817
  }
1021
818
  var Text3 = React54__default.default.memo(TextBase);
1022
819
  var webInputResetStyle = reactNative.Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
1023
- function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, sheetMode = false, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
820
+ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, sheetMode = false, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, autoCapitalize, autoCorrect, ...props }) {
1024
821
  const { colors } = useTheme();
1025
822
  const [focused, setFocused] = React54.useState(false);
1026
823
  const [showPassword, setShowPassword] = React54.useState(false);
1027
824
  const isDisabled = disabled || editable === false;
1028
825
  const isPassword = type === "password";
1029
826
  const effectiveSecure = isPassword ? !showPassword : secureTextEntry;
1030
- const effectivePrefix = prefixIcon ? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.foregroundMuted) : prefix;
827
+ const effectiveAutoCapitalize = isPassword ? "none" : autoCapitalize;
828
+ const effectiveAutoCorrect = isPassword ? false : autoCorrect;
829
+ const effectivePrefix = prefixIcon ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: prefixIcon, size: 20, color: prefixIconColor ?? colors.foregroundMuted }) : prefix;
1031
830
  const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React54__default.default.createElement(
1032
831
  reactNative.TouchableOpacity,
1033
832
  {
@@ -1035,10 +834,10 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
1035
834
  style: styles4.passwordToggle,
1036
835
  activeOpacity: 0.6,
1037
836
  accessibilityRole: "button",
1038
- accessibilityLabel: showPassword ? "Hide password" : "Show password"
837
+ accessibilityLabel: showPassword ? "Ocultar contrase\xF1a" : "Mostrar contrase\xF1a"
1039
838
  },
1040
839
  /* @__PURE__ */ React54__default.default.createElement(vectorIcons.AntDesign, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.foregroundMuted })
1041
- ) : suffixIcon ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted) : suffix;
840
+ ) : suffixIcon ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: suffixIcon, size: 20, color: suffixIconColor ?? colors.foregroundMuted }) : suffix;
1042
841
  const borderColor = error ? colors.destructive : focused ? colors.primary : colors.border;
1043
842
  return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles4.container, isDisabled && styles4.containerDisabled, containerStyle] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles4.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React54__default.default.createElement(
1044
843
  reactNativeEase.EaseView,
@@ -1075,6 +874,8 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
1075
874
  secureTextEntry: effectiveSecure,
1076
875
  editable: isDisabled ? false : editable,
1077
876
  accessibilityLabel: accessibilityLabel ?? label,
877
+ autoCapitalize: effectiveAutoCapitalize,
878
+ autoCorrect: effectiveAutoCorrect,
1078
879
  ...props
1079
880
  }
1080
881
  ) : /* @__PURE__ */ React54__default.default.createElement(
@@ -1099,6 +900,8 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
1099
900
  secureTextEntry: effectiveSecure,
1100
901
  editable: isDisabled ? false : editable,
1101
902
  accessibilityLabel: accessibilityLabel ?? label,
903
+ autoCapitalize: effectiveAutoCapitalize,
904
+ autoCorrect: effectiveAutoCorrect,
1102
905
  ...props
1103
906
  }
1104
907
  ),
@@ -1210,7 +1013,7 @@ function BadgeBase({ label, children, variant = "default", size = "md", icon, ic
1210
1013
  destructiveOutline: colors.destructive,
1211
1014
  warningOutline: colors.warning
1212
1015
  }[variant];
1213
- const effectiveIcon = iconName ? renderIcon(iconName, sizeIconSize[size], iconColor ?? textColor) : icon;
1016
+ const effectiveIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: sizeIconSize[size], color: iconColor ?? textColor }) : icon;
1214
1017
  const content = children ?? label;
1215
1018
  const a11yLabel = typeof content === "string" ? content : label;
1216
1019
  return /* @__PURE__ */ React54__default.default.createElement(
@@ -1279,7 +1082,8 @@ function Card({ children, variant = "elevated", onPress, style, accessibilityLab
1279
1082
  touchSoundDisabled: true,
1280
1083
  activateOnHover: true,
1281
1084
  accessibilityRole: "button",
1282
- accessibilityLabel
1085
+ accessibilityLabel,
1086
+ accessibilityState: { disabled: false }
1283
1087
  },
1284
1088
  cardContent
1285
1089
  );
@@ -1362,7 +1166,7 @@ var styles7 = reactNative.StyleSheet.create({
1362
1166
  });
1363
1167
  var sizeMap2 = {
1364
1168
  sm: "small",
1365
- md: "small",
1169
+ md: "large",
1366
1170
  lg: "large"
1367
1171
  };
1368
1172
  var labelFontSize = {
@@ -1372,7 +1176,7 @@ var labelFontSize = {
1372
1176
  };
1373
1177
  function Spinner({ size = "md", color, label, ...props }) {
1374
1178
  const { colors } = useTheme();
1375
- const a11yLabel = label || "Loading";
1179
+ const a11yLabel = label || "Cargando";
1376
1180
  if (label) {
1377
1181
  return /* @__PURE__ */ React54__default.default.createElement(
1378
1182
  reactNative.View,
@@ -1421,20 +1225,21 @@ function Skeleton({
1421
1225
  borderRadius = 6,
1422
1226
  preset = "base",
1423
1227
  diameter = 40,
1228
+ backgroundColor,
1424
1229
  style
1425
1230
  }) {
1426
1231
  const { colors, colorScheme } = useTheme();
1427
- const shimmer = Animated12.useSharedValue(0);
1232
+ const shimmer = Animated6.useSharedValue(0);
1428
1233
  const [containerWidth, setContainerWidth] = React54.useState(300);
1429
- const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(255,255,255,0.7)";
1234
+ const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.07)";
1430
1235
  React54.useEffect(() => {
1431
- shimmer.value = Animated12.withRepeat(
1432
- Animated12.withTiming(1, { duration: TIMINGS.shimmer.duration, easing: Animated12.Easing.linear }),
1236
+ shimmer.value = Animated6.withRepeat(
1237
+ Animated6.withTiming(1, { duration: TIMINGS.shimmer.duration, easing: Animated6.Easing.linear }),
1433
1238
  -1,
1434
1239
  false
1435
1240
  );
1436
1241
  }, [shimmer]);
1437
- const shimmerStyle = Animated12.useAnimatedStyle(() => ({
1242
+ const shimmerStyle = Animated6.useAnimatedStyle(() => ({
1438
1243
  transform: [{ translateX: -containerWidth + shimmer.value * (containerWidth * 2) }]
1439
1244
  }));
1440
1245
  const resolvedWidth = preset === "circle" ? s(diameter) : preset === "text" ? "60%" : width;
@@ -1445,15 +1250,15 @@ function Skeleton({
1445
1250
  {
1446
1251
  style: [
1447
1252
  styles9.base,
1448
- { width: resolvedWidth, height: resolvedHeight, borderRadius: resolvedRadius, backgroundColor: colors.surface },
1253
+ { width: resolvedWidth, height: resolvedHeight, borderRadius: resolvedRadius, backgroundColor: backgroundColor ?? colors.skeleton },
1449
1254
  style
1450
1255
  ],
1451
1256
  onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width),
1452
1257
  accessibilityRole: "progressbar",
1453
- accessibilityLabel: "Loading",
1258
+ accessibilityLabel: "Cargando",
1454
1259
  accessibilityState: { busy: true }
1455
1260
  },
1456
- /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [reactNative.StyleSheet.absoluteFill, shimmerStyle] }, /* @__PURE__ */ React54__default.default.createElement(
1261
+ /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: [reactNative.StyleSheet.absoluteFill, shimmerStyle] }, /* @__PURE__ */ React54__default.default.createElement(
1457
1262
  expoLinearGradient.LinearGradient,
1458
1263
  {
1459
1264
  colors: ["transparent", shimmerHighlight, "transparent"],
@@ -1580,7 +1385,7 @@ function AvatarBase({ src, fallback, fallbackText, size = "md", status, style })
1580
1385
  accessibilityLabel: a11yLabel
1581
1386
  },
1582
1387
  /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles10.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React54__default.default.createElement(
1583
- reactNative.Image,
1388
+ expoImage.Image,
1584
1389
  {
1585
1390
  source: { uri: src },
1586
1391
  style: { width: dimension, height: dimension },
@@ -1613,6 +1418,66 @@ function AvatarBase({ src, fallback, fallbackText, size = "md", status, style })
1613
1418
  );
1614
1419
  }
1615
1420
  var Avatar = React54__default.default.memo(AvatarBase);
1421
+ function AvatarGroup({
1422
+ users,
1423
+ max = 3,
1424
+ size = "sm",
1425
+ overlap = vs(8),
1426
+ onOverflowPress,
1427
+ style
1428
+ }) {
1429
+ const { colors } = useTheme();
1430
+ const visible = users.slice(0, max);
1431
+ const overflowCount = users.length - max;
1432
+ const dimension = sizeMap3[size];
1433
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles10.group, style], accessibilityLabel: `${users.length} avatares` }, visible.map((user, i) => /* @__PURE__ */ React54__default.default.createElement(
1434
+ reactNative.View,
1435
+ {
1436
+ key: `${user.name}-${i}`,
1437
+ style: [
1438
+ styles10.groupItem,
1439
+ i > 0 && { marginLeft: -overlap },
1440
+ { zIndex: visible.length - i }
1441
+ ]
1442
+ },
1443
+ /* @__PURE__ */ React54__default.default.createElement(
1444
+ Avatar,
1445
+ {
1446
+ src: user.src,
1447
+ fallbackText: user.name,
1448
+ size
1449
+ }
1450
+ )
1451
+ )), overflowCount > 0 ? /* @__PURE__ */ React54__default.default.createElement(
1452
+ reactNative.TouchableOpacity,
1453
+ {
1454
+ style: [
1455
+ styles10.overflowBadge,
1456
+ {
1457
+ width: dimension,
1458
+ height: dimension,
1459
+ borderRadius: dimension / 2,
1460
+ backgroundColor: colors.surfaceStrong,
1461
+ marginLeft: -overlap
1462
+ }
1463
+ ],
1464
+ onPress: onOverflowPress,
1465
+ disabled: !onOverflowPress,
1466
+ activeOpacity: 0.7,
1467
+ accessibilityRole: "button",
1468
+ accessibilityLabel: `${overflowCount} avatares m\xE1s`
1469
+ },
1470
+ /* @__PURE__ */ React54__default.default.createElement(
1471
+ reactNative.Text,
1472
+ {
1473
+ style: [styles10.overflowText, { color: colors.foregroundMuted }],
1474
+ allowFontScaling: true
1475
+ },
1476
+ "+",
1477
+ overflowCount
1478
+ )
1479
+ ) : null);
1480
+ }
1616
1481
  var styles10 = reactNative.StyleSheet.create({
1617
1482
  wrapper: {
1618
1483
  alignSelf: "flex-start",
@@ -1629,6 +1494,21 @@ var styles10 = reactNative.StyleSheet.create({
1629
1494
  position: "absolute",
1630
1495
  bottom: 0,
1631
1496
  right: 0
1497
+ },
1498
+ group: {
1499
+ flexDirection: "row",
1500
+ alignItems: "center"
1501
+ },
1502
+ groupItem: {
1503
+ borderRadius: 999
1504
+ },
1505
+ overflowBadge: {
1506
+ alignItems: "center",
1507
+ justifyContent: "center"
1508
+ },
1509
+ overflowText: {
1510
+ fontFamily: "Sohne-SemiBold",
1511
+ fontSize: ms(11)
1632
1512
  }
1633
1513
  });
1634
1514
  function AlertBanner({ title, description, variant = "default", icon, iconName, iconColor, onDismiss, style }) {
@@ -1643,7 +1523,7 @@ function AlertBanner({ title, description, variant = "default", icon, iconName,
1643
1523
  // a meaningful chromatic signal when an accent is defined.
1644
1524
  /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: ms(16), color: accentColor })
1645
1525
  );
1646
- const effectiveIcon = iconName ? renderIcon(iconName, ms(16), iconColor ?? accentColor) : icon ?? defaultIcon;
1526
+ const effectiveIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: ms(16), color: iconColor ?? accentColor }) : icon ?? defaultIcon;
1647
1527
  const a11yLabel = description ? `${title}. ${description}` : title;
1648
1528
  return /* @__PURE__ */ React54__default.default.createElement(
1649
1529
  reactNative.View,
@@ -1663,9 +1543,10 @@ function AlertBanner({ title, description, variant = "default", icon, iconName,
1663
1543
  {
1664
1544
  onPress: onDismiss,
1665
1545
  style: styles11.dismissButton,
1546
+ hitSlop: { top: 10, bottom: 10, left: 10, right: 10 },
1666
1547
  activeOpacity: 0.6,
1667
1548
  accessibilityRole: "button",
1668
- accessibilityLabel: "Dismiss"
1549
+ accessibilityLabel: "Descartar"
1669
1550
  },
1670
1551
  /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Feather, { name: "x", size: ms(16), color: colors.foregroundMuted })
1671
1552
  ) : null
@@ -1696,21 +1577,21 @@ var styles11 = reactNative.StyleSheet.create({
1696
1577
  fontSize: ms(12)
1697
1578
  },
1698
1579
  dismissButton: {
1699
- padding: s(4),
1700
- marginTop: vs(-2),
1701
- marginRight: -s(4)
1580
+ padding: s(10),
1581
+ marginTop: vs(-8),
1582
+ marginRight: -s(10)
1702
1583
  }
1703
1584
  });
1704
1585
  function Progress({ value = 0, max = 100, variant = "default", style, accessibilityLabel }) {
1705
1586
  const { colors } = useTheme();
1706
1587
  const percent = Math.min(Math.max(value / max * 100, 0), 100);
1707
1588
  const [trackWidth, setTrackWidth] = React54.useState(0);
1708
- const animatedWidth = Animated12.useSharedValue(0);
1589
+ const animatedWidth = Animated6.useSharedValue(0);
1709
1590
  React54.useEffect(() => {
1710
1591
  if (trackWidth === 0) return;
1711
- animatedWidth.value = Animated12.withSpring(percent / 100 * trackWidth, SPRINGS.glide);
1592
+ animatedWidth.value = Animated6.withSpring(percent / 100 * trackWidth, SPRINGS.glide);
1712
1593
  }, [percent, trackWidth, animatedWidth]);
1713
- const indicatorAnimatedStyle = Animated12.useAnimatedStyle(() => ({
1594
+ const indicatorAnimatedStyle = Animated6.useAnimatedStyle(() => ({
1714
1595
  width: animatedWidth.value
1715
1596
  }));
1716
1597
  const indicatorColor = variant === "success" ? colors.success : variant === "warning" ? colors.warning : variant === "destructive" ? colors.destructive : colors.primary;
@@ -1724,7 +1605,7 @@ function Progress({ value = 0, max = 100, variant = "default", style, accessibil
1724
1605
  accessibilityValue: { min: 0, max: 100, now: Math.round(percent) }
1725
1606
  },
1726
1607
  /* @__PURE__ */ React54__default.default.createElement(
1727
- Animated12__default.default.View,
1608
+ Animated6__default.default.View,
1728
1609
  {
1729
1610
  style: [styles12.indicator, { backgroundColor: indicatorColor }, indicatorAnimatedStyle]
1730
1611
  }
@@ -1746,7 +1627,7 @@ var styles12 = reactNative.StyleSheet.create({
1746
1627
  function EmptyState({ icon, iconName, iconColor, title, description, action, actionLabel, onAction, size = "default", style }) {
1747
1628
  const { colors } = useTheme();
1748
1629
  const isCompact = size === "compact";
1749
- const effectiveIcon = iconName ? renderIcon(iconName, isCompact ? 32 : 48, iconColor ?? colors.foregroundMuted) : icon;
1630
+ const effectiveIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: isCompact ? 32 : 48, color: iconColor ?? colors.foregroundMuted }) : icon;
1750
1631
  return /* @__PURE__ */ React54__default.default.createElement(
1751
1632
  reactNative.View,
1752
1633
  {
@@ -1832,21 +1713,12 @@ var styles13 = reactNative.StyleSheet.create({
1832
1713
  paddingHorizontal: s(32)
1833
1714
  }
1834
1715
  });
1835
- function useColorTransition(active, options = {}) {
1836
- const { duration = TIMINGS.state.duration } = options;
1837
- const progress = Animated12.useSharedValue(active ? 1 : 0);
1838
- React54.useEffect(() => {
1839
- progress.value = Animated12.withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard });
1840
- }, [active, duration, progress]);
1841
- return progress;
1842
- }
1843
-
1844
- // src/components/Textarea/Textarea.tsx
1845
1716
  var webInputResetStyle2 = reactNative.Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
1846
1717
  function Textarea({
1847
1718
  label,
1848
1719
  error,
1849
1720
  hint,
1721
+ disabled,
1850
1722
  rows = 4,
1851
1723
  prefixIcon,
1852
1724
  prefixIconNode,
@@ -1860,54 +1732,48 @@ function Textarea({
1860
1732
  }) {
1861
1733
  const { colors } = useTheme();
1862
1734
  const [focused, setFocused] = React54.useState(false);
1863
- const focusProgress = useColorTransition(focused, {
1864
- duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
1865
- });
1866
- const resolvedPrefixIcon = prefixIcon ? renderIcon(prefixIcon, ms(16), prefixIconColor ?? colors.foregroundMuted) : prefixIconNode;
1867
- const borderAnimStyle = Animated12.useAnimatedStyle(() => ({
1868
- borderColor: error ? colors.destructive : Animated12.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
1869
- borderWidth: error ? 2 : Animated12.interpolate(focusProgress.value, [0, 1], [1, 2])
1870
- }));
1871
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles14.container, containerStyle] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles14.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React54__default.default.createElement(
1872
- Animated12__default.default.View,
1735
+ const resolvedPrefixIcon = prefixIcon ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: prefixIcon, size: ms(16), color: prefixIconColor ?? colors.foregroundMuted }) : prefixIconNode;
1736
+ const borderColor = error ? colors.destructive : focused ? colors.primary : colors.border;
1737
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles14.container, containerStyle] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles14.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles14.inputWrapper, { backgroundColor: colors.background }] }, /* @__PURE__ */ React54__default.default.createElement(
1738
+ reactNativeEase.EaseView,
1739
+ {
1740
+ style: [styles14.borderOverlay, { borderWidth: error ? 2 : 1 }],
1741
+ animate: { borderColor },
1742
+ transition: COLOR_TRANSITION,
1743
+ pointerEvents: "none"
1744
+ }
1745
+ ), resolvedPrefixIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles14.prefixIcon }, resolvedPrefixIcon) : null, /* @__PURE__ */ React54__default.default.createElement(
1746
+ reactNative.TextInput,
1873
1747
  {
1748
+ multiline: true,
1749
+ numberOfLines: rows,
1750
+ textAlignVertical: "top",
1751
+ editable: !disabled,
1874
1752
  style: [
1875
- styles14.inputWrapper,
1876
- { backgroundColor: colors.background }
1877
- ]
1878
- },
1879
- /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [styles14.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
1880
- resolvedPrefixIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles14.prefixIcon }, resolvedPrefixIcon) : null,
1881
- /* @__PURE__ */ React54__default.default.createElement(
1882
- reactNative.TextInput,
1883
- {
1884
- multiline: true,
1885
- numberOfLines: rows,
1886
- textAlignVertical: "top",
1887
- style: [
1888
- styles14.input,
1889
- {
1890
- color: colors.foreground,
1891
- minHeight: rows * vs(30)
1892
- },
1893
- webInputResetStyle2,
1894
- style
1895
- ],
1896
- onFocus: (e) => {
1897
- setFocused(true);
1898
- onFocus?.(e);
1899
- },
1900
- onBlur: (e) => {
1901
- setFocused(false);
1902
- onBlur?.(e);
1753
+ styles14.input,
1754
+ {
1755
+ color: colors.foreground,
1756
+ minHeight: rows * vs(30)
1903
1757
  },
1904
- placeholderTextColor: colors.foregroundMuted,
1905
- allowFontScaling: true,
1906
- accessibilityLabel: accessibilityLabel ?? label,
1907
- ...props
1908
- }
1909
- )
1910
- ), error ? /* @__PURE__ */ React54__default.default.createElement(
1758
+ disabled && { opacity: 0.45 },
1759
+ webInputResetStyle2,
1760
+ style
1761
+ ],
1762
+ onFocus: (e) => {
1763
+ setFocused(true);
1764
+ onFocus?.(e);
1765
+ },
1766
+ onBlur: (e) => {
1767
+ setFocused(false);
1768
+ onBlur?.(e);
1769
+ },
1770
+ placeholderTextColor: colors.foregroundMuted,
1771
+ allowFontScaling: true,
1772
+ accessibilityLabel: accessibilityLabel ?? label,
1773
+ accessibilityState: { disabled: !!disabled },
1774
+ ...props
1775
+ }
1776
+ )), error ? /* @__PURE__ */ React54__default.default.createElement(
1911
1777
  reactNative.Text,
1912
1778
  {
1913
1779
  style: [styles14.helperText, { color: colors.destructive }],
@@ -1928,8 +1794,6 @@ var styles14 = reactNative.StyleSheet.create({
1928
1794
  marginBottom: vs(2)
1929
1795
  },
1930
1796
  inputWrapper: {
1931
- // Border lives on borderOverlay (absolute); wrapper carries none so the
1932
- // focus weight change never reflows content.
1933
1797
  borderRadius: 8,
1934
1798
  paddingHorizontal: s(14),
1935
1799
  paddingVertical: vs(11),
@@ -2052,14 +1916,14 @@ function Switch({ checked = false, onCheckedChange, disabled, style, accessibili
2052
1916
  const { colors } = useTheme();
2053
1917
  const isDisabled = !!disabled;
2054
1918
  return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [{ alignSelf: "flex-start" }, style] }, /* @__PURE__ */ React54__default.default.createElement(
2055
- reactNative.TouchableOpacity,
1919
+ PressableButton,
2056
1920
  {
2057
1921
  onPress: () => {
2058
1922
  selectionAsync();
2059
1923
  onCheckedChange?.(!checked);
2060
1924
  },
2061
- disabled,
2062
- activeOpacity: 0.8,
1925
+ enabled: !disabled,
1926
+ rippleColor: "transparent",
2063
1927
  touchSoundDisabled: true,
2064
1928
  accessibilityRole: "switch",
2065
1929
  accessibilityLabel,
@@ -2111,7 +1975,9 @@ function Switch({ checked = false, onCheckedChange, disabled, style, accessibili
2111
1975
  }
2112
1976
  var styles16 = reactNative.StyleSheet.create({
2113
1977
  touchable: {
2114
- alignSelf: "flex-start"
1978
+ alignSelf: "flex-start",
1979
+ minHeight: 44,
1980
+ justifyContent: "center"
2115
1981
  },
2116
1982
  trackContainer: {
2117
1983
  position: "relative",
@@ -2157,12 +2023,12 @@ function ToggleIcon({ pressed, iconName, activeIconName, icon, activeIcon, iconC
2157
2023
  return prop;
2158
2024
  };
2159
2025
  if (pressed) {
2160
- if (activeIconName) return /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, renderIcon(activeIconName, iconSize, activeIconColor ?? primaryColor));
2026
+ if (activeIconName) return /* @__PURE__ */ React54__default.default.createElement(Icon, { name: activeIconName, size: iconSize, color: activeIconColor ?? primaryColor });
2161
2027
  const active = renderProp(activeIcon);
2162
2028
  if (active) return /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, active);
2163
2029
  return /* @__PURE__ */ React54__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: iconSize, color: primaryColor });
2164
2030
  }
2165
- if (iconName) return /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, renderIcon(iconName, iconSize, iconColor ?? mutedColor));
2031
+ if (iconName) return /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: iconSize, color: iconColor ?? mutedColor });
2166
2032
  const custom = renderProp(icon);
2167
2033
  if (custom) return /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, custom);
2168
2034
  return /* @__PURE__ */ React54__default.default.createElement(vectorIcons.FontAwesome5, { name: "circle", size: iconSize, color: mutedColor });
@@ -2261,106 +2127,52 @@ var styles17 = reactNative.StyleSheet.create({
2261
2127
  fontSize: ms(14)
2262
2128
  }
2263
2129
  });
2264
- function useHover() {
2265
- const [hovered, setHovered] = React54.useState(false);
2266
- const onMouseEnter = React54.useCallback(() => setHovered(true), []);
2267
- const onMouseLeave = React54.useCallback(() => setHovered(false), []);
2268
- if (reactNative.Platform.OS !== "web") {
2269
- return { hovered: false, hoverHandlers: {} };
2270
- }
2271
- return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
2272
- }
2273
-
2274
- // src/utils/usePressScale.ts
2275
- function usePressScale({
2276
- pressScale = PRESS_SCALE.button,
2277
- hoverScale = 1.02,
2278
- pressInSpring = SPRINGS.pressIn,
2279
- pressOutSpring = SPRINGS.pressOut,
2280
- disabled = false
2281
- } = {}) {
2282
- const scale2 = Animated12.useSharedValue(1);
2283
- const { hovered, hoverHandlers } = useHover();
2284
- const onPressIn = React54.useCallback(() => {
2285
- if (disabled) return;
2286
- scale2.value = Animated12.withSpring(pressScale, pressInSpring);
2287
- }, [disabled, pressScale, pressInSpring, scale2]);
2288
- const onPressOut = React54.useCallback(() => {
2289
- if (disabled) return;
2290
- scale2.value = Animated12.withSpring(1, pressOutSpring);
2291
- }, [disabled, pressOutSpring, scale2]);
2292
- const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
2293
- const animatedStyle = Animated12.useAnimatedStyle(() => ({
2294
- transform: [
2295
- { scale: scale2.value * (hoverActive ? hoverScale : 1) }
2296
- ]
2297
- }));
2298
- return {
2299
- animatedStyle,
2300
- onPressIn,
2301
- onPressOut,
2302
- hoverHandlers
2303
- };
2304
- }
2305
-
2306
- // src/components/RadioGroup/RadioGroup.tsx
2307
2130
  function RadioItem({
2308
2131
  option,
2309
2132
  selected,
2310
2133
  onSelect
2311
2134
  }) {
2312
2135
  const { colors } = useTheme();
2313
- const { animatedStyle: scaleStyle, onPressIn, onPressOut } = usePressScale({
2314
- pressScale: PRESS_SCALE.button,
2315
- disabled: option.disabled
2316
- });
2317
- return (
2318
- // AUDIT FIX: opacity was applied only to the radio circle, leaving the label
2319
- // at full opacity when disabled. The whole row now dims uniformly so users
2320
- // get a single, consistent disabled signal across the entire item.
2136
+ return /* @__PURE__ */ React54__default.default.createElement(
2137
+ PressableButton,
2138
+ {
2139
+ style: [styles18.row, option.disabled && styles18.rowDisabled],
2140
+ onPress: () => {
2141
+ if (!option.disabled) {
2142
+ selectionAsync();
2143
+ onSelect();
2144
+ }
2145
+ },
2146
+ enabled: !option.disabled,
2147
+ rippleColor: "transparent",
2148
+ touchSoundDisabled: true,
2149
+ accessibilityRole: "radio",
2150
+ accessibilityLabel: option.label,
2151
+ accessibilityState: { checked: selected, disabled: !!option.disabled }
2152
+ },
2321
2153
  /* @__PURE__ */ React54__default.default.createElement(
2322
- reactNative.TouchableOpacity,
2154
+ reactNativeEase.EaseView,
2323
2155
  {
2324
- style: [styles18.row, option.disabled && styles18.rowDisabled],
2325
- onPress: () => {
2326
- if (!option.disabled) {
2327
- selectionAsync();
2328
- onSelect();
2329
- }
2330
- },
2331
- onPressIn,
2332
- onPressOut,
2333
- activeOpacity: 1,
2334
- touchSoundDisabled: true,
2335
- disabled: option.disabled,
2336
- accessibilityRole: "radio",
2337
- accessibilityLabel: option.label,
2338
- accessibilityState: { checked: selected, disabled: !!option.disabled }
2156
+ style: styles18.radio,
2157
+ animate: { borderColor: selected ? colors.primary : colors.border },
2158
+ transition: COLOR_TRANSITION
2339
2159
  },
2340
- /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: scaleStyle }, /* @__PURE__ */ React54__default.default.createElement(
2160
+ /* @__PURE__ */ React54__default.default.createElement(
2341
2161
  reactNativeEase.EaseView,
2342
2162
  {
2343
- style: styles18.radio,
2344
- animate: { borderColor: selected ? colors.primary : colors.border },
2345
- transition: COLOR_TRANSITION
2346
- },
2347
- /* @__PURE__ */ React54__default.default.createElement(
2348
- reactNativeEase.EaseView,
2349
- {
2350
- style: [styles18.dot, { backgroundColor: colors.primary }],
2351
- animate: { scale: selected ? 1 : 0, opacity: selected ? 1 : 0 },
2352
- transition: SPRING_ELASTIC
2353
- }
2354
- )
2355
- )),
2356
- /* @__PURE__ */ React54__default.default.createElement(
2357
- reactNative.Text,
2358
- {
2359
- style: [styles18.label, { color: colors.foreground }],
2360
- allowFontScaling: true
2361
- },
2362
- option.label
2163
+ style: [styles18.dot, { backgroundColor: colors.primary }],
2164
+ animate: { scale: selected ? 1 : 0, opacity: selected ? 1 : 0 },
2165
+ transition: SPRING_ELASTIC
2166
+ }
2363
2167
  )
2168
+ ),
2169
+ /* @__PURE__ */ React54__default.default.createElement(
2170
+ reactNative.Text,
2171
+ {
2172
+ style: [styles18.label, { color: colors.foreground }],
2173
+ allowFontScaling: true
2174
+ },
2175
+ option.label
2364
2176
  )
2365
2177
  );
2366
2178
  }
@@ -2403,7 +2215,6 @@ var styles18 = reactNative.StyleSheet.create({
2403
2215
  alignItems: "center",
2404
2216
  gap: s(12)
2405
2217
  },
2406
- // AUDIT FIX: was opacity on the inner circle only
2407
2218
  rowDisabled: {
2408
2219
  opacity: 0.45
2409
2220
  },
@@ -2472,15 +2283,15 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2472
2283
  const { colors } = useTheme();
2473
2284
  const active = value ?? internal;
2474
2285
  const tabLayouts = React54.useRef({});
2475
- const pillX = Animated12.useSharedValue(0);
2476
- const pillWidth = Animated12.useSharedValue(0);
2286
+ const pillX = Animated6.useSharedValue(0);
2287
+ const pillWidth = Animated6.useSharedValue(0);
2477
2288
  const initialised = React54.useRef(false);
2478
2289
  const animatePill = React54.useCallback((tabValue, animate) => {
2479
2290
  const layout = tabLayouts.current[tabValue];
2480
2291
  if (!layout) return;
2481
2292
  if (animate) {
2482
- pillX.value = Animated12.withSpring(layout.x, SPRINGS.glide);
2483
- pillWidth.value = Animated12.withSpring(layout.width, SPRINGS.glide);
2293
+ pillX.value = Animated6.withSpring(layout.x, SPRINGS.glide);
2294
+ pillWidth.value = Animated6.withSpring(layout.width, SPRINGS.glide);
2484
2295
  } else {
2485
2296
  pillX.value = layout.x;
2486
2297
  pillWidth.value = layout.width;
@@ -2494,7 +2305,7 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2494
2305
  if (!value) setInternal(v);
2495
2306
  onValueChange?.(v);
2496
2307
  };
2497
- const pillAnimatedStyle = Animated12.useAnimatedStyle(() => ({
2308
+ const pillAnimatedStyle = Animated6.useAnimatedStyle(() => ({
2498
2309
  transform: [{ translateX: pillX.value }],
2499
2310
  width: pillWidth.value
2500
2311
  }));
@@ -2507,7 +2318,7 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2507
2318
  accessibilityRole: "tablist"
2508
2319
  },
2509
2320
  variant === "pill" && /* @__PURE__ */ React54__default.default.createElement(
2510
- Animated12__default.default.View,
2321
+ Animated6__default.default.View,
2511
2322
  {
2512
2323
  style: [
2513
2324
  styles19.pill,
@@ -2608,46 +2419,56 @@ function AccordionItemComponent({
2608
2419
  onToggle
2609
2420
  }) {
2610
2421
  const { colors } = useTheme();
2611
- const resolvedIcon = item.iconName ? renderIcon(item.iconName, ms(16), item.iconColor ?? colors.foregroundMuted) : item.icon;
2612
- const isExpanded = Animated12.useSharedValue(isOpen);
2613
- const height = Animated12.useSharedValue(0);
2422
+ const resolvedIcon = item.iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: item.iconName, size: ms(16), color: item.iconColor ?? colors.foregroundMuted }) : item.icon;
2423
+ const isExpanded = Animated6.useSharedValue(isOpen);
2424
+ const height = Animated6.useSharedValue(0);
2614
2425
  React54__default.default.useEffect(() => {
2615
2426
  isExpanded.value = isOpen;
2616
2427
  }, [isOpen, isExpanded]);
2617
- const derivedHeight = Animated12.useDerivedValue(
2618
- () => Animated12.withTiming(height.value * Number(isExpanded.value), {
2428
+ const derivedHeight = Animated6.useDerivedValue(
2429
+ () => Animated6.withTiming(height.value * Number(isExpanded.value), {
2619
2430
  duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
2620
- easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
2431
+ easing: isExpanded.value ? Animated6.Easing.bezier(0.23, 1, 0.32, 1) : Animated6.Easing.in(Animated6.Easing.ease)
2621
2432
  })
2622
2433
  );
2623
- const derivedRotation = Animated12.useDerivedValue(
2624
- () => Animated12.withTiming(isExpanded.value ? 1 : 0, {
2434
+ const derivedRotation = Animated6.useDerivedValue(
2435
+ () => Animated6.withTiming(isExpanded.value ? 1 : 0, {
2625
2436
  duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
2626
- easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
2437
+ easing: isExpanded.value ? Animated6.Easing.bezier(0.23, 1, 0.32, 1) : Animated6.Easing.in(Animated6.Easing.ease)
2627
2438
  })
2628
2439
  );
2629
- const bodyStyle = Animated12.useAnimatedStyle(() => ({
2440
+ const bodyStyle = Animated6.useAnimatedStyle(() => ({
2630
2441
  height: derivedHeight.value,
2631
2442
  overflow: "hidden"
2632
2443
  }));
2633
- const rotationStyle = Animated12.useAnimatedStyle(() => ({
2444
+ const rotationStyle = Animated6.useAnimatedStyle(() => ({
2634
2445
  transform: [{ rotate: `${derivedRotation.value * 180}deg` }]
2635
2446
  }));
2636
2447
  return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles20.item, { backgroundColor: colors.card, borderColor: colors.border }] }, /* @__PURE__ */ React54__default.default.createElement(
2637
- reactNative.Pressable,
2448
+ PressableRow,
2638
2449
  {
2639
- style: ({ pressed }) => [styles20.trigger, { opacity: pressed ? 0.6 : 1 }],
2640
2450
  onPress: () => {
2641
2451
  selectionAsync();
2642
2452
  onToggle();
2643
2453
  },
2454
+ rippleColor: "transparent",
2455
+ touchSoundDisabled: true,
2644
2456
  accessibilityRole: "button",
2645
2457
  accessibilityState: { expanded: isOpen },
2646
- accessibilityLabel: typeof item.trigger === "string" ? item.trigger : void 0
2458
+ accessibilityLabel: typeof item.trigger === "string" ? item.trigger : void 0,
2459
+ style: styles20.trigger
2647
2460
  },
2648
2461
  /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles20.triggerContent }, resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles20.icon }, resolvedIcon) : null, typeof item.trigger === "string" ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles20.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger) : item.trigger),
2649
- /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [styles20.chevron, rotationStyle] }, /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
2650
- ), /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React54__default.default.createElement(
2462
+ item.triggerActions ? /* @__PURE__ */ React54__default.default.createElement(
2463
+ reactNative.View,
2464
+ {
2465
+ style: styles20.triggerActions,
2466
+ onTouchEnd: (e) => e.stopPropagation()
2467
+ },
2468
+ item.triggerActions
2469
+ ) : null,
2470
+ /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: [styles20.chevron, rotationStyle] }, /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
2471
+ ), /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React54__default.default.createElement(
2651
2472
  reactNative.View,
2652
2473
  {
2653
2474
  style: styles20.content,
@@ -2715,6 +2536,12 @@ var styles20 = reactNative.StyleSheet.create({
2715
2536
  chevron: {
2716
2537
  marginLeft: s(8)
2717
2538
  },
2539
+ triggerActions: {
2540
+ flexDirection: "row",
2541
+ alignItems: "center",
2542
+ gap: s(4),
2543
+ marginLeft: s(8)
2544
+ },
2718
2545
  // position:'absolute' is the key — the inner View escapes the animated wrapper's
2719
2546
  // clipped height so onLayout always reports the true content height.
2720
2547
  content: {
@@ -2842,13 +2669,19 @@ function Sheet({
2842
2669
  const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
2843
2670
  const ref = React54.useRef(null);
2844
2671
  const wasOpened = React54.useRef(false);
2672
+ const isPresentedRef = React54.useRef(false);
2845
2673
  const name = React54.useId();
2674
+ const handleDismiss = React54.useCallback(() => {
2675
+ isPresentedRef.current = false;
2676
+ onClose?.();
2677
+ }, [onClose]);
2846
2678
  React54.useEffect(() => {
2847
- if (open) {
2679
+ if (open && !isPresentedRef.current) {
2848
2680
  impactMedium();
2849
2681
  ref.current?.present();
2850
2682
  wasOpened.current = true;
2851
- } else if (wasOpened.current) {
2683
+ isPresentedRef.current = true;
2684
+ } else if (!open && wasOpened.current && isPresentedRef.current) {
2852
2685
  ref.current?.dismiss();
2853
2686
  }
2854
2687
  }, [open]);
@@ -2880,7 +2713,7 @@ function Sheet({
2880
2713
  activeOpacity: 0.6,
2881
2714
  touchSoundDisabled: true,
2882
2715
  accessibilityRole: "button",
2883
- accessibilityLabel: "Close",
2716
+ accessibilityLabel: "Cerrar",
2884
2717
  hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
2885
2718
  },
2886
2719
  /* @__PURE__ */ React54__default.default.createElement(vectorIcons.AntDesign, { name: "close", size: ms(18), color: colors.foregroundMuted })
@@ -2900,7 +2733,7 @@ function Sheet({
2900
2733
  {
2901
2734
  ref,
2902
2735
  name,
2903
- onDismiss: onClose,
2736
+ onDismiss: handleDismiss,
2904
2737
  enableDynamicSizing: useDynamicSizing,
2905
2738
  snapPoints,
2906
2739
  maxDynamicContentSize: useDynamicSizing && maxHeight ? maxHeight : void 0,
@@ -2995,16 +2828,13 @@ function Select({
2995
2828
  onValueChange,
2996
2829
  placeholder = "Select an option",
2997
2830
  label,
2831
+ hint,
2998
2832
  error,
2999
2833
  disabled,
3000
2834
  style,
3001
2835
  accessibilityLabel
3002
2836
  }) {
3003
2837
  const { colors } = useTheme();
3004
- const { animatedStyle, onPressIn, onPressOut } = usePressScale({
3005
- pressScale: PRESS_SCALE.button,
3006
- disabled
3007
- });
3008
2838
  const [pickerVisible, setPickerVisible] = React54.useState(false);
3009
2839
  const [pendingValue, setPendingValue] = React54.useState(value);
3010
2840
  const pickerRef = React54.useRef(null);
@@ -3029,20 +2859,20 @@ function Select({
3029
2859
  }
3030
2860
  setPickerVisible(false);
3031
2861
  };
3032
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [animatedStyle, { opacity: disabled ? 0.45 : 1 }] }, /* @__PURE__ */ React54__default.default.createElement(
3033
- reactNative.TouchableOpacity,
2862
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React54__default.default.createElement(
2863
+ PressableButton,
3034
2864
  {
3035
2865
  style: [
3036
2866
  styles23.trigger,
3037
2867
  {
3038
2868
  borderColor: error ? colors.destructive : colors.border,
3039
2869
  backgroundColor: colors.background
3040
- }
2870
+ },
2871
+ disabled && { opacity: 0.45 }
3041
2872
  ],
3042
2873
  onPress: handleOpen,
3043
- onPressIn,
3044
- onPressOut,
3045
- activeOpacity: 1,
2874
+ enabled: !disabled,
2875
+ rippleColor: "transparent",
3046
2876
  touchSoundDisabled: true,
3047
2877
  accessibilityRole: "combobox",
3048
2878
  accessibilityLabel: accessibilityLabel ?? label,
@@ -3062,7 +2892,7 @@ function Select({
3062
2892
  selected?.label ?? placeholder
3063
2893
  ),
3064
2894
  /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 20, color: colors.foregroundMuted })
3065
- )) : null, isIOS ? /* @__PURE__ */ React54__default.default.createElement(
2895
+ ) : null, isIOS ? /* @__PURE__ */ React54__default.default.createElement(
3066
2896
  reactNative.Modal,
3067
2897
  {
3068
2898
  visible: pickerVisible,
@@ -3146,7 +2976,7 @@ function Select({
3146
2976
  enabled: !o.disabled
3147
2977
  }
3148
2978
  ))
3149
- ) : null, error ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles23.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null);
2979
+ ) : null, error ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles23.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : !error && hint ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles23.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
3150
2980
  }
3151
2981
  var styles23 = reactNative.StyleSheet.create({
3152
2982
  container: {
@@ -3170,9 +3000,6 @@ var styles23 = reactNative.StyleSheet.create({
3170
3000
  fontSize: ms(15),
3171
3001
  flex: 1
3172
3002
  },
3173
- chevron: {
3174
- marginLeft: s(8)
3175
- },
3176
3003
  helperText: {
3177
3004
  fontFamily: "Sohne-Regular",
3178
3005
  fontSize: ms(13)
@@ -3399,7 +3226,7 @@ function ListItemBase({
3399
3226
  selectionAsync();
3400
3227
  onPress?.();
3401
3228
  };
3402
- const effectiveLeft = imageSource ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Image, { source: imageSource, style: styles25.image }) : leftIcon ? renderIcon(leftIcon, 24, leftIconColor ?? colors.foreground) : leftRender;
3229
+ const effectiveLeft = imageSource ? /* @__PURE__ */ React54__default.default.createElement(expoImage.Image, { source: imageSource, style: styles25.image }) : leftIcon ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: leftIcon, size: 24, color: leftIconColor ?? colors.foreground }) : leftRender;
3403
3230
  const hasRightContent = !!(rightIcon || rightActions && rightActions.length > 0 || rightRender !== void 0 || showChevron);
3404
3231
  const cardStyle = variant === "card" ? {
3405
3232
  backgroundColor: colors.card,
@@ -3437,7 +3264,7 @@ function ListItemBase({
3437
3264
  allowFontScaling: true
3438
3265
  },
3439
3266
  caption
3440
- ) : null), hasRightContent ? rightIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, renderIcon(rightIcon, 24, rightIconColor ?? colors.foregroundMuted)) : rightActions && rightActions.length > 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles25.rightActionsContainer }, rightActions.map((action, i) => /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, { key: i }, action))) : rightRender !== void 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof rightRender === "string" ? /* @__PURE__ */ React54__default.default.createElement(
3267
+ ) : null), hasRightContent ? rightIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, /* @__PURE__ */ React54__default.default.createElement(Icon, { name: rightIcon, size: 24, color: rightIconColor ?? colors.foregroundMuted })) : rightActions && rightActions.length > 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles25.rightActionsContainer }, rightActions.map((action, i) => /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, { key: i }, action))) : rightRender !== void 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof rightRender === "string" ? /* @__PURE__ */ React54__default.default.createElement(
3441
3268
  reactNative.Text,
3442
3269
  {
3443
3270
  style: [styles25.rightText, { color: colors.foregroundMuted }],
@@ -3624,7 +3451,7 @@ function MenuItemBase({
3624
3451
  selectionAsync();
3625
3452
  onPress();
3626
3453
  };
3627
- const resolvedIcon = iconName ? renderIcon(iconName, 22, iconColor ?? colors.foreground) : icon;
3454
+ const resolvedIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: 22, color: iconColor ?? colors.foreground }) : icon;
3628
3455
  const cardStyle = variant === "card" ? {
3629
3456
  backgroundColor: colors.card,
3630
3457
  borderRadius: RADIUS.md,
@@ -3802,7 +3629,7 @@ function ChipBase({ label, selected = false, onPress, icon, iconName, style, acc
3802
3629
  selectionAsync();
3803
3630
  onPress?.();
3804
3631
  };
3805
- const resolvedIcon = iconName ? renderIcon(iconName, ms(13), selected ? colors.primaryForeground : colors.foreground) : icon;
3632
+ const resolvedIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: ms(13), color: selected ? colors.primaryForeground : colors.foreground }) : icon;
3806
3633
  return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles29.wrapper, style] }, /* @__PURE__ */ React54__default.default.createElement(
3807
3634
  PressableChip,
3808
3635
  {
@@ -3860,14 +3687,14 @@ function ChipGroup({ options, value, onValueChange, multiSelect = false, style }
3860
3687
  onPress: opt.disabled ? void 0 : () => handlePress(opt.value),
3861
3688
  iconName: opt.iconName,
3862
3689
  style: opt.disabled ? styles29.chipDisabled : void 0,
3863
- accessibilityLabel: opt.disabled ? `${opt.label}, unavailable` : opt.label
3690
+ accessibilityLabel: opt.disabled ? `${opt.label}, no disponible` : opt.label
3864
3691
  }
3865
3692
  )));
3866
3693
  }
3867
3694
  var styles29 = reactNative.StyleSheet.create({
3868
3695
  wrapper: {},
3869
3696
  chip: {
3870
- borderRadius: 999,
3697
+ borderRadius: RADIUS.full,
3871
3698
  paddingHorizontal: s(14),
3872
3699
  // AUDIT FIX: was vs(5) → ~28px total height — below WCAG 44px tap target.
3873
3700
  // vs(10) → ~44px total height meets WCAG 2.5.5 (AAA) minimum.
@@ -3901,8 +3728,8 @@ function ConfirmDialog({
3901
3728
  visible,
3902
3729
  title,
3903
3730
  subtitle,
3904
- confirmLabel = "Confirm",
3905
- cancelLabel = "Cancel",
3731
+ confirmLabel = "Confirmar",
3732
+ cancelLabel = "Cancelar",
3906
3733
  confirmVariant = "primary",
3907
3734
  loading = false,
3908
3735
  showCloseButton = false,
@@ -3913,13 +3740,19 @@ function ConfirmDialog({
3913
3740
  const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
3914
3741
  const ref = React54.useRef(null);
3915
3742
  const wasOpened = React54.useRef(false);
3743
+ const isPresentedRef = React54.useRef(false);
3916
3744
  const name = React54.useId();
3745
+ const handleDismiss = React54.useCallback(() => {
3746
+ isPresentedRef.current = false;
3747
+ onCancel();
3748
+ }, [onCancel]);
3917
3749
  React54.useEffect(() => {
3918
- if (visible) {
3750
+ if (visible && !isPresentedRef.current) {
3919
3751
  impactMedium();
3920
3752
  ref.current?.present();
3921
3753
  wasOpened.current = true;
3922
- } else if (wasOpened.current) {
3754
+ isPresentedRef.current = true;
3755
+ } else if (!visible && wasOpened.current && isPresentedRef.current) {
3923
3756
  ref.current?.dismiss();
3924
3757
  }
3925
3758
  }, [visible]);
@@ -3940,7 +3773,7 @@ function ConfirmDialog({
3940
3773
  {
3941
3774
  ref,
3942
3775
  name,
3943
- onDismiss: onCancel,
3776
+ onDismiss: handleDismiss,
3944
3777
  enableDynamicSizing: true,
3945
3778
  backdropComponent: renderBackdrop,
3946
3779
  backgroundStyle: { ...styles30.background, backgroundColor: colors.card },
@@ -3956,7 +3789,7 @@ function ConfirmDialog({
3956
3789
  activeOpacity: 0.6,
3957
3790
  touchSoundDisabled: true,
3958
3791
  accessibilityRole: "button",
3959
- accessibilityLabel: "Close",
3792
+ accessibilityLabel: "Cerrar",
3960
3793
  hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
3961
3794
  },
3962
3795
  /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Feather, { name: "x", size: ms(18), color: colors.foregroundMuted })
@@ -4041,7 +3874,7 @@ var styles30 = reactNative.StyleSheet.create({
4041
3874
  });
4042
3875
  function LabelValueBase({ label, value, iconName, iconColor, style }) {
4043
3876
  const { colors } = useTheme();
4044
- const resolvedIcon = iconName ? renderIcon(iconName, ms(14), iconColor ?? colors.foregroundMuted) : null;
3877
+ const resolvedIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: ms(14), color: iconColor ?? colors.foregroundMuted }) : null;
4045
3878
  return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles31.container, style] }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles31.labelSide }, resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles31.icon }, resolvedIcon) : null, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles31.label, { color: colors.foregroundMuted }], allowFontScaling: true }, label)), typeof value === "string" ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles31.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
4046
3879
  }
4047
3880
  var LabelValue = React54__default.default.memo(LabelValueBase);
@@ -4118,7 +3951,7 @@ function MonthPicker({ value, onChange, minValue, maxValue, locale = "en", forma
4118
3951
  activeOpacity: 0.6,
4119
3952
  touchSoundDisabled: true,
4120
3953
  accessibilityRole: "button",
4121
- accessibilityLabel: "Previous month",
3954
+ accessibilityLabel: "Mes anterior",
4122
3955
  accessibilityState: { disabled: prevDisabled },
4123
3956
  hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
4124
3957
  },
@@ -4140,7 +3973,7 @@ function MonthPicker({ value, onChange, minValue, maxValue, locale = "en", forma
4140
3973
  activeOpacity: 0.6,
4141
3974
  touchSoundDisabled: true,
4142
3975
  accessibilityRole: "button",
4143
- accessibilityLabel: "Next month",
3976
+ accessibilityLabel: "Mes siguiente",
4144
3977
  accessibilityState: { disabled: nextDisabled },
4145
3978
  hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
4146
3979
  },
@@ -4195,71 +4028,53 @@ function MediaCardBase({
4195
4028
  accessibilityLabel
4196
4029
  }) {
4197
4030
  const { colors } = useTheme();
4198
- const { hovered, hoverHandlers } = useHover();
4199
- const { animatedStyle, onPressIn, onPressOut } = usePressScale({
4200
- pressScale: PRESS_SCALE.card,
4201
- pressInSpring: SPRINGS.surfacePressIn,
4202
- pressOutSpring: SPRINGS.surfacePressOut,
4203
- disabled: !onPress
4204
- });
4205
4031
  const handlePress = () => {
4206
4032
  if (!onPress) return;
4207
4033
  impactLight();
4208
4034
  onPress();
4209
4035
  };
4210
4036
  const ratio = aspectRatioMap2[aspectRatio];
4211
- const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
4037
+ const resolvedActionIcon = actionIconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: actionIconName, size: 18, color: actionActive ? colors.primary : colors.background }) : actionIcon ?? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "heart", size: 18, color: actionActive ? colors.primary : colors.background });
4212
4038
  const a11yLabel = accessibilityLabel ?? [title, subtitle].filter(Boolean).join(". ");
4213
- const cardContent = /* @__PURE__ */ React54__default.default.createElement(
4214
- reactNative.View,
4039
+ const cardContent = /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles33.card, style] }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles33.imageContainer, imageStyle] }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React54__default.default.createElement(
4040
+ expoImage.Image,
4215
4041
  {
4216
- style: [
4217
- styles33.card,
4218
- hovered && styles33.cardHovered,
4219
- style
4220
- ],
4221
- ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
4222
- },
4223
- /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles33.imageContainer, imageStyle] }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React54__default.default.createElement(
4224
- reactNative.Image,
4225
- {
4226
- source: imageSource,
4227
- style: styles33.image,
4228
- resizeMode: "cover"
4229
- }
4230
- ) : /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles33.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles33.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React54__default.default.createElement(
4231
- reactNative.TouchableOpacity,
4232
- {
4233
- style: [styles33.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
4234
- onPress: (e) => {
4235
- e?.stopPropagation?.();
4236
- impactLight();
4237
- onActionPress?.();
4238
- },
4239
- activeOpacity: 0.8,
4240
- touchSoundDisabled: true,
4241
- accessibilityRole: reactNative.Platform.OS === "web" && onPress ? void 0 : "button",
4242
- accessibilityLabel: actionIconName ?? "action",
4243
- accessibilityState: { selected: actionActive }
4042
+ source: imageSource,
4043
+ style: styles33.image,
4044
+ contentFit: "cover"
4045
+ }
4046
+ ) : /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles33.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles33.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React54__default.default.createElement(
4047
+ reactNative.TouchableOpacity,
4048
+ {
4049
+ style: [styles33.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
4050
+ onPress: (e) => {
4051
+ e?.stopPropagation?.();
4052
+ impactLight();
4053
+ onActionPress?.();
4244
4054
  },
4245
- resolvedActionIcon
4246
- )),
4247
- (title || subtitle || caption || footer) && /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles33.meta }, title ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles33.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles33.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles33.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
4248
- );
4055
+ activeOpacity: 0.8,
4056
+ touchSoundDisabled: true,
4057
+ accessibilityRole: reactNative.Platform.OS === "web" && onPress ? void 0 : "button",
4058
+ accessibilityLabel: actionIconName ?? "acci\xF3n",
4059
+ accessibilityState: { selected: actionActive }
4060
+ },
4061
+ resolvedActionIcon
4062
+ )), (title || subtitle || caption || footer) && /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles33.meta }, title ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles33.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles33.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles33.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer));
4249
4063
  if (onPress) {
4250
- return /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: animatedStyle }, /* @__PURE__ */ React54__default.default.createElement(
4251
- reactNative.TouchableOpacity,
4064
+ return /* @__PURE__ */ React54__default.default.createElement(
4065
+ PressableCard,
4252
4066
  {
4253
4067
  onPress: handlePress,
4254
- onPressIn,
4255
- onPressOut,
4256
- activeOpacity: 1,
4068
+ enabled: true,
4069
+ rippleColor: "transparent",
4257
4070
  touchSoundDisabled: true,
4071
+ activateOnHover: true,
4258
4072
  accessibilityRole: "button",
4259
- accessibilityLabel: a11yLabel
4073
+ accessibilityLabel: a11yLabel,
4074
+ accessibilityState: { disabled: false }
4260
4075
  },
4261
4076
  cardContent
4262
- ));
4077
+ );
4263
4078
  }
4264
4079
  return cardContent;
4265
4080
  }
@@ -4270,9 +4085,6 @@ var styles33 = reactNative.StyleSheet.create({
4270
4085
  overflow: "hidden",
4271
4086
  backgroundColor: "transparent"
4272
4087
  },
4273
- cardHovered: {
4274
- ...SHADOWS.md
4275
- },
4276
4088
  imageContainer: {
4277
4089
  borderRadius: RADIUS.md,
4278
4090
  overflow: "hidden"
@@ -4327,19 +4139,16 @@ var CategoryChip = React54__default.default.memo(function CategoryChip2({
4327
4139
  onSelect
4328
4140
  }) {
4329
4141
  const { colors } = useTheme();
4330
- const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
4331
- pressScale: PRESS_SCALE.chip
4332
- });
4333
4142
  const iconColor = selected ? colors.primaryForeground : colors.foregroundSubtle;
4334
- const resolvedIcon = typeof item.icon === "string" ? renderIcon(item.icon, 16, iconColor) : item.icon ?? null;
4335
- return /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: scaleStyle, ...hoverHandlers }, /* @__PURE__ */ React54__default.default.createElement(
4336
- reactNative.TouchableOpacity,
4143
+ const resolvedIcon = typeof item.icon === "string" ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: item.icon, size: 16, color: iconColor }) : item.icon ?? null;
4144
+ return /* @__PURE__ */ React54__default.default.createElement(
4145
+ PressableChip,
4337
4146
  {
4338
4147
  onPress: () => onSelect(item.value),
4339
- onPressIn,
4340
- onPressOut,
4341
- activeOpacity: 1,
4148
+ enabled: true,
4149
+ rippleColor: "transparent",
4342
4150
  touchSoundDisabled: true,
4151
+ activateOnHover: true,
4343
4152
  accessibilityRole: "button",
4344
4153
  accessibilityLabel: item.label,
4345
4154
  accessibilityState: { selected }
@@ -4365,7 +4174,7 @@ var CategoryChip = React54__default.default.memo(function CategoryChip2({
4365
4174
  ),
4366
4175
  item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles34.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles34.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99)))
4367
4176
  )
4368
- ));
4177
+ );
4369
4178
  });
4370
4179
  function CategoryStrip({
4371
4180
  categories,
@@ -4451,7 +4260,7 @@ var styles34 = reactNative.StyleSheet.create({
4451
4260
  lineHeight: 14
4452
4261
  }
4453
4262
  });
4454
- function Pressable2({
4263
+ function Pressable({
4455
4264
  children,
4456
4265
  onPress,
4457
4266
  pressScale: _pressScale = PRESS_SCALE.card,
@@ -4506,8 +4315,8 @@ function DetailRowBase({
4506
4315
  valueStyle
4507
4316
  }) {
4508
4317
  const { colors } = useTheme();
4509
- const resolvedLeftIcon = leftIconName ? renderIcon(leftIconName, ms(14), leftIconColor ?? colors.foregroundMuted) : leftIcon;
4510
- const resolvedRightIcon = rightIconName ? renderIcon(rightIconName, ms(14), rightIconColor ?? colors.foregroundMuted) : null;
4318
+ const resolvedLeftIcon = leftIconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: leftIconName, size: ms(14), color: leftIconColor ?? colors.foregroundMuted }) : leftIcon;
4319
+ const resolvedRightIcon = rightIconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: rightIconName, size: ms(14), color: rightIconColor ?? colors.foregroundMuted }) : null;
4511
4320
  const separatorStyle = separator === "none" ? null : {
4512
4321
  flex: 1,
4513
4322
  height: 1,
@@ -4632,32 +4441,6 @@ var styles36 = reactNative.StyleSheet.create({
4632
4441
  paddingTop: vs(8)
4633
4442
  }
4634
4443
  });
4635
- var defaultKeyExtractor = (item, index) => {
4636
- const id = item?.id;
4637
- return id !== void 0 ? String(id) : String(index);
4638
- };
4639
- function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, ref) {
4640
- const getItemLayout = React54.useCallback(
4641
- (_data, index) => ({
4642
- length: itemHeight ?? 0,
4643
- offset: (itemHeight ?? 0) * index,
4644
- index
4645
- }),
4646
- [itemHeight]
4647
- );
4648
- return /* @__PURE__ */ React54__default.default.createElement(
4649
- reactNative.FlatList,
4650
- {
4651
- ref,
4652
- keyExtractor: keyExtractor ?? defaultKeyExtractor,
4653
- renderItem,
4654
- getItemLayout: itemHeight !== void 0 ? getItemLayout : void 0,
4655
- removeClippedSubviews: true,
4656
- ...props
4657
- }
4658
- );
4659
- }
4660
- var VirtualList = React54__default.default.forwardRef(VirtualListInner);
4661
4444
  function RetrayProvider({ children, theme, colorScheme = "system" }) {
4662
4445
  return /* @__PURE__ */ React54__default.default.createElement(reactNativeSafeAreaContext.SafeAreaProvider, { initialMetrics: reactNativeSafeAreaContext.initialWindowMetrics }, /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles37.root }, /* @__PURE__ */ React54__default.default.createElement(ThemeProvider, { theme, colorScheme }, /* @__PURE__ */ React54__default.default.createElement(bottomSheet.BottomSheetModalProvider, null, /* @__PURE__ */ React54__default.default.createElement(ToastProvider, null, children)))));
4663
4446
  }
@@ -4667,11 +4450,11 @@ var styles37 = reactNative.StyleSheet.create({
4667
4450
  function DefaultErrorFallback({
4668
4451
  error,
4669
4452
  reset,
4670
- title = "Something went wrong",
4453
+ title = "Algo sali\xF3 mal",
4671
4454
  message
4672
4455
  }) {
4673
4456
  const { colors } = useTheme();
4674
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles38.container, { backgroundColor: colors.background }], accessibilityRole: "alert" }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles38.iconCircle, { backgroundColor: colors.destructiveTint }] }, renderIcon("alert-triangle", ms(28), colors.destructive)), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles38.title, { color: colors.foreground }], allowFontScaling: true }, title), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles38.message, { color: colors.foregroundMuted }], allowFontScaling: true }, message ?? error.message ?? "An unexpected error occurred."), /* @__PURE__ */ React54__default.default.createElement(
4457
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles38.container, { backgroundColor: colors.background }], accessibilityRole: "alert" }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles38.iconCircle, { backgroundColor: colors.destructiveTint }] }, /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "alert-triangle", size: ms(28), color: colors.destructive })), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles38.title, { color: colors.foreground }], allowFontScaling: true }, title), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles38.message, { color: colors.foregroundMuted }], allowFontScaling: true }, message ?? error.message ?? "Ocurri\xF3 un error inesperado."), /* @__PURE__ */ React54__default.default.createElement(
4675
4458
  reactNative.TouchableOpacity,
4676
4459
  {
4677
4460
  style: [styles38.button, { backgroundColor: colors.primary }],
@@ -4682,9 +4465,9 @@ function DefaultErrorFallback({
4682
4465
  activeOpacity: 0.85,
4683
4466
  touchSoundDisabled: true,
4684
4467
  accessibilityRole: "button",
4685
- accessibilityLabel: "Try again"
4468
+ accessibilityLabel: "Intentar de nuevo"
4686
4469
  },
4687
- /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles38.buttonLabel, { color: colors.primaryForeground }], allowFontScaling: true }, "Try again")
4470
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles38.buttonLabel, { color: colors.primaryForeground }], allowFontScaling: true }, "Intentar de nuevo")
4688
4471
  ));
4689
4472
  }
4690
4473
  var ErrorBoundary = class extends React54__default.default.Component {
@@ -4759,29 +4542,30 @@ var styles38 = reactNative.StyleSheet.create({
4759
4542
  }
4760
4543
  });
4761
4544
  function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }) {
4762
- const progress = Animated12.useSharedValue(active ? 1 : 0);
4545
+ const progress = Animated6.useSharedValue(active ? 1 : 0);
4763
4546
  React54.useEffect(() => {
4764
- progress.value = Animated12.withSpring(active ? 1 : 0, SPRINGS.glide);
4547
+ progress.value = Animated6.withSpring(active ? 1 : 0, SPRINGS.glide);
4765
4548
  }, [active, progress]);
4766
- const animatedStyle = Animated12.useAnimatedStyle(() => ({
4767
- width: size + progress.value * size * 1.5,
4768
- backgroundColor: Animated12.interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor])
4549
+ const animatedStyle = Animated6.useAnimatedStyle(() => ({
4550
+ width: size + progress.value * size,
4551
+ backgroundColor: Animated6.interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor])
4769
4552
  }));
4770
- const dot = /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [{ height: size, borderRadius: size / 2 }, animatedStyle] });
4553
+ const dot = /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: [{ height: size, borderRadius: size / 2 }, animatedStyle] });
4771
4554
  if (!onPress) return dot;
4772
4555
  const handlePress = () => {
4773
4556
  selectionAsync();
4774
4557
  onPress();
4775
4558
  };
4776
4559
  return /* @__PURE__ */ React54__default.default.createElement(
4777
- reactNative.TouchableOpacity,
4560
+ PressableButton,
4778
4561
  {
4779
4562
  onPress: handlePress,
4780
- activeOpacity: 0.7,
4563
+ rippleColor: "transparent",
4781
4564
  touchSoundDisabled: true,
4782
4565
  accessibilityRole: "button",
4783
- accessibilityLabel: `Page ${index + 1} of ${total}${active ? ", current page" : ""}`,
4784
- hitSlop: { top: 8, bottom: 8, left: 4, right: 4 }
4566
+ accessibilityLabel: `P\xE1gina ${index + 1} de ${total}${active ? ", p\xE1gina actual" : ""}`,
4567
+ hitSlop: { top: 10, bottom: 10, left: 18, right: 18 },
4568
+ style: styles39.dotTouchable
4785
4569
  },
4786
4570
  dot
4787
4571
  );
@@ -4792,7 +4576,7 @@ function PagerDots({
4792
4576
  onDotPress,
4793
4577
  showControls = false,
4794
4578
  dotSize = 8,
4795
- spacing = 8,
4579
+ spacing = 4,
4796
4580
  activeColor,
4797
4581
  inactiveColor,
4798
4582
  style
@@ -4827,21 +4611,21 @@ function PagerDots({
4827
4611
  {
4828
4612
  style: [styles39.container, { gap: s(spacing) }, style],
4829
4613
  accessibilityRole: "adjustable",
4830
- accessibilityLabel: `Page ${activeIndex + 1} of ${count}`
4614
+ accessibilityLabel: `P\xE1gina ${activeIndex + 1} de ${count}`
4831
4615
  },
4832
4616
  hasControls && /* @__PURE__ */ React54__default.default.createElement(
4833
- reactNative.TouchableOpacity,
4617
+ PressableButton,
4834
4618
  {
4835
4619
  onPress: handlePrevious,
4836
- disabled: !canGoPrev,
4837
- activeOpacity: 0.7,
4620
+ enabled: canGoPrev,
4621
+ rippleColor: "transparent",
4838
4622
  touchSoundDisabled: true,
4839
4623
  accessibilityRole: "button",
4840
- accessibilityLabel: "Previous page",
4841
- hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
4624
+ accessibilityLabel: "P\xE1gina anterior",
4625
+ hitSlop: { top: 10, bottom: 10, left: 10, right: 10 },
4842
4626
  style: [styles39.controlBtn, !canGoPrev && styles39.controlBtnDisabled]
4843
4627
  },
4844
- renderIcon("chevron-left", s(18), canGoPrev ? colors.foreground : colors.foregroundMuted)
4628
+ /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "chevron-left", size: s(18), color: canGoPrev ? colors.foreground : colors.foregroundMuted })
4845
4629
  ),
4846
4630
  /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles39.dotsRow, { gap: s(spacing) }] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React54__default.default.createElement(
4847
4631
  Dot,
@@ -4857,18 +4641,18 @@ function PagerDots({
4857
4641
  }
4858
4642
  ))),
4859
4643
  hasControls && /* @__PURE__ */ React54__default.default.createElement(
4860
- reactNative.TouchableOpacity,
4644
+ PressableButton,
4861
4645
  {
4862
4646
  onPress: handleNext,
4863
- disabled: !canGoNext,
4864
- activeOpacity: 0.7,
4647
+ enabled: canGoNext,
4648
+ rippleColor: "transparent",
4865
4649
  touchSoundDisabled: true,
4866
4650
  accessibilityRole: "button",
4867
- accessibilityLabel: "Next page",
4868
- hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
4651
+ accessibilityLabel: "P\xE1gina siguiente",
4652
+ hitSlop: { top: 10, bottom: 10, left: 10, right: 10 },
4869
4653
  style: [styles39.controlBtn, !canGoNext && styles39.controlBtnDisabled]
4870
4654
  },
4871
- renderIcon("chevron-right", s(18), canGoNext ? colors.foreground : colors.foregroundMuted)
4655
+ /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "chevron-right", size: s(18), color: canGoNext ? colors.foreground : colors.foregroundMuted })
4872
4656
  )
4873
4657
  );
4874
4658
  }
@@ -4883,7 +4667,15 @@ var styles39 = reactNative.StyleSheet.create({
4883
4667
  alignItems: "center"
4884
4668
  },
4885
4669
  controlBtn: {
4886
- padding: s(4)
4670
+ padding: s(4),
4671
+ minHeight: 44,
4672
+ justifyContent: "center"
4673
+ },
4674
+ dotTouchable: {
4675
+ minHeight: 44,
4676
+ paddingHorizontal: s(14),
4677
+ justifyContent: "center",
4678
+ alignItems: "center"
4887
4679
  },
4888
4680
  controlBtnDisabled: {
4889
4681
  opacity: 0.3
@@ -4914,7 +4706,7 @@ function AppHeader({
4914
4706
  variant: "text",
4915
4707
  size: "md",
4916
4708
  onPress: onBack,
4917
- accessibilityLabel: "Go back"
4709
+ accessibilityLabel: "Atr\xE1s"
4918
4710
  }
4919
4711
  ) : null);
4920
4712
  const titleBlock = /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles40.titleBlock, centered && styles40.titleBlockCentered], pointerEvents: "none" }, title ? /* @__PURE__ */ React54__default.default.createElement(
@@ -5000,26 +4792,21 @@ function isSelected(value, candidate) {
5000
4792
  }
5001
4793
  function Cell({ item, selected, width, onPress }) {
5002
4794
  const { colors } = useTheme();
5003
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
5004
- pressScale: PRESS_SCALE.chip,
5005
- disabled: item.disabled
5006
- });
5007
4795
  const iconColor = selected ? colors.primary : colors.foregroundSubtle;
5008
- const iconNode = item.icon ?? (item.iconName ? renderIcon(item.iconName, ms(24), iconColor) : null);
5009
- return /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [{ width }, animatedStyle] }, /* @__PURE__ */ React54__default.default.createElement(
5010
- reactNative.TouchableOpacity,
4796
+ const iconNode = item.icon ?? (item.iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: item.iconName, size: ms(24), color: iconColor }) : null);
4797
+ return /* @__PURE__ */ React54__default.default.createElement(
4798
+ PressableChip,
5011
4799
  {
5012
4800
  onPress,
5013
- onPressIn,
5014
- onPressOut,
5015
- disabled: item.disabled,
5016
- activeOpacity: 1,
4801
+ enabled: !item.disabled,
4802
+ rippleColor: "transparent",
5017
4803
  touchSoundDisabled: true,
4804
+ activateOnHover: true,
5018
4805
  accessibilityRole: "button",
5019
4806
  accessibilityState: { selected, disabled: item.disabled },
5020
4807
  accessibilityLabel: item.label ?? String(item.value),
5021
- ...hoverHandlers,
5022
4808
  style: [
4809
+ { width },
5023
4810
  styles41.cell,
5024
4811
  {
5025
4812
  backgroundColor: selected ? colors.primary + "14" : colors.surface,
@@ -5038,7 +4825,7 @@ function Cell({ item, selected, width, onPress }) {
5038
4825
  },
5039
4826
  item.label
5040
4827
  ) : null
5041
- ));
4828
+ );
5042
4829
  }
5043
4830
  function SelectableGrid({
5044
4831
  items,
@@ -5109,25 +4896,247 @@ var styles41 = reactNative.StyleSheet.create({
5109
4896
  paddingHorizontal: s(4)
5110
4897
  },
5111
4898
  cell: {
5112
- flex: 1,
5113
4899
  borderRadius: RADIUS.md,
5114
4900
  borderWidth: 2,
5115
4901
  alignItems: "center",
5116
4902
  justifyContent: "center",
5117
4903
  gap: vs(4),
5118
- paddingHorizontal: s(12),
5119
- paddingVertical: vs(12)
4904
+ paddingHorizontal: s(8),
4905
+ paddingVertical: vs(10)
5120
4906
  },
5121
4907
  cellDisabled: {
5122
4908
  opacity: 0.4
5123
4909
  },
5124
4910
  label: {
5125
4911
  fontFamily: "Sohne-Medium",
5126
- fontSize: ms(12),
5127
- lineHeight: mvs(15),
4912
+ fontSize: ms(11),
4913
+ lineHeight: mvs(14),
5128
4914
  textAlign: "center"
5129
4915
  }
5130
4916
  });
4917
+ var SelectableCardContext = React54.createContext(null);
4918
+ function SelectableCardGroup({
4919
+ type,
4920
+ value,
4921
+ onValueChange,
4922
+ variant = "elevated",
4923
+ gap = s(8),
4924
+ style,
4925
+ children
4926
+ }) {
4927
+ return /* @__PURE__ */ React54__default.default.createElement(SelectableCardContext.Provider, { value: { type, value, onValueChange, variant } }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles42.group, { gap }, style] }, children));
4928
+ }
4929
+ function SelectableCard({
4930
+ value,
4931
+ title,
4932
+ description,
4933
+ iconName,
4934
+ icon,
4935
+ disabled = false,
4936
+ style
4937
+ }) {
4938
+ const ctx = React54.useContext(SelectableCardContext);
4939
+ if (!ctx) {
4940
+ throw new Error("SelectableCard must be used inside <SelectableCard.Group>");
4941
+ }
4942
+ const { colors } = useTheme();
4943
+ const { type, value: selectedValue, onValueChange, variant } = ctx;
4944
+ const isSelected2 = type === "radio" ? selectedValue === value : Array.isArray(selectedValue) && selectedValue.includes(value);
4945
+ const handlePress = () => {
4946
+ if (disabled) return;
4947
+ impactLight();
4948
+ if (type === "radio") {
4949
+ onValueChange(value);
4950
+ } else {
4951
+ const arr = Array.isArray(selectedValue) ? selectedValue : [];
4952
+ if (arr.includes(value)) {
4953
+ onValueChange(arr.filter((v) => v !== value));
4954
+ } else {
4955
+ onValueChange([...arr, value]);
4956
+ }
4957
+ }
4958
+ };
4959
+ const variantStyle = (() => {
4960
+ const borderWidth = 2;
4961
+ const base = {
4962
+ elevated: {
4963
+ backgroundColor: colors.card,
4964
+ borderWidth,
4965
+ borderColor: "transparent"
4966
+ // reserve space for selected border
4967
+ },
4968
+ outlined: {
4969
+ backgroundColor: colors.card,
4970
+ borderWidth,
4971
+ borderColor: colors.border
4972
+ },
4973
+ filled: {
4974
+ backgroundColor: colors.surfaceStrong,
4975
+ borderWidth,
4976
+ borderColor: colors.border
4977
+ }
4978
+ }[variant];
4979
+ if (isSelected2 && !disabled) {
4980
+ return {
4981
+ ...base,
4982
+ borderColor: colors.primary,
4983
+ shadowColor: "transparent",
4984
+ shadowOpacity: 0,
4985
+ shadowRadius: 0,
4986
+ elevation: 0
4987
+ };
4988
+ }
4989
+ if (disabled) {
4990
+ return {
4991
+ ...base,
4992
+ shadowColor: "transparent",
4993
+ shadowOpacity: 0,
4994
+ shadowRadius: 0,
4995
+ elevation: 0,
4996
+ borderColor: colors.border
4997
+ };
4998
+ }
4999
+ return base;
5000
+ })();
5001
+ const resolvedIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: ms(22), color: disabled ? colors.foregroundMuted : colors.foregroundMuted }) : icon;
5002
+ const resolvedIconElement = resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles42.iconWrapper, disabled && { opacity: 0.45 }] }, resolvedIcon) : null;
5003
+ return /* @__PURE__ */ React54__default.default.createElement(
5004
+ reactNative.Pressable,
5005
+ {
5006
+ onPress: handlePress,
5007
+ disabled,
5008
+ accessibilityRole: type === "radio" ? "radio" : "checkbox",
5009
+ accessibilityLabel: `${title}${description ? `, ${description}` : ""}`,
5010
+ accessibilityState: { selected: isSelected2, disabled },
5011
+ style: [
5012
+ styles42.card,
5013
+ variantStyle,
5014
+ isSelected2 && !disabled && styles42.cardSelected,
5015
+ style
5016
+ ]
5017
+ },
5018
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles42.row }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles42.selectorContainer }, type === "radio" ? /* @__PURE__ */ React54__default.default.createElement(
5019
+ reactNativeEase.EaseView,
5020
+ {
5021
+ style: styles42.radioCircle,
5022
+ animate: { borderColor: !disabled && isSelected2 ? colors.primary : colors.border },
5023
+ transition: COLOR_TRANSITION
5024
+ },
5025
+ /* @__PURE__ */ React54__default.default.createElement(
5026
+ reactNativeEase.EaseView,
5027
+ {
5028
+ animate: {
5029
+ scale: !disabled && isSelected2 ? 1 : 0,
5030
+ opacity: !disabled && isSelected2 ? 1 : 0
5031
+ },
5032
+ transition: SPRING_ELASTIC
5033
+ },
5034
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles42.radioDot, { backgroundColor: colors.primary }] })
5035
+ )
5036
+ ) : /* @__PURE__ */ React54__default.default.createElement(
5037
+ reactNativeEase.EaseView,
5038
+ {
5039
+ style: styles42.checkboxBox,
5040
+ animate: {
5041
+ borderColor: !disabled && isSelected2 ? colors.primary : colors.border,
5042
+ backgroundColor: !disabled && isSelected2 ? colors.primary : "transparent"
5043
+ },
5044
+ transition: COLOR_TRANSITION
5045
+ },
5046
+ /* @__PURE__ */ React54__default.default.createElement(
5047
+ reactNativeEase.EaseView,
5048
+ {
5049
+ animate: { opacity: !disabled && isSelected2 ? 1 : 0 },
5050
+ transition: OPACITY_TRANSITION
5051
+ },
5052
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles42.checkmark, { borderColor: colors.primaryForeground }] })
5053
+ )
5054
+ )), resolvedIconElement, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles42.textArea }, /* @__PURE__ */ React54__default.default.createElement(
5055
+ reactNative.Text,
5056
+ {
5057
+ style: [styles42.title, { color: disabled ? colors.foregroundMuted : colors.foreground }],
5058
+ allowFontScaling: true,
5059
+ numberOfLines: 2
5060
+ },
5061
+ title
5062
+ ), description ? /* @__PURE__ */ React54__default.default.createElement(
5063
+ reactNative.Text,
5064
+ {
5065
+ style: [styles42.description, { color: disabled ? colors.foregroundMuted : colors.foregroundSubtle }],
5066
+ allowFontScaling: true,
5067
+ numberOfLines: 4
5068
+ },
5069
+ description
5070
+ ) : null))
5071
+ );
5072
+ }
5073
+ var styles42 = reactNative.StyleSheet.create({
5074
+ group: {
5075
+ width: "100%"
5076
+ },
5077
+ card: {
5078
+ borderRadius: RADIUS.md,
5079
+ borderWidth: 1
5080
+ },
5081
+ cardSelected: {
5082
+ backgroundColor: void 0
5083
+ // overridden by variantStyle
5084
+ },
5085
+ row: {
5086
+ flexDirection: "row",
5087
+ alignItems: "flex-start",
5088
+ padding: s(16),
5089
+ gap: s(12)
5090
+ },
5091
+ selectorContainer: {
5092
+ paddingTop: vs(1)
5093
+ },
5094
+ radioCircle: {
5095
+ width: s(24),
5096
+ height: s(24),
5097
+ borderRadius: s(12),
5098
+ borderWidth: 2,
5099
+ alignItems: "center",
5100
+ justifyContent: "center"
5101
+ },
5102
+ radioDot: {
5103
+ width: s(10),
5104
+ height: s(10),
5105
+ borderRadius: s(5)
5106
+ },
5107
+ checkboxBox: {
5108
+ width: s(24),
5109
+ height: s(24),
5110
+ borderRadius: ms(4),
5111
+ borderWidth: 2,
5112
+ alignItems: "center",
5113
+ justifyContent: "center"
5114
+ },
5115
+ checkmark: {
5116
+ width: s(12),
5117
+ height: vs(7),
5118
+ borderLeftWidth: 2,
5119
+ borderBottomWidth: 2,
5120
+ transform: [{ rotate: "-45deg" }, { translateY: -1 }]
5121
+ },
5122
+ iconWrapper: {
5123
+ paddingTop: vs(1)
5124
+ },
5125
+ textArea: {
5126
+ flex: 1,
5127
+ gap: vs(4)
5128
+ },
5129
+ title: {
5130
+ fontFamily: "Sohne-SemiBold",
5131
+ fontSize: ms(16),
5132
+ lineHeight: mvs(22)
5133
+ },
5134
+ description: {
5135
+ fontFamily: "Sohne-Regular",
5136
+ fontSize: ms(13),
5137
+ lineHeight: mvs(18)
5138
+ }
5139
+ });
5131
5140
  var normalize = (f) => typeof f === "string" ? { label: f, included: true } : { included: true, ...f };
5132
5141
  function PricingCard({
5133
5142
  name,
@@ -5147,7 +5156,7 @@ function PricingCard({
5147
5156
  reactNative.View,
5148
5157
  {
5149
5158
  style: [
5150
- styles42.card,
5159
+ styles43.card,
5151
5160
  {
5152
5161
  backgroundColor: colors.card,
5153
5162
  borderColor: highlighted ? colors.primary : colors.border,
@@ -5158,20 +5167,23 @@ function PricingCard({
5158
5167
  ],
5159
5168
  accessibilityRole: "summary"
5160
5169
  },
5161
- /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles42.header }, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles42.name, { color: colors.foreground }], allowFontScaling: true }, name), badge ? /* @__PURE__ */ React54__default.default.createElement(Badge, { label: badge, variant: highlighted ? "default" : "secondary", size: "sm" }) : null),
5162
- /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles42.priceRow }, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles42.price, { color: colors.foreground }], allowFontScaling: true }, price), period ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles42.period, { color: colors.foregroundMuted }], allowFontScaling: true }, period) : null),
5163
- description ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles42.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null,
5164
- features.length > 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles42.features }, features.map(normalize).map((f, i) => /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { key: i, style: styles42.featureRow }, renderIcon(
5165
- f.included ? "check" : "minus",
5166
- ms(16),
5167
- f.included ? colors.success : colors.foregroundMuted
5170
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles43.header }, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.name, { color: colors.foreground }], allowFontScaling: true }, name), badge ? /* @__PURE__ */ React54__default.default.createElement(Badge, { label: badge, variant: highlighted ? "default" : "secondary", size: "sm" }) : null),
5171
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles43.priceRow }, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.price, { color: colors.foreground }], allowFontScaling: true }, price), period ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.period, { color: colors.foregroundMuted }], allowFontScaling: true }, period) : null),
5172
+ description ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null,
5173
+ features.length > 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles43.features }, features.map(normalize).map((f, i) => /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { key: i, style: styles43.featureRow }, /* @__PURE__ */ React54__default.default.createElement(
5174
+ Icon,
5175
+ {
5176
+ name: f.included ? "check" : "minus",
5177
+ size: ms(16),
5178
+ color: f.included ? colors.success : colors.foregroundMuted
5179
+ }
5168
5180
  ), /* @__PURE__ */ React54__default.default.createElement(
5169
5181
  reactNative.Text,
5170
5182
  {
5171
5183
  style: [
5172
- styles42.featureLabel,
5184
+ styles43.featureLabel,
5173
5185
  { color: f.included ? colors.foreground : colors.foregroundMuted },
5174
- !f.included && styles42.featureExcluded
5186
+ !f.included && styles43.featureExcluded
5175
5187
  ],
5176
5188
  allowFontScaling: true
5177
5189
  },
@@ -5184,13 +5196,13 @@ function PricingCard({
5184
5196
  variant: highlighted ? "primary" : "secondary",
5185
5197
  fullWidth: true,
5186
5198
  onPress: onCtaPress,
5187
- style: styles42.cta
5199
+ style: styles43.cta
5188
5200
  }
5189
5201
  ) : null,
5190
- footnote ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles42.footnote, { color: colors.foregroundMuted }], allowFontScaling: true }, footnote) : null
5202
+ footnote ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.footnote, { color: colors.foregroundMuted }], allowFontScaling: true }, footnote) : null
5191
5203
  );
5192
5204
  }
5193
- var styles42 = reactNative.StyleSheet.create({
5205
+ var styles43 = reactNative.StyleSheet.create({
5194
5206
  card: {
5195
5207
  borderRadius: RADIUS.md,
5196
5208
  padding: s(16),
@@ -5273,7 +5285,7 @@ function TabBar({
5273
5285
  reactNative.View,
5274
5286
  {
5275
5287
  style: [
5276
- styles43.container,
5288
+ styles44.container,
5277
5289
  {
5278
5290
  backgroundColor: colors.card,
5279
5291
  borderTopColor: colors.border,
@@ -5286,41 +5298,41 @@ function TabBar({
5286
5298
  items.map((item) => {
5287
5299
  const active = item.key === activeKey;
5288
5300
  const tint = active ? resolvedActive : resolvedInactive;
5289
- const iconNode = item.icon ?? (item.iconName ? renderIcon(item.iconName, ms(24), tint) : null);
5301
+ const iconNode = item.icon ?? (item.iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: item.iconName, size: ms(24), color: tint }) : null);
5290
5302
  const showBadge = item.badge !== void 0 && item.badge !== false;
5291
5303
  const badgeCount = typeof item.badge === "number" ? item.badge : void 0;
5292
5304
  return /* @__PURE__ */ React54__default.default.createElement(
5293
- reactNative.TouchableOpacity,
5305
+ PressableTab,
5294
5306
  {
5295
5307
  key: item.key,
5296
- style: styles43.tab,
5297
5308
  onPress: () => {
5298
5309
  if (!active) selectionAsync();
5299
5310
  onTabPress(item.key);
5300
5311
  },
5301
- activeOpacity: 0.7,
5312
+ rippleColor: "transparent",
5302
5313
  touchSoundDisabled: true,
5303
5314
  accessibilityRole: "tab",
5304
5315
  accessibilityState: { selected: active },
5305
- accessibilityLabel: item.label ?? item.key
5316
+ accessibilityLabel: item.label ?? item.key,
5317
+ style: styles44.tab
5306
5318
  },
5307
5319
  /* @__PURE__ */ React54__default.default.createElement(reactNative.View, null, iconNode, showBadge ? /* @__PURE__ */ React54__default.default.createElement(
5308
5320
  reactNative.View,
5309
5321
  {
5310
5322
  style: [
5311
- styles43.badge,
5323
+ styles44.badge,
5312
5324
  { backgroundColor: colors.destructive, borderColor: colors.card },
5313
- badgeCount === void 0 && styles43.badgeDot
5325
+ badgeCount === void 0 && styles44.badgeDot
5314
5326
  ]
5315
5327
  },
5316
- badgeCount !== void 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.badgeText, { color: colors.destructiveForeground }], allowFontScaling: false }, badgeCount > 99 ? "99+" : badgeCount) : null
5328
+ badgeCount !== void 0 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles44.badgeText, { color: colors.destructiveForeground }], allowFontScaling: false }, badgeCount > 99 ? "99+" : badgeCount) : null
5317
5329
  ) : null),
5318
- item.label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles43.label, { color: tint }], numberOfLines: 1, allowFontScaling: true }, item.label) : null
5330
+ item.label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles44.label, { color: tint }], numberOfLines: 1, allowFontScaling: true }, item.label) : null
5319
5331
  );
5320
5332
  })
5321
5333
  );
5322
5334
  }
5323
- var styles43 = reactNative.StyleSheet.create({
5335
+ var styles44 = reactNative.StyleSheet.create({
5324
5336
  container: {
5325
5337
  flexDirection: "row",
5326
5338
  borderTopWidth: reactNative.StyleSheet.hairlineWidth
@@ -5368,22 +5380,22 @@ var styles43 = reactNative.StyleSheet.create({
5368
5380
  var MAX_SCALE = 3;
5369
5381
  var DOUBLE_TAP_SCALE = 2.5;
5370
5382
  function ZoomableImage({ source, width, height, onZoomChange }) {
5371
- const scale2 = Animated12.useSharedValue(1);
5372
- const savedScale = Animated12.useSharedValue(1);
5373
- const translateX = Animated12.useSharedValue(0);
5374
- const translateY = Animated12.useSharedValue(0);
5375
- const savedX = Animated12.useSharedValue(0);
5376
- const savedY = Animated12.useSharedValue(0);
5383
+ const scale2 = Animated6.useSharedValue(1);
5384
+ const savedScale = Animated6.useSharedValue(1);
5385
+ const translateX = Animated6.useSharedValue(0);
5386
+ const translateY = Animated6.useSharedValue(0);
5387
+ const savedX = Animated6.useSharedValue(0);
5388
+ const savedY = Animated6.useSharedValue(0);
5377
5389
  const reportZoom = React54.useCallback((zoomed) => onZoomChange(zoomed), [onZoomChange]);
5378
5390
  const reset = () => {
5379
5391
  "worklet";
5380
- scale2.value = Animated12.withTiming(1);
5392
+ scale2.value = Animated6.withTiming(1);
5381
5393
  savedScale.value = 1;
5382
- translateX.value = Animated12.withTiming(0);
5383
- translateY.value = Animated12.withTiming(0);
5394
+ translateX.value = Animated6.withTiming(0);
5395
+ translateY.value = Animated6.withTiming(0);
5384
5396
  savedX.value = 0;
5385
5397
  savedY.value = 0;
5386
- Animated12.runOnJS(reportZoom)(false);
5398
+ Animated6.runOnJS(reportZoom)(false);
5387
5399
  };
5388
5400
  const pinch = reactNativeGestureHandler.Gesture.Pinch().onUpdate((e) => {
5389
5401
  scale2.value = Math.max(1, Math.min(savedScale.value * e.scale, MAX_SCALE));
@@ -5392,7 +5404,7 @@ function ZoomableImage({ source, width, height, onZoomChange }) {
5392
5404
  if (scale2.value <= 1) {
5393
5405
  reset();
5394
5406
  } else {
5395
- Animated12.runOnJS(reportZoom)(true);
5407
+ Animated6.runOnJS(reportZoom)(true);
5396
5408
  }
5397
5409
  });
5398
5410
  const pan = reactNativeGestureHandler.Gesture.Pan().onUpdate((e) => {
@@ -5407,20 +5419,20 @@ function ZoomableImage({ source, width, height, onZoomChange }) {
5407
5419
  if (scale2.value > 1) {
5408
5420
  reset();
5409
5421
  } else {
5410
- scale2.value = Animated12.withTiming(DOUBLE_TAP_SCALE);
5422
+ scale2.value = Animated6.withTiming(DOUBLE_TAP_SCALE);
5411
5423
  savedScale.value = DOUBLE_TAP_SCALE;
5412
- Animated12.runOnJS(reportZoom)(true);
5424
+ Animated6.runOnJS(reportZoom)(true);
5413
5425
  }
5414
5426
  });
5415
5427
  const composed = reactNativeGestureHandler.Gesture.Exclusive(doubleTap, reactNativeGestureHandler.Gesture.Simultaneous(pinch, pan));
5416
- const animatedStyle = Animated12.useAnimatedStyle(() => ({
5428
+ const animatedStyle = Animated6.useAnimatedStyle(() => ({
5417
5429
  transform: [
5418
5430
  { translateX: translateX.value },
5419
5431
  { translateY: translateY.value },
5420
5432
  { scale: scale2.value }
5421
5433
  ]
5422
5434
  }));
5423
- return /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: composed }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [{ width, height }, styles44.imageWrap], collapsable: false }, /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [{ width, height }, animatedStyle] }, /* @__PURE__ */ React54__default.default.createElement(reactNative.Image, { source, style: { width, height }, resizeMode: "contain" }))));
5435
+ return /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: composed }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [{ width, height }, styles45.imageWrap], collapsable: false }, /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: [{ width, height }, animatedStyle] }, /* @__PURE__ */ React54__default.default.createElement(expoImage.Image, { source, style: { width, height }, contentFit: "contain" }))));
5424
5436
  }
5425
5437
  function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5426
5438
  const window = reactNative.useWindowDimensions();
@@ -5439,25 +5451,25 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5439
5451
  });
5440
5452
  return () => cancelAnimationFrame(handle);
5441
5453
  }, [visible, initialIndex, width]);
5442
- const dragY = Animated12.useSharedValue(0);
5454
+ const dragY = Animated6.useSharedValue(0);
5443
5455
  const DISMISS_THRESHOLD = height * 0.18;
5444
5456
  const closeViewer = React54.useCallback(() => onClose(), [onClose]);
5445
5457
  const swipeDown = reactNativeGestureHandler.Gesture.Pan().enabled(pagingEnabled).activeOffsetY(12).failOffsetX([-16, 16]).onUpdate((e) => {
5446
5458
  dragY.value = Math.max(0, e.translationY);
5447
5459
  }).onEnd((e) => {
5448
5460
  if (e.translationY > DISMISS_THRESHOLD || e.velocityY > 800) {
5449
- Animated12.runOnJS(closeViewer)();
5461
+ Animated6.runOnJS(closeViewer)();
5450
5462
  } else {
5451
- dragY.value = Animated12.withTiming(0);
5463
+ dragY.value = Animated6.withTiming(0);
5452
5464
  }
5453
5465
  });
5454
5466
  React54__default.default.useEffect(() => {
5455
5467
  if (visible) dragY.value = 0;
5456
5468
  }, [visible, dragY]);
5457
- const dismissStyle = Animated12.useAnimatedStyle(() => ({
5469
+ const dismissStyle = Animated6.useAnimatedStyle(() => ({
5458
5470
  transform: [{ translateY: dragY.value }]
5459
5471
  }));
5460
- const backdropStyle = Animated12.useAnimatedStyle(() => ({
5472
+ const backdropStyle = Animated6.useAnimatedStyle(() => ({
5461
5473
  opacity: 1 - Math.min(dragY.value / (height * 0.5), 0.85)
5462
5474
  }));
5463
5475
  const onMomentumEnd = (e) => {
@@ -5468,7 +5480,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5468
5480
  scrollRef.current?.scrollTo({ x: page * width, animated: true });
5469
5481
  setIndex(page);
5470
5482
  };
5471
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.Modal, { visible, transparent: false, animationType: "fade", onRequestClose: onClose, statusBarTranslucent: true }, /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles44.root }, /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [styles44.backdrop, backdropStyle], pointerEvents: "none" }), /* @__PURE__ */ React54__default.default.createElement(Animated12__default.default.View, { style: [styles44.container, dismissStyle] }, /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: swipeDown }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles44.root, collapsable: false }, /* @__PURE__ */ React54__default.default.createElement(
5483
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.Modal, { visible, transparent: false, animationType: "fade", onRequestClose: onClose, statusBarTranslucent: true }, /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles45.root }, /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: [styles45.backdrop, backdropStyle], pointerEvents: "none" }), /* @__PURE__ */ React54__default.default.createElement(Animated6__default.default.View, { style: [styles45.container, dismissStyle] }, /* @__PURE__ */ React54__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: swipeDown }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles45.root, collapsable: false }, /* @__PURE__ */ React54__default.default.createElement(
5472
5484
  reactNative.ScrollView,
5473
5485
  {
5474
5486
  ref: scrollRef,
@@ -5489,7 +5501,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5489
5501
  onZoomChange: (zoomed) => setPagingEnabled(!zoomed)
5490
5502
  }
5491
5503
  ))
5492
- ))), /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles44.closeButtonWrapper, { top: insets.top + vs(8) }] }, /* @__PURE__ */ React54__default.default.createElement(
5504
+ ))), /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles45.closeButtonWrapper, { top: insets.top + vs(8) }] }, /* @__PURE__ */ React54__default.default.createElement(
5493
5505
  IconButton,
5494
5506
  {
5495
5507
  iconName: "x",
@@ -5498,9 +5510,9 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5498
5510
  style: { backgroundColor: "rgba(255,255,255,0.18)" },
5499
5511
  iconColor: "#fff",
5500
5512
  onPress: onClose,
5501
- accessibilityLabel: "Close"
5513
+ accessibilityLabel: "Cerrar"
5502
5514
  }
5503
- )), images.length > 1 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles44.dots, { bottom: insets.bottom + vs(16) }], pointerEvents: "box-none" }, /* @__PURE__ */ React54__default.default.createElement(
5515
+ )), images.length > 1 ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles45.dots, { bottom: insets.bottom + vs(16) }], pointerEvents: "box-none" }, /* @__PURE__ */ React54__default.default.createElement(
5504
5516
  PagerDots,
5505
5517
  {
5506
5518
  count: images.length,
@@ -5511,7 +5523,7 @@ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5511
5523
  }
5512
5524
  )) : null)));
5513
5525
  }
5514
- var styles44 = reactNative.StyleSheet.create({
5526
+ var styles45 = reactNative.StyleSheet.create({
5515
5527
  root: {
5516
5528
  flex: 1
5517
5529
  },
@@ -5549,7 +5561,7 @@ function SheetSelectChip({
5549
5561
  onPress();
5550
5562
  };
5551
5563
  const iconColor = selected ? colors.primaryForeground : colors.foreground;
5552
- const resolvedIcon = option.iconName ? renderIcon(option.iconName, ms(13), iconColor) : null;
5564
+ const resolvedIcon = option.iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: option.iconName, size: ms(13), color: iconColor }) : null;
5553
5565
  return /* @__PURE__ */ React54__default.default.createElement(
5554
5566
  PressableChip,
5555
5567
  {
@@ -5557,24 +5569,24 @@ function SheetSelectChip({
5557
5569
  rippleColor: "transparent",
5558
5570
  touchSoundDisabled: true,
5559
5571
  accessibilityRole: "button",
5560
- accessibilityLabel: option.disabled ? `${option.label}, unavailable` : option.label,
5572
+ accessibilityLabel: option.disabled ? `${option.label}, no disponible` : option.label,
5561
5573
  accessibilityState: { selected, disabled: option.disabled }
5562
5574
  },
5563
5575
  /* @__PURE__ */ React54__default.default.createElement(
5564
5576
  reactNativeEase.EaseView,
5565
5577
  {
5566
- style: [styles45.chip, option.disabled && styles45.chipDisabled],
5578
+ style: [styles46.chip, option.disabled && styles46.chipDisabled],
5567
5579
  animate: {
5568
5580
  backgroundColor: selected ? colors.primary : colors.surface,
5569
5581
  borderColor: selected ? colors.primary : colors.border
5570
5582
  },
5571
5583
  transition: COLOR_TRANSITION
5572
5584
  },
5573
- resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles45.chipIcon }, resolvedIcon) : null,
5585
+ resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles46.chipIcon }, resolvedIcon) : null,
5574
5586
  /* @__PURE__ */ React54__default.default.createElement(
5575
5587
  reactNative.Text,
5576
5588
  {
5577
- style: [styles45.chipLabel, { color: selected ? colors.primaryForeground : colors.foreground }],
5589
+ style: [styles46.chipLabel, { color: selected ? colors.primaryForeground : colors.foreground }],
5578
5590
  allowFontScaling: true
5579
5591
  },
5580
5592
  option.label
@@ -5617,17 +5629,17 @@ function SheetSelect({
5617
5629
  onPress: () => handlePress(opt.value)
5618
5630
  }
5619
5631
  ));
5620
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles45.container, style], accessibilityLabel }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles45.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, wrap ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles45.wrapContainer }, chips) : /* @__PURE__ */ React54__default.default.createElement(
5632
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles46.container, style], accessibilityLabel }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles46.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, wrap ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles46.wrapContainer }, chips) : /* @__PURE__ */ React54__default.default.createElement(
5621
5633
  reactNative.ScrollView,
5622
5634
  {
5623
5635
  horizontal: true,
5624
5636
  showsHorizontalScrollIndicator: false,
5625
- contentContainerStyle: styles45.scrollContent
5637
+ contentContainerStyle: styles46.scrollContent
5626
5638
  },
5627
5639
  chips
5628
- ), error ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles45.error, { color: colors.destructive }], allowFontScaling: true, accessibilityLiveRegion: "polite" }, error) : null);
5640
+ ), error ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles46.error, { color: colors.destructive }], allowFontScaling: true, accessibilityLiveRegion: "polite" }, error) : null);
5629
5641
  }
5630
- var styles45 = reactNative.StyleSheet.create({
5642
+ var styles46 = reactNative.StyleSheet.create({
5631
5643
  container: {
5632
5644
  gap: vs(8)
5633
5645
  },
@@ -5676,45 +5688,38 @@ function ImageUpload({
5676
5688
  value,
5677
5689
  onChange,
5678
5690
  loading = false,
5679
- placeholder = "Tap to add image",
5691
+ placeholder = "Toca para a\xF1adir imagen",
5680
5692
  showPlaceholderText = true,
5681
5693
  width,
5682
5694
  height = 200,
5683
5695
  borderRadius = RADIUS.lg,
5684
5696
  resizeMode = "cover",
5697
+ allowsEditing = true,
5685
5698
  disabled = false,
5686
5699
  style,
5687
- accessibilityLabel
5700
+ accessibilityLabel,
5701
+ onPickerStarting
5688
5702
  }) {
5689
5703
  const { colors } = useTheme();
5704
+ const [imageLoaded, setImageLoaded] = React54.useState(false);
5690
5705
  const handlePress = async () => {
5691
5706
  if (disabled || loading) return;
5692
5707
  impactLight();
5708
+ onPickerStarting?.();
5693
5709
  let picker;
5694
5710
  try {
5695
- const mod = await import('expo-image-picker/build/ExponentImagePicker');
5696
- picker = mod.default;
5711
+ picker = __require("expo-image-picker");
5697
5712
  } catch {
5698
- try {
5699
- picker = await import('expo-image-picker');
5700
- } catch {
5701
- if (__DEV__) console.warn("[ImageUpload] expo-image-picker not installed.");
5702
- return;
5703
- }
5704
- }
5705
- if (reactNative.Platform.OS !== "web") {
5706
- try {
5707
- const { status } = await picker.requestMediaLibraryPermissionsAsync();
5708
- if (status !== "granted") return;
5709
- } catch {
5710
- }
5713
+ if (__DEV__) console.warn("[ImageUpload] expo-image-picker not installed.");
5714
+ return;
5711
5715
  }
5712
5716
  const result = await picker.launchImageLibraryAsync({
5713
5717
  mediaTypes: ["images"],
5714
- allowsEditing: true,
5718
+ allowsEditing,
5715
5719
  quality: 0.8
5716
5720
  });
5717
5721
  if (!result.canceled && result.assets?.[0]) {
5722
+ setImageLoaded(false);
5718
5723
  onChange?.(result.assets[0].uri);
5719
5724
  }
5720
5725
  };
@@ -5725,7 +5730,7 @@ function ImageUpload({
5725
5730
  borderWidth: value ? 0 : 1,
5726
5731
  borderStyle: "dashed",
5727
5732
  borderColor: colors.border,
5728
- backgroundColor: value ? "transparent" : colors.surface,
5733
+ backgroundColor: value && imageLoaded ? "transparent" : colors.surface,
5729
5734
  overflow: "hidden"
5730
5735
  };
5731
5736
  return /* @__PURE__ */ React54__default.default.createElement(
@@ -5736,31 +5741,33 @@ function ImageUpload({
5736
5741
  rippleColor: "transparent",
5737
5742
  touchSoundDisabled: true,
5738
5743
  accessibilityRole: "button",
5739
- accessibilityLabel: accessibilityLabel ?? (value ? "Change image" : placeholder),
5744
+ accessibilityLabel: accessibilityLabel ?? (value ? "Cambiar imagen" : placeholder),
5740
5745
  accessibilityState: { disabled: disabled || loading },
5741
5746
  style: [containerStyle, style]
5742
5747
  },
5743
5748
  value ? /* @__PURE__ */ React54__default.default.createElement(
5744
- reactNative.Image,
5749
+ expoImage.Image,
5745
5750
  {
5746
5751
  source: { uri: value },
5747
5752
  style: [reactNative.StyleSheet.absoluteFillObject, { borderRadius }],
5748
- resizeMode
5753
+ contentFit: resizeMode === "stretch" ? "fill" : resizeMode,
5754
+ onLoad: () => setImageLoaded(true),
5755
+ onError: () => setImageLoaded(true)
5749
5756
  }
5750
- ) : /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles46.placeholder }, /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Feather, { name: "image", size: ms(28), color: colors.foregroundMuted }), showPlaceholderText ? /* @__PURE__ */ React54__default.default.createElement(
5757
+ ) : /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles47.placeholder }, /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Feather, { name: "image", size: ms(28), color: colors.foregroundMuted }), showPlaceholderText ? /* @__PURE__ */ React54__default.default.createElement(
5751
5758
  reactNative.Text,
5752
5759
  {
5753
- style: [styles46.placeholderText, { color: colors.foregroundMuted }],
5760
+ style: [styles47.placeholderText, { color: colors.foregroundMuted }],
5754
5761
  numberOfLines: 1,
5755
5762
  allowFontScaling: true
5756
5763
  },
5757
5764
  placeholder
5758
5765
  ) : null),
5759
- loading ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles46.loadingOverlay, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React54__default.default.createElement(Spinner, { size: "md" })) : null,
5760
- value && !loading ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles46.editBadge, pointerEvents: "none" }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles46.editBadgeInner, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Feather, { name: "edit-2", size: ms(12), color: "#fff" }))) : null
5766
+ loading ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles47.loadingOverlay, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React54__default.default.createElement(Spinner, { size: "md" })) : null,
5767
+ value && !loading ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles47.editBadge, pointerEvents: "none" }, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles47.editBadgeInner, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React54__default.default.createElement(vectorIcons.Feather, { name: "edit-2", size: ms(12), color: "#fff" }))) : null
5761
5768
  );
5762
5769
  }
5763
- var styles46 = reactNative.StyleSheet.create({
5770
+ var styles47 = reactNative.StyleSheet.create({
5764
5771
  placeholder: {
5765
5772
  flex: 1,
5766
5773
  alignItems: "center",
@@ -5792,442 +5799,73 @@ var styles46 = reactNative.StyleSheet.create({
5792
5799
  });
5793
5800
 
5794
5801
  // src/utils/curatedIcons.ts
5795
- var CURATED_ICONS = [
5796
- // ─── Food ────────────────────────────────────────────────────────────────────
5797
- {
5798
- name: "food",
5799
- label: "Food",
5800
- labelEs: "Comida",
5801
- categoryIcon: "coffee",
5802
- icons: [
5803
- // Bebidas
5804
- "beer-outline",
5805
- "wine-outline",
5806
- "cafe-outline",
5807
- "water-outline",
5808
- "coffee",
5809
- // Comida
5810
- "pizza-outline",
5811
- "fast-food-outline",
5812
- "fish-outline",
5813
- "ice-cream-outline",
5814
- "egg-outline",
5815
- "nutrition-outline",
5816
- // Servicio y operación
5817
- "restaurant-outline",
5818
- "server-outline",
5819
- "menu-outline",
5820
- "basket-outline",
5821
- "receipt-outline",
5822
- "pricetag-outline",
5823
- "pricetags-outline",
5824
- "reorder-four-outline",
5825
- "reorder-three-outline",
5826
- "cart-outline",
5827
- "cash-outline",
5828
- "wallet-outline",
5829
- "storefront-outline",
5830
- // Delivery / pedidos
5831
- "truck",
5832
- "package",
5833
- "shopping-bag",
5834
- "shopping-cart",
5835
- // Ubicación y reserva
5836
- "map-pin",
5837
- "home",
5838
- "calendar",
5839
- "clock",
5840
- // Experiencia
5841
- "star",
5842
- "heart",
5843
- "bookmark",
5844
- "thumbs-up",
5845
- "check",
5846
- "gift"
5847
- ]
5848
- },
5849
- // ─── Sports ──────────────────────────────────────────────────────────────────
5850
- {
5851
- name: "sports",
5852
- label: "Sports",
5853
- labelEs: "Deportes",
5854
- categoryIcon: "trophy-outline",
5855
- icons: [
5856
- // Deportes
5857
- "american-football-outline",
5858
- "baseball-outline",
5859
- "basketball-outline",
5860
- "bicycle-outline",
5861
- "football-outline",
5862
- "tennisball-outline",
5863
- "golf-outline",
5864
- "fitness-outline",
5865
- "car-sport-outline",
5866
- "game-controller-outline",
5867
- // Competición y logros
5868
- "trophy-outline",
5869
- "medal-outline",
5870
- "award",
5871
- "target",
5872
- "flag",
5873
- "crosshair",
5874
- // Outdoor
5875
- "compass-outline",
5876
- "map-outline",
5877
- "trail-sign-outline",
5878
- "bonfire-outline",
5879
- "snow-outline",
5880
- "flame-outline",
5881
- "sun",
5882
- "droplet",
5883
- "wind",
5884
- "map",
5885
- "map-pin",
5886
- "navigation",
5887
- "navigation-2",
5888
- // Rendimiento y métricas
5889
- "stats-chart-outline",
5890
- "trending-up-outline",
5891
- "trending-down-outline",
5892
- "bar-chart-outline",
5893
- "pie-chart-outline",
5894
- "analytics-outline",
5895
- "activity",
5896
- "zap",
5897
- "watch",
5898
- "trending-up",
5899
- "trending-down",
5900
- "bar-chart-2",
5901
- "clock",
5902
- "calendar"
5903
- ]
5904
- },
5905
- // ─── Business ────────────────────────────────────────────────────────────────
5906
- {
5907
- name: "business",
5908
- label: "Business",
5909
- labelEs: "Negocios",
5910
- categoryIcon: "briefcase",
5911
- icons: [
5912
- // Empresa
5913
- "briefcase",
5914
- "users",
5915
- "user",
5916
- "user-plus",
5917
- "user-check",
5918
- "user-x",
5919
- "briefcase-outline",
5920
- "business-outline",
5921
- "id-card-outline",
5922
- // Comercio y operación
5923
- "shopping-cart",
5924
- "shopping-bag",
5925
- "credit-card",
5926
- "dollar-sign",
5927
- "percent",
5928
- "tag",
5929
- "gift",
5930
- "cart-outline",
5931
- "cash-outline",
5932
- "wallet-outline",
5933
- "storefront-outline",
5934
- "pricetag-outline",
5935
- "pricetags-outline",
5936
- "receipt-outline",
5937
- "card-outline",
5938
- // Logística
5939
- "truck",
5940
- "package",
5941
- // Documentos
5942
- "file",
5943
- "file-text",
5944
- "file-plus",
5945
- "folder",
5946
- "paperclip",
5947
- "document-outline",
5948
- "document-text-outline",
5949
- "documents-outline",
5950
- "folder-outline",
5951
- // Comunicación de negocio
5952
- "mail",
5953
- "phone",
5954
- "phone-call",
5955
- "send",
5956
- "message-square",
5957
- "mail-outline",
5958
- // Análisis
5959
- "bar-chart",
5960
- "bar-chart-2",
5961
- "pie-chart",
5962
- "trending-up",
5963
- "trending-down",
5964
- "activity",
5965
- "globe"
5966
- ]
5967
- },
5968
- // ─── Objects ─────────────────────────────────────────────────────────────────
5969
- {
5970
- name: "objects",
5971
- label: "Objects",
5972
- labelEs: "Objetos",
5973
- categoryIcon: "package",
5974
- icons: [
5975
- // Archivos y carpetas
5976
- "file",
5977
- "file-text",
5978
- "file-plus",
5979
- "file-minus",
5980
- "folder",
5981
- "folder-plus",
5982
- "folder-minus",
5983
- "archive",
5984
- "save",
5985
- "paperclip",
5986
- "document-outline",
5987
- "document-text-outline",
5988
- "documents-outline",
5989
- "folder-outline",
5990
- "folder-open-outline",
5991
- "file-tray-outline",
5992
- "file-tray-full-outline",
5993
- "file-tray-stacked-outline",
5994
- "archive-outline",
5995
- "save-outline",
5996
- // Seguridad
5997
- "lock",
5998
- "unlock",
5999
- "key",
6000
- "shield",
6001
- "shield-off",
6002
- "lock-closed-outline",
6003
- "lock-open-outline",
6004
- "key-outline",
6005
- "shield-outline",
6006
- "shield-checkmark-outline",
6007
- // Dispositivos
6008
- "monitor",
6009
- "tablet",
6010
- "smartphone",
6011
- "tv",
6012
- "server",
6013
- "database",
6014
- "hard-drive",
6015
- "cpu",
6016
- "radio",
6017
- "laptop-outline",
6018
- "phone-portrait-outline",
6019
- "phone-landscape-outline",
6020
- "tablet-landscape-outline",
6021
- "tablet-portrait-outline",
6022
- "tv-outline",
6023
- "server-outline",
6024
- "hardware-chip-outline",
6025
- "watch-outline"
6026
- ]
6027
- },
6028
- // ─── Status ──────────────────────────────────────────────────────────────────
6029
- {
6030
- name: "status",
6031
- label: "Status",
6032
- labelEs: "Estado",
6033
- categoryIcon: "alert-circle",
6034
- icons: [
6035
- // Alertas
6036
- "alert-circle",
6037
- "alert-triangle",
6038
- "alert-octagon",
6039
- "info",
6040
- "help-circle",
6041
- "alert-circle-outline",
6042
- "alert-outline",
6043
- "information-circle-outline",
6044
- "help-circle-outline",
6045
- // Notificaciones
6046
- "bell",
6047
- "bell-off",
6048
- "notifications-outline",
6049
- "notifications-off-outline",
6050
- "notifications-circle-outline",
6051
- // Visibilidad
6052
- "eye",
6053
- "eye-off",
6054
- "eye-outline",
6055
- "eye-off-outline",
6056
- // Indicadores
6057
- "flag",
6058
- "zap",
6059
- "zap-off",
6060
- "loader",
6061
- "activity",
6062
- "flash-outline",
6063
- "bulb-outline",
6064
- // Éxito / error / advertencia
6065
- "check",
6066
- "check-circle",
6067
- "x",
6068
- "x-circle",
6069
- "x-octagon",
6070
- "slash",
6071
- "plus-circle",
6072
- "minus-circle",
6073
- "checkmark-circle-outline",
6074
- "checkmark-done-circle-outline",
6075
- "close-circle-outline",
6076
- "add-circle-outline",
6077
- "remove-circle-outline",
6078
- // Estados de proceso
6079
- "play-circle",
6080
- "pause-circle",
6081
- "stop-circle",
6082
- "play-circle-outline",
6083
- "pause-circle-outline",
6084
- "stop-circle-outline"
6085
- ]
6086
- },
6087
- // ─── Actions ─────────────────────────────────────────────────────────────────
5802
+ var CATEGORIES = [
6088
5803
  {
6089
- name: "actions",
5804
+ name: "acciones",
6090
5805
  label: "Actions",
6091
5806
  labelEs: "Acciones",
6092
- categoryIcon: "edit-3",
5807
+ categoryIcon: "zap",
6093
5808
  icons: [
6094
- // Crear / añadir
6095
5809
  "plus",
6096
- "plus-circle",
6097
- "plus-square",
6098
- "add-outline",
6099
- "add-circle-outline",
6100
- // Eliminar / quitar
6101
- "minus",
6102
- "minus-circle",
6103
- "minus-square",
6104
- "trash",
6105
- "trash-2",
6106
5810
  "x",
6107
- "x-circle",
6108
- "x-square",
6109
- "x-octagon",
6110
- "slash",
6111
- "trash-outline",
6112
- "trash-bin-outline",
6113
- "remove-outline",
6114
- "remove-circle-outline",
6115
- "close-circle-outline",
6116
- "backspace-outline",
6117
- "cut-outline",
6118
- // Confirmar
6119
5811
  "check",
6120
- "check-circle",
6121
- "check-square",
6122
- "checkmark-circle-outline",
6123
- // Editar
6124
- "edit",
6125
5812
  "edit-2",
6126
- "edit-3",
5813
+ "search",
5814
+ "settings",
5815
+ "filter",
5816
+ "trash-2",
6127
5817
  "copy",
6128
- "clipboard",
6129
- "scissors",
6130
- "create-outline",
6131
- "pencil-outline",
6132
- "duplicate-outline",
6133
- "copy-outline",
6134
- "clipboard-outline",
6135
- // Mover datos
5818
+ "save",
5819
+ "share-2",
6136
5820
  "download",
6137
- "download-cloud",
6138
5821
  "upload",
6139
- "upload-cloud",
6140
- "download-outline",
6141
- "cloud-download-outline",
6142
- "cloud-upload-outline"
5822
+ "refresh-cw",
5823
+ "lock",
5824
+ "bookmark",
5825
+ "heart",
5826
+ "star",
5827
+ "flag",
5828
+ "link-2"
6143
5829
  ]
6144
5830
  },
6145
- // ─── Communication ───────────────────────────────────────────────────────────
6146
5831
  {
6147
- name: "communication",
5832
+ name: "comunicacion",
6148
5833
  label: "Communication",
6149
5834
  labelEs: "Comunicaci\xF3n",
6150
- categoryIcon: "message-circle",
5835
+ categoryIcon: "mail",
6151
5836
  icons: [
6152
- // Mensajería
5837
+ "mail",
6153
5838
  "message-circle",
6154
5839
  "message-square",
6155
- "send",
6156
- "mail",
6157
- "inbox",
6158
- "at-sign",
6159
- "mail-outline",
6160
- "mail-open-outline",
6161
- "mail-unread-outline",
6162
- "chatbubble-outline",
6163
- "chatbubble-ellipses-outline",
6164
- "chatbubbles-outline",
6165
- "send-outline",
6166
- "attach-outline",
6167
- "at-outline",
6168
- "at-circle-outline",
6169
- // Llamadas
6170
5840
  "phone",
6171
5841
  "phone-call",
5842
+ "phone-forwarded",
6172
5843
  "phone-incoming",
6173
- "phone-outgoing",
6174
5844
  "phone-missed",
6175
5845
  "phone-off",
6176
- "phone-forwarded",
6177
- "voicemail",
6178
- "call-outline",
6179
- "phone-portrait-outline",
6180
- "phone-landscape-outline",
6181
- // Personas
6182
- "user",
6183
- "user-plus",
6184
- "user-minus",
6185
- "user-check",
6186
- "user-x",
6187
- "users",
6188
- "person-outline",
6189
- "person-circle-outline",
6190
- "person-add-outline",
6191
- "person-remove-outline",
6192
- "people-outline",
6193
- "people-circle-outline",
6194
- // Reacciones
6195
- "smile",
6196
- "frown",
6197
- "meh",
6198
- "heart",
6199
- "thumbs-up",
6200
- "thumbs-down",
6201
- "happy-outline",
6202
- "sad-outline",
6203
- "heart-outline",
6204
- "thumbs-up-outline",
6205
- "thumbs-down-outline"
5846
+ "phone-outgoing",
5847
+ "send",
5848
+ "at-sign",
5849
+ "paperclip",
5850
+ "inbox",
5851
+ "volume",
5852
+ "volume-1",
5853
+ "volume-2",
5854
+ "volume-x",
5855
+ "mic",
5856
+ "mic-off"
6206
5857
  ]
6207
5858
  },
6208
- // ─── Navigation ──────────────────────────────────────────────────────────────
6209
5859
  {
6210
- name: "navigation",
5860
+ name: "navegacion",
6211
5861
  label: "Navigation",
6212
5862
  labelEs: "Navegaci\xF3n",
6213
- categoryIcon: "compass",
5863
+ categoryIcon: "map-pin",
6214
5864
  icons: [
6215
- // Flechas cardinales
6216
5865
  "arrow-up",
6217
5866
  "arrow-down",
6218
5867
  "arrow-left",
6219
5868
  "arrow-right",
6220
- "arrow-up-left",
6221
- "arrow-up-right",
6222
- "arrow-down-left",
6223
- "arrow-down-right",
6224
- "arrow-up-outline",
6225
- "arrow-down-outline",
6226
- "arrow-back-outline",
6227
- "arrow-forward-outline",
6228
- "arrow-undo-outline",
6229
- "arrow-redo-outline",
6230
- // Chevrones
6231
5869
  "chevron-up",
6232
5870
  "chevron-down",
6233
5871
  "chevron-left",
@@ -6236,346 +5874,181 @@ var CURATED_ICONS = [
6236
5874
  "chevrons-down",
6237
5875
  "chevrons-left",
6238
5876
  "chevrons-right",
6239
- "chevron-up-outline",
6240
- "chevron-down-outline",
6241
- "chevron-back-outline",
6242
- "chevron-forward-outline",
6243
- "chevron-collapse-outline",
6244
- "chevron-expand-outline",
6245
- // Esquinas
5877
+ "arrow-up-circle",
5878
+ "arrow-down-circle",
5879
+ "arrow-left-circle",
5880
+ "arrow-right-circle",
6246
5881
  "corner-up-left",
6247
5882
  "corner-up-right",
6248
5883
  "corner-down-left",
6249
- "corner-down-right",
6250
- "corner-left-up",
6251
- "corner-left-down",
6252
- "corner-right-up",
6253
- "corner-right-down",
6254
- // Giro / refrescar
6255
- "refresh-cw",
6256
- "refresh-ccw",
6257
- "rotate-cw",
6258
- "rotate-ccw",
6259
- "refresh-outline",
6260
- "reload-outline",
6261
- // Orientación y mapa
6262
- "navigation",
6263
- "navigation-2",
6264
- "compass",
6265
- "map",
5884
+ "corner-down-right"
5885
+ ]
5886
+ },
5887
+ {
5888
+ name: "comida",
5889
+ label: "Food",
5890
+ labelEs: "Comida",
5891
+ categoryIcon: "coffee",
5892
+ icons: [
5893
+ "coffee",
5894
+ "shopping-bag",
5895
+ "shopping-cart",
5896
+ "package",
5897
+ "box",
5898
+ "tag",
5899
+ "truck",
5900
+ "gift",
5901
+ "award",
5902
+ "star",
5903
+ "heart",
5904
+ "zap",
5905
+ "sun",
5906
+ "moon",
5907
+ "cloud",
5908
+ "droplet",
5909
+ "thermometer",
5910
+ "wind",
6266
5911
  "map-pin",
5912
+ "home"
5913
+ ]
5914
+ },
5915
+ {
5916
+ name: "negocios",
5917
+ label: "Business",
5918
+ labelEs: "Negocios",
5919
+ categoryIcon: "briefcase",
5920
+ icons: [
5921
+ "briefcase",
5922
+ "dollar-sign",
5923
+ "credit-card",
5924
+ "bar-chart",
5925
+ "bar-chart-2",
5926
+ "pie-chart",
5927
+ "trending-up",
5928
+ "trending-down",
5929
+ "activity",
6267
5930
  "target",
6268
- "crosshair",
6269
- "home",
6270
- "anchor",
6271
- "compass-outline",
6272
- "map-outline",
6273
- "location-outline",
6274
- "navigate-outline",
6275
- "pin-outline",
6276
- "home-outline"
5931
+ "hash",
5932
+ "percent",
5933
+ "file-text",
5934
+ "folder",
5935
+ "clipboard",
5936
+ "calendar",
5937
+ "clock",
5938
+ "database",
5939
+ "archive",
5940
+ "terminal"
5941
+ ]
5942
+ },
5943
+ {
5944
+ name: "perfil",
5945
+ label: "Profile",
5946
+ labelEs: "Perfil",
5947
+ categoryIcon: "user",
5948
+ icons: [
5949
+ "user",
5950
+ "users",
5951
+ "user-check",
5952
+ "user-x",
5953
+ "user-plus",
5954
+ "user-minus",
5955
+ "key",
5956
+ "shield",
5957
+ "shield-off",
5958
+ "lock",
5959
+ "unlock",
5960
+ "log-in",
5961
+ "log-out",
5962
+ "eye",
5963
+ "eye-off",
5964
+ "bell",
5965
+ "bell-off",
5966
+ "settings",
5967
+ "tool",
5968
+ "sliders"
6277
5969
  ]
6278
5970
  },
6279
- // ─── Media ───────────────────────────────────────────────────────────────────
6280
5971
  {
6281
- name: "media",
5972
+ name: "multimedia",
6282
5973
  label: "Media",
6283
- labelEs: "Medios",
6284
- categoryIcon: "image",
5974
+ labelEs: "Multimedia",
5975
+ categoryIcon: "camera",
6285
5976
  icons: [
6286
- // Visual
6287
- "image",
6288
- "film",
6289
- "video",
6290
- "video-off",
6291
5977
  "camera",
6292
5978
  "camera-off",
6293
- "image-outline",
6294
- "images-outline",
6295
- "film-outline",
6296
- "videocam-outline",
6297
- "videocam-off-outline",
6298
- "camera-outline",
6299
- "camera-reverse-outline",
6300
- // Reproducción
6301
- "play",
6302
- "play-circle",
6303
- "pause",
6304
- "pause-circle",
6305
- "square",
6306
- "stop-circle",
6307
- "fast-forward",
6308
- "rewind",
6309
- "skip-forward",
6310
- "skip-back",
6311
- "repeat",
6312
- "shuffle",
6313
- "play-outline",
6314
- "pause-outline",
6315
- "play-circle-outline",
6316
- "pause-circle-outline",
6317
- "stop-circle-outline",
6318
- "play-back-outline",
6319
- "play-forward-outline",
6320
- "play-skip-back-outline",
6321
- "play-skip-forward-outline",
6322
- "repeat-outline",
6323
- "shuffle-outline",
6324
- // Audio
5979
+ "video",
5980
+ "video-off",
5981
+ "film",
6325
5982
  "music",
5983
+ "music-off",
6326
5984
  "headphones",
6327
5985
  "speaker",
6328
- "volume",
6329
- "volume-1",
6330
- "volume-2",
6331
- "volume-x",
6332
- "mic",
6333
- "mic-off",
6334
- "mic-outline",
6335
- "mic-off-outline",
6336
- "mic-circle-outline",
6337
- "musical-note-outline",
6338
- "musical-notes-outline",
6339
- "volume-high-outline",
6340
- "volume-low-outline",
6341
- "volume-medium-outline",
6342
- "volume-mute-outline",
6343
- "volume-off-outline"
5986
+ "radio",
5987
+ "image",
5988
+ "images",
5989
+ "play",
5990
+ "pause",
5991
+ "stop",
5992
+ "skip-back",
5993
+ "skip-forward",
5994
+ "monitor",
5995
+ "smart-phone",
5996
+ "tablet"
6344
5997
  ]
6345
5998
  },
6346
- // ─── Layout ──────────────────────────────────────────────────────────────────
6347
5999
  {
6348
- name: "layout",
6349
- label: "Layout",
6350
- labelEs: "Dise\xF1o",
6351
- categoryIcon: "grid",
6000
+ name: "texto",
6001
+ label: "Text",
6002
+ labelEs: "Texto",
6003
+ categoryIcon: "type",
6352
6004
  icons: [
6353
- // Estructura
6354
- "grid",
6355
- "columns",
6356
- "sidebar",
6357
- "layout",
6358
- "list",
6359
- "menu",
6360
- "table",
6361
- "trello",
6362
- "grid-outline",
6363
- "list-outline",
6364
- "menu-outline",
6365
- "layers-outline",
6366
- // Alineación
6005
+ "type",
6006
+ "bold",
6007
+ "italic",
6008
+ "underline",
6367
6009
  "align-left",
6368
6010
  "align-center",
6369
6011
  "align-right",
6370
6012
  "align-justify",
6371
- // Tipografía
6372
- "bold",
6373
- "italic",
6374
- "underline",
6375
- "type",
6376
- "hash",
6377
- // Formas
6013
+ "list",
6014
+ "columns",
6015
+ "sidebar",
6016
+ "minimize-2",
6017
+ "maximize-2",
6018
+ "edit-3",
6019
+ "feather",
6378
6020
  "circle",
6379
6021
  "square",
6380
- "triangle",
6381
- "hexagon",
6382
- "octagon",
6383
- "square-outline",
6384
- "triangle-outline",
6385
- "diamond-outline",
6386
- "shapes-outline",
6387
- // Herramientas de diseño
6388
- "pen-tool",
6389
- "crop",
6390
- "layers",
6391
- "filter",
6392
- "sliders",
6393
- "aperture",
6394
- "crop-outline",
6395
- "filter-outline",
6396
- "color-fill-outline",
6397
- "color-filter-outline",
6398
- "color-palette-outline",
6399
- "color-wand-outline",
6400
- "brush-outline",
6401
- // Edición
6402
- "edit",
6403
- "edit-2",
6404
- "edit-3",
6405
- "copy",
6406
- "trash",
6407
- "move",
6408
- "create-outline",
6409
- "pencil-outline",
6410
- "move-outline",
6411
- "resize-outline",
6412
- "duplicate-outline",
6413
- // Navegación UI
6414
- "more-horizontal",
6415
- "more-vertical",
6416
- "maximize",
6417
- "minimize",
6418
- "zoom-in",
6419
- "zoom-out",
6420
- "eye",
6421
- "eye-off",
6422
- "eye-outline",
6423
- "eye-off-outline",
6424
- "ellipsis-horizontal-circle-outline",
6425
- "ellipsis-vertical-circle-outline"
6426
- ]
6427
- },
6428
- // ─── Nature ──────────────────────────────────────────────────────────────────
6429
- {
6430
- name: "nature",
6431
- label: "Nature",
6432
- labelEs: "Naturaleza",
6433
- categoryIcon: "sunny-outline",
6434
- icons: [
6435
- // Sol, luna y estrellas
6436
- "sunny-outline",
6437
- "moon-outline",
6438
- "star-outline",
6439
- "star-half-outline",
6440
- "partly-sunny-outline",
6441
- "sun",
6442
- "moon",
6443
- "sunrise",
6444
- "sunset",
6445
- // Clima
6446
- "rainy-outline",
6447
- "thunderstorm-outline",
6448
- "snow-outline",
6449
- "cloudy-outline",
6450
- "cloudy-night-outline",
6451
- "cloud-outline",
6452
- "cloud-done-outline",
6453
- "cloud-download-outline",
6454
- "cloud-upload-outline",
6455
- "cloud-offline-outline",
6456
- "cloud-circle-outline",
6457
- "cloud",
6458
- "cloud-drizzle",
6459
- "cloud-lightning",
6460
- "cloud-rain",
6461
- "cloud-snow",
6462
- "cloud-off",
6463
- "umbrella-outline",
6464
- "thermometer-outline",
6465
- "droplet",
6466
- "wind",
6467
- // Agua y fuego
6468
- "water-outline",
6469
- "flame-outline",
6470
- "bonfire-outline",
6471
- "eyedrop-outline",
6472
- // Flora y fauna
6473
- "leaf-outline",
6474
- "flower-outline",
6475
- "bug-outline",
6476
- "fish-outline",
6477
- "paw-outline",
6478
- // Outdoor
6479
- "binoculars-outline",
6480
- "telescope-outline",
6481
- "compass-outline",
6482
- "map-outline",
6483
- "location-outline",
6484
- "flag-outline",
6485
- "trail-sign-outline",
6486
- "earth-outline",
6487
- "globe-outline",
6488
- "planet-outline",
6489
- "compass",
6490
- "map",
6491
- "map-pin",
6492
- "flag",
6493
- "navigation",
6494
- "navigation-2",
6495
- "target",
6496
- "crosshair",
6497
- "life-buoy"
6498
- ]
6499
- },
6500
- // ─── Brands ──────────────────────────────────────────────────────────────────
6501
- {
6502
- name: "brands",
6503
- label: "Brands",
6504
- labelEs: "Marcas",
6505
- categoryIcon: "globe",
6506
- icons: [
6507
- // Feather brand icons — outlined, consistent with the rest of the library
6508
- "github",
6509
- "gitlab",
6510
- "codepen",
6511
- "codesandbox",
6512
- "twitter",
6513
- "facebook",
6514
- "instagram",
6515
- "linkedin",
6516
- "youtube",
6517
- "dribbble",
6518
- "twitch",
6519
- "slack",
6520
- "figma",
6521
- "framer",
6522
- "chrome",
6523
- "rss",
6524
- // Filled / flat brand logos (FA5 brands) — kept in a second
6525
- // visual tier. Rendered as the brand's official silhouette.
6526
- // Visually consistent (all flat single-color) but heavier than the
6527
- // Feather outlined set above. Use these only when an outlined Feather
6528
- // version of the brand doesn't exist.
6529
- "reddit",
6530
- "tiktok",
6531
- "pinterest",
6532
- "whatsapp",
6533
- "discord",
6534
- "snapchat",
6535
- "telegram",
6536
- "viber",
6537
- "line",
6538
- "vimeo",
6539
- "tumblr",
6540
- "behance",
6541
- "medium",
6542
- "soundcloud",
6543
- "google",
6544
- "apple",
6545
- "android",
6546
- "windows",
6547
- "linux",
6548
- "amazon",
6549
- "paypal",
6550
- "stripe",
6551
- "shopify",
6552
- "dropbox",
6553
- "spotify",
6554
- "steam",
6555
- "atlassian",
6556
- "jira",
6557
- "confluence",
6558
- "bitbucket",
6559
- "jenkins",
6560
- "docker",
6561
- "aws",
6562
- "node",
6563
- "react",
6564
- "angular",
6565
- "wordpress",
6566
- "drupal",
6567
- "joomla",
6568
- "squarespace",
6569
- "wix",
6570
- "magento",
6571
- "terminal",
6572
- "pen-tool"
6022
+ "plus-circle",
6023
+ "minus-circle",
6024
+ "x-circle"
6573
6025
  ]
6574
6026
  }
6575
6027
  ];
6576
- var ALL_CURATED_ICONS = [
6577
- ...new Set(CURATED_ICONS.flatMap((c) => c.icons))
6578
- ];
6028
+ var _allIcons = null;
6029
+ var _categorized = null;
6030
+ function getAllCuratedIcons() {
6031
+ if (!_allIcons) {
6032
+ const seen = /* @__PURE__ */ new Set();
6033
+ const result = [];
6034
+ for (const cat of CATEGORIES) {
6035
+ for (const name of cat.icons) {
6036
+ if (!seen.has(name)) {
6037
+ seen.add(name);
6038
+ result.push(name);
6039
+ }
6040
+ }
6041
+ }
6042
+ _allIcons = result;
6043
+ }
6044
+ return _allIcons;
6045
+ }
6046
+ function getCuratedCategories() {
6047
+ if (!_categorized) {
6048
+ _categorized = CATEGORIES.map((cat) => ({ ...cat, icons: [...cat.icons] }));
6049
+ }
6050
+ return _categorized;
6051
+ }
6579
6052
 
6580
6053
  // src/components/IconPicker/IconPicker.tsx
6581
6054
  var NUM_COLUMNS = 6;
@@ -6599,9 +6072,9 @@ function IconCell({ name, selected, size, onPress }) {
6599
6072
  accessibilityRole: "button",
6600
6073
  accessibilityState: { selected },
6601
6074
  accessibilityLabel: name,
6602
- style: [styles47.cell, { width: size, height: size, backgroundColor: bg }]
6075
+ style: [styles48.cell, { width: size, height: size, backgroundColor: bg }]
6603
6076
  },
6604
- renderIcon(name, ms(20), iconColor)
6077
+ /* @__PURE__ */ React54__default.default.createElement(Icon, { name, size: ms(20), color: iconColor })
6605
6078
  );
6606
6079
  }
6607
6080
  var IconCellMemo = React54__default.default.memo(IconCell);
@@ -6625,10 +6098,11 @@ function IconPicker({
6625
6098
  const [ready, setReady] = React54.useState(false);
6626
6099
  const sheetName = React54.useId();
6627
6100
  const activeIcons = React54.useMemo(() => {
6101
+ const allIcons = getAllCuratedIcons();
6628
6102
  if (activeCategory) {
6629
- return CURATED_ICONS.find((c) => c.name === activeCategory)?.icons ?? ALL_CURATED_ICONS;
6103
+ return getCuratedCategories().find((c) => c.name === activeCategory)?.icons ?? allIcons;
6630
6104
  }
6631
- return ALL_CURATED_ICONS;
6105
+ return allIcons;
6632
6106
  }, [activeCategory]);
6633
6107
  const gapPx = s(gap);
6634
6108
  const cellSize = containerWidth > 0 ? Math.floor((containerWidth - gapPx * (numColumns - 1)) / numColumns) : 0;
@@ -6660,8 +6134,8 @@ function IconPicker({
6660
6134
  (props) => /* @__PURE__ */ React54__default.default.createElement(bottomSheet.BottomSheetBackdrop, { ...props, disappearsOnIndex: -1, appearsOnIndex: 0, pressBehavior: "close" }),
6661
6135
  []
6662
6136
  );
6663
- const selectedIcon = value ? renderIcon(value, ms(28), colors.foreground) : null;
6664
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles47.triggerContainer, style] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles47.triggerLabel, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React54__default.default.createElement(
6137
+ const selectedIcon = value ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: value, size: ms(28), color: colors.foreground }) : null;
6138
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles48.triggerContainer, style] }, label ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles48.triggerLabel, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React54__default.default.createElement(
6665
6139
  reactNative.TouchableOpacity,
6666
6140
  {
6667
6141
  onPress: handleOpen,
@@ -6672,26 +6146,26 @@ function IconPicker({
6672
6146
  accessibilityLabel: label ?? "Seleccionar icono",
6673
6147
  accessibilityState: { disabled },
6674
6148
  style: [
6675
- styles47.trigger,
6149
+ styles48.trigger,
6676
6150
  {
6677
6151
  backgroundColor: disabled ? colors.surface : colors.background,
6678
6152
  width: TRIGGER_SIZE,
6679
6153
  height: TRIGGER_SIZE,
6680
6154
  borderColor: error ? colors.destructive : value ? colors.primary : colors.border
6681
6155
  },
6682
- disabled && styles47.triggerDisabled
6156
+ disabled && styles48.triggerDisabled
6683
6157
  ]
6684
6158
  },
6685
- selectedIcon ?? renderIcon("plus", ms(24), colors.foregroundMuted)
6159
+ selectedIcon ?? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "plus", size: ms(24), color: colors.foregroundMuted })
6686
6160
  ), error ? /* @__PURE__ */ React54__default.default.createElement(
6687
6161
  reactNative.Text,
6688
6162
  {
6689
- style: [styles47.helperText, { color: colors.destructive }],
6163
+ style: [styles48.helperText, { color: colors.destructive }],
6690
6164
  allowFontScaling: true,
6691
6165
  accessibilityLiveRegion: "polite"
6692
6166
  },
6693
6167
  error
6694
- ) : null, !error && hint ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles47.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null, /* @__PURE__ */ React54__default.default.createElement(
6168
+ ) : null, !error && hint ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles48.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null, /* @__PURE__ */ React54__default.default.createElement(
6695
6169
  bottomSheet.BottomSheetModal,
6696
6170
  {
6697
6171
  ref: sheetRef,
@@ -6700,8 +6174,8 @@ function IconPicker({
6700
6174
  enableDynamicSizing: true,
6701
6175
  maxDynamicContentSize: SCREEN_HEIGHT * 0.7,
6702
6176
  backdropComponent: renderBackdrop,
6703
- backgroundStyle: { ...styles47.sheetBackground, backgroundColor: colors.card },
6704
- handleIndicatorStyle: { ...styles47.handle, backgroundColor: colors.border },
6177
+ backgroundStyle: { ...styles48.sheetBackground, backgroundColor: colors.card },
6178
+ handleIndicatorStyle: { ...styles48.handle, backgroundColor: colors.border },
6705
6179
  enablePanDownToClose: true,
6706
6180
  topInset: insets.top,
6707
6181
  android_keyboardInputMode: "adjustPan"
@@ -6709,26 +6183,26 @@ function IconPicker({
6709
6183
  /* @__PURE__ */ React54__default.default.createElement(
6710
6184
  bottomSheet.BottomSheetScrollView,
6711
6185
  {
6712
- contentContainerStyle: styles47.sheetContent,
6186
+ contentContainerStyle: styles48.sheetContent,
6713
6187
  showsVerticalScrollIndicator: true
6714
6188
  },
6715
6189
  /* @__PURE__ */ React54__default.default.createElement(
6716
6190
  reactNative.View,
6717
6191
  {
6718
- style: styles47.gridContainer,
6192
+ style: styles48.gridContainer,
6719
6193
  onLayout: (e) => {
6720
6194
  setContainerWidth(e.nativeEvent.layout.width);
6721
6195
  setReady(true);
6722
6196
  }
6723
6197
  },
6724
- !ready ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles47.loader }, /* @__PURE__ */ React54__default.default.createElement(Spinner, { size: "md", color: colors.primary, label: "Cargando iconos..." })) : /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles47.sectionLabel, { color: colors.foregroundSubtle }], allowFontScaling: true }, "Categor\xEDas"), /* @__PURE__ */ React54__default.default.createElement(
6198
+ !ready ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles48.loader }, /* @__PURE__ */ React54__default.default.createElement(Spinner, { size: "md", color: colors.primary, label: "Cargando iconos..." })) : /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles48.sectionLabel, { color: colors.foregroundSubtle }], allowFontScaling: true }, "Categor\xEDas"), /* @__PURE__ */ React54__default.default.createElement(
6725
6199
  reactNativeGestureHandler.ScrollView,
6726
6200
  {
6727
6201
  ref: catScrollRef,
6728
6202
  horizontal: true,
6729
6203
  showsHorizontalScrollIndicator: false,
6730
- contentContainerStyle: styles47.categoryStrip,
6731
- style: styles47.categoryScroll
6204
+ contentContainerStyle: styles48.categoryStrip,
6205
+ style: styles48.categoryScroll
6732
6206
  },
6733
6207
  /* @__PURE__ */ React54__default.default.createElement(
6734
6208
  reactNative.TouchableOpacity,
@@ -6737,30 +6211,30 @@ function IconPicker({
6737
6211
  activeOpacity: 0.7,
6738
6212
  touchSoundDisabled: true,
6739
6213
  accessibilityRole: "button",
6740
- accessibilityLabel: "Todos",
6214
+ accessibilityLabel: "Todas",
6741
6215
  accessibilityState: { selected: activeCategory === null },
6742
6216
  style: [
6743
- styles47.categoryChip,
6217
+ styles48.categoryChip,
6744
6218
  {
6745
6219
  backgroundColor: activeCategory === null ? colors.primary : colors.surface,
6746
6220
  borderColor: activeCategory === null ? colors.primary : colors.border
6747
6221
  }
6748
6222
  ]
6749
6223
  },
6750
- /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles47.categoryChipInner }, renderIcon("grid", ms(14), activeCategory === null ? colors.primaryForeground : colors.foregroundSubtle), /* @__PURE__ */ React54__default.default.createElement(
6224
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles48.categoryChipInner }, /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "grid", size: ms(14), color: activeCategory === null ? colors.primaryForeground : colors.foregroundSubtle }), /* @__PURE__ */ React54__default.default.createElement(
6751
6225
  reactNative.Text,
6752
6226
  {
6753
6227
  style: [
6754
- styles47.categoryChipText,
6228
+ styles48.categoryChipText,
6755
6229
  { color: activeCategory === null ? colors.primaryForeground : colors.foreground }
6756
6230
  ],
6757
6231
  allowFontScaling: true,
6758
6232
  numberOfLines: 1
6759
6233
  },
6760
- "Todos"
6234
+ "Todas"
6761
6235
  ))
6762
6236
  ),
6763
- CURATED_ICONS.map((cat) => /* @__PURE__ */ React54__default.default.createElement(
6237
+ getCuratedCategories().map((cat) => /* @__PURE__ */ React54__default.default.createElement(
6764
6238
  reactNative.TouchableOpacity,
6765
6239
  {
6766
6240
  key: cat.name,
@@ -6771,18 +6245,18 @@ function IconPicker({
6771
6245
  accessibilityLabel: cat.labelEs,
6772
6246
  accessibilityState: { selected: activeCategory === cat.name },
6773
6247
  style: [
6774
- styles47.categoryChip,
6248
+ styles48.categoryChip,
6775
6249
  {
6776
6250
  backgroundColor: activeCategory === cat.name ? colors.primary : colors.surface,
6777
6251
  borderColor: activeCategory === cat.name ? colors.primary : colors.border
6778
6252
  }
6779
6253
  ]
6780
6254
  },
6781
- /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles47.categoryChipInner }, renderIcon(cat.categoryIcon, ms(14), activeCategory === cat.name ? colors.primaryForeground : colors.foregroundSubtle), /* @__PURE__ */ React54__default.default.createElement(
6255
+ /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles48.categoryChipInner }, /* @__PURE__ */ React54__default.default.createElement(Icon, { name: cat.categoryIcon, size: ms(14), color: activeCategory === cat.name ? colors.primaryForeground : colors.foregroundSubtle }), /* @__PURE__ */ React54__default.default.createElement(
6782
6256
  reactNative.Text,
6783
6257
  {
6784
6258
  style: [
6785
- styles47.categoryChipText,
6259
+ styles48.categoryChipText,
6786
6260
  { color: activeCategory === cat.name ? colors.primaryForeground : colors.foreground }
6787
6261
  ],
6788
6262
  allowFontScaling: true,
@@ -6791,7 +6265,7 @@ function IconPicker({
6791
6265
  cat.labelEs
6792
6266
  ))
6793
6267
  ))
6794
- ), /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles47.separator, { backgroundColor: colors.border }] }), cellSize > 0 ? rows.map((row, i) => /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { key: row[0] ?? `row-${i}`, style: [styles47.row, { marginBottom: gapPx }] }, row.map((name) => /* @__PURE__ */ React54__default.default.createElement(
6268
+ ), /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles48.separator, { backgroundColor: colors.border }] }), cellSize > 0 ? rows.map((row, i) => /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { key: row[0] ?? `row-${i}`, style: [styles48.row, { marginBottom: gapPx }] }, row.map((name) => /* @__PURE__ */ React54__default.default.createElement(
6795
6269
  IconCellMemo,
6796
6270
  {
6797
6271
  key: name,
@@ -6808,7 +6282,7 @@ function IconPicker({
6808
6282
  )
6809
6283
  ));
6810
6284
  }
6811
- var styles47 = reactNative.StyleSheet.create({
6285
+ var styles48 = reactNative.StyleSheet.create({
6812
6286
  triggerContainer: {
6813
6287
  gap: vs(8)
6814
6288
  },
@@ -6922,33 +6396,33 @@ function NumberStepperBase({
6922
6396
  };
6923
6397
  const { button: buttonSize, icon: iconSize, valueFontSize, valueLineHeight, valueMinWidth } = sizeConfig[size];
6924
6398
  const displayValue = String(value);
6925
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles48.container, style] }, /* @__PURE__ */ React54__default.default.createElement(
6399
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles49.container, style] }, /* @__PURE__ */ React54__default.default.createElement(
6926
6400
  PressableButton,
6927
6401
  {
6928
6402
  style: [
6929
- styles48.button,
6403
+ styles49.button,
6930
6404
  {
6931
6405
  width: buttonSize,
6932
6406
  height: buttonSize,
6933
6407
  backgroundColor: colors.surface,
6934
6408
  borderColor: colors.border
6935
6409
  },
6936
- !canDecrement && styles48.buttonDisabled
6410
+ !canDecrement && styles49.buttonDisabled
6937
6411
  ],
6938
6412
  enabled: canDecrement,
6939
6413
  onPress: handleDecrement,
6940
6414
  rippleColor: "transparent",
6941
6415
  touchSoundDisabled: true,
6942
6416
  accessibilityRole: "button",
6943
- accessibilityLabel: `Decrease, current value ${displayValue}`,
6417
+ accessibilityLabel: `Disminuir, valor actual ${displayValue}`,
6944
6418
  accessibilityState: { disabled: !canDecrement }
6945
6419
  },
6946
- renderIcon("minus", iconSize, canDecrement ? colors.foreground : colors.foregroundMuted)
6420
+ /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "minus", size: iconSize, color: canDecrement ? colors.foreground : colors.foregroundMuted })
6947
6421
  ), /* @__PURE__ */ React54__default.default.createElement(
6948
6422
  reactNative.Text,
6949
6423
  {
6950
6424
  style: [
6951
- styles48.value,
6425
+ styles49.value,
6952
6426
  {
6953
6427
  color: colors.foreground,
6954
6428
  fontSize: valueFontSize,
@@ -6957,7 +6431,7 @@ function NumberStepperBase({
6957
6431
  }
6958
6432
  ],
6959
6433
  allowFontScaling: true,
6960
- accessibilityLabel: accessibilityLabel ?? `Quantity: ${displayValue}`,
6434
+ accessibilityLabel: accessibilityLabel ?? `Cantidad: ${displayValue}`,
6961
6435
  accessibilityRole: "text"
6962
6436
  },
6963
6437
  displayValue
@@ -6965,28 +6439,28 @@ function NumberStepperBase({
6965
6439
  PressableButton,
6966
6440
  {
6967
6441
  style: [
6968
- styles48.button,
6442
+ styles49.button,
6969
6443
  {
6970
6444
  width: buttonSize,
6971
6445
  height: buttonSize,
6972
6446
  backgroundColor: colors.surface,
6973
6447
  borderColor: colors.border
6974
6448
  },
6975
- !canIncrement && styles48.buttonDisabled
6449
+ !canIncrement && styles49.buttonDisabled
6976
6450
  ],
6977
6451
  enabled: canIncrement,
6978
6452
  onPress: handleIncrement,
6979
6453
  rippleColor: "transparent",
6980
6454
  touchSoundDisabled: true,
6981
6455
  accessibilityRole: "button",
6982
- accessibilityLabel: `Increase, current value ${displayValue}`,
6456
+ accessibilityLabel: `Aumentar, valor actual ${displayValue}`,
6983
6457
  accessibilityState: { disabled: !canIncrement }
6984
6458
  },
6985
- renderIcon("plus", iconSize, canIncrement ? colors.foreground : colors.foregroundMuted)
6459
+ /* @__PURE__ */ React54__default.default.createElement(Icon, { name: "plus", size: iconSize, color: canIncrement ? colors.foreground : colors.foregroundMuted })
6986
6460
  ));
6987
6461
  }
6988
6462
  var NumberStepper = React54__default.default.memo(NumberStepperBase);
6989
- var styles48 = reactNative.StyleSheet.create({
6463
+ var styles49 = reactNative.StyleSheet.create({
6990
6464
  container: {
6991
6465
  flexDirection: "row",
6992
6466
  alignItems: "center",
@@ -7015,6 +6489,7 @@ function StatsComponent({
7015
6489
  iconName,
7016
6490
  iconColor,
7017
6491
  variant = "elevated",
6492
+ size = "default",
7018
6493
  onPress,
7019
6494
  style,
7020
6495
  accessibilityLabel
@@ -7033,6 +6508,27 @@ function StatsComponent({
7033
6508
  onPress();
7034
6509
  };
7035
6510
  const isCompact = containerWidth > 0 && containerWidth < COMPACT_THRESHOLD && !!(icon ?? iconName);
6511
+ const sizeStyles2 = size === "compact" ? {
6512
+ valueFontFamily: "Sohne-SemiBold",
6513
+ valueFontSize: ms(16),
6514
+ valueLineHeight: mvs(20),
6515
+ labelFontSize: ms(11),
6516
+ labelLineHeight: mvs(14),
6517
+ descriptionFontSize: ms(10),
6518
+ descriptionLineHeight: mvs(14),
6519
+ iconSize: ms(18),
6520
+ padding: s(12)
6521
+ } : {
6522
+ valueFontFamily: "Sohne-Bold",
6523
+ valueFontSize: ms(21),
6524
+ valueLineHeight: mvs(25),
6525
+ labelFontSize: ms(13),
6526
+ labelLineHeight: mvs(18),
6527
+ descriptionFontSize: ms(12),
6528
+ descriptionLineHeight: mvs(16),
6529
+ iconSize: ms(20),
6530
+ padding: s(16)
6531
+ };
7036
6532
  const variantStyle = {
7037
6533
  elevated: {
7038
6534
  backgroundColor: colors.card,
@@ -7057,10 +6553,10 @@ function StatsComponent({
7057
6553
  }
7058
6554
  }[variant];
7059
6555
  const iconColorResolved = iconColor ?? colors.primary;
7060
- const resolvedIcon = iconName ? renderIcon(iconName, ms(22), iconColorResolved) : icon;
7061
- const iconElement = resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles49.iconWrapper }, resolvedIcon) : null;
7062
- const valueElement = /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles49.value, { color: colors.foreground }], allowFontScaling: true }, value);
7063
- const cardContent = /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles49.card, variantStyle, style], onLayout: handleLayout }, isCompact ? /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, iconElement, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles49.compactValue }, valueElement), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles49.label, { color: colors.foregroundSubtle }], allowFontScaling: true }, label), description ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles49.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null) : /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles49.valueRow }, iconElement, valueElement), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles49.label, { color: colors.foregroundSubtle }], allowFontScaling: true }, label), description ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles49.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null));
6556
+ const resolvedIcon = iconName ? /* @__PURE__ */ React54__default.default.createElement(Icon, { name: iconName, size: sizeStyles2.iconSize, color: iconColorResolved }) : icon;
6557
+ const iconElement = resolvedIcon ? /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles50.iconWrapper }, resolvedIcon) : null;
6558
+ const valueElement = /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles50.value, { color: colors.foreground, fontFamily: sizeStyles2.valueFontFamily, fontSize: sizeStyles2.valueFontSize, lineHeight: sizeStyles2.valueLineHeight }], allowFontScaling: true }, value);
6559
+ const cardContent = /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles50.card, variantStyle, { padding: sizeStyles2.padding }, style], onLayout: handleLayout }, isCompact ? /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, iconElement, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles50.compactValue }, valueElement), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles50.label, { color: colors.foregroundSubtle, fontSize: sizeStyles2.labelFontSize, lineHeight: sizeStyles2.labelLineHeight }], allowFontScaling: true }, label), description ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles50.description, { color: colors.foregroundMuted, fontSize: sizeStyles2.descriptionFontSize, lineHeight: sizeStyles2.descriptionLineHeight }], allowFontScaling: true }, description) : null) : /* @__PURE__ */ React54__default.default.createElement(React54__default.default.Fragment, null, /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles50.valueRow }, iconElement, valueElement), /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles50.label, { color: colors.foregroundSubtle, fontSize: sizeStyles2.labelFontSize, lineHeight: sizeStyles2.labelLineHeight }], allowFontScaling: true }, label), description ? /* @__PURE__ */ React54__default.default.createElement(reactNative.Text, { style: [styles50.description, { color: colors.foregroundMuted, fontSize: sizeStyles2.descriptionFontSize, lineHeight: sizeStyles2.descriptionLineHeight }], allowFontScaling: true }, description) : null));
7064
6560
  if (onPress) {
7065
6561
  return /* @__PURE__ */ React54__default.default.createElement(
7066
6562
  PressableCard,
@@ -7078,18 +6574,18 @@ function StatsComponent({
7078
6574
  return cardContent;
7079
6575
  }
7080
6576
  function StatsGroup({ children, gap = s(12), style }) {
7081
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles49.group, { gap }, style] }, React54__default.default.Children.map(children, (child) => {
6577
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: [styles50.group, { gap }, style] }, React54__default.default.Children.map(children, (child) => {
7082
6578
  if (!React54__default.default.isValidElement(child)) return child;
7083
6579
  const childStyle = child.props.style;
7084
6580
  const mergedStyle = childStyle ? [childStyle, { alignSelf: "stretch" }] : [{ alignSelf: "stretch" }];
7085
- return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles49.groupItem }, React54__default.default.cloneElement(
6581
+ return /* @__PURE__ */ React54__default.default.createElement(reactNative.View, { style: styles50.groupItem }, React54__default.default.cloneElement(
7086
6582
  child,
7087
6583
  { style: mergedStyle }
7088
6584
  ));
7089
6585
  }));
7090
6586
  }
7091
6587
  var Stats = Object.assign(React54__default.default.memo(StatsComponent), { Group: StatsGroup });
7092
- var styles49 = reactNative.StyleSheet.create({
6588
+ var styles50 = reactNative.StyleSheet.create({
7093
6589
  card: {
7094
6590
  borderRadius: RADIUS.md,
7095
6591
  borderWidth: 1,
@@ -7155,39 +6651,37 @@ function getResponsiveFontSize(text, maxSize, steps = [
7155
6651
  }
7156
6652
  function useConfirmDialog(options) {
7157
6653
  const [visible, setVisible] = React54.useState(false);
7158
- const [target, setTarget] = React54.useState(null);
7159
6654
  const [loading, setLoading] = React54.useState(false);
7160
- const open = React54.useCallback((t) => {
7161
- setTarget(t ?? null);
7162
- setVisible(true);
6655
+ const mountedRef = React54.useRef(true);
6656
+ const onConfirmRef = React54.useRef(options.onConfirm);
6657
+ const onCancelRef = React54.useRef(options.onCancel);
6658
+ React54.useEffect(() => {
6659
+ onConfirmRef.current = options.onConfirm;
6660
+ onCancelRef.current = options.onCancel;
6661
+ });
6662
+ React54.useEffect(() => {
6663
+ return () => {
6664
+ mountedRef.current = false;
6665
+ };
7163
6666
  }, []);
6667
+ const open = React54.useCallback(() => setVisible(true), []);
7164
6668
  const handleConfirm = React54.useCallback(async () => {
7165
6669
  setLoading(true);
7166
6670
  try {
7167
- await options.onConfirm();
6671
+ await onConfirmRef.current();
6672
+ } catch {
7168
6673
  } finally {
7169
- setLoading(false);
7170
- setVisible(false);
7171
- setTarget(null);
6674
+ if (mountedRef.current) {
6675
+ setLoading(false);
6676
+ setVisible(false);
6677
+ }
7172
6678
  }
7173
- }, [options]);
6679
+ }, []);
7174
6680
  const handleCancel = React54.useCallback(() => {
7175
6681
  setVisible(false);
7176
- setTarget(null);
7177
- options.onCancel?.();
7178
- }, [options]);
7179
- return {
7180
- visible,
7181
- target,
7182
- loading,
7183
- open,
7184
- dialogProps: {
7185
- visible,
7186
- loading,
7187
- onConfirm: handleConfirm,
7188
- onCancel: handleCancel
7189
- }
7190
- };
6682
+ onCancelRef.current?.();
6683
+ }, []);
6684
+ return { visible, loading, open, onConfirm: handleConfirm, onCancel: handleCancel };
7191
6685
  }
7192
6686
 
7193
6687
  Object.defineProperty(exports, "BottomSheetModalProvider", {
@@ -7206,6 +6700,7 @@ exports.Accordion = Accordion;
7206
6700
  exports.AlertBanner = AlertBanner;
7207
6701
  exports.AppHeader = AppHeader;
7208
6702
  exports.Avatar = Avatar;
6703
+ exports.AvatarGroup = AvatarGroup;
7209
6704
  exports.BREAKPOINTS = BREAKPOINTS;
7210
6705
  exports.Badge = Badge;
7211
6706
  exports.Button = Button;
@@ -7250,7 +6745,7 @@ exports.MenuItem = MenuItem;
7250
6745
  exports.MonthPicker = MonthPicker;
7251
6746
  exports.NumberStepper = NumberStepper;
7252
6747
  exports.PagerDots = PagerDots;
7253
- exports.Pressable = Pressable2;
6748
+ exports.Pressable = Pressable;
7254
6749
  exports.PricingCard = PricingCard;
7255
6750
  exports.Progress = Progress;
7256
6751
  exports.RADIUS = RADIUS;
@@ -7259,6 +6754,8 @@ exports.RetrayProvider = RetrayProvider;
7259
6754
  exports.SHADOWS = SHADOWS;
7260
6755
  exports.SPACING = SPACING;
7261
6756
  exports.Select = Select;
6757
+ exports.SelectableCard = SelectableCard;
6758
+ exports.SelectableCardGroup = SelectableCardGroup;
7262
6759
  exports.SelectableGrid = SelectableGrid;
7263
6760
  exports.Separator = Separator;
7264
6761
  exports.Sheet = Sheet;
@@ -7277,14 +6774,12 @@ exports.Textarea = Textarea;
7277
6774
  exports.ThemeProvider = ThemeProvider;
7278
6775
  exports.ToastProvider = ToastProvider;
7279
6776
  exports.Toggle = Toggle;
7280
- exports.VirtualList = VirtualList;
7281
- exports.configureIconFamilies = configureIconFamilies;
7282
6777
  exports.dateToMonthPickerValue = dateToMonthPickerValue;
7283
6778
  exports.defaultDark = defaultDark;
7284
6779
  exports.defaultLight = defaultLight;
7285
6780
  exports.deriveColors = deriveColors;
7286
6781
  exports.getResponsiveFontSize = getResponsiveFontSize;
7287
- exports.getValidIconNames = getValidIconNames;
6782
+ exports.hexToRgb = hexToRgb;
7288
6783
  exports.impactHeavy = impactHeavy;
7289
6784
  exports.impactLight = impactLight;
7290
6785
  exports.impactMedium = impactMedium;
@@ -7292,8 +6787,6 @@ exports.monthPickerValueToDate = monthPickerValueToDate;
7292
6787
  exports.notificationError = notificationError;
7293
6788
  exports.notificationSuccess = notificationSuccess;
7294
6789
  exports.notificationWarning = notificationWarning;
7295
- exports.renderIcon = renderIcon;
7296
- exports.richHaptics = richHaptics;
7297
6790
  exports.selectionAsync = selectionAsync;
7298
6791
  exports.useConfirmDialog = useConfirmDialog;
7299
6792
  exports.useTheme = useTheme;