@retray-dev/ui-kit 7.0.1 → 9.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 (234) hide show
  1. package/COMPONENTS.md +554 -11
  2. package/EXAMPLES.md +2 -2
  3. package/README.md +14 -8
  4. package/dist/Accordion.js +57 -5
  5. package/dist/Accordion.mjs +4 -3
  6. package/dist/AlertBanner.js +4 -1
  7. package/dist/AlertBanner.mjs +3 -2
  8. package/dist/AppHeader.d.mts +40 -0
  9. package/dist/AppHeader.d.ts +40 -0
  10. package/dist/AppHeader.js +515 -0
  11. package/dist/AppHeader.mjs +10 -0
  12. package/dist/Avatar.js +39 -29
  13. package/dist/Avatar.mjs +2 -1
  14. package/dist/Badge.js +11 -1
  15. package/dist/Badge.mjs +2 -1
  16. package/dist/Button.d.mts +8 -3
  17. package/dist/Button.d.ts +8 -3
  18. package/dist/Button.js +126 -108
  19. package/dist/Button.mjs +6 -5
  20. package/dist/ButtonGroup.mjs +1 -0
  21. package/dist/Card.js +90 -70
  22. package/dist/Card.mjs +5 -4
  23. package/dist/CategoryStrip.js +79 -22
  24. package/dist/CategoryStrip.mjs +6 -6
  25. package/dist/Checkbox.js +118 -86
  26. package/dist/Checkbox.mjs +5 -5
  27. package/dist/Chip.js +113 -80
  28. package/dist/Chip.mjs +5 -5
  29. package/dist/ConfirmDialog.js +140 -110
  30. package/dist/ConfirmDialog.mjs +7 -6
  31. package/dist/CurrencyDisplay.mjs +1 -0
  32. package/dist/CurrencyInput.d.mts +1 -1
  33. package/dist/CurrencyInput.d.ts +1 -1
  34. package/dist/CurrencyInput.js +9 -5
  35. package/dist/CurrencyInput.mjs +5 -4
  36. package/dist/DetailRow.mjs +1 -0
  37. package/dist/EmptyState.js +131 -111
  38. package/dist/EmptyState.mjs +7 -6
  39. package/dist/ErrorBoundary.d.mts +42 -0
  40. package/dist/ErrorBoundary.d.ts +42 -0
  41. package/dist/ErrorBoundary.js +351 -0
  42. package/dist/ErrorBoundary.mjs +7 -0
  43. package/dist/Form.mjs +1 -0
  44. package/dist/HolographicCard.d.mts +55 -0
  45. package/dist/HolographicCard.d.ts +55 -0
  46. package/dist/HolographicCard.js +316 -0
  47. package/dist/HolographicCard.mjs +191 -0
  48. package/dist/IconButton.d.mts +8 -3
  49. package/dist/IconButton.d.ts +8 -3
  50. package/dist/IconButton.js +115 -98
  51. package/dist/IconButton.mjs +5 -4
  52. package/dist/ImageViewer.d.mts +23 -0
  53. package/dist/ImageViewer.d.ts +23 -0
  54. package/dist/ImageViewer.js +582 -0
  55. package/dist/ImageViewer.mjs +8 -0
  56. package/dist/Input.mjs +4 -3
  57. package/dist/LabelValue.mjs +1 -0
  58. package/dist/ListGroup.mjs +1 -0
  59. package/dist/ListItem.js +131 -117
  60. package/dist/ListItem.mjs +6 -5
  61. package/dist/MediaCard.js +54 -6
  62. package/dist/MediaCard.mjs +6 -5
  63. package/dist/MenuGroup.mjs +1 -0
  64. package/dist/MenuItem.js +91 -79
  65. package/dist/MenuItem.mjs +6 -5
  66. package/dist/MonthPicker.d.mts +10 -2
  67. package/dist/MonthPicker.d.ts +10 -2
  68. package/dist/MonthPicker.js +80 -17
  69. package/dist/MonthPicker.mjs +3 -2
  70. package/dist/PagerDots.d.mts +35 -0
  71. package/dist/PagerDots.d.ts +35 -0
  72. package/dist/PagerDots.js +392 -0
  73. package/dist/PagerDots.mjs +7 -0
  74. package/dist/Pressable.d.mts +5 -5
  75. package/dist/Pressable.d.ts +5 -5
  76. package/dist/Pressable.js +97 -86
  77. package/dist/Pressable.mjs +5 -4
  78. package/dist/PricingCard.d.mts +50 -0
  79. package/dist/PricingCard.d.ts +50 -0
  80. package/dist/PricingCard.js +636 -0
  81. package/dist/PricingCard.mjs +11 -0
  82. package/dist/Progress.mjs +3 -2
  83. package/dist/RadioGroup.js +81 -30
  84. package/dist/RadioGroup.mjs +5 -5
  85. package/dist/RetrayProvider.d.mts +2 -0
  86. package/dist/RetrayProvider.d.ts +2 -0
  87. package/dist/RetrayProvider.js +214 -0
  88. package/dist/RetrayProvider.mjs +5 -0
  89. package/dist/Select.js +51 -4
  90. package/dist/Select.mjs +5 -4
  91. package/dist/SelectableGrid.d.mts +44 -0
  92. package/dist/SelectableGrid.d.ts +44 -0
  93. package/dist/SelectableGrid.js +448 -0
  94. package/dist/SelectableGrid.mjs +9 -0
  95. package/dist/Separator.mjs +1 -0
  96. package/dist/Sheet.d.mts +13 -1
  97. package/dist/Sheet.d.ts +13 -1
  98. package/dist/Sheet.js +115 -5
  99. package/dist/Sheet.mjs +4 -2
  100. package/dist/Skeleton.d.mts +50 -0
  101. package/dist/Skeleton.d.ts +50 -0
  102. package/dist/Skeleton.js +61 -0
  103. package/dist/Skeleton.mjs +4 -2
  104. package/dist/Slider.js +51 -4
  105. package/dist/Slider.mjs +3 -2
  106. package/dist/Spinner.js +28 -7
  107. package/dist/Spinner.mjs +2 -1
  108. package/dist/Switch.js +98 -48
  109. package/dist/Switch.mjs +4 -3
  110. package/dist/TabBar.d.mts +42 -0
  111. package/dist/TabBar.d.ts +42 -0
  112. package/dist/TabBar.js +361 -0
  113. package/dist/TabBar.mjs +6 -0
  114. package/dist/Tabs.js +92 -62
  115. package/dist/Tabs.mjs +5 -4
  116. package/dist/Text.js +16 -0
  117. package/dist/Text.mjs +2 -1
  118. package/dist/Textarea.mjs +4 -3
  119. package/dist/Toast.d.mts +7 -7
  120. package/dist/Toast.d.ts +7 -7
  121. package/dist/Toast.mjs +1 -0
  122. package/dist/Toggle.d.mts +6 -3
  123. package/dist/Toggle.d.ts +6 -3
  124. package/dist/Toggle.js +135 -120
  125. package/dist/Toggle.mjs +5 -5
  126. package/dist/VirtualList.mjs +1 -0
  127. package/dist/{chunk-7H2OR44A.mjs → chunk-26BCI223.mjs} +1 -1
  128. package/dist/{chunk-CRYBX2CM.mjs → chunk-2TFTAWVJ.mjs} +44 -59
  129. package/dist/chunk-3DKJ2GIC.mjs +30 -0
  130. package/dist/{chunk-KWCPOM6W.mjs → chunk-3U4SSNWP.mjs} +32 -48
  131. package/dist/chunk-4I7D47FH.mjs +139 -0
  132. package/dist/chunk-4K625MVM.mjs +142 -0
  133. package/dist/{chunk-MN7OG7IY.mjs → chunk-6OAZJ577.mjs} +6 -4
  134. package/dist/{chunk-L7E7TVEZ.mjs → chunk-756RAKE4.mjs} +2 -2
  135. package/dist/{chunk-HSPSMN6U.mjs → chunk-7QHVVCB3.mjs} +2 -2
  136. package/dist/{chunk-URLL5JBR.mjs → chunk-A3A6KNQN.mjs} +3 -3
  137. package/dist/chunk-AJ7ZDNBT.mjs +120 -0
  138. package/dist/{chunk-FTLJOUOQ.mjs → chunk-AV4EMIRH.mjs} +25 -28
  139. package/dist/chunk-AZJF2BLK.mjs +115 -0
  140. package/dist/chunk-BNP626TY.mjs +159 -0
  141. package/dist/{chunk-5IKW3VNC.mjs → chunk-DVK4G2GT.mjs} +17 -1
  142. package/dist/{chunk-6LQYY7HC.mjs → chunk-EH745HE5.mjs} +2 -2
  143. package/dist/chunk-EJ7ZPXOH.mjs +163 -0
  144. package/dist/{chunk-RKLHUDZS.mjs → chunk-GD6KXMG5.mjs} +29 -15
  145. package/dist/{chunk-RR2VQLKE.mjs → chunk-GQYFLP3D.mjs} +14 -17
  146. package/dist/{chunk-Y6MXOREN.mjs → chunk-ID72TK46.mjs} +8 -17
  147. package/dist/{chunk-NQGVLMWG.mjs → chunk-JMOZEC77.mjs} +1 -1
  148. package/dist/{chunk-GCWOGZYL.mjs → chunk-JT7HKXRB.mjs} +39 -29
  149. package/dist/{chunk-LWG526VX.mjs → chunk-KIHCWCWL.mjs} +47 -62
  150. package/dist/chunk-LXJIIOYQ.mjs +104 -0
  151. package/dist/{chunk-SBZYEV4S.mjs → chunk-M6ZXVBTK.mjs} +5 -2
  152. package/dist/{chunk-XDMN67KV.mjs → chunk-MAC465BB.mjs} +10 -8
  153. package/dist/chunk-MBMXYJJV.mjs +36 -0
  154. package/dist/chunk-MLF3EZFW.mjs +119 -0
  155. package/dist/chunk-NA7PARID.mjs +147 -0
  156. package/dist/{chunk-QXGYKWI7.mjs → chunk-O3HA6TYM.mjs} +9 -4
  157. package/dist/{chunk-63357L2X.mjs → chunk-OB4JUQ3O.mjs} +1 -1
  158. package/dist/{chunk-AU2VDY4P.mjs → chunk-PFZTM6D5.mjs} +52 -4
  159. package/dist/chunk-QKH5ZOD5.mjs +97 -0
  160. package/dist/{chunk-KZJRQOIU.mjs → chunk-TERDKCLE.mjs} +11 -1
  161. package/dist/{chunk-U4N7WF4Z.mjs → chunk-UREA2GYY.mjs} +28 -23
  162. package/dist/{chunk-TAJ2PQ2O.mjs → chunk-VGTDN7SW.mjs} +7 -6
  163. package/dist/{chunk-URDE3EUU.mjs → chunk-VQ57HWPL.mjs} +27 -15
  164. package/dist/chunk-WBOOUHSS.mjs +62 -0
  165. package/dist/{chunk-GNGLDL6Z.mjs → chunk-WJLKJMKR.mjs} +18 -0
  166. package/dist/{chunk-YZJAFS4P.mjs → chunk-X4G6APW6.mjs} +22 -19
  167. package/dist/chunk-Y6FXYEAI.mjs +8 -0
  168. package/dist/chunk-YFZ3ELX5.mjs +16 -0
  169. package/dist/{chunk-QCNARS3X.mjs → chunk-YNROWHQJ.mjs} +1 -1
  170. package/dist/chunk-Z4BVUWW6.mjs +196 -0
  171. package/dist/{chunk-GPOUINK5.mjs → chunk-ZJKGQMYH.mjs} +10 -27
  172. package/dist/index-wt-orHUi.d.mts +85 -0
  173. package/dist/index-wt-orHUi.d.ts +85 -0
  174. package/dist/index.d.mts +59 -51
  175. package/dist/index.d.ts +59 -51
  176. package/dist/index.js +1940 -744
  177. package/dist/index.mjs +49 -39
  178. package/package.json +35 -5
  179. package/src/components/Accordion/Accordion.tsx +12 -1
  180. package/src/components/AlertBanner/AlertBanner.tsx +5 -0
  181. package/src/components/AppHeader/AppHeader.tsx +172 -0
  182. package/src/components/AppHeader/index.ts +1 -0
  183. package/src/components/Avatar/Avatar.tsx +10 -2
  184. package/src/components/Badge/Badge.tsx +8 -1
  185. package/src/components/Button/Button.tsx +20 -27
  186. package/src/components/Card/Card.tsx +12 -23
  187. package/src/components/CategoryStrip/CategoryStrip.tsx +17 -21
  188. package/src/components/Checkbox/Checkbox.tsx +26 -40
  189. package/src/components/Chip/Chip.tsx +24 -33
  190. package/src/components/CurrencyInput/CurrencyInput.tsx +10 -8
  191. package/src/components/EmptyState/EmptyState.tsx +2 -1
  192. package/src/components/ErrorBoundary/ErrorBoundary.tsx +153 -0
  193. package/src/components/ErrorBoundary/index.ts +1 -0
  194. package/src/components/HolographicCard/HolographicCard.tsx +315 -0
  195. package/src/components/HolographicCard/index.ts +1 -0
  196. package/src/components/IconButton/IconButton.tsx +19 -27
  197. package/src/components/ImageViewer/ImageViewer.tsx +290 -0
  198. package/src/components/ImageViewer/index.ts +1 -0
  199. package/src/components/ListItem/ListItem.tsx +70 -67
  200. package/src/components/MediaCard/MediaCard.tsx +8 -2
  201. package/src/components/MenuItem/MenuItem.tsx +10 -25
  202. package/src/components/MonthPicker/MonthPicker.tsx +39 -13
  203. package/src/components/MonthPicker/index.ts +1 -1
  204. package/src/components/PagerDots/PagerDots.tsx +200 -0
  205. package/src/components/PagerDots/index.ts +1 -0
  206. package/src/components/Pressable/Pressable.tsx +19 -35
  207. package/src/components/PricingCard/PricingCard.tsx +220 -0
  208. package/src/components/PricingCard/index.ts +1 -0
  209. package/src/components/RadioGroup/RadioGroup.tsx +14 -27
  210. package/src/components/RetrayProvider/RetrayProvider.tsx +59 -0
  211. package/src/components/RetrayProvider/index.ts +1 -0
  212. package/src/components/SelectableGrid/SelectableGrid.tsx +205 -0
  213. package/src/components/SelectableGrid/index.ts +1 -0
  214. package/src/components/Sheet/Sheet.tsx +65 -1
  215. package/src/components/Skeleton/Skeleton.tsx +142 -1
  216. package/src/components/Spinner/Spinner.tsx +17 -2
  217. package/src/components/Switch/Switch.tsx +30 -58
  218. package/src/components/TabBar/TabBar.tsx +169 -0
  219. package/src/components/TabBar/index.ts +1 -0
  220. package/src/components/Tabs/Tabs.tsx +23 -26
  221. package/src/components/Text/Text.tsx +2 -0
  222. package/src/components/Toggle/Toggle.tsx +35 -51
  223. package/src/fonts.ts +4 -1
  224. package/src/index.ts +23 -2
  225. package/src/utils/animations.ts +29 -1
  226. package/src/utils/fontGuard.ts +34 -0
  227. package/src/utils/haptics.ts +211 -9
  228. package/src/utils/pressable.ts +66 -0
  229. package/dist/chunk-76PFOSM2.mjs +0 -41
  230. package/dist/chunk-DITNP6PL.mjs +0 -106
  231. package/dist/chunk-JBLL7U3U.mjs +0 -64
  232. package/dist/chunk-LG4DO3DK.mjs +0 -174
  233. package/dist/chunk-RMMK64W5.mjs +0 -54
  234. package/dist/chunk-RTC3CFXF.mjs +0 -29
package/dist/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var React26 = require('react');
3
+ var React25 = require('react');
4
4
  var reactNative = require('react-native');
5
- var Animated9 = require('react-native-reanimated');
6
5
  var reactNativeSizeMatters = require('react-native-size-matters');
7
6
  var AntDesign = require('@expo/vector-icons/AntDesign');
8
7
  var Entypo = require('@expo/vector-icons/Entypo');
@@ -10,27 +9,37 @@ var Feather = require('@expo/vector-icons/Feather');
10
9
  var FontAwesome5 = require('@expo/vector-icons/FontAwesome5');
11
10
  var MaterialIcons = require('@expo/vector-icons/MaterialIcons');
12
11
  var Ionicons = require('@expo/vector-icons/Ionicons');
12
+ var pressto = require('pressto');
13
+ var Animated13 = require('react-native-reanimated');
14
+ var expoFont = require('expo-font');
13
15
  var vectorIcons = require('@expo/vector-icons');
14
16
  var expoLinearGradient = require('expo-linear-gradient');
17
+ var reactNativeEase = require('react-native-ease');
15
18
  var RNSlider = require('@react-native-community/slider');
16
19
  var bottomSheet = require('@gorhom/bottom-sheet');
17
20
  var reactNativeSafeAreaContext = require('react-native-safe-area-context');
18
21
  var picker = require('@react-native-picker/picker');
19
22
  var sonnerNative = require('sonner-native');
23
+ var reactNativeGestureHandler = require('react-native-gesture-handler');
20
24
 
21
25
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
22
26
 
23
- var React26__default = /*#__PURE__*/_interopDefault(React26);
24
- var Animated9__default = /*#__PURE__*/_interopDefault(Animated9);
27
+ var React25__default = /*#__PURE__*/_interopDefault(React25);
25
28
  var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
26
29
  var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
27
30
  var Feather__default = /*#__PURE__*/_interopDefault(Feather);
28
31
  var FontAwesome5__default = /*#__PURE__*/_interopDefault(FontAwesome5);
29
32
  var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
30
33
  var Ionicons__default = /*#__PURE__*/_interopDefault(Ionicons);
34
+ var Animated13__default = /*#__PURE__*/_interopDefault(Animated13);
31
35
  var RNSlider__default = /*#__PURE__*/_interopDefault(RNSlider);
32
36
 
33
- // src/theme/ThemeProvider.tsx
37
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
38
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
39
+ }) : x)(function(x) {
40
+ if (typeof require !== "undefined") return require.apply(this, arguments);
41
+ throw Error('Dynamic require of "' + x + '" is not supported');
42
+ });
34
43
 
35
44
  // src/theme/colorUtils.ts
36
45
  function hexToRgb(hex) {
@@ -158,52 +167,186 @@ function deriveColors(t, scheme) {
158
167
  }
159
168
 
160
169
  // src/theme/ThemeProvider.tsx
161
- var ThemeContext = React26.createContext({
170
+ var ThemeContext = React25.createContext({
162
171
  colors: deriveColors(defaultLight, "light"),
163
172
  colorScheme: "light"
164
173
  });
165
174
  function ThemeProvider({ children, theme, colorScheme = "system" }) {
166
175
  const systemScheme = reactNative.useColorScheme() ?? "light";
167
176
  const resolvedScheme = colorScheme === "system" ? systemScheme : colorScheme;
168
- const colors = React26.useMemo(() => {
177
+ const colors = React25.useMemo(() => {
169
178
  const base = resolvedScheme === "dark" ? defaultDark : defaultLight;
170
179
  const override = resolvedScheme === "dark" ? theme?.dark : theme?.light;
171
180
  const merged = override ? { ...base, ...override } : base;
172
181
  return deriveColors(merged, resolvedScheme);
173
182
  }, [resolvedScheme, theme]);
174
- return /* @__PURE__ */ React26__default.default.createElement(ThemeContext.Provider, { value: { colors, colorScheme: resolvedScheme } }, children);
183
+ return /* @__PURE__ */ React25__default.default.createElement(ThemeContext.Provider, { value: { colors, colorScheme: resolvedScheme } }, children);
175
184
  }
176
185
  function useTheme() {
177
- const context = React26.useContext(ThemeContext);
186
+ const context = React25.useContext(ThemeContext);
178
187
  if (!context) {
179
188
  throw new Error("useTheme must be used within a ThemeProvider");
180
189
  }
181
190
  return context;
182
191
  }
183
192
  var _haptics = null;
193
+ var _hapticsLoaded = false;
184
194
  async function getHaptics() {
185
195
  if (reactNative.Platform.OS === "web") return null;
186
- if (!_haptics) {
187
- _haptics = await import('expo-haptics');
196
+ if (!_hapticsLoaded) {
197
+ _hapticsLoaded = true;
198
+ try {
199
+ _haptics = await import('expo-haptics');
200
+ } catch {
201
+ _haptics = null;
202
+ }
188
203
  }
189
204
  return _haptics;
190
205
  }
206
+ var _pulsar = null;
207
+ var _pulsarChecked = false;
208
+ var _pulsarAvailable = false;
209
+ function isPulsarNativeRegistered() {
210
+ try {
211
+ const g = globalThis;
212
+ if (typeof g.__turboModuleProxy === "function") {
213
+ return g.__turboModuleProxy("RNPulsar") != null;
214
+ }
215
+ return reactNative.NativeModules?.RNPulsar != null;
216
+ } catch {
217
+ return false;
218
+ }
219
+ }
220
+ function getPulsar() {
221
+ if (reactNative.Platform.OS === "web") return null;
222
+ if (!_pulsarChecked) {
223
+ _pulsarChecked = true;
224
+ try {
225
+ if (isPulsarNativeRegistered()) {
226
+ _pulsar = __require("react-native-pulsar");
227
+ _pulsarAvailable = true;
228
+ }
229
+ } catch {
230
+ _pulsar = null;
231
+ _pulsarAvailable = false;
232
+ }
233
+ }
234
+ return _pulsarAvailable ? _pulsar : null;
235
+ }
191
236
  function selectionAsync() {
192
237
  if (reactNative.Platform.OS === "web") return;
193
- getHaptics().then((h) => h?.selectionAsync());
238
+ getHaptics().then((h) => {
239
+ if (h) {
240
+ h.selectionAsync();
241
+ } else {
242
+ getPulsar()?.Presets.System.selection();
243
+ }
244
+ });
194
245
  }
195
246
  function impactLight() {
196
247
  if (reactNative.Platform.OS === "web") return;
197
- getHaptics().then((h) => h?.impactAsync(h.ImpactFeedbackStyle.Light));
248
+ getHaptics().then((h) => {
249
+ if (h) {
250
+ h.impactAsync(h.ImpactFeedbackStyle.Light);
251
+ } else {
252
+ getPulsar()?.Presets.System.impactLight();
253
+ }
254
+ });
198
255
  }
199
256
  function impactMedium() {
200
257
  if (reactNative.Platform.OS === "web") return;
201
- getHaptics().then((h) => h?.impactAsync(h.ImpactFeedbackStyle.Medium));
258
+ getHaptics().then((h) => {
259
+ if (h) {
260
+ h.impactAsync(h.ImpactFeedbackStyle.Medium);
261
+ } else {
262
+ getPulsar()?.Presets.System.impactMedium();
263
+ }
264
+ });
265
+ }
266
+ function impactHeavy() {
267
+ if (reactNative.Platform.OS === "web") return;
268
+ getHaptics().then((h) => {
269
+ if (h) {
270
+ h.impactAsync(h.ImpactFeedbackStyle.Heavy);
271
+ } else {
272
+ getPulsar()?.Presets.System.impactHeavy();
273
+ }
274
+ });
202
275
  }
203
276
  function notificationSuccess() {
204
277
  if (reactNative.Platform.OS === "web") return;
205
- getHaptics().then((h) => h?.notificationAsync(h.NotificationFeedbackType.Success));
278
+ getHaptics().then((h) => {
279
+ if (h) {
280
+ h.notificationAsync(h.NotificationFeedbackType.Success);
281
+ } else {
282
+ getPulsar()?.Presets.System.notificationSuccess();
283
+ }
284
+ });
285
+ }
286
+ function notificationError() {
287
+ if (reactNative.Platform.OS === "web") return;
288
+ getHaptics().then((h) => {
289
+ if (h) {
290
+ h.notificationAsync(h.NotificationFeedbackType.Error);
291
+ } else {
292
+ getPulsar()?.Presets.System.notificationError();
293
+ }
294
+ });
295
+ }
296
+ function notificationWarning() {
297
+ if (reactNative.Platform.OS === "web") return;
298
+ getHaptics().then((h) => {
299
+ if (h) {
300
+ h.notificationAsync(h.NotificationFeedbackType.Warning);
301
+ } else {
302
+ getPulsar()?.Presets.System.notificationWarning();
303
+ }
304
+ });
206
305
  }
306
+ var richHaptics = {
307
+ /** Hammer strike — strong confirmation feedback. */
308
+ hammer: () => {
309
+ if (reactNative.Platform.OS === "web") return;
310
+ const p = getPulsar();
311
+ if (p) p.Presets.hammer();
312
+ else impactHeavy();
313
+ },
314
+ /** Pulse — rhythmic feedback for toggles or state changes. */
315
+ pulse: () => {
316
+ if (reactNative.Platform.OS === "web") return;
317
+ const p = getPulsar();
318
+ if (p) p.Presets.pulse();
319
+ else selectionAsync();
320
+ },
321
+ /** Buzz — continuous vibration for attention. */
322
+ buzz: () => {
323
+ if (reactNative.Platform.OS === "web") return;
324
+ const p = getPulsar();
325
+ if (p) p.Presets.buzz();
326
+ else impactMedium();
327
+ },
328
+ /** Flick — crisp click feedback. */
329
+ flick: () => {
330
+ if (reactNative.Platform.OS === "web") return;
331
+ const p = getPulsar();
332
+ if (p) p.Presets.flick();
333
+ else selectionAsync();
334
+ },
335
+ /** Soft — gentle, subtle feedback. */
336
+ soft: () => {
337
+ if (reactNative.Platform.OS === "web") return;
338
+ const p = getPulsar();
339
+ if (p) p.Presets.System.impactSoft();
340
+ else impactLight();
341
+ },
342
+ /** Rigid — firm, solid feedback. */
343
+ rigid: () => {
344
+ if (reactNative.Platform.OS === "web") return;
345
+ const p = getPulsar();
346
+ if (p) p.Presets.System.impactRigid();
347
+ else impactMedium();
348
+ }
349
+ };
207
350
  var isWeb = reactNative.Platform.OS === "web";
208
351
  var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
209
352
  var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
@@ -250,10 +393,10 @@ function Icon({ name, size, color, family }) {
250
393
  }
251
394
  if (!resolved) return null;
252
395
  const Component = resolved.component;
253
- return React26__default.default.createElement(Component, { name, size, color });
396
+ return React25__default.default.createElement(Component, { name, size, color });
254
397
  }
255
398
  function renderIcon(name, size, color) {
256
- return React26__default.default.createElement(Icon, { name, size, color });
399
+ return React25__default.default.createElement(Icon, { name, size, color });
257
400
  }
258
401
 
259
402
  // src/tokens.ts
@@ -453,10 +596,7 @@ var SPRINGS = {
453
596
  surfacePressIn: { stiffness: 380, damping: 30, mass: 0.95 },
454
597
  surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 },
455
598
  /** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
456
- glide: { stiffness: 380, damping: 38, mass: 1 },
457
- /** Elastic indicator — Switch thumb, RadioGroup dot. */
458
- elastic: { stiffness: 320, damping: 22, mass: 0.7 }
459
- };
599
+ glide: { stiffness: 380, damping: 38, mass: 1 }};
460
600
  var TIMINGS = {
461
601
  /** Color/opacity transitions on toggles, checkboxes, switches. */
462
602
  state: { duration: 160 },
@@ -471,11 +611,27 @@ var TIMINGS = {
471
611
  };
472
612
  var EASINGS = {
473
613
  /** Material-style ease-out — natural deceleration for state changes. */
474
- standard: Animated9.Easing.bezier(0.2, 0, 0, 1),
614
+ standard: Animated13.Easing.bezier(0.2, 0, 0, 1),
475
615
  /** Strong ease-out for expanding surfaces (Accordion open). */
476
- expand: Animated9.Easing.bezier(0.23, 1, 0.32, 1),
616
+ expand: Animated13.Easing.bezier(0.23, 1, 0.32, 1),
477
617
  /** Quick ease-in for collapsing. */
478
- collapse: Animated9.Easing.in(Animated9.Easing.ease)
618
+ collapse: Animated13.Easing.in(Animated13.Easing.ease)
619
+ };
620
+ var COLOR_TRANSITION = {
621
+ type: "timing",
622
+ duration: TIMINGS.state.duration,
623
+ easing: [0.2, 0, 0, 1]
624
+ };
625
+ var OPACITY_TRANSITION = {
626
+ type: "timing",
627
+ duration: TIMINGS.state.duration,
628
+ easing: [0.2, 0, 0, 1]
629
+ };
630
+ var SPRING_ELASTIC = {
631
+ type: "spring",
632
+ stiffness: 320,
633
+ damping: 22,
634
+ mass: 0.7
479
635
  };
480
636
  var PRESS_SCALE = {
481
637
  button: 0.95,
@@ -483,51 +639,36 @@ var PRESS_SCALE = {
483
639
  row: 0.97,
484
640
  chip: 0.94
485
641
  };
486
- function useHover() {
487
- const [hovered, setHovered] = React26.useState(false);
488
- const onMouseEnter = React26.useCallback(() => setHovered(true), []);
489
- const onMouseLeave = React26.useCallback(() => setHovered(false), []);
490
- if (reactNative.Platform.OS !== "web") {
491
- return { hovered: false, hoverHandlers: {} };
492
- }
493
- return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
494
- }
495
-
496
- // src/utils/usePressScale.ts
497
- function usePressScale({
498
- pressScale = PRESS_SCALE.button,
499
- hoverScale = 1.02,
500
- pressInSpring = SPRINGS.pressIn,
501
- pressOutSpring = SPRINGS.pressOut,
502
- disabled = false
503
- } = {}) {
504
- const scale2 = Animated9.useSharedValue(1);
505
- const { hovered, hoverHandlers } = useHover();
506
- const onPressIn = React26.useCallback(() => {
507
- if (disabled) return;
508
- scale2.value = Animated9.withSpring(pressScale, pressInSpring);
509
- }, [disabled, pressScale, pressInSpring, scale2]);
510
- const onPressOut = React26.useCallback(() => {
511
- if (disabled) return;
512
- scale2.value = Animated9.withSpring(1, pressOutSpring);
513
- }, [disabled, pressOutSpring, scale2]);
514
- const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
515
- const animatedStyle = Animated9.useAnimatedStyle(() => ({
516
- transform: [
517
- { scale: scale2.value * (hoverActive ? hoverScale : 1) }
518
- ]
519
- }));
520
- return {
521
- animatedStyle,
522
- onPressIn,
523
- onPressOut,
524
- hoverHandlers
525
- };
526
- }
642
+ var PressableButton = pressto.createAnimatedPressable((progress) => {
643
+ "worklet";
644
+ const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
645
+ return { transform: [{ scale: scale2 }] };
646
+ });
647
+ var PressableCard = pressto.createAnimatedPressable((progress) => {
648
+ "worklet";
649
+ const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
650
+ return { transform: [{ scale: scale2 }] };
651
+ });
652
+ var PressableRow = pressto.createAnimatedPressable((progress) => {
653
+ "worklet";
654
+ const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
655
+ return { transform: [{ scale: scale2 }] };
656
+ });
657
+ var PressableChip = pressto.createAnimatedPressable((progress) => {
658
+ "worklet";
659
+ const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
660
+ return { transform: [{ scale: scale2 }] };
661
+ });
662
+ var PressableTab = pressto.createAnimatedPressable((progress) => {
663
+ "worklet";
664
+ const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
665
+ return { transform: [{ scale: scale2 }] };
666
+ });
527
667
 
528
668
  // src/components/Button/Button.tsx
529
669
  var containerSizeStyles = {
530
- sm: { paddingHorizontal: s(16), paddingVertical: vs(10), minHeight: 40 },
670
+ // AUDIT FIX: sm was 40pt below Apple HIG 44pt minimum touch target.
671
+ sm: { paddingHorizontal: s(16), paddingVertical: vs(12), minHeight: 44 },
531
672
  md: { paddingHorizontal: s(24), paddingVertical: vs(14), minHeight: 48 },
532
673
  lg: { paddingHorizontal: s(28), paddingVertical: vs(16), minHeight: 56 }
533
674
  };
@@ -551,18 +692,13 @@ function ButtonBase({
551
692
  style,
552
693
  onPress,
553
694
  accessibilityLabel,
554
- accessibilityHint,
555
- ...props
695
+ accessibilityHint
556
696
  }) {
557
697
  const { colors } = useTheme();
558
698
  const isDisabled = disabled || loading;
559
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
560
- pressScale: PRESS_SCALE.button,
561
- disabled: isDisabled
562
- });
563
- const handlePress = (e) => {
699
+ const handlePress = () => {
564
700
  impactMedium();
565
- onPress?.(e);
701
+ onPress?.();
566
702
  };
567
703
  const containerVariantStyle = {
568
704
  primary: { backgroundColor: colors.primary },
@@ -585,56 +721,47 @@ function ButtonBase({
585
721
  const styleArray = Array.isArray(style) ? style : style ? [style] : [];
586
722
  const flatStyle = reactNative.StyleSheet.flatten(styleArray);
587
723
  const { flex, ...restStyle } = flatStyle || {};
588
- return /* @__PURE__ */ React26__default.default.createElement(
589
- Animated9__default.default.View,
724
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [fullWidth && styles.fullWidth, flex !== void 0 && { flex }] }, /* @__PURE__ */ React25__default.default.createElement(
725
+ PressableButton,
590
726
  {
591
- style: [fullWidth && styles.fullWidth, flex !== void 0 && { flex }, animatedStyle],
592
- ...hoverHandlers
727
+ style: [
728
+ styles.base,
729
+ containerVariantStyle,
730
+ containerSizeStyles[size],
731
+ fullWidth && styles.fullWidth,
732
+ isDisabled && styles.disabled,
733
+ restStyle
734
+ ],
735
+ enabled: !isDisabled,
736
+ onPress: handlePress,
737
+ rippleColor: "transparent",
738
+ touchSoundDisabled: true,
739
+ activateOnHover: true,
740
+ accessibilityRole: "button",
741
+ accessibilityLabel: accessibilityLabel ?? label,
742
+ accessibilityHint,
743
+ accessibilityState: { disabled: isDisabled, busy: loading }
593
744
  },
594
- /* @__PURE__ */ React26__default.default.createElement(
595
- reactNative.TouchableOpacity,
745
+ loading ? /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React25__default.default.createElement(
746
+ reactNative.Text,
596
747
  {
597
- style: [
598
- styles.base,
599
- containerVariantStyle,
600
- containerSizeStyles[size],
601
- fullWidth && styles.fullWidth,
602
- isDisabled && styles.disabled,
603
- restStyle
604
- ],
605
- disabled: isDisabled,
606
- activeOpacity: 1,
607
- touchSoundDisabled: true,
608
- onPress: handlePress,
609
- onPressIn,
610
- onPressOut,
611
- accessibilityRole: "button",
612
- accessibilityLabel: accessibilityLabel ?? label,
613
- accessibilityHint,
614
- accessibilityState: { disabled: isDisabled, busy: loading },
615
- ...props
748
+ style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
749
+ allowFontScaling: true,
750
+ numberOfLines: 1
616
751
  },
617
- loading ? /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, /* @__PURE__ */ React26__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React26__default.default.createElement(
618
- reactNative.Text,
619
- {
620
- style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
621
- allowFontScaling: true,
622
- numberOfLines: 1
623
- },
624
- label
625
- )) : /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React26__default.default.createElement(
626
- reactNative.Text,
627
- {
628
- style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
629
- allowFontScaling: true,
630
- numberOfLines: 1
631
- },
632
- label
633
- ), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, effectiveIcon))
634
- )
635
- );
752
+ label
753
+ )) : /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon), /* @__PURE__ */ React25__default.default.createElement(
754
+ reactNative.Text,
755
+ {
756
+ style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
757
+ allowFontScaling: true,
758
+ numberOfLines: 1
759
+ },
760
+ label
761
+ ), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveIcon))
762
+ ));
636
763
  }
