@retray-dev/ui-kit 7.0.1 → 9.1.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 +567 -14
  2. package/EXAMPLES.md +21 -14
  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,316 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactNative = require('react-native');
5
+ var reactNativeSkia = require('@shopify/react-native-skia');
6
+ var Animated = require('react-native-reanimated');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var React__default = /*#__PURE__*/_interopDefault(React);
11
+ var Animated__default = /*#__PURE__*/_interopDefault(Animated);
12
+
13
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
14
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
15
+ }) : x)(function(x) {
16
+ if (typeof require !== "undefined") return require.apply(this, arguments);
17
+ throw Error('Dynamic require of "' + x + '" is not supported');
18
+ });
19
+ var SPRINGS = {
20
+ /** Tight, premium press feel — Buttons, Toggle, Tabs triggers. */
21
+ pressIn: { stiffness: 600, damping: 35, mass: 0.8 },
22
+ pressOut: { stiffness: 280, damping: 22, mass: 0.8 }};
23
+ ({
24
+ /** Material-style ease-out — natural deceleration for state changes. */
25
+ standard: Animated.Easing.bezier(0.2, 0, 0, 1),
26
+ /** Strong ease-out for expanding surfaces (Accordion open). */
27
+ expand: Animated.Easing.bezier(0.23, 1, 0.32, 1),
28
+ /** Quick ease-in for collapsing. */
29
+ collapse: Animated.Easing.in(Animated.Easing.ease)
30
+ });
31
+ var PRESS_SCALE = {
32
+ button: 0.95,
33
+ card: 0.98};
34
+ function useHover() {
35
+ const [hovered, setHovered] = React.useState(false);
36
+ const onMouseEnter = React.useCallback(() => setHovered(true), []);
37
+ const onMouseLeave = React.useCallback(() => setHovered(false), []);
38
+ if (reactNative.Platform.OS !== "web") {
39
+ return { hovered: false, hoverHandlers: {} };
40
+ }
41
+ return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
42
+ }
43
+
44
+ // src/utils/usePressScale.ts
45
+ function usePressScale({
46
+ pressScale = PRESS_SCALE.button,
47
+ hoverScale = 1.02,
48
+ pressInSpring = SPRINGS.pressIn,
49
+ pressOutSpring = SPRINGS.pressOut,
50
+ disabled = false
51
+ } = {}) {
52
+ const scale = Animated.useSharedValue(1);
53
+ const { hovered, hoverHandlers } = useHover();
54
+ const onPressIn = React.useCallback(() => {
55
+ if (disabled) return;
56
+ scale.value = Animated.withSpring(pressScale, pressInSpring);
57
+ }, [disabled, pressScale, pressInSpring, scale]);
58
+ const onPressOut = React.useCallback(() => {
59
+ if (disabled) return;
60
+ scale.value = Animated.withSpring(1, pressOutSpring);
61
+ }, [disabled, pressOutSpring, scale]);
62
+ const hoverActive = reactNative.Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
63
+ const animatedStyle = Animated.useAnimatedStyle(() => ({
64
+ transform: [
65
+ { scale: scale.value * (hoverActive ? hoverScale : 1) }
66
+ ]
67
+ }));
68
+ return {
69
+ animatedStyle,
70
+ onPressIn,
71
+ onPressOut,
72
+ hoverHandlers
73
+ };
74
+ }
75
+ var _haptics = null;
76
+ var _hapticsLoaded = false;
77
+ async function getHaptics() {
78
+ if (reactNative.Platform.OS === "web") return null;
79
+ if (!_hapticsLoaded) {
80
+ _hapticsLoaded = true;
81
+ try {
82
+ _haptics = await import('expo-haptics');
83
+ } catch {
84
+ _haptics = null;
85
+ }
86
+ }
87
+ return _haptics;
88
+ }
89
+ var _pulsar = null;
90
+ var _pulsarChecked = false;
91
+ var _pulsarAvailable = false;
92
+ function isPulsarNativeRegistered() {
93
+ try {
94
+ const g = globalThis;
95
+ if (typeof g.__turboModuleProxy === "function") {
96
+ return g.__turboModuleProxy("RNPulsar") != null;
97
+ }
98
+ return reactNative.NativeModules?.RNPulsar != null;
99
+ } catch {
100
+ return false;
101
+ }
102
+ }
103
+ function getPulsar() {
104
+ if (reactNative.Platform.OS === "web") return null;
105
+ if (!_pulsarChecked) {
106
+ _pulsarChecked = true;
107
+ try {
108
+ if (isPulsarNativeRegistered()) {
109
+ _pulsar = __require("react-native-pulsar");
110
+ _pulsarAvailable = true;
111
+ }
112
+ } catch {
113
+ _pulsar = null;
114
+ _pulsarAvailable = false;
115
+ }
116
+ }
117
+ return _pulsarAvailable ? _pulsar : null;
118
+ }
119
+ function impactLight() {
120
+ if (reactNative.Platform.OS === "web") return;
121
+ getHaptics().then((h) => {
122
+ if (h) {
123
+ h.impactAsync(h.ImpactFeedbackStyle.Light);
124
+ } else {
125
+ getPulsar()?.Presets.System.impactLight();
126
+ }
127
+ });
128
+ }
129
+
130
+ // src/tokens.ts
131
+ var RADIUS = {
132
+ md: 14};
133
+
134
+ // src/components/HolographicCard/HolographicCard.tsx
135
+ var FOIL_PRESETS = {
136
+ // Classic holographic rainbow
137
+ rainbow: [
138
+ "rgba(255, 0, 128, 0.45)",
139
+ "rgba(255, 200, 0, 0.40)",
140
+ "rgba(0, 255, 170, 0.40)",
141
+ "rgba(0, 170, 255, 0.45)",
142
+ "rgba(180, 0, 255, 0.45)"
143
+ ],
144
+ // Premium gold foil
145
+ gold: [
146
+ "rgba(255, 215, 0, 0.50)",
147
+ "rgba(255, 180, 0, 0.45)",
148
+ "rgba(218, 165, 32, 0.40)",
149
+ "rgba(255, 223, 128, 0.50)",
150
+ "rgba(184, 134, 11, 0.45)"
151
+ ],
152
+ // Chrome silver foil
153
+ silver: [
154
+ "rgba(192, 192, 192, 0.50)",
155
+ "rgba(220, 220, 220, 0.45)",
156
+ "rgba(169, 169, 169, 0.40)",
157
+ "rgba(240, 240, 240, 0.50)",
158
+ "rgba(128, 128, 128, 0.45)"
159
+ ],
160
+ // Deep space cosmic
161
+ cosmic: [
162
+ "rgba(75, 0, 130, 0.50)",
163
+ "rgba(138, 43, 226, 0.45)",
164
+ "rgba(255, 20, 147, 0.40)",
165
+ "rgba(0, 191, 255, 0.45)",
166
+ "rgba(148, 0, 211, 0.50)"
167
+ ],
168
+ // Emerald green luxury
169
+ emerald: [
170
+ "rgba(0, 201, 87, 0.50)",
171
+ "rgba(46, 139, 87, 0.45)",
172
+ "rgba(0, 255, 127, 0.40)",
173
+ "rgba(60, 179, 113, 0.45)",
174
+ "rgba(0, 128, 0, 0.50)"
175
+ ],
176
+ // Rose gold / pink
177
+ rose: [
178
+ "rgba(255, 105, 180, 0.50)",
179
+ "rgba(255, 182, 193, 0.45)",
180
+ "rgba(219, 112, 147, 0.40)",
181
+ "rgba(255, 20, 147, 0.45)",
182
+ "rgba(199, 21, 133, 0.50)"
183
+ ],
184
+ // Deep ocean blue
185
+ ocean: [
186
+ "rgba(0, 119, 190, 0.50)",
187
+ "rgba(0, 180, 216, 0.45)",
188
+ "rgba(72, 202, 228, 0.40)",
189
+ "rgba(144, 224, 239, 0.45)",
190
+ "rgba(0, 150, 199, 0.50)"
191
+ ],
192
+ // Hot fire gradient
193
+ fire: [
194
+ "rgba(255, 69, 0, 0.50)",
195
+ "rgba(255, 140, 0, 0.45)",
196
+ "rgba(255, 215, 0, 0.40)",
197
+ "rgba(255, 99, 71, 0.45)",
198
+ "rgba(220, 20, 60, 0.50)"
199
+ ],
200
+ // Aurora borealis
201
+ aurora: [
202
+ "rgba(0, 255, 127, 0.45)",
203
+ "rgba(127, 255, 212, 0.40)",
204
+ "rgba(0, 206, 209, 0.45)",
205
+ "rgba(138, 43, 226, 0.40)",
206
+ "rgba(255, 20, 147, 0.45)"
207
+ ],
208
+ // Neon cyberpunk
209
+ neon: [
210
+ "rgba(255, 0, 255, 0.55)",
211
+ "rgba(0, 255, 255, 0.50)",
212
+ "rgba(255, 255, 0, 0.45)",
213
+ "rgba(0, 255, 0, 0.50)",
214
+ "rgba(255, 0, 128, 0.55)"
215
+ ]
216
+ };
217
+ var DEFAULT_FOIL_COLORS = FOIL_PRESETS.rainbow;
218
+ var DEFAULT_TILT_DEG = 10;
219
+ var DEFAULT_NORM_FACTOR = Math.PI / 6;
220
+ function HolographicCard({
221
+ source,
222
+ width = 300,
223
+ height,
224
+ borderRadius = RADIUS.md,
225
+ enableTilt = true,
226
+ intensity = 1,
227
+ onPress,
228
+ style,
229
+ // New customization props
230
+ foilPreset = "rainbow",
231
+ foilColors,
232
+ maxTiltDegrees = DEFAULT_TILT_DEG,
233
+ tiltSensitivity = 1,
234
+ sheenSpread = 0.6,
235
+ tiltAnimationDuration = 80,
236
+ perspective = 800,
237
+ blendMode = "plus"
238
+ }) {
239
+ const h = height ?? width * 1.4;
240
+ const image = reactNativeSkia.useImage(source ?? null);
241
+ const clampedTilt = Math.max(0, Math.min(45, maxTiltDegrees));
242
+ const clampedSensitivity = Math.max(0.1, Math.min(2, tiltSensitivity));
243
+ const clampedSpread = Math.max(0, Math.min(1, sheenSpread));
244
+ const clampedPerspective = Math.max(200, Math.min(2e3, perspective));
245
+ const resolvedFoilColors = React.useMemo(() => {
246
+ if (foilColors && foilColors.length >= 2) return foilColors;
247
+ return FOIL_PRESETS[foilPreset] ?? DEFAULT_FOIL_COLORS;
248
+ }, [foilColors, foilPreset]);
249
+ const normFactor = DEFAULT_NORM_FACTOR / clampedSensitivity;
250
+ const tiltX = Animated.useSharedValue(0);
251
+ const tiltY = Animated.useSharedValue(0);
252
+ React.useEffect(() => {
253
+ if (!enableTilt || reactNative.Platform.OS === "web") return;
254
+ let remove;
255
+ let cancelled = false;
256
+ import('expo-sensors').then(({ DeviceMotion }) => {
257
+ if (cancelled) return;
258
+ DeviceMotion.setUpdateInterval(16);
259
+ const sub = DeviceMotion.addListener(({ rotation }) => {
260
+ if (!rotation) return;
261
+ const nx = Math.max(-1, Math.min(rotation.gamma / normFactor, 1));
262
+ const ny = Math.max(-1, Math.min(rotation.beta / normFactor, 1));
263
+ tiltX.value = Animated.withTiming(nx, { duration: tiltAnimationDuration });
264
+ tiltY.value = Animated.withTiming(ny, { duration: tiltAnimationDuration });
265
+ });
266
+ remove = () => sub.remove();
267
+ }).catch(() => {
268
+ });
269
+ return () => {
270
+ cancelled = true;
271
+ remove?.();
272
+ };
273
+ }, [enableTilt, tiltX, tiltY, normFactor, tiltAnimationDuration]);
274
+ const { animatedStyle: pressStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
275
+ pressScale: PRESS_SCALE.card,
276
+ disabled: !onPress
277
+ });
278
+ const tiltStyle = Animated.useAnimatedStyle(() => ({
279
+ transform: [
280
+ { perspective: clampedPerspective },
281
+ { rotateX: `${-tiltY.value * clampedTilt}deg` },
282
+ { rotateY: `${tiltX.value * clampedTilt}deg` }
283
+ ]
284
+ }));
285
+ const start = Animated.useDerivedValue(() => reactNativeSkia.vec(width * (0.5 - tiltX.value * clampedSpread), h * (0.5 - tiltY.value * clampedSpread)));
286
+ const end = Animated.useDerivedValue(() => reactNativeSkia.vec(width * (0.5 + tiltX.value * clampedSpread), h * (0.5 + tiltY.value * clampedSpread)));
287
+ const rrct = { x: 0, y: 0, width, height: h };
288
+ const canvas = /* @__PURE__ */ React__default.default.createElement(reactNativeSkia.Canvas, { style: { width, height: h } }, image ? /* @__PURE__ */ React__default.default.createElement(reactNativeSkia.Group, { clip: { rect: rrct, rx: borderRadius, ry: borderRadius } }, /* @__PURE__ */ React__default.default.createElement(reactNativeSkia.Image, { image, x: 0, y: 0, width, height: h, fit: "cover" })) : null, /* @__PURE__ */ React__default.default.createElement(reactNativeSkia.RoundedRect, { x: 0, y: 0, width, height: h, r: borderRadius, opacity: intensity, blendMode }, /* @__PURE__ */ React__default.default.createElement(reactNativeSkia.LinearGradient, { start, end, colors: resolvedFoilColors })));
289
+ const card = /* @__PURE__ */ React__default.default.createElement(Animated__default.default.View, { style: [{ width, height: h }, tiltStyle, style] }, canvas);
290
+ if (!onPress) return card;
291
+ return /* @__PURE__ */ React__default.default.createElement(Animated__default.default.View, { style: pressStyle }, /* @__PURE__ */ React__default.default.createElement(
292
+ reactNative.TouchableOpacity,
293
+ {
294
+ onPress: () => {
295
+ impactLight();
296
+ onPress();
297
+ },
298
+ onPressIn,
299
+ onPressOut,
300
+ activeOpacity: 1,
301
+ touchSoundDisabled: true,
302
+ accessibilityRole: "imagebutton",
303
+ ...hoverHandlers,
304
+ style: styles.touch
305
+ },
306
+ card
307
+ ));
308
+ }
309
+ var styles = reactNative.StyleSheet.create({
310
+ touch: {
311
+ alignSelf: "flex-start"
312
+ }
313
+ });
314
+
315
+ exports.FOIL_PRESETS = FOIL_PRESETS;
316
+ exports.HolographicCard = HolographicCard;
@@ -0,0 +1,191 @@
1
+ import { usePressScale } from './chunk-YNROWHQJ.mjs';
2
+ import { impactLight } from './chunk-EJ7ZPXOH.mjs';
3
+ import { PRESS_SCALE } from './chunk-DVK4G2GT.mjs';
4
+ import { RADIUS } from './chunk-QY3X2UYR.mjs';
5
+ import './chunk-Y6FXYEAI.mjs';
6
+ import React, { useMemo, useEffect } from 'react';
7
+ import { StyleSheet, Platform, TouchableOpacity } from 'react-native';
8
+ import { useImage, vec, Canvas, Group, Image, RoundedRect, LinearGradient } from '@shopify/react-native-skia';
9
+ import Animated, { useSharedValue, withTiming, useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
10
+
11
+ var FOIL_PRESETS = {
12
+ // Classic holographic rainbow
13
+ rainbow: [
14
+ "rgba(255, 0, 128, 0.45)",
15
+ "rgba(255, 200, 0, 0.40)",
16
+ "rgba(0, 255, 170, 0.40)",
17
+ "rgba(0, 170, 255, 0.45)",
18
+ "rgba(180, 0, 255, 0.45)"
19
+ ],
20
+ // Premium gold foil
21
+ gold: [
22
+ "rgba(255, 215, 0, 0.50)",
23
+ "rgba(255, 180, 0, 0.45)",
24
+ "rgba(218, 165, 32, 0.40)",
25
+ "rgba(255, 223, 128, 0.50)",
26
+ "rgba(184, 134, 11, 0.45)"
27
+ ],
28
+ // Chrome silver foil
29
+ silver: [
30
+ "rgba(192, 192, 192, 0.50)",
31
+ "rgba(220, 220, 220, 0.45)",
32
+ "rgba(169, 169, 169, 0.40)",
33
+ "rgba(240, 240, 240, 0.50)",
34
+ "rgba(128, 128, 128, 0.45)"
35
+ ],
36
+ // Deep space cosmic
37
+ cosmic: [
38
+ "rgba(75, 0, 130, 0.50)",
39
+ "rgba(138, 43, 226, 0.45)",
40
+ "rgba(255, 20, 147, 0.40)",
41
+ "rgba(0, 191, 255, 0.45)",
42
+ "rgba(148, 0, 211, 0.50)"
43
+ ],
44
+ // Emerald green luxury
45
+ emerald: [
46
+ "rgba(0, 201, 87, 0.50)",
47
+ "rgba(46, 139, 87, 0.45)",
48
+ "rgba(0, 255, 127, 0.40)",
49
+ "rgba(60, 179, 113, 0.45)",
50
+ "rgba(0, 128, 0, 0.50)"
51
+ ],
52
+ // Rose gold / pink
53
+ rose: [
54
+ "rgba(255, 105, 180, 0.50)",
55
+ "rgba(255, 182, 193, 0.45)",
56
+ "rgba(219, 112, 147, 0.40)",
57
+ "rgba(255, 20, 147, 0.45)",
58
+ "rgba(199, 21, 133, 0.50)"
59
+ ],
60
+ // Deep ocean blue
61
+ ocean: [
62
+ "rgba(0, 119, 190, 0.50)",
63
+ "rgba(0, 180, 216, 0.45)",
64
+ "rgba(72, 202, 228, 0.40)",
65
+ "rgba(144, 224, 239, 0.45)",
66
+ "rgba(0, 150, 199, 0.50)"
67
+ ],
68
+ // Hot fire gradient
69
+ fire: [
70
+ "rgba(255, 69, 0, 0.50)",
71
+ "rgba(255, 140, 0, 0.45)",
72
+ "rgba(255, 215, 0, 0.40)",
73
+ "rgba(255, 99, 71, 0.45)",
74
+ "rgba(220, 20, 60, 0.50)"
75
+ ],
76
+ // Aurora borealis
77
+ aurora: [
78
+ "rgba(0, 255, 127, 0.45)",
79
+ "rgba(127, 255, 212, 0.40)",
80
+ "rgba(0, 206, 209, 0.45)",
81
+ "rgba(138, 43, 226, 0.40)",
82
+ "rgba(255, 20, 147, 0.45)"
83
+ ],
84
+ // Neon cyberpunk
85
+ neon: [
86
+ "rgba(255, 0, 255, 0.55)",
87
+ "rgba(0, 255, 255, 0.50)",
88
+ "rgba(255, 255, 0, 0.45)",
89
+ "rgba(0, 255, 0, 0.50)",
90
+ "rgba(255, 0, 128, 0.55)"
91
+ ]
92
+ };
93
+ var DEFAULT_FOIL_COLORS = FOIL_PRESETS.rainbow;
94
+ var DEFAULT_TILT_DEG = 10;
95
+ var DEFAULT_NORM_FACTOR = Math.PI / 6;
96
+ function HolographicCard({
97
+ source,
98
+ width = 300,
99
+ height,
100
+ borderRadius = RADIUS.md,
101
+ enableTilt = true,
102
+ intensity = 1,
103
+ onPress,
104
+ style,
105
+ // New customization props
106
+ foilPreset = "rainbow",
107
+ foilColors,
108
+ maxTiltDegrees = DEFAULT_TILT_DEG,
109
+ tiltSensitivity = 1,
110
+ sheenSpread = 0.6,
111
+ tiltAnimationDuration = 80,
112
+ perspective = 800,
113
+ blendMode = "plus"
114
+ }) {
115
+ const h = height ?? width * 1.4;
116
+ const image = useImage(source ?? null);
117
+ const clampedTilt = Math.max(0, Math.min(45, maxTiltDegrees));
118
+ const clampedSensitivity = Math.max(0.1, Math.min(2, tiltSensitivity));
119
+ const clampedSpread = Math.max(0, Math.min(1, sheenSpread));
120
+ const clampedPerspective = Math.max(200, Math.min(2e3, perspective));
121
+ const resolvedFoilColors = useMemo(() => {
122
+ if (foilColors && foilColors.length >= 2) return foilColors;
123
+ return FOIL_PRESETS[foilPreset] ?? DEFAULT_FOIL_COLORS;
124
+ }, [foilColors, foilPreset]);
125
+ const normFactor = DEFAULT_NORM_FACTOR / clampedSensitivity;
126
+ const tiltX = useSharedValue(0);
127
+ const tiltY = useSharedValue(0);
128
+ useEffect(() => {
129
+ if (!enableTilt || Platform.OS === "web") return;
130
+ let remove;
131
+ let cancelled = false;
132
+ import('expo-sensors').then(({ DeviceMotion }) => {
133
+ if (cancelled) return;
134
+ DeviceMotion.setUpdateInterval(16);
135
+ const sub = DeviceMotion.addListener(({ rotation }) => {
136
+ if (!rotation) return;
137
+ const nx = Math.max(-1, Math.min(rotation.gamma / normFactor, 1));
138
+ const ny = Math.max(-1, Math.min(rotation.beta / normFactor, 1));
139
+ tiltX.value = withTiming(nx, { duration: tiltAnimationDuration });
140
+ tiltY.value = withTiming(ny, { duration: tiltAnimationDuration });
141
+ });
142
+ remove = () => sub.remove();
143
+ }).catch(() => {
144
+ });
145
+ return () => {
146
+ cancelled = true;
147
+ remove?.();
148
+ };
149
+ }, [enableTilt, tiltX, tiltY, normFactor, tiltAnimationDuration]);
150
+ const { animatedStyle: pressStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
151
+ pressScale: PRESS_SCALE.card,
152
+ disabled: !onPress
153
+ });
154
+ const tiltStyle = useAnimatedStyle(() => ({
155
+ transform: [
156
+ { perspective: clampedPerspective },
157
+ { rotateX: `${-tiltY.value * clampedTilt}deg` },
158
+ { rotateY: `${tiltX.value * clampedTilt}deg` }
159
+ ]
160
+ }));
161
+ const start = useDerivedValue(() => vec(width * (0.5 - tiltX.value * clampedSpread), h * (0.5 - tiltY.value * clampedSpread)));
162
+ const end = useDerivedValue(() => vec(width * (0.5 + tiltX.value * clampedSpread), h * (0.5 + tiltY.value * clampedSpread)));
163
+ const rrct = { x: 0, y: 0, width, height: h };
164
+ const canvas = /* @__PURE__ */ React.createElement(Canvas, { style: { width, height: h } }, image ? /* @__PURE__ */ React.createElement(Group, { clip: { rect: rrct, rx: borderRadius, ry: borderRadius } }, /* @__PURE__ */ React.createElement(Image, { image, x: 0, y: 0, width, height: h, fit: "cover" })) : null, /* @__PURE__ */ React.createElement(RoundedRect, { x: 0, y: 0, width, height: h, r: borderRadius, opacity: intensity, blendMode }, /* @__PURE__ */ React.createElement(LinearGradient, { start, end, colors: resolvedFoilColors })));
165
+ const card = /* @__PURE__ */ React.createElement(Animated.View, { style: [{ width, height: h }, tiltStyle, style] }, canvas);
166
+ if (!onPress) return card;
167
+ return /* @__PURE__ */ React.createElement(Animated.View, { style: pressStyle }, /* @__PURE__ */ React.createElement(
168
+ TouchableOpacity,
169
+ {
170
+ onPress: () => {
171
+ impactLight();
172
+ onPress();
173
+ },
174
+ onPressIn,
175
+ onPressOut,
176
+ activeOpacity: 1,
177
+ touchSoundDisabled: true,
178
+ accessibilityRole: "imagebutton",
179
+ ...hoverHandlers,
180
+ style: styles.touch
181
+ },
182
+ card
183
+ ));
184
+ }
185
+ var styles = StyleSheet.create({
186
+ touch: {
187
+ alignSelf: "flex-start"
188
+ }
189
+ });
190
+
191
+ export { FOIL_PRESETS, HolographicCard };
@@ -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 IconButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'destructive';
5
5
  type IconButtonSize = 'sm' | 'md' | 'lg';
