@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
@@ -0,0 +1,515 @@
1
+ 'use strict';
2
+
3
+ var React4 = require('react');
4
+ var reactNative = require('react-native');
5
+ var reactNativeSafeAreaContext = require('react-native-safe-area-context');
6
+ var reactNativeSizeMatters = require('react-native-size-matters');
7
+ var AntDesign = require('@expo/vector-icons/AntDesign');
8
+ var Entypo = require('@expo/vector-icons/Entypo');
9
+ var Feather = require('@expo/vector-icons/Feather');
10
+ var FontAwesome5 = require('@expo/vector-icons/FontAwesome5');
11
+ var MaterialIcons = require('@expo/vector-icons/MaterialIcons');
12
+ var Ionicons = require('@expo/vector-icons/Ionicons');
13
+ var pressto = require('pressto');
14
+ var reactNativeReanimated = require('react-native-reanimated');
15
+
16
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
+
18
+ var React4__default = /*#__PURE__*/_interopDefault(React4);
19
+ var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
20
+ var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
21
+ var Feather__default = /*#__PURE__*/_interopDefault(Feather);
22
+ var FontAwesome5__default = /*#__PURE__*/_interopDefault(FontAwesome5);
23
+ var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
24
+ var Ionicons__default = /*#__PURE__*/_interopDefault(Ionicons);
25
+
26
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
27
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
28
+ }) : x)(function(x) {
29
+ if (typeof require !== "undefined") return require.apply(this, arguments);
30
+ throw Error('Dynamic require of "' + x + '" is not supported');
31
+ });
32
+
33
+ // src/theme/colorUtils.ts
34
+ function hexToRgb(hex) {
35
+ const clean = hex.replace("#", "");
36
+ const full = clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean;
37
+ if (full.length !== 6) return null;
38
+ return {
39
+ r: parseInt(full.slice(0, 2), 16),
40
+ g: parseInt(full.slice(2, 4), 16),
41
+ b: parseInt(full.slice(4, 6), 16)
42
+ };
43
+ }
44
+ function componentToHex(c) {
45
+ return Math.round(Math.max(0, Math.min(255, c))).toString(16).padStart(2, "0");
46
+ }
47
+ function rgbToHex(r, g, b) {
48
+ return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
49
+ }
50
+ function withAlphaOnWhite(hex, alpha) {
51
+ const rgb = hexToRgb(hex);
52
+ if (!rgb) return hex;
53
+ const r = rgb.r * alpha + 255 * (1 - alpha);
54
+ const g = rgb.g * alpha + 255 * (1 - alpha);
55
+ const b = rgb.b * alpha + 255 * (1 - alpha);
56
+ return rgbToHex(r, g, b);
57
+ }
58
+ function withAlphaOnDark(hex, alpha, bgHex = "#0f0f0f") {
59
+ const rgb = hexToRgb(hex);
60
+ const bg = hexToRgb(bgHex);
61
+ if (!rgb || !bg) return hex;
62
+ const r = rgb.r * alpha + bg.r * (1 - alpha);
63
+ const g = rgb.g * alpha + bg.g * (1 - alpha);
64
+ const b = rgb.b * alpha + bg.b * (1 - alpha);
65
+ return rgbToHex(r, g, b);
66
+ }
67
+ function mixWithBackground(fgHex, bgHex, opacity) {
68
+ const fg = hexToRgb(fgHex);
69
+ const bg = hexToRgb(bgHex);
70
+ if (!fg || !bg) return fgHex;
71
+ const r = fg.r * opacity + bg.r * (1 - opacity);
72
+ const g = fg.g * opacity + bg.g * (1 - opacity);
73
+ const b = fg.b * opacity + bg.b * (1 - opacity);
74
+ return rgbToHex(r, g, b);
75
+ }
76
+ function lighten(hex, amount) {
77
+ return withAlphaOnWhite(hex, 1 - amount);
78
+ }
79
+ function darken(hex, amount) {
80
+ const rgb = hexToRgb(hex);
81
+ if (!rgb) return hex;
82
+ return rgbToHex(rgb.r * (1 - amount), rgb.g * (1 - amount), rgb.b * (1 - amount));
83
+ }
84
+
85
+ // src/theme/colors.ts
86
+ var defaultLight = {
87
+ background: "#ffffff",
88
+ foreground: "#1a1a1a",
89
+ card: "#ffffff",
90
+ primary: "#1a1a1a",
91
+ primaryForeground: "#ffffff",
92
+ // AUDIT FIX: brand accent — was undefined; falls back to primary when omitted
93
+ accent: "#d4561d",
94
+ accentForeground: "#ffffff",
95
+ border: "#dddddd",
96
+ // AUDIT FIX: was #e53935 (4.22:1 on white — fails AA); #c72828 = 5.59:1 ✓
97
+ destructive: "#c72828",
98
+ destructiveForeground: "#ffffff",
99
+ success: "#1a7a45",
100
+ successForeground: "#ffffff",
101
+ // AUDIT FIX: was #e67e00 (2.86:1 — severe fail); #9a5200 = 5.86:1 ✓ AAA-near
102
+ warning: "#9a5200",
103
+ warningForeground: "#ffffff"
104
+ };
105
+ function deriveColors(t, scheme) {
106
+ const dark = scheme === "dark";
107
+ const bg = t.background;
108
+ const foregroundSubtle = mixWithBackground(t.foreground, bg, 0.7);
109
+ const foregroundMuted = mixWithBackground(t.foreground, bg, 0.62);
110
+ const surface = dark ? lighten(bg, -0.06) : darken(bg, 0.04);
111
+ const surfaceStrong = dark ? lighten(bg, -0.12) : darken(bg, 0.08);
112
+ const destructiveTint = dark ? withAlphaOnDark(t.destructive, 0.15, bg) : withAlphaOnWhite(t.destructive, 0.08);
113
+ const destructiveBorder = dark ? withAlphaOnDark(t.destructive, 0.45, bg) : withAlphaOnWhite(t.destructive, 0.3);
114
+ const successTint = dark ? withAlphaOnDark(t.success, 0.15, bg) : withAlphaOnWhite(t.success, 0.08);
115
+ const successBorder = dark ? withAlphaOnDark(t.success, 0.45, bg) : withAlphaOnWhite(t.success, 0.3);
116
+ const warningTint = dark ? withAlphaOnDark(t.warning, 0.15, bg) : withAlphaOnWhite(t.warning, 0.08);
117
+ const warningBorder = dark ? withAlphaOnDark(t.warning, 0.45, bg) : withAlphaOnWhite(t.warning, 0.3);
118
+ return {
119
+ ...t,
120
+ foregroundSubtle,
121
+ foregroundMuted,
122
+ surface,
123
+ surfaceStrong,
124
+ destructiveTint,
125
+ destructiveBorder,
126
+ successTint,
127
+ successBorder,
128
+ warningTint,
129
+ warningBorder,
130
+ overlay: t.overlay ?? "rgba(0,0,0,0.45)",
131
+ accentResolved: t.accent ?? t.primary,
132
+ accentForegroundResolved: t.accentForeground ?? t.primaryForeground,
133
+ ring: t.accent ?? t.primary,
134
+ input: t.border,
135
+ separator: dark ? lighten(t.border, 0.22) : darken(t.border, 0.16)
136
+ };
137
+ }
138
+
139
+ // src/theme/ThemeProvider.tsx
140
+ var ThemeContext = React4.createContext({
141
+ colors: deriveColors(defaultLight, "light"),
142
+ colorScheme: "light"
143
+ });
144
+ function useTheme() {
145
+ const context = React4.useContext(ThemeContext);
146
+ if (!context) {
147
+ throw new Error("useTheme must be used within a ThemeProvider");
148
+ }
149
+ return context;
150
+ }
151
+ var _haptics = null;
152
+ var _hapticsLoaded = false;
153
+ async function getHaptics() {
154
+ if (reactNative.Platform.OS === "web") return null;
155
+ if (!_hapticsLoaded) {
156
+ _hapticsLoaded = true;
157
+ try {
158
+ _haptics = await import('expo-haptics');
159
+ } catch {
160
+ _haptics = null;
161
+ }
162
+ }
163
+ return _haptics;
164
+ }
165
+ var _pulsar = null;
166
+ var _pulsarChecked = false;
167
+ var _pulsarAvailable = false;
168
+ function isPulsarNativeRegistered() {
169
+ try {
170
+ const g = globalThis;
171
+ if (typeof g.__turboModuleProxy === "function") {
172
+ return g.__turboModuleProxy("RNPulsar") != null;
173
+ }
174
+ return reactNative.NativeModules?.RNPulsar != null;
175
+ } catch {
176
+ return false;
177
+ }
178
+ }
179
+ function getPulsar() {
180
+ if (reactNative.Platform.OS === "web") return null;
181
+ if (!_pulsarChecked) {
182
+ _pulsarChecked = true;
183
+ try {
184
+ if (isPulsarNativeRegistered()) {
185
+ _pulsar = __require("react-native-pulsar");
186
+ _pulsarAvailable = true;
187
+ }
188
+ } catch {
189
+ _pulsar = null;
190
+ _pulsarAvailable = false;
191
+ }
192
+ }
193
+ return _pulsarAvailable ? _pulsar : null;
194
+ }
195
+ function impactLight() {
196
+ if (reactNative.Platform.OS === "web") return;
197
+ getHaptics().then((h) => {
198
+ if (h) {
199
+ h.impactAsync(h.ImpactFeedbackStyle.Light);
200
+ } else {
201
+ getPulsar()?.Presets.System.impactLight();
202
+ }
203
+ });
204
+ }
205
+ var isWeb = reactNative.Platform.OS === "web";
206
+ var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
207
+ var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
208
+ var ms = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateScale;
209
+ var mvs = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateVerticalScale;
210
+ var glyphMapOf = (mod) => mod.glyphMap ?? {};
211
+ var ALL_FAMILIES = [
212
+ { name: "Ionicons", component: Ionicons__default.default, getGlyphMap: () => glyphMapOf(Ionicons__default.default) },
213
+ { name: "MaterialIcons", component: MaterialIcons__default.default, getGlyphMap: () => glyphMapOf(MaterialIcons__default.default) },
214
+ { name: "FontAwesome5", component: FontAwesome5__default.default, getGlyphMap: () => glyphMapOf(FontAwesome5__default.default) },
215
+ { name: "Entypo", component: Entypo__default.default, getGlyphMap: () => glyphMapOf(Entypo__default.default) },
216
+ { name: "AntDesign", component: AntDesign__default.default, getGlyphMap: () => glyphMapOf(AntDesign__default.default) },
217
+ { name: "Feather", component: Feather__default.default, getGlyphMap: () => glyphMapOf(Feather__default.default) }
218
+ ];
219
+ var activeFamilies = ALL_FAMILIES;
220
+ var resolvedCache = null;
221
+ function buildCache() {
222
+ const cache = /* @__PURE__ */ new Map();
223
+ for (const family of activeFamilies) {
224
+ const glyphMap = family.getGlyphMap();
225
+ for (const iconName of Object.keys(glyphMap)) {
226
+ cache.set(iconName, family);
227
+ }
228
+ }
229
+ return cache;
230
+ }
231
+ function resolveFamily(name) {
232
+ if (!resolvedCache) {
233
+ resolvedCache = buildCache();
234
+ }
235
+ return resolvedCache.get(name) ?? null;
236
+ }
237
+ function Icon({ name, size, color, family }) {
238
+ let resolved = null;
239
+ if (family) {
240
+ resolved = ALL_FAMILIES.find((f) => f.name === family) ?? null;
241
+ } else {
242
+ resolved = resolveFamily(name);
243
+ }
244
+ if (!resolved) return null;
245
+ const Component = resolved.component;
246
+ return React4__default.default.createElement(Component, { name, size, color });
247
+ }
248
+ function renderIcon(name, size, color) {
249
+ return React4__default.default.createElement(Icon, { name, size, color });
250
+ }
251
+ ({
252
+ /** Material-style ease-out — natural deceleration for state changes. */
253
+ standard: reactNativeReanimated.Easing.bezier(0.2, 0, 0, 1),
254
+ /** Strong ease-out for expanding surfaces (Accordion open). */
255
+ expand: reactNativeReanimated.Easing.bezier(0.23, 1, 0.32, 1),
256
+ /** Quick ease-in for collapsing. */
257
+ collapse: reactNativeReanimated.Easing.in(reactNativeReanimated.Easing.ease)
258
+ });
259
+ var PRESS_SCALE = {
260
+ button: 0.95,
261
+ card: 0.98,
262
+ row: 0.97,
263
+ chip: 0.94
264
+ };
265
+ var PressableButton = pressto.createAnimatedPressable((progress) => {
266
+ "worklet";
267
+ const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
268
+ return { transform: [{ scale: scale2 }] };
269
+ });
270
+ pressto.createAnimatedPressable((progress) => {
271
+ "worklet";
272
+ const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
273
+ return { transform: [{ scale: scale2 }] };
274
+ });
275
+ pressto.createAnimatedPressable((progress) => {
276
+ "worklet";
277
+ const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
278
+ return { transform: [{ scale: scale2 }] };
279
+ });
280
+ pressto.createAnimatedPressable((progress) => {
281
+ "worklet";
282
+ const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
283
+ return { transform: [{ scale: scale2 }] };
284
+ });
285
+ pressto.createAnimatedPressable((progress) => {
286
+ "worklet";
287
+ const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
288
+ return { transform: [{ scale: scale2 }] };
289
+ });
290
+
291
+ // src/components/IconButton/IconButton.tsx
292
+ var sizeMap = {
293
+ // AUDIT FIX: sm was 32pt — below Apple HIG 44pt minimum touch target.
294
+ sm: { container: s(44), icon: 18 },
295
+ md: { container: s(44), icon: 20 },
296
+ lg: { container: s(52), icon: 24 }
297
+ };
298
+ function IconButtonBase({
299
+ iconName,
300
+ icon,
301
+ iconColor,
302
+ variant = "primary",
303
+ size = "md",
304
+ loading = false,
305
+ badge,
306
+ disabled,
307
+ style,
308
+ onPress,
309
+ accessibilityLabel,
310
+ accessibilityHint
311
+ }) {
312
+ const { colors } = useTheme();
313
+ const isDisabled = disabled || loading;
314
+ const handlePress = () => {
315
+ impactLight();
316
+ onPress?.();
317
+ };
318
+ const containerVariantStyle = {
319
+ primary: { backgroundColor: colors.primary },
320
+ secondary: { backgroundColor: colors.surface },
321
+ outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: colors.border },
322
+ text: { backgroundColor: "transparent" },
323
+ destructive: { backgroundColor: colors.destructive }
324
+ }[variant];
325
+ const defaultIconColor = {
326
+ primary: colors.primaryForeground,
327
+ secondary: colors.foreground,
328
+ outline: colors.foreground,
329
+ text: colors.foreground,
330
+ destructive: colors.destructiveForeground
331
+ }[variant];
332
+ const spinnerColor = variant === "destructive" ? colors.destructiveForeground : variant === "primary" ? colors.primaryForeground : colors.foreground;
333
+ const { container: containerSize, icon: iconSize } = sizeMap[size];
334
+ const resolvedIcon = iconName ? renderIcon(iconName, iconSize, iconColor ?? defaultIconColor) : icon;
335
+ const showBadge = badge !== void 0 && badge !== false && badge !== 0;
336
+ const badgeCount = typeof badge === "number" ? Math.min(badge, 99) : null;
337
+ const showCount = typeof badge === "number" && badge > 0;
338
+ return /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles.wrapper }, /* @__PURE__ */ React4__default.default.createElement(
339
+ PressableButton,
340
+ {
341
+ style: [
342
+ styles.base,
343
+ containerVariantStyle,
344
+ { width: containerSize, height: containerSize },
345
+ isDisabled && styles.disabled,
346
+ style
347
+ ],
348
+ enabled: !isDisabled,
349
+ onPress: handlePress,
350
+ rippleColor: "transparent",
351
+ touchSoundDisabled: true,
352
+ activateOnHover: true,
353
+ accessibilityRole: "button",
354
+ accessibilityLabel: accessibilityLabel ?? iconName ?? "icon button",
355
+ accessibilityHint,
356
+ accessibilityState: { disabled: isDisabled, busy: loading }
357
+ },
358
+ loading ? /* @__PURE__ */ React4__default.default.createElement(reactNative.ActivityIndicator, { size: "small", color: spinnerColor }) : resolvedIcon
359
+ ), showBadge && /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [
360
+ styles.badge,
361
+ { backgroundColor: colors.primary },
362
+ showCount ? styles.badgeCount : styles.badgeDot
363
+ ] }, showCount && /* @__PURE__ */ React4__default.default.createElement(reactNative.Text, { style: [styles.badgeText, { color: colors.primaryForeground }] }, badgeCount)));
364
+ }
365
+ var IconButton = React4__default.default.memo(IconButtonBase);
366
+ var styles = reactNative.StyleSheet.create({
367
+ wrapper: {
368
+ alignSelf: "flex-start"
369
+ },
370
+ base: {
371
+ borderRadius: 9999,
372
+ alignItems: "center",
373
+ justifyContent: "center"
374
+ },
375
+ disabled: {
376
+ opacity: 0.45
377
+ },
378
+ badge: {
379
+ position: "absolute",
380
+ top: -2,
381
+ right: -2,
382
+ alignItems: "center",
383
+ justifyContent: "center"
384
+ },
385
+ badgeDot: {
386
+ width: 8,
387
+ height: 8,
388
+ borderRadius: 9999
389
+ },
390
+ badgeCount: {
391
+ minWidth: 16,
392
+ height: 16,
393
+ borderRadius: 9999,
394
+ paddingHorizontal: 3
395
+ },
396
+ badgeText: {
397
+ fontFamily: "Sohne-Bold",
398
+ fontSize: ms(9),
399
+ lineHeight: 14
400
+ }
401
+ });
402
+
403
+ // src/tokens.ts
404
+ var BREAKPOINTS = {
405
+ wide: 700
406
+ };
407
+
408
+ // src/components/AppHeader/AppHeader.tsx
409
+ function AppHeader({
410
+ title,
411
+ subtitle,
412
+ onBack,
413
+ backIconName = "chevron-left",
414
+ left,
415
+ right,
416
+ titleAlign = "auto",
417
+ bordered = true,
418
+ withSafeArea = true,
419
+ backgroundColor,
420
+ style
421
+ }) {
422
+ const { colors } = useTheme();
423
+ const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
424
+ const { width } = reactNative.useWindowDimensions();
425
+ const isWide = width >= BREAKPOINTS.wide;
426
+ const centered = titleAlign === "center" || titleAlign === "auto" && isWide;
427
+ const leftNode = left ?? (onBack ? /* @__PURE__ */ React4__default.default.createElement(
428
+ IconButton,
429
+ {
430
+ iconName: backIconName,
431
+ variant: "text",
432
+ size: "md",
433
+ onPress: onBack,
434
+ accessibilityLabel: "Go back"
435
+ }
436
+ ) : null);
437
+ const titleBlock = /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.titleBlock, centered && styles2.titleBlockCentered], pointerEvents: "none" }, title ? /* @__PURE__ */ React4__default.default.createElement(
438
+ reactNative.Text,
439
+ {
440
+ style: [styles2.title, { color: colors.foreground }, centered && styles2.textCentered],
441
+ numberOfLines: 1,
442
+ allowFontScaling: true,
443
+ accessibilityRole: "header"
444
+ },
445
+ title
446
+ ) : null, subtitle ? /* @__PURE__ */ React4__default.default.createElement(
447
+ reactNative.Text,
448
+ {
449
+ style: [styles2.subtitle, { color: colors.foregroundMuted }, centered && styles2.textCentered],
450
+ numberOfLines: 1,
451
+ allowFontScaling: true
452
+ },
453
+ subtitle
454
+ ) : null);
455
+ return /* @__PURE__ */ React4__default.default.createElement(
456
+ reactNative.View,
457
+ {
458
+ style: [
459
+ styles2.container,
460
+ {
461
+ backgroundColor: backgroundColor ?? colors.background,
462
+ paddingTop: withSafeArea ? insets.top : 0,
463
+ borderBottomWidth: bordered ? reactNative.StyleSheet.hairlineWidth : 0,
464
+ borderBottomColor: colors.border
465
+ },
466
+ style
467
+ ]
468
+ },
469
+ /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles2.bar }, centered ? /* @__PURE__ */ React4__default.default.createElement(React4__default.default.Fragment, null, /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: reactNative.StyleSheet.absoluteFill }, titleBlock), /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles2.side }, leftNode), /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.side, styles2.sideRight] }, right)) : /* @__PURE__ */ React4__default.default.createElement(React4__default.default.Fragment, null, /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: styles2.side }, leftNode), titleBlock, /* @__PURE__ */ React4__default.default.createElement(reactNative.View, { style: [styles2.side, styles2.sideRight] }, right)))
470
+ );
471
+ }
472
+ var styles2 = reactNative.StyleSheet.create({
473
+ container: {
474
+ width: "100%"
475
+ },
476
+ bar: {
477
+ minHeight: vs(48),
478
+ flexDirection: "row",
479
+ alignItems: "center",
480
+ paddingHorizontal: s(8)
481
+ },
482
+ side: {
483
+ minWidth: s(44),
484
+ flexDirection: "row",
485
+ alignItems: "center",
486
+ justifyContent: "flex-start"
487
+ },
488
+ sideRight: {
489
+ justifyContent: "flex-end"
490
+ },
491
+ titleBlock: {
492
+ flex: 1,
493
+ justifyContent: "center",
494
+ paddingHorizontal: s(8),
495
+ gap: vs(1)
496
+ },
497
+ titleBlockCentered: {
498
+ alignItems: "center"
499
+ },
500
+ title: {
501
+ fontFamily: "Sohne-SemiBold",
502
+ fontSize: ms(18),
503
+ lineHeight: mvs(24)
504
+ },
505
+ subtitle: {
506
+ fontFamily: "Sohne-Regular",
507
+ fontSize: ms(13),
508
+ lineHeight: mvs(16)
509
+ },
510
+ textCentered: {
511
+ textAlign: "center"
512
+ }
513
+ });
514
+
515
+ exports.AppHeader = AppHeader;
@@ -0,0 +1,10 @@
1
+ export { AppHeader } from './chunk-AZJF2BLK.mjs';
2
+ import './chunk-3U4SSNWP.mjs';
3
+ import './chunk-3DKJ2GIC.mjs';
4
+ import './chunk-EJ7ZPXOH.mjs';
5
+ import './chunk-DVK4G2GT.mjs';
6
+ import './chunk-QY3X2UYR.mjs';
7
+ import './chunk-T7XZ7H7Y.mjs';
8
+ import './chunk-SOYNZDVY.mjs';
9
+ import './chunk-2CE3TQVY.mjs';
10
+ import './chunk-Y6FXYEAI.mjs';
package/dist/Avatar.js CHANGED
@@ -168,7 +168,7 @@ function AvatarBase({ src, fallback, fallbackText, size = "md", status, style })
168
168
  const showFallback = !src || imageError;