637
- var Button = React26__default.default.memo(ButtonBase);
764
+ var Button = React25__default.default.memo(ButtonBase);
638
765
  var styles = reactNative.StyleSheet.create({
639
766
  base: {
640
767
  borderRadius: RADIUS.md,
@@ -660,7 +787,7 @@ var styles = reactNative.StyleSheet.create({
660
787
  }
661
788
  });
662
789
  function ButtonGroup({ children, gap = 12, vertical = false, style }) {
663
- return /* @__PURE__ */ React26__default.default.createElement(
790
+ return /* @__PURE__ */ React25__default.default.createElement(
664
791
  reactNative.View,
665
792
  {
666
793
  style: [
@@ -670,8 +797,8 @@ function ButtonGroup({ children, gap = 12, vertical = false, style }) {
670
797
  style
671
798
  ]
672
799
  },
673
- React26__default.default.Children.map(children, (child) => {
674
- if (!React26__default.default.isValidElement(child)) return child;
800
+ React25__default.default.Children.map(children, (child) => {
801
+ if (!React25__default.default.isValidElement(child)) return child;
675
802
  const childProps = child.props;
676
803
  const extraProps = {
677
804
  style: [child.props.style, { flex: 1 }]
@@ -679,7 +806,7 @@ function ButtonGroup({ children, gap = 12, vertical = false, style }) {
679
806
  if (!vertical && "label" in childProps && childProps["size"] === void 0) {
680
807
  extraProps["size"] = "sm";
681
808
  }
682
- return React26__default.default.cloneElement(child, extraProps);
809
+ return React25__default.default.cloneElement(child, extraProps);
683
810
  })
684
811
  );
685
812
  }
@@ -695,7 +822,8 @@ var styles2 = reactNative.StyleSheet.create({
695
822
  }
696
823
  });
697
824
  var sizeMap = {
698
- sm: { container: s(32), icon: 16 },
825
+ // AUDIT FIX: sm was 32pt — below Apple HIG 44pt minimum touch target.
826
+ sm: { container: s(44), icon: 18 },
699
827
  md: { container: s(44), icon: 20 },
700
828
  lg: { container: s(52), icon: 24 }
701
829
  };
@@ -711,18 +839,13 @@ function IconButtonBase({
711
839
  style,
712
840
  onPress,
713
841
  accessibilityLabel,
714
- accessibilityHint,
715
- ...props
842
+ accessibilityHint
716
843
  }) {
717
844
  const { colors } = useTheme();
718
845
  const isDisabled = disabled || loading;
719
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
720
- pressScale: PRESS_SCALE.button,
721
- disabled: isDisabled
722
- });
723
- const handlePress = (e) => {
846
+ const handlePress = () => {
724
847
  impactLight();
725
- onPress?.(e);
848
+ onPress?.();
726
849
  };
727
850
  const containerVariantStyle = {
728
851
  primary: { backgroundColor: colors.primary },
@@ -744,44 +867,34 @@ function IconButtonBase({
744
867
  const showBadge = badge !== void 0 && badge !== false && badge !== 0;
745
868
  const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
746
869
  const showCount = typeof badge === "number" && badge > 0;
747
- return /* @__PURE__ */ React26__default.default.createElement(
748
- Animated9__default.default.View,
870
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles3.wrapper }, /* @__PURE__ */ React25__default.default.createElement(
871
+ PressableButton,
749
872
  {
750
- style: [styles3.wrapper, animatedStyle],
751
- ...hoverHandlers
873
+ style: [
874
+ styles3.base,
875
+ containerVariantStyle,
876
+ { width: containerSize, height: containerSize },
877
+ isDisabled && styles3.disabled,
878
+ style
879
+ ],
880
+ enabled: !isDisabled,
881
+ onPress: handlePress,
882
+ rippleColor: "transparent",
883
+ touchSoundDisabled: true,
884
+ activateOnHover: true,
885
+ accessibilityRole: "button",
886
+ accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
887
+ accessibilityHint,
888
+ accessibilityState: { disabled: isDisabled, busy: loading }
752
889
  },
753
- /* @__PURE__ */ React26__default.default.createElement(
754
- reactNative.TouchableOpacity,
755
- {
756
- style: [
757
- styles3.base,
758
- containerVariantStyle,
759
- { width: containerSize, height: containerSize },
760
- isDisabled && styles3.disabled,
761
- style
762
- ],
763
- disabled: isDisabled,
764
- activeOpacity: 1,
765
- touchSoundDisabled: true,
766
- onPress: handlePress,
767
- onPressIn,
768
- onPressOut,
769
- accessibilityRole: "button",
770
- accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
771
- accessibilityHint,
772
- accessibilityState: { disabled: isDisabled, busy: loading },
773
- ...props
774
- },
775
- loading ? /* @__PURE__ */ React26__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
776
- ),
777
- showBadge && /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [
778
- styles3.badge,
779
- { backgroundColor: colors.primary },
780
- showCount ? styles3.badgeCount : styles3.badgeDot
781
- ] }, showCount && /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles3.badgeText, { color: colors.primaryForeground }] }, badgeCount))
782
- );
890
+ loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
891
+ ), showBadge && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [
892
+ styles3.badge,
893
+ { backgroundColor: colors.primary },
894
+ showCount ? styles3.badgeCount : styles3.badgeDot
895
+ ] }, showCount && /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles3.badgeText, { color: colors.primaryForeground }] }, badgeCount)));
783
896
  }
784
- var IconButton = React26__default.default.memo(IconButtonBase);
897
+ var IconButton = React25__default.default.memo(IconButtonBase);
785
898
  var styles3 = reactNative.StyleSheet.create({
786
899
  wrapper: {
787
900
  alignSelf: "flex-start"
@@ -818,6 +931,22 @@ var styles3 = reactNative.StyleSheet.create({
818
931
  lineHeight: 14
819
932
  }
820
933
  });
934
+ var warned = false;
935
+ function warnIfFontsMissing() {
936
+ if (warned) return;
937
+ if (typeof __DEV__ !== "undefined" && !__DEV__) return;
938
+ warned = true;
939
+ try {
940
+ if (!expoFont.isLoaded("Sohne-Regular")) {
941
+ console.warn(
942
+ "[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 { SohneFonts } from '@retray-dev/ui-kit/fonts'\n\n const [fontsLoaded] = useFonts(SohneFonts)\n if (!fontsLoaded) return null\n"
943
+ );
944
+ }
945
+ } catch {
946
+ }
947
+ }
948
+
949
+ // src/components/Text/Text.tsx
821
950
  var variantStyles = {
822
951
  "display-hero": { ...TYPOGRAPHY["display-hero"], fontSize: ms(TYPOGRAPHY["display-hero"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-hero"].lineHeight) },
823
952
  "display-xl": { ...TYPOGRAPHY["display-xl"], fontSize: ms(TYPOGRAPHY["display-xl"].fontSize), lineHeight: mvs(TYPOGRAPHY["display-xl"].lineHeight) },
@@ -856,10 +985,11 @@ var defaultColorVariant = {
856
985
  "button-sm": "foreground"
857
986
  };
858
987
  function TextBase({ variant = "body-md", color, style, children, ...props }) {
988
+ warnIfFontsMissing();
859
989
  const { colors } = useTheme();
860
990
  const colorKey = defaultColorVariant[variant] ?? "foreground";
861
991
  const resolvedColor = color ?? colors[colorKey];
862
- return /* @__PURE__ */ React26__default.default.createElement(
992
+ return /* @__PURE__ */ React25__default.default.createElement(
863
993
  reactNative.Text,
864
994
  {
865
995
  style: [variantStyles[variant], { color: resolvedColor }, style],
@@ -869,12 +999,12 @@ function TextBase({ variant = "body-md", color, style, children, ...props }) {
869
999
  children
870
1000
  );
871
1001
  }
872
- var Text3 = React26__default.default.memo(TextBase);
1002
+ var Text3 = React25__default.default.memo(TextBase);
873
1003
  function useColorTransition(active, options = {}) {
874
1004
  const { duration = TIMINGS.state.duration } = options;
875
- const progress = Animated9.useSharedValue(active ? 1 : 0);
876
- React26.useEffect(() => {
877
- progress.value = Animated9.withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard });
1005
+ const progress = Animated13.useSharedValue(active ? 1 : 0);
1006
+ React25.useEffect(() => {
1007
+ progress.value = Animated13.withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard });
878
1008
  }, [active, duration, progress]);
879
1009
  return progress;
880
1010
  }
@@ -883,8 +1013,8 @@ function useColorTransition(active, options = {}) {
883
1013
  var webInputResetStyle = reactNative.Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
884
1014
  function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
885
1015
  const { colors } = useTheme();
886
- const [focused, setFocused] = React26.useState(false);
887
- const [showPassword, setShowPassword] = React26.useState(false);
1016
+ const [focused, setFocused] = React25.useState(false);
1017
+ const [showPassword, setShowPassword] = React25.useState(false);
888
1018
  const focusProgress = useColorTransition(focused, {
889
1019
  duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
890
1020
  });
@@ -892,7 +1022,7 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
892
1022
  const isPassword = type === "password";
893
1023
  const effectiveSecure = isPassword ? !showPassword : secureTextEntry;
894
1024
  const effectivePrefix = prefixIcon ? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.foregroundMuted) : prefix;
895
- const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React26__default.default.createElement(
1025
+ const effectiveSuffix = isPassword && !suffix && !suffixIcon ? /* @__PURE__ */ React25__default.default.createElement(
896
1026
  reactNative.TouchableOpacity,
897
1027
  {
898
1028
  onPress: () => setShowPassword(!showPassword),
@@ -901,14 +1031,14 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
901
1031
  accessibilityRole: "button",
902
1032
  accessibilityLabel: showPassword ? "Hide password" : "Show password"
903
1033
  },
904
- /* @__PURE__ */ React26__default.default.createElement(vectorIcons.AntDesign, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.foregroundMuted })
1034
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: showPassword ? "eye" : "eye-invisible", size: 20, color: colors.foregroundMuted })
905
1035
  ) : suffixIcon ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted) : suffix;
906
- const borderAnimStyle = Animated9.useAnimatedStyle(() => ({
907
- borderColor: error ? colors.destructive : Animated9.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
908
- borderWidth: error ? 2 : Animated9.interpolate(focusProgress.value, [0, 1], [1, 2])
1036
+ const borderAnimStyle = Animated13.useAnimatedStyle(() => ({
1037
+ borderColor: error ? colors.destructive : Animated13.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
1038
+ borderWidth: error ? 2 : Animated13.interpolate(focusProgress.value, [0, 1], [1, 2])
909
1039
  }));
910
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles4.container, isDisabled && styles4.containerDisabled, containerStyle] }, label ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles4.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React26__default.default.createElement(
911
- Animated9__default.default.View,
1040
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles4.container, isDisabled && styles4.containerDisabled, containerStyle] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React25__default.default.createElement(
1041
+ Animated13__default.default.View,
912
1042
  {
913
1043
  style: [
914
1044
  styles4.inputWrapper,
@@ -916,9 +1046,9 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
916
1046
  inputWrapperStyle
917
1047
  ]
918
1048
  },
919
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles4.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
920
- effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles4.prefixText, { color: colors.foregroundMuted }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles4.prefixContainer }, effectivePrefix) : null,
921
- /* @__PURE__ */ React26__default.default.createElement(
1049
+ /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles4.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
1050
+ effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.prefixText, { color: colors.foregroundMuted }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles4.prefixContainer }, effectivePrefix) : null,
1051
+ /* @__PURE__ */ React25__default.default.createElement(
922
1052
  reactNative.TextInput,
923
1053
  {
924
1054
  style: [
@@ -943,8 +1073,8 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
943
1073
  ...props
944
1074
  }
945
1075
  ),
946
- effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles4.suffixText, { color: colors.foregroundMuted }, suffixStyle], allowFontScaling: true }, effectiveSuffix) : /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles4.suffixContainer }, effectiveSuffix) : null
947
- ), error ? /* @__PURE__ */ React26__default.default.createElement(
1076
+ effectiveSuffix ? typeof effectiveSuffix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.suffixText, { color: colors.foregroundMuted }, suffixStyle], allowFontScaling: true }, effectiveSuffix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles4.suffixContainer }, effectiveSuffix) : null
1077
+ ), error ? /* @__PURE__ */ React25__default.default.createElement(
948
1078
  reactNative.Text,
949
1079
  {
950
1080
  style: [styles4.helperText, { color: colors.destructive }],
@@ -952,7 +1082,7 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
952
1082
  accessibilityLiveRegion: "polite"
953
1083
  },
954
1084
  error
955
- ) : null, !error && hint ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles4.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
1085
+ ) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
956
1086
  }
957
1087
  var styles4 = reactNative.StyleSheet.create({
958
1088
  container: {
@@ -1055,9 +1185,19 @@ function BadgeBase({ label, children, variant = "default", size = "md", icon, ic
1055
1185
  }[variant];
1056
1186
  const effectiveIcon = iconName ? renderIcon(iconName, sizeIconSize[size], iconColor ?? textColor) : icon;
1057
1187
  const content = children ?? label;
1058
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles5.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style] }, effectiveIcon, typeof content === "string" ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles5.label, { color: textColor }, sizeFontSize[size]], allowFontScaling: true }, content) : content);
1188
+ const a11yLabel = typeof content === "string" ? content : label;
1189
+ return /* @__PURE__ */ React25__default.default.createElement(
1190
+ reactNative.View,
1191
+ {
1192
+ style: [styles5.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style],
1193
+ accessibilityRole: "text",
1194
+ accessibilityLabel: a11yLabel
1195
+ },
1196
+ effectiveIcon,
1197
+ typeof content === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles5.label, { color: textColor }, sizeFontSize[size]], allowFontScaling: true }, content) : content
1198
+ );
1059
1199
  }
1060
- var Badge = React26__default.default.memo(BadgeBase);
1200
+ var Badge = React25__default.default.memo(BadgeBase);
1061
1201
  var styles5 = reactNative.StyleSheet.create({
1062
1202
  container: {
1063
1203
  borderRadius: 9999,
@@ -1071,12 +1211,6 @@ var styles5 = reactNative.StyleSheet.create({
1071
1211
  });
1072
1212
  function Card({ children, variant = "elevated", onPress, style, accessibilityLabel }) {
1073
1213
  const { colors } = useTheme();
1074
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
1075
- pressScale: PRESS_SCALE.card,
1076
- pressInSpring: SPRINGS.surfacePressIn,
1077
- pressOutSpring: SPRINGS.surfacePressOut,
1078
- disabled: !onPress
1079
- });
1080
1214
  const handlePress = () => {
1081
1215
  if (!onPress) return;
1082
1216
  impactLight();
@@ -1108,40 +1242,39 @@ function Card({ children, variant = "elevated", onPress, style, accessibilityLab
1108
1242
  elevation: 0
1109
1243
  }
1110
1244
  }[variant];
1111
- const cardContent = /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles6.card, variantStyle, style] }, children);
1245
+ const cardContent = /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.card, variantStyle, style] }, children);
1112
1246
  if (onPress) {
1113
- return /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: animatedStyle, ...hoverHandlers }, /* @__PURE__ */ React26__default.default.createElement(
1114
- reactNative.TouchableOpacity,
1247
+ return /* @__PURE__ */ React25__default.default.createElement(
1248
+ PressableCard,
1115
1249
  {
1116
1250
  onPress: handlePress,
1117
- onPressIn,
1118
- onPressOut,
1119
- activeOpacity: 1,
1251
+ rippleColor: "transparent",
1120
1252
  touchSoundDisabled: true,
1253
+ activateOnHover: true,
1121
1254
  accessibilityRole: "button",
1122
1255
  accessibilityLabel
1123
1256
  },
1124
1257
  cardContent
1125
- ));
1258
+ );
1126
1259
  }
1127
1260
  return cardContent;
1128
1261
  }
1129
1262
  function CardHeader({ children, style }) {
1130
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles6.header, style] }, children);
1263
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.header, style] }, children);
1131
1264
  }
1132
1265
  function CardTitle({ children, style }) {
1133
1266
  const { colors } = useTheme();
1134
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles6.title, { color: colors.foreground }, style], allowFontScaling: true }, children);
1267
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles6.title, { color: colors.foreground }, style], allowFontScaling: true }, children);
1135
1268
  }
1136
1269
  function CardDescription({ children, style }) {
1137
1270
  const { colors } = useTheme();
1138
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles6.description, { color: colors.foregroundSubtle }, style], allowFontScaling: true }, children);
1271
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles6.description, { color: colors.foregroundSubtle }, style], allowFontScaling: true }, children);
1139
1272
  }
1140
1273
  function CardContent({ children, style }) {
1141
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles6.content, style] }, children);
1274
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.content, style] }, children);
1142
1275
  }
1143
1276
  function CardFooter({ children, style }) {
1144
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles6.footer, style] }, children);
1277
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles6.footer, style] }, children);
1145
1278
  }
