@retray-dev/ui-kit 6.2.0 → 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 (389) hide show
  1. package/COMPONENTS.md +997 -20
  2. package/EXAMPLES.md +250 -2
  3. package/README.md +21 -14
  4. package/dist/Accordion.d.mts +28 -0
  5. package/dist/Accordion.d.ts +28 -0
  6. package/dist/Accordion.js +392 -0
  7. package/dist/Accordion.mjs +7 -0
  8. package/dist/AlertBanner.d.mts +16 -0
  9. package/dist/AlertBanner.d.ts +16 -0
  10. package/dist/AlertBanner.js +250 -0
  11. package/dist/AlertBanner.mjs +6 -0
  12. package/dist/AppHeader.d.mts +40 -0
  13. package/dist/AppHeader.d.ts +40 -0
  14. package/dist/AppHeader.js +515 -0
  15. package/dist/AppHeader.mjs +10 -0
  16. package/dist/Avatar.d.mts +20 -0
  17. package/dist/Avatar.d.ts +20 -0
  18. package/dist/Avatar.js +244 -0
  19. package/dist/Avatar.mjs +4 -0
  20. package/dist/Badge.d.mts +26 -0
  21. package/dist/Badge.d.ts +26 -0
  22. package/dist/Badge.js +257 -0
  23. package/dist/Badge.mjs +5 -0
  24. package/dist/Button.d.mts +30 -0
  25. package/dist/Button.d.ts +30 -0
  26. package/dist/Button.js +432 -0
  27. package/dist/Button.mjs +9 -0
  28. package/dist/ButtonGroup.d.mts +26 -0
  29. package/dist/ButtonGroup.d.ts +26 -0
  30. package/dist/ButtonGroup.js +52 -0
  31. package/dist/ButtonGroup.mjs +3 -0
  32. package/dist/Card.d.mts +39 -0
  33. package/dist/Card.d.ts +39 -0
  34. package/dist/Card.js +349 -0
  35. package/dist/Card.mjs +8 -0
  36. package/dist/CategoryStrip.d.mts +26 -0
  37. package/dist/CategoryStrip.d.ts +26 -0
  38. package/dist/CategoryStrip.js +453 -0
  39. package/dist/CategoryStrip.mjs +9 -0
  40. package/dist/Checkbox.d.mts +14 -0
  41. package/dist/Checkbox.d.ts +14 -0
  42. package/dist/Checkbox.js +336 -0
  43. package/dist/Checkbox.mjs +7 -0
  44. package/dist/Chip.d.mts +31 -0
  45. package/dist/Chip.d.ts +31 -0
  46. package/dist/Chip.js +403 -0
  47. package/dist/Chip.mjs +8 -0
  48. package/dist/ConfirmDialog.d.mts +15 -0
  49. package/dist/ConfirmDialog.d.ts +15 -0
  50. package/dist/ConfirmDialog.js +560 -0
  51. package/dist/ConfirmDialog.mjs +10 -0
  52. package/dist/CurrencyDisplay.d.mts +24 -0
  53. package/dist/CurrencyDisplay.d.ts +24 -0
  54. package/dist/CurrencyDisplay.js +189 -0
  55. package/dist/CurrencyDisplay.mjs +4 -0
  56. package/dist/CurrencyInput.d.mts +26 -0
  57. package/dist/CurrencyInput.d.ts +26 -0
  58. package/dist/CurrencyInput.js +408 -0
  59. package/dist/CurrencyInput.mjs +8 -0
  60. package/dist/DetailRow.d.mts +32 -0
  61. package/dist/DetailRow.d.ts +32 -0
  62. package/dist/DetailRow.js +275 -0
  63. package/dist/DetailRow.mjs +5 -0
  64. package/dist/EmptyState.d.mts +27 -0
  65. package/dist/EmptyState.d.ts +27 -0
  66. package/dist/EmptyState.js +523 -0
  67. package/dist/EmptyState.mjs +10 -0
  68. package/dist/ErrorBoundary.d.mts +42 -0
  69. package/dist/ErrorBoundary.d.ts +42 -0
  70. package/dist/ErrorBoundary.js +351 -0
  71. package/dist/ErrorBoundary.mjs +7 -0
  72. package/dist/Form.d.mts +52 -0
  73. package/dist/Form.d.ts +52 -0
  74. package/dist/Form.js +204 -0
  75. package/dist/Form.mjs +4 -0
  76. package/dist/HolographicCard.d.mts +55 -0
  77. package/dist/HolographicCard.d.ts +55 -0
  78. package/dist/HolographicCard.js +316 -0
  79. package/dist/HolographicCard.mjs +191 -0
  80. package/dist/IconButton.d.mts +27 -0
  81. package/dist/IconButton.d.ts +27 -0
  82. package/dist/IconButton.js +400 -0
  83. package/dist/IconButton.mjs +8 -0
  84. package/dist/ImageViewer.d.mts +23 -0
  85. package/dist/ImageViewer.d.ts +23 -0
  86. package/dist/ImageViewer.js +582 -0
  87. package/dist/ImageViewer.mjs +8 -0
  88. package/dist/Input.d.mts +23 -0
  89. package/dist/Input.d.ts +23 -0
  90. package/dist/Input.js +351 -0
  91. package/dist/Input.mjs +7 -0
  92. package/dist/LabelValue.d.mts +16 -0
  93. package/dist/LabelValue.d.ts +16 -0
  94. package/dist/LabelValue.js +225 -0
  95. package/dist/LabelValue.mjs +5 -0
  96. package/dist/ListGroup.d.mts +34 -0
  97. package/dist/ListGroup.d.ts +34 -0
  98. package/dist/ListGroup.js +217 -0
  99. package/dist/ListGroup.mjs +5 -0
  100. package/dist/ListItem.d.mts +64 -0
  101. package/dist/ListItem.d.ts +64 -0
  102. package/dist/ListItem.js +444 -0
  103. package/dist/ListItem.mjs +9 -0
  104. package/dist/MediaCard.d.mts +39 -0
  105. package/dist/MediaCard.d.ts +39 -0
  106. package/dist/MediaCard.js +475 -0
  107. package/dist/MediaCard.mjs +9 -0
  108. package/dist/MenuGroup.d.mts +34 -0
  109. package/dist/MenuGroup.d.ts +34 -0
  110. package/dist/MenuGroup.js +217 -0
  111. package/dist/MenuGroup.mjs +5 -0
  112. package/dist/MenuItem.d.mts +48 -0
  113. package/dist/MenuItem.d.ts +48 -0
  114. package/dist/MenuItem.js +415 -0
  115. package/dist/MenuItem.mjs +9 -0
  116. package/dist/MonthPicker.d.mts +28 -0
  117. package/dist/MonthPicker.d.ts +28 -0
  118. package/dist/MonthPicker.js +297 -0
  119. package/dist/MonthPicker.mjs +5 -0
  120. package/dist/PagerDots.d.mts +35 -0
  121. package/dist/PagerDots.d.ts +35 -0
  122. package/dist/PagerDots.js +392 -0
  123. package/dist/PagerDots.mjs +7 -0
  124. package/dist/Pressable.d.mts +34 -0
  125. package/dist/Pressable.d.ts +34 -0
  126. package/dist/Pressable.js +143 -0
  127. package/dist/Pressable.mjs +5 -0
  128. package/dist/PricingCard.d.mts +50 -0
  129. package/dist/PricingCard.d.ts +50 -0
  130. package/dist/PricingCard.js +636 -0
  131. package/dist/PricingCard.mjs +11 -0
  132. package/dist/Progress.d.mts +14 -0
  133. package/dist/Progress.d.ts +14 -0
  134. package/dist/Progress.js +191 -0
  135. package/dist/Progress.mjs +5 -0
  136. package/dist/RadioGroup.d.mts +19 -0
  137. package/dist/RadioGroup.d.ts +19 -0
  138. package/dist/RadioGroup.js +392 -0
  139. package/dist/RadioGroup.mjs +7 -0
  140. package/dist/RetrayProvider.d.mts +2 -0
  141. package/dist/RetrayProvider.d.ts +2 -0
  142. package/dist/RetrayProvider.js +214 -0
  143. package/dist/RetrayProvider.mjs +5 -0
  144. package/dist/Select.d.mts +22 -0
  145. package/dist/Select.d.ts +22 -0
  146. package/dist/Select.js +488 -0
  147. package/dist/Select.mjs +7 -0
  148. package/dist/SelectableGrid.d.mts +44 -0
  149. package/dist/SelectableGrid.d.ts +44 -0
  150. package/dist/SelectableGrid.js +448 -0
  151. package/dist/SelectableGrid.mjs +9 -0
  152. package/dist/Separator.d.mts +10 -0
  153. package/dist/Separator.d.ts +10 -0
  154. package/dist/Separator.js +156 -0
  155. package/dist/Separator.mjs +3 -0
  156. package/dist/Sheet.d.mts +93 -0
  157. package/dist/Sheet.d.ts +93 -0
  158. package/dist/Sheet.js +450 -0
  159. package/dist/Sheet.mjs +6 -0
  160. package/dist/Skeleton.d.mts +67 -0
  161. package/dist/Skeleton.d.ts +67 -0
  162. package/dist/Skeleton.js +266 -0
  163. package/dist/Skeleton.mjs +6 -0
  164. package/dist/Slider.d.mts +20 -0
  165. package/dist/Slider.d.ts +20 -0
  166. package/dist/Slider.js +279 -0
  167. package/dist/Slider.mjs +5 -0
  168. package/dist/Spinner.d.mts +12 -0
  169. package/dist/Spinner.d.ts +12 -0
  170. package/dist/Spinner.js +193 -0
  171. package/dist/Spinner.mjs +4 -0
  172. package/dist/Switch.d.mts +13 -0
  173. package/dist/Switch.d.ts +13 -0
  174. package/dist/Switch.js +311 -0
  175. package/dist/Switch.mjs +6 -0
  176. package/dist/TabBar.d.mts +42 -0
  177. package/dist/TabBar.d.ts +42 -0
  178. package/dist/TabBar.js +361 -0
  179. package/dist/TabBar.mjs +6 -0
  180. package/dist/Tabs.d.mts +27 -0
  181. package/dist/Tabs.d.ts +27 -0
  182. package/dist/Tabs.js +419 -0
  183. package/dist/Tabs.mjs +7 -0
  184. package/dist/Text.d.mts +12 -0
  185. package/dist/Text.d.ts +12 -0
  186. package/dist/Text.js +327 -0
  187. package/dist/Text.mjs +5 -0
  188. package/dist/Textarea.d.mts +16 -0
  189. package/dist/Textarea.d.ts +16 -0
  190. package/dist/Textarea.js +333 -0
  191. package/dist/Textarea.mjs +7 -0
  192. package/dist/Toast.d.mts +47 -0
  193. package/dist/Toast.d.ts +47 -0
  194. package/dist/Toast.js +185 -0
  195. package/dist/Toast.mjs +4 -0
  196. package/dist/Toggle.d.mts +36 -0
  197. package/dist/Toggle.d.ts +36 -0
  198. package/dist/Toggle.js +412 -0
  199. package/dist/Toggle.mjs +8 -0
  200. package/dist/VirtualList.d.mts +19 -0
  201. package/dist/VirtualList.d.ts +19 -0
  202. package/dist/VirtualList.js +38 -0
  203. package/dist/VirtualList.mjs +2 -0
  204. package/dist/chunk-26BCI223.mjs +14 -0
  205. package/dist/chunk-2CE3TQVY.mjs +11 -0
  206. package/dist/chunk-2TFTAWVJ.mjs +131 -0
  207. package/dist/chunk-2UYENBLV.mjs +49 -0
  208. package/dist/chunk-3BBOZ3OQ.mjs +41 -0
  209. package/dist/chunk-3DKJ2GIC.mjs +30 -0
  210. package/dist/chunk-3U4SSNWP.mjs +120 -0
  211. package/dist/chunk-4I7D47FH.mjs +139 -0
  212. package/dist/chunk-4K625MVM.mjs +142 -0
  213. package/dist/chunk-6OAZJ577.mjs +98 -0
  214. package/dist/chunk-6Q64UFIA.mjs +71 -0
  215. package/dist/chunk-756RAKE4.mjs +145 -0
  216. package/dist/chunk-7QHVVCB3.mjs +115 -0
  217. package/dist/chunk-A3A6KNQN.mjs +245 -0
  218. package/dist/chunk-A4MDAP7G.mjs +42 -0
  219. package/dist/chunk-AJ7ZDNBT.mjs +120 -0
  220. package/dist/chunk-AV4EMIRH.mjs +94 -0
  221. package/dist/chunk-AZJF2BLK.mjs +115 -0
  222. package/dist/chunk-BNP626TY.mjs +159 -0
  223. package/dist/chunk-BRKYVJVV.mjs +60 -0
  224. package/dist/chunk-DVK4G2GT.mjs +59 -0
  225. package/dist/chunk-EH745HE5.mjs +127 -0
  226. package/dist/chunk-EJ7ZPXOH.mjs +163 -0
  227. package/dist/chunk-GD6KXMG5.mjs +106 -0
  228. package/dist/chunk-GQYFLP3D.mjs +187 -0
  229. package/dist/chunk-ID72TK46.mjs +111 -0
  230. package/dist/chunk-IRRY3CRZ.mjs +82 -0
  231. package/dist/chunk-JB67UOB5.mjs +92 -0
  232. package/dist/chunk-JMOZEC77.mjs +90 -0
  233. package/dist/chunk-JT7HKXRB.mjs +114 -0
  234. package/dist/chunk-KIHCWCWL.mjs +124 -0
  235. package/dist/chunk-LXJIIOYQ.mjs +104 -0
  236. package/dist/chunk-M6ZXVBTK.mjs +64 -0
  237. package/dist/chunk-MAC465BB.mjs +61 -0
  238. package/dist/chunk-MBMXYJJV.mjs +36 -0
  239. package/dist/chunk-MLF3EZFW.mjs +119 -0
  240. package/dist/chunk-MX6HRKMI.mjs +29 -0
  241. package/dist/chunk-NA7PARID.mjs +147 -0
  242. package/dist/chunk-NC5ZTR2Y.mjs +32 -0
  243. package/dist/chunk-O3HA6TYM.mjs +139 -0
  244. package/dist/chunk-OB4JUQ3O.mjs +51 -0
  245. package/dist/chunk-PFZTM6D5.mjs +238 -0
  246. package/dist/chunk-QKH5ZOD5.mjs +97 -0
  247. package/dist/chunk-QY3X2UYR.mjs +191 -0
  248. package/dist/chunk-SOA2Z4RB.mjs +82 -0
  249. package/dist/chunk-SOYNZDVY.mjs +151 -0
  250. package/dist/chunk-T7XZ7H7Y.mjs +57 -0
  251. package/dist/chunk-TERDKCLE.mjs +74 -0
  252. package/dist/chunk-UREA2GYY.mjs +113 -0
  253. package/dist/chunk-VGTDN7SW.mjs +164 -0
  254. package/dist/chunk-VQ57HWPL.mjs +144 -0
  255. package/dist/chunk-WBOOUHSS.mjs +62 -0
  256. package/dist/chunk-WJLKJMKR.mjs +78 -0
  257. package/dist/chunk-X4G6APW6.mjs +134 -0
  258. package/dist/chunk-Y6FXYEAI.mjs +8 -0
  259. package/dist/chunk-YFZ3ELX5.mjs +16 -0
  260. package/dist/chunk-YNROWHQJ.mjs +46 -0
  261. package/dist/chunk-Z4BVUWW6.mjs +196 -0
  262. package/dist/chunk-ZJKGQMYH.mjs +131 -0
  263. package/dist/index-wt-orHUi.d.mts +85 -0
  264. package/dist/index-wt-orHUi.d.ts +85 -0
  265. package/dist/index.d.mts +149 -920
  266. package/dist/index.d.ts +149 -920
  267. package/dist/index.js +2560 -970
  268. package/dist/index.mjs +60 -3895
  269. package/package.json +55 -16
  270. package/src/assets/fonts/Sohne-Bold.otf +0 -0
  271. package/src/assets/fonts/Sohne-BoldItalic.otf +0 -0
  272. package/src/assets/fonts/Sohne-ExtraBold.otf +0 -0
  273. package/src/assets/fonts/Sohne-ExtraBoldItalic.otf +0 -0
  274. package/src/assets/fonts/Sohne-ExtraLight.otf +0 -0
  275. package/src/assets/fonts/Sohne-ExtraLightItalic.otf +0 -0
  276. package/src/assets/fonts/Sohne-Italic.otf +0 -0
  277. package/src/assets/fonts/Sohne-Light.otf +0 -0
  278. package/src/assets/fonts/Sohne-LightItalic.otf +0 -0
  279. package/src/assets/fonts/Sohne-Medium.otf +0 -0
  280. package/src/assets/fonts/Sohne-MediumItalic.otf +0 -0
  281. package/src/assets/fonts/Sohne-Regular.otf +0 -0
  282. package/src/assets/fonts/Sohne-SemiBold.otf +0 -0
  283. package/src/assets/fonts/Sohne-SemiBoldItalic.otf +0 -0
  284. package/src/assets/fonts/SohneMono-Bold.otf +0 -0
  285. package/src/assets/fonts/SohneMono-BoldItalic.otf +0 -0
  286. package/src/assets/fonts/SohneMono-ExtraBold.otf +0 -0
  287. package/src/assets/fonts/SohneMono-ExtraBoldItalic.otf +0 -0
  288. package/src/assets/fonts/SohneMono-ExtraLight.otf +0 -0
  289. package/src/assets/fonts/SohneMono-ExtraLightItalic.otf +0 -0
  290. package/src/assets/fonts/SohneMono-Italic.otf +0 -0
  291. package/src/assets/fonts/SohneMono-Light.otf +0 -0
  292. package/src/assets/fonts/SohneMono-LightItalic.otf +0 -0
  293. package/src/assets/fonts/SohneMono-Medium.otf +0 -0
  294. package/src/assets/fonts/SohneMono-MediumItalic.otf +0 -0
  295. package/src/assets/fonts/SohneMono-Regular.otf +0 -0
  296. package/src/assets/fonts/SohneMono-SemiBold.otf +0 -0
  297. package/src/assets/fonts/SohneMono-SemiBoldItalic.otf +0 -0
  298. package/src/components/Accordion/Accordion.tsx +15 -4
  299. package/src/components/AlertBanner/AlertBanner.tsx +38 -12
  300. package/src/components/AppHeader/AppHeader.tsx +172 -0
  301. package/src/components/AppHeader/index.ts +1 -0
  302. package/src/components/Avatar/Avatar.tsx +14 -4
  303. package/src/components/Badge/Badge.tsx +12 -3
  304. package/src/components/Button/Button.tsx +30 -38
  305. package/src/components/ButtonGroup/ButtonGroup.tsx +13 -10
  306. package/src/components/Card/Card.tsx +29 -57
  307. package/src/components/CategoryStrip/CategoryStrip.tsx +41 -42
  308. package/src/components/Checkbox/Checkbox.tsx +36 -45
  309. package/src/components/Chip/Chip.tsx +41 -48
  310. package/src/components/ConfirmDialog/ConfirmDialog.tsx +2 -2
  311. package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +4 -2
  312. package/src/components/CurrencyInput/CurrencyInput.tsx +12 -10
  313. package/src/components/DetailRow/DetailRow.tsx +9 -7
  314. package/src/components/EmptyState/EmptyState.tsx +4 -3
  315. package/src/components/ErrorBoundary/ErrorBoundary.tsx +153 -0
  316. package/src/components/ErrorBoundary/index.ts +1 -0
  317. package/src/components/Form/Form.tsx +149 -0
  318. package/src/components/Form/index.ts +1 -0
  319. package/src/components/HolographicCard/HolographicCard.tsx +315 -0
  320. package/src/components/HolographicCard/index.ts +1 -0
  321. package/src/components/IconButton/IconButton.tsx +23 -29
  322. package/src/components/ImageViewer/ImageViewer.tsx +290 -0
  323. package/src/components/ImageViewer/index.ts +1 -0
  324. package/src/components/Input/Input.tsx +27 -31
  325. package/src/components/LabelValue/LabelValue.tsx +6 -4
  326. package/src/components/ListGroup/ListGroup.tsx +145 -0
  327. package/src/components/ListGroup/index.ts +1 -0
  328. package/src/components/ListItem/ListItem.tsx +78 -76
  329. package/src/components/MediaCard/MediaCard.tsx +15 -7
  330. package/src/components/MenuGroup/MenuGroup.tsx +145 -0
  331. package/src/components/MenuGroup/index.ts +1 -0
  332. package/src/components/MenuItem/MenuItem.tsx +16 -33
  333. package/src/components/MonthPicker/MonthPicker.tsx +41 -15
  334. package/src/components/MonthPicker/index.ts +1 -1
  335. package/src/components/PagerDots/PagerDots.tsx +200 -0
  336. package/src/components/PagerDots/index.ts +1 -0
  337. package/src/components/Pressable/Pressable.tsx +19 -35
  338. package/src/components/PricingCard/PricingCard.tsx +220 -0
  339. package/src/components/PricingCard/index.ts +1 -0
  340. package/src/components/RadioGroup/RadioGroup.tsx +23 -39
  341. package/src/components/RetrayProvider/RetrayProvider.tsx +59 -0
  342. package/src/components/RetrayProvider/index.ts +1 -0
  343. package/src/components/Select/Select.tsx +6 -6
  344. package/src/components/SelectableGrid/SelectableGrid.tsx +205 -0
  345. package/src/components/SelectableGrid/index.ts +1 -0
  346. package/src/components/Separator/Separator.tsx +1 -3
  347. package/src/components/Sheet/Sheet.tsx +146 -18
  348. package/src/components/Skeleton/Skeleton.tsx +143 -2
  349. package/src/components/Slider/Slider.tsx +2 -2
  350. package/src/components/Spinner/Spinner.tsx +18 -3
  351. package/src/components/Switch/Switch.tsx +44 -49
  352. package/src/components/TabBar/TabBar.tsx +169 -0
  353. package/src/components/TabBar/index.ts +1 -0
  354. package/src/components/Tabs/Tabs.tsx +45 -44
  355. package/src/components/Text/Text.tsx +5 -1
  356. package/src/components/Textarea/Textarea.tsx +18 -14
  357. package/src/components/Toast/Toast.tsx +6 -6
  358. package/src/components/Toggle/Toggle.tsx +80 -72
  359. package/src/components/VirtualList/VirtualList.tsx +60 -0
  360. package/src/components/VirtualList/index.ts +1 -0
  361. package/src/fonts.ts +41 -20
  362. package/src/index.ts +28 -3
  363. package/src/theme/colors.ts +53 -39
  364. package/src/theme/types.ts +3 -0
  365. package/src/tokens.ts +49 -39
  366. package/src/utils/animations.ts +29 -1
  367. package/src/utils/fontGuard.ts +34 -0
  368. package/src/utils/haptics.ts +211 -9
  369. package/src/utils/icons.ts +47 -20
  370. package/src/utils/pressable.ts +66 -0
  371. package/src/utils/usePressScale.ts +2 -0
  372. package/src/assets/fonts/Poppins-Black.ttf +0 -0
  373. package/src/assets/fonts/Poppins-BlackItalic.ttf +0 -0
  374. package/src/assets/fonts/Poppins-Bold.ttf +0 -0
  375. package/src/assets/fonts/Poppins-BoldItalic.ttf +0 -0
  376. package/src/assets/fonts/Poppins-ExtraBold.ttf +0 -0
  377. package/src/assets/fonts/Poppins-ExtraBoldItalic.ttf +0 -0
  378. package/src/assets/fonts/Poppins-ExtraLight.ttf +0 -0
  379. package/src/assets/fonts/Poppins-ExtraLightItalic.ttf +0 -0
  380. package/src/assets/fonts/Poppins-Italic.ttf +0 -0
  381. package/src/assets/fonts/Poppins-Light.ttf +0 -0
  382. package/src/assets/fonts/Poppins-LightItalic.ttf +0 -0
  383. package/src/assets/fonts/Poppins-Medium.ttf +0 -0
  384. package/src/assets/fonts/Poppins-MediumItalic.ttf +0 -0
  385. package/src/assets/fonts/Poppins-Regular.ttf +0 -0
  386. package/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
  387. package/src/assets/fonts/Poppins-SemiBoldItalic.ttf +0 -0
  388. package/src/assets/fonts/Poppins-Thin.ttf +0 -0
  389. package/src/assets/fonts/Poppins-ThinItalic.ttf +0 -0
package/src/tokens.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  // ─── Spacing ─────────────────────────────────────────────────────────────────
2
- // 8pt grid with 2pt micro-step. `section` for major band separators (Airbnb: 64px).
3
2
  export const SPACING = {
4
3
  xxs: 2,
5
4
  xs: 4,
@@ -22,8 +21,6 @@ export const ICON_SIZES = {
22
21
  } as const
23
22
 
24
23
  // ─── Border radius ────────────────────────────────────────────────────────────
25
- // Airbnb-aligned shape language — soft everywhere, no hard corners on interactive elements.
26
- // xs: micro chips/tags sm: inputs/forms md: cards lg: sheet corners xl: primary CTAs (pill)
27
24
  export const RADIUS = {
28
25
  none: 0,
29
26
  xs: 4,
@@ -35,7 +32,6 @@ export const RADIUS = {
35
32
  } as const
36
33
 
37
34
  // ─── Shadows ──────────────────────────────────────────────────────────────────
38
- // Multi-tier. Default card usage = sm. Hover float = md. Modals = lg/xl.
39
35
  export const SHADOWS = {
40
36
  sm: {
41
37
  shadowColor: '#000',
@@ -73,118 +69,132 @@ export const BREAKPOINTS = {
73
69
  } as const
74
70
 
75
71
  // ─── Typography ───────────────────────────────────────────────────────────────
76
- // Airbnb-inspired hierarchy. Modest weights500-600 on display, not 700+.
77
- // Exception: display-hero (large number display) and display-xl always bold.
78
- // Poppins carries the full scale. All fontFamily values reference loaded font names.
72
+ // AUDIT FIX: Rationalised display scale removed weight inversions and size
73
+ // collisions. display-lg/md separated by 4px with matching weights. title-md/sm
74
+ // now actually differ in size. uppercase-tag raised from 10px 11px for
75
+ // minimum mobile readability (Apple HIG: 11pt floor).
79
76
  export const TYPOGRAPHY = {
80
77
  'display-hero': {
81
- fontFamily: 'Poppins-Bold',
78
+ fontFamily: 'Sohne-Bold',
82
79
  fontSize: 64,
83
80
  fontWeight: '700' as const,
84
81
  lineHeight: 70,
85
82
  letterSpacing: -1,
86
83
  },
87
84
  'display-xl': {
88
- fontFamily: 'Poppins-Bold',
85
+ fontFamily: 'Sohne-Bold',
89
86
  fontSize: 28,
90
87
  fontWeight: '700' as const,
91
88
  lineHeight: 40,
92
89
  letterSpacing: 0,
93
90
  },
91
+ // AUDIT FIX: was 22px/500 — raised to 24px/600; removes weight inversion vs display-md
94
92
  'display-lg': {
95
- fontFamily: 'Poppins-Medium',
96
- fontSize: 22,
97
- fontWeight: '500' as const,
98
- lineHeight: 26,
99
- letterSpacing: -0.44,
93
+ fontFamily: 'Sohne-SemiBold',
94
+ fontSize: 24,
95
+ fontWeight: '600' as const,
96
+ lineHeight: 32,
97
+ letterSpacing: -0.3,
100
98
  },
99
+ // AUDIT FIX: was 21px/700 — lowered to 20px/600; weight normalised, 4px gap preserved
101
100
  'display-md': {
102
- fontFamily: 'Poppins-Bold',
103
- fontSize: 21,
104
- fontWeight: '700' as const,
105
- lineHeight: 30,
101
+ fontFamily: 'Sohne-SemiBold',
102
+ fontSize: 20,
103
+ fontWeight: '600' as const,
104
+ lineHeight: 28,
106
105
  letterSpacing: 0,
107
106
  },
108
107
  'display-sm': {
109
- fontFamily: 'Poppins-SemiBold',
110
- fontSize: 20,
108
+ fontFamily: 'Sohne-SemiBold',
109
+ fontSize: 18,
111
110
  fontWeight: '600' as const,
112
111
  lineHeight: 24,
113
112
  letterSpacing: -0.18,
114
113
  },
114
+ // AUDIT FIX: was 16px — raised to 17px so title-md > title-sm is size-visible
115
115
  'title-md': {
116
- fontFamily: 'Poppins-SemiBold',
117
- fontSize: 16,
116
+ fontFamily: 'Sohne-SemiBold',
117
+ fontSize: 17,
118
118
  fontWeight: '600' as const,
119
- lineHeight: 20,
119
+ lineHeight: 22,
120
120
  letterSpacing: 0,
121
121
  },
122
+ // AUDIT FIX: was 16px — lowered to 15px; now distinct from title-md
122
123
  'title-sm': {
123
- fontFamily: 'Poppins-Medium',
124
- fontSize: 16,
124
+ fontFamily: 'Sohne-Medium',
125
+ fontSize: 15,
125
126
  fontWeight: '500' as const,
126
127
  lineHeight: 20,
127
128
  letterSpacing: 0,
128
129
  },
129
130
  'body-md': {
130
- fontFamily: 'Poppins-Regular',
131
+ fontFamily: 'Sohne-Regular',
131
132
  fontSize: 16,
132
133
  fontWeight: '400' as const,
133
134
  lineHeight: 24,
134
135
  letterSpacing: 0,
135
136
  },
136
137
  'body-sm': {
137
- fontFamily: 'Poppins-Regular',
138
+ fontFamily: 'Sohne-Regular',
138
139
  fontSize: 14,
139
140
  fontWeight: '400' as const,
140
141
  lineHeight: 20,
141
142
  letterSpacing: 0,
142
143
  },
143
- caption: {
144
- fontFamily: 'Poppins-Medium',
144
+ 'caption': {
145
+ fontFamily: 'Sohne-Medium',
145
146
  fontSize: 14,
146
147
  fontWeight: '500' as const,
147
148
  lineHeight: 18,
148
149
  letterSpacing: 0,
149
150
  },
150
151
  'caption-sm': {
151
- fontFamily: 'Poppins-Regular',
152
+ fontFamily: 'Sohne-Regular',
152
153
  fontSize: 13,
153
154
  fontWeight: '400' as const,
154
155
  lineHeight: 16,
155
156
  letterSpacing: 0,
156
157
  },
157
158
  'badge-text': {
158
- fontFamily: 'Poppins-SemiBold',
159
+ fontFamily: 'Sohne-SemiBold',
159
160
  fontSize: 11,
160
161
  fontWeight: '600' as const,
161
- lineHeight: 13,
162
+ lineHeight: 14,
163
+ letterSpacing: 0,
164
+ },
165
+ // AUDIT FIX: added badge-text-md so Badge md size has a canonical token
166
+ 'badge-text-md': {
167
+ fontFamily: 'Sohne-SemiBold',
168
+ fontSize: 13,
169
+ fontWeight: '600' as const,
170
+ lineHeight: 16,
162
171
  letterSpacing: 0,
163
172
  },
164
173
  'micro-label': {
165
- fontFamily: 'Poppins-Bold',
174
+ fontFamily: 'Sohne-Bold',
166
175
  fontSize: 12,
167
176
  fontWeight: '700' as const,
168
177
  lineHeight: 16,
169
178
  letterSpacing: 0,
170
179
  },
180
+ // AUDIT FIX: was 10px/0.8 letterSpacing — raised to 11px/0.6; minimum mobile readability
171
181
  'uppercase-tag': {
172
- fontFamily: 'Poppins-Bold',
173
- fontSize: 10,
182
+ fontFamily: 'Sohne-Bold',
183
+ fontSize: 11,
174
184
  fontWeight: '700' as const,
175
- lineHeight: 13,
176
- letterSpacing: 0.8,
185
+ lineHeight: 14,
186
+ letterSpacing: 0.6,
177
187
  textTransform: 'uppercase' as const,
178
188
  },
179
189
  'button-lg': {
180
- fontFamily: 'Poppins-Medium',
190
+ fontFamily: 'Sohne-Medium',
181
191
  fontSize: 16,
182
192
  fontWeight: '500' as const,
183
193
  lineHeight: 22,
184
194
  letterSpacing: 0,
185
195
  },
186
196
  'button-sm': {
187
- fontFamily: 'Poppins-Medium',
197
+ fontFamily: 'Sohne-Medium',
188
198
  fontSize: 14,
189
199
  fontWeight: '500' as const,
190
200
  lineHeight: 18,
@@ -1,4 +1,5 @@
1
1
  import { Easing } from 'react-native-reanimated'
2
+ import type { SingleTransition } from 'react-native-ease'
2
3
 
3
4
  // ─── Spring presets ──────────────────────────────────────────────────────────
4
5
  // Tuned for the "Apple HIG / Airbnb" press-feel: snap inward fast, settle out elastically.
@@ -17,7 +18,7 @@ export const SPRINGS = {
17
18
  surfacePressOut: { stiffness: 220, damping: 20, mass: 0.95 },
18
19
 
19
20
  /** Settled transitions for moving indicators — Tabs pill, Switch thumb. */
20
- glide: { stiffness: 380, damping: 38, mass: 1.0 },
21
+ glide: { stiffness: 380, damping: 38, mass: 1 },
21
22
 
22
23
  /** Elastic indicator — Switch thumb, RadioGroup dot. */
23
24
  elastic: { stiffness: 320, damping: 22, mass: 0.7 },
@@ -48,6 +49,33 @@ export const EASINGS = {
48
49
  collapse: Easing.in(Easing.ease),
49
50
  } as const
50
51
 
52
+ // ─── EaseView transition presets ─────────────────────────────────────────────
53
+ // Equivalents of the reanimated presets above, in `react-native-ease` units.
54
+ // EaseView spring takes raw damping/stiffness/mass (same physical model). EaseView
55
+ // timing takes duration + an easing curve as a cubic-bezier tuple.
56
+
57
+ /** Color/border state transition for Toggle, Checkbox, Chip, CategoryStrip, Switch track. Mirrors TIMINGS.state + EASINGS.standard. */
58
+ export const COLOR_TRANSITION: SingleTransition = {
59
+ type: 'timing',
60
+ duration: TIMINGS.state.duration,
61
+ easing: [0.2, 0, 0, 1],
62
+ }
63
+
64
+ /** Icon/opacity crossfade. Mirrors TIMINGS.state + EASINGS.standard. */
65
+ export const OPACITY_TRANSITION: SingleTransition = {
66
+ type: 'timing',
67
+ duration: TIMINGS.state.duration,
68
+ easing: [0.2, 0, 0, 1],
69
+ }
70
+
71
+ /** Elastic indicator spring — Switch thumb, RadioGroup dot. Mirrors SPRINGS.elastic. */
72
+ export const SPRING_ELASTIC: SingleTransition = {
73
+ type: 'spring',
74
+ stiffness: 320,
75
+ damping: 22,
76
+ mass: 0.7,
77
+ }
78
+
51
79
  // ─── Press scale tokens ──────────────────────────────────────────────────────
52
80
  // Per-component press intensities — taken from DESIGN.md.
53
81
  export const PRESS_SCALE = {
@@ -0,0 +1,34 @@
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 { SohneFonts } from '@retray-dev/ui-kit/fonts'\n\n" +
27
+ ' const [fontsLoaded] = useFonts(SohneFonts)\n' +
28
+ ' if (!fontsLoaded) return null\n',
29
+ )
30
+ }
31
+ } catch {
32
+ // `isLoaded` not available in this expo-font version — skip the guard silently.
33
+ }
34
+ }
@@ -1,38 +1,240 @@
1
- import { Platform } from 'react-native'
1
+ /**
2
+ * Haptic feedback utilities using expo-haptics.
3
+ *
4
+ * Uses expo-haptics which works with both Expo Go and development builds.
5
+ * react-native-pulsar support is optional for dev builds with native modules.
6
+ *
7
+ * All functions are web-safe (no-op on web platform).
8
+ */
9
+ import { Platform, NativeModules } from 'react-native'
2
10
 
11
+ // ─── expo-haptics (primary) ───────────────────────────────────────────────────
3
12
  type HapticsModule = typeof import('expo-haptics')
4
-
5
13
  let _haptics: HapticsModule | null = null
14
+ let _hapticsLoaded = false
6
15
 
7
16
  async function getHaptics(): Promise<HapticsModule | null> {
8
17
  if (Platform.OS === 'web') return null
9
- if (!_haptics) {
10
- _haptics = await import('expo-haptics')
18
+ if (!_hapticsLoaded) {
19
+ _hapticsLoaded = true
20
+ try {
21
+ _haptics = await import('expo-haptics')
22
+ } catch {
23
+ _haptics = null
24
+ }
11
25
  }
12
26
  return _haptics
13
27
  }
14
28
 
29
+ // ─── Pulsar (optional for dev builds) ─────────────────────────────────────────
30
+ // Only available in development builds with native modules installed.
31
+ // Gracefully falls back to expo-haptics if not available.
32
+ type PulsarModule = typeof import('react-native-pulsar')
33
+ let _pulsar: PulsarModule | null = null
34
+ let _pulsarChecked = false
35
+ let _pulsarAvailable = false
36
+
37
+ function isPulsarNativeRegistered(): boolean {
38
+ // react-native-pulsar's NativeRNPulsar.ts calls
39
+ // TurboModuleRegistry.getEnforcing('RNPulsar') at module-eval time. When the
40
+ // native binary is absent (e.g. Expo Go), requiring the package throws during
41
+ // Metro module eval — and that throw is surfaced by RN's global error handler
42
+ // (red screen) even when wrapped in try/catch, because guardedLoadModule
43
+ // reports it before rethrowing. So we must confirm the native module is
44
+ // actually registered BEFORE requiring the JS wrapper.
45
+ //
46
+ // TurboModuleRegistry.get() returns a truthy proxy even for unregistered
47
+ // modules (false positive), so it can't be trusted. Instead we probe the low
48
+ // level: the new-arch turbo proxy returns null for unregistered names, and
49
+ // the old-arch NativeModules map omits them. A direct lookup throws nothing —
50
+ // unlike a top-level import — so any failure is caught safely here.
51
+ try {
52
+ const g = globalThis as {
53
+ __turboModuleProxy?: (name: string) => unknown
54
+ }
55
+ if (typeof g.__turboModuleProxy === 'function') {
56
+ return g.__turboModuleProxy('RNPulsar') != null
57
+ }
58
+ return NativeModules?.RNPulsar != null
59
+ } catch {
60
+ return false
61
+ }
62
+ }
63
+
64
+ function getPulsar(): PulsarModule | null {
65
+ if (Platform.OS === 'web') return null
66
+ if (!_pulsarChecked) {
67
+ _pulsarChecked = true
68
+ try {
69
+ // Only require the package when its native module is registered —
70
+ // otherwise the require would red-screen the app (see above).
71
+ if (isPulsarNativeRegistered()) {
72
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
73
+ _pulsar = require('react-native-pulsar') as PulsarModule
74
+ _pulsarAvailable = true
75
+ }
76
+ } catch {
77
+ _pulsar = null
78
+ _pulsarAvailable = false
79
+ }
80
+ }
81
+ return _pulsarAvailable ? _pulsar : null
82
+ }
83
+
84
+ // ─── Public API ───────────────────────────────────────────────────────────────
85
+
86
+ /**
87
+ * Light selection feedback — checkboxes, switches, toggles, pickers.
88
+ */
15
89
  export function selectionAsync(): void {
16
90
  if (Platform.OS === 'web') return
17
- getHaptics().then(h => h?.selectionAsync())
91
+ // Try expo-haptics first (always available in Expo Go)
92
+ getHaptics().then((h) => {
93
+ if (h) {
94
+ h.selectionAsync()
95
+ } else {
96
+ // Fallback to Pulsar if available
97
+ getPulsar()?.Presets.System.selection()
98
+ }
99
+ })
18
100
  }
19
101
 
102
+ /**
103
+ * Light impact — cards, surfaces, light interactions.
104
+ */
20
105
  export function impactLight(): void {
21
106
  if (Platform.OS === 'web') return
22
- getHaptics().then(h => h?.impactAsync(h.ImpactFeedbackStyle.Light))
107
+ getHaptics().then((h) => {
108
+ if (h) {
109
+ h.impactAsync(h.ImpactFeedbackStyle.Light)
110
+ } else {
111
+ getPulsar()?.Presets.System.impactLight()
112
+ }
113
+ })
23
114
  }
24
115
 
116
+ /**
117
+ * Medium impact — buttons, primary actions.
118
+ */
25
119
  export function impactMedium(): void {
26
120
  if (Platform.OS === 'web') return
27
- getHaptics().then(h => h?.impactAsync(h.ImpactFeedbackStyle.Medium))
121
+ getHaptics().then((h) => {
122
+ if (h) {
123
+ h.impactAsync(h.ImpactFeedbackStyle.Medium)
124
+ } else {
125
+ getPulsar()?.Presets.System.impactMedium()
126
+ }
127
+ })
128
+ }
129
+
130
+ /**
131
+ * Heavy impact — confirmations, important actions.
132
+ */
133
+ export function impactHeavy(): void {
134
+ if (Platform.OS === 'web') return
135
+ getHaptics().then((h) => {
136
+ if (h) {
137
+ h.impactAsync(h.ImpactFeedbackStyle.Heavy)
138
+ } else {
139
+ getPulsar()?.Presets.System.impactHeavy()
140
+ }
141
+ })
28
142
  }
29
143
 
144
+ /**
145
+ * Success notification — confirmations, completed actions.
146
+ */
30
147
  export function notificationSuccess(): void {
31
148
  if (Platform.OS === 'web') return
32
- getHaptics().then(h => h?.notificationAsync(h.NotificationFeedbackType.Success))
149
+ getHaptics().then((h) => {
150
+ if (h) {
151
+ h.notificationAsync(h.NotificationFeedbackType.Success)
152
+ } else {
153
+ getPulsar()?.Presets.System.notificationSuccess()
154
+ }
155
+ })
33
156
  }
34
157
 
158
+ /**
159
+ * Error notification — failed actions, errors.
160
+ */
35
161
  export function notificationError(): void {
36
162
  if (Platform.OS === 'web') return
37
- getHaptics().then(h => h?.notificationAsync(h.NotificationFeedbackType.Error))
163
+ getHaptics().then((h) => {
164
+ if (h) {
165
+ h.notificationAsync(h.NotificationFeedbackType.Error)
166
+ } else {
167
+ getPulsar()?.Presets.System.notificationError()
168
+ }
169
+ })
170
+ }
171
+
172
+ /**
173
+ * Warning notification — caution states.
174
+ */
175
+ export function notificationWarning(): void {
176
+ if (Platform.OS === 'web') return
177
+ getHaptics().then((h) => {
178
+ if (h) {
179
+ h.notificationAsync(h.NotificationFeedbackType.Warning)
180
+ } else {
181
+ getPulsar()?.Presets.System.notificationWarning()
182
+ }
183
+ })
184
+ }
185
+
186
+ // ─── Rich Pulsar Presets (enhanced feedback) ──────────────────────────────────
187
+
188
+ /**
189
+ * Rich haptic presets from Pulsar — enhanced feedback for special interactions.
190
+ * Falls back to basic expo-haptics on Expo Go or unsupported devices.
191
+ */
192
+ export const richHaptics = {
193
+ /** Hammer strike — strong confirmation feedback. */
194
+ hammer: (): void => {
195
+ if (Platform.OS === 'web') return
196
+ const p = getPulsar()
197
+ if (p) p.Presets.hammer()
198
+ else impactHeavy()
199
+ },
200
+
201
+ /** Pulse — rhythmic feedback for toggles or state changes. */
202
+ pulse: (): void => {
203
+ if (Platform.OS === 'web') return
204
+ const p = getPulsar()
205
+ if (p) p.Presets.pulse()
206
+ else selectionAsync()
207
+ },
208
+
209
+ /** Buzz — continuous vibration for attention. */
210
+ buzz: (): void => {
211
+ if (Platform.OS === 'web') return
212
+ const p = getPulsar()
213
+ if (p) p.Presets.buzz()
214
+ else impactMedium()
215
+ },
216
+
217
+ /** Flick — crisp click feedback. */
218
+ flick: (): void => {
219
+ if (Platform.OS === 'web') return
220
+ const p = getPulsar()
221
+ if (p) p.Presets.flick()
222
+ else selectionAsync()
223
+ },
224
+
225
+ /** Soft — gentle, subtle feedback. */
226
+ soft: (): void => {
227
+ if (Platform.OS === 'web') return
228
+ const p = getPulsar()
229
+ if (p) p.Presets.System.impactSoft()
230
+ else impactLight()
231
+ },
232
+
233
+ /** Rigid — firm, solid feedback. */
234
+ rigid: (): void => {
235
+ if (Platform.OS === 'web') return
236
+ const p = getPulsar()
237
+ if (p) p.Presets.System.impactRigid()
238
+ else impactMedium()
239
+ },
38
240
  }
@@ -17,36 +17,63 @@ export interface IconProps {
17
17
  family?: IconFamily
18
18
  }
19
19
 
20
- type ResolvedFamily = {
20
+ type IconComponentType = React.ComponentType<{ name: string; size: number; color: string }>
21
+ type IconFamilyEntry = {
21
22
  name: IconFamily
22
- component: React.ComponentType<{ name: any; size: number; color: string }>
23
- glyphMap: Record<string, number>
23
+ component: IconComponentType
24
+ /** Deferred — glyphMap is only read when the resolution cache is first built. */
25
+ getGlyphMap: () => Record<string, number>
24
26
  }
25
27
 
26
- // Priority order: highest-priority family listed last so it overwrites lower-priority entries in the cache
27
- const ICON_FAMILIES: ResolvedFamily[] = [
28
- { name: 'Ionicons', component: Ionicons as any, glyphMap: (Ionicons as any).glyphMap },
29
- { name: 'MaterialIcons', component: MaterialIcons as any, glyphMap: (MaterialIcons as any).glyphMap },
30
- { name: 'FontAwesome5', component: FontAwesome5 as any, glyphMap: (FontAwesome5 as any).glyphMap },
31
- { name: 'Entypo', component: Entypo as any, glyphMap: (Entypo as any).glyphMap },
32
- { name: 'AntDesign', component: AntDesign as any, glyphMap: (AntDesign as any).glyphMap },
33
- { name: 'Feather', component: Feather as any, glyphMap: (Feather as any).glyphMap },
28
+ type WithGlyphMap = { glyphMap?: Record<string, number> }
29
+
30
+ const glyphMapOf = (mod: unknown): Record<string, number> =>
31
+ (mod as WithGlyphMap).glyphMap ?? {}
32
+
33
+ // Priority order: highest-priority family LAST so it overwrites lower-priority entries in the cache.
34
+ const ALL_FAMILIES: IconFamilyEntry[] = [
35
+ { name: 'Ionicons', component: Ionicons as unknown as IconComponentType, getGlyphMap: () => glyphMapOf(Ionicons) },
36
+ { name: 'MaterialIcons', component: MaterialIcons as unknown as IconComponentType, getGlyphMap: () => glyphMapOf(MaterialIcons) },
37
+ { name: 'FontAwesome5', component: FontAwesome5 as unknown as IconComponentType, getGlyphMap: () => glyphMapOf(FontAwesome5) },
38
+ { name: 'Entypo', component: Entypo as unknown as IconComponentType, getGlyphMap: () => glyphMapOf(Entypo) },
39
+ { name: 'AntDesign', component: AntDesign as unknown as IconComponentType, getGlyphMap: () => glyphMapOf(AntDesign) },
40
+ { name: 'Feather', component: Feather as unknown as IconComponentType, getGlyphMap: () => glyphMapOf(Feather) },
34
41
  ]
35
42
 
36
- let resolvedCache: Map<string, ResolvedFamily> | null = null
43
+ // Active families participating in name resolution. Defaults to all six.
44
+ let activeFamilies: IconFamilyEntry[] = ALL_FAMILIES
45
+ let resolvedCache: Map<string, IconFamilyEntry> | null = null
46
+
47
+ /**
48
+ * Restrict which icon families participate in automatic name resolution.
49
+ * Narrowing to the families you actually use shrinks the resolution cache and
50
+ * speeds up the first `renderIcon` call (no scanning thousands of unused glyphs).
51
+ *
52
+ * Note: all six families are still statically imported by this module — Metro
53
+ * bundles them regardless. This controls *resolution scope*, not bundle size.
54
+ *
55
+ * @example configureIconFamilies(['Feather', 'MaterialIcons'])
56
+ */
57
+ export function configureIconFamilies(families: IconFamily[]): void {
58
+ const order = families
59
+ .map((n) => ALL_FAMILIES.find((f) => f.name === n))
60
+ .filter((f): f is IconFamilyEntry => f !== undefined)
61
+ activeFamilies = order.length > 0 ? order : ALL_FAMILIES
62
+ resolvedCache = null // invalidate — rebuilt lazily on next resolve
63
+ }
37
64
 
38
- function buildCache(): Map<string, ResolvedFamily> {
39
- const cache = new Map<string, ResolvedFamily>()
40
- for (const family of ICON_FAMILIES) {
41
- if (!family.glyphMap) continue
42
- for (const iconName of Object.keys(family.glyphMap)) {
65
+ function buildCache(): Map<string, IconFamilyEntry> {
66
+ const cache = new Map<string, IconFamilyEntry>()
67
+ for (const family of activeFamilies) {
68
+ const glyphMap = family.getGlyphMap()
69
+ for (const iconName of Object.keys(glyphMap)) {
43
70
  cache.set(iconName, family)
44
71
  }
45
72
  }
46
73
  return cache
47
74
  }
48
75
 
49
- function resolveFamily(name: string): ResolvedFamily | null {
76
+ function resolveFamily(name: string): IconFamilyEntry | null {
50
77
  if (!resolvedCache) {
51
78
  resolvedCache = buildCache()
52
79
  }
@@ -54,10 +81,10 @@ function resolveFamily(name: string): ResolvedFamily | null {
54
81
  }
55
82
 
56
83
  export function Icon({ name, size, color, family }: IconProps): React.ReactElement | null {
57
- let resolved: ResolvedFamily | null = null
84
+ let resolved: IconFamilyEntry | null = null
58
85
 
59
86
  if (family) {
60
- resolved = ICON_FAMILIES.find((f) => f.name === family) ?? null
87
+ resolved = ALL_FAMILIES.find((f) => f.name === family) ?? null
61
88
  } else {
62
89
  resolved = resolveFamily(name)
63
90
  }