169
169
  const statusSize = typeof size === "number" ? size * 0.25 : statusSizeMap[size];
170
170
  const statusColor = {
171
- online: "#22c55e",
171
+ online: colors.success,
172
172
  offline: "transparent",
173
173
  busy: colors.destructive,
174
174
  away: colors.warning
@@ -180,36 +180,46 @@ function AvatarBase({ src, fallback, fallbackText, size = "md", status, style })
180
180
  backgroundColor: colors.surface,
181
181
  overflow: "hidden"
182
182
  };
183
- return /* @__PURE__ */ React2__default.default.createElement(reactNative.View, { style: [styles.wrapper, style] }, /* @__PURE__ */ React2__default.default.createElement(reactNative.View, { style: [styles.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React2__default.default.createElement(
184
- reactNative.Image,
185
- {
186
- source: { uri: src },
187
- style: { width: dimension, height: dimension },
188
- onError: () => setImageError(true)
189
- }
190
- ) : /* @__PURE__ */ React2__default.default.createElement(
191
- reactNative.Text,
192
- {
193
- style: [styles.fallback, { color: colors.foregroundMuted, fontSize }],
194
- allowFontScaling: true
195
- },
196
- getInitials(fallback, fallbackText)
197
- )), status && /* @__PURE__ */ React2__default.default.createElement(
183
+ const a11yLabel = fallbackText || fallback || "Avatar";
184
+ return /* @__PURE__ */ React2__default.default.createElement(
198
185
  reactNative.View,
199
186
  {
200
- style: [
201
- styles.statusDot,
202
- {
203
- width: statusSize,
204
- height: statusSize,
205
- borderRadius: statusSize / 2,
206
- backgroundColor: statusColor[status],
207
- borderWidth: status === "offline" ? 2 : 1.5,
208
- borderColor: status === "offline" ? colors.border : colors.background
209
- }
210
- ]
211
- }
212
- ));
187
+ style: [styles.wrapper, style],
188
+ accessibilityRole: "image",
189
+ accessibilityLabel: a11yLabel
190
+ },
191
+ /* @__PURE__ */ React2__default.default.createElement(reactNative.View, { style: [styles.base, containerStyle] }, !showFallback ? /* @__PURE__ */ React2__default.default.createElement(
192
+ reactNative.Image,
193
+ {
194
+ source: { uri: src },
195
+ style: { width: dimension, height: dimension },
196
+ onError: () => setImageError(true)
197
+ }
198
+ ) : /* @__PURE__ */ React2__default.default.createElement(
199
+ reactNative.Text,
200
+ {
201
+ style: [styles.fallback, { color: colors.foregroundMuted, fontSize }],
202
+ allowFontScaling: true
203
+ },
204
+ getInitials(fallback, fallbackText)
205
+ )),
206
+ status && /* @__PURE__ */ React2__default.default.createElement(
207
+ reactNative.View,
208
+ {
209
+ style: [
210
+ styles.statusDot,
211
+ {
212
+ width: statusSize,
213
+ height: statusSize,
214
+ borderRadius: statusSize / 2,
215
+ backgroundColor: statusColor[status],
216
+ borderWidth: status === "offline" ? 2 : 1.5,
217
+ borderColor: status === "offline" ? colors.border : colors.background
218
+ }
219
+ ]
220
+ }
221
+ )
222
+ );
213
223
  }