1146
1279
  var styles6 = reactNative.StyleSheet.create({
1147
1280
  card: {
@@ -1179,7 +1312,7 @@ var styles6 = reactNative.StyleSheet.create({
1179
1312
  });
1180
1313
  function Separator({ orientation = "horizontal", style }) {
1181
1314
  const { colors } = useTheme();
1182
- return /* @__PURE__ */ React26__default.default.createElement(
1315
+ return /* @__PURE__ */ React25__default.default.createElement(
1183
1316
  reactNative.View,
1184
1317
  {
1185
1318
  style: [
@@ -1212,17 +1345,38 @@ var labelFontSize = {
1212
1345
  };
1213
1346
  function Spinner({ size = "md", color, label, ...props }) {
1214
1347
  const { colors } = useTheme();
1348
+ const a11yLabel = label || "Loading";
1215
1349
  if (label) {
1216
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles8.wrapper }, /* @__PURE__ */ React26__default.default.createElement(reactNative.ActivityIndicator, { size: sizeMap2[size], color: color ?? colors.primary, ...props }), /* @__PURE__ */ React26__default.default.createElement(
1217
- reactNative.Text,
1350
+ return /* @__PURE__ */ React25__default.default.createElement(
1351
+ reactNative.View,
1218
1352
  {
1219
- style: [styles8.label, { color: colors.foregroundMuted, fontSize: labelFontSize[size] }],
1220
- allowFontScaling: true
1353
+ style: styles8.wrapper,
1354
+ accessibilityRole: "progressbar",
1355
+ accessibilityLabel: a11yLabel,
1356
+ accessibilityState: { busy: true }
1221
1357
  },
1222
- label
1223
- ));
1358
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.ActivityIndicator, { size: sizeMap2[size], color: color ?? colors.primary, ...props }),
1359
+ /* @__PURE__ */ React25__default.default.createElement(
1360
+ reactNative.Text,
1361
+ {
1362
+ style: [styles8.label, { color: colors.foregroundMuted, fontSize: labelFontSize[size] }],
1363
+ allowFontScaling: true
1364
+ },
1365
+ label
1366
+ )
1367
+ );
1224
1368
  }
1225
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.ActivityIndicator, { size: sizeMap2[size], color: color ?? colors.primary, ...props });
1369
+ return /* @__PURE__ */ React25__default.default.createElement(
1370
+ reactNative.ActivityIndicator,
1371
+ {
1372
+ size: sizeMap2[size],
1373
+ color: color ?? colors.primary,
1374
+ accessibilityRole: "progressbar",
1375
+ accessibilityLabel: a11yLabel,
1376
+ accessibilityState: { busy: true },
1377
+ ...props
1378
+ }
1379
+ );
1226
1380
  }
1227
1381
  var styles8 = reactNative.StyleSheet.create({
1228
1382
  wrapper: {
@@ -1243,23 +1397,23 @@ function Skeleton({
1243
1397
  style
1244
1398
  }) {
1245
1399
  const { colors, colorScheme } = useTheme();
1246
- const shimmer = Animated9.useSharedValue(0);
1247
- const [containerWidth, setContainerWidth] = React26.useState(300);
1400
+ const shimmer = Animated13.useSharedValue(0);
1401
+ const [containerWidth, setContainerWidth] = React25.useState(300);
1248
1402
  const shimmerHighlight = colorScheme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(255,255,255,0.7)";
1249
- React26.useEffect(() => {
1250
- shimmer.value = Animated9.withRepeat(
1251
- Animated9.withTiming(1, { duration: TIMINGS.shimmer.duration, easing: Animated9.Easing.linear }),
1403
+ React25.useEffect(() => {
1404
+ shimmer.value = Animated13.withRepeat(
1405
+ Animated13.withTiming(1, { duration: TIMINGS.shimmer.duration, easing: Animated13.Easing.linear }),
1252
1406
  -1,
1253
1407
  false
1254
1408
  );
1255
1409
  }, [shimmer]);
1256
- const shimmerStyle = Animated9.useAnimatedStyle(() => ({
1410
+ const shimmerStyle = Animated13.useAnimatedStyle(() => ({
1257
1411
  transform: [{ translateX: -containerWidth + shimmer.value * (containerWidth * 2) }]
1258
1412
  }));
1259
1413
  const resolvedWidth = preset === "circle" ? s(diameter) : preset === "text" ? "60%" : width;
1260
1414
  const resolvedHeight = preset === "circle" ? s(diameter) : preset === "text" ? 14 : height;
1261
1415
  const resolvedRadius = preset === "circle" ? 9999 : preset === "text" ? 4 : borderRadius;
1262
- return /* @__PURE__ */ React26__default.default.createElement(
1416
+ return /* @__PURE__ */ React25__default.default.createElement(
1263
1417
  reactNative.View,
1264
1418
  {
1265
1419
  style: [
@@ -1272,7 +1426,7 @@ function Skeleton({
1272
1426
  accessibilityLabel: "Loading",
1273
1427
  accessibilityState: { busy: true }
1274
1428
  },
1275
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [reactNative.StyleSheet.absoluteFill, shimmerStyle] }, /* @__PURE__ */ React26__default.default.createElement(
1429
+ /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [reactNative.StyleSheet.absoluteFill, shimmerStyle] }, /* @__PURE__ */ React25__default.default.createElement(
1276
1430
  expoLinearGradient.LinearGradient,
1277
1431
  {
1278
1432
  colors: ["transparent", shimmerHighlight, "transparent"],
@@ -1283,11 +1437,66 @@ function Skeleton({
1283
1437
  ))
1284
1438
  );
1285
1439
  }
1440
+ var aspectRatioMap = {
1441
+ "1:1": 1,
1442
+ "4:3": 3 / 4,
1443
+ "16:9": 9 / 16,
1444
+ "4:5": 5 / 4,
1445
+ "3:2": 2 / 3
1446
+ };
1447
+ function MediaCardSkeleton({ aspectRatio = "4:3", showSubtitle = true, style }) {
1448
+ const ratio = aspectRatioMap[aspectRatio];
1449
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "100%", height: void 0, style: skeletonStyles.fill, borderRadius: RADIUS.md }))), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: skeletonStyles.meta }, /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "70%", height: vs(14), borderRadius: RADIUS.xs }), showSubtitle ? /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "45%", height: vs(12), borderRadius: RADIUS.xs }) : null));
1450
+ }
1451
+ function ListItemSkeleton({ showAvatar = true, showSubtitle = true, style }) {
1452
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [skeletonStyles.row, style] }, showAvatar ? /* @__PURE__ */ React25__default.default.createElement(Skeleton, { preset: "circle", diameter: 40 }) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: skeletonStyles.rowText }, /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "60%", height: vs(14), borderRadius: RADIUS.xs }), showSubtitle ? /* @__PURE__ */ React25__default.default.createElement(Skeleton, { width: "40%", height: vs(12), borderRadius: RADIUS.xs }) : null));
1453
+ }
1454
+ function ListSkeleton({
1455
+ count = 6,
1456
+ columns = 1,
1457
+ gap = 12,
1458
+ aspectRatio = "4:3",
1459
+ showAvatar = true,
1460
+ style
1461
+ }) {
1462
+ if (columns <= 1) {
1463
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [{ gap: vs(gap) }, style] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React25__default.default.createElement(ListItemSkeleton, { key: i, showAvatar })));
1464
+ }
1465
+ const widthPct = `${100 / columns}%`;
1466
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [skeletonStyles.grid, { marginHorizontal: -s(gap) / 2 }, style] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: i, style: { width: widthPct, paddingHorizontal: s(gap) / 2, marginBottom: vs(gap) } }, /* @__PURE__ */ React25__default.default.createElement(MediaCardSkeleton, { aspectRatio }))));
1467
+ }
1468
+ Skeleton.MediaCard = MediaCardSkeleton;
1469
+ Skeleton.ListItem = ListItemSkeleton;
1470
+ Skeleton.List = ListSkeleton;
1286
1471
  var styles9 = reactNative.StyleSheet.create({
1287
1472
  base: {
1288
1473
  overflow: "hidden"
1289
1474
  }
1290
1475
  });
1476
+ var skeletonStyles = reactNative.StyleSheet.create({
1477
+ grid: {
1478
+ flexDirection: "row",
1479
+ flexWrap: "wrap"
1480
+ },
1481
+ fill: {
1482
+ width: "100%",
1483
+ height: "100%"
1484
+ },
1485
+ meta: {
1486
+ paddingTop: vs(8),
1487
+ gap: vs(6)
1488
+ },
1489
+ row: {
1490
+ flexDirection: "row",
1491
+ alignItems: "center",
1492
+ gap: s(12),
1493
+ paddingVertical: vs(8)
1494
+ },
1495
+ rowText: {
1496
+ flex: 1,
1497
+ gap: vs(6)
1498
+ }
1499
+ });
1291
1500
  var sizeMap3 = {
1292
1501
  sm: s(28),
1293
1502
  md: s(40),
@@ -1317,13 +1526,13 @@ function getInitials(fallback, fallbackText) {
1317
1526
  }
1318
1527
  function AvatarBase({ src, fallback, fallbackText, size = "md", status, style }) {
1319
1528
  const { colors } = useTheme();
1320
- const [imageError, setImageError] = React26.useState(false);
1529
+ const [imageError, setImageError] = React25.useState(false);
1321
1530
  const dimension = typeof size === "number" ? size : sizeMap3[size];
1322
1531
  const fontSize = typeof size === "number" ? size * 0.38 : fontSizeMap[size];
1323
1532
  const showFallback = !src || imageError;
1324
1533
  const statusSize = typeof size === "number" ? size * 0.25 : statusSizeMap[size];
1325
1534
  const statusColor = {
1326
- online: "#22c55e",
1535
+ online: colors.success,
1327
1536
  offline: "transparent",
1328
1537
  busy: colors.destructive,
1329
1538
  away: colors.warning
@@ -1335,38 +1544,48 @@ function AvatarBase({ src, fallback, fallbackText, size = "md", status, style })
1335
1544
  backgroundColor: colors.surface,
1336
1545
  overflow: "hidden"
1337
1546
  };
1338
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles10.wrapper, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles10.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React26__default.default.createElement(
1339
- reactNative.Image,
1340
- {
1341
- source: { uri: src },
1342
- style: { width: dimension, height: dimension },
1343
- onError: () => setImageError(true)
1344
- }
1345
- ) : /* @__PURE__ */ React26__default.default.createElement(
1346
- reactNative.Text,
1347
- {
1348
- style: [styles10.fallback, { color: colors.foregroundMuted, fontSize }],
1349
- allowFontScaling: true
1350
- },
1351
- getInitials(fallback, fallbackText)
1352
- )), status && /* @__PURE__ */ React26__default.default.createElement(
1547
+ const a11yLabel = fallbackText || fallback || "Avatar";
1548
+ return /* @__PURE__ */ React25__default.default.createElement(
1353
1549
  reactNative.View,
1354
1550
  {
1355
- style: [
1356
- styles10.statusDot,
1357
- {
1358
- width: statusSize,
1359
- height: statusSize,
1360
- borderRadius: statusSize / 2,
1361
- backgroundColor: statusColor[status],
1362
- borderWidth: status === "offline" ? 2 : 1.5,
1363
- borderColor: status === "offline" ? colors.border : colors.background
1364
- }
1365
- ]
1366
- }
1367
- ));
1551
+ style: [styles10.wrapper, style],
1552
+ accessibilityRole: "image",
1553
+ accessibilityLabel: a11yLabel
1554
+ },
1555
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles10.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React25__default.default.createElement(
1556
+ reactNative.Image,
1557
+ {
1558
+ source: { uri: src },
1559
+ style: { width: dimension, height: dimension },
1560
+ onError: () => setImageError(true)
1561
+ }
1562
+ ) : /* @__PURE__ */ React25__default.default.createElement(
1563
+ reactNative.Text,
1564
+ {
1565
+ style: [styles10.fallback, { color: colors.foregroundMuted, fontSize }],
1566
+ allowFontScaling: true
1567
+ },
1568
+ getInitials(fallback, fallbackText)
1569
+ )),
1570
+ status && /* @__PURE__ */ React25__default.default.createElement(
1571
+ reactNative.View,
1572
+ {
1573
+ style: [
1574
+ styles10.statusDot,
1575
+ {
1576
+ width: statusSize,
1577
+ height: statusSize,
1578
+ borderRadius: statusSize / 2,
1579
+ backgroundColor: statusColor[status],
1580
+ borderWidth: status === "offline" ? 2 : 1.5,
1581
+ borderColor: status === "offline" ? colors.border : colors.background
1582
+ }
1583
+ ]
1584
+ }
1585
+ )
1586
+ );
1368
1587
  }
1369
- var Avatar = React26__default.default.memo(AvatarBase);
1588
+ var Avatar = React25__default.default.memo(AvatarBase);
1370
1589
  var styles10 = reactNative.StyleSheet.create({
1371
1590
  wrapper: {
1372
1591
  alignSelf: "flex-start",
@@ -1391,24 +1610,27 @@ function AlertBanner({ title, description, variant = "default", icon, iconName,
1391
1610
  const accentColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : variant === "warning" ? colors.warning : colors.foreground;
1392
1611
  const bgColor = variant === "destructive" ? isDark ? "rgba(239, 83, 80, 0.15)" : "rgba(199, 40, 40, 0.10)" : variant === "success" ? isDark ? "rgba(46, 125, 82, 0.15)" : "rgba(26, 122, 69, 0.10)" : variant === "warning" ? isDark ? "rgba(245, 166, 35, 0.15)" : "rgba(154, 82, 0, 0.10)" : colors.surface;
1393
1612
  const borderColor = variant === "destructive" ? isDark ? "rgba(239, 83, 80, 0.30)" : "rgba(199, 40, 40, 0.25)" : variant === "success" ? isDark ? "rgba(46, 125, 82, 0.30)" : "rgba(26, 122, 69, 0.25)" : variant === "warning" ? isDark ? "rgba(245, 166, 35, 0.30)" : "rgba(154, 82, 0, 0.25)" : colors.border;
1394
- const defaultIcon = variant === "success" ? /* @__PURE__ */ React26__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: ms(16), color: accentColor }) : variant === "destructive" ? /* @__PURE__ */ React26__default.default.createElement(vectorIcons.MaterialIcons, { name: "error-outline", size: ms(17), color: accentColor }) : variant === "warning" ? /* @__PURE__ */ React26__default.default.createElement(vectorIcons.MaterialIcons, { name: "warning-amber", size: ms(17), color: accentColor }) : (
1613
+ const defaultIcon = variant === "success" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: ms(16), color: accentColor }) : variant === "destructive" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "error-outline", size: ms(17), color: accentColor }) : variant === "warning" ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.MaterialIcons, { name: "warning-amber", size: ms(17), color: accentColor }) : (
1395
1614
  // AUDIT FIX: default variant previously used colors.primary (near-black)
1396
1615
  // as the info icon tint — ambiguous and heavy. accentResolved gives it
1397
1616
  // a meaningful chromatic signal when an accent is defined.
1398
- /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: ms(16), color: accentColor })
1617
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "info-with-circle", size: ms(16), color: accentColor })
1399
1618
  );
1400
1619
  const effectiveIcon = iconName ? renderIcon(iconName, ms(16), iconColor ?? accentColor) : icon ?? defaultIcon;
1401
- return /* @__PURE__ */ React26__default.default.createElement(
1620
+ const a11yLabel = description ? `${title}. ${description}` : title;
1621
+ return /* @__PURE__ */ React25__default.default.createElement(
1402
1622
  reactNative.View,
1403
1623
  {
1404
1624
  style: [
1405
1625
  styles11.container,
1406
1626
  { backgroundColor: bgColor, borderWidth: 1, borderColor },
1407
1627
  style
1408
- ]
1628
+ ],
1629
+ accessibilityRole: "alert",
1630
+ accessibilityLabel: a11yLabel
1409
1631
  },
1410
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles11.iconSlot }, effectiveIcon),
1411
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles11.content }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles11.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles11.description, { color: colors.foreground, opacity: 0.85 }], allowFontScaling: true }, description) : null)
1632
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.iconSlot }, effectiveIcon),
1633
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.description, { color: colors.foreground, opacity: 0.85 }], allowFontScaling: true }, description) : null)
1412
1634
  );
1413
1635
  }
1414
1636
  var styles11 = reactNative.StyleSheet.create({
@@ -1439,17 +1661,17 @@ var styles11 = reactNative.StyleSheet.create({
1439
1661
  function Progress({ value = 0, max = 100, variant = "default", style, accessibilityLabel }) {
1440
1662
  const { colors } = useTheme();
1441
1663
  const percent = Math.min(Math.max(value / max * 100, 0), 100);
1442
- const [trackWidth, setTrackWidth] = React26.useState(0);
1443
- const animatedWidth = Animated9.useSharedValue(0);
1444
- React26.useEffect(() => {
1664
+ const [trackWidth, setTrackWidth] = React25.useState(0);
1665
+ const animatedWidth = Animated13.useSharedValue(0);
1666
+ React25.useEffect(() => {
1445
1667
  if (trackWidth === 0) return;
1446
- animatedWidth.value = Animated9.withSpring(percent / 100 * trackWidth, SPRINGS.glide);
1668
+ animatedWidth.value = Animated13.withSpring(percent / 100 * trackWidth, SPRINGS.glide);
1447
1669
  }, [percent, trackWidth, animatedWidth]);
1448
- const indicatorAnimatedStyle = Animated9.useAnimatedStyle(() => ({
1670
+ const indicatorAnimatedStyle = Animated13.useAnimatedStyle(() => ({
1449
1671
  width: animatedWidth.value
1450
1672
  }));
1451
1673
  const indicatorColor = variant === "success" ? colors.success : variant === "warning" ? colors.warning : variant === "destructive" ? colors.destructive : colors.primary;
1452
- return /* @__PURE__ */ React26__default.default.createElement(
1674
+ return /* @__PURE__ */ React25__default.default.createElement(
1453
1675
  reactNative.View,
1454
1676
  {
1455
1677
  style: [styles12.track, { backgroundColor: colors.surface }, style],
@@ -1458,8 +1680,8 @@ function Progress({ value = 0, max = 100, variant = "default", style, accessibil
1458
1680
  accessibilityLabel,
1459
1681
  accessibilityValue: { min: 0, max: 100, now: Math.round(percent) }
1460
1682
  },
1461
- /* @__PURE__ */ React26__default.default.createElement(
1462
- Animated9__default.default.View,
1683
+ /* @__PURE__ */ React25__default.default.createElement(
1684
+ Animated13__default.default.View,
1463
1685
  {
1464
1686
  style: [styles12.indicator, { backgroundColor: indicatorColor }, indicatorAnimatedStyle]
1465
1687
  }
@@ -1482,7 +1704,7 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, act
1482
1704
  const { colors } = useTheme();
1483
1705
  const isCompact = size === "compact";
1484
1706
  const effectiveIcon = iconName ? renderIcon(iconName, isCompact ? 32 : 48, iconColor ?? colors.foregroundMuted) : icon;
1485
- return /* @__PURE__ */ React26__default.default.createElement(
1707
+ return /* @__PURE__ */ React25__default.default.createElement(
1486
1708
  reactNative.View,
1487
1709
  {
1488
1710
  style: [
@@ -1492,7 +1714,7 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, act
1492
1714
  style
1493
1715
  ]
1494
1716
  },
1495
- effectiveIcon ? /* @__PURE__ */ React26__default.default.createElement(
1717
+ effectiveIcon ? /* @__PURE__ */ React25__default.default.createElement(
1496
1718
  reactNative.View,
1497
1719
  {
1498
1720
  style: [
@@ -1503,15 +1725,15 @@ function EmptyState({ icon, iconName, iconColor, title, description, action, act
1503
1725
  },
1504
1726
  effectiveIcon
1505
1727
  ) : null,
1506
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles13.textWrapper }, /* @__PURE__ */ React26__default.default.createElement(
1728
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles13.textWrapper }, /* @__PURE__ */ React25__default.default.createElement(
1507
1729
  reactNative.Text,
1508
1730
  {
1509
1731
  style: [styles13.title, isCompact && styles13.titleCompact, { color: colors.foreground }],
1510
1732
  allowFontScaling: true
1511
1733
  },
1512
1734
  title
1513
- ), description && !isCompact ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles13.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null),
1514
- !isCompact && (action ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles13.action }, action) : actionLabel && onAction ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles13.action }, /* @__PURE__ */ React26__default.default.createElement(Button, { label: actionLabel, variant: "primary", onPress: onAction })) : null)
1735
+ ), description && !isCompact ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles13.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null),
1736
+ !isCompact && (action ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles13.action }, action) : actionLabel && onAction ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles13.action }, /* @__PURE__ */ React25__default.default.createElement(Button, { label: actionLabel, variant: "primary", onPress: onAction })) : null)
1515
1737
  );
1516
1738
  }
1517
1739
  var styles13 = reactNative.StyleSheet.create({
@@ -1520,9 +1742,12 @@ var styles13 = reactNative.StyleSheet.create({
1520
1742
  justifyContent: "center",
1521
1743
  borderWidth: 1,
1522
1744
  borderStyle: "dashed",
1523
- borderRadius: ms(12)
1745
+ borderRadius: ms(12),
1746
+ paddingBottom: vs(32)
1747
+ },
1748
+ containerCompact: {
1749
+ paddingBottom: vs(20)
1524
1750
  },
1525
- containerCompact: {},
1526
1751
  iconWrapper: {
1527
1752
  width: s(80),
1528
1753
  height: s(80),
@@ -1561,7 +1786,6 @@ var styles13 = reactNative.StyleSheet.create({
1561
1786
  },
1562
1787
  action: {
1563
1788
  marginTop: vs(8),
1564
- marginBottom: s(32),
1565
1789
  paddingHorizontal: s(32)
1566
1790
  }
1567
1791
  });
@@ -1582,26 +1806,26 @@ function Textarea({
1582
1806
  ...props
1583
1807
  }) {
1584
1808
  const { colors } = useTheme();
1585
- const [focused, setFocused] = React26.useState(false);
1809
+ const [focused, setFocused] = React25.useState(false);
1586
1810
  const focusProgress = useColorTransition(focused, {
1587
1811
  duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration
1588
1812
  });
1589
1813
  const resolvedPrefixIcon = prefixIcon ? renderIcon(prefixIcon, ms(16), prefixIconColor ?? colors.foregroundMuted) : prefixIconNode;
1590
- const borderAnimStyle = Animated9.useAnimatedStyle(() => ({
1591
- borderColor: error ? colors.destructive : Animated9.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
1592
- borderWidth: error ? 2 : Animated9.interpolate(focusProgress.value, [0, 1], [1, 2])
1814
+ const borderAnimStyle = Animated13.useAnimatedStyle(() => ({
1815
+ borderColor: error ? colors.destructive : Animated13.interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
1816
+ borderWidth: error ? 2 : Animated13.interpolate(focusProgress.value, [0, 1], [1, 2])
1593
1817
  }));
1594
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles14.container, containerStyle] }, label ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles14.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React26__default.default.createElement(
1595
- Animated9__default.default.View,
1818
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles14.container, containerStyle] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles14.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, /* @__PURE__ */ React25__default.default.createElement(
1819
+ Animated13__default.default.View,
1596
1820
  {
1597
1821
  style: [
1598
1822
  styles14.inputWrapper,
1599
1823
  { backgroundColor: colors.background }
1600
1824
  ]
1601
1825
  },
1602
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles14.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
1603
- resolvedPrefixIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles14.prefixIcon }, resolvedPrefixIcon) : null,
1604
- /* @__PURE__ */ React26__default.default.createElement(
1826
+ /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles14.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
1827
+ resolvedPrefixIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles14.prefixIcon }, resolvedPrefixIcon) : null,
1828
+ /* @__PURE__ */ React25__default.default.createElement(
1605
1829
  reactNative.TextInput,
1606
1830
  {
1607
1831
  multiline: true,
@@ -1630,7 +1854,7 @@ function Textarea({
1630
1854
  ...props
1631
1855
  }
1632
1856
  )
1633
- ), error ? /* @__PURE__ */ React26__default.default.createElement(
1857
+ ), error ? /* @__PURE__ */ React25__default.default.createElement(
1634
1858
  reactNative.Text,
1635
1859
  {
1636
1860
  style: [styles14.helperText, { color: colors.destructive }],
@@ -1638,7 +1862,7 @@ function Textarea({
1638
1862
  accessibilityLiveRegion: "polite"
1639
1863
  },
1640
1864
  error
1641
- ) : null, !error && hint ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles14.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
1865
+ ) : null, !error && hint ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles14.helperText, { color: colors.foregroundMuted }], allowFontScaling: true }, hint) : null);
1642
1866
  }
1643
1867
  var styles14 = reactNative.StyleSheet.create({
1644
1868
  container: {
@@ -1690,41 +1914,39 @@ function Checkbox({
1690
1914
  accessibilityLabel
1691
1915
  }) {
1692
1916
  const { colors } = useTheme();
1693
- const { animatedStyle: scaleStyle, onPressIn, onPressOut } = usePressScale({
1694
- pressScale: PRESS_SCALE.button,
1695
- disabled
1696
- });
1697
- const progress = useColorTransition(checked);
1698
- const boxStyle = Animated9.useAnimatedStyle(() => ({
1699
- borderColor: Animated9.interpolateColor(progress.value, [0, 1], [colors.border, colors.primary]),
1700
- backgroundColor: Animated9.interpolateColor(progress.value, [0, 1], ["transparent", colors.primary])
1701
- }));
1702
- const checkStyle = Animated9.useAnimatedStyle(() => ({
1703
- opacity: Animated9.withTiming(checked ? 1 : 0, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
1704
- }));
1917
+ const handlePress = () => {
1918
+ selectionAsync();
1919
+ onCheckedChange?.(!checked);
1920
+ };
1705
1921
  return (
1706
1922
  // AUDIT FIX: opacity was applied only to the box, leaving the label at full
1707
1923
  // opacity when disabled — a contradictory visual signal. Now the entire row
1708
1924
  // dims uniformly so label and control communicate the same disabled state.
1709
- /* @__PURE__ */ React26__default.default.createElement(
1710
- reactNative.TouchableOpacity,
1925
+ /* @__PURE__ */ React25__default.default.createElement(
1926
+ PressableButton,
1711
1927
  {
1712
1928
  style: [styles15.row, disabled && styles15.rowDisabled, style],
1713
- onPress: () => {
1714
- selectionAsync();
1715
- onCheckedChange?.(!checked);
1716
- },
1717
- onPressIn,
1718
- onPressOut,
1719
- disabled,
1720
- activeOpacity: 1,
1929
+ onPress: handlePress,
1930
+ enabled: !disabled,
1931
+ rippleColor: "transparent",
1721
1932
  touchSoundDisabled: true,
1722
1933
  accessibilityRole: "checkbox",
1723
1934
  accessibilityLabel: accessibilityLabel ?? label,
1724
1935
  accessibilityState: { checked, disabled: !!disabled }
1725
1936
  },
1726
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: scaleStyle }, /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles15.box, boxStyle] }, /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: checkStyle }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles15.checkmark, { borderColor: colors.primaryForeground }] })))),
1727
- label ? /* @__PURE__ */ React26__default.default.createElement(
1937
+ /* @__PURE__ */ React25__default.default.createElement(
1938
+ reactNativeEase.EaseView,
1939
+ {
1940
+ style: styles15.box,
1941
+ animate: {
1942
+ borderColor: checked ? colors.primary : colors.border,
1943
+ backgroundColor: checked ? colors.primary : "transparent"
1944
+ },
1945
+ transition: COLOR_TRANSITION
1946
+ },
1947
+ /* @__PURE__ */ React25__default.default.createElement(reactNativeEase.EaseView, { animate: { opacity: checked ? 1 : 0 }, transition: OPACITY_TRANSITION }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles15.checkmark, { borderColor: colors.primaryForeground }] }))
1948
+ ),
1949
+ label ? /* @__PURE__ */ React25__default.default.createElement(
1728
1950
  reactNative.Text,
1729
1951
  {
1730
1952
  style: [styles15.label, { color: colors.foreground }],
@@ -1774,35 +1996,7 @@ var THUMB_TRAVEL = TRACK_WIDTH - THUMB_SIZE - THUMB_OFFSET * 2;
1774
1996
  var ICON_SIZE = s(13);
1775
1997
  function Switch({ checked = false, onCheckedChange, disabled, style, accessibilityLabel }) {
1776
1998
  const { colors } = useTheme();
1777
- const progress = Animated9.useSharedValue(checked ? 1 : 0);
1778
- React26.useEffect(() => {
1779
- progress.value = Animated9.withSpring(checked ? 1 : 0, SPRINGS.elastic);
1780
- }, [checked, progress]);
1781
- const thumbStyle = Animated9.useAnimatedStyle(() => ({
1782
- transform: [{ translateX: progress.value * THUMB_TRAVEL }]
1783
- }));
1784
- const trackStyle = Animated9.useAnimatedStyle(() => ({
1785
- backgroundColor: Animated9.interpolateColor(
1786
- progress.value,
1787
- [0, 1],
1788
- [colors.surfaceStrong, colors.primary]
1789
- )
1790
- }));
1791
- const trackBorderStyle = Animated9.useAnimatedStyle(() => ({
1792
- borderWidth: 1.5,
1793
- borderColor: Animated9.interpolateColor(
1794
- progress.value,
1795
- [0, 1],
1796
- [colors.border, "transparent"]
1797
- )
1798
- }));
1799
- const checkIconStyle = Animated9.useAnimatedStyle(() => ({
1800
- opacity: Animated9.withTiming(checked ? 1 : 0, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
1801
- }));
1802
- const crossIconStyle = Animated9.useAnimatedStyle(() => ({
1803
- opacity: Animated9.withTiming(checked ? 0 : 1, { duration: TIMINGS.state.duration, easing: EASINGS.standard })
1804
- }));
1805
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [{ opacity: disabled ? 0.45 : 1, alignSelf: "flex-start" }, style] }, /* @__PURE__ */ React26__default.default.createElement(
1999
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [{ opacity: disabled ? 0.45 : 1, alignSelf: "flex-start" }, style] }, /* @__PURE__ */ React25__default.default.createElement(
1806
2000
  reactNative.TouchableOpacity,
1807
2001
  {
1808
2002
  onPress: () => {
@@ -1817,14 +2011,33 @@ function Switch({ checked = false, onCheckedChange, disabled, style, accessibili
1817
2011
  accessibilityState: { checked, disabled: !!disabled },
1818
2012
  style: styles16.touchable
1819
2013
  },
1820
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles16.track, trackStyle] }, /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles16.trackBorder, trackBorderStyle], pointerEvents: "none" }), /* @__PURE__ */ React26__default.default.createElement(
1821
- Animated9__default.default.View,
2014
+ /* @__PURE__ */ React25__default.default.createElement(
2015
+ reactNativeEase.EaseView,
1822
2016
  {
1823
- style: [styles16.thumb, { backgroundColor: colors.primaryForeground }, thumbStyle]
2017
+ style: styles16.track,
2018
+ animate: { backgroundColor: checked ? colors.primary : colors.surfaceStrong },
2019
+ transition: COLOR_TRANSITION
1824
2020
  },
1825
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles16.iconWrapper, checkIconStyle] }, /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Feather, { name: "check", size: ICON_SIZE, color: colors.primary })),
1826
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles16.iconWrapper, crossIconStyle] }, /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Feather, { name: "x", size: ICON_SIZE, color: colors.foregroundMuted }))
1827
- ))
2021
+ /* @__PURE__ */ React25__default.default.createElement(
2022
+ reactNativeEase.EaseView,
2023
+ {
2024
+ style: [styles16.trackBorder, { borderWidth: 1.5 }],
2025
+ pointerEvents: "none",
2026
+ animate: { borderColor: checked ? "transparent" : colors.border },
2027
+ transition: COLOR_TRANSITION
2028
+ }
2029
+ ),
2030
+ /* @__PURE__ */ React25__default.default.createElement(
2031
+ reactNativeEase.EaseView,
2032
+ {
2033
+ style: [styles16.thumb, { backgroundColor: colors.primaryForeground }],
2034
+ animate: { translateX: checked ? THUMB_TRAVEL : 0 },
2035
+ transition: SPRING_ELASTIC
2036
+ },
2037
+ /* @__PURE__ */ React25__default.default.createElement(reactNativeEase.EaseView, { style: styles16.iconWrapper, animate: { opacity: checked ? 1 : 0 }, transition: OPACITY_TRANSITION }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "check", size: ICON_SIZE, color: colors.primary })),
2038
+ /* @__PURE__ */ React25__default.default.createElement(reactNativeEase.EaseView, { style: styles16.iconWrapper, animate: { opacity: checked ? 0 : 1 }, transition: OPACITY_TRANSITION }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: ICON_SIZE, color: colors.foregroundMuted }))
2039
+ )
2040
+ )
1828
2041
  ));