6
- interface IconButtonProps extends TouchableOpacityProps {
6
+ interface IconButtonProps {
7
7
  iconName?: string;
8
8
  icon?: React.ReactNode;
9
9
  iconColor?: string;
@@ -15,8 +15,13 @@ interface IconButtonProps extends TouchableOpacityProps {
15
15
  * The dot/count appears top-right of the button.
16
16
  */
17
17
  badge?: boolean | number;
18
+ disabled?: boolean;
19
+ style?: ViewStyle;
20
+ onPress?: () => void;
21
+ accessibilityLabel?: string;
22
+ accessibilityHint?: string;
18
23
  }
19
- declare function IconButtonBase({ iconName, icon, iconColor, variant, size, loading, badge, disabled, style, onPress, accessibilityLabel, accessibilityHint, ...props }: IconButtonProps): React.JSX.Element;
24
+ declare function IconButtonBase({ iconName, icon, iconColor, variant, size, loading, badge, disabled, style, onPress, accessibilityLabel, accessibilityHint, }: IconButtonProps): React.JSX.Element;
20
25
  declare const IconButton: React.MemoExoticComponent<typeof IconButtonBase>;
21
26
 
22
27
  export { IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant };
@@ -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 IconButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'destructive';
5
5
  type IconButtonSize = 'sm' | 'md' | 'lg';
6
- interface IconButtonProps extends TouchableOpacityProps {
6
+ interface IconButtonProps {
7
7
  iconName?: string;
8
8
  icon?: React.ReactNode;
9
9
  iconColor?: string;
@@ -15,8 +15,13 @@ interface IconButtonProps extends TouchableOpacityProps {
15
15
  * The dot/count appears top-right of the button.
16
16
  */
17
17
  badge?: boolean | number;
18
+ disabled?: boolean;
19
+ style?: ViewStyle;
20
+ onPress?: () => void;
21
+ accessibilityLabel?: string;
22
+ accessibilityHint?: string;
18
23
  }
19
- declare function IconButtonBase({ iconName, icon, iconColor, variant, size, loading, badge, disabled, style, onPress, accessibilityLabel, accessibilityHint, ...props }: IconButtonProps): React.JSX.Element;
24
+ declare function IconButtonBase({ iconName, icon, iconColor, variant, size, loading, badge, disabled, style, onPress, accessibilityLabel, accessibilityHint, }: IconButtonProps): React.JSX.Element;
20
25
  declare const IconButton: React.MemoExoticComponent<typeof IconButtonBase>;
21
26
 
22
27
  export { IconButton, type IconButtonProps, type IconButtonSize, type IconButtonVariant };