@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,392 @@
1
+ 'use strict';
2
+
3
+ var React3 = require('react');
4
+ var reactNative = require('react-native');
5
+ var Animated = require('react-native-reanimated');
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
+
14
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
+
16
+ var React3__default = /*#__PURE__*/_interopDefault(React3);
17
+ var Animated__default = /*#__PURE__*/_interopDefault(Animated);
18
+ var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
19
+ var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
20
+ var Feather__default = /*#__PURE__*/_interopDefault(Feather);
21
+ var FontAwesome5__default = /*#__PURE__*/_interopDefault(FontAwesome5);
22
+ var MaterialIcons__default = /*#__PURE__*/_interopDefault(MaterialIcons);
23
+ var Ionicons__default = /*#__PURE__*/_interopDefault(Ionicons);
24
+
25
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
26
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
27
+ }) : x)(function(x) {
28
+ if (typeof require !== "undefined") return require.apply(this, arguments);
29
+ throw Error('Dynamic require of "' + x + '" is not supported');
30
+ });
31
+
32
+ // src/theme/colorUtils.ts
33
+ function hexToRgb(hex) {
34
+ const clean = hex.replace("#", "");
35
+ const full = clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean;
36
+ if (full.length !== 6) return null;
37
+ return {
38
+ r: parseInt(full.slice(0, 2), 16),
39
+ g: parseInt(full.slice(2, 4), 16),
40
+ b: parseInt(full.slice(4, 6), 16)
41
+ };
42
+ }
43
+ function componentToHex(c) {
44
+ return Math.round(Math.max(0, Math.min(255, c))).toString(16).padStart(2, "0");
45
+ }
46
+ function rgbToHex(r, g, b) {
47
+ return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
48
+ }
49
+ function withAlphaOnWhite(hex, alpha) {
50
+ const rgb = hexToRgb(hex);
51
+ if (!rgb) return hex;
52
+ const r = rgb.r * alpha + 255 * (1 - alpha);
53
+ const g = rgb.g * alpha + 255 * (1 - alpha);
54
+ const b = rgb.b * alpha + 255 * (1 - alpha);
55
+ return rgbToHex(r, g, b);
56
+ }
57
+ function withAlphaOnDark(hex, alpha, bgHex = "#0f0f0f") {
58
+ const rgb = hexToRgb(hex);
59
+ const bg = hexToRgb(bgHex);
60
+ if (!rgb || !bg) return hex;
61
+ const r = rgb.r * alpha + bg.r * (1 - alpha);
62
+ const g = rgb.g * alpha + bg.g * (1 - alpha);
63
+ const b = rgb.b * alpha + bg.b * (1 - alpha);
64
+ return rgbToHex(r, g, b);
65
+ }
66
+ function mixWithBackground(fgHex, bgHex, opacity) {
67
+ const fg = hexToRgb(fgHex);
68
+ const bg = hexToRgb(bgHex);
69
+ if (!fg || !bg) return fgHex;
70
+ const r = fg.r * opacity + bg.r * (1 - opacity);
71
+ const g = fg.g * opacity + bg.g * (1 - opacity);
72
+ const b = fg.b * opacity + bg.b * (1 - opacity);
73
+ return rgbToHex(r, g, b);
74
+ }
75
+ function lighten(hex, amount) {
76
+ return withAlphaOnWhite(hex, 1 - amount);
77
+ }
78
+ function darken(hex, amount) {
79
+ const rgb = hexToRgb(hex);
80
+ if (!rgb) return hex;
81
+ return rgbToHex(rgb.r * (1 - amount), rgb.g * (1 - amount), rgb.b * (1 - amount));
82
+ }
83
+
84
+ // src/theme/colors.ts
85
+ var defaultLight = {
86
+ background: "#ffffff",
87
+ foreground: "#1a1a1a",
88
+ card: "#ffffff",
89
+ primary: "#1a1a1a",
90
+ primaryForeground: "#ffffff",
91
+ // AUDIT FIX: brand accent — was undefined; falls back to primary when omitted
92
+ accent: "#d4561d",
93
+ accentForeground: "#ffffff",
94
+ border: "#dddddd",
95
+ // AUDIT FIX: was #e53935 (4.22:1 on white — fails AA); #c72828 = 5.59:1 ✓
96
+ destructive: "#c72828",
97
+ destructiveForeground: "#ffffff",
98
+ success: "#1a7a45",
99
+ successForeground: "#ffffff",
100
+ // AUDIT FIX: was #e67e00 (2.86:1 — severe fail); #9a5200 = 5.86:1 ✓ AAA-near
101
+ warning: "#9a5200",
102
+ warningForeground: "#ffffff"
103
+ };
104
+ function deriveColors(t, scheme) {
105
+ const dark = scheme === "dark";
106
+ const bg = t.background;
107
+ const foregroundSubtle = mixWithBackground(t.foreground, bg, 0.7);
108
+ const foregroundMuted = mixWithBackground(t.foreground, bg, 0.62);
109
+ const surface = dark ? lighten(bg, -0.06) : darken(bg, 0.04);
110
+ const surfaceStrong = dark ? lighten(bg, -0.12) : darken(bg, 0.08);
111
+ const destructiveTint = dark ? withAlphaOnDark(t.destructive, 0.15, bg) : withAlphaOnWhite(t.destructive, 0.08);
112
+ const destructiveBorder = dark ? withAlphaOnDark(t.destructive, 0.45, bg) : withAlphaOnWhite(t.destructive, 0.3);
113
+ const successTint = dark ? withAlphaOnDark(t.success, 0.15, bg) : withAlphaOnWhite(t.success, 0.08);
114
+ const successBorder = dark ? withAlphaOnDark(t.success, 0.45, bg) : withAlphaOnWhite(t.success, 0.3);
115
+ const warningTint = dark ? withAlphaOnDark(t.warning, 0.15, bg) : withAlphaOnWhite(t.warning, 0.08);
116
+ const warningBorder = dark ? withAlphaOnDark(t.warning, 0.45, bg) : withAlphaOnWhite(t.warning, 0.3);
117
+ return {
118
+ ...t,
119
+ foregroundSubtle,
120
+ foregroundMuted,
121
+ surface,
122
+ surfaceStrong,
123
+ destructiveTint,
124
+ destructiveBorder,
125
+ successTint,
126
+ successBorder,
127
+ warningTint,
128
+ warningBorder,
129
+ overlay: t.overlay ?? "rgba(0,0,0,0.45)",
130
+ accentResolved: t.accent ?? t.primary,
131
+ accentForegroundResolved: t.accentForeground ?? t.primaryForeground,
132
+ ring: t.accent ?? t.primary,
133
+ input: t.border,
134
+ separator: dark ? lighten(t.border, 0.22) : darken(t.border, 0.16)
135
+ };
136
+ }
137
+
138
+ // src/theme/ThemeProvider.tsx
139
+ var ThemeContext = React3.createContext({
140
+ colors: deriveColors(defaultLight, "light"),
141
+ colorScheme: "light"
142
+ });
143
+ function useTheme() {
144
+ const context = React3.useContext(ThemeContext);
145
+ if (!context) {
146
+ throw new Error("useTheme must be used within a ThemeProvider");
147
+ }
148
+ return context;
149
+ }
150
+ var isWeb = reactNative.Platform.OS === "web";
151
+ var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
152
+ var SPRINGS = {
153
+ /** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
154
+ glide: { stiffness: 380, damping: 38, mass: 1 }};
155
+ ({
156
+ /** Material-style ease-out — natural deceleration for state changes. */
157
+ standard: Animated.Easing.bezier(0.2, 0, 0, 1),
158
+ /** Strong ease-out for expanding surfaces (Accordion open). */
159
+ expand: Animated.Easing.bezier(0.23, 1, 0.32, 1),
160
+ /** Quick ease-in for collapsing. */
161
+ collapse: Animated.Easing.in(Animated.Easing.ease)
162
+ });
163
+ var _haptics = null;
164
+ var _hapticsLoaded = false;
165
+ async function getHaptics() {
166
+ if (reactNative.Platform.OS === "web") return null;
167
+ if (!_hapticsLoaded) {
168
+ _hapticsLoaded = true;
169
+ try {
170
+ _haptics = await import('expo-haptics');
171
+ } catch {
172
+ _haptics = null;
173
+ }
174
+ }
175
+ return _haptics;
176
+ }
177
+ var _pulsar = null;
178
+ var _pulsarChecked = false;
179
+ var _pulsarAvailable = false;
180
+ function isPulsarNativeRegistered() {
181
+ try {
182
+ const g = globalThis;
183
+ if (typeof g.__turboModuleProxy === "function") {
184
+ return g.__turboModuleProxy("RNPulsar") != null;
185
+ }
186
+ return reactNative.NativeModules?.RNPulsar != null;
187
+ } catch {
188
+ return false;
189
+ }
190
+ }
191
+ function getPulsar() {
192
+ if (reactNative.Platform.OS === "web") return null;
193
+ if (!_pulsarChecked) {
194
+ _pulsarChecked = true;
195
+ try {
196
+ if (isPulsarNativeRegistered()) {
197
+ _pulsar = __require("react-native-pulsar");
198
+ _pulsarAvailable = true;
199
+ }
200
+ } catch {
201
+ _pulsar = null;
202
+ _pulsarAvailable = false;
203
+ }
204
+ }
205
+ return _pulsarAvailable ? _pulsar : null;
206
+ }
207
+ function selectionAsync() {
208
+ if (reactNative.Platform.OS === "web") return;
209
+ getHaptics().then((h) => {
210
+ if (h) {
211
+ h.selectionAsync();
212
+ } else {
213
+ getPulsar()?.Presets.System.selection();
214
+ }
215
+ });
216
+ }
217
+ var glyphMapOf = (mod) => mod.glyphMap ?? {};
218
+ var ALL_FAMILIES = [
219
+ { name: "Ionicons", component: Ionicons__default.default, getGlyphMap: () => glyphMapOf(Ionicons__default.default) },
220
+ { name: "MaterialIcons", component: MaterialIcons__default.default, getGlyphMap: () => glyphMapOf(MaterialIcons__default.default) },
221
+ { name: "FontAwesome5", component: FontAwesome5__default.default, getGlyphMap: () => glyphMapOf(FontAwesome5__default.default) },
222
+ { name: "Entypo", component: Entypo__default.default, getGlyphMap: () => glyphMapOf(Entypo__default.default) },
223
+ { name: "AntDesign", component: AntDesign__default.default, getGlyphMap: () => glyphMapOf(AntDesign__default.default) },
224
+ { name: "Feather", component: Feather__default.default, getGlyphMap: () => glyphMapOf(Feather__default.default) }
225
+ ];
226
+ var activeFamilies = ALL_FAMILIES;
227
+ var resolvedCache = null;
228
+ function buildCache() {
229
+ const cache = /* @__PURE__ */ new Map();
230
+ for (const family of activeFamilies) {
231
+ const glyphMap = family.getGlyphMap();
232
+ for (const iconName of Object.keys(glyphMap)) {
233
+ cache.set(iconName, family);
234
+ }
235
+ }
236
+ return cache;
237
+ }
238
+ function resolveFamily(name) {
239
+ if (!resolvedCache) {
240
+ resolvedCache = buildCache();
241
+ }
242
+ return resolvedCache.get(name) ?? null;
243
+ }
244
+ function Icon({ name, size, color, family }) {
245
+ let resolved = null;
246
+ if (family) {
247
+ resolved = ALL_FAMILIES.find((f) => f.name === family) ?? null;
248
+ } else {
249
+ resolved = resolveFamily(name);
250
+ }
251
+ if (!resolved) return null;
252
+ const Component = resolved.component;
253
+ return React3__default.default.createElement(Component, { name, size, color });
254
+ }
255
+ function renderIcon(name, size, color) {
256
+ return React3__default.default.createElement(Icon, { name, size, color });
257
+ }
258
+
259
+ // src/components/PagerDots/PagerDots.tsx
260
+ function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }) {
261
+ const progress = Animated.useSharedValue(active ? 1 : 0);
262
+ React3.useEffect(() => {
263
+ progress.value = Animated.withSpring(active ? 1 : 0, SPRINGS.glide);
264
+ }, [active, progress]);
265
+ const animatedStyle = Animated.useAnimatedStyle(() => ({
266
+ width: size + progress.value * size * 1.5,
267
+ backgroundColor: Animated.interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor])
268
+ }));
269
+ const dot = /* @__PURE__ */ React3__default.default.createElement(Animated__default.default.View, { style: [{ height: size, borderRadius: size / 2 }, animatedStyle] });
270
+ if (!onPress) return dot;
271
+ const handlePress = () => {
272
+ selectionAsync();
273
+ onPress();
274
+ };
275
+ return /* @__PURE__ */ React3__default.default.createElement(
276
+ reactNative.TouchableOpacity,
277
+ {
278
+ onPress: handlePress,
279
+ activeOpacity: 0.7,
280
+ touchSoundDisabled: true,
281
+ accessibilityRole: "button",
282
+ accessibilityLabel: `Page ${index + 1} of ${total}${active ? ", current page" : ""}`,
283
+ hitSlop: { top: 8, bottom: 8, left: 4, right: 4 }
284
+ },
285
+ dot
286
+ );
287
+ }
288
+ function PagerDots({
289
+ count,
290
+ activeIndex,
291
+ onDotPress,
292
+ showControls = false,
293
+ dotSize = 8,
294
+ spacing = 8,
295
+ activeColor,
296
+ inactiveColor,
297
+ style
298
+ }) {
299
+ const { colors } = useTheme();
300
+ const resolvedActive = activeColor ?? colors.primary;
301
+ const resolvedInactive = inactiveColor ?? colors.border;
302
+ const size = s(dotSize);
303
+ const hasControls = showControls !== false;
304
+ const canGoPrev = activeIndex > 0;
305
+ const canGoNext = activeIndex < count - 1;
306
+ const handlePrevious = () => {
307
+ if (!canGoPrev) return;
308
+ selectionAsync();
309
+ if (typeof showControls === "object" && showControls.onPrevious) {
310
+ showControls.onPrevious();
311
+ } else if (onDotPress) {
312
+ onDotPress(activeIndex - 1);
313
+ }
314
+ };
315
+ const handleNext = () => {
316
+ if (!canGoNext) return;
317
+ selectionAsync();
318
+ if (typeof showControls === "object" && showControls.onNext) {
319
+ showControls.onNext();
320
+ } else if (onDotPress) {
321
+ onDotPress(activeIndex + 1);
322
+ }
323
+ };
324
+ return /* @__PURE__ */ React3__default.default.createElement(
325
+ reactNative.View,
326
+ {
327
+ style: [styles.container, { gap: s(spacing) }, style],
328
+ accessibilityRole: "adjustable",
329
+ accessibilityLabel: `Page ${activeIndex + 1} of ${count}`
330
+ },
331
+ hasControls && /* @__PURE__ */ React3__default.default.createElement(
332
+ reactNative.TouchableOpacity,
333
+ {
334
+ onPress: handlePrevious,
335
+ disabled: !canGoPrev,
336
+ activeOpacity: 0.7,
337
+ touchSoundDisabled: true,
338
+ accessibilityRole: "button",
339
+ accessibilityLabel: "Previous page",
340
+ hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
341
+ style: [styles.controlBtn, !canGoPrev && styles.controlBtnDisabled]
342
+ },
343
+ renderIcon("chevron-left", s(18), canGoPrev ? colors.foreground : colors.foregroundMuted)
344
+ ),
345
+ /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: [styles.dotsRow, { gap: s(spacing) }] }, Array.from({ length: count }).map((_, i) => /* @__PURE__ */ React3__default.default.createElement(
346
+ Dot,
347
+ {
348
+ key: i,
349
+ active: i === activeIndex,
350
+ size,
351
+ activeColor: resolvedActive,
352
+ inactiveColor: resolvedInactive,
353
+ index: i,
354
+ total: count,
355
+ onPress: onDotPress ? () => onDotPress(i) : void 0
356
+ }
357
+ ))),
358
+ hasControls && /* @__PURE__ */ React3__default.default.createElement(
359
+ reactNative.TouchableOpacity,
360
+ {
361
+ onPress: handleNext,
362
+ disabled: !canGoNext,
363
+ activeOpacity: 0.7,
364
+ touchSoundDisabled: true,
365
+ accessibilityRole: "button",
366
+ accessibilityLabel: "Next page",
367
+ hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
368
+ style: [styles.controlBtn, !canGoNext && styles.controlBtnDisabled]
369
+ },
370
+ renderIcon("chevron-right", s(18), canGoNext ? colors.foreground : colors.foregroundMuted)
371
+ )
372
+ );
373
+ }
374
+ var styles = reactNative.StyleSheet.create({
375
+ container: {
376
+ flexDirection: "row",
377
+ alignItems: "center",
378
+ justifyContent: "center"
379
+ },
380
+ dotsRow: {
381
+ flexDirection: "row",
382
+ alignItems: "center"
383
+ },
384
+ controlBtn: {
385
+ padding: s(4)
386
+ },
387
+ controlBtnDisabled: {
388
+ opacity: 0.3
389
+ }
390
+ });
391
+
392
+ exports.PagerDots = PagerDots;
@@ -0,0 +1,7 @@
1
+ export { PagerDots } from './chunk-4K625MVM.mjs';
2
+ import './chunk-EJ7ZPXOH.mjs';
3
+ import './chunk-DVK4G2GT.mjs';
4
+ import './chunk-T7XZ7H7Y.mjs';
5
+ import './chunk-SOYNZDVY.mjs';
6
+ import './chunk-2CE3TQVY.mjs';
7
+ import './chunk-Y6FXYEAI.mjs';
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { TouchableOpacityProps, ViewStyle } from 'react-native';
2
+ import { ViewStyle } from 'react-native';
3
3
 