1829
2042
  }
1830
2043
  var styles16 = reactNative.StyleSheet.create({
@@ -1868,15 +2081,15 @@ function ToggleIcon({ pressed, iconName, activeIconName, icon, activeIcon, iconC
1868
2081
  return prop;
1869
2082
  };
1870
2083
  if (pressed) {
1871
- if (activeIconName) return /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, renderIcon(activeIconName, iconSize, activeIconColor ?? primaryColor));
2084
+ if (activeIconName) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, renderIcon(activeIconName, iconSize, activeIconColor ?? primaryColor));
1872
2085
  const active = renderProp(activeIcon);
1873
- if (active) return /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, active);
1874
- return /* @__PURE__ */ React26__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: iconSize, color: primaryColor });
2086
+ if (active) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, active);
2087
+ return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "check-circle", size: iconSize, color: primaryColor });
1875
2088
  }
1876
- if (iconName) return /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, renderIcon(iconName, iconSize, iconColor ?? mutedColor));
2089
+ if (iconName) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, renderIcon(iconName, iconSize, iconColor ?? mutedColor));
1877
2090
  const custom = renderProp(icon);
1878
- if (custom) return /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, custom);
1879
- return /* @__PURE__ */ React26__default.default.createElement(vectorIcons.FontAwesome5, { name: "circle", size: iconSize, color: mutedColor });
2091
+ if (custom) return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, custom);
2092
+ return /* @__PURE__ */ React25__default.default.createElement(vectorIcons.FontAwesome5, { name: "circle", size: iconSize, color: mutedColor });
1880
2093
  }
1881
2094
  var sizeStyles = {
1882
2095
  sm: { paddingHorizontal: s(12), paddingVertical: vs(8), minWidth: s(40), minHeight: vs(40) },
@@ -1898,75 +2111,61 @@ function Toggle({
1898
2111
  activeIconColor,
1899
2112
  disabled,
1900
2113
  style,
1901
- accessibilityLabel,
1902
- ...props
2114
+ accessibilityLabel
1903
2115
  }) {
1904
2116
  const { colors } = useTheme();
1905
- const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
1906
- pressScale: PRESS_SCALE.button,
1907
- disabled
1908
- });
1909
- const progress = useColorTransition(pressed);
1910
2117
  const inactiveBorder = variant === "outline" ? colors.border : "transparent";
1911
- const surfaceStyle = Animated9.useAnimatedStyle(() => ({
1912
- borderColor: Animated9.interpolateColor(progress.value, [0, 1], [inactiveBorder, colors.primary]),
1913
- backgroundColor: Animated9.interpolateColor(progress.value, [0, 1], ["transparent", colors.surfaceStrong])
1914
- }));
1915
- const textStyle = Animated9.useAnimatedStyle(() => ({
1916
- color: Animated9.interpolateColor(progress.value, [0, 1], [colors.foreground, colors.primary])
1917
- }));
1918
2118
  const iconSize = iconSizeMap2[size];
1919
- return /* @__PURE__ */ React26__default.default.createElement(
1920
- Animated9__default.default.View,
2119
+ const handlePress = () => {
2120
+ selectionAsync();
2121
+ onPressedChange?.(!pressed);
2122
+ };
2123
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [disabled && styles17.disabled, style] }, /* @__PURE__ */ React25__default.default.createElement(
2124
+ PressableButton,
1921
2125
  {
1922
- style: [scaleStyle, disabled && styles17.disabled, style],
1923
- ...hoverHandlers
2126
+ onPress: handlePress,
2127
+ enabled: !disabled,
2128
+ rippleColor: "transparent",
2129
+ touchSoundDisabled: true,
2130
+ activateOnHover: true,
2131
+ accessibilityRole: "button",
2132
+ accessibilityLabel: accessibilityLabel ?? label,
2133
+ accessibilityState: { selected: pressed, disabled: !!disabled }
1924
2134
  },
1925
- /* @__PURE__ */ React26__default.default.createElement(
1926
- reactNative.TouchableOpacity,
2135
+ /* @__PURE__ */ React25__default.default.createElement(
2136
+ reactNativeEase.EaseView,
1927
2137
  {
1928
- onPress: () => {
1929
- selectionAsync();
1930
- onPressedChange?.(!pressed);
2138
+ style: [styles17.base, sizeStyles[size], { borderWidth: 2 }],
2139
+ animate: {
2140
+ borderColor: pressed ? colors.primary : inactiveBorder,
2141
+ backgroundColor: pressed ? colors.surfaceStrong : "transparent"
1931
2142
  },
1932
- onPressIn,
1933
- onPressOut,
1934
- disabled,
1935
- activeOpacity: 1,
1936
- touchSoundDisabled: true,
1937
- accessibilityRole: "button",
1938
- accessibilityLabel: accessibilityLabel ?? label,
1939
- accessibilityState: { selected: pressed, disabled: !!disabled },
1940
- ...props
2143
+ transition: COLOR_TRANSITION
1941
2144
  },
1942
- /* @__PURE__ */ React26__default.default.createElement(
1943
- Animated9__default.default.View,
2145
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles17.inner }, /* @__PURE__ */ React25__default.default.createElement(
2146
+ ToggleIcon,
2147
+ {
2148
+ pressed,
2149
+ iconName,
2150
+ activeIconName,
2151
+ icon,
2152
+ activeIcon,
2153
+ iconColor,
2154
+ activeIconColor,
2155
+ iconSize,
2156
+ primaryColor: colors.primary,
2157
+ mutedColor: colors.foregroundMuted
2158
+ }
2159
+ ), label ? /* @__PURE__ */ React25__default.default.createElement(
2160
+ reactNative.Text,
1944
2161
  {
1945
- style: [
1946
- styles17.base,
1947
- sizeStyles[size],
1948
- { borderWidth: 2 },
1949
- surfaceStyle
1950
- ]
2162
+ style: [styles17.label, { color: pressed ? colors.primary : colors.foreground }],
2163
+ allowFontScaling: true
1951
2164
  },
1952
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles17.inner }, /* @__PURE__ */ React26__default.default.createElement(
1953
- ToggleIcon,
1954
- {
1955
- pressed,
1956
- iconName,
1957
- activeIconName,
1958
- icon,
1959
- activeIcon,
1960
- iconColor,
1961
- activeIconColor,
1962
- iconSize,
1963
- primaryColor: colors.primary,
1964
- mutedColor: colors.foregroundMuted
1965
- }
1966
- ), label ? /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.Text, { style: [styles17.label, textStyle], allowFontScaling: true }, label) : null)
1967
- )
2165
+ label
2166
+ ) : null)
1968
2167
  )
1969
- );
2168
+ ));
1970
2169
  }
1971
2170
  var styles17 = reactNative.StyleSheet.create({
1972
2171
  base: {
@@ -1986,6 +2185,49 @@ var styles17 = reactNative.StyleSheet.create({
1986
2185
  fontSize: ms(14)
1987
2186
  }
1988
2187
  });
2188
+ function useHover() {
2189
+ const [hovered, setHovered] = React25.useState(false);
2190
+ const onMouseEnter = React25.useCallback(() => setHovered(true), []);
2191
+ const onMouseLeave = React25.useCallback(() => setHovered(false), []);
2192
+ if (reactNative.Platform.OS !== "web") {
2193
+ return { hovered: false, hoverHandlers: {} };
2194
+ }
2195
+ return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
2196
+ }
2197
+
2198
+ // src/utils/usePressScale.ts
2199
+ function usePressScale({
2200
+ pressScale = PRESS_SCALE.button,
2201
+ hoverScale = 1.02,
2202
+ pressInSpring = SPRINGS.pressIn,
2203
+ pressOutSpring = SPRINGS.pressOut,
2204
+ disabled = false
2205
+ } = {}) {
2206
+ const scale2 = Animated13.useSharedValue(1);
2207
+ const { hovered, hoverHandlers } = useHover();
2208
+ const onPressIn = React25.useCallback(() => {
2209
+ if (disabled) return;
2210
+ scale2.value = Animated13.withSpring(pressScale, pressInSpring);
2211
+ }, [disabled, pressScale, pressInSpring, scale2]);
2212
+ const onPressOut = React25.useCallback(() => {
2213
+ if (disabled) return;
2214
+ scale2.value = Animated13.withSpring(1, pressOutSpring);
2215
+ }, [disabled, pressOutSpring, scale2]);
2216
+ const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
2217
+ const animatedStyle = Animated13.useAnimatedStyle(() => ({
2218
+ transform: [
2219
+ { scale: scale2.value * (hoverActive ? hoverScale : 1) }
2220
+ ]
2221
+ }));
2222
+ return {
2223
+ animatedStyle,
2224
+ onPressIn,
2225
+ onPressOut,
2226
+ hoverHandlers
2227
+ };
2228
+ }
2229
+
2230
+ // src/components/RadioGroup/RadioGroup.tsx
1989
2231
  function RadioItem({
1990
2232
  option,
1991
2233
  selected,
@@ -1996,23 +2238,11 @@ function RadioItem({
1996
2238
  pressScale: PRESS_SCALE.button,
1997
2239
  disabled: option.disabled
1998
2240
  });
1999
- const colorProgress = useColorTransition(selected);
2000
- const dotScale = Animated9.useSharedValue(selected ? 1 : 0);
2001
- React26.useEffect(() => {
2002
- dotScale.value = Animated9.withSpring(selected ? 1 : 0, SPRINGS.elastic);
2003
- }, [selected, dotScale]);
2004
- const radioStyle = Animated9.useAnimatedStyle(() => ({
2005
- borderColor: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.border, colors.primary])
2006
- }));
2007
- const dotStyle = Animated9.useAnimatedStyle(() => ({
2008
- transform: [{ scale: dotScale.value }],
2009
- opacity: dotScale.value
2010
- }));
2011
2241
  return (
2012
2242
  // AUDIT FIX: opacity was applied only to the radio circle, leaving the label
2013
2243
  // at full opacity when disabled. The whole row now dims uniformly so users
2014
2244
  // get a single, consistent disabled signal across the entire item.
2015
- /* @__PURE__ */ React26__default.default.createElement(
2245
+ /* @__PURE__ */ React25__default.default.createElement(
2016
2246
  reactNative.TouchableOpacity,
2017
2247
  {
2018
2248
  style: [styles18.row, option.disabled && styles18.rowDisabled],
@@ -2031,8 +2261,23 @@ function RadioItem({
2031
2261
  accessibilityLabel: option.label,
2032
2262
  accessibilityState: { checked: selected, disabled: !!option.disabled }
2033
2263
  },
2034
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: scaleStyle }, /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles18.radio, radioStyle] }, /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles18.dot, { backgroundColor: colors.primary }, dotStyle] }))),
2035
- /* @__PURE__ */ React26__default.default.createElement(
2264
+ /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: scaleStyle }, /* @__PURE__ */ React25__default.default.createElement(
2265
+ reactNativeEase.EaseView,
2266
+ {
2267
+ style: styles18.radio,
2268
+ animate: { borderColor: selected ? colors.primary : colors.border },
2269
+ transition: COLOR_TRANSITION
2270
+ },
2271
+ /* @__PURE__ */ React25__default.default.createElement(
2272
+ reactNativeEase.EaseView,
2273
+ {
2274
+ style: [styles18.dot, { backgroundColor: colors.primary }],
2275
+ animate: { scale: selected ? 1 : 0, opacity: selected ? 1 : 0 },
2276
+ transition: SPRING_ELASTIC
2277
+ }
2278
+ )
2279
+ )),
2280
+ /* @__PURE__ */ React25__default.default.createElement(
2036
2281
  reactNative.Text,
2037
2282
  {
2038
2283
  style: [styles18.label, { color: colors.foreground }],
@@ -2051,14 +2296,14 @@ function RadioGroup({
2051
2296
  style,
2052
2297
  accessibilityLabel
2053
2298
  }) {
2054
- return /* @__PURE__ */ React26__default.default.createElement(
2299
+ return /* @__PURE__ */ React25__default.default.createElement(
2055
2300
  reactNative.View,
2056
2301
  {
2057
2302
  style: [styles18.container, orientation === "horizontal" && styles18.horizontal, style],
2058
2303
  accessibilityRole: "radiogroup",
2059
2304
  accessibilityLabel
2060
2305
  },
2061
- options.map((option) => /* @__PURE__ */ React26__default.default.createElement(
2306
+ options.map((option) => /* @__PURE__ */ React25__default.default.createElement(
2062
2307
  RadioItem,
2063
2308
  {
2064
2309
  key: option.value,
@@ -2113,12 +2358,9 @@ function TabTrigger({
2113
2358
  variant
2114
2359
  }) {
2115
2360
  const { colors } = useTheme();
2116
- const { animatedStyle, onPressIn, onPressOut } = usePressScale({
2117
- pressScale: PRESS_SCALE.button
2118
- });
2119
2361
  const isUnderline = variant === "underline";
2120
- return /* @__PURE__ */ React26__default.default.createElement(
2121
- reactNative.TouchableOpacity,
2362
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { onLayout, style: styles19.triggerWrap }, /* @__PURE__ */ React25__default.default.createElement(
2363
+ PressableTab,
2122
2364
  {
2123
2365
  style: [
2124
2366
  styles19.trigger,
@@ -2126,16 +2368,13 @@ function TabTrigger({
2126
2368
  isUnderline && isActive && { borderBottomColor: colors.primary }
2127
2369
  ],
2128
2370
  onPress,
2129
- onPressIn,
2130
- onPressOut,
2131
- onLayout,
2132
- activeOpacity: 1,
2371
+ rippleColor: "transparent",
2133
2372
  touchSoundDisabled: true,
2134
2373
  accessibilityRole: "tab",
2135
2374
  accessibilityState: { selected: isActive },
2136
2375
  accessibilityLabel: tab.label
2137
2376
  },
2138
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: animatedStyle }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles19.triggerInner }, tab.icon ? typeof tab.icon === "function" ? tab.icon(isActive) : tab.icon : null, /* @__PURE__ */ React26__default.default.createElement(
2377
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles19.triggerInner }, tab.icon ? typeof tab.icon === "function" ? tab.icon(isActive) : tab.icon : null, /* @__PURE__ */ React25__default.default.createElement(
2139
2378
  reactNative.Text,
2140
2379
  {
2141
2380
  style: [
@@ -2149,29 +2388,29 @@ function TabTrigger({
2149
2388
  allowFontScaling: true
2150
2389
  },
2151
2390
  tab.label
2152
- )))
2153
- );
2391
+ ))
2392
+ ));
2154
2393
  }
2155
2394
  function Tabs({ tabs, variant = "pill", value, onValueChange, children, style }) {
2156
- const [internal, setInternal] = React26.useState(tabs[0]?.value ?? "");
2395
+ const [internal, setInternal] = React25.useState(tabs[0]?.value ?? "");
2157
2396
  const { colors } = useTheme();
2158
2397
  const active = value ?? internal;
2159
- const tabLayouts = React26.useRef({});
2160
- const pillX = Animated9.useSharedValue(0);
2161
- const pillWidth = Animated9.useSharedValue(0);
2162
- const initialised = React26.useRef(false);
2163
- const animatePill = React26.useCallback((tabValue, animate) => {
2398
+ const tabLayouts = React25.useRef({});
2399
+ const pillX = Animated13.useSharedValue(0);
2400
+ const pillWidth = Animated13.useSharedValue(0);
2401
+ const initialised = React25.useRef(false);
2402
+ const animatePill = React25.useCallback((tabValue, animate) => {
2164
2403
  const layout = tabLayouts.current[tabValue];
2165
2404
  if (!layout) return;
2166
2405
  if (animate) {
2167
- pillX.value = Animated9.withSpring(layout.x, SPRINGS.glide);
2168
- pillWidth.value = Animated9.withSpring(layout.width, SPRINGS.glide);
2406
+ pillX.value = Animated13.withSpring(layout.x, SPRINGS.glide);
2407
+ pillWidth.value = Animated13.withSpring(layout.width, SPRINGS.glide);
2169
2408
  } else {
2170
2409
  pillX.value = layout.x;
2171
2410
  pillWidth.value = layout.width;
2172
2411
  }
2173
2412
  }, [pillX, pillWidth]);
2174
- React26.useEffect(() => {
2413
+ React25.useEffect(() => {
2175
2414
  if (initialised.current) animatePill(active, true);
2176
2415
  }, [active, animatePill]);
2177
2416
  const handlePress = (v) => {
@@ -2179,11 +2418,11 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2179
2418
  if (!value) setInternal(v);
2180
2419
  onValueChange?.(v);
2181
2420
  };
2182
- const pillAnimatedStyle = Animated9.useAnimatedStyle(() => ({
2421
+ const pillAnimatedStyle = Animated13.useAnimatedStyle(() => ({
2183
2422
  transform: [{ translateX: pillX.value }],
2184
2423
  width: pillWidth.value
2185
2424
  }));
2186
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React26__default.default.createElement(
2425
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style }, /* @__PURE__ */ React25__default.default.createElement(
2187
2426
  reactNative.View,
2188
2427
  {
2189
2428
  style: [
@@ -2191,8 +2430,8 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2191
2430
  ],
2192
2431
  accessibilityRole: "tablist"
2193
2432
  },
2194
- variant === "pill" && /* @__PURE__ */ React26__default.default.createElement(
2195
- Animated9__default.default.View,
2433
+ variant === "pill" && /* @__PURE__ */ React25__default.default.createElement(
2434
+ Animated13__default.default.View,
2196
2435
  {
2197
2436
  style: [
2198
2437
  styles19.pill,
@@ -2213,7 +2452,7 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2213
2452
  ]
2214
2453
  }
2215
2454
  ),
2216
- tabs.map((tab) => /* @__PURE__ */ React26__default.default.createElement(
2455
+ tabs.map((tab) => /* @__PURE__ */ React25__default.default.createElement(
2217
2456
  TabTrigger,
2218
2457
  {
2219
2458
  key: tab.value,
@@ -2235,7 +2474,7 @@ function Tabs({ tabs, variant = "pill", value, onValueChange, children, style })
2235
2474
  }
2236
2475
  function TabsContent({ value, activeValue, children, style }) {
2237
2476
  if (value !== activeValue) return null;
2238
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style, accessibilityRole: "none" }, children);
2477
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style, accessibilityRole: "none" }, children);
2239
2478
  }
2240
2479
  var styles19 = reactNative.StyleSheet.create({
2241
2480
  list: {
@@ -2251,6 +2490,9 @@ var styles19 = reactNative.StyleSheet.create({
2251
2490
  borderBottomWidth: 1
2252
2491
  },
2253
2492
  pill: {},
2493
+ triggerWrap: {
2494
+ flex: 1
2495
+ },
2254
2496
  trigger: {
2255
2497
  flex: 1,
2256
2498
  paddingVertical: vs(7),
@@ -2261,7 +2503,7 @@ var styles19 = reactNative.StyleSheet.create({
2261
2503
  zIndex: 1
2262
2504
  },
2263
2505
  triggerUnderline: {
2264
- flex: 0,
2506
+ flex: 1,
2265
2507
  paddingVertical: vs(12),
2266
2508
  paddingHorizontal: s(16),
2267
2509
  borderRadius: 0,
@@ -2291,31 +2533,31 @@ function AccordionItemComponent({
2291
2533
  }) {
2292
2534
  const { colors } = useTheme();
2293
2535
  const resolvedIcon = item.iconName ? renderIcon(item.iconName, ms(16), item.iconColor ?? colors.foregroundMuted) : item.icon;
2294
- const isExpanded = Animated9.useSharedValue(isOpen);
2295
- const height = Animated9.useSharedValue(0);
2296
- React26__default.default.useEffect(() => {
2536
+ const isExpanded = Animated13.useSharedValue(isOpen);
2537
+ const height = Animated13.useSharedValue(0);
2538
+ React25__default.default.useEffect(() => {
2297
2539
  isExpanded.value = isOpen;
2298
2540
  }, [isOpen, isExpanded]);
2299
- const derivedHeight = Animated9.useDerivedValue(
2300
- () => Animated9.withTiming(height.value * Number(isExpanded.value), {
2541
+ const derivedHeight = Animated13.useDerivedValue(
2542
+ () => Animated13.withTiming(height.value * Number(isExpanded.value), {
2301
2543
  duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
2302
2544
  easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
2303
2545
  })
2304
2546
  );
2305
- const derivedRotation = Animated9.useDerivedValue(
2306
- () => Animated9.withTiming(isExpanded.value ? 1 : 0, {
2547
+ const derivedRotation = Animated13.useDerivedValue(
2548
+ () => Animated13.withTiming(isExpanded.value ? 1 : 0, {
2307
2549
  duration: isExpanded.value ? TIMINGS.expand.duration : TIMINGS.collapse.duration,
2308
2550
  easing: isExpanded.value ? EASINGS.expand : EASINGS.collapse
2309
2551
  })
2310
2552
  );
2311
- const bodyStyle = Animated9.useAnimatedStyle(() => ({
2553
+ const bodyStyle = Animated13.useAnimatedStyle(() => ({
2312
2554
  height: derivedHeight.value,
2313
2555
  overflow: "hidden"
2314
2556
  }));
2315
- const rotationStyle = Animated9.useAnimatedStyle(() => ({
2557
+ const rotationStyle = Animated13.useAnimatedStyle(() => ({
2316
2558
  transform: [{ rotate: `${derivedRotation.value * 180}deg` }]
2317
2559
  }));
2318
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles20.item, { backgroundColor: colors.card, borderColor: colors.border }] }, /* @__PURE__ */ React26__default.default.createElement(
2560
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles20.item, { backgroundColor: colors.card, borderColor: colors.border }] }, /* @__PURE__ */ React25__default.default.createElement(
2319
2561
  reactNative.Pressable,
2320
2562
  {
2321
2563
  style: ({ pressed }) => [styles20.trigger, { opacity: pressed ? 0.6 : 1 }],
@@ -2327,9 +2569,9 @@ function AccordionItemComponent({
2327
2569
  accessibilityState: { expanded: isOpen },
2328
2570
  accessibilityLabel: item.trigger
2329
2571
  },
2330
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles20.triggerContent }, resolvedIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles20.icon }, resolvedIcon) : null, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles20.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger)),
2331
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles20.chevron, rotationStyle] }, /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
2332
- ), /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React26__default.default.createElement(
2572
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles20.triggerContent }, resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles20.icon }, resolvedIcon) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger)),
2573
+ /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles20.chevron, rotationStyle] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
2574
+ ), /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React25__default.default.createElement(
2333
2575
  reactNative.View,
2334
2576
  {
2335
2577
  style: styles20.content,
@@ -2337,11 +2579,11 @@ function AccordionItemComponent({
2337
2579
  height.value = e.nativeEvent.layout.height;
2338
2580
  }
2339
2581
  },
2340
- item.content
2582
+ typeof item.content === "string" || typeof item.content === "number" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles20.contentText, { color: colors.foregroundMuted }], allowFontScaling: true }, item.content) : item.content
2341
2583
  )));
2342
2584
  }
2343
2585
  function Accordion({ items, type = "single", defaultValue, style }) {
2344
- const [openValues, setOpenValues] = React26.useState(() => {
2586
+ const [openValues, setOpenValues] = React25.useState(() => {
2345
2587
  if (!defaultValue) return [];
2346
2588
  return Array.isArray(defaultValue) ? defaultValue : [defaultValue];
2347
2589
  });
@@ -2354,7 +2596,7 @@ function Accordion({ items, type = "single", defaultValue, style }) {
2354
2596
  );
2355
2597
  }
2356
2598
  };
2357
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles20.list, style] }, items.map((item) => /* @__PURE__ */ React26__default.default.createElement(
2599
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles20.list, style] }, items.map((item) => /* @__PURE__ */ React25__default.default.createElement(
2358
2600
  AccordionItemComponent,
2359
2601
  {
2360
2602
  key: item.value,
@@ -2404,6 +2646,11 @@ var styles20 = reactNative.StyleSheet.create({
2404
2646
  paddingBottom: vs(12),
2405
2647
  position: "absolute",
2406
2648
  width: "100%"
2649
+ },
2650
+ contentText: {
2651
+ fontFamily: "Sohne-Regular",
2652
+ fontSize: ms(14),
2653
+ lineHeight: ms(20)
2407
2654
  }
2408
2655
  });
2409
2656
  function Slider({
@@ -2421,7 +2668,7 @@ function Slider({
2421
2668
  style
2422
2669
  }) {
2423
2670
  const { colors } = useTheme();
2424
- const lastSteppedValue = React26.useRef(value);
2671
+ const lastSteppedValue = React25.useRef(value);
2425
2672
  const handleValueChange = (v) => {
2426
2673
  if (step && v !== lastSteppedValue.current) {
2427
2674
  lastSteppedValue.current = v;
@@ -2429,7 +2676,7 @@ function Slider({
2429
2676
  }
2430
2677
  onValueChange?.(v);
2431
2678
  };
2432
- return /* @__PURE__ */ React26__default.default.createElement(
2679
+ return /* @__PURE__ */ React25__default.default.createElement(
2433
2680
  reactNative.View,
2434
2681
  {
2435
2682
  style: [styles21.wrapper, style],
@@ -2442,8 +2689,8 @@ function Slider({
2442
2689
  text: formatValue2(value)
2443
2690
  }
2444
2691
  },
2445
- label || showValue ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles21.header }, label ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles21.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, showValue ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles21.valueText, { color: colors.foregroundMuted }], allowFontScaling: true }, formatValue2(value)) : null) : null,
2446
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: disabled ? styles21.disabled : void 0 }, /* @__PURE__ */ React26__default.default.createElement(
2692
+ label || showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles21.header }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, showValue ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles21.valueText, { color: colors.foregroundMuted }], allowFontScaling: true }, formatValue2(value)) : null) : null,
2693
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled ? styles21.disabled : void 0 }, /* @__PURE__ */ React25__default.default.createElement(
2447
2694
  RNSlider__default.default,
2448
2695
  {
2449
2696
  value,
@@ -2491,14 +2738,14 @@ var SCREEN_HEIGHT = reactNative.Dimensions.get("window").height;
2491
2738
  var DEFAULT_MAX_HEIGHT = SCREEN_HEIGHT * 0.85;
2492
2739
  var isAndroid = reactNative.Platform.OS === "android";
2493
2740
  function SheetHeader({ children, style }) {
2494
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles22.header, style] }, children);
2741
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles22.header, style] }, children);
2495
2742
  }
2496
2743
  function SheetContent({ children, style }) {
2497
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles22.sheetContent, style] }, children);
2744
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles22.sheetContent, style] }, children);
2498
2745
  }
2499
2746
  function SheetFooter({ children, style }) {
2500
2747
  const { colors } = useTheme();
2501
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles22.sheetFooter, { backgroundColor: colors.card, borderTopColor: colors.border }, style] }, children);
2748
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles22.sheetFooter, { backgroundColor: colors.card, borderTopColor: colors.border }, style] }, children);
2502
2749
  }
2503
2750
  function Sheet({
2504
2751
  open,
@@ -2517,13 +2764,17 @@ function Sheet({
2517
2764
  enableBlurKeyboardOnGesture = true,
2518
2765
  android_keyboardInputMode = "adjustPan",
2519
2766
  footer,
2520
- snapPoints
2767
+ snapPoints,
2768
+ responsive = false,
2769
+ dialogMaxWidth = 480
2521
2770
  }) {
2522
2771
  const { colors } = useTheme();
2523
2772
  const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
2524
- const ref = React26.useRef(null);
2773
+ const { width: windowWidth } = reactNative.useWindowDimensions();
2774
+ const ref = React25.useRef(null);
2775
+ const asDialog = responsive && windowWidth >= BREAKPOINTS.wide;
2525
2776
  const effectiveKeyboardBehavior = keyboardBehavior ?? "interactive";
2526
- React26.useEffect(() => {
2777
+ React25.useEffect(() => {
2527
2778
  if (open) {
2528
2779
  impactMedium();
2529
2780
  ref.current?.present();
@@ -2531,7 +2782,7 @@ function Sheet({
2531
2782
  ref.current?.dismiss();
2532
2783
  }
2533
2784
  }, [open]);
2534
- const renderBackdrop = React26.useCallback((props) => /* @__PURE__ */ React26__default.default.createElement(
2785
+ const renderBackdrop = React25.useCallback((props) => /* @__PURE__ */ React25__default.default.createElement(
2535
2786
  bottomSheet.BottomSheetBackdrop,
2536
2787
  {
2537
2788
  ...props,
@@ -2540,16 +2791,16 @@ function Sheet({
2540
2791
  pressBehavior: "close"
2541
2792
  }
2542
2793
  ), []);
2543
- const childArray = React26__default.default.Children.toArray(children);
2544
- const customHeader = childArray.find((child) => React26__default.default.isValidElement(child) && child.type === SheetHeader);
2545
- const customContent = childArray.find((child) => React26__default.default.isValidElement(child) && child.type === SheetContent);
2546
- const customFooter = childArray.find((child) => React26__default.default.isValidElement(child) && child.type === SheetFooter);
2794
+ const childArray = React25__default.default.Children.toArray(children);
2795
+ const customHeader = childArray.find((child) => React25__default.default.isValidElement(child) && child.type === SheetHeader);
2796
+ const customContent = childArray.find((child) => React25__default.default.isValidElement(child) && child.type === SheetContent);
2797
+ const customFooter = childArray.find((child) => React25__default.default.isValidElement(child) && child.type === SheetFooter);
2547
2798
  const filteredChildren = customHeader || customContent || customFooter ? childArray.filter(
2548
- (child) => !React26__default.default.isValidElement(child) || child.type !== SheetHeader && child.type !== SheetContent && child.type !== SheetFooter
2799
+ (child) => !React25__default.default.isValidElement(child) || child.type !== SheetHeader && child.type !== SheetContent && child.type !== SheetFooter
2549
2800
  ) : children;
2550
2801
  const effectiveSubtitle = subtitle ?? description;
2551
2802
  const showHeader = !!(title || effectiveSubtitle || showCloseButton) && !customHeader;
2552
- const headerNode = customHeader ? customHeader : showHeader ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles22.header, accessibilityRole: "header" }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles22.headerRow }, title ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles22.title, { color: colors.foreground }], allowFontScaling: true }, title) : /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: { flex: 1 } }), showCloseButton ? /* @__PURE__ */ React26__default.default.createElement(
2803
+ const headerNode = customHeader ? customHeader : showHeader ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles22.header, accessibilityRole: "header" }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles22.headerRow }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles22.title, { color: colors.foreground }], allowFontScaling: true }, title) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { flex: 1 } }), showCloseButton ? /* @__PURE__ */ React25__default.default.createElement(
2553
2804
  reactNative.TouchableOpacity,
2554
2805
  {
2555
2806
  onPress: onClose,
@@ -2560,18 +2811,43 @@ function Sheet({
2560
2811
  accessibilityLabel: "Close",
2561
2812
  hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
2562
2813
  },
2563
- /* @__PURE__ */ React26__default.default.createElement(vectorIcons.AntDesign, { name: "close", size: ms(18), color: colors.foregroundMuted })
2564
- ) : null), effectiveSubtitle ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles22.subtitle, { color: colors.foregroundMuted }], allowFontScaling: true }, effectiveSubtitle) : null) : null;
2814
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.AntDesign, { name: "close", size: ms(18), color: colors.foregroundMuted })
2815
+ ) : null), effectiveSubtitle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles22.subtitle, { color: colors.foregroundMuted }], allowFontScaling: true }, effectiveSubtitle) : null) : null;
2565
2816
  const contentNode = customContent ? customContent : filteredChildren;