214
224
  var Avatar = React2__default.default.memo(AvatarBase);
215
225
  var styles = reactNative.StyleSheet.create({
package/dist/Avatar.mjs CHANGED
@@ -1,3 +1,4 @@
1
- export { Avatar } from './chunk-GCWOGZYL.mjs';
1
+ export { Avatar } from './chunk-JT7HKXRB.mjs';
2
2
  import './chunk-SOYNZDVY.mjs';
3
3
  import './chunk-2CE3TQVY.mjs';
4
+ import './chunk-Y6FXYEAI.mjs';
package/dist/Badge.js CHANGED
@@ -229,7 +229,17 @@ function BadgeBase({ label, children, variant = "default", size = "md", icon, ic
229
229
  }[variant];
230
230
  const effectiveIcon = iconName ? renderIcon(iconName, sizeIconSize[size], iconColor ?? textColor) : icon;
231
231
  const content = children ?? label;
232
- return /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: [styles.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style] }, effectiveIcon, typeof content === "string" ? /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles.label, { color: textColor }, sizeFontSize[size]], allowFontScaling: true }, content) : content);
232
+ const a11yLabel = typeof content === "string" ? content : label;
233
+ return /* @__PURE__ */ React3__default.default.createElement(
234
+ reactNative.View,
235
+ {
236
+ style: [styles.container, containerStyle, sizePadding[size], { gap: sizeIconGap[size] }, style],
237
+ accessibilityRole: "text",
238
+ accessibilityLabel: a11yLabel
239
+ },
240
+ effectiveIcon,
241
+ typeof content === "string" ? /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles.label, { color: textColor }, sizeFontSize[size]], allowFontScaling: true }, content) : content
242
+ );
233
243
  }
