@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
@@ -1,21 +1,18 @@
1
1
  import React from 'react'
2
2
  import {
3
- TouchableOpacity,
4
3
  View,
5
4
  Text,
6
5
  StyleSheet,
7
6
  ViewStyle,
8
7
  TextStyle,
9
8
  } from 'react-native'
10
- import Animated from 'react-native-reanimated'
11
9
  import { Entypo } from '@expo/vector-icons'
12
10
  import { selectionAsync as hapticSelection } from '../../utils/haptics'
13
11
  import { useTheme } from '../../theme'
14
12
  import { s, vs, ms, mvs } from '../../utils/scaling'
15
13
  import { renderIcon } from '../../utils/icons'
16
14
  import { RADIUS } from '../../tokens'
17
- import { usePressScale } from '../../utils/usePressScale'
18
- import { SPRINGS, PRESS_SCALE } from '../../utils/animations'
15
+ import { PressableRow } from '../../utils/pressable'
19
16
 
20
17
  export type ListItemVariant = 'plain' | 'card'
21
18
 
@@ -81,7 +78,7 @@ export interface ListItemProps {
81
78
  accessibilityLabel?: string
82
79
  }
83
80
 
84
- export function ListItem({
81
+ function ListItemBase({
85
82
  leftRender,
86
83
  rightRender,
87
84
  trailing,
@@ -105,12 +102,6 @@ export function ListItem({
105
102
  accessibilityLabel,
106
103
  }: ListItemProps) {
107
104
  const { colors } = useTheme()
108
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
109
- pressScale: PRESS_SCALE.row,
110
- pressInSpring: SPRINGS.surfacePressIn,
111
- pressOutSpring: SPRINGS.surfacePressOut,
112
- disabled: !onPress || disabled,
113
- })
114
105
 
115
106
  const handlePress = () => {
116
107
  hapticSelection()
@@ -142,90 +133,101 @@ export function ListItem({
142
133
 
143
134
  const a11yLabel = accessibilityLabel ?? [title, subtitle, caption].filter(Boolean).join('. ')
144
135
 
145
- return (
146
- <Animated.View style={[animatedStyle, disabled && styles.disabled]} {...hoverHandlers}>
147
- <TouchableOpacity
148
- style={[styles.container, cardStyle, style]}
149
- onPress={onPress ? handlePress : undefined}
150
- onPressIn={onPressIn}
151
- onPressOut={onPressOut}
152
- disabled={disabled}
153
- activeOpacity={1}
154
- touchSoundDisabled={true}
155
- accessibilityRole={onPress ? 'button' : undefined}
156
- accessibilityLabel={onPress ? a11yLabel : undefined}
157
- accessibilityState={onPress ? { disabled: !!disabled } : undefined}
158
- >
159
- {effectiveLeft ? (
160
- <View style={styles.leftContainer}>{effectiveLeft}</View>
161
- ) : null}
136
+ const content = (
137
+ <>
138
+ {effectiveLeft ? (
139
+ <View style={styles.leftContainer}>{effectiveLeft}</View>
140
+ ) : null}
162
141
 
163
- <View style={styles.content}>
142
+ <View style={styles.content}>
143
+ <Text
144
+ style={[styles.title, { color: colors.foreground }, titleStyle]}
145
+ numberOfLines={2}
146
+ allowFontScaling={true}
147
+ >
148
+ {title}
149
+ </Text>
150
+ {subtitle ? (
164
151
  <Text
165
- style={[styles.title, { color: colors.foreground }, titleStyle]}
152
+ style={[styles.subtitle, { color: colors.foregroundMuted }, subtitleStyle]}
166
153
  numberOfLines={2}
167
154
  allowFontScaling={true}
168
155
  >
169
- {title}
156
+ {subtitle}
170
157
  </Text>
171
- {subtitle ? (
172
- <Text
173
- style={[styles.subtitle, { color: colors.foregroundMuted }, subtitleStyle]}
174
- numberOfLines={2}
175
- allowFontScaling={true}
176
- >
177
- {subtitle}
178
- </Text>
179
- ) : null}
180
- {caption ? (
158
+ ) : null}
159
+ {caption ? (
160
+ <Text
161
+ style={[styles.caption, { color: colors.foregroundMuted }, captionStyle]}
162
+ numberOfLines={1}
163
+ allowFontScaling={true}
164
+ >
165
+ {caption}
166
+ </Text>
167
+ ) : null}
168
+ </View>
169
+
170
+ {effectiveRight !== undefined ? (
171
+ <View style={styles.rightContainer}>
172
+ {typeof effectiveRight === 'string' ? (
181
173
  <Text
182
- style={[styles.caption, { color: colors.foregroundMuted }, captionStyle]}
183
- numberOfLines={1}
174
+ style={[styles.rightText, { color: colors.foregroundMuted }]}
184
175
  allowFontScaling={true}
185
176
  >
186
- {caption}
177
+ {effectiveRight}
187
178
  </Text>
188
- ) : null}
179
+ ) : (
180
+ effectiveRight
181
+ )}
189
182
  </View>
183
+ ) : showChevron ? (
184
+ <Entypo name="chevron-with-circle-right" size={20} color={colors.foregroundMuted} />
185
+ ) : null}
186
+ </>
187
+ )
190
188
 
191
- {effectiveRight !== undefined ? (
192
- <View style={styles.rightContainer}>
193
- {typeof effectiveRight === 'string' ? (
194
- <Text
195
- style={[styles.rightText, { color: colors.foregroundMuted }]}
196
- allowFontScaling={true}
197
- >
198
- {effectiveRight}
199
- </Text>
200
- ) : (
201
- effectiveRight
202
- )}
203
- </View>
204
- ) : showChevron ? (
205
- <Entypo name="chevron-with-circle-right" size={20} color={colors.foregroundMuted} />
189
+ if (onPress) {
190
+ return (
191
+ <View style={disabled && styles.disabled}>
192
+ <PressableRow
193
+ style={[styles.container, cardStyle, style]}
194
+ onPress={handlePress}
195
+ enabled={!disabled}
196
+ rippleColor="transparent"
197
+ touchSoundDisabled
198
+ activateOnHover
199
+ accessibilityRole="button"
200
+ accessibilityLabel={a11yLabel}
201
+ accessibilityState={{ disabled: !!disabled }}
202
+ >
203
+ {content}
204
+ </PressableRow>
205
+ {showSeparator ? (
206
+ <View style={[styles.separator, { backgroundColor: colors.separator }]} />
206
207
  ) : null}
207
- </TouchableOpacity>
208
+ </View>
209
+ )
210
+ }
208
211
 
212
+ return (
213
+ <View style={[disabled && styles.disabled]}>
214
+ <View style={[styles.container, cardStyle, style]}>
215
+ {content}
216
+ </View>
209
217
  {showSeparator ? (
210
- <View
211
- style={[
212
- styles.separator,
213
- {
214
- backgroundColor: colors.border,
215
- marginLeft: effectiveLeft ? s(44) + s(12) : 0
216
- },
217
- ]}
218
- />
218
+ <View style={[styles.separator, { backgroundColor: colors.separator }]} />
219
219
  ) : null}
220
- </Animated.View>
220
+ </View>
221
221
  )
222
222
  }
223
223
 
224
+ export const ListItem = React.memo(ListItemBase)
225
+
224
226
  const styles = StyleSheet.create({
225
227
  container: {
226
228
  flexDirection: 'row',
227
229
  alignItems: 'center',
228
- paddingHorizontal: 0,
230
+ paddingHorizontal: s(16),
229
231
  paddingVertical: vs(10),
230
232
  gap: s(12),
231
233
  },
@@ -241,17 +243,17 @@ const styles = StyleSheet.create({
241
243
  gap: vs(4),
242
244
  },
243
245
  title: {
244
- fontFamily: 'Poppins-Medium',
246
+ fontFamily: 'Sohne-Medium',
245
247
  fontSize: ms(15),
246
248
  lineHeight: mvs(22),
247
249
  },
248
250
  subtitle: {
249
- fontFamily: 'Poppins-Regular',
251
+ fontFamily: 'Sohne-Regular',
250
252
  fontSize: ms(13),
251
253
  lineHeight: mvs(18),
252
254
  },
253
255
  caption: {
254
- fontFamily: 'Poppins-Regular',
256
+ fontFamily: 'Sohne-Regular',
255
257
  fontSize: ms(12),
256
258
  lineHeight: mvs(16),
257
259
  opacity: 0.7,
@@ -263,7 +265,7 @@ const styles = StyleSheet.create({
263
265
  maxWidth: s(160),
264
266
  },
265
267
  rightText: {
266
- fontFamily: 'Poppins-Regular',
268
+ fontFamily: 'Sohne-Regular',
267
269
  fontSize: ms(14),
268
270
  },
269
271
  separator: {
@@ -61,7 +61,7 @@ export interface MediaCardProps {
61
61
  accessibilityLabel?: string
62
62
  }
63
63
 
64
- export function MediaCard({
64
+ function MediaCardBase({
65
65
  imageSource,
66
66
  aspectRatio = '4:3',
67
67
  badge,
@@ -112,7 +112,7 @@ export function MediaCard({
112
112
  {...(Platform.OS === 'web' ? hoverHandlers : {})}
113
113
  >
114
114
  <View style={[styles.imageContainer, imageStyle]}>
115
- <View style={{ paddingTop: `${ratio * 100}%` as any }}>
115
+ <View style={{ paddingTop: `${ratio * 100}%` as `${number}%` }}>
116
116
  <View style={StyleSheet.absoluteFill}>
117
117
  {imageSource ? (
118
118
  <Image
@@ -135,10 +135,16 @@ export function MediaCard({
135
135
  {(onActionPress || actionIcon || actionIconName) && (
136
136
  <TouchableOpacity
137
137
  style={[styles.actionButton, { backgroundColor: 'rgba(0,0,0,0.24)' }]}
138
- onPress={() => { impactLight(); onActionPress?.() }}
138
+ onPress={(e) => {
139
+ // Stop propagation to prevent triggering parent onPress
140
+ e?.stopPropagation?.()
141
+ impactLight()
142
+ onActionPress?.()
143
+ }}
139
144
  activeOpacity={0.8}
140
145
  touchSoundDisabled={true}
141
- accessibilityRole="button"
146
+ // On web, avoid nested <button> by using a non-button role when parent is pressable
147
+ accessibilityRole={Platform.OS === 'web' && onPress ? undefined : 'button'}
142
148
  accessibilityLabel={actionIconName ?? 'action'}
143
149
  accessibilityState={{ selected: actionActive }}
144
150
  >
@@ -191,6 +197,8 @@ export function MediaCard({
191
197
  return cardContent
192
198
  }
193
199
 
200
+ export const MediaCard = React.memo(MediaCardBase)
201
+
194
202
  const styles = StyleSheet.create({
195
203
  card: {
196
204
  borderRadius: RADIUS.md,
@@ -233,17 +241,17 @@ const styles = StyleSheet.create({
233
241
  gap: vs(2),
234
242
  },
235
243
  title: {
236
- fontFamily: 'Poppins-SemiBold',
244
+ fontFamily: 'Sohne-SemiBold',
237
245
  fontSize: ms(14),
238
246
  lineHeight: mvs(20),
239
247
  },
240
248
  subtitle: {
241
- fontFamily: 'Poppins-Regular',
249
+ fontFamily: 'Sohne-Regular',
242
250
  fontSize: ms(13),
243
251
  lineHeight: mvs(18),
244
252
  },
245
253
  caption: {
246
- fontFamily: 'Poppins-Regular',
254
+ fontFamily: 'Sohne-Regular',
247
255
  fontSize: ms(12),
248
256
  lineHeight: mvs(16),
249
257
  },
@@ -0,0 +1,145 @@
1
+ import React from 'react'
2
+ import { View, Text, StyleSheet, ViewStyle } from 'react-native'
3
+ import { useTheme } from '../../theme'
4
+ import { s, vs } from '../../utils/scaling'
5
+ import { RADIUS } from '../../tokens'
6
+
7
+ export type MenuGroupVariant = 'plain' | 'card'
8
+
9
+ export interface MenuGroupProps {
10
+ children: React.ReactNode
11
+ /**
12
+ * - `plain` (default): no background, plain MenuItems inside.
13
+ * - `card`: card surface with background + border wrapping plain MenuItems.
14
+ */
15
+ variant?: MenuGroupVariant
16
+ style?: ViewStyle
17
+ }
18
+
19
+ export interface MenuGroupHeaderProps {
20
+ children: React.ReactNode
21
+ style?: ViewStyle
22
+ }
23
+
24
+ export interface MenuGroupFooterProps {
25
+ children: React.ReactNode
26
+ style?: ViewStyle
27
+ }
28
+
29
+ /**
30
+ * MenuGroup wraps multiple MenuItems and auto-adds separators between them.
31
+ * Use variant="card" for a standalone surface or "plain" for items inside another container.
32
+ */
33
+ export function MenuGroup({ children, variant = 'plain', style }: MenuGroupProps) {
34
+ const { colors } = useTheme()
35
+
36
+ // Auto-inject showSeparator={true} to all MenuItem children except the last
37
+ const processedChildren = React.Children.map(children, (child, index) => {
38
+ if (!React.isValidElement(child)) return child
39
+
40
+ // Skip MenuGroup.Header and MenuGroup.Footer
41
+ if (child.type === MenuGroupHeader || child.type === MenuGroupFooter) {
42
+ return child
43
+ }
44
+
45
+ // Check if it's a MenuItem (has onPress prop as a heuristic)
46
+ const childProps = child.props as Record<string, unknown>
47
+ const isMenuItem = 'onPress' in childProps
48
+ if (!isMenuItem) return child
49
+
50
+ const isLast = index === React.Children.count(children) - 1
51
+
52
+ // Only add separator if not already explicitly set and not last item
53
+ if (childProps['showSeparator'] === undefined && !isLast) {
54
+ return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {
55
+ showSeparator: true,
56
+ })
57
+ }
58
+
59
+ return child
60
+ })
61
+
62
+ const cardStyle: ViewStyle =
63
+ variant === 'card'
64
+ ? {
65
+ backgroundColor: colors.card,
66
+ borderRadius: RADIUS.md,
67
+ borderWidth: 1,
68
+ borderColor: colors.border,
69
+ shadowColor: '#000',
70
+ shadowOffset: { width: 0, height: 2 },
71
+ shadowOpacity: 0.06,
72
+ shadowRadius: 6,
73
+ elevation: 2,
74
+ paddingVertical: vs(4),
75
+ }
76
+ : {}
77
+
78
+ return (
79
+ <View style={[styles.container, cardStyle, style]}>
80
+ {processedChildren}
81
+ </View>
82
+ )
83
+ }
84
+
85
+ export function MenuGroupHeader({ children, style }: MenuGroupHeaderProps) {
86
+ const { colors } = useTheme()
87
+
88
+ if (typeof children === 'string') {
89
+ return (
90
+ <View style={[styles.header, { borderBottomColor: colors.separator }, style]}>
91
+ <Text style={[styles.headerText, { color: colors.foregroundMuted }]} allowFontScaling={true}>
92
+ {children}
93
+ </Text>
94
+ </View>
95
+ )
96
+ }
97
+
98
+ return <View style={[styles.header, { borderBottomColor: colors.separator }, style]}>{children}</View>
99
+ }
100
+
101
+ export function MenuGroupFooter({ children, style }: MenuGroupFooterProps) {
102
+ const { colors } = useTheme()
103
+
104
+ if (typeof children === 'string') {
105
+ return (
106
+ <View style={[styles.footer, style]}>
107
+ <Text style={[styles.footerText, { color: colors.foregroundMuted }]} allowFontScaling={true}>
108
+ {children}
109
+ </Text>
110
+ </View>
111
+ )
112
+ }
113
+
114
+ return <View style={[styles.footer, style]}>{children}</View>
115
+ }
116
+
117
+ MenuGroup.Header = MenuGroupHeader
118
+ MenuGroup.Footer = MenuGroupFooter
119
+
120
+ const styles = StyleSheet.create({
121
+ container: {
122
+ overflow: 'hidden',
123
+ },
124
+ header: {
125
+ paddingHorizontal: s(16),
126
+ paddingTop: vs(12),
127
+ paddingBottom: vs(8),
128
+ borderBottomWidth: StyleSheet.hairlineWidth,
129
+ },
130
+ headerText: {
131
+ fontFamily: 'Sohne-SemiBold',
132
+ fontSize: 13,
133
+ letterSpacing: 0.32,
134
+ textTransform: 'uppercase',
135
+ },
136
+ footer: {
137
+ paddingHorizontal: s(16),
138
+ paddingTop: vs(8),
139
+ paddingBottom: vs(12),
140
+ },
141
+ footerText: {
142
+ fontFamily: 'Sohne-Regular',
143
+ fontSize: 12,
144
+ },
145
+ })
@@ -0,0 +1 @@
1
+ export * from './MenuGroup'
@@ -1,21 +1,18 @@
1
1
  import React from 'react'
2
2
  import {
3
- TouchableOpacity,
4
3
  View,
5
4
  Text,
6
5
  StyleSheet,
7
6
  ViewStyle,
8
7
  TextStyle,
9
8
  } from 'react-native'
10
- import Animated from 'react-native-reanimated'
11
9
  import { Entypo } from '@expo/vector-icons'
12
10
  import { selectionAsync as hapticSelection } from '../../utils/haptics'
13
11
  import { useTheme } from '../../theme'
14
12
  import { s, vs, ms } from '../../utils/scaling'
15
13
  import { renderIcon } from '../../utils/icons'
16
14
  import { RADIUS } from '../../tokens'
17
- import { usePressScale } from '../../utils/usePressScale'
18
- import { SPRINGS, PRESS_SCALE } from '../../utils/animations'
15
+ import { PressableRow } from '../../utils/pressable'
19
16
 
20
17
  export type MenuItemVariant = 'plain' | 'card'
21
18
 
@@ -60,7 +57,7 @@ export interface MenuItemProps {
60
57
  accessibilityLabel?: string
61
58
  }
62
59
 
63
- export function MenuItem({
60
+ function MenuItemBase({
64
61
  label,
65
62
  subtitle,
66
63
  iconName,
@@ -77,12 +74,6 @@ export function MenuItem({
77
74
  accessibilityLabel,
78
75
  }: MenuItemProps) {
79
76
  const { colors } = useTheme()
80
- const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
81
- pressScale: PRESS_SCALE.row,
82
- pressInSpring: SPRINGS.surfacePressIn,
83
- pressOutSpring: SPRINGS.surfacePressOut,
84
- disabled,
85
- })
86
77
 
87
78
  const handlePress = () => {
88
79
  hapticSelection()
@@ -111,15 +102,14 @@ export function MenuItem({
111
102
  const a11yLabel = accessibilityLabel ?? (subtitle ? `${label}. ${subtitle}` : label)
112
103
 
113
104
  return (
114
- <Animated.View style={[animatedStyle, disabled && styles.disabled]} {...hoverHandlers}>
115
- <TouchableOpacity
105
+ <View style={disabled && styles.disabled}>
106
+ <PressableRow
116
107
  style={[styles.container, cardStyle, style]}
117
108
  onPress={handlePress}
118
- onPressIn={onPressIn}
119
- onPressOut={onPressOut}
120
- disabled={disabled}
121
- activeOpacity={1}
122
- touchSoundDisabled={true}
109
+ enabled={!disabled}
110
+ rippleColor="transparent"
111
+ touchSoundDisabled
112
+ activateOnHover
123
113
  accessibilityRole="button"
124
114
  accessibilityLabel={a11yLabel}
125
115
  accessibilityState={{ disabled }}
@@ -158,29 +148,22 @@ export function MenuItem({
158
148
  ) : showChevron ? (
159
149
  <Entypo name="chevron-right" size={18} color={colors.foregroundMuted} />
160
150
  ) : null}
161
- </TouchableOpacity>
151
+ </PressableRow>
162
152
 
163
153
  {showSeparator ? (
164
- <View
165
- style={[
166
- styles.separator,
167
- {
168
- backgroundColor: colors.border,
169
- marginLeft: resolvedIcon ? s(22) + s(12) : 0,
170
- opacity: 0.6,
171
- },
172
- ]}
173
- />
154
+ <View style={[styles.separator, { backgroundColor: colors.separator }]} />
174
155
  ) : null}
175
- </Animated.View>
156
+ </View>
176
157
  )
177
158
  }
178
159
 
160
+ export const MenuItem = React.memo(MenuItemBase)
161
+
179
162
  const styles = StyleSheet.create({
180
163
  container: {
181
164
  flexDirection: 'row',
182
165
  alignItems: 'center',
183
- paddingHorizontal: 0,
166
+ paddingHorizontal: s(16),
184
167
  paddingVertical: vs(16),
185
168
  minHeight: vs(54),
186
169
  gap: s(12),
@@ -196,11 +179,11 @@ const styles = StyleSheet.create({
196
179
  justifyContent: 'center',
197
180
  },
198
181
  label: {
199
- fontFamily: 'Poppins-Medium',
182
+ fontFamily: 'Sohne-Medium',
200
183
  fontSize: ms(15),
201
184
  },
202
185
  subtitle: {
203
- fontFamily: 'Poppins-Regular',
186
+ fontFamily: 'Sohne-Regular',
204
187
  fontSize: ms(12),
205
188
  marginTop: vs(1),
206
189
  },
@@ -3,7 +3,7 @@ import { View, Text, TouchableOpacity, StyleSheet, ViewStyle } from 'react-nativ
3
3
  import { Entypo } from '@expo/vector-icons'
4
4
  import { selectionAsync as hapticSelection } from '../../utils/haptics'
5
5
  import { useTheme } from '../../theme'
6
- import { s, vs, ms, mvs } from '../../utils/scaling'
6
+ import { s, ms, mvs } from '../../utils/scaling'
7
7
 
8
8
  const MONTH_NAMES: Record<string, string[]> = {
9
9
  en: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
@@ -18,9 +18,27 @@ export interface MonthPickerValue {
18
18
  year: number
19
19
  }
20
20
 
21
+ /** Convert a JS `Date` to a `MonthPickerValue` (uses local time). */
22
+ export function dateToMonthPickerValue(date: Date): MonthPickerValue {
23
+ return { month: date.getMonth() + 1, year: date.getFullYear() }
24
+ }
25
+
26
+ /** Convert a `MonthPickerValue` to a `Date` at the first day of that month (local time). */
27
+ export function monthPickerValueToDate(value: MonthPickerValue): Date {
28
+ return new Date(value.year, value.month - 1, 1)
29
+ }
30
+
31
+ // Absolute month index — lets us compare/clamp values with simple arithmetic.
32
+ const toIndex = (v: MonthPickerValue) => v.year * 12 + (v.month - 1)
33
+ const fromIndex = (i: number): MonthPickerValue => ({ year: Math.floor(i / 12), month: (i % 12) + 1 })
34
+
21
35
  export interface MonthPickerProps {
22
36
  value: MonthPickerValue
23
37
  onChange: (value: MonthPickerValue) => void
38
+ /** Earliest selectable month (inclusive). Prev arrow disables at this bound. */
39
+ minValue?: MonthPickerValue
40
+ /** Latest selectable month (inclusive). Next arrow disables at this bound — e.g. cap at the current month. */
41
+ maxValue?: MonthPickerValue
24
42
  /** BCP 47 locale tag. Built-in: 'en' | 'es' | 'pt' | 'fr'. For other locales supply formatLabel. */
25
43
  locale?: string
26
44
  /** Custom label formatter. Takes precedence over locale. */
@@ -28,9 +46,16 @@ export interface MonthPickerProps {
28
46
  style?: ViewStyle
29
47
  }
30
48
 
31
- export function MonthPicker({ value, onChange, locale = 'en', formatLabel, style }: MonthPickerProps) {
49
+ export function MonthPicker({ value, onChange, minValue, maxValue, locale = 'en', formatLabel, style }: MonthPickerProps) {
32
50
  const { colors } = useTheme()
33
51
 
52
+ const index = toIndex(value)
53
+ const minIndex = minValue ? toIndex(minValue) : -Infinity
54
+ const maxIndex = maxValue ? toIndex(maxValue) : Infinity
55
+
56
+ const prevDisabled = index - 1 < minIndex
57
+ const nextDisabled = index + 1 > maxIndex
58
+
34
59
  const getLabel = (): string => {
35
60
  if (formatLabel) return formatLabel(value)
36
61
  const names = MONTH_NAMES[locale] ?? MONTH_NAMES.en
@@ -38,32 +63,28 @@ export function MonthPicker({ value, onChange, locale = 'en', formatLabel, style
38
63
  }
39
64
 
40
65
  const handlePrev = () => {
66
+ if (prevDisabled) return
41
67
  hapticSelection()
42
- if (value.month === 1) {
43
- onChange({ month: 12, year: value.year - 1 })
44
- } else {
45
- onChange({ month: value.month - 1, year: value.year })
46
- }
68
+ onChange(fromIndex(index - 1))
47
69
  }
48
70
 
49
71
  const handleNext = () => {
72
+ if (nextDisabled) return
50
73
  hapticSelection()
51
- if (value.month === 12) {
52
- onChange({ month: 1, year: value.year + 1 })
53
- } else {
54
- onChange({ month: value.month + 1, year: value.year })
55
- }
74
+ onChange(fromIndex(index + 1))
56
75
  }
57
76
 
58
77
  return (
59
78
  <View style={[styles.container, style]} accessibilityRole="adjustable" accessibilityLabel={getLabel()}>
60
79
  <TouchableOpacity
61
- style={styles.arrow}
80
+ style={[styles.arrow, prevDisabled && styles.arrowDisabled]}
62
81
  onPress={handlePrev}
82
+ disabled={prevDisabled}
63
83
  activeOpacity={0.6}
64
84
  touchSoundDisabled={true}
65
85
  accessibilityRole="button"
66
86
  accessibilityLabel="Previous month"
87
+ accessibilityState={{ disabled: prevDisabled }}
67
88
  hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
68
89
  >
69
90
  <Entypo name="chevron-left" size={22} color={colors.foreground} />
@@ -76,12 +97,14 @@ export function MonthPicker({ value, onChange, locale = 'en', formatLabel, style
76
97
  {getLabel()}
77
98
  </Text>
78
99
  <TouchableOpacity
79
- style={styles.arrow}
100
+ style={[styles.arrow, nextDisabled && styles.arrowDisabled]}
80
101
  onPress={handleNext}
102
+ disabled={nextDisabled}
81
103
  activeOpacity={0.6}
82
104
  touchSoundDisabled={true}
83
105
  accessibilityRole="button"
84
106
  accessibilityLabel="Next month"
107
+ accessibilityState={{ disabled: nextDisabled }}
85
108
  hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
86
109
  >
87
110
  <Entypo name="chevron-right" size={22} color={colors.foreground} />
@@ -102,8 +125,11 @@ const styles = StyleSheet.create({
102
125
  alignItems: 'center',
103
126
  justifyContent: 'center',
104
127
  },
128
+ arrowDisabled: {
129
+ opacity: 0.3,
130
+ },
105
131
  label: {
106
- fontFamily: 'Poppins-Medium',
132
+ fontFamily: 'Sohne-Medium',
107
133
  fontSize: ms(17),
108
134
  lineHeight: mvs(24),
109
135
  textAlign: 'center',