2566
2817
  const effectiveFooter = customFooter ? customFooter : footer;
2567
- const renderFooter = React26.useCallback((props) => {
2818
+ const renderFooter = React25.useCallback((props) => {
2568
2819
  if (!effectiveFooter) return null;
2569
- return /* @__PURE__ */ React26__default.default.createElement(bottomSheet.BottomSheetFooter, { ...props }, effectiveFooter);
2820
+ return /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetFooter, { ...props }, effectiveFooter);
2570
2821
  }, [effectiveFooter]);
2822
+ if (asDialog) {
2823
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: onClose }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Pressable, { style: styles22.dialogBackdrop, onPress: onClose, accessibilityRole: "button", accessibilityLabel: "Close" }, /* @__PURE__ */ React25__default.default.createElement(
2824
+ reactNative.Pressable,
2825
+ {
2826
+ style: [
2827
+ styles22.dialogCard,
2828
+ { backgroundColor: colors.card, maxWidth: dialogMaxWidth, maxHeight: SCREEN_HEIGHT * 0.85 }
2829
+ ],
2830
+ onPress: () => {
2831
+ }
2832
+ },
2833
+ headerNode,
2834
+ /* @__PURE__ */ React25__default.default.createElement(
2835
+ reactNative.ScrollView,
2836
+ {
2837
+ contentContainerStyle: [styles22.dialogContent, style],
2838
+ style: contentStyle,
2839
+ showsVerticalScrollIndicator: true,
2840
+ bounces: false
2841
+ },
2842
+ contentNode
2843
+ ),
2844
+ effectiveFooter
2845
+ )));
2846
+ }
2571
2847
  const useScroll = scrollable || !!maxHeight;
2572
2848
  const effectiveMaxHeight = maxHeight ?? DEFAULT_MAX_HEIGHT;
2573
2849
  const useDynamicSizing = !snapPoints;
2574
- return /* @__PURE__ */ React26__default.default.createElement(
2850
+ return /* @__PURE__ */ React25__default.default.createElement(
2575
2851
  bottomSheet.BottomSheetModal,
2576
2852
  {
2577
2853
  ref,
@@ -2590,7 +2866,7 @@ function Sheet({
2590
2866
  android_keyboardInputMode,
2591
2867
  enableBlurKeyboardOnGesture
2592
2868
  },
2593
- useScroll ? /* @__PURE__ */ React26__default.default.createElement(
2869
+ useScroll ? /* @__PURE__ */ React25__default.default.createElement(
2594
2870
  bottomSheet.BottomSheetScrollView,
2595
2871
  {
2596
2872
  contentContainerStyle: [
@@ -2604,7 +2880,7 @@ function Sheet({
2604
2880
  },
2605
2881
  headerNode,
2606
2882
  contentNode
2607
- ) : /* @__PURE__ */ React26__default.default.createElement(bottomSheet.BottomSheetView, { style: [styles22.content, contentStyle, style] }, headerNode, contentNode)
2883
+ ) : /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: [styles22.content, contentStyle, style] }, headerNode, contentNode)
2608
2884
  );
2609
2885
  }
2610
2886
  Sheet.Header = SheetHeader;
@@ -2663,6 +2939,24 @@ var styles22 = reactNative.StyleSheet.create({
2663
2939
  borderTopWidth: 1,
2664
2940
  flexDirection: "row",
2665
2941
  gap: s(12)
2942
+ },
2943
+ dialogBackdrop: {
2944
+ flex: 1,
2945
+ backgroundColor: "rgba(0,0,0,0.5)",
2946
+ alignItems: "center",
2947
+ justifyContent: "center",
2948
+ padding: s(24)
2949
+ },
2950
+ dialogCard: {
2951
+ width: "100%",
2952
+ borderRadius: RADIUS.lg,
2953
+ paddingTop: vs(16),
2954
+ overflow: "hidden",
2955
+ ...SHADOWS.xl
2956
+ },
2957
+ dialogContent: {
2958
+ paddingHorizontal: s(16),
2959
+ paddingBottom: vs(16)
2666
2960
  }
2667
2961
  });
2668
2962
  var isIOS = reactNative.Platform.OS === "ios";
@@ -2684,9 +2978,9 @@ function Select({
2684
2978
  pressScale: PRESS_SCALE.button,
2685
2979
  disabled
2686
2980
  });
2687
- const [pickerVisible, setPickerVisible] = React26.useState(false);
2688
- const [pendingValue, setPendingValue] = React26.useState(value);
2689
- const pickerRef = React26.useRef(null);
2981
+ const [pickerVisible, setPickerVisible] = React25.useState(false);
2982
+ const [pendingValue, setPendingValue] = React25.useState(value);
2983
+ const pickerRef = React25.useRef(null);
2690
2984
  const selected = options.find((o) => o.value === value);
2691
2985
  const handleOpen = () => {
2692
2986
  if (disabled) return;
@@ -2708,7 +3002,7 @@ function Select({
2708
3002
  }
2709
3003
  setPickerVisible(false);
2710
3004
  };
2711
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [animatedStyle, { opacity: disabled ? 0.45 : 1 }] }, /* @__PURE__ */ React26__default.default.createElement(
3005
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles23.container, style] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, !isWeb2 ? /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [animatedStyle, { opacity: disabled ? 0.45 : 1 }] }, /* @__PURE__ */ React25__default.default.createElement(
2712
3006
  reactNative.TouchableOpacity,
2713
3007
  {
2714
3008
  style: [
@@ -2728,7 +3022,7 @@ function Select({
2728
3022
  accessibilityValue: { text: selected?.label ?? placeholder },
2729
3023
  accessibilityState: { disabled: !!disabled, expanded: pickerVisible }
2730
3024
  },
2731
- /* @__PURE__ */ React26__default.default.createElement(
3025
+ /* @__PURE__ */ React25__default.default.createElement(
2732
3026
  reactNative.Text,
2733
3027
  {
2734
3028
  style: [
@@ -2740,8 +3034,8 @@ function Select({
2740
3034
  },
2741
3035
  selected?.label ?? placeholder
2742
3036
  ),
2743
- /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 20, color: colors.foregroundMuted })
2744
- )) : null, isIOS ? /* @__PURE__ */ React26__default.default.createElement(
3037
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 20, color: colors.foregroundMuted })
3038
+ )) : null, isIOS ? /* @__PURE__ */ React25__default.default.createElement(
2745
3039
  reactNative.Modal,
2746
3040
  {
2747
3041
  visible: pickerVisible,
@@ -2749,16 +3043,16 @@ function Select({
2749
3043
  animationType: "slide",
2750
3044
  onRequestClose: handleDismiss
2751
3045
  },
2752
- /* @__PURE__ */ React26__default.default.createElement(reactNative.TouchableOpacity, { style: styles23.iosBackdrop, activeOpacity: 1, onPress: handleDismiss }),
2753
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles23.iosSheet, { backgroundColor: colors.card }] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles23.iosToolbar, { borderBottomColor: colors.border }] }, label ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles23.iosToolbarTitle, { color: colors.foreground }], allowFontScaling: true }, label) : /* @__PURE__ */ React26__default.default.createElement(reactNative.View, null), /* @__PURE__ */ React26__default.default.createElement(reactNative.TouchableOpacity, { onPress: handleConfirm, style: styles23.iosDoneBtn, hitSlop: { top: 8, bottom: 8, left: 8, right: 8 } }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles23.iosDoneBtnText, { color: colors.primary }], allowFontScaling: true }, "Done"))), /* @__PURE__ */ React26__default.default.createElement(
3046
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { style: styles23.iosBackdrop, activeOpacity: 1, onPress: handleDismiss }),
3047
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles23.iosSheet, { backgroundColor: colors.card }] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles23.iosToolbar, { borderBottomColor: colors.border }] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.iosToolbarTitle, { color: colors.foreground }], allowFontScaling: true }, label) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, null), /* @__PURE__ */ React25__default.default.createElement(reactNative.TouchableOpacity, { onPress: handleConfirm, style: styles23.iosDoneBtn, hitSlop: { top: 8, bottom: 8, left: 8, right: 8 } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.iosDoneBtnText, { color: colors.primary }], allowFontScaling: true }, "Done"))), /* @__PURE__ */ React25__default.default.createElement(
2754
3048
  picker.Picker,
2755
3049
  {
2756
3050
  selectedValue: pendingValue ?? "",
2757
3051
  onValueChange: (val) => setPendingValue(val),
2758
3052
  itemStyle: { color: colors.foreground }
2759
3053
  },
2760
- !value ? /* @__PURE__ */ React26__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.foregroundMuted, enabled: false }) : null,
2761
- options.map((o) => /* @__PURE__ */ React26__default.default.createElement(
3054
+ !value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", color: colors.foregroundMuted, enabled: false }) : null,
3055
+ options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
2762
3056
  picker.Picker.Item,
2763
3057
  {
2764
3058
  key: o.value,
@@ -2769,7 +3063,7 @@ function Select({
2769
3063
  }
2770
3064
  ))
2771
3065
  ))
2772
- ) : null, isAndroid2 ? /* @__PURE__ */ React26__default.default.createElement(
3066
+ ) : null, isAndroid2 ? /* @__PURE__ */ React25__default.default.createElement(
2773
3067
  picker.Picker,
2774
3068
  {
2775
3069
  ref: pickerRef,
@@ -2785,8 +3079,8 @@ function Select({
2785
3079
  prompt: label,
2786
3080
  style: styles23.androidHiddenPicker
2787
3081
  },
2788
- !value ? /* @__PURE__ */ React26__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", enabled: false }) : null,
2789
- options.map((o) => /* @__PURE__ */ React26__default.default.createElement(
3082
+ !value ? /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", enabled: false }) : null,
3083
+ options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
2790
3084
  picker.Picker.Item,
2791
3085
  {
2792
3086
  key: o.value,
@@ -2795,7 +3089,7 @@ function Select({
2795
3089
  enabled: !o.disabled
2796
3090
  }
2797
3091
  ))
2798
- ) : null, isWeb2 ? /* @__PURE__ */ React26__default.default.createElement(
3092
+ ) : null, isWeb2 ? /* @__PURE__ */ React25__default.default.createElement(
2799
3093
  picker.Picker,
2800
3094
  {
2801
3095
  selectedValue: value ?? "",
@@ -2815,8 +3109,8 @@ function Select({
2815
3109
  }
2816
3110
  ]
2817
3111
  },
2818
- /* @__PURE__ */ React26__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", enabled: false }),
2819
- options.map((o) => /* @__PURE__ */ React26__default.default.createElement(
3112
+ /* @__PURE__ */ React25__default.default.createElement(picker.Picker.Item, { label: placeholder, value: "", enabled: false }),
3113
+ options.map((o) => /* @__PURE__ */ React25__default.default.createElement(
2820
3114
  picker.Picker.Item,
2821
3115
  {
2822
3116
  key: o.value,
@@ -2825,7 +3119,7 @@ function Select({
2825
3119
  enabled: !o.disabled
2826
3120
  }
2827
3121
  ))
2828
- ) : null, error ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles23.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null);
3122
+ ) : null, error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles23.helperText, { color: colors.destructive }], allowFontScaling: true }, error) : null);
2829
3123
  }
2830
3124
  var styles23 = reactNative.StyleSheet.create({
2831
3125
  container: {
@@ -2906,7 +3200,7 @@ function useToast() {
2906
3200
  function ToastProvider({ children }) {
2907
3201
  const { colorScheme } = useTheme();
2908
3202
  const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
2909
- return /* @__PURE__ */ React26__default.default.createElement(React26__default.default.Fragment, null, children, /* @__PURE__ */ React26__default.default.createElement(
3203
+ return /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, children, /* @__PURE__ */ React25__default.default.createElement(
2910
3204
  sonnerNative.Toaster,
2911
3205
  {
2912
3206
  theme: colorScheme,
@@ -2957,7 +3251,6 @@ function CurrencyInput({
2957
3251
  containerStyle,
2958
3252
  style
2959
3253
  }) {
2960
- const { colors } = useTheme();
2961
3254
  const handleChange = (text) => {
2962
3255
  const withoutPrefix = prefix && text.startsWith(prefix) ? text.slice(prefix.length) : text;
2963
3256
  const formatted = formatCurrency(withoutPrefix, thousandsSeparator);
@@ -2967,10 +3260,14 @@ function CurrencyInput({
2967
3260
  const raw = parseFloat(formatted.replace(separatorRegex, "") || "0");
2968
3261
  onChangeValue?.(isNaN(raw) ? 0 : raw);
2969
3262
  };
2970
- const inputStyle = size === "large" ? { fontFamily: "Sohne-Regular", fontSize: ms(36) } : { fontFamily: "Sohne-Regular" };
2971
- const dollarIcon = renderIcon("dollar-sign", size === "large" ? 24 : 16, colors.foregroundMuted);
3263
+ const isLarge = size === "large";
3264
+ const inputStyle = isLarge ? { fontFamily: "Sohne-Regular", fontSize: ms(36) } : { fontFamily: "Sohne-Regular" };
3265
+ const prefixStyle = {
3266
+ fontFamily: "Sohne-Regular",
3267
+ fontSize: isLarge ? ms(32) : ms(17)
3268
+ };
2972
3269
  const displayValue = value && prefix && value.startsWith(prefix) ? value.slice(prefix.length) : value;
2973
- return /* @__PURE__ */ React26__default.default.createElement(
3270
+ return /* @__PURE__ */ React25__default.default.createElement(
2974
3271
  Input,
2975
3272
  {
2976
3273
  value: displayValue,
@@ -2981,9 +3278,10 @@ function CurrencyInput({
2981
3278
  hint,
2982
3279
  placeholder: placeholder ?? "0",
2983
3280
  editable,
2984
- prefix: dollarIcon,
3281
+ prefix,
3282
+ prefixStyle,
2985
3283
  containerStyle,
2986
- inputWrapperStyle: size === "large" ? { paddingVertical: vs(16), minHeight: 72 } : void 0,
3284
+ inputWrapperStyle: isLarge ? { paddingVertical: vs(16), minHeight: 72 } : void 0,
2987
3285
  style: [inputStyle, style]
2988
3286
  }
2989
3287
  );
@@ -3018,7 +3316,7 @@ function CurrencyDisplayBase({ value, prefix = "$", showDecimals = false, textCo
3018
3316
  const baseFontSize = variant ? variantFontSize[variant] : ms(56);
3019
3317
  const fontSize = maxFontSize ?? baseFontSize;
3020
3318
  const letterSpacing = variant ? variantLetterSpacing[variant] : -2;
3021
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles24.container, style] }, /* @__PURE__ */ React26__default.default.createElement(
3319
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles24.container, style] }, /* @__PURE__ */ React25__default.default.createElement(
3022
3320
  reactNative.Text,
3023
3321
  {
3024
3322
  style: [styles24.amount, { color: textColor ?? colors.foreground, fontSize, letterSpacing }],
@@ -3030,7 +3328,7 @@ function CurrencyDisplayBase({ value, prefix = "$", showDecimals = false, textCo
3030
3328
  formatted
3031
3329
  ));
3032
3330
  }
3033
- var CurrencyDisplay = React26__default.default.memo(CurrencyDisplayBase);
3331
+ var CurrencyDisplay = React25__default.default.memo(CurrencyDisplayBase);
3034
3332
  var styles24 = reactNative.StyleSheet.create({
3035
3333
  container: {
3036
3334
  alignSelf: "flex-start"
@@ -3065,12 +3363,6 @@ function ListItemBase({
3065
3363
  accessibilityLabel
3066
3364
  }) {
3067
3365
  const { colors } = useTheme();
3068
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
3069
- pressScale: PRESS_SCALE.row,
3070
- pressInSpring: SPRINGS.surfacePressIn,
3071
- pressOutSpring: SPRINGS.surfacePressOut,
3072
- disabled: !onPress || disabled
3073
- });
3074
3366
  const handlePress = () => {
3075
3367
  selectionAsync();
3076
3368
  onPress?.();
@@ -3089,65 +3381,58 @@ function ListItemBase({
3089
3381
  elevation: 2
3090
3382
  } : {};
3091
3383
  const a11yLabel = accessibilityLabel ?? [title, subtitle, caption].filter(Boolean).join(". ");
3092
- return /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [animatedStyle, disabled && styles25.disabled], ...hoverHandlers }, /* @__PURE__ */ React26__default.default.createElement(
3093
- reactNative.TouchableOpacity,
3384
+ const content = /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, effectiveLeft ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.leftContainer }, effectiveLeft) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.content }, /* @__PURE__ */ React25__default.default.createElement(
3385
+ reactNative.Text,
3094
3386
  {
3095
- style: [styles25.container, cardStyle, style],
3096
- onPress: onPress ? handlePress : void 0,
3097
- onPressIn,
3098
- onPressOut,
3099
- disabled,
3100
- activeOpacity: 1,
3101
- touchSoundDisabled: true,
3102
- accessibilityRole: onPress ? "button" : void 0,
3103
- accessibilityLabel: onPress ? a11yLabel : void 0,
3104
- accessibilityState: onPress ? { disabled: !!disabled } : void 0
3387
+ style: [styles25.title, { color: colors.foreground }, titleStyle],
3388
+ numberOfLines: 2,
3389
+ allowFontScaling: true
3105
3390
  },
3106
- effectiveLeft ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles25.leftContainer }, effectiveLeft) : null,
3107
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles25.content }, /* @__PURE__ */ React26__default.default.createElement(
3108
- reactNative.Text,
3109
- {
3110
- style: [styles25.title, { color: colors.foreground }, titleStyle],
3111
- numberOfLines: 2,
3112
- allowFontScaling: true
3113
- },
3114
- title
3115
- ), subtitle ? /* @__PURE__ */ React26__default.default.createElement(
3116
- reactNative.Text,
3117
- {
3118
- style: [styles25.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
3119
- numberOfLines: 2,
3120
- allowFontScaling: true
3121
- },
3122
- subtitle
3123
- ) : null, caption ? /* @__PURE__ */ React26__default.default.createElement(
3124
- reactNative.Text,
3125
- {
3126
- style: [styles25.caption, { color: colors.foregroundMuted }, captionStyle],
3127
- numberOfLines: 1,
3128
- allowFontScaling: true
3129
- },
3130
- caption
3131
- ) : null),
3132
- effectiveRight !== void 0 ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof effectiveRight === "string" ? /* @__PURE__ */ React26__default.default.createElement(
3133
- reactNative.Text,
3391
+ title
3392
+ ), subtitle ? /* @__PURE__ */ React25__default.default.createElement(
3393
+ reactNative.Text,
3394
+ {
3395
+ style: [styles25.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
3396
+ numberOfLines: 2,
3397
+ allowFontScaling: true
3398
+ },
3399
+ subtitle
3400
+ ) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(
3401
+ reactNative.Text,
3402
+ {
3403
+ style: [styles25.caption, { color: colors.foregroundMuted }, captionStyle],
3404
+ numberOfLines: 1,
3405
+ allowFontScaling: true
3406
+ },
3407
+ caption
3408
+ ) : null), effectiveRight !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles25.rightContainer }, typeof effectiveRight === "string" ? /* @__PURE__ */ React25__default.default.createElement(
3409
+ reactNative.Text,
3410
+ {
3411
+ style: [styles25.rightText, { color: colors.foregroundMuted }],
3412
+ allowFontScaling: true
3413
+ },
3414
+ effectiveRight
3415
+ ) : effectiveRight) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.foregroundMuted }) : null);
3416
+ if (onPress) {
3417
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled && styles25.disabled }, /* @__PURE__ */ React25__default.default.createElement(
3418
+ PressableRow,
3134
3419
  {
3135
- style: [styles25.rightText, { color: colors.foregroundMuted }],
3136
- allowFontScaling: true
3420
+ style: [styles25.container, cardStyle, style],
3421
+ onPress: handlePress,
3422
+ enabled: !disabled,
3423
+ rippleColor: "transparent",
3424
+ touchSoundDisabled: true,
3425
+ activateOnHover: true,
3426
+ accessibilityRole: "button",
3427
+ accessibilityLabel: a11yLabel,
3428
+ accessibilityState: { disabled: !!disabled }
3137
3429
  },
3138
- effectiveRight
3139
- ) : effectiveRight) : showChevron ? /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "chevron-with-circle-right", size: 20, color: colors.foregroundMuted }) : null
3140
- ), showSeparator ? /* @__PURE__ */ React26__default.default.createElement(
3141
- reactNative.View,
3142
- {
3143
- style: [
3144
- styles25.separator,
3145
- { backgroundColor: colors.separator }
3146
- ]
3147
- }
3148
- ) : null);
3430
+ content
3431
+ ), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles25.separator, { backgroundColor: colors.separator }] }) : null);
3432
+ }
3433
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [disabled && styles25.disabled] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles25.container, cardStyle, style] }, content), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles25.separator, { backgroundColor: colors.separator }] }) : null);
3149
3434
  }