234
244
  var Badge = React3__default.default.memo(BadgeBase);
235
245
  var styles = reactNative.StyleSheet.create({
package/dist/Badge.mjs CHANGED
@@ -1,4 +1,5 @@
1
- export { Badge } from './chunk-KZJRQOIU.mjs';
1
+ export { Badge } from './chunk-TERDKCLE.mjs';
2
2
  import './chunk-T7XZ7H7Y.mjs';
3
3
  import './chunk-SOYNZDVY.mjs';
4
4
  import './chunk-2CE3TQVY.mjs';
5
+ import './chunk-Y6FXYEAI.mjs';
package/dist/Button.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import { TouchableOpacityProps } from 'react-native';
2
+ import { ViewStyle } from 'react-native';
3
3
 
4
4
  type ButtonVariant = 'primary' | 'secondary' | 'text' | 'destructive';
5
5
  type ButtonSize = 'sm' | 'md' | 'lg';
6
- interface ButtonProps extends TouchableOpacityProps {
6
+ interface ButtonProps {
7
7
  label: string;
8
8
  variant?: ButtonVariant;
9
9
  size?: ButtonSize;
@@ -18,8 +18,13 @@ interface ButtonProps extends TouchableOpacityProps {
18
18
  iconName?: string;
19
19
  iconColor?: string;
20
20
  iconPosition?: 'left' | 'right';
21
+ disabled?: boolean;
22
+ style?: ViewStyle;
23
+ onPress?: () => void;
24
+ accessibilityLabel?: string;
25
+ accessibilityHint?: string;
21
26
  }
22
- declare function ButtonBase({ label, variant, size, loading, fullWidth, icon, iconName, iconColor, iconPosition, disabled, style, onPress, accessibilityLabel, accessibilityHint, ...props }: ButtonProps): React.JSX.Element;
27
+ declare function ButtonBase({ label, variant, size, loading, fullWidth, icon, iconName, iconColor, iconPosition, disabled, style, onPress, accessibilityLabel, accessibilityHint, }: ButtonProps): React.JSX.Element;
23
28
  declare const Button: React.MemoExoticComponent<typeof ButtonBase>;
24
29
 
25
30
  export { Button, type ButtonProps, type ButtonSize, type ButtonVariant };