@retray-dev/ui-kit 12.2.0 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/COMPONENTS.md +85 -143
  2. package/CONSUMER.md +2 -2
  3. package/DESIGN.md +2 -2
  4. package/README.md +11 -6
  5. package/dist/Accordion.js +48 -210
  6. package/dist/Accordion.mjs +6 -5
  7. package/dist/AlertBanner.js +29 -153
  8. package/dist/AlertBanner.mjs +3 -3
  9. package/dist/AppHeader.js +37 -235
  10. package/dist/AppHeader.mjs +6 -7
  11. package/dist/Avatar.d.mts +17 -1
  12. package/dist/Avatar.d.ts +17 -1
  13. package/dist/Avatar.js +80 -115
  14. package/dist/Avatar.mjs +2 -2
  15. package/dist/Badge.js +24 -149
  16. package/dist/Badge.mjs +3 -3
  17. package/dist/Button.js +79 -267
  18. package/dist/Button.mjs +6 -6
  19. package/dist/Card.js +15 -200
  20. package/dist/Card.mjs +4 -5
  21. package/dist/CategoryStrip.d.mts +0 -5
  22. package/dist/CategoryStrip.d.ts +0 -5
  23. package/dist/CategoryStrip.js +47 -265
  24. package/dist/CategoryStrip.mjs +6 -6
  25. package/dist/Checkbox.js +15 -200
  26. package/dist/Checkbox.mjs +5 -5
  27. package/dist/Chip.js +44 -236
  28. package/dist/Chip.mjs +7 -6
  29. package/dist/ConfirmDialog.js +84 -286
  30. package/dist/ConfirmDialog.mjs +7 -7
  31. package/dist/CurrencyDisplay.js +1 -114
  32. package/dist/CurrencyDisplay.mjs +2 -2
  33. package/dist/CurrencyInput.js +35 -162
  34. package/dist/CurrencyInput.mjs +5 -5
  35. package/dist/DetailRow.js +25 -150
  36. package/dist/DetailRow.mjs +3 -3
  37. package/dist/EmptyState.js +80 -268
  38. package/dist/EmptyState.mjs +7 -7
  39. package/dist/ErrorBoundary.js +32 -199
  40. package/dist/ErrorBoundary.mjs +4 -4
  41. package/dist/Form.js +1 -114
  42. package/dist/Form.mjs +2 -2
  43. package/dist/HolographicCard.d.mts +0 -28
  44. package/dist/HolographicCard.d.ts +0 -28
  45. package/dist/HolographicCard.js +20 -130
  46. package/dist/HolographicCard.mjs +9 -32
  47. package/dist/IconButton.js +36 -234
  48. package/dist/IconButton.mjs +5 -6
  49. package/dist/IconPicker.js +222 -929
  50. package/dist/IconPicker.mjs +5 -5
  51. package/dist/ImageUpload.d.mts +3 -1
  52. package/dist/ImageUpload.d.ts +3 -1
  53. package/dist/ImageUpload.js +25 -215
  54. package/dist/ImageUpload.mjs +5 -6
  55. package/dist/ImageViewer.js +75 -266
  56. package/dist/ImageViewer.mjs +8 -8
  57. package/dist/Input.d.mts +1 -1
  58. package/dist/Input.d.ts +1 -1
  59. package/dist/Input.js +35 -162
  60. package/dist/Input.mjs +4 -4
  61. package/dist/LabelValue.js +24 -149
  62. package/dist/LabelValue.mjs +3 -3
  63. package/dist/ListGroup.js +1 -114
  64. package/dist/ListGroup.mjs +2 -2
  65. package/dist/ListItem.js +38 -235
  66. package/dist/ListItem.mjs +5 -6
  67. package/dist/MediaCard.d.mts +0 -14
  68. package/dist/MediaCard.d.ts +0 -14
  69. package/dist/MediaCard.js +69 -315
  70. package/dist/MediaCard.mjs +5 -6
  71. package/dist/MenuGroup.js +1 -114
  72. package/dist/MenuGroup.mjs +2 -2
  73. package/dist/MenuItem.js +36 -234
  74. package/dist/MenuItem.mjs +5 -6
  75. package/dist/MonthPicker.js +8 -163
  76. package/dist/MonthPicker.mjs +3 -3
  77. package/dist/NumberStepper.js +40 -238
  78. package/dist/NumberStepper.mjs +5 -6
  79. package/dist/PagerDots.d.mts +1 -1
  80. package/dist/PagerDots.d.ts +1 -1
  81. package/dist/PagerDots.js +69 -224
  82. package/dist/PagerDots.mjs +6 -5
  83. package/dist/Pressable.js +14 -85
  84. package/dist/Pressable.mjs +4 -4
  85. package/dist/PricingCard.js +87 -272
  86. package/dist/PricingCard.mjs +8 -8
  87. package/dist/Progress.js +3 -123
  88. package/dist/Progress.mjs +3 -3
  89. package/dist/RadioGroup.js +52 -265
  90. package/dist/RadioGroup.mjs +5 -5
  91. package/dist/RetrayProvider.js +3 -6
  92. package/dist/RetrayProvider.mjs +3 -3
  93. package/dist/Select.d.mts +2 -1
  94. package/dist/Select.d.ts +2 -1
  95. package/dist/Select.js +24 -232
  96. package/dist/Select.mjs +4 -5
  97. package/dist/SelectableCard.js +33 -209
  98. package/dist/SelectableCard.mjs +5 -5
  99. package/dist/SelectableGrid.d.mts +0 -21
  100. package/dist/SelectableGrid.d.ts +0 -21
  101. package/dist/SelectableGrid.js +49 -271
  102. package/dist/SelectableGrid.mjs +5 -6
  103. package/dist/Separator.js +1 -114
  104. package/dist/Separator.mjs +2 -2
  105. package/dist/Sheet.js +7 -162
  106. package/dist/Sheet.mjs +3 -3
  107. package/dist/SheetSelect.js +39 -236
  108. package/dist/SheetSelect.mjs +6 -6
  109. package/dist/Skeleton.js +4 -124
  110. package/dist/Skeleton.mjs +3 -3
  111. package/dist/Slider.js +6 -161
  112. package/dist/Slider.mjs +3 -3
  113. package/dist/Spinner.js +3 -116
  114. package/dist/Spinner.mjs +2 -2
  115. package/dist/Stats.js +36 -234
  116. package/dist/Stats.mjs +5 -6
  117. package/dist/Switch.js +24 -175
  118. package/dist/Switch.mjs +5 -4
  119. package/dist/TabBar.js +43 -200
  120. package/dist/TabBar.mjs +5 -4
  121. package/dist/Tabs.js +15 -199
  122. package/dist/Tabs.mjs +5 -5
  123. package/dist/Text.js +9 -130
  124. package/dist/Text.mjs +2 -2
  125. package/dist/Textarea.d.mts +2 -1
  126. package/dist/Textarea.d.ts +2 -1
  127. package/dist/Textarea.js +71 -219
  128. package/dist/Textarea.mjs +4 -4
  129. package/dist/Toast.js +1 -114
  130. package/dist/Toast.mjs +2 -2
  131. package/dist/Toggle.js +39 -236
  132. package/dist/Toggle.mjs +6 -6
  133. package/dist/{chunk-M3C7XM2M.mjs → chunk-2QOHHBJC.mjs} +3 -3
  134. package/dist/{chunk-LIS6I5UP.mjs → chunk-2VIDP72N.mjs} +3 -3
  135. package/dist/{chunk-DF7JA72E.mjs → chunk-4NQFTHN3.mjs} +13 -7
  136. package/dist/{chunk-UBUXUMER.mjs → chunk-4ZO5PTKF.mjs} +4 -4
  137. package/dist/{chunk-3XCFYSX4.mjs → chunk-5MYNAAFE.mjs} +13 -17
  138. package/dist/{chunk-E7NEHHXV.mjs → chunk-62BBSSUF.mjs} +3 -3
  139. package/dist/{chunk-MVMGPZN6.mjs → chunk-6CR4S6W2.mjs} +3 -3
  140. package/dist/{chunk-EDLCGYIO.mjs → chunk-6QLBHUEG.mjs} +8 -7
  141. package/dist/chunk-ARONDO7M.mjs +40 -0
  142. package/dist/{chunk-GH67YXG6.mjs → chunk-AZV7KNJI.mjs} +3 -3
  143. package/dist/{chunk-RMRS44MQ.mjs → chunk-BTUW5LSG.mjs} +11 -8
  144. package/dist/{chunk-2P2CB235.mjs → chunk-BULKGOIZ.mjs} +7 -8
  145. package/dist/{chunk-NHDI3VQB.mjs → chunk-CBIZLRYH.mjs} +15 -12
  146. package/dist/chunk-CM2DG4MR.mjs +142 -0
  147. package/dist/{chunk-TS7DGUIR.mjs → chunk-DBHSUUKU.mjs} +2 -2
  148. package/dist/{chunk-57V2LXCK.mjs → chunk-DE25XTVQ.mjs} +3 -3
  149. package/dist/{chunk-UQ4742ET.mjs → chunk-E4EQSCKR.mjs} +5 -5
  150. package/dist/{chunk-GUTDFUNF.mjs → chunk-EHGBHFMH.mjs} +9 -17
  151. package/dist/{chunk-CF27NBXO.mjs → chunk-EROPDCB5.mjs} +16 -24
  152. package/dist/{chunk-ZIMY2QUM.mjs → chunk-ERWJPVX7.mjs} +2 -2
  153. package/dist/{chunk-NLZY4TXU.mjs → chunk-ESQDPO5E.mjs} +7 -7
  154. package/dist/{chunk-VJBUCITV.mjs → chunk-EW2FIDSM.mjs} +1 -1
  155. package/dist/{chunk-HC4VVCWY.mjs → chunk-FTTI6T5Q.mjs} +4 -4
  156. package/dist/{chunk-2HFD4IHU.mjs → chunk-HUSSF6TF.mjs} +1 -1
  157. package/dist/chunk-IFYMBOEN.mjs +14 -0
  158. package/dist/{chunk-QOLWA2PW.mjs → chunk-IGU223UM.mjs} +80 -4
  159. package/dist/chunk-IJCMPVW5.mjs +121 -0
  160. package/dist/{chunk-AENAVIKT.mjs → chunk-ITG4JQM3.mjs} +4 -4
  161. package/dist/{chunk-E5UKLSJZ.mjs → chunk-K3QX2M26.mjs} +11 -8
  162. package/dist/{chunk-4OORJ2DY.mjs → chunk-K7TKID3V.mjs} +8 -7
  163. package/dist/{chunk-2LG326TT.mjs → chunk-KAGADD2O.mjs} +4 -4
  164. package/dist/{chunk-IVSRW4HS.mjs → chunk-KC5QDYGZ.mjs} +4 -4
  165. package/dist/{chunk-7AFZWSCI.mjs → chunk-KPTY7UYQ.mjs} +1 -1
  166. package/dist/{chunk-YTXRIXNZ.mjs → chunk-KSSVIFYR.mjs} +9 -12
  167. package/dist/chunk-L3YKPTJQ.mjs +119 -0
  168. package/dist/chunk-M53LC4Q7.mjs +35 -0
  169. package/dist/{chunk-ZR6HSEAB.mjs → chunk-MP7GLMIR.mjs} +17 -25
  170. package/dist/chunk-MZ6WRTD2.mjs +40 -0
  171. package/dist/chunk-NGEN2EES.mjs +581 -0
  172. package/dist/{chunk-C43HRKXH.mjs → chunk-OBV72JD4.mjs} +1 -1
  173. package/dist/{chunk-LPV4NJJK.mjs → chunk-PGQ6FMXS.mjs} +6 -5
  174. package/dist/{chunk-MEPSKGBO.mjs → chunk-PI6RULJX.mjs} +1 -1
  175. package/dist/{chunk-F3YTWO3T.mjs → chunk-RA6SAAFE.mjs} +9 -8
  176. package/dist/{chunk-UNNRUJTM.mjs → chunk-RRKM4MKB.mjs} +7 -7
  177. package/dist/{chunk-ULGNQPNE.mjs → chunk-S2VGME7X.mjs} +1 -1
  178. package/dist/{chunk-OLVJFKXS.mjs → chunk-S44XWTTC.mjs} +35 -25
  179. package/dist/{chunk-YMYIEVZP.mjs → chunk-SZEKQAOY.mjs} +1 -1
  180. package/dist/{chunk-ELGEOM7I.mjs → chunk-TETMEKZE.mjs} +9 -9
  181. package/dist/{chunk-BXF4AMHY.mjs → chunk-TMH263OK.mjs} +5 -4
  182. package/dist/{chunk-NJG7DHVF.mjs → chunk-U6DEBYU5.mjs} +10 -9
  183. package/dist/{chunk-RJNLAH76.mjs → chunk-UOKFSFNJ.mjs} +2 -2
  184. package/dist/{chunk-HEDQPK4I.mjs → chunk-URIH43IJ.mjs} +13 -21
  185. package/dist/{chunk-QXDGGOLC.mjs → chunk-V2ZB2XNS.mjs} +6 -6
  186. package/dist/{chunk-KSUWPU2F.mjs → chunk-WIPEDNSD.mjs} +7 -7
  187. package/dist/{chunk-QDAZGZUF.mjs → chunk-XCIG6HT2.mjs} +3 -3
  188. package/dist/{chunk-4J2PXL36.mjs → chunk-Y6YS33GM.mjs} +40 -38
  189. package/dist/{chunk-4XOB5TTD.mjs → chunk-ZKDKKQCE.mjs} +5 -5
  190. package/dist/{chunk-LOBLCFMN.mjs → chunk-ZTPYUU5C.mjs} +5 -5
  191. package/dist/index.d.mts +12 -72
  192. package/dist/index.d.ts +12 -72
  193. package/dist/index.js +1051 -1838
  194. package/dist/index.mjs +81 -85
  195. package/package.json +8 -10
  196. package/src/components/Accordion/Accordion.tsx +12 -9
  197. package/src/components/AlertBanner/AlertBanner.tsx +7 -6
  198. package/src/components/AppHeader/AppHeader.tsx +1 -1
  199. package/src/components/Avatar/Avatar.tsx +92 -1
  200. package/src/components/Avatar/index.ts +2 -2
  201. package/src/components/Badge/Badge.tsx +2 -2
  202. package/src/components/Button/Button.tsx +50 -46
  203. package/src/components/Card/Card.tsx +1 -0
  204. package/src/components/CategoryStrip/CategoryStrip.tsx +36 -49
  205. package/src/components/Chip/Chip.tsx +5 -4
  206. package/src/components/ConfirmDialog/ConfirmDialog.tsx +3 -3
  207. package/src/components/DetailRow/DetailRow.tsx +3 -3
  208. package/src/components/EmptyState/EmptyState.tsx +2 -2
  209. package/src/components/ErrorBoundary/ErrorBoundary.tsx +6 -6
  210. package/src/components/HolographicCard/HolographicCard.tsx +14 -95
  211. package/src/components/IconButton/IconButton.tsx +2 -2
  212. package/src/components/IconPicker/IconPicker.tsx +13 -12
  213. package/src/components/ImageUpload/ImageUpload.tsx +14 -25
  214. package/src/components/ImageViewer/ImageViewer.tsx +3 -3
  215. package/src/components/Input/Input.tsx +11 -5
  216. package/src/components/LabelValue/LabelValue.tsx +2 -2
  217. package/src/components/ListItem/ListItem.tsx +4 -4
  218. package/src/components/MediaCard/MediaCard.tsx +21 -59
  219. package/src/components/MenuItem/MenuItem.tsx +2 -2
  220. package/src/components/MonthPicker/MonthPicker.tsx +2 -2
  221. package/src/components/NumberStepper/NumberStepper.tsx +6 -6
  222. package/src/components/PagerDots/PagerDots.tsx +38 -28
  223. package/src/components/PricingCard/PricingCard.tsx +6 -6
  224. package/src/components/RadioGroup/RadioGroup.tsx +18 -31
  225. package/src/components/Select/Select.tsx +32 -39
  226. package/src/components/SelectableCard/SelectableCard.tsx +4 -6
  227. package/src/components/SelectableGrid/SelectableGrid.tsx +38 -72
  228. package/src/components/Sheet/Sheet.tsx +1 -1
  229. package/src/components/SheetSelect/SheetSelect.tsx +3 -3
  230. package/src/components/Skeleton/Skeleton.tsx +1 -1
  231. package/src/components/Spinner/Spinner.tsx +2 -2
  232. package/src/components/Stats/Stats.tsx +2 -2
  233. package/src/components/Switch/Switch.tsx +9 -6
  234. package/src/components/TabBar/TabBar.tsx +9 -8
  235. package/src/components/Text/Text.tsx +12 -1
  236. package/src/components/Textarea/Textarea.tsx +18 -32
  237. package/src/components/Toggle/Toggle.tsx +3 -3
  238. package/src/hooks/useConfirmDialog.ts +31 -42
  239. package/src/index.ts +3 -4
  240. package/src/theme/ThemeProvider.tsx +1 -4
  241. package/src/theme/colorUtils.ts +1 -72
  242. package/src/theme/colors.ts +40 -1
  243. package/src/theme/types.ts +2 -2
  244. package/src/utils/animations.ts +0 -47
  245. package/src/utils/curatedIcons.ts +93 -801
  246. package/src/utils/haptics.ts +13 -208
  247. package/src/utils/icons.ts +27 -91
  248. package/src/utils/pressable.ts +10 -61
  249. package/dist/VirtualList.d.mts +0 -19
  250. package/dist/VirtualList.d.ts +0 -19
  251. package/dist/VirtualList.js +0 -38
  252. package/dist/VirtualList.mjs +0 -2
  253. package/dist/chunk-2BA3JMKK.mjs +0 -136
  254. package/dist/chunk-3DKJ2GIC.mjs +0 -30
  255. package/dist/chunk-7ELGZ66G.mjs +0 -164
  256. package/dist/chunk-DVK4G2GT.mjs +0 -59
  257. package/dist/chunk-EJ7ZPXOH.mjs +0 -163
  258. package/dist/chunk-KA7LTET3.mjs +0 -71
  259. package/dist/chunk-LNPKGWBG.mjs +0 -134
  260. package/dist/chunk-NC5ZTR2Y.mjs +0 -32
  261. package/dist/chunk-SAWUXP3A.mjs +0 -1114
  262. package/dist/chunk-YNROWHQJ.mjs +0 -46
  263. package/src/components/VirtualList/VirtualList.tsx +0 -60
  264. package/src/components/VirtualList/index.ts +0 -1
  265. package/src/utils/fontGuard.ts +0 -35
  266. package/src/utils/hover.ts +0 -25
  267. package/src/utils/useColorTransition.ts +0 -40
  268. package/src/utils/usePressScale.ts +0 -75