3150
- var ListItem = React26__default.default.memo(ListItemBase);
3435
+ var ListItem = React25__default.default.memo(ListItemBase);
3151
3436
  var styles25 = reactNative.StyleSheet.create({
3152
3437
  container: {
3153
3438
  flexDirection: "row",
@@ -3203,17 +3488,17 @@ var styles25 = reactNative.StyleSheet.create({
3203
3488
  });
3204
3489
  function ListGroup({ children, variant = "plain", style }) {
3205
3490
  const { colors } = useTheme();
3206
- const processedChildren = React26__default.default.Children.map(children, (child, index) => {
3207
- if (!React26__default.default.isValidElement(child)) return child;
3491
+ const processedChildren = React25__default.default.Children.map(children, (child, index) => {
3492
+ if (!React25__default.default.isValidElement(child)) return child;
3208
3493
  if (child.type === ListGroupHeader || child.type === ListGroupFooter) {
3209
3494
  return child;
3210
3495
  }
3211
3496
  const childProps = child.props;
3212
3497
  const isListItem = "title" in childProps;
3213
3498
  if (!isListItem) return child;
3214
- const isLast = index === React26__default.default.Children.count(children) - 1;
3499
+ const isLast = index === React25__default.default.Children.count(children) - 1;
3215
3500
  if (childProps["showSeparator"] === void 0 && !isLast) {
3216
- return React26__default.default.cloneElement(child, {
3501
+ return React25__default.default.cloneElement(child, {
3217
3502
  showSeparator: true
3218
3503
  });
3219
3504
  }
@@ -3231,21 +3516,21 @@ function ListGroup({ children, variant = "plain", style }) {
3231
3516
  elevation: 2,
3232
3517
  paddingVertical: vs(4)
3233
3518
  } : {};
3234
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles26.container, cardStyle, style] }, processedChildren);
3519
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.container, cardStyle, style] }, processedChildren);
3235
3520
  }
3236
3521
  function ListGroupHeader({ children, style }) {
3237
3522
  const { colors } = useTheme();
3238
3523
  if (typeof children === "string") {
3239
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles26.header, { borderBottomColor: colors.separator }, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles26.headerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3524
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.header, { borderBottomColor: colors.separator }, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles26.headerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3240
3525
  }
3241
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles26.header, { borderBottomColor: colors.separator }, style] }, children);
3526
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.header, { borderBottomColor: colors.separator }, style] }, children);
3242
3527
  }
3243
3528
  function ListGroupFooter({ children, style }) {
3244
3529
  const { colors } = useTheme();
3245
3530
  if (typeof children === "string") {
3246
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles26.footer, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles26.footerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3531
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.footer, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles26.footerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3247
3532
  }
3248
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles26.footer, style] }, children);
3533
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles26.footer, style] }, children);
3249
3534
  }
3250
3535
  ListGroup.Header = ListGroupHeader;
3251
3536
  ListGroup.Footer = ListGroupFooter;
@@ -3292,12 +3577,6 @@ function MenuItemBase({
3292
3577
  accessibilityLabel
3293
3578
  }) {
3294
3579
  const { colors } = useTheme();
3295
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
3296
- pressScale: PRESS_SCALE.row,
3297
- pressInSpring: SPRINGS.surfacePressIn,
3298
- pressOutSpring: SPRINGS.surfacePressOut,
3299
- disabled
3300
- });
3301
3580
  const handlePress = () => {
3302
3581
  selectionAsync();
3303
3582
  onPress();
@@ -3315,22 +3594,21 @@ function MenuItemBase({
3315
3594
  elevation: 2
3316
3595
  } : {};
3317
3596
  const a11yLabel = accessibilityLabel ?? (subtitle ? `${label}. ${subtitle}` : label);
3318
- return /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [animatedStyle, disabled && styles27.disabled], ...hoverHandlers }, /* @__PURE__ */ React26__default.default.createElement(
3319
- reactNative.TouchableOpacity,
3597
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: disabled && styles27.disabled }, /* @__PURE__ */ React25__default.default.createElement(
3598
+ PressableRow,
3320
3599
  {
3321
3600
  style: [styles27.container, cardStyle, style],
3322
3601
  onPress: handlePress,
3323
- onPressIn,
3324
- onPressOut,
3325
- disabled,
3326
- activeOpacity: 1,
3602
+ enabled: !disabled,
3603
+ rippleColor: "transparent",
3327
3604
  touchSoundDisabled: true,
3605
+ activateOnHover: true,
3328
3606
  accessibilityRole: "button",
3329
3607
  accessibilityLabel: a11yLabel,
3330
3608
  accessibilityState: { disabled }
3331
3609
  },
3332
- resolvedIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles27.iconContainer }, resolvedIcon) : null,
3333
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles27.labelContainer }, /* @__PURE__ */ React26__default.default.createElement(
3610
+ resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles27.iconContainer }, resolvedIcon) : null,
3611
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles27.labelContainer }, /* @__PURE__ */ React25__default.default.createElement(
3334
3612
  reactNative.Text,
3335
3613
  {
3336
3614
  style: [styles27.label, { color: colors.foreground }, labelStyle],
@@ -3338,7 +3616,7 @@ function MenuItemBase({
3338
3616
  allowFontScaling: true
3339
3617
  },
3340
3618
  label
3341
- ), subtitle ? /* @__PURE__ */ React26__default.default.createElement(
3619
+ ), subtitle ? /* @__PURE__ */ React25__default.default.createElement(
3342
3620
  reactNative.Text,
3343
3621
  {
3344
3622
  style: [styles27.subtitle, { color: colors.foregroundMuted }],
@@ -3347,7 +3625,7 @@ function MenuItemBase({
3347
3625
  },
3348
3626
  subtitle
3349
3627
  ) : null),
3350
- rightRender !== void 0 ? /* @__PURE__ */ React26__default.default.createElement(
3628
+ rightRender !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(
3351
3629
  reactNative.View,
3352
3630
  {
3353
3631
  style: styles27.rightContainer,
@@ -3356,18 +3634,10 @@ function MenuItemBase({
3356
3634
  }
3357
3635
  },
3358
3636
  rightRender
3359
- ) : showChevron ? /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "chevron-right", size: 18, color: colors.foregroundMuted }) : null
3360
- ), showSeparator ? /* @__PURE__ */ React26__default.default.createElement(
3361
- reactNative.View,
3362
- {
3363
- style: [
3364
- styles27.separator,
3365
- { backgroundColor: colors.separator }
3366
- ]
3367
- }
3368
- ) : null);
3637
+ ) : showChevron ? /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-right", size: 18, color: colors.foregroundMuted }) : null
3638
+ ), showSeparator ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles27.separator, { backgroundColor: colors.separator }] }) : null);
3369
3639
  }
3370
- var MenuItem = React26__default.default.memo(MenuItemBase);
3640
+ var MenuItem = React25__default.default.memo(MenuItemBase);
3371
3641
  var styles27 = reactNative.StyleSheet.create({
3372
3642
  container: {
3373
3643
  flexDirection: "row",
@@ -3411,17 +3681,17 @@ var styles27 = reactNative.StyleSheet.create({
3411
3681
  });
3412
3682
  function MenuGroup({ children, variant = "plain", style }) {
3413
3683
  const { colors } = useTheme();
3414
- const processedChildren = React26__default.default.Children.map(children, (child, index) => {
3415
- if (!React26__default.default.isValidElement(child)) return child;
3684
+ const processedChildren = React25__default.default.Children.map(children, (child, index) => {
3685
+ if (!React25__default.default.isValidElement(child)) return child;
3416
3686
  if (child.type === MenuGroupHeader || child.type === MenuGroupFooter) {
3417
3687
  return child;
3418
3688
  }
3419
3689
  const childProps = child.props;
3420
3690
  const isMenuItem = "onPress" in childProps;
3421
3691
  if (!isMenuItem) return child;
3422
- const isLast = index === React26__default.default.Children.count(children) - 1;
3692
+ const isLast = index === React25__default.default.Children.count(children) - 1;
3423
3693
  if (childProps["showSeparator"] === void 0 && !isLast) {
3424
- return React26__default.default.cloneElement(child, {
3694
+ return React25__default.default.cloneElement(child, {
3425
3695
  showSeparator: true
3426
3696
  });
3427
3697
  }
@@ -3439,21 +3709,21 @@ function MenuGroup({ children, variant = "plain", style }) {
3439
3709
  elevation: 2,
3440
3710
  paddingVertical: vs(4)
3441
3711
  } : {};
3442
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles28.container, cardStyle, style] }, processedChildren);
3712
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.container, cardStyle, style] }, processedChildren);
3443
3713
  }
3444
3714
  function MenuGroupHeader({ children, style }) {
3445
3715
  const { colors } = useTheme();
3446
3716
  if (typeof children === "string") {
3447
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles28.header, { borderBottomColor: colors.separator }, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles28.headerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3717
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.header, { borderBottomColor: colors.separator }, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.headerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3448
3718
  }
3449
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles28.header, { borderBottomColor: colors.separator }, style] }, children);
3719
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.header, { borderBottomColor: colors.separator }, style] }, children);
3450
3720
  }
3451
3721
  function MenuGroupFooter({ children, style }) {
3452
3722
  const { colors } = useTheme();
3453
3723
  if (typeof children === "string") {
3454
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles28.footer, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles28.footerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3724
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.footer, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles28.footerText, { color: colors.foregroundMuted }], allowFontScaling: true }, children));
3455
3725
  }
3456
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles28.footer, style] }, children);
3726
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles28.footer, style] }, children);
3457
3727
  }
3458
3728
  MenuGroup.Header = MenuGroupHeader;
3459
3729
  MenuGroup.Footer = MenuGroupFooter;
@@ -3485,38 +3755,44 @@ var styles28 = reactNative.StyleSheet.create({
3485
3755
  });
3486
3756
  function ChipBase({ label, selected = false, onPress, icon, iconName, style, accessibilityLabel }) {
3487
3757
  const { colors } = useTheme();
3488
- const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
3489
- pressScale: PRESS_SCALE.chip
3490
- });
3491
- const colorProgress = useColorTransition(selected);
3492
- const surfaceStyle = Animated9.useAnimatedStyle(() => ({
3493
- backgroundColor: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.surface, colors.primary]),
3494
- borderColor: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.border, colors.primary])
3495
- }));
3496
- const textStyle = Animated9.useAnimatedStyle(() => ({
3497
- color: Animated9.interpolateColor(colorProgress.value, [0, 1], [colors.foreground, colors.primaryForeground])
3498
- }));
3499
3758
  const handlePress = () => {
3500
3759
  selectionAsync();
3501
3760
  onPress?.();
3502
3761
  };
3503
3762
  const resolvedIcon = iconName ? renderIcon(iconName, ms(13), selected ? colors.primaryForeground : colors.foreground) : icon;
3504
- return /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles29.wrapper, scaleStyle, style], ...hoverHandlers }, /* @__PURE__ */ React26__default.default.createElement(
3505
- reactNative.TouchableOpacity,
3763
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles29.wrapper, style] }, /* @__PURE__ */ React25__default.default.createElement(
3764
+ PressableChip,
3506
3765
  {
3507
3766
  onPress: handlePress,
3508
- onPressIn,
3509
- onPressOut,
3510
- activeOpacity: 1,
3767
+ rippleColor: "transparent",
3511
3768
  touchSoundDisabled: true,
3512
3769
  accessibilityRole: "button",
3513
3770
  accessibilityLabel: accessibilityLabel ?? label,
3514
3771
  accessibilityState: { selected }
3515
3772
  },
3516
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles29.chip, surfaceStyle] }, resolvedIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles29.chipIcon }, resolvedIcon) : null, /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.Text, { style: [styles29.label, textStyle], allowFontScaling: true }, label))
3773
+ /* @__PURE__ */ React25__default.default.createElement(
3774
+ reactNativeEase.EaseView,
3775
+ {
3776
+ style: styles29.chip,
3777
+ animate: {
3778
+ backgroundColor: selected ? colors.primary : colors.surface,
3779
+ borderColor: selected ? colors.primary : colors.border
3780
+ },
3781
+ transition: COLOR_TRANSITION
3782
+ },
3783
+ resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles29.chipIcon }, resolvedIcon) : null,
3784
+ /* @__PURE__ */ React25__default.default.createElement(
3785
+ reactNative.Text,
3786
+ {
3787
+ style: [styles29.label, { color: selected ? colors.primaryForeground : colors.foreground }],
3788
+ allowFontScaling: true
3789
+ },
3790
+ label
3791
+ )
3792
+ )
3517
3793
  ));
3518
3794
  }
3519
- var Chip = React26__default.default.memo(ChipBase);
3795
+ var Chip = React25__default.default.memo(ChipBase);
3520
3796
  function ChipGroup({ options, value, onValueChange, multiSelect = false, style }) {
3521
3797
  const handlePress = (optionValue) => {
3522
3798
  if (!multiSelect) {
@@ -3524,20 +3800,20 @@ function ChipGroup({ options, value, onValueChange, multiSelect = false, style }
3524
3800
  return;
3525
3801
  }
3526
3802
  const currentArray = Array.isArray(value) ? value : value ? [value] : [];
3527
- const isSelected2 = currentArray.includes(optionValue);
3528
- const newArray = isSelected2 ? currentArray.filter((v) => v !== optionValue) : [...currentArray, optionValue];
3803
+ const isSelected3 = currentArray.includes(optionValue);
3804
+ const newArray = isSelected3 ? currentArray.filter((v) => v !== optionValue) : [...currentArray, optionValue];
3529
3805
  onValueChange?.(newArray);
3530
3806
  };
3531
- const isSelected = (optionValue) => {
3807
+ const isSelected2 = (optionValue) => {
3532
3808
  if (Array.isArray(value)) return value.includes(optionValue);
3533
3809
  return optionValue === value;
3534
3810
  };
3535
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles29.group, style] }, options.map((opt) => /* @__PURE__ */ React26__default.default.createElement(
3811
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles29.group, style] }, options.map((opt) => /* @__PURE__ */ React25__default.default.createElement(
3536
3812
  Chip,
3537
3813
  {
3538
3814
  key: opt.value,
3539
3815
  label: opt.label,
3540
- selected: isSelected(opt.value),
3816
+ selected: isSelected2(opt.value),
3541
3817
  onPress: opt.disabled ? void 0 : () => handlePress(opt.value),
3542
3818
  iconName: opt.iconName,
3543
3819
  style: opt.disabled ? styles29.chipDisabled : void 0,
@@ -3589,8 +3865,8 @@ function ConfirmDialog({
3589
3865
  onCancel
3590
3866
  }) {
3591
3867
  const { colors } = useTheme();
3592
- const ref = React26.useRef(null);
3593
- React26.useEffect(() => {
3868
+ const ref = React25.useRef(null);
3869
+ React25.useEffect(() => {
3594
3870
  if (visible) {
3595
3871
  impactMedium();
3596
3872
  ref.current?.present();
@@ -3598,7 +3874,7 @@ function ConfirmDialog({
3598
3874
  ref.current?.dismiss();
3599
3875
  }
3600
3876
  }, [visible]);
3601
- const renderBackdrop = (props) => /* @__PURE__ */ React26__default.default.createElement(
3877
+ const renderBackdrop = (props) => /* @__PURE__ */ React25__default.default.createElement(
3602
3878
  bottomSheet.BottomSheetBackdrop,
3603
3879
  {
3604
3880
  ...props,
@@ -3607,7 +3883,7 @@ function ConfirmDialog({
3607
3883
  pressBehavior: "close"
3608
3884
  }
3609
3885
  );
3610
- return /* @__PURE__ */ React26__default.default.createElement(
3886
+ return /* @__PURE__ */ React25__default.default.createElement(
3611
3887
  bottomSheet.BottomSheetModal,
3612
3888
  {
3613
3889
  ref,
@@ -3618,7 +3894,7 @@ function ConfirmDialog({
3618
3894
  handleIndicatorStyle: [styles30.handle, { backgroundColor: colors.border }],
3619
3895
  enablePanDownToClose: true
3620
3896
  },
3621
- /* @__PURE__ */ React26__default.default.createElement(bottomSheet.BottomSheetView, { style: styles30.content }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles30.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles30.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles30.actions }, /* @__PURE__ */ React26__default.default.createElement(
3897
+ /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetView, { style: styles30.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles30.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles30.actions }, /* @__PURE__ */ React25__default.default.createElement(
3622
3898
  Button,
3623
3899
  {
3624
3900
  label: confirmLabel,
@@ -3628,7 +3904,7 @@ function ConfirmDialog({
3628
3904
  notificationSuccess();
3629
3905
  onConfirm();
3630
3906
  },
3631
- icon: /* @__PURE__ */ React26__default.default.createElement(
3907
+ icon: /* @__PURE__ */ React25__default.default.createElement(
3632
3908
  vectorIcons.Feather,
3633
3909
  {
3634
3910
  name: confirmVariant === "destructive" ? "trash-2" : "check",
@@ -3637,7 +3913,7 @@ function ConfirmDialog({
3637
3913
  }
3638
3914
  )
3639
3915
  }
3640
- ), /* @__PURE__ */ React26__default.default.createElement(
3916
+ ), /* @__PURE__ */ React25__default.default.createElement(
3641
3917
  Button,
3642
3918
  {
3643
3919
  label: cancelLabel,
@@ -3647,7 +3923,7 @@ function ConfirmDialog({
3647
3923
  selectionAsync();
3648
3924
  onCancel();
3649
3925
  },
3650
- icon: /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Feather, { name: "x", size: 15, color: colors.foreground })
3926
+ icon: /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: 15, color: colors.foreground })
3651
3927
  }
3652
3928
  )))
3653
3929
  );
@@ -3685,9 +3961,9 @@ var styles30 = reactNative.StyleSheet.create({
3685
3961
  function LabelValueBase({ label, value, iconName, iconColor, style }) {
3686
3962
  const { colors } = useTheme();
3687
3963
  const resolvedIcon = iconName ? renderIcon(iconName, ms(14), iconColor ?? colors.foregroundMuted) : null;
3688
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles31.container, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles31.labelSide }, resolvedIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles31.icon }, resolvedIcon) : null, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles31.label, { color: colors.foregroundMuted }], allowFontScaling: true }, label)), typeof value === "string" ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles31.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
3964
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles31.container, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles31.labelSide }, resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles31.icon }, resolvedIcon) : null, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.label, { color: colors.foregroundMuted }], allowFontScaling: true }, label)), typeof value === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles31.value, { color: colors.foreground }], allowFontScaling: true }, value) : value);
3689
3965
  }
3690
- var LabelValue = React26__default.default.memo(LabelValueBase);
3966
+ var LabelValue = React25__default.default.memo(LabelValueBase);
3691
3967
  var styles31 = reactNative.StyleSheet.create({
3692
3968
  container: {
3693
3969
  flexDirection: "row",
@@ -3722,42 +3998,51 @@ var MONTH_NAMES = {
3722
3998
  pt: ["janeiro", "fevereiro", "mar\xE7o", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro"],
3723
3999
  fr: ["janvier", "f\xE9vrier", "mars", "avril", "mai", "juin", "juillet", "ao\xFBt", "septembre", "octobre", "novembre", "d\xE9cembre"]
3724
4000
  };
3725
- function MonthPicker({ value, onChange, locale = "en", formatLabel, style }) {
4001
+ function dateToMonthPickerValue(date) {
4002
+ return { month: date.getMonth() + 1, year: date.getFullYear() };
4003
+ }
4004
+ function monthPickerValueToDate(value) {
4005
+ return new Date(value.year, value.month - 1, 1);
4006
+ }
4007
+ var toIndex = (v) => v.year * 12 + (v.month - 1);
4008
+ var fromIndex = (i) => ({ year: Math.floor(i / 12), month: i % 12 + 1 });
4009
+ function MonthPicker({ value, onChange, minValue, maxValue, locale = "en", formatLabel, style }) {
3726
4010
  const { colors } = useTheme();
4011
+ const index = toIndex(value);
4012
+ const minIndex = minValue ? toIndex(minValue) : -Infinity;
4013
+ const maxIndex = maxValue ? toIndex(maxValue) : Infinity;
4014
+ const prevDisabled = index - 1 < minIndex;
4015
+ const nextDisabled = index + 1 > maxIndex;
3727
4016
  const getLabel = () => {
3728
4017
  if (formatLabel) return formatLabel(value);
3729
4018
  const names = MONTH_NAMES[locale] ?? MONTH_NAMES.en;
3730
4019
  return `${names[value.month - 1]} ${value.year}`;
3731
4020
  };
3732
4021
  const handlePrev = () => {
4022
+ if (prevDisabled) return;
3733
4023
  selectionAsync();
3734
- if (value.month === 1) {
3735
- onChange({ month: 12, year: value.year - 1 });
3736
- } else {
3737
- onChange({ month: value.month - 1, year: value.year });
3738
- }
4024
+ onChange(fromIndex(index - 1));
3739
4025
  };
3740
4026
  const handleNext = () => {
4027
+ if (nextDisabled) return;
3741
4028
  selectionAsync();
3742
- if (value.month === 12) {
3743
- onChange({ month: 1, year: value.year + 1 });
3744
- } else {
3745
- onChange({ month: value.month + 1, year: value.year });
3746
- }
4029
+ onChange(fromIndex(index + 1));
3747
4030
  };
3748
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles32.container, style], accessibilityRole: "adjustable", accessibilityLabel: getLabel() }, /* @__PURE__ */ React26__default.default.createElement(
4031
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles32.container, style], accessibilityRole: "adjustable", accessibilityLabel: getLabel() }, /* @__PURE__ */ React25__default.default.createElement(
3749
4032
  reactNative.TouchableOpacity,
3750
4033
  {
3751
- style: styles32.arrow,
4034
+ style: [styles32.arrow, prevDisabled && styles32.arrowDisabled],
3752
4035
  onPress: handlePrev,
4036
+ disabled: prevDisabled,
3753
4037
  activeOpacity: 0.6,
3754
4038
  touchSoundDisabled: true,
3755
4039
  accessibilityRole: "button",
3756
4040
  accessibilityLabel: "Previous month",
4041
+ accessibilityState: { disabled: prevDisabled },
3757
4042
  hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
3758
4043
  },
3759
- /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "chevron-left", size: 22, color: colors.foreground })
3760
- ), /* @__PURE__ */ React26__default.default.createElement(
4044
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-left", size: 22, color: colors.foreground })
4045
+ ), /* @__PURE__ */ React25__default.default.createElement(
3761
4046
  reactNative.Text,
3762
4047
  {
3763
4048
  style: [styles32.label, { color: colors.foreground }],
@@ -3765,18 +4050,20 @@ function MonthPicker({ value, onChange, locale = "en", formatLabel, style }) {
3765
4050
  accessibilityLiveRegion: "polite"
3766
4051
  },
3767
4052
  getLabel()
3768
- ), /* @__PURE__ */ React26__default.default.createElement(
4053
+ ), /* @__PURE__ */ React25__default.default.createElement(
3769
4054
  reactNative.TouchableOpacity,
3770
4055
  {
3771
- style: styles32.arrow,
4056
+ style: [styles32.arrow, nextDisabled && styles32.arrowDisabled],
3772
4057
  onPress: handleNext,
4058
+ disabled: nextDisabled,
3773
4059
  activeOpacity: 0.6,
3774
4060
  touchSoundDisabled: true,
3775
4061
  accessibilityRole: "button",
3776
4062
  accessibilityLabel: "Next month",
4063
+ accessibilityState: { disabled: nextDisabled },
3777
4064
  hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }
3778
4065
  },
3779
- /* @__PURE__ */ React26__default.default.createElement(vectorIcons.Entypo, { name: "chevron-right", size: 22, color: colors.foreground })
4066
+ /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Entypo, { name: "chevron-right", size: 22, color: colors.foreground })
3780
4067
  ));
3781
4068
  }
3782
4069
  var styles32 = reactNative.StyleSheet.create({
@@ -3791,6 +4078,9 @@ var styles32 = reactNative.StyleSheet.create({
3791
4078
  alignItems: "center",
3792
4079
  justifyContent: "center"
3793
4080
  },
4081
+ arrowDisabled: {
4082
+ opacity: 0.3
4083
+ },
3794
4084
  label: {
3795
4085
  fontFamily: "Sohne-Medium",
3796
4086
  fontSize: ms(17),
@@ -3799,7 +4089,7 @@ var styles32 = reactNative.StyleSheet.create({
3799
4089
  minWidth: s(160)
3800
4090
  }
3801
4091
  });
3802
- var aspectRatioMap = {
4092
+ var aspectRatioMap2 = {
3803
4093
  "1:1": 1,
3804
4094
  "4:3": 3 / 4,
3805
4095
  "16:9": 9 / 16,
@@ -3836,10 +4126,10 @@ function MediaCardBase({
3836
4126
  impactLight();
3837
4127
  onPress();
3838
4128
  };
3839
- const ratio = aspectRatioMap[aspectRatio];
4129
+ const ratio = aspectRatioMap2[aspectRatio];
3840
4130
  const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
3841
4131
  const a11yLabel = accessibilityLabel ?? [title, subtitle].filter(Boolean).join(". ");
3842
- const cardContent = /* @__PURE__ */ React26__default.default.createElement(
4132
+ const cardContent = /* @__PURE__ */ React25__default.default.createElement(
3843
4133
  reactNative.View,
3844
4134
  {
3845
4135
  style: [
@@ -3849,33 +4139,34 @@ function MediaCardBase({
3849
4139
  ],
3850
4140
  ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
3851
4141
  },
3852
- /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles33.imageContainer, imageStyle] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React26__default.default.createElement(
4142
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles33.imageContainer, imageStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React25__default.default.createElement(
3853
4143
  reactNative.Image,
3854
4144
  {
3855
4145
  source: imageSource,
3856
4146
  style: styles33.image,
3857
4147
  resizeMode: "cover"
3858
4148
  }
3859
- ) : /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles33.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles33.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React26__default.default.createElement(
4149
+ ) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles33.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles33.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React25__default.default.createElement(
3860
4150
  reactNative.TouchableOpacity,
3861
4151
  {
3862
4152
  style: [styles33.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
3863
- onPress: () => {
4153
+ onPress: (e) => {
4154
+ e?.stopPropagation?.();
3864
4155
  impactLight();
3865
4156
  onActionPress?.();
3866
4157
  },
3867
4158
  activeOpacity: 0.8,
3868
4159
  touchSoundDisabled: true,
3869
- accessibilityRole: "button",
4160
+ accessibilityRole: reactNative.Platform.OS === "web" && onPress ? void 0 : "button",
3870
4161
  accessibilityLabel: actionIconName ?? "action",
3871
4162
  accessibilityState: { selected: actionActive }
3872
4163
  },
3873
4164
  resolvedActionIcon
3874
4165
  )),
3875
- (title || subtitle || caption || footer) && /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles33.meta }, title ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles33.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles33.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles33.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
4166
+ (title || subtitle || caption || footer) && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles33.meta }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles33.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles33.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles33.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
3876
4167
  );
3877
4168
  if (onPress) {
3878
- return /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: animatedStyle }, /* @__PURE__ */ React26__default.default.createElement(
4169
+ return /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: animatedStyle }, /* @__PURE__ */ React25__default.default.createElement(
3879
4170
  reactNative.TouchableOpacity,
3880
4171
  {
3881
4172
  onPress: handlePress,
@@ -3891,7 +4182,7 @@ function MediaCardBase({
3891
4182
  }
3892
4183
  return cardContent;
3893
4184
  }
3894
- var MediaCard = React26__default.default.memo(MediaCardBase);
4185
+ var MediaCard = React25__default.default.memo(MediaCardBase);
3895
4186
  var styles33 = reactNative.StyleSheet.create({
3896
4187
  card: {
3897
4188
  borderRadius: RADIUS.md,
@@ -3949,7 +4240,7 @@ var styles33 = reactNative.StyleSheet.create({
3949
4240
  lineHeight: mvs(16)
3950
4241
  }
3951
4242
  });
3952
- var CategoryChip = React26__default.default.memo(function CategoryChip2({
4243
+ var CategoryChip = React25__default.default.memo(function CategoryChip2({
3953
4244
  item,
3954
4245
  selected,
3955
4246
  onSelect
@@ -3958,17 +4249,9 @@ var CategoryChip = React26__default.default.memo(function CategoryChip2({
3958
4249
  const { animatedStyle: scaleStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
3959
4250
  pressScale: PRESS_SCALE.chip
3960
4251
  });
3961
- const progress = useColorTransition(selected);
3962
- const surfaceStyle = Animated9.useAnimatedStyle(() => ({
3963
- backgroundColor: Animated9.interpolateColor(progress.value, [0, 1], [colors.surface, colors.primary]),
3964
- borderColor: Animated9.interpolateColor(progress.value, [0, 1], [colors.border, colors.primary])
3965
- }));
3966
- const textColorStyle = Animated9.useAnimatedStyle(() => ({
3967
- color: Animated9.interpolateColor(progress.value, [0, 1], [colors.foregroundSubtle, colors.primaryForeground])
3968
- }));
3969
4252
  const iconColor = selected ? colors.primaryForeground : colors.foregroundSubtle;
3970
4253
  const resolvedIcon = typeof item.icon === "string" ? renderIcon(item.icon, 16, iconColor) : item.icon ?? null;
3971
- return /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: scaleStyle, ...hoverHandlers }, /* @__PURE__ */ React26__default.default.createElement(
4254
+ return /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: scaleStyle, ...hoverHandlers }, /* @__PURE__ */ React25__default.default.createElement(
3972
4255
  reactNative.TouchableOpacity,
3973
4256
  {
3974
4257
  onPress: () => onSelect(item.value),
@@ -3980,7 +4263,27 @@ var CategoryChip = React26__default.default.memo(function CategoryChip2({
3980
4263
  accessibilityLabel: item.label,
3981
4264
  accessibilityState: { selected }
3982
4265
  },
3983
- /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.View, { style: [styles34.chip, surfaceStyle] }, resolvedIcon && /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles34.chipIcon }, resolvedIcon), /* @__PURE__ */ React26__default.default.createElement(Animated9__default.default.Text, { style: [styles34.chipLabel, textColorStyle], allowFontScaling: true }, item.label), item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles34.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles34.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99))))
4266
+ /* @__PURE__ */ React25__default.default.createElement(
4267
+ reactNativeEase.EaseView,
4268
+ {
4269
+ style: styles34.chip,
4270
+ animate: {
4271
+ backgroundColor: selected ? colors.primary : colors.surface,
4272
+ borderColor: selected ? colors.primary : colors.border
4273
+ },
4274
+ transition: COLOR_TRANSITION
4275
+ },
4276
+ resolvedIcon && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles34.chipIcon }, resolvedIcon),
4277
+ /* @__PURE__ */ React25__default.default.createElement(
4278
+ reactNative.Text,
4279
+ {
4280
+ style: [styles34.chipLabel, { color: selected ? colors.primaryForeground : colors.foregroundSubtle }],
4281
+ allowFontScaling: true
4282
+ },
4283
+ item.label
4284
+ ),
4285
+ item.badge !== void 0 && item.badge > 0 && /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles34.chipBadge, { backgroundColor: colors.primary }] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles34.chipBadgeText, { color: colors.primaryForeground }] }, Math.min(item.badge, 99)))
4286
+ )
3984
4287
  ));
3985
4288
  });
3986
4289
  function CategoryStrip({
@@ -3993,7 +4296,7 @@ function CategoryStrip({
3993
4296
  accessibilityLabel
3994
4297
  }) {
3995
4298
  const selected = Array.isArray(value) ? value : value ? [value] : [];
3996
- const handlePress = React26.useCallback(
4299
+ const handlePress = React25.useCallback(
3997
4300
  (v) => {
3998
4301
  selectionAsync();
3999
4302
  if (multiSelect) {
@@ -4006,7 +4309,7 @@ function CategoryStrip({
4006
4309
  },
4007
4310
  [multiSelect, value, onValueChange]
4008
4311
  );
4009
- return /* @__PURE__ */ React26__default.default.createElement(
4312
+ return /* @__PURE__ */ React25__default.default.createElement(
4010
4313
  reactNative.ScrollView,
4011
4314
  {
4012
4315
  horizontal: true,
@@ -4016,7 +4319,7 @@ function CategoryStrip({
4016
4319
  accessibilityRole: multiSelect ? void 0 : "radiogroup",
4017
4320
  accessibilityLabel
4018
4321
  },
4019
- categories.map((cat) => /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { key: cat.value, style: itemStyle }, /* @__PURE__ */ React26__default.default.createElement(
4322
+ categories.map((cat) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: cat.value, style: itemStyle }, /* @__PURE__ */ React25__default.default.createElement(
4020
4323
  CategoryChip,
4021
4324
  {
4022
4325
  item: cat,
@@ -4067,49 +4370,33 @@ var styles34 = reactNative.StyleSheet.create({
4067
4370
  lineHeight: 14
4068
4371
  }
4069
4372
  });
4070
- function Pressable2({
4373
+ function Pressable3({
4071
4374
  children,
4072
4375
  onPress,
4073
- pressScale = PRESS_SCALE.card,
4376
+ pressScale: _pressScale = PRESS_SCALE.card,
4074
4377
  haptics = true,
4075
4378
  style,
4076
4379
  disabled,
4077
- hoverScale = 1.02,
4078
- ...touchableProps
4380
+ hoverScale: _hoverScale = 1.02
4079
4381
  }) {
4080
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
4081
- pressScale,
4082
- hoverScale,
4083
- pressInSpring: SPRINGS.surfacePressIn,
4084
- pressOutSpring: SPRINGS.surfacePressOut,
4085
- disabled
4086
- });
4087
4382
  const handlePress = () => {
4088
4383
  if (disabled || !onPress) return;
4089
4384
  if (haptics) impactLight();
4090
4385
  onPress();
4091
4386
  };
4092
- return /* @__PURE__ */ React26__default.default.createElement(
4093
- Animated9__default.default.View,
4387
+ return /* @__PURE__ */ React25__default.default.createElement(
4388
+ PressableCard,
4094
4389
  {
4095
- style: [animatedStyle, style],
4096
- ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
4390
+ style,
4391
+ onPress: handlePress,
4392
+ enabled: !disabled,
4393
+ rippleColor: "transparent",
4394
+ touchSoundDisabled: true,
4395
+ activateOnHover: true,
4396
+ accessibilityRole: "button",
4397
+ accessibilityState: { disabled: !!disabled }
4097
4398
  },
4098
- /* @__PURE__ */ React26__default.default.createElement(
4099
- reactNative.TouchableOpacity,
4100
- {
4101
- onPress: handlePress,
4102
- onPressIn,
4103
- onPressOut,
4104
- activeOpacity: 1,
4105
- disabled,
4106
- touchSoundDisabled: true,
4107
- accessibilityRole: "button",
4108
- accessibilityState: { disabled: !!disabled },
4109
- ...touchableProps
4110
- },
4111
- children
4112
- )
4399
+ children
4113
4400
  );
4114
4401
  }
4115
4402
  var weightMap = {
@@ -4144,23 +4431,23 @@ function DetailRowBase({
4144
4431
  borderColor: "rgba(128,128,128,0.3)",
4145
4432
  marginHorizontal: s(4)
4146
4433
  };
4147
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles35.row, style] }, /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles35.labelSide }, resolvedLeftIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles35.icon }, resolvedLeftIcon) : null, typeof label === "string" ? /* @__PURE__ */ React26__default.default.createElement(
4434
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles35.row, style] }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.labelSide }, resolvedLeftIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.icon }, resolvedLeftIcon) : null, typeof label === "string" ? /* @__PURE__ */ React25__default.default.createElement(
4148
4435
  reactNative.Text,
4149
4436
  {
4150
4437
  style: [styles35.labelText, { color: colors.foregroundMuted, fontFamily: weightMap[labelWeight] }, labelStyle],
4151
4438
  allowFontScaling: true
4152
4439
  },
4153
4440
  label
4154
- ) : label), separatorStyle ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: separatorStyle }) : /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles35.spacer }), /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles35.valueSide }, typeof value === "string" ? /* @__PURE__ */ React26__default.default.createElement(
4441
+ ) : label), separatorStyle ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: separatorStyle }) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.spacer }), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.valueSide }, typeof value === "string" ? /* @__PURE__ */ React25__default.default.createElement(
4155
4442
  reactNative.Text,
4156
4443
  {
4157
4444
  style: [styles35.valueText, { color: valueColor ?? colors.foreground }, valueStyle],
4158
4445
  allowFontScaling: true
4159
4446
  },
4160
4447
  value
4161
- ) : value, resolvedRightIcon ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles35.icon }, resolvedRightIcon) : null));
4448
+ ) : value, resolvedRightIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles35.icon }, resolvedRightIcon) : null));
4162
4449
  }
4163
- var DetailRow = React26__default.default.memo(DetailRowBase);
4450
+ var DetailRow = React25__default.default.memo(DetailRowBase);
4164
4451
  var styles35 = reactNative.StyleSheet.create({
4165
4452
  row: {
4166
4453
  flexDirection: "row",
@@ -4197,7 +4484,7 @@ var styles35 = reactNative.StyleSheet.create({
4197
4484
  }
4198
4485
  });
4199
4486
  function Form({ children, style }) {
4200
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles36.form, style] }, children);
4487
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.form, style] }, children);
4201
4488
  }
4202
4489
  function FormField({
4203
4490
  children,
@@ -4209,14 +4496,14 @@ function FormField({
4209
4496
  errorStyle
4210
4497
  }) {
4211
4498
  const { colors } = useTheme();
4212
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles36.field, style] }, label ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles36.label, { color: colors.foreground }, labelStyle], allowFontScaling: true }, label, required ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: { color: colors.destructive } }, " *") : null) : null, children, error ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles36.error, { color: colors.destructive }, errorStyle], allowFontScaling: true }, error) : null);
4499
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.field, style] }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.label, { color: colors.foreground }, labelStyle], allowFontScaling: true }, label, required ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: { color: colors.destructive } }, " *") : null) : null, children, error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.error, { color: colors.destructive }, errorStyle], allowFontScaling: true }, error) : null);
4213
4500
  }
4214
4501
  function FormSection({ children, title, description, style }) {
4215
4502
  const { colors } = useTheme();
4216
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles36.section, style] }, title ? /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: styles36.sectionHeader }, /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles36.sectionTitle, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React26__default.default.createElement(reactNative.Text, { style: [styles36.sectionDescription, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null) : null, children);
4503
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.section, style] }, title ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles36.sectionHeader }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.sectionTitle, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles36.sectionDescription, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null) : null, children);
4217
4504
  }
4218
4505
  function FormFooter({ children, style }) {
4219
- return /* @__PURE__ */ React26__default.default.createElement(reactNative.View, { style: [styles36.footer, style] }, children);
4506
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles36.footer, style] }, children);
4220
4507
  }
4221
4508
  Form.Field = FormField;
4222
4509
  Form.Section = FormSection;
@@ -4265,7 +4552,7 @@ var defaultKeyExtractor = (item, index) => {
4265
4552
  return id !== void 0 ? String(id) : String(index);
4266
4553
  };