4
- interface PressableProps extends Omit<TouchableOpacityProps, 'activeOpacity'> {
4
+ interface PressableProps {
5
5
  /** Children content to render inside the pressable. */
6
6
  children: React.ReactNode;
7
7
  /** Called when pressed. */
@@ -15,7 +15,7 @@ interface PressableProps extends Omit<TouchableOpacityProps, 'activeOpacity'> {
15
15
  bounciness?: number;
16
16
  /** Enable haptic feedback on press. Defaults to `true`. */
17
17
  haptics?: boolean;
18
- /** Additional style for the Animated wrapper. */
18
+ /** Additional style for the wrapper. */
19
19
  style?: ViewStyle;
20
20
  /** Disable interaction. */
21
21
  disabled?: boolean;
@@ -24,11 +24,11 @@ interface PressableProps extends Omit<TouchableOpacityProps, 'activeOpacity'> {
24
24
  }
25
25
  /**
26
26
  * Generic pressable with a calibrated spring bounce — Apple HIG / Airbnb feel.
27
- * All animation runs on the UI thread via Reanimated v4 worklets.
27
+ * All animation runs on the UI thread via pressto (Reanimated v4 worklets).
28
28
  *
29
29
  * Use this for any custom pressable surface that needs consistent press feel
30
30
  * (cards, list rows, image tiles, etc).
31
31
  */
32
- declare function Pressable({ children, onPress, pressScale, haptics, style, disabled, hoverScale, ...touchableProps }: PressableProps): React.JSX.Element;
32
+ declare function Pressable({ children, onPress, pressScale: _pressScale, haptics, style, disabled, hoverScale: _hoverScale, }: PressableProps): React.JSX.Element;
33
33
 
34
34
  export { Pressable, type PressableProps };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { TouchableOpacityProps, ViewStyle } from 'react-native';
2
+ import { ViewStyle } from 'react-native';
3
3
 
4
- interface PressableProps extends Omit<TouchableOpacityProps, 'activeOpacity'> {
4
+ interface PressableProps {
5
5
  /** Children content to render inside the pressable. */
6
6
  children: React.ReactNode;
7
7
  /** Called when pressed. */
@@ -15,7 +15,7 @@ interface PressableProps extends Omit<TouchableOpacityProps, 'activeOpacity'> {
15
15
  bounciness?: number;
16
16
  /** Enable haptic feedback on press. Defaults to `true`. */
17
17
  haptics?: boolean;
18
- /** Additional style for the Animated wrapper. */
18
+ /** Additional style for the wrapper. */
19
19
  style?: ViewStyle;
20
20
  /** Disable interaction. */
21
21
  disabled?: boolean;
@@ -24,11 +24,11 @@ interface PressableProps extends Omit<TouchableOpacityProps, 'activeOpacity'> {
24
24
  }
25
25
  /**
26
26
  * Generic pressable with a calibrated spring bounce — Apple HIG / Airbnb feel.
27
- * All animation runs on the UI thread via Reanimated v4 worklets.
27
+ * All animation runs on the UI thread via pressto (Reanimated v4 worklets).
28
28
  *
29
29
  * Use this for any custom pressable surface that needs consistent press feel
30
30
  * (cards, list rows, image tiles, etc).
31
31
  */
32
- declare function Pressable({ children, onPress, pressScale, haptics, style, disabled, hoverScale, ...touchableProps }: PressableProps): React.JSX.Element;
32
+ declare function Pressable({ children, onPress, pressScale: _pressScale, haptics, style, disabled, hoverScale: _hoverScale, }: PressableProps): React.JSX.Element;
33
33
 
34
34
  export { Pressable, type PressableProps };
package/dist/Pressable.js CHANGED
@@ -2,130 +2,141 @@
2
2
 
3
3
  var React = require('react');
4
4
  var reactNative = require('react-native');
5
- var Animated = require('react-native-reanimated');
5
+ var pressto = require('pressto');
6
+ var reactNativeReanimated = require('react-native-reanimated');
6
7
 
7
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
9
 
9
10
  var React__default = /*#__PURE__*/_interopDefault(React);
10
- var Animated__default = /*#__PURE__*/_interopDefault(Animated);
11
11
 
12
- // src/components/Pressable/Pressable.tsx
12
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
13
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
14
+ }) : x)(function(x) {
15
+ if (typeof require !== "undefined") return require.apply(this, arguments);
16
+ throw Error('Dynamic require of "' + x + '" is not supported');
17
+ });
13
18
  var _haptics = null;
19
+ var _hapticsLoaded = false;
14
20
  async function getHaptics() {
15
21
  if (reactNative.Platform.OS === "web") return null;
16
- if (!_haptics) {
17
- _haptics = await import('expo-haptics');
22
+ if (!_hapticsLoaded) {
23
+ _hapticsLoaded = true;
24
+ try {
25
+ _haptics = await import('expo-haptics');
26
+ } catch {
27
+ _haptics = null;
28
+ }
18
29
  }
19
30
  return _haptics;
20
31
  }
32
+ var _pulsar = null;
33
+ var _pulsarChecked = false;
34
+ var _pulsarAvailable = false;
35
+ function isPulsarNativeRegistered() {
36
+ try {
37
+ const g = globalThis;
38
+ if (typeof g.__turboModuleProxy === "function") {
39
+ return g.__turboModuleProxy("RNPulsar") != null;
40
+ }
41
+ return reactNative.NativeModules?.RNPulsar != null;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+ function getPulsar() {
47
+ if (reactNative.Platform.OS === "web") return null;
48
+ if (!_pulsarChecked) {
49
+ _pulsarChecked = true;
50
+ try {
51
+ if (isPulsarNativeRegistered()) {
52
+ _pulsar = __require("react-native-pulsar");
53
+ _pulsarAvailable = true;
54
+ }
55
+ } catch {
56
+ _pulsar = null;
57
+ _pulsarAvailable = false;
58
+ }
59
+ }
60
+ return _pulsarAvailable ? _pulsar : null;
61
+ }
21
62
  function impactLight() {
22
63
  if (reactNative.Platform.OS === "web") return;
23
- getHaptics().then((h) => h?.impactAsync(h.ImpactFeedbackStyle.Light));
64
+ getHaptics().then((h) => {
65
+ if (h) {
66
+ h.impactAsync(h.ImpactFeedbackStyle.Light);
67
+ } else {
68
+ getPulsar()?.Presets.System.impactLight();
69
+ }
70
+ });
24
71
  }
25
- var SPRINGS = {
26
- /** Tight, premium press feel — Buttons, Toggle, Tabs triggers. */
27
- pressIn: { stiffness: 600, damping: 35, mass: 0.8 },
28
- pressOut: { stiffness: 280, damping: 22, mass: 0.8 },
29
- /** Slightly softer for larger surfaces — Card, ListItem, MenuItem. */
30
- surfacePressIn: { stiffness: 380, damping: 30, mass: 0.95 },
31
- surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 }};
32
72
  ({
33
73
  /** Material-style ease-out — natural deceleration for state changes. */
34
- standard: Animated.Easing.bezier(0.2, 0, 0, 1),
74
+ standard: reactNativeReanimated.Easing.bezier(0.2, 0, 0, 1),
35
75
  /** Strong ease-out for expanding surfaces (Accordion open). */
36
- expand: Animated.Easing.bezier(0.23, 1, 0.32, 1),
76
+ expand: reactNativeReanimated.Easing.bezier(0.23, 1, 0.32, 1),
37
77
  /** Quick ease-in for collapsing. */
38
- collapse: Animated.Easing.in(Animated.Easing.ease)
78
+ collapse: reactNativeReanimated.Easing.in(reactNativeReanimated.Easing.ease)
39
79
  });
40
80
  var PRESS_SCALE = {
41
81
  button: 0.95,
42
- card: 0.98};
43
- function useHover() {
44
- const [hovered, setHovered] = React.useState(false);
45
- const onMouseEnter = React.useCallback(() => setHovered(true), []);
46
- const onMouseLeave = React.useCallback(() => setHovered(false), []);
47
- if (reactNative.Platform.OS !== "web") {
48
- return { hovered: false, hoverHandlers: {} };
49
- }
50
- return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
51
- }
52
-
53
- // src/utils/usePressScale.ts
54
- function usePressScale({
55
- pressScale = PRESS_SCALE.button,
56
- hoverScale = 1.02,
57
- pressInSpring = SPRINGS.pressIn,
58
- pressOutSpring = SPRINGS.pressOut,
59
- disabled = false
60
- } = {}) {
61
- const scale = Animated.useSharedValue(1);
62
- const { hovered, hoverHandlers } = useHover();
63
- const onPressIn = React.useCallback(() => {
64
- if (disabled) return;
65
- scale.value = Animated.withSpring(pressScale, pressInSpring);
66
- }, [disabled, pressScale, pressInSpring, scale]);
67
- const onPressOut = React.useCallback(() => {
68
- if (disabled) return;
69
- scale.value = Animated.withSpring(1, pressOutSpring);
70
- }, [disabled, pressOutSpring, scale]);
71
- const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
72
- const animatedStyle = Animated.useAnimatedStyle(() => ({
73
- transform: [
74
- { scale: scale.value * (hoverActive ? hoverScale : 1) }
75
- ]
76
- }));
77
- return {
78
- animatedStyle,
79
- onPressIn,
80
- onPressOut,
81
- hoverHandlers
82
- };
83
- }
82
+ card: 0.98,
83
+ row: 0.97,
84
+ chip: 0.94
85
+ };
86
+ pressto.createAnimatedPressable((progress) => {
87
+ "worklet";
88
+ const scale = 1 - (1 - PRESS_SCALE.button) * progress;
89
+ return { transform: [{ scale }] };
90
+ });
91
+ var PressableCard = pressto.createAnimatedPressable((progress) => {
92
+ "worklet";
93
+ const scale = 1 - (1 - PRESS_SCALE.card) * progress;
94
+ return { transform: [{ scale }] };
95
+ });
96
+ pressto.createAnimatedPressable((progress) => {
97
+ "worklet";
98
+ const scale = 1 - (1 - PRESS_SCALE.row) * progress;
99
+ return { transform: [{ scale }] };
100
+ });
101
+ pressto.createAnimatedPressable((progress) => {
102
+ "worklet";
103
+ const scale = 1 - (1 - PRESS_SCALE.chip) * progress;
104
+ return { transform: [{ scale }] };
105
+ });
106
+ pressto.createAnimatedPressable((progress) => {
107
+ "worklet";
108
+ const scale = 1 - (1 - PRESS_SCALE.button) * progress;
109
+ return { transform: [{ scale }] };
110
+ });
84
111
 
85
112
  // src/components/Pressable/Pressable.tsx
86
113
  function Pressable({
87
114
  children,
88
115
  onPress,
89
- pressScale = PRESS_SCALE.card,
116
+ pressScale: _pressScale = PRESS_SCALE.card,
90
117
  haptics = true,
91
118
  style,
92
119
  disabled,
93
- hoverScale = 1.02,
94
- ...touchableProps
120
+ hoverScale: _hoverScale = 1.02
95
121
  }) {
96
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
97
- pressScale,
98
- hoverScale,
99
- pressInSpring: SPRINGS.surfacePressIn,
100
- pressOutSpring: SPRINGS.surfacePressOut,
101
- disabled
102
- });
103
122
  const handlePress = () => {
104
123
  if (disabled || !onPress) return;
105
124
  if (haptics) impactLight();
106
125
  onPress();
107
126
  };
108
127
  return /* @__PURE__ */ React__default.default.createElement(
109
- Animated__default.default.View,
128
+ PressableCard,
110
129
  {
111
- style: [animatedStyle, style],
112
- ...reactNative.Platform.OS === "web" ? hoverHandlers : {}
130
+ style,
131
+ onPress: handlePress,
132
+ enabled: !disabled,
133
+ rippleColor: "transparent",
134
+ touchSoundDisabled: true,
135
+ activateOnHover: true,
136
+ accessibilityRole: "button",
137
+ accessibilityState: { disabled: !!disabled }
113
138
  },
114
- /* @__PURE__ */ React__default.default.createElement(
115
- reactNative.TouchableOpacity,
116
- {
117
- onPress: handlePress,
118
- onPressIn,
119
- onPressOut,
120
- activeOpacity: 1,
121
- disabled,
122
- touchSoundDisabled: true,
123
- accessibilityRole: "button",
124
- accessibilityState: { disabled: !!disabled },
125
- ...touchableProps
126
- },
127
- children
128
- )
139
+ children
129
140
  );
130
141
  }
131
142