@@ -1,46 +0,0 @@
1
- import { PRESS_SCALE, SPRINGS } from './chunk-DVK4G2GT.mjs';
2
- import { useState, useCallback } from 'react';
3
- import { Platform } from 'react-native';
4
- import { useSharedValue, withSpring, useAnimatedStyle } from 'react-native-reanimated';
5
-
6
- function useHover() {
7
- const [hovered, setHovered] = useState(false);
8
- const onMouseEnter = useCallback(() => setHovered(true), []);
9
- const onMouseLeave = useCallback(() => setHovered(false), []);
10
- if (Platform.OS !== "web") {
11
- return { hovered: false, hoverHandlers: {} };
12
- }
13
- return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } };
14
- }
15
- function usePressScale({
16
- pressScale = PRESS_SCALE.button,
17
- hoverScale = 1.02,
18
- pressInSpring = SPRINGS.pressIn,
19
- pressOutSpring = SPRINGS.pressOut,
20
- disabled = false
21
- } = {}) {
22
- const scale = useSharedValue(1);
23
- const { hovered, hoverHandlers } = useHover();
24
- const onPressIn = useCallback(() => {
25
- if (disabled) return;
26
- scale.value = withSpring(pressScale, pressInSpring);
27
- }, [disabled, pressScale, pressInSpring, scale]);
28
- const onPressOut = useCallback(() => {
29
- if (disabled) return;
30
- scale.value = withSpring(1, pressOutSpring);
31
- }, [disabled, pressOutSpring, scale]);
32
- const hoverActive = Platform.OS === "web" && hovered && hoverScale !== 1 && !disabled;
33
- const animatedStyle = useAnimatedStyle(() => ({
34
- transform: [
35
- { scale: scale.value * (hoverActive ? hoverScale : 1) }
36
- ]
37
- }));
38
- return {
39
- animatedStyle,
40
- onPressIn,
41
- onPressOut,
42
- hoverHandlers
43
- };
44
- }
45
-
46
- export { useHover, usePressScale };
@@ -1,60 +0,0 @@
1
- import React, { useCallback } from 'react'
2
- import { FlatList, FlatListProps, ListRenderItem } from 'react-native'
3
-
4
- export interface VirtualListItem {
5
- id?: string | number
6
- }
7
-
8
- export interface VirtualListProps<T> extends Omit<FlatListProps<T>, 'getItemLayout'> {
9
- /**
10
- * Fixed row height in px. When provided, enables `getItemLayout` so the list
11
- * skips async measurement — large datasets scroll and `scrollToIndex` jump
12
- * without layout passes. Omit only for variable-height rows.
13
- */
14
- itemHeight?: number
15
- }
16
-
17
- const defaultKeyExtractor = <T,>(item: T, index: number): string => {
18
- const id = (item as VirtualListItem | null)?.id
19
- return id !== undefined ? String(id) : String(index)
20
- }
21
-
22
- /**
23
- * Virtualized list primitive. Thin wrapper over `FlatList` with sane defaults
24
- * for the common case: stable keys + optional fixed-height fast path.
25
- *
26
- * For 10k+ rows, pass `itemHeight` and a `React.memo`-wrapped `renderItem` so
27
- * only on-screen rows mount and re-render.
28
- *
29
- * @example
30
- * const renderItem = useCallback(({ item }) => <ListItem title={item.title} onPress={...} />, [])
31
- * <VirtualList data={rows} renderItem={renderItem} itemHeight={64} />
32
- */
33
- function VirtualListInner<T>(
34
- { itemHeight, keyExtractor, renderItem, ...props }: VirtualListProps<T>,
35
- ref: React.Ref<FlatList<T>>,
36
- ) {
37
- const getItemLayout = useCallback(
38
- (_data: ArrayLike<T> | null | undefined, index: number) => ({
39
- length: itemHeight ?? 0,
40
- offset: (itemHeight ?? 0) * index,
41
- index,
42
- }),
43
- [itemHeight],
44
- )
45
-
46
- return (
47
- <FlatList<T>
48
- ref={ref}
49
- keyExtractor={keyExtractor ?? defaultKeyExtractor}
50
- renderItem={renderItem as ListRenderItem<T>}
51
- getItemLayout={itemHeight !== undefined ? getItemLayout : undefined}
52
- removeClippedSubviews
53
- {...props}
54
- />
55
- )
56
- }
57
-
58
- export const VirtualList = React.forwardRef(VirtualListInner) as <T>(
59
- props: VirtualListProps<T> & { ref?: React.Ref<FlatList<T>> },
60
- ) => React.ReactElement
@@ -1 +0,0 @@
1
- export * from './VirtualList'
@@ -1,35 +0,0 @@
1
- import { isLoaded } from 'expo-font'
2
-
3
- declare const __DEV__: boolean
4
-
5
- let warned = false
6
-
7
- /**
8
- * Dev-only guard: warns once if the Sohne font family is not loaded.
9
- *
10
- * Called lazily from `Text` on first render. Without this, a missing
11
- * `useFonts(SohneFonts)` call (or a broken font path) produces invisible /
12
- * system-font text with no signal — a silent failure consumers reported losing
13
- * hours to. In production (`__DEV__ === false`) this is a no-op.
14
- */
15
- export function warnIfFontsMissing(): void {
16
- if (warned) return
17
- if (typeof __DEV__ !== 'undefined' && !__DEV__) return
18
- warned = true
19
- try {
20
- if (!isLoaded('Sohne-Regular')) {
21
- console.warn(
22
- '[retray-ui-kit] Sohne fonts are not loaded — text will fall back to the ' +
23
- 'system font. Load them at your app root before rendering any UI kit ' +
24
- 'component:\n\n' +
25
- " import { useFonts } from 'expo-font'\n" +
26
- ' import { SohneFontNames } from \'@retray-dev/ui-kit/fonts\'\n' +
27
- ' // Copy the SohneFonts boilerplate from CONSUMER.md into your App.tsx\n\n' +
28
- ' const [fontsLoaded] = useFonts(SohneFonts)\n' +
29
- ' if (!fontsLoaded) return null\n',
30
- )
31
- }
32
- } catch {
33
- // `isLoaded` not available in this expo-font version — skip the guard silently.
34
- }
35
- }
@@ -1,25 +0,0 @@
1
- import { useState, useCallback } from 'react'
2
- import { Platform } from 'react-native'
3
-
4
- export interface HoverHandlers {
5
- onMouseEnter?: () => void
6
- onMouseLeave?: () => void
7
- }
8
-
9
- /**
10
- * Web-only hover state hook. Returns `{ hovered, hoverHandlers }`.
11
- * On native (iOS/Android) `hovered` is always false and handlers are no-ops.
12
- * Spread `hoverHandlers` onto any View/TouchableOpacity to activate.
13
- */
14
- export function useHover(): { hovered: boolean; hoverHandlers: HoverHandlers } {
15
- const [hovered, setHovered] = useState(false)
16
-
17
- const onMouseEnter = useCallback(() => setHovered(true), [])
18
- const onMouseLeave = useCallback(() => setHovered(false), [])
19
-
20
- if (Platform.OS !== 'web') {
21
- return { hovered: false, hoverHandlers: {} }
22
- }
23
-
24
- return { hovered, hoverHandlers: { onMouseEnter, onMouseLeave } }
25
- }
@@ -1,40 +0,0 @@
1
- import { useEffect } from 'react'
2
- import {
3
- useSharedValue,
4
- withTiming,
5
- interpolateColor,
6
- type SharedValue,
7
- } from 'react-native-reanimated'
8
- import { TIMINGS, EASINGS } from './animations'
9
-
10
- export interface UseColorTransitionOptions {
11
- /** Animation duration in ms. Defaults to `160`. */
12
- duration?: number
13
- }
14
-
15
- /**
16
- * Drives a 0→1 `SharedValue` based on a boolean state, animated via `withTiming` on the UI thread.
17
- * Use with Reanimated's `interpolateColor` inside a `useAnimatedStyle` to drive borderColor/backgroundColor/etc.
18
- *
19
- * @example
20
- * const progress = useColorTransition(focused)
21
- * const animatedStyle = useAnimatedStyle(() => ({
22
- * borderColor: interpolateColor(progress.value, [0, 1], [colors.border, colors.primary]),
23
- * }))
24
- */
25
- export function useColorTransition(
26
- active: boolean,
27
- options: UseColorTransitionOptions = {},
28
- ): SharedValue<number> {
29
- const { duration = TIMINGS.state.duration } = options
30
- const progress = useSharedValue(active ? 1 : 0)
31
-
32
- useEffect(() => {
33
- progress.value = withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard })
34
- }, [active, duration, progress])
35
-
36
- return progress
37
- }
38
-
39
- // Re-export interpolateColor for ergonomic consumer access
40
- export { interpolateColor }
@@ -1,75 +0,0 @@
1
- import { useCallback } from 'react'
2
- import { Platform } from 'react-native'
3
- import {
4
- useSharedValue,
5
- useAnimatedStyle,
6
- withSpring,
7
- } from 'react-native-reanimated'
8
- import { SPRINGS, PRESS_SCALE } from './animations'
9
- import { useHover } from './hover'
10
-
11
- export interface SpringConfig {
12
- stiffness?: number
13
- damping?: number
14
- mass?: number
15
- }
16
-
17
- export interface UsePressScaleOptions {
18
- /** Scale value while pressed. Defaults to `0.95` (button). */
19
- pressScale?: number
20
- /** Scale value while hovered on web. Defaults to `1.02`. Set to `1` to disable. */
21
- hoverScale?: number
22
- /** Spring config for press-in. Defaults to `SPRINGS.pressIn`. */
23
- pressInSpring?: SpringConfig
24
- /** Spring config for press-out. Defaults to `SPRINGS.pressOut`. */
25
- pressOutSpring?: SpringConfig
26
- /** Disable all interaction animations (still returns stable handlers). */
27
- disabled?: boolean
28
- }
29
-
30
- /**
31
- * Unified press + hover scale primitive.
32
- * All animation lives on the UI thread via Reanimated v4 worklets — zero JS-thread cost.
33
- *
34
- * Returns:
35
- * - `animatedStyle`: spread onto an `Animated.View` (from `react-native-reanimated`)
36
- * - `onPressIn` / `onPressOut`: bind to a `TouchableOpacity`
37
- * - `hoverHandlers`: spread for web hover scaling (no-op on native)
38
- */
39
- export function usePressScale({
40
- pressScale = PRESS_SCALE.button,
41
- hoverScale = 1.02,
42
- pressInSpring = SPRINGS.pressIn,
43
- pressOutSpring = SPRINGS.pressOut,
44
- disabled = false,
45
- }: UsePressScaleOptions = {}) {
46
- const scale = useSharedValue(1)
47
- const { hovered, hoverHandlers } = useHover()
48
-
49
- const onPressIn = useCallback(() => {
50
- if (disabled) return
51
- // eslint-disable-next-line react-hooks/immutability
52
- scale.value = withSpring(pressScale, pressInSpring)
53
- }, [disabled, pressScale, pressInSpring, scale])
54
-
55
- const onPressOut = useCallback(() => {
56
- if (disabled) return
57
- // eslint-disable-next-line react-hooks/immutability
58
- scale.value = withSpring(1, pressOutSpring)
59
- }, [disabled, pressOutSpring, scale])
60
-
61
- const hoverActive = Platform.OS === 'web' && hovered && hoverScale !== 1 && !disabled
62
-
63
- const animatedStyle = useAnimatedStyle(() => ({
64
- transform: [
65
- { scale: scale.value * (hoverActive ? hoverScale : 1) },
66
- ],
67
- }))
68
-
69
- return {
70
- animatedStyle,
71
- onPressIn,
72
- onPressOut,
73
- hoverHandlers,
74
- }
75
- }