4267
4554
  function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, ref) {
4268
- const getItemLayout = React26.useCallback(
4555
+ const getItemLayout = React25.useCallback(
4269
4556
  (_data, index) => ({
4270
4557
  length: itemHeight ?? 0,
4271
4558
  offset: (itemHeight ?? 0) * index,
@@ -4273,7 +4560,7 @@ function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, re
4273
4560
  }),
4274
4561
  [itemHeight]
4275
4562
  );
4276
- return /* @__PURE__ */ React26__default.default.createElement(
4563
+ return /* @__PURE__ */ React25__default.default.createElement(
4277
4564
  reactNative.FlatList,
4278
4565
  {
4279
4566
  ref,
@@ -4285,7 +4572,899 @@ function VirtualListInner({ itemHeight, keyExtractor, renderItem, ...props }, re
4285
4572
  }
4286
4573
  );
4287
4574
  }
4288
- var VirtualList = React26__default.default.forwardRef(VirtualListInner);
4575
+ var VirtualList = React25__default.default.forwardRef(VirtualListInner);
4576
+ function RetrayProvider({ children, theme, colorScheme = "system" }) {
4577
+ return /* @__PURE__ */ React25__default.default.createElement(reactNativeSafeAreaContext.SafeAreaProvider, { initialMetrics: reactNativeSafeAreaContext.initialWindowMetrics }, /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles37.root }, /* @__PURE__ */ React25__default.default.createElement(ThemeProvider, { theme, colorScheme }, /* @__PURE__ */ React25__default.default.createElement(bottomSheet.BottomSheetModalProvider, null, /* @__PURE__ */ React25__default.default.createElement(ToastProvider, null, children)))));
4578
+ }
4579
+ var styles37 = reactNative.StyleSheet.create({
4580
+ root: { flex: 1 }
4581
+ });
4582
+ function DefaultErrorFallback({
4583
+ error,
4584
+ reset,
4585
+ title = "Something went wrong",
4586
+ message
4587
+ }) {
4588
+ const { colors } = useTheme();
4589
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles38.container, { backgroundColor: colors.background }], accessibilityRole: "alert" }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles38.iconCircle, { backgroundColor: colors.destructiveTint }] }, renderIcon("alert-triangle", ms(28), colors.destructive)), /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles38.title, { color: colors.foreground }], allowFontScaling: true }, title), /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles38.message, { color: colors.foregroundMuted }], allowFontScaling: true }, message ?? error.message ?? "An unexpected error occurred."), /* @__PURE__ */ React25__default.default.createElement(
4590
+ reactNative.TouchableOpacity,
4591
+ {
4592
+ style: [styles38.button, { backgroundColor: colors.primary }],
4593
+ onPress: () => {
4594
+ impactLight();
4595
+ reset();
4596
+ },
4597
+ activeOpacity: 0.85,
4598
+ touchSoundDisabled: true,
4599
+ accessibilityRole: "button",
4600
+ accessibilityLabel: "Try again"
4601
+ },
4602
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles38.buttonLabel, { color: colors.primaryForeground }], allowFontScaling: true }, "Try again")
4603
+ ));
4604
+ }
4605
+ var ErrorBoundary = class extends React25__default.default.Component {
4606
+ constructor() {
4607
+ super(...arguments);
4608
+ this.state = { error: null };
4609
+ this.reset = () => {
4610
+ this.setState({ error: null });
4611
+ };
4612
+ }
4613
+ static getDerivedStateFromError(error) {
4614
+ return { error };
4615
+ }
4616
+ componentDidCatch(error, info) {
4617
+ this.props.onError?.(error, info);
4618
+ }
4619
+ render() {
4620
+ const { error } = this.state;
4621
+ if (error) {
4622
+ const { fallback, title, message } = this.props;
4623
+ if (typeof fallback === "function") {
4624
+ return fallback({ error, reset: this.reset });
4625
+ }
4626
+ if (fallback !== void 0) {
4627
+ return fallback;
4628
+ }
4629
+ return /* @__PURE__ */ React25__default.default.createElement(DefaultErrorFallback, { error, reset: this.reset, title, message });
4630
+ }
4631
+ return this.props.children;
4632
+ }
4633
+ };
4634
+ var styles38 = reactNative.StyleSheet.create({
4635
+ container: {
4636
+ flex: 1,
4637
+ alignItems: "center",
4638
+ justifyContent: "center",
4639
+ paddingHorizontal: s(32),
4640
+ gap: vs(12)
4641
+ },
4642
+ iconCircle: {
4643
+ width: s(64),
4644
+ height: s(64),
4645
+ borderRadius: RADIUS.full,
4646
+ alignItems: "center",
4647
+ justifyContent: "center",
4648
+ marginBottom: vs(4)
4649
+ },
4650
+ title: {
4651
+ fontFamily: "Sohne-SemiBold",
4652
+ fontSize: ms(18),
4653
+ lineHeight: mvs(24),
4654
+ textAlign: "center"
4655
+ },
4656
+ message: {
4657
+ fontFamily: "Sohne-Regular",
4658
+ fontSize: ms(14),
4659
+ lineHeight: mvs(20),
4660
+ textAlign: "center"
4661
+ },
4662
+ button: {
4663
+ marginTop: vs(8),
4664
+ paddingHorizontal: s(20),
4665
+ paddingVertical: vs(10),
4666
+ borderRadius: RADIUS.md,
4667
+ minHeight: vs(44),
4668
+ alignItems: "center",
4669
+ justifyContent: "center"
4670
+ },
4671
+ buttonLabel: {
4672
+ fontFamily: "Sohne-Medium",
4673
+ fontSize: ms(15)
4674
+ }
4675
+ });
4676
+ function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }) {
4677
+ const progress = Animated13.useSharedValue(active ? 1 : 0);
4678
+ React25.useEffect(() => {
4679
+ progress.value = Animated13.withSpring(active ? 1 : 0, SPRINGS.glide);
4680
+ }, [active, progress]);
4681
+ const animatedStyle = Animated13.useAnimatedStyle(() => ({
4682
+ width: size + progress.value * size * 1.5,
4683
+ backgroundColor: Animated13.interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor])
4684
+ }));
4685
+ const dot = /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [{ height: size, borderRadius: size / 2 }, animatedStyle] });
4686
+ if (!onPress) return dot;
4687
+ const handlePress = () => {
4688
+ selectionAsync();
4689
+ onPress();
4690
+ };
4691
+ return /* @__PURE__ */ React25__default.default.createElement(
4692
+ reactNative.TouchableOpacity,
4693
+ {
4694
+ onPress: handlePress,
4695
+ activeOpacity: 0.7,
4696
+ touchSoundDisabled: true,
4697
+ accessibilityRole: "button",
4698
+ accessibilityLabel: `Page ${index + 1} of ${total}${active ? ", current page" : ""}`,
4699
+ hitSlop: { top: 8, bottom: 8, left: 4, right: 4 }
4700
+ },
4701
+ dot
4702
+ );
4703
+ }
4704
+ function PagerDots({
4705
+ count,
4706
+ activeIndex,
4707
+ onDotPress,
4708
+ showControls = false,
4709
+ dotSize = 8,
4710
+ spacing = 8,
4711
+ activeColor,
4712
+ inactiveColor,
4713
+ style
4714
+ }) {
4715
+ const { colors } = useTheme();
4716
+ const resolvedActive = activeColor ?? colors.primary;
4717
+ const resolvedInactive = inactiveColor ?? colors.border;
4718
+ const size = s(dotSize);
4719
+ const hasControls = showControls !== false;
4720
+ const canGoPrev = activeIndex > 0;
4721
+ const canGoNext = activeIndex < count - 1;
4722
+ const handlePrevious = () => {
4723
+ if (!canGoPrev) return;
4724
+ selectionAsync();
4725
+ if (typeof showControls === "object" && showControls.onPrevious) {
4726
+ showControls.onPrevious();
4727
+ } else if (onDotPress) {
4728
+ onDotPress(activeIndex - 1);
4729
+ }
4730
+ };
4731
+ const handleNext = () => {
4732
+ if (!canGoNext) return;
4733
+ selectionAsync();
4734
+ if (typeof showControls === "object" && showControls.onNext) {
4735
+ showControls.onNext();
4736
+ } else if (onDotPress) {
4737
+ onDotPress(activeIndex + 1);
4738
+ }
4739
+ };
4740
+ return /* @__PURE__ */ React25__default.default.createElement(
4741
+ reactNative.View,
4742
+ {
4743
+ style: [styles39.container, { gap: s(spacing) }, style],
4744
+ accessibilityRole: "adjustable",
4745
+ accessibilityLabel: `Page ${activeIndex + 1} of ${count}`
4746
+ },
4747
+ hasControls && /* @__PURE__ */ React25__default.default.createElement(
4748
+ reactNative.TouchableOpacity,
4749
+ {
4750
+ onPress: handlePrevious,
4751
+ disabled: !canGoPrev,
4752
+ activeOpacity: 0.7,
4753
+ touchSoundDisabled: true,
4754
+ accessibilityRole: "button",
4755
+ accessibilityLabel: "Previous page",
4756
+ hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
4757
+ style: [styles39.controlBtn, !canGoPrev && styles39.controlBtnDisabled]
4758
+ },
4759
+ renderIcon("chevron-left", s(18), canGoPrev ? colors.foreground : colors.foregroundMuted)
4760
+ ),
4761
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles39.dotsRow, { gap: s(spacing) }] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React25__default.default.createElement(
4762
+ Dot,
4763
+ {
4764
+ key: i,
4765
+ active: i === activeIndex,
4766
+ size,
4767
+ activeColor: resolvedActive,
4768
+ inactiveColor: resolvedInactive,
4769
+ index: i,
4770
+ total: count,
4771
+ onPress: onDotPress ? () => onDotPress(i) : void 0
4772
+ }
4773
+ ))),
4774
+ hasControls && /* @__PURE__ */ React25__default.default.createElement(
4775
+ reactNative.TouchableOpacity,
4776
+ {
4777
+ onPress: handleNext,
4778
+ disabled: !canGoNext,
4779
+ activeOpacity: 0.7,
4780
+ touchSoundDisabled: true,
4781
+ accessibilityRole: "button",
4782
+ accessibilityLabel: "Next page",
4783
+ hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
4784
+ style: [styles39.controlBtn, !canGoNext && styles39.controlBtnDisabled]
4785
+ },
4786
+ renderIcon("chevron-right", s(18), canGoNext ? colors.foreground : colors.foregroundMuted)
4787
+ )
4788
+ );
4789
+ }
4790
+ var styles39 = reactNative.StyleSheet.create({
4791
+ container: {
4792
+ flexDirection: "row",
4793
+ alignItems: "center",
4794
+ justifyContent: "center"
4795
+ },
4796
+ dotsRow: {
4797
+ flexDirection: "row",
4798
+ alignItems: "center"
4799
+ },
4800
+ controlBtn: {
4801
+ padding: s(4)
4802
+ },
4803
+ controlBtnDisabled: {
4804
+ opacity: 0.3
4805
+ }
4806
+ });
4807
+ function AppHeader({
4808
+ title,
4809
+ subtitle,
4810
+ onBack,
4811
+ backIconName = "chevron-left",
4812
+ left,
4813
+ right,
4814
+ titleAlign = "auto",
4815
+ bordered = true,
4816
+ withSafeArea = true,
4817
+ backgroundColor,
4818
+ style
4819
+ }) {
4820
+ const { colors } = useTheme();
4821
+ const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
4822
+ const { width } = reactNative.useWindowDimensions();
4823
+ const isWide = width >= BREAKPOINTS.wide;
4824
+ const centered = titleAlign === "center" || titleAlign === "auto" && isWide;
4825
+ const leftNode = left ?? (onBack ? /* @__PURE__ */ React25__default.default.createElement(
4826
+ IconButton,
4827
+ {
4828
+ iconName: backIconName,
4829
+ variant: "text",
4830
+ size: "md",
4831
+ onPress: onBack,
4832
+ accessibilityLabel: "Go back"
4833
+ }
4834
+ ) : null);
4835
+ const titleBlock = /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles40.titleBlock, centered && styles40.titleBlockCentered], pointerEvents: "none" }, title ? /* @__PURE__ */ React25__default.default.createElement(
4836
+ reactNative.Text,
4837
+ {
4838
+ style: [styles40.title, { color: colors.foreground }, centered && styles40.textCentered],
4839
+ numberOfLines: 1,
4840
+ allowFontScaling: true,
4841
+ accessibilityRole: "header"
4842
+ },
4843
+ title
4844
+ ) : null, subtitle ? /* @__PURE__ */ React25__default.default.createElement(
4845
+ reactNative.Text,
4846
+ {
4847
+ style: [styles40.subtitle, { color: colors.foregroundMuted }, centered && styles40.textCentered],
4848
+ numberOfLines: 1,
4849
+ allowFontScaling: true
4850
+ },
4851
+ subtitle
4852
+ ) : null);
4853
+ return /* @__PURE__ */ React25__default.default.createElement(
4854
+ reactNative.View,
4855
+ {
4856
+ style: [
4857
+ styles40.container,
4858
+ {
4859
+ backgroundColor: backgroundColor ?? colors.background,
4860
+ paddingTop: withSafeArea ? insets.top : 0,
4861
+ borderBottomWidth: bordered ? reactNative.StyleSheet.hairlineWidth : 0,
4862
+ borderBottomColor: colors.border
4863
+ },
4864
+ style
4865
+ ]
4866
+ },
4867
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles40.bar }, centered ? /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, titleBlock), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles40.side }, leftNode), /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles40.side, styles40.sideRight] }, right)) : /* @__PURE__ */ React25__default.default.createElement(React25__default.default.Fragment, null, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles40.side }, leftNode), titleBlock, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles40.side, styles40.sideRight] }, right)))
4868
+ );
4869
+ }
4870
+ var styles40 = reactNative.StyleSheet.create({
4871
+ container: {
4872
+ width: "100%"
4873
+ },
4874
+ bar: {
4875
+ minHeight: vs(48),
4876
+ flexDirection: "row",
4877
+ alignItems: "center",
4878
+ paddingHorizontal: s(8)
4879
+ },
4880
+ side: {
4881
+ minWidth: s(44),
4882
+ flexDirection: "row",
4883
+ alignItems: "center",
4884
+ justifyContent: "flex-start"
4885
+ },
4886
+ sideRight: {
4887
+ justifyContent: "flex-end"
4888
+ },
4889
+ titleBlock: {
4890
+ flex: 1,
4891
+ justifyContent: "center",
4892
+ paddingHorizontal: s(8),
4893
+ gap: vs(1)
4894
+ },
4895
+ titleBlockCentered: {
4896
+ alignItems: "center"
4897
+ },
4898
+ title: {
4899
+ fontFamily: "Sohne-SemiBold",
4900
+ fontSize: ms(18),
4901
+ lineHeight: mvs(24)
4902
+ },
4903
+ subtitle: {
4904
+ fontFamily: "Sohne-Regular",
4905
+ fontSize: ms(13),
4906
+ lineHeight: mvs(16)
4907
+ },
4908
+ textCentered: {
4909
+ textAlign: "center"
4910
+ }
4911
+ });
4912
+ function isSelected(value, candidate) {
4913
+ if (value == null) return false;
4914
+ return Array.isArray(value) ? value.includes(candidate) : value === candidate;
4915
+ }
4916
+ function Cell({ item, selected, width, onPress }) {
4917
+ const { colors } = useTheme();
4918
+ const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
4919
+ pressScale: PRESS_SCALE.chip,
4920
+ disabled: item.disabled
4921
+ });
4922
+ const iconColor = selected ? colors.primary : colors.foregroundSubtle;
4923
+ const iconNode = item.icon ?? (item.iconName ? renderIcon(item.iconName, ms(24), iconColor) : null);
4924
+ return /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [{ width }, animatedStyle] }, /* @__PURE__ */ React25__default.default.createElement(
4925
+ reactNative.TouchableOpacity,
4926
+ {
4927
+ onPress,
4928
+ onPressIn,
4929
+ onPressOut,
4930
+ disabled: item.disabled,
4931
+ activeOpacity: 1,
4932
+ touchSoundDisabled: true,
4933
+ accessibilityRole: "button",
4934
+ accessibilityState: { selected, disabled: item.disabled },
4935
+ accessibilityLabel: item.label ?? String(item.value),
4936
+ ...hoverHandlers,
4937
+ style: [
4938
+ styles41.cell,
4939
+ {
4940
+ backgroundColor: selected ? colors.primary + "14" : colors.surface,
4941
+ borderColor: selected ? colors.primary : "transparent"
4942
+ },
4943
+ item.disabled && styles41.cellDisabled
4944
+ ]
4945
+ },
4946
+ iconNode,
4947
+ item.label ? /* @__PURE__ */ React25__default.default.createElement(
4948
+ reactNative.Text,
4949
+ {
4950
+ style: [styles41.label, { color: selected ? colors.primary : colors.foreground }],
4951
+ numberOfLines: 1,
4952
+ allowFontScaling: true
4953
+ },
4954
+ item.label
4955
+ ) : null
4956
+ ));
4957
+ }
4958
+ function SelectableGrid({
4959
+ items,
4960
+ value,
4961
+ onChange,
4962
+ multiple = false,
4963
+ numColumns = 4,
4964
+ gap = 12,
4965
+ orientation = "grid",
4966
+ style
4967
+ }) {
4968
+ const [containerWidth, setContainerWidth] = React25.useState(0);
4969
+ const gapPx = s(gap);
4970
+ const cellWidth = containerWidth > 0 ? (containerWidth - gapPx * (numColumns - 1)) / numColumns - 0.5 : 0;
4971
+ const horizCellWidth = s(72);
4972
+ const handlePress = (item) => {
4973
+ if (item.disabled) return;
4974
+ selectionAsync();
4975
+ onChange(item.value);
4976
+ };
4977
+ if (orientation === "horizontal") {
4978
+ return /* @__PURE__ */ React25__default.default.createElement(
4979
+ reactNative.ScrollView,
4980
+ {
4981
+ horizontal: true,
4982
+ showsHorizontalScrollIndicator: false,
4983
+ contentContainerStyle: [styles41.horizontal, { gap: gapPx }, style],
4984
+ accessibilityRole: multiple ? void 0 : "radiogroup"
4985
+ },
4986
+ items.map((item) => /* @__PURE__ */ React25__default.default.createElement(
4987
+ Cell,
4988
+ {
4989
+ key: String(item.value),
4990
+ item,
4991
+ selected: isSelected(value, item.value),
4992
+ width: horizCellWidth,
4993
+ onPress: () => handlePress(item)
4994
+ }
4995
+ ))
4996
+ );
4997
+ }
4998
+ return /* @__PURE__ */ React25__default.default.createElement(
4999
+ reactNative.View,
5000
+ {
5001
+ style: [styles41.grid, { gap: gapPx }, style],
5002
+ onLayout: (e) => setContainerWidth(e.nativeEvent.layout.width),
5003
+ accessibilityRole: multiple ? void 0 : "radiogroup"
5004
+ },
5005
+ cellWidth > 0 ? items.map((item) => /* @__PURE__ */ React25__default.default.createElement(
5006
+ Cell,
5007
+ {
5008
+ key: String(item.value),
5009
+ item,
5010
+ selected: isSelected(value, item.value),
5011
+ width: cellWidth,
5012
+ onPress: () => handlePress(item)
5013
+ }
5014
+ )) : null
5015
+ );
5016
+ }
5017
+ var styles41 = reactNative.StyleSheet.create({
5018
+ grid: {
5019
+ flexDirection: "row",
5020
+ flexWrap: "wrap"
5021
+ },
5022
+ horizontal: {
5023
+ flexDirection: "row",
5024
+ paddingHorizontal: s(4)
5025
+ },
5026
+ cell: {
5027
+ flex: 1,
5028
+ borderRadius: RADIUS.md,
5029
+ borderWidth: 2,
5030
+ alignItems: "center",
5031
+ justifyContent: "center",
5032
+ gap: vs(4),
5033
+ paddingHorizontal: s(12),
5034
+ paddingVertical: vs(12)
5035
+ },
5036
+ cellDisabled: {
5037
+ opacity: 0.4
5038
+ },
5039
+ label: {
5040
+ fontFamily: "Sohne-Medium",
5041
+ fontSize: ms(12),
5042
+ lineHeight: mvs(15),
5043
+ textAlign: "center"
5044
+ }
5045
+ });
5046
+ var normalize = (f) => typeof f === "string" ? { label: f, included: true } : { included: true, ...f };
5047
+ function PricingCard({
5048
+ name,
5049
+ price,
5050
+ period,
5051
+ description,
5052
+ features = [],
5053
+ ctaLabel,
5054
+ onCtaPress,
5055
+ badge,
5056
+ highlighted = false,
5057
+ footnote,
5058
+ style
5059
+ }) {
5060
+ const { colors } = useTheme();
5061
+ return /* @__PURE__ */ React25__default.default.createElement(
5062
+ reactNative.View,
5063
+ {
5064
+ style: [
5065
+ styles42.card,
5066
+ {
5067
+ backgroundColor: colors.card,
5068
+ borderColor: highlighted ? colors.primary : colors.border,
5069
+ borderWidth: highlighted ? 2 : reactNative.StyleSheet.hairlineWidth
5070
+ },
5071
+ highlighted && SHADOWS.md,
5072
+ style
5073
+ ],
5074
+ accessibilityRole: "summary"
5075
+ },
5076
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles42.header }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.name, { color: colors.foreground }], allowFontScaling: true }, name), badge ? /* @__PURE__ */ React25__default.default.createElement(Badge, { label: badge, variant: highlighted ? "default" : "secondary", size: "sm" }) : null),
5077
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles42.priceRow }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.price, { color: colors.foreground }], allowFontScaling: true }, price), period ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.period, { color: colors.foregroundMuted }], allowFontScaling: true }, period) : null),
5078
+ description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null,
5079
+ features.length > 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles42.features }, features.map(normalize).map((f, i) => /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { key: i, style: styles42.featureRow }, renderIcon(
5080
+ f.included ? "check" : "minus",
5081
+ ms(16),
5082
+ f.included ? colors.success : colors.foregroundMuted
5083
+ ), /* @__PURE__ */ React25__default.default.createElement(
5084
+ reactNative.Text,
5085
+ {
5086
+ style: [
5087
+ styles42.featureLabel,
5088
+ { color: f.included ? colors.foreground : colors.foregroundMuted },
5089
+ !f.included && styles42.featureExcluded
5090
+ ],
5091
+ allowFontScaling: true
5092
+ },
5093
+ f.label
5094
+ )))) : null,
5095
+ ctaLabel ? /* @__PURE__ */ React25__default.default.createElement(
5096
+ Button,
5097
+ {
5098
+ label: ctaLabel,
5099
+ variant: highlighted ? "primary" : "secondary",
5100
+ fullWidth: true,
5101
+ onPress: onCtaPress,
5102
+ style: styles42.cta
5103
+ }
5104
+ ) : null,
5105
+ footnote ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles42.footnote, { color: colors.foregroundMuted }], allowFontScaling: true }, footnote) : null
5106
+ );
5107
+ }
5108
+ var styles42 = reactNative.StyleSheet.create({
5109
+ card: {
5110
+ borderRadius: RADIUS.md,
5111
+ padding: s(16),
5112
+ gap: vs(8)
5113
+ },
5114
+ header: {
5115
+ flexDirection: "row",
5116
+ alignItems: "center",
5117
+ justifyContent: "space-between",
5118
+ gap: s(8)
5119
+ },
5120
+ name: {
5121
+ fontFamily: "Sohne-SemiBold",
5122
+ fontSize: ms(16),
5123
+ lineHeight: mvs(20)
5124
+ },
5125
+ priceRow: {
5126
+ flexDirection: "row",
5127
+ alignItems: "baseline",
5128
+ gap: s(3)
5129
+ },
5130
+ price: {
5131
+ fontFamily: "Sohne-Bold",
5132
+ fontSize: ms(28),
5133
+ lineHeight: mvs(32),
5134
+ letterSpacing: -0.5
5135
+ },
5136
+ period: {
5137
+ fontFamily: "Sohne-Regular",
5138
+ fontSize: ms(13),
5139
+ lineHeight: mvs(16)
5140
+ },
5141
+ description: {
5142
+ fontFamily: "Sohne-Regular",
5143
+ fontSize: ms(13),
5144
+ lineHeight: mvs(18)
5145
+ },
5146
+ features: {
5147
+ gap: vs(6),
5148
+ marginTop: vs(2)
5149
+ },
5150
+ featureRow: {
5151
+ flexDirection: "row",
5152
+ alignItems: "center",
5153
+ gap: s(6)
5154
+ },
5155
+ featureLabel: {
5156
+ flex: 1,
5157
+ fontFamily: "Sohne-Regular",
5158
+ fontSize: ms(13),
5159
+ lineHeight: mvs(18)
5160
+ },
5161
+ featureExcluded: {
5162
+ textDecorationLine: "line-through"
5163
+ },
5164
+ cta: {
5165
+ marginTop: vs(2)
5166
+ },
5167
+ footnote: {
5168
+ fontFamily: "Sohne-Regular",
5169
+ fontSize: ms(11),
5170
+ lineHeight: mvs(14),
5171
+ textAlign: "center"
5172
+ }
5173
+ });
5174
+ function TabBar({
5175
+ items,
5176
+ activeKey,
5177
+ onTabPress,
5178
+ activeColor,
5179
+ inactiveColor,
5180
+ withSafeArea = true,
5181
+ style
5182
+ }) {
5183
+ const { colors } = useTheme();
5184
+ const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
5185
+ const resolvedActive = activeColor ?? colors.primary;
5186
+ const resolvedInactive = inactiveColor ?? colors.foregroundMuted;
5187
+ return /* @__PURE__ */ React25__default.default.createElement(
5188
+ reactNative.View,
5189
+ {
5190
+ style: [
5191
+ styles43.container,
5192
+ {
5193
+ backgroundColor: colors.card,
5194
+ borderTopColor: colors.border,
5195
+ paddingBottom: withSafeArea ? insets.bottom : 0
5196
+ },
5197
+ style
5198
+ ],
5199
+ accessibilityRole: "tablist"
5200
+ },
5201
+ items.map((item) => {
5202
+ const active = item.key === activeKey;
5203
+ const tint = active ? resolvedActive : resolvedInactive;
5204
+ const iconNode = item.icon ?? (item.iconName ? renderIcon(item.iconName, ms(24), tint) : null);
5205
+ const showBadge = item.badge !== void 0 && item.badge !== false;
5206
+ const badgeCount = typeof item.badge === "number" ? item.badge : void 0;
5207
+ return /* @__PURE__ */ React25__default.default.createElement(
5208
+ reactNative.TouchableOpacity,
5209
+ {
5210
+ key: item.key,
5211
+ style: styles43.tab,
5212
+ onPress: () => {
5213
+ if (!active) selectionAsync();
5214
+ onTabPress(item.key);
5215
+ },
5216
+ activeOpacity: 0.7,
5217
+ touchSoundDisabled: true,
5218
+ accessibilityRole: "tab",
5219
+ accessibilityState: { selected: active },
5220
+ accessibilityLabel: item.label ?? item.key
5221
+ },
5222
+ /* @__PURE__ */ React25__default.default.createElement(reactNative.View, null, iconNode, showBadge ? /* @__PURE__ */ React25__default.default.createElement(
5223
+ reactNative.View,
5224
+ {
5225
+ style: [
5226
+ styles43.badge,
5227
+ { backgroundColor: colors.destructive, borderColor: colors.card },
5228
+ badgeCount === void 0 && styles43.badgeDot
5229
+ ]
5230
+ },
5231
+ badgeCount !== void 0 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles43.badgeText, { color: colors.destructiveForeground }], allowFontScaling: false }, badgeCount > 99 ? "99+" : badgeCount) : null
5232
+ ) : null),
5233
+ item.label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles43.label, { color: tint }], numberOfLines: 1, allowFontScaling: true }, item.label) : null
5234
+ );
5235
+ })
5236
+ );
5237
+ }
5238
+ var styles43 = reactNative.StyleSheet.create({
5239
+ container: {
5240
+ flexDirection: "row",
5241
+ borderTopWidth: reactNative.StyleSheet.hairlineWidth
5242
+ },
5243
+ tab: {
5244
+ flex: 1,
5245
+ alignItems: "center",
5246
+ justifyContent: "center",
5247
+ paddingTop: vs(8),
5248
+ paddingBottom: vs(6),
5249
+ gap: vs(2),
5250
+ minHeight: vs(48)
5251
+ },
5252
+ label: {
5253
+ fontFamily: "Sohne-Medium",
5254
+ fontSize: ms(11),
5255
+ lineHeight: mvs(14)
5256
+ },
5257
+ badge: {
5258
+ position: "absolute",
5259
+ top: -vs(4),
5260
+ right: -s(10),
5261
+ minWidth: s(16),
5262
+ height: s(16),
5263
+ borderRadius: s(8),
5264
+ borderWidth: 1.5,
5265
+ alignItems: "center",
5266
+ justifyContent: "center",
5267
+ paddingHorizontal: s(3)
5268
+ },
5269
+ badgeDot: {
5270
+ minWidth: s(10),
5271
+ height: s(10),
5272
+ borderRadius: s(5),
5273
+ top: -vs(2),
5274
+ right: -s(6),
5275
+ paddingHorizontal: 0
5276
+ },
5277
+ badgeText: {
5278
+ fontFamily: "Sohne-SemiBold",
5279
+ fontSize: ms(9),
5280
+ lineHeight: ms(11)
5281
+ }
5282
+ });
5283
+ var MAX_SCALE = 3;
5284
+ var DOUBLE_TAP_SCALE = 2.5;
5285
+ function ZoomableImage({ source, width, height, onZoomChange }) {
5286
+ const scale2 = Animated13.useSharedValue(1);
5287
+ const savedScale = Animated13.useSharedValue(1);
5288
+ const translateX = Animated13.useSharedValue(0);
5289
+ const translateY = Animated13.useSharedValue(0);
5290
+ const savedX = Animated13.useSharedValue(0);
5291
+ const savedY = Animated13.useSharedValue(0);
5292
+ const reportZoom = React25.useCallback((zoomed) => onZoomChange(zoomed), [onZoomChange]);
5293
+ const reset = () => {
5294
+ "worklet";
5295
+ scale2.value = Animated13.withTiming(1);
5296
+ savedScale.value = 1;
5297
+ translateX.value = Animated13.withTiming(0);
5298
+ translateY.value = Animated13.withTiming(0);
5299
+ savedX.value = 0;
5300
+ savedY.value = 0;
5301
+ Animated13.runOnJS(reportZoom)(false);
5302
+ };
5303
+ const pinch = reactNativeGestureHandler.Gesture.Pinch().onUpdate((e) => {
5304
+ scale2.value = Math.max(1, Math.min(savedScale.value * e.scale, MAX_SCALE));
5305
+ }).onEnd(() => {
5306
+ savedScale.value = scale2.value;
5307
+ if (scale2.value <= 1) {
5308
+ reset();
5309
+ } else {
5310
+ Animated13.runOnJS(reportZoom)(true);
5311
+ }
5312
+ });
5313
+ const pan = reactNativeGestureHandler.Gesture.Pan().onUpdate((e) => {
5314
+ if (scale2.value <= 1) return;
5315
+ translateX.value = savedX.value + e.translationX;
5316
+ translateY.value = savedY.value + e.translationY;
5317
+ }).onEnd(() => {
5318
+ savedX.value = translateX.value;
5319
+ savedY.value = translateY.value;
5320
+ });
5321
+ const doubleTap = reactNativeGestureHandler.Gesture.Tap().numberOfTaps(2).onEnd(() => {
5322
+ if (scale2.value > 1) {
5323
+ reset();
5324
+ } else {
5325
+ scale2.value = Animated13.withTiming(DOUBLE_TAP_SCALE);
5326
+ savedScale.value = DOUBLE_TAP_SCALE;
5327
+ Animated13.runOnJS(reportZoom)(true);
5328
+ }
5329
+ });
5330
+ const composed = reactNativeGestureHandler.Gesture.Exclusive(doubleTap, reactNativeGestureHandler.Gesture.Simultaneous(pinch, pan));
5331
+ const animatedStyle = Animated13.useAnimatedStyle(() => ({
5332
+ transform: [
5333
+ { translateX: translateX.value },
5334
+ { translateY: translateY.value },
5335
+ { scale: scale2.value }
5336
+ ]
5337
+ }));
5338
+ return /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: composed }, /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [{ width, height }, styles44.imageWrap] }, /* @__PURE__ */ React25__default.default.createElement(
5339
+ Animated13__default.default.Image,
5340
+ {
5341
+ source,
5342
+ style: [{ width, height }, animatedStyle],
5343
+ resizeMode: "contain"
5344
+ }
5345
+ )));
5346
+ }
5347
+ function ImageViewer({ images, visible, onClose, initialIndex = 0 }) {
5348
+ const { width, height } = reactNative.useWindowDimensions();
5349
+ const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
5350
+ const [index, setIndex] = React25.useState(initialIndex);
5351
+ const [pagingEnabled, setPagingEnabled] = React25.useState(true);
5352
+ const scrollRef = React25__default.default.useRef(null);
5353
+ React25__default.default.useEffect(() => {
5354
+ if (!visible) return;
5355
+ const handle = requestAnimationFrame(() => {
5356
+ setIndex(initialIndex);
5357
+ setPagingEnabled(true);
5358
+ scrollRef.current?.scrollTo({ x: initialIndex * width, animated: false });
5359
+ });
5360
+ return () => cancelAnimationFrame(handle);
5361
+ }, [visible, initialIndex, width]);
5362
+ const dragY = Animated13.useSharedValue(0);
5363
+ const DISMISS_THRESHOLD = height * 0.18;
5364
+ const closeViewer = React25.useCallback(() => onClose(), [onClose]);
5365
+ const swipeDown = reactNativeGestureHandler.Gesture.Pan().enabled(pagingEnabled).activeOffsetY(12).failOffsetX([-16, 16]).onUpdate((e) => {
5366
+ dragY.value = Math.max(0, e.translationY);
5367
+ }).onEnd((e) => {
5368
+ if (e.translationY > DISMISS_THRESHOLD || e.velocityY > 800) {
5369
+ Animated13.runOnJS(closeViewer)();
5370
+ } else {
5371
+ dragY.value = Animated13.withTiming(0);
5372
+ }
5373
+ });
5374
+ React25__default.default.useEffect(() => {
5375
+ if (visible) dragY.value = 0;
5376
+ }, [visible, dragY]);
5377
+ const dismissStyle = Animated13.useAnimatedStyle(() => ({
5378
+ transform: [{ translateY: dragY.value }]
5379
+ }));
5380
+ const backdropStyle = Animated13.useAnimatedStyle(() => ({
5381
+ opacity: 1 - Math.min(dragY.value / (height * 0.5), 0.85)
5382
+ }));
5383
+ const onMomentumEnd = (e) => {
5384
+ const page = Math.round(e.nativeEvent.contentOffset.x / width);
5385
+ setIndex(page);
5386
+ };
5387
+ const goTo = (page) => {
5388
+ scrollRef.current?.scrollTo({ x: page * width, animated: true });
5389
+ setIndex(page);
5390
+ };
5391
+ return /* @__PURE__ */ React25__default.default.createElement(reactNative.Modal, { visible, transparent: false, animationType: "fade", onRequestClose: onClose, statusBarTranslucent: true }, /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureHandlerRootView, { style: styles44.root }, /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles44.backdrop, backdropStyle], pointerEvents: "none" }), /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles44.container, dismissStyle] }, /* @__PURE__ */ React25__default.default.createElement(reactNativeGestureHandler.GestureDetector, { gesture: swipeDown }, /* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: styles44.root }, /* @__PURE__ */ React25__default.default.createElement(
5392
+ reactNative.ScrollView,
5393
+ {
5394
+ ref: scrollRef,
5395
+ horizontal: true,
5396
+ pagingEnabled: true,
5397
+ scrollEnabled: pagingEnabled,
5398
+ showsHorizontalScrollIndicator: false,
5399
+ onMomentumScrollEnd: onMomentumEnd,
5400
+ bounces: false
5401
+ },
5402
+ images.map((source, i) => /* @__PURE__ */ React25__default.default.createElement(
5403
+ ZoomableImage,
5404
+ {
5405
+ key: i,
5406
+ source,
5407
+ width,
5408
+ height,
5409
+ onZoomChange: (zoomed) => setPagingEnabled(!zoomed)
5410
+ }
5411
+ ))
5412
+ ))), /* @__PURE__ */ React25__default.default.createElement(
5413
+ reactNative.TouchableOpacity,
5414
+ {
5415
+ style: [styles44.closeButton, { top: insets.top + vs(8) }],
5416
+ onPress: onClose,
5417
+ activeOpacity: 0.7,
5418
+ touchSoundDisabled: true,
5419
+ accessibilityRole: "button",
5420
+ accessibilityLabel: "Close",
5421
+ hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
5422
+ },
5423
+ renderIcon("x", 26, "#fff")
5424
+ ), images.length > 1 ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles44.dots, { bottom: insets.bottom + vs(16) }], pointerEvents: "box-none" }, /* @__PURE__ */ React25__default.default.createElement(
5425
+ PagerDots,
5426
+ {
5427
+ count: images.length,
5428
+ activeIndex: index,
5429
+ onDotPress: goTo,
5430
+ activeColor: "#fff",
5431
+ inactiveColor: "rgba(255,255,255,0.4)"
5432
+ }
5433
+ )) : null)));
5434
+ }
5435
+ var styles44 = reactNative.StyleSheet.create({
5436
+ root: {
5437
+ flex: 1
5438
+ },
5439
+ container: {
5440
+ flex: 1
5441
+ },
5442
+ backdrop: {
5443
+ ...reactNative.StyleSheet.absoluteFillObject,
5444
+ backgroundColor: "#000"
5445
+ },
5446
+ imageWrap: {
5447
+ alignItems: "center",
5448
+ justifyContent: "center",
5449
+ overflow: "hidden"
5450
+ },
5451
+ closeButton: {
5452
+ position: "absolute",
5453
+ right: s(12),
5454
+ width: s(40),
5455
+ height: s(40),
5456
+ borderRadius: s(20),
5457
+ backgroundColor: "rgba(0,0,0,0.4)",
5458
+ alignItems: "center",
5459
+ justifyContent: "center"
5460
+ },
5461
+ dots: {
5462
+ position: "absolute",
5463
+ left: 0,
5464
+ right: 0,
5465
+ alignItems: "center"
5466
+ }
5467
+ });
4289
5468
 
4290
5469
  // src/utils/typography.ts
4291
5470
  function getResponsiveFontSize(text, maxSize, steps = [
@@ -4315,6 +5494,7 @@ Object.defineProperty(exports, "toast", {
4315
5494
  });
4316
5495
  exports.Accordion = Accordion;
4317
5496
  exports.AlertBanner = AlertBanner;
5497
+ exports.AppHeader = AppHeader;
4318
5498
  exports.Avatar = Avatar;
4319
5499
  exports.BREAKPOINTS = BREAKPOINTS;
4320
5500
  exports.Badge = Badge;
@@ -4333,9 +5513,9 @@ exports.ChipGroup = ChipGroup;
4333
5513
  exports.ConfirmDialog = ConfirmDialog;
4334
5514
  exports.CurrencyDisplay = CurrencyDisplay;
4335
5515
  exports.CurrencyInput = CurrencyInput;
4336
- exports.CurrencyInputLarge = CurrencyInput;
4337
5516
  exports.DetailRow = DetailRow;
4338
5517
  exports.EmptyState = EmptyState;
5518
+ exports.ErrorBoundary = ErrorBoundary;
4339
5519
  exports.Form = Form;
4340
5520
  exports.FormField = FormField;
4341
5521
  exports.FormFooter = FormFooter;
@@ -4343,6 +5523,7 @@ exports.FormSection = FormSection;
4343
5523
  exports.ICON_SIZES = ICON_SIZES;
4344
5524
  exports.Icon = Icon;
4345
5525
  exports.IconButton = IconButton;
5526
+ exports.ImageViewer = ImageViewer;
4346
5527
  exports.Input = Input;
4347
5528
  exports.LabelValue = LabelValue;
4348
5529
  exports.ListGroup = ListGroup;
@@ -4355,13 +5536,17 @@ exports.MenuGroupFooter = MenuGroupFooter;
4355
5536
  exports.MenuGroupHeader = MenuGroupHeader;
4356
5537
  exports.MenuItem = MenuItem;
4357
5538
  exports.MonthPicker = MonthPicker;
4358
- exports.Pressable = Pressable2;
5539
+ exports.PagerDots = PagerDots;
5540
+ exports.Pressable = Pressable3;
5541
+ exports.PricingCard = PricingCard;
4359
5542
  exports.Progress = Progress;
4360
5543
  exports.RADIUS = RADIUS;
4361
5544
  exports.RadioGroup = RadioGroup;
5545
+ exports.RetrayProvider = RetrayProvider;
4362
5546
  exports.SHADOWS = SHADOWS;
4363
5547
  exports.SPACING = SPACING;
4364
5548
  exports.Select = Select;
5549
+ exports.SelectableGrid = SelectableGrid;
4365
5550
  exports.Separator = Separator;
4366
5551
  exports.Sheet = Sheet;
4367
5552
  exports.Skeleton = Skeleton;
@@ -4369,6 +5554,7 @@ exports.Slider = Slider;
4369
5554
  exports.Spinner = Spinner;
4370
5555
  exports.Switch = Switch;
4371
5556
  exports.TYPOGRAPHY = TYPOGRAPHY;
5557
+ exports.TabBar = TabBar;
4372
5558
  exports.Tabs = Tabs;
4373
5559
  exports.TabsContent = TabsContent;
4374
5560
  exports.Text = Text3;
@@ -4378,10 +5564,20 @@ exports.ToastProvider = ToastProvider;
4378
5564
  exports.Toggle = Toggle;
4379
5565
  exports.VirtualList = VirtualList;
4380
5566
  exports.configureIconFamilies = configureIconFamilies;
5567
+ exports.dateToMonthPickerValue = dateToMonthPickerValue;
4381
5568
  exports.defaultDark = defaultDark;
4382
5569
  exports.defaultLight = defaultLight;
4383
5570
  exports.deriveColors = deriveColors;
4384
5571
  exports.getResponsiveFontSize = getResponsiveFontSize;
5572
+ exports.impactHeavy = impactHeavy;
5573
+ exports.impactLight = impactLight;
5574
+ exports.impactMedium = impactMedium;
5575
+ exports.monthPickerValueToDate = monthPickerValueToDate;
5576
+ exports.notificationError = notificationError;
5577
+ exports.notificationSuccess = notificationSuccess;
5578
+ exports.notificationWarning = notificationWarning;
4385
5579
  exports.renderIcon = renderIcon;
5580
+ exports.richHaptics = richHaptics;
5581
+ exports.selectionAsync = selectionAsync;
4386
5582
  exports.useTheme = useTheme;
4387
5583
  exports.useToast = useToast;