@retray-dev/ui-kit 12.1.0 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/COMPONENTS.md +183 -147
  2. package/CONSUMER.md +2 -2
  3. package/DESIGN.md +2 -2
  4. package/README.md +13 -8
  5. package/dist/Accordion.d.mts +6 -0
  6. package/dist/Accordion.d.ts +6 -0
  7. package/dist/Accordion.js +62 -208
  8. package/dist/Accordion.mjs +6 -5
  9. package/dist/AlertBanner.js +29 -151
  10. package/dist/AlertBanner.mjs +3 -3
  11. package/dist/AppHeader.js +37 -233
  12. package/dist/AppHeader.mjs +6 -7
  13. package/dist/Avatar.d.mts +17 -1
  14. package/dist/Avatar.d.ts +17 -1
  15. package/dist/Avatar.js +80 -113
  16. package/dist/Avatar.mjs +2 -2
  17. package/dist/Badge.js +24 -147
  18. package/dist/Badge.mjs +3 -3
  19. package/dist/Button.js +86 -274
  20. package/dist/Button.mjs +6 -6
  21. package/dist/Card.js +15 -198
  22. package/dist/Card.mjs +4 -5
  23. package/dist/CategoryStrip.d.mts +0 -5
  24. package/dist/CategoryStrip.d.ts +0 -5
  25. package/dist/CategoryStrip.js +47 -263
  26. package/dist/CategoryStrip.mjs +6 -6
  27. package/dist/Checkbox.js +15 -198
  28. package/dist/Checkbox.mjs +5 -5
  29. package/dist/Chip.js +44 -234
  30. package/dist/Chip.mjs +7 -6
  31. package/dist/ConfirmDialog.js +100 -296
  32. package/dist/ConfirmDialog.mjs +7 -7
  33. package/dist/CurrencyDisplay.js +1 -112
  34. package/dist/CurrencyDisplay.mjs +2 -2
  35. package/dist/CurrencyInput.js +35 -160
  36. package/dist/CurrencyInput.mjs +5 -5
  37. package/dist/DetailRow.js +25 -148
  38. package/dist/DetailRow.mjs +3 -3
  39. package/dist/EmptyState.js +87 -275
  40. package/dist/EmptyState.mjs +7 -7
  41. package/dist/ErrorBoundary.js +32 -197
  42. package/dist/ErrorBoundary.mjs +4 -4
  43. package/dist/Form.js +1 -112
  44. package/dist/Form.mjs +2 -2
  45. package/dist/HolographicCard.d.mts +0 -28
  46. package/dist/HolographicCard.d.ts +0 -28
  47. package/dist/HolographicCard.js +20 -130
  48. package/dist/HolographicCard.mjs +9 -32
  49. package/dist/IconButton.js +36 -232
  50. package/dist/IconButton.mjs +5 -6
  51. package/dist/IconPicker.js +222 -927
  52. package/dist/IconPicker.mjs +5 -5
  53. package/dist/ImageUpload.d.mts +5 -1
  54. package/dist/ImageUpload.d.ts +5 -1
  55. package/dist/ImageUpload.js +32 -215
  56. package/dist/ImageUpload.mjs +5 -6
  57. package/dist/ImageViewer.js +75 -264
  58. package/dist/ImageViewer.mjs +8 -8
  59. package/dist/Input.d.mts +1 -1
  60. package/dist/Input.d.ts +1 -1
  61. package/dist/Input.js +35 -160
  62. package/dist/Input.mjs +4 -4
  63. package/dist/LabelValue.js +24 -147
  64. package/dist/LabelValue.mjs +3 -3
  65. package/dist/ListGroup.js +1 -112
  66. package/dist/ListGroup.mjs +2 -2
  67. package/dist/ListItem.js +38 -233
  68. package/dist/ListItem.mjs +5 -6
  69. package/dist/MediaCard.d.mts +0 -14
  70. package/dist/MediaCard.d.ts +0 -14
  71. package/dist/MediaCard.js +69 -313
  72. package/dist/MediaCard.mjs +5 -6
  73. package/dist/MenuGroup.js +1 -112
  74. package/dist/MenuGroup.mjs +2 -2
  75. package/dist/MenuItem.js +36 -232
  76. package/dist/MenuItem.mjs +5 -6
  77. package/dist/MonthPicker.js +8 -161
  78. package/dist/MonthPicker.mjs +3 -3
  79. package/dist/NumberStepper.js +40 -236
  80. package/dist/NumberStepper.mjs +5 -6
  81. package/dist/PagerDots.d.mts +1 -1
  82. package/dist/PagerDots.d.ts +1 -1
  83. package/dist/PagerDots.js +69 -222
  84. package/dist/PagerDots.mjs +6 -5
  85. package/dist/Pressable.js +14 -85
  86. package/dist/Pressable.mjs +4 -4
  87. package/dist/PricingCard.js +94 -279
  88. package/dist/PricingCard.mjs +8 -8
  89. package/dist/Progress.js +3 -121
  90. package/dist/Progress.mjs +3 -3
  91. package/dist/RadioGroup.js +52 -263
  92. package/dist/RadioGroup.mjs +5 -5
  93. package/dist/RetrayProvider.d.mts +1 -1
  94. package/dist/RetrayProvider.d.ts +1 -1
  95. package/dist/RetrayProvider.js +5 -6
  96. package/dist/RetrayProvider.mjs +3 -3
  97. package/dist/Select.d.mts +2 -1
  98. package/dist/Select.d.ts +2 -1
  99. package/dist/Select.js +24 -230
  100. package/dist/Select.mjs +4 -5
  101. package/dist/SelectableCard.d.mts +27 -0
  102. package/dist/SelectableCard.d.ts +27 -0
  103. package/dist/SelectableCard.js +335 -0
  104. package/dist/SelectableCard.mjs +8 -0
  105. package/dist/SelectableGrid.d.mts +0 -21
  106. package/dist/SelectableGrid.d.ts +0 -21
  107. package/dist/SelectableGrid.js +49 -269
  108. package/dist/SelectableGrid.mjs +5 -6
  109. package/dist/Separator.js +1 -112
  110. package/dist/Separator.mjs +2 -2
  111. package/dist/Sheet.js +16 -163
  112. package/dist/Sheet.mjs +3 -3
  113. package/dist/SheetSelect.js +39 -234
  114. package/dist/SheetSelect.mjs +6 -6
  115. package/dist/Skeleton.d.mts +3 -1
  116. package/dist/Skeleton.d.ts +3 -1
  117. package/dist/Skeleton.js +7 -124
  118. package/dist/Skeleton.mjs +3 -3
  119. package/dist/Slider.js +6 -159
  120. package/dist/Slider.mjs +3 -3
  121. package/dist/Spinner.js +3 -114
  122. package/dist/Spinner.mjs +2 -2
  123. package/dist/Stats.d.mts +4 -1
  124. package/dist/Stats.d.ts +4 -1
  125. package/dist/Stats.js +60 -234
  126. package/dist/Stats.mjs +5 -6
  127. package/dist/Switch.js +24 -173
  128. package/dist/Switch.mjs +5 -4
  129. package/dist/TabBar.js +43 -198
  130. package/dist/TabBar.mjs +5 -4
  131. package/dist/Tabs.js +15 -197
  132. package/dist/Tabs.mjs +5 -5
  133. package/dist/Text.js +9 -128
  134. package/dist/Text.mjs +2 -2
  135. package/dist/Textarea.d.mts +2 -1
  136. package/dist/Textarea.d.ts +2 -1
  137. package/dist/Textarea.js +71 -217
  138. package/dist/Textarea.mjs +4 -4
  139. package/dist/Toast.js +1 -112
  140. package/dist/Toast.mjs +2 -2
  141. package/dist/Toggle.js +39 -234
  142. package/dist/Toggle.mjs +6 -6
  143. package/dist/{chunk-FFTYLPSB.mjs → chunk-2QOHHBJC.mjs} +13 -7
  144. package/dist/{chunk-BCWEHE34.mjs → chunk-2VIDP72N.mjs} +3 -3
  145. package/dist/{chunk-PGERH3P7.mjs → chunk-4NQFTHN3.mjs} +13 -7
  146. package/dist/{chunk-3N2M3WZL.mjs → chunk-4ZO5PTKF.mjs} +4 -4
  147. package/dist/{chunk-MYZ2EDYU.mjs → chunk-5MYNAAFE.mjs} +13 -17
  148. package/dist/{chunk-E7NEHHXV.mjs → chunk-62BBSSUF.mjs} +3 -3
  149. package/dist/{chunk-ISY26JQJ.mjs → chunk-6CR4S6W2.mjs} +3 -3
  150. package/dist/{chunk-FUVYSVGR.mjs → chunk-6QLBHUEG.mjs} +8 -7
  151. package/dist/chunk-ARONDO7M.mjs +40 -0
  152. package/dist/{chunk-3UYAZ7I4.mjs → chunk-AZV7KNJI.mjs} +3 -3
  153. package/dist/{chunk-HLMPMUK2.mjs → chunk-BTUW5LSG.mjs} +11 -8
  154. package/dist/chunk-BULKGOIZ.mjs +235 -0
  155. package/dist/{chunk-265G6A46.mjs → chunk-CBIZLRYH.mjs} +29 -12
  156. package/dist/chunk-CM2DG4MR.mjs +142 -0
  157. package/dist/{chunk-2I2AYECM.mjs → chunk-DBHSUUKU.mjs} +2 -2
  158. package/dist/{chunk-P64WHW4A.mjs → chunk-DE25XTVQ.mjs} +3 -3
  159. package/dist/{chunk-DI7CBDL6.mjs → chunk-E4EQSCKR.mjs} +5 -5
  160. package/dist/{chunk-357YO24D.mjs → chunk-EHGBHFMH.mjs} +9 -17
  161. package/dist/{chunk-GK4VRMNE.mjs → chunk-EROPDCB5.mjs} +24 -27
  162. package/dist/{chunk-XBAGGKLW.mjs → chunk-ERWJPVX7.mjs} +2 -2
  163. package/dist/{chunk-LRM4AVYY.mjs → chunk-ESQDPO5E.mjs} +7 -7
  164. package/dist/{chunk-EFLFRAHD.mjs → chunk-EW2FIDSM.mjs} +1 -1
  165. package/dist/{chunk-7HSILTC4.mjs → chunk-FTTI6T5Q.mjs} +4 -4
  166. package/dist/{chunk-X26S5EVZ.mjs → chunk-HUSSF6TF.mjs} +1 -1
  167. package/dist/chunk-IFYMBOEN.mjs +14 -0
  168. package/dist/{chunk-S3KJCPEJ.mjs → chunk-IGU223UM.mjs} +80 -4
  169. package/dist/chunk-IJCMPVW5.mjs +121 -0
  170. package/dist/{chunk-I4V5XZPS.mjs → chunk-ITG4JQM3.mjs} +4 -4
  171. package/dist/{chunk-F4V6XLP4.mjs → chunk-K3QX2M26.mjs} +11 -8
  172. package/dist/{chunk-V6NFJXKO.mjs → chunk-K7TKID3V.mjs} +8 -7
  173. package/dist/{chunk-ZHMSAYLT.mjs → chunk-KAGADD2O.mjs} +4 -4
  174. package/dist/{chunk-3GEYJ7I5.mjs → chunk-KC5QDYGZ.mjs} +4 -4
  175. package/dist/{chunk-HJ46DTJE.mjs → chunk-KPTY7UYQ.mjs} +1 -1
  176. package/dist/{chunk-EMUWGDWC.mjs → chunk-KSSVIFYR.mjs} +11 -12
  177. package/dist/chunk-L3YKPTJQ.mjs +119 -0
  178. package/dist/chunk-M53LC4Q7.mjs +35 -0
  179. package/dist/{chunk-NXI4YDZ2.mjs → chunk-MP7GLMIR.mjs} +17 -25
  180. package/dist/chunk-MZ6WRTD2.mjs +40 -0
  181. package/dist/chunk-NGEN2EES.mjs +581 -0
  182. package/dist/{chunk-JULSIZDM.mjs → chunk-OBV72JD4.mjs} +1 -1
  183. package/dist/{chunk-2A2LEFZG.mjs → chunk-PGQ6FMXS.mjs} +6 -5
  184. package/dist/{chunk-BQZE3HAW.mjs → chunk-PI6RULJX.mjs} +1 -1
  185. package/dist/{chunk-FA2KMTH5.mjs → chunk-RA6SAAFE.mjs} +9 -8
  186. package/dist/{chunk-FVTVCJAH.mjs → chunk-RRKM4MKB.mjs} +7 -7
  187. package/dist/{chunk-AKM4EPOT.mjs → chunk-S2VGME7X.mjs} +1 -1
  188. package/dist/{chunk-OULVKTWL.mjs → chunk-S44XWTTC.mjs} +35 -25
  189. package/dist/{chunk-QSFV2P7O.mjs → chunk-SZEKQAOY.mjs} +1 -1
  190. package/dist/{chunk-N4ZPVCJH.mjs → chunk-TETMEKZE.mjs} +9 -9
  191. package/dist/{chunk-2CBQKU7H.mjs → chunk-TMH263OK.mjs} +5 -4
  192. package/dist/{chunk-D3Y2T42P.mjs → chunk-U6DEBYU5.mjs} +10 -9
  193. package/dist/{chunk-4WFMPFZB.mjs → chunk-UOKFSFNJ.mjs} +2 -2
  194. package/dist/{chunk-WOEWGSTU.mjs → chunk-URIH43IJ.mjs} +13 -21
  195. package/dist/{chunk-JCZQOY4O.mjs → chunk-V2ZB2XNS.mjs} +16 -10
  196. package/dist/{chunk-P73V2EKS.mjs → chunk-WIPEDNSD.mjs} +7 -7
  197. package/dist/{chunk-BOVUP27T.mjs → chunk-XCIG6HT2.mjs} +6 -5
  198. package/dist/chunk-Y6YS33GM.mjs +131 -0
  199. package/dist/{chunk-5OLNXP3S.mjs → chunk-ZKDKKQCE.mjs} +29 -7
  200. package/dist/{chunk-DF6DU42P.mjs → chunk-ZTPYUU5C.mjs} +5 -5
  201. package/dist/{index-wt-orHUi.d.ts → index-CY34hxPN.d.mts} +1 -0
  202. package/dist/{index-wt-orHUi.d.mts → index-CY34hxPN.d.ts} +1 -0
  203. package/dist/index.d.mts +15 -74
  204. package/dist/index.d.ts +15 -74
  205. package/dist/index.js +1055 -1562
  206. package/dist/index.mjs +81 -84
  207. package/package.json +8 -10
  208. package/src/components/Accordion/Accordion.tsx +32 -9
  209. package/src/components/AlertBanner/AlertBanner.tsx +7 -6
  210. package/src/components/AppHeader/AppHeader.tsx +1 -1
  211. package/src/components/Avatar/Avatar.tsx +92 -1
  212. package/src/components/Avatar/index.ts +2 -2
  213. package/src/components/Badge/Badge.tsx +2 -2
  214. package/src/components/Button/Button.tsx +64 -57
  215. package/src/components/Card/Card.tsx +1 -0
  216. package/src/components/CategoryStrip/CategoryStrip.tsx +36 -49
  217. package/src/components/Chip/Chip.tsx +5 -4
  218. package/src/components/ConfirmDialog/ConfirmDialog.tsx +13 -6
  219. package/src/components/DetailRow/DetailRow.tsx +3 -3
  220. package/src/components/EmptyState/EmptyState.tsx +2 -2
  221. package/src/components/ErrorBoundary/ErrorBoundary.tsx +6 -6
  222. package/src/components/HolographicCard/HolographicCard.tsx +14 -95
  223. package/src/components/IconButton/IconButton.tsx +2 -2
  224. package/src/components/IconPicker/IconPicker.tsx +13 -12
  225. package/src/components/ImageUpload/ImageUpload.tsx +24 -28
  226. package/src/components/ImageViewer/ImageViewer.tsx +3 -3
  227. package/src/components/Input/Input.tsx +11 -5
  228. package/src/components/LabelValue/LabelValue.tsx +2 -2
  229. package/src/components/ListItem/ListItem.tsx +4 -4
  230. package/src/components/MediaCard/MediaCard.tsx +21 -59
  231. package/src/components/MenuItem/MenuItem.tsx +2 -2
  232. package/src/components/MonthPicker/MonthPicker.tsx +2 -2
  233. package/src/components/NumberStepper/NumberStepper.tsx +6 -6
  234. package/src/components/PagerDots/PagerDots.tsx +38 -28
  235. package/src/components/PricingCard/PricingCard.tsx +6 -6
  236. package/src/components/RadioGroup/RadioGroup.tsx +18 -31
  237. package/src/components/Select/Select.tsx +32 -39
  238. package/src/components/SelectableCard/SelectableCard.tsx +302 -0
  239. package/src/components/SelectableCard/index.ts +1 -0
  240. package/src/components/SelectableGrid/SelectableGrid.tsx +38 -72
  241. package/src/components/Sheet/Sheet.tsx +11 -4
  242. package/src/components/SheetSelect/SheetSelect.tsx +3 -3
  243. package/src/components/Skeleton/Skeleton.tsx +6 -3
  244. package/src/components/Spinner/Spinner.tsx +2 -2
  245. package/src/components/Stats/Stats.tsx +36 -8
  246. package/src/components/Switch/Switch.tsx +9 -6
  247. package/src/components/TabBar/TabBar.tsx +9 -8
  248. package/src/components/Text/Text.tsx +12 -1
  249. package/src/components/Textarea/Textarea.tsx +18 -32
  250. package/src/components/Toggle/Toggle.tsx +3 -3
  251. package/src/hooks/useConfirmDialog.ts +31 -42
  252. package/src/index.ts +4 -4
  253. package/src/theme/ThemeProvider.tsx +1 -4
  254. package/src/theme/colorUtils.ts +1 -72
  255. package/src/theme/colors.ts +47 -1
  256. package/src/theme/types.ts +6 -3
  257. package/src/utils/animations.ts +0 -47
  258. package/src/utils/curatedIcons.ts +93 -801
  259. package/src/utils/haptics.ts +13 -208
  260. package/src/utils/icons.ts +27 -91
  261. package/src/utils/pressable.ts +10 -61
  262. package/dist/VirtualList.d.mts +0 -19
  263. package/dist/VirtualList.d.ts +0 -19
  264. package/dist/VirtualList.js +0 -38
  265. package/dist/VirtualList.mjs +0 -2
  266. package/dist/chunk-3DKJ2GIC.mjs +0 -30
  267. package/dist/chunk-AQEVCEXV.mjs +0 -164
  268. package/dist/chunk-DOGIPOF5.mjs +0 -131
  269. package/dist/chunk-DVK4G2GT.mjs +0 -59
  270. package/dist/chunk-EJ7ZPXOH.mjs +0 -163
  271. package/dist/chunk-J6Q2YJEV.mjs +0 -134
  272. package/dist/chunk-JNVAIDLK.mjs +0 -136
  273. package/dist/chunk-KA7LTET3.mjs +0 -71
  274. package/dist/chunk-KHYX4IOM.mjs +0 -1114
  275. package/dist/chunk-NC5ZTR2Y.mjs +0 -32
  276. package/dist/chunk-YNROWHQJ.mjs +0 -46
  277. package/src/components/VirtualList/VirtualList.tsx +0 -60
  278. package/src/components/VirtualList/index.ts +0 -1
  279. package/src/utils/fontGuard.ts +0 -35
  280. package/src/utils/hover.ts +0 -25
  281. package/src/utils/useColorTransition.ts +0 -40
  282. package/src/utils/usePressScale.ts +0 -75
@@ -1,164 +0,0 @@
1
- import { useHover, usePressScale } from './chunk-YNROWHQJ.mjs';
2
- import { impactLight } from './chunk-EJ7ZPXOH.mjs';
3
- import { SPRINGS, PRESS_SCALE } from './chunk-DVK4G2GT.mjs';
4
- import { RADIUS, SHADOWS } from './chunk-QY3X2UYR.mjs';
5
- import { renderIcon } from './chunk-KA7LTET3.mjs';
6
- import { useTheme } from './chunk-EMUWGDWC.mjs';
7
- import { mvs, ms, vs, s } from './chunk-2CE3TQVY.mjs';
8
- import React from 'react';
9
- import { StyleSheet, View, Platform, Image, TouchableOpacity, Text } from 'react-native';
10
- import Animated from 'react-native-reanimated';
11
-
12
- var aspectRatioMap = {
13
- "1:1": 1,
14
- "4:3": 3 / 4,
15
- "16:9": 9 / 16,
16
- "4:5": 5 / 4,
17
- "3:2": 2 / 3
18
- };
19
- function MediaCardBase({
20
- imageSource,
21
- aspectRatio = "4:3",
22
- badge,
23
- actionIcon,
24
- actionIconName,
25
- actionActive = false,
26
- onActionPress,
27
- title,
28
- subtitle,
29
- caption,
30
- onPress,
31
- style,
32
- imageStyle,
33
- footer,
34
- accessibilityLabel
35
- }) {
36
- const { colors } = useTheme();
37
- const { hovered, hoverHandlers } = useHover();
38
- const { animatedStyle, onPressIn, onPressOut } = usePressScale({
39
- pressScale: PRESS_SCALE.card,
40
- pressInSpring: SPRINGS.surfacePressIn,
41
- pressOutSpring: SPRINGS.surfacePressOut,
42
- disabled: !onPress
43
- });
44
- const handlePress = () => {
45
- if (!onPress) return;
46
- impactLight();
47
- onPress();
48
- };
49
- const ratio = aspectRatioMap[aspectRatio];
50
- const resolvedActionIcon = actionIconName ? renderIcon(actionIconName, 18, actionActive ? colors.primary : colors.background) : actionIcon ?? renderIcon("heart", 18, actionActive ? colors.primary : colors.background);
51
- const a11yLabel = accessibilityLabel ?? [title, subtitle].filter(Boolean).join(". ");
52
- const cardContent = /* @__PURE__ */ React.createElement(
53
- View,
54
- {
55
- style: [
56
- styles.card,
57
- hovered && styles.cardHovered,
58
- style
59
- ],
60
- ...Platform.OS === "web" ? hoverHandlers : {}
61
- },
62
- /* @__PURE__ */ React.createElement(View, { style: [styles.imageContainer, imageStyle] }, /* @__PURE__ */ React.createElement(View, { style: { paddingTop: `${ratio * 100}%` } }, /* @__PURE__ */ React.createElement(View, { style: StyleSheet.absoluteFill }, imageSource ? /* @__PURE__ */ React.createElement(
63
- Image,
64
- {
65
- source: imageSource,
66
- style: styles.image,
67
- resizeMode: "cover"
68
- }
69
- ) : /* @__PURE__ */ React.createElement(View, { style: [styles.imagePlaceholder, { backgroundColor: colors.surface }] }))), badge && /* @__PURE__ */ React.createElement(View, { style: styles.badgeContainer }, badge), (onActionPress || actionIcon || actionIconName) && /* @__PURE__ */ React.createElement(
70
- TouchableOpacity,
71
- {
72
- style: [styles.actionButton, { backgroundColor: "rgba(0,0,0,0.24)" }],
73
- onPress: (e) => {
74
- e?.stopPropagation?.();
75
- impactLight();
76
- onActionPress?.();
77
- },
78
- activeOpacity: 0.8,
79
- touchSoundDisabled: true,
80
- accessibilityRole: Platform.OS === "web" && onPress ? void 0 : "button",
81
- accessibilityLabel: actionIconName ?? "action",
82
- accessibilityState: { selected: actionActive }
83
- },
84
- resolvedActionIcon
85
- )),
86
- (title || subtitle || caption || footer) && /* @__PURE__ */ React.createElement(View, { style: styles.meta }, title ? /* @__PURE__ */ React.createElement(Text, { style: [styles.title, { color: colors.foreground }], numberOfLines: 2, allowFontScaling: true }, title) : null, subtitle ? /* @__PURE__ */ React.createElement(Text, { style: [styles.subtitle, { color: colors.foregroundSubtle }], numberOfLines: 1, allowFontScaling: true }, subtitle) : null, caption ? /* @__PURE__ */ React.createElement(Text, { style: [styles.caption, { color: colors.foregroundMuted }], numberOfLines: 1, allowFontScaling: true }, caption) : null, footer)
87
- );
88
- if (onPress) {
89
- return /* @__PURE__ */ React.createElement(Animated.View, { style: animatedStyle }, /* @__PURE__ */ React.createElement(
90
- TouchableOpacity,
91
- {
92
- onPress: handlePress,
93
- onPressIn,
94
- onPressOut,
95
- activeOpacity: 1,
96
- touchSoundDisabled: true,
97
- accessibilityRole: "button",
98
- accessibilityLabel: a11yLabel
99
- },
100
- cardContent
101
- ));
102
- }
103
- return cardContent;
104
- }
105
- var MediaCard = React.memo(MediaCardBase);
106
- var styles = StyleSheet.create({
107
- card: {
108
- borderRadius: RADIUS.md,
109
- overflow: "hidden",
110
- backgroundColor: "transparent"
111
- },
112
- cardHovered: {
113
- ...SHADOWS.md
114
- },
115
- imageContainer: {
116
- borderRadius: RADIUS.md,
117
- overflow: "hidden"
118
- },
119
- image: {
120
- width: "100%",
121
- height: "100%"
122
- },
123
- imagePlaceholder: {
124
- width: "100%",
125
- height: "100%"
126
- },
127
- badgeContainer: {
128
- position: "absolute",
129
- top: s(8),
130
- left: s(8)
131
- },
132
- actionButton: {
133
- position: "absolute",
134
- top: s(8),
135
- right: s(8),
136
- width: s(32),
137
- height: s(32),
138
- borderRadius: 9999,
139
- alignItems: "center",
140
- justifyContent: "center"
141
- },
142
- meta: {
143
- paddingTop: vs(8),
144
- paddingBottom: vs(4),
145
- gap: vs(2)
146
- },
147
- title: {
148
- fontFamily: "Sohne-SemiBold",
149
- fontSize: ms(14),
150
- lineHeight: mvs(20)
151
- },
152
- subtitle: {
153
- fontFamily: "Sohne-Regular",
154
- fontSize: ms(13),
155
- lineHeight: mvs(18)
156
- },
157
- caption: {
158
- fontFamily: "Sohne-Regular",
159
- fontSize: ms(12),
160
- lineHeight: mvs(16)
161
- }
162
- });
163
-
164
- export { MediaCard };
@@ -1,131 +0,0 @@
1
- import { PressableButton } from './chunk-3DKJ2GIC.mjs';
2
- import { impactMedium } from './chunk-EJ7ZPXOH.mjs';
3
- import { TYPOGRAPHY, RADIUS } from './chunk-QY3X2UYR.mjs';
4
- import { renderIcon } from './chunk-KA7LTET3.mjs';
5
- import { useTheme } from './chunk-EMUWGDWC.mjs';
6
- import { vs, s, mvs, ms } from './chunk-2CE3TQVY.mjs';
7
- import React from 'react';
8
- import { StyleSheet, View, ActivityIndicator, Text } from 'react-native';
9
-
10
- var containerSizeStyles = {
11
- // AUDIT FIX: sm was 40pt — below Apple HIG 44pt minimum touch target.
12
- sm: { paddingHorizontal: s(16), paddingVertical: vs(12), minHeight: 44 },
13
- md: { paddingHorizontal: s(24), paddingVertical: vs(14), minHeight: 48 },
14
- lg: { paddingHorizontal: s(28), paddingVertical: vs(16), minHeight: 56 }
15
- };
16
- var labelSizeStyles = {
17
- sm: { ...TYPOGRAPHY["button-sm"], fontSize: ms(TYPOGRAPHY["button-sm"].fontSize) },
18
- md: { ...TYPOGRAPHY["button-lg"], fontSize: ms(TYPOGRAPHY["button-lg"].fontSize) },
19
- lg: { ...TYPOGRAPHY["button-lg"], fontSize: ms(TYPOGRAPHY["button-lg"].fontSize + 1), lineHeight: mvs(24) }
20
- };
21
- var iconSizeMap = { sm: 16, md: 18, lg: 20 };
22
- function ButtonBase({
23
- label,
24
- variant = "primary",
25
- size = "md",
26
- loading = false,
27
- fullWidth = false,
28
- icon,
29
- iconName,
30
- iconColor,
31
- iconPosition = "left",
32
- disabled,
33
- style,
34
- onPress,
35
- accessibilityLabel,
36
- accessibilityHint
37
- }) {
38
- const { colors } = useTheme();
39
- const isDisabled = disabled || loading;
40
- const handlePress = () => {
41
- impactMedium();
42
- onPress?.();
43
- };
44
- const containerVariantStyle = {
45
- primary: { backgroundColor: colors.primary },
46
- secondary: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.primary },
47
- text: { backgroundColor: "transparent" },
48
- destructive: { backgroundColor: colors.destructive }
49
- }[variant];
50
- const labelVariantStyle = {
51
- primary: { color: colors.primaryForeground },
52
- secondary: { color: colors.primary },
53
- // AUDIT FIX: was colors.foreground — visually indistinguishable from plain text,
54
- // no affordance that it's a CTA. Now uses accentResolved so text-only buttons
55
- // carry the brand voltage. Falls back to primary when no accent is defined.
56
- text: { color: colors.accentResolved },
57
- destructive: { color: colors.destructiveForeground }
58
- }[variant];
59
- const textColor = iconColor ?? labelVariantStyle.color;
60
- const effectiveIcon = iconName ? renderIcon(iconName, iconSizeMap[size], textColor) : typeof icon === "function" ? icon({ label, size, variant, color: textColor }) : icon;
61
- const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.accentResolved;
62
- const styleArray = Array.isArray(style) ? style : style ? [style] : [];
63
- const flatStyle = StyleSheet.flatten(styleArray);
64
- const { flex, ...restStyle } = flatStyle || {};
65
- return /* @__PURE__ */ React.createElement(View, { style: [fullWidth && styles.fullWidth, flex !== void 0 && { flex }] }, /* @__PURE__ */ React.createElement(
66
- PressableButton,
67
- {
68
- style: [
69
- styles.base,
70
- containerVariantStyle,
71
- containerSizeStyles[size],
72
- fullWidth && styles.fullWidth,
73
- isDisabled && styles.disabled,
74
- restStyle
75
- ],
76
- enabled: !isDisabled,
77
- onPress: handlePress,
78
- rippleColor: "transparent",
79
- touchSoundDisabled: true,
80
- activateOnHover: true,
81
- accessibilityRole: "button",
82
- accessibilityLabel: accessibilityLabel ?? label,
83
- accessibilityHint,
84
- accessibilityState: { disabled: isDisabled, busy: loading }
85
- },
86
- loading ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ActivityIndicator, { size: "small", color: spinnerColor, style: { marginRight: s(6) } }), /* @__PURE__ */ React.createElement(
87
- Text,
88
- {
89
- style: [styles.label, labelVariantStyle, labelSizeStyles[size], styles.labelLoading],
90
- allowFontScaling: true,
91
- numberOfLines: 1
92
- },
93
- label
94
- )) : /* @__PURE__ */ React.createElement(React.Fragment, null, effectiveIcon && iconPosition === "left" && /* @__PURE__ */ React.createElement(React.Fragment, null, effectiveIcon), /* @__PURE__ */ React.createElement(
95
- Text,
96
- {
97
- style: [styles.label, labelVariantStyle, labelSizeStyles[size], effectiveIcon ? styles.labelWithIcon : void 0],
98
- allowFontScaling: true,
99
- numberOfLines: 1
100
- },
101
- label
102
- ), effectiveIcon && iconPosition === "right" && /* @__PURE__ */ React.createElement(React.Fragment, null, effectiveIcon))
103
- ));
104
- }
105
- var Button = React.memo(ButtonBase);
106
- var styles = StyleSheet.create({
107
- base: {
108
- borderRadius: RADIUS.md,
109
- alignItems: "center",
110
- justifyContent: "center",
111
- flexDirection: "row"
112
- },
113
- fullWidth: {
114
- width: "100%"
115
- },
116
- disabled: {
117
- opacity: 0.45
118
- },
119
- label: {
120
- fontFamily: "Sohne-Medium",
121
- flexShrink: 1
122
- },
123
- labelWithIcon: {
124
- marginHorizontal: s(6)
125
- },
126
- labelLoading: {
127
- opacity: 0.6
128
- }
129
- });
130
-
131
- export { Button };
@@ -1,59 +0,0 @@
1
- import { Easing } from 'react-native-reanimated';
2
-
3
- // src/utils/animations.ts
4
- var SPRINGS = {
5
- /** Tight, premium press feel — Buttons, Toggle, Tabs triggers. */
6
- pressIn: { stiffness: 600, damping: 35, mass: 0.8 },
7
- pressOut: { stiffness: 280, damping: 22, mass: 0.8 },
8
- /** Slightly softer for larger surfaces — Card, ListItem, MenuItem. */
9
- surfacePressIn: { stiffness: 380, damping: 30, mass: 0.95 },
10
- surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 },
11
- /** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
12
- glide: { stiffness: 380, damping: 38, mass: 1 },
13
- /** Elastic indicator — Switch thumb, RadioGroup dot. */
14
- elastic: { stiffness: 320, damping: 22, mass: 0.7 }
15
- };
16
- var TIMINGS = {
17
- /** Color/opacity transitions on toggles, checkboxes, switches. */
18
- state: { duration: 160 },
19
- /** Focus ring on inputs. */
20
- focusIn: { duration: 140 },
21
- focusOut: { duration: 100 },
22
- /** Accordion / collapsible content. */
23
- expand: { duration: 240 },
24
- collapse: { duration: 200 },
25
- /** Skeleton shimmer cycle (full pass). */
26
- shimmer: { duration: 1400 }
27
- };
28
- var EASINGS = {
29
- /** Material-style ease-out — natural deceleration for state changes. */
30
- standard: Easing.bezier(0.2, 0, 0, 1),
31
- /** Strong ease-out for expanding surfaces (Accordion open). */
32
- expand: Easing.bezier(0.23, 1, 0.32, 1),
33
- /** Quick ease-in for collapsing. */
34
- collapse: Easing.in(Easing.ease)
35
- };
36
- var COLOR_TRANSITION = {
37
- type: "timing",
38
- duration: TIMINGS.state.duration,
39
- easing: [0.2, 0, 0, 1]
40
- };
41
- var OPACITY_TRANSITION = {
42
- type: "timing",
43
- duration: TIMINGS.state.duration,
44
- easing: [0.2, 0, 0, 1]
45
- };
46
- var SPRING_ELASTIC = {
47
- type: "spring",
48
- stiffness: 320,
49
- damping: 22,
50
- mass: 0.7
51
- };
52
- var PRESS_SCALE = {
53
- button: 0.95,
54
- card: 0.98,
55
- row: 0.97,
56
- chip: 0.94
57
- };
58
-
59
- export { COLOR_TRANSITION, EASINGS, OPACITY_TRANSITION, PRESS_SCALE, SPRINGS, SPRING_ELASTIC, TIMINGS };
@@ -1,163 +0,0 @@
1
- import { __require } from './chunk-Y6FXYEAI.mjs';
2
- import { Platform, NativeModules } from 'react-native';
3
-
4
- var _haptics = null;
5
- var _hapticsLoaded = false;
6
- async function getHaptics() {
7
- if (Platform.OS === "web") return null;
8
- if (!_hapticsLoaded) {
9
- _hapticsLoaded = true;
10
- try {
11
- _haptics = await import('expo-haptics');
12
- } catch {
13
- _haptics = null;
14
- }
15
- }
16
- return _haptics;
17
- }
18
- var _pulsar = null;
19
- var _pulsarChecked = false;
20
- var _pulsarAvailable = false;
21
- function isPulsarNativeRegistered() {
22
- try {
23
- const g = globalThis;
24
- if (typeof g.__turboModuleProxy === "function") {
25
- return g.__turboModuleProxy("RNPulsar") != null;
26
- }
27
- return NativeModules?.RNPulsar != null;
28
- } catch {
29
- return false;
30
- }
31
- }
32
- function getPulsar() {
33
- if (Platform.OS === "web") return null;
34
- if (!_pulsarChecked) {
35
- _pulsarChecked = true;
36
- try {
37
- if (isPulsarNativeRegistered()) {
38
- _pulsar = __require("react-native-pulsar");
39
- _pulsarAvailable = true;
40
- }
41
- } catch {
42
- _pulsar = null;
43
- _pulsarAvailable = false;
44
- }
45
- }
46
- return _pulsarAvailable ? _pulsar : null;
47
- }
48
- function selectionAsync() {
49
- if (Platform.OS === "web") return;
50
- getHaptics().then((h) => {
51
- if (h) {
52
- h.selectionAsync();
53
- } else {
54
- getPulsar()?.Presets.System.selection();
55
- }
56
- });
57
- }
58
- function impactLight() {
59
- if (Platform.OS === "web") return;
60
- getHaptics().then((h) => {
61
- if (h) {
62
- h.impactAsync(h.ImpactFeedbackStyle.Light);
63
- } else {
64
- getPulsar()?.Presets.System.impactLight();
65
- }
66
- });
67
- }
68
- function impactMedium() {
69
- if (Platform.OS === "web") return;
70
- getHaptics().then((h) => {
71
- if (h) {
72
- h.impactAsync(h.ImpactFeedbackStyle.Medium);
73
- } else {
74
- getPulsar()?.Presets.System.impactMedium();
75
- }
76
- });
77
- }
78
- function impactHeavy() {
79
- if (Platform.OS === "web") return;
80
- getHaptics().then((h) => {
81
- if (h) {
82
- h.impactAsync(h.ImpactFeedbackStyle.Heavy);
83
- } else {
84
- getPulsar()?.Presets.System.impactHeavy();
85
- }
86
- });
87
- }
88
- function notificationSuccess() {
89
- if (Platform.OS === "web") return;
90
- getHaptics().then((h) => {
91
- if (h) {
92
- h.notificationAsync(h.NotificationFeedbackType.Success);
93
- } else {
94
- getPulsar()?.Presets.System.notificationSuccess();
95
- }
96
- });
97
- }
98
- function notificationError() {
99
- if (Platform.OS === "web") return;
100
- getHaptics().then((h) => {
101
- if (h) {
102
- h.notificationAsync(h.NotificationFeedbackType.Error);
103
- } else {
104
- getPulsar()?.Presets.System.notificationError();
105
- }
106
- });
107
- }
108
- function notificationWarning() {
109
- if (Platform.OS === "web") return;
110
- getHaptics().then((h) => {
111
- if (h) {
112
- h.notificationAsync(h.NotificationFeedbackType.Warning);
113
- } else {
114
- getPulsar()?.Presets.System.notificationWarning();
115
- }
116
- });
117
- }
118
- var richHaptics = {
119
- /** Hammer strike — strong confirmation feedback. */
120
- hammer: () => {
121
- if (Platform.OS === "web") return;
122
- const p = getPulsar();
123
- if (p) p.Presets.hammer();
124
- else impactHeavy();
125
- },
126
- /** Pulse — rhythmic feedback for toggles or state changes. */
127
- pulse: () => {
128
- if (Platform.OS === "web") return;
129
- const p = getPulsar();
130
- if (p) p.Presets.pulse();
131
- else selectionAsync();
132
- },
133
- /** Buzz — continuous vibration for attention. */
134
- buzz: () => {
135
- if (Platform.OS === "web") return;
136
- const p = getPulsar();
137
- if (p) p.Presets.buzz();
138
- else impactMedium();
139
- },
140
- /** Flick — crisp click feedback. */
141
- flick: () => {
142
- if (Platform.OS === "web") return;
143
- const p = getPulsar();
144
- if (p) p.Presets.flick();
145
- else selectionAsync();
146
- },
147
- /** Soft — gentle, subtle feedback. */
148
- soft: () => {
149
- if (Platform.OS === "web") return;
150
- const p = getPulsar();
151
- if (p) p.Presets.System.impactSoft();
152
- else impactLight();
153
- },
154
- /** Rigid — firm, solid feedback. */
155
- rigid: () => {
156
- if (Platform.OS === "web") return;
157
- const p = getPulsar();
158
- if (p) p.Presets.System.impactRigid();
159
- else impactMedium();
160
- }
161
- };
162
-
163
- export { impactHeavy, impactLight, impactMedium, notificationError, notificationSuccess, notificationWarning, richHaptics, selectionAsync };
@@ -1,134 +0,0 @@
1
- import { usePressScale } from './chunk-YNROWHQJ.mjs';
2
- import { selectionAsync } from './chunk-EJ7ZPXOH.mjs';
3
- import { PRESS_SCALE, COLOR_TRANSITION, SPRING_ELASTIC } from './chunk-DVK4G2GT.mjs';
4
- import { useTheme } from './chunk-EMUWGDWC.mjs';
5
- import { mvs, ms, s, vs } from './chunk-2CE3TQVY.mjs';
6
- import React from 'react';
7
- import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';
8
- import Animated from 'react-native-reanimated';
9
- import { EaseView } from 'react-native-ease';
10
-
11
- function RadioItem({
12
- option,
13
- selected,
14
- onSelect
15
- }) {
16
- const { colors } = useTheme();
17
- const { animatedStyle: scaleStyle, onPressIn, onPressOut } = usePressScale({
18
- pressScale: PRESS_SCALE.button,
19
- disabled: option.disabled
20
- });
21
- return (
22
- // AUDIT FIX: opacity was applied only to the radio circle, leaving the label
23
- // at full opacity when disabled. The whole row now dims uniformly so users
24
- // get a single, consistent disabled signal across the entire item.
25
- /* @__PURE__ */ React.createElement(
26
- TouchableOpacity,
27
- {
28
- style: [styles.row, option.disabled && styles.rowDisabled],
29
- onPress: () => {
30
- if (!option.disabled) {
31
- selectionAsync();
32
- onSelect();
33
- }
34
- },
35
- onPressIn,
36
- onPressOut,
37
- activeOpacity: 1,
38
- touchSoundDisabled: true,
39
- disabled: option.disabled,
40
- accessibilityRole: "radio",
41
- accessibilityLabel: option.label,
42
- accessibilityState: { checked: selected, disabled: !!option.disabled }
43
- },
44
- /* @__PURE__ */ React.createElement(Animated.View, { style: scaleStyle }, /* @__PURE__ */ React.createElement(
45
- EaseView,
46
- {
47
- style: styles.radio,
48
- animate: { borderColor: selected ? colors.primary : colors.border },
49
- transition: COLOR_TRANSITION
50
- },
51
- /* @__PURE__ */ React.createElement(
52
- EaseView,
53
- {
54
- style: [styles.dot, { backgroundColor: colors.primary }],
55
- animate: { scale: selected ? 1 : 0, opacity: selected ? 1 : 0 },
56
- transition: SPRING_ELASTIC
57
- }
58
- )
59
- )),
60
- /* @__PURE__ */ React.createElement(
61
- Text,
62
- {
63
- style: [styles.label, { color: colors.foreground }],
64
- allowFontScaling: true
65
- },
66
- option.label
67
- )
68
- )
69
- );
70
- }
71
- function RadioGroup({
72
- options,
73
- value,
74
- onValueChange,
75
- orientation = "vertical",
76
- style,
77
- accessibilityLabel
78
- }) {
79
- return /* @__PURE__ */ React.createElement(
80
- View,
81
- {
82
- style: [styles.container, orientation === "horizontal" && styles.horizontal, style],
83
- accessibilityRole: "radiogroup",
84
- accessibilityLabel
85
- },
86
- options.map((option) => /* @__PURE__ */ React.createElement(
87
- RadioItem,
88
- {
89
- key: option.value,
90
- option,
91
- selected: option.value === value,
92
- onSelect: () => onValueChange?.(option.value)
93
- }
94
- ))
95
- );
96
- }
97
- var styles = StyleSheet.create({
98
- container: {
99
- gap: vs(12)
100
- },
101
- horizontal: {
102
- flexDirection: "row",
103
- flexWrap: "wrap"
104
- },
105
- row: {
106
- flexDirection: "row",
107
- alignItems: "center",
108
- gap: s(12)
109
- },
110
- // AUDIT FIX: was opacity on the inner circle only
111
- rowDisabled: {
112
- opacity: 0.45
113
- },
114
- radio: {
115
- width: s(24),
116
- height: s(24),
117
- borderRadius: s(12),
118
- borderWidth: 1.5,
119
- alignItems: "center",
120
- justifyContent: "center"
121
- },
122
- dot: {
123
- width: s(10),
124
- height: s(10),
125
- borderRadius: s(5)
126
- },
127
- label: {
128
- fontFamily: "Sohne-Regular",
129
- fontSize: ms(14),
130
- lineHeight: mvs(20)
131
- }
132
- });
133
-
134
- export { RadioGroup };