jfs-components 0.1.0 → 0.1.2

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 (331) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/lib/commonjs/components/AreaLineChart/AreaLineChart.js +1 -1
  3. package/lib/commonjs/components/Balance/Balance.js +17 -12
  4. package/lib/commonjs/components/Card/Card.js +2 -1
  5. package/lib/commonjs/components/CardFeedback/CardFeedback.js +2 -1
  6. package/lib/commonjs/components/Checkbox/Checkbox.js +2 -1
  7. package/lib/commonjs/components/Drawer/Drawer.js +13 -4
  8. package/lib/commonjs/components/DropdownInput/DropdownInput.js +1 -1
  9. package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +62 -2
  10. package/lib/commonjs/components/Image/Image.js +11 -5
  11. package/lib/commonjs/components/LottiePlayer/loadNativeLottieView.js +8 -13
  12. package/lib/commonjs/components/Overlay/Overlay.js +92 -0
  13. package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +2 -1
  14. package/lib/commonjs/components/TextInput/TextInput.js +2 -1
  15. package/lib/commonjs/components/docs/modeControls.js +116 -0
  16. package/lib/commonjs/components/index.js +7 -0
  17. package/lib/commonjs/design-tokens/JFSThemeProvider.js +1 -1
  18. package/lib/commonjs/design-tokens/figma-modes.generated.js +391 -0
  19. package/lib/commonjs/design-tokens/index.js +11 -0
  20. package/lib/commonjs/icons/registry.js +1 -1
  21. package/lib/module/components/Accordion/Accordion.js +1 -2
  22. package/lib/module/components/AreaLineChart/AreaLineChart.js +1 -1
  23. package/lib/module/components/Balance/Balance.js +18 -13
  24. package/lib/module/components/Card/Card.js +1 -2
  25. package/lib/module/components/CardFeedback/CardFeedback.js +1 -2
  26. package/lib/module/components/Checkbox/Checkbox.js +1 -2
  27. package/lib/module/components/Drawer/Drawer.js +12 -4
  28. package/lib/module/components/DropdownInput/DropdownInput.js +1 -1
  29. package/lib/module/components/FullscreenModal/FullscreenModal.js +64 -5
  30. package/lib/module/components/Image/Image.js +11 -5
  31. package/lib/module/components/InstitutionBadge/InstitutionBadge.js +1 -2
  32. package/lib/module/components/LottiePlayer/loadNativeLottieView.js +8 -13
  33. package/lib/module/components/MoneyValue/MoneyValue.js +1 -2
  34. package/lib/module/components/OTP/OTP.js +1 -2
  35. package/lib/module/components/Overlay/Overlay.js +87 -0
  36. package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +1 -2
  37. package/lib/module/components/PoweredByLabel/PoweredByLabel.js +1 -2
  38. package/lib/module/components/RechargeCard/RechargeCard.js +1 -2
  39. package/lib/module/components/Section/Section.js +1 -2
  40. package/lib/module/components/TextInput/TextInput.js +1 -2
  41. package/lib/module/components/UpiHandle/UpiHandle.js +1 -2
  42. package/lib/module/components/docs/modeControls.js +111 -0
  43. package/lib/module/components/index.js +1 -0
  44. package/lib/module/design-tokens/JFSThemeProvider.js +1 -1
  45. package/lib/module/design-tokens/figma-modes.generated.js +387 -0
  46. package/lib/module/design-tokens/index.js +2 -1
  47. package/lib/module/icons/registry.js +1 -1
  48. package/lib/module/utils/react-utils.js +0 -1
  49. package/lib/typescript/scripts/extract-component-tokens.d.ts +1 -1
  50. package/lib/typescript/scripts/generate-mode-types.d.ts +2 -0
  51. package/lib/typescript/scripts/retype-modes.d.cts +2 -0
  52. package/lib/typescript/src/components/Accordion/Accordion.d.ts +2 -1
  53. package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +2 -1
  54. package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +2 -1
  55. package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +2 -1
  56. package/lib/typescript/src/components/ActionTile/ActionTile.d.ts +2 -1
  57. package/lib/typescript/src/components/AllocationComparisonChart/AllocationComparisonChart.d.ts +2 -1
  58. package/lib/typescript/src/components/AmountInput/AmountInput.d.ts +2 -1
  59. package/lib/typescript/src/components/AppBar/AppBar.d.ts +2 -1
  60. package/lib/typescript/src/components/AreaLineChart/AreaLineChart.d.ts +3 -2
  61. package/lib/typescript/src/components/Attached/Attached.d.ts +2 -1
  62. package/lib/typescript/src/components/Avatar/Avatar.d.ts +2 -1
  63. package/lib/typescript/src/components/AvatarGroup/AvatarGroup.d.ts +2 -1
  64. package/lib/typescript/src/components/Badge/Badge.d.ts +2 -1
  65. package/lib/typescript/src/components/Balance/Balance.d.ts +2 -1
  66. package/lib/typescript/src/components/BottomNav/BottomNav.d.ts +2 -1
  67. package/lib/typescript/src/components/BottomNavItem/BottomNavItem.d.ts +2 -1
  68. package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +2 -1
  69. package/lib/typescript/src/components/BubbleChart/BubbleChart.d.ts +2 -1
  70. package/lib/typescript/src/components/Button/Button.d.ts +2 -1
  71. package/lib/typescript/src/components/ButtonGroup/ButtonGroup.d.ts +2 -1
  72. package/lib/typescript/src/components/Card/Card.d.ts +3 -2
  73. package/lib/typescript/src/components/CardAdvisory/CardAdvisory.d.ts +2 -1
  74. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +2 -1
  75. package/lib/typescript/src/components/CardCTA/CardCTA.d.ts +2 -1
  76. package/lib/typescript/src/components/CardFeedback/CardFeedback.d.ts +7 -6
  77. package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +2 -1
  78. package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +2 -1
  79. package/lib/typescript/src/components/CardProviderInfo/CardProviderInfo.d.ts +2 -1
  80. package/lib/typescript/src/components/Carousel/Carousel.d.ts +4 -3
  81. package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +2 -1
  82. package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +2 -1
  83. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +2 -1
  84. package/lib/typescript/src/components/ChipGroup/ChipGroup.d.ts +2 -1
  85. package/lib/typescript/src/components/ChipSelect/ChipSelect.d.ts +2 -1
  86. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +2 -1
  87. package/lib/typescript/src/components/CircularProgressBarDoted/CircularProgressBarDoted.d.ts +2 -1
  88. package/lib/typescript/src/components/CircularRating/CircularRating.d.ts +2 -1
  89. package/lib/typescript/src/components/ClusterBubble/ClusterBubble.d.ts +2 -1
  90. package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +3 -2
  91. package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +2 -1
  92. package/lib/typescript/src/components/DebitCard/DebitCard.d.ts +2 -1
  93. package/lib/typescript/src/components/Disclaimer/Disclaimer.d.ts +2 -1
  94. package/lib/typescript/src/components/Divider/Divider.d.ts +2 -1
  95. package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +4 -3
  96. package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +3 -2
  97. package/lib/typescript/src/components/Drawer/Drawer.d.ts +15 -1
  98. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +3 -2
  99. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +2 -1
  100. package/lib/typescript/src/components/EmptyState/EmptyState.d.ts +2 -1
  101. package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +2 -1
  102. package/lib/typescript/src/components/FilterBar/FilterBar.d.ts +3 -2
  103. package/lib/typescript/src/components/Form/Form.d.ts +2 -1
  104. package/lib/typescript/src/components/FormField/FormField.d.ts +2 -1
  105. package/lib/typescript/src/components/FullscreenModal/FullscreenModal.d.ts +2 -1
  106. package/lib/typescript/src/components/Gauge/Gauge.d.ts +2 -1
  107. package/lib/typescript/src/components/HStack/HStack.d.ts +2 -1
  108. package/lib/typescript/src/components/HoldingsCard/HoldingsCard.d.ts +2 -1
  109. package/lib/typescript/src/components/Icon/Icon.d.ts +2 -1
  110. package/lib/typescript/src/components/IconButton/IconButton.d.ts +2 -1
  111. package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +2 -1
  112. package/lib/typescript/src/components/Image/Image.d.ts +17 -1
  113. package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +2 -1
  114. package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +2 -1
  115. package/lib/typescript/src/components/LazyList/LazyList.d.ts +2 -1
  116. package/lib/typescript/src/components/LinearMeter/LinearMeter.d.ts +3 -2
  117. package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +2 -1
  118. package/lib/typescript/src/components/ListGroup/ListGroup.d.ts +2 -1
  119. package/lib/typescript/src/components/ListItem/ListItem.d.ts +2 -1
  120. package/lib/typescript/src/components/LottieIntroBlock/LottieIntroBlock.d.ts +2 -1
  121. package/lib/typescript/src/components/LottiePlayer/LottiePlayer.d.ts +2 -1
  122. package/lib/typescript/src/components/LottiePlayer/LottiePlayer.web.d.ts +2 -1
  123. package/lib/typescript/src/components/MediaCard/MediaCard.d.ts +6 -5
  124. package/lib/typescript/src/components/MerchantProfile/MerchantProfile.d.ts +2 -1
  125. package/lib/typescript/src/components/MessageField/MessageField.d.ts +2 -1
  126. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +2 -1
  127. package/lib/typescript/src/components/MoneyValue/MoneyValue.d.ts +2 -1
  128. package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +4 -3
  129. package/lib/typescript/src/components/NavArrow/NavArrow.d.ts +2 -1
  130. package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +2 -1
  131. package/lib/typescript/src/components/Nudge/Nudge.d.ts +2 -1
  132. package/lib/typescript/src/components/Numpad/Numpad.d.ts +2 -1
  133. package/lib/typescript/src/components/OTP/OTP.d.ts +3 -2
  134. package/lib/typescript/src/components/Overlay/Overlay.d.ts +52 -0
  135. package/lib/typescript/src/components/PageHero/PageHero.d.ts +2 -1
  136. package/lib/typescript/src/components/PaymentFeedback/PaymentFeedback.d.ts +2 -1
  137. package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +2 -1
  138. package/lib/typescript/src/components/Popup/Popup.d.ts +2 -1
  139. package/lib/typescript/src/components/PortfolioHero/PortfolioHero.d.ts +2 -1
  140. package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +2 -1
  141. package/lib/typescript/src/components/ProductLabel/ProductLabel.d.ts +2 -1
  142. package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +2 -1
  143. package/lib/typescript/src/components/ProgressBadge/ProgressBadge.d.ts +2 -1
  144. package/lib/typescript/src/components/Radio/Radio.d.ts +2 -1
  145. package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +3 -2
  146. package/lib/typescript/src/components/RechargeCard/RechargeCard.d.ts +2 -1
  147. package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +2 -1
  148. package/lib/typescript/src/components/Screen/Screen.d.ts +2 -1
  149. package/lib/typescript/src/components/Section/Section.d.ts +3 -2
  150. package/lib/typescript/src/components/SegmentedControl/SegmentedControl.d.ts +2 -1
  151. package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +4 -3
  152. package/lib/typescript/src/components/Slot/Slot.d.ts +2 -1
  153. package/lib/typescript/src/components/Spinner/Spinner.d.ts +2 -1
  154. package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +2 -1
  155. package/lib/typescript/src/components/StatItem/StatItem.d.ts +2 -1
  156. package/lib/typescript/src/components/StatusHero/StatusHero.d.ts +2 -1
  157. package/lib/typescript/src/components/Stepper/Step.d.ts +2 -1
  158. package/lib/typescript/src/components/Stepper/StepLabel.d.ts +2 -1
  159. package/lib/typescript/src/components/Stepper/Stepper.d.ts +2 -1
  160. package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +2 -1
  161. package/lib/typescript/src/components/SuggestiveSearch/SuggestiveSearch.d.ts +2 -1
  162. package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +2 -1
  163. package/lib/typescript/src/components/SupportText/SupportText.d.ts +2 -1
  164. package/lib/typescript/src/components/SupportText/SupportTextIcon.d.ts +2 -1
  165. package/lib/typescript/src/components/SwappableAmount/SwappableAmount.d.ts +2 -1
  166. package/lib/typescript/src/components/Tabs/TabItem.d.ts +2 -1
  167. package/lib/typescript/src/components/Tabs/Tabs.d.ts +2 -1
  168. package/lib/typescript/src/components/TestimonialsCard/TestimonialsCard.d.ts +2 -1
  169. package/lib/typescript/src/components/Text/Text.d.ts +2 -1
  170. package/lib/typescript/src/components/TextInput/TextInput.d.ts +3 -2
  171. package/lib/typescript/src/components/ThreadHero/ThreadHero.d.ts +2 -1
  172. package/lib/typescript/src/components/Title/Title.d.ts +2 -1
  173. package/lib/typescript/src/components/Toast/Toast.d.ts +2 -1
  174. package/lib/typescript/src/components/Toast/ToastProvider.d.ts +2 -1
  175. package/lib/typescript/src/components/Toast/useToast.d.ts +3 -2
  176. package/lib/typescript/src/components/Toggle/Toggle.d.ts +2 -1
  177. package/lib/typescript/src/components/Tooltip/Tooltip.d.ts +2 -1
  178. package/lib/typescript/src/components/TransactionBubble/TransactionBubble.d.ts +2 -1
  179. package/lib/typescript/src/components/TransactionDetails/TransactionDetails.d.ts +3 -2
  180. package/lib/typescript/src/components/TransactionStatus/TransactionStatus.d.ts +2 -1
  181. package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +2 -1
  182. package/lib/typescript/src/components/VStack/VStack.d.ts +2 -1
  183. package/lib/typescript/src/components/docs/modeControls.d.ts +28 -0
  184. package/lib/typescript/src/components/index.d.ts +1 -0
  185. package/lib/typescript/src/design-tokens/JFSThemeProvider.d.ts +4 -3
  186. package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +264 -0
  187. package/lib/typescript/src/design-tokens/index.d.ts +1 -0
  188. package/lib/typescript/src/icons/registry.d.ts +1 -1
  189. package/lib/typescript/src/skeleton/Skeleton.d.ts +2 -1
  190. package/lib/typescript/src/utils/react-utils.d.ts +2 -1
  191. package/package.json +3 -2
  192. package/src/components/Accordion/Accordion.tsx +2 -1
  193. package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +2 -1
  194. package/src/components/AccountCard/AccountCard.tsx +2 -1
  195. package/src/components/ActionFooter/ActionFooter.tsx +2 -1
  196. package/src/components/ActionTile/ActionTile.tsx +2 -1
  197. package/src/components/AllocationComparisonChart/AllocationComparisonChart.tsx +2 -1
  198. package/src/components/AmountInput/AmountInput.tsx +2 -1
  199. package/src/components/AppBar/AppBar.tsx +2 -1
  200. package/src/components/AreaLineChart/AreaLineChart.tsx +8 -7
  201. package/src/components/Attached/Attached.tsx +2 -1
  202. package/src/components/Avatar/Avatar.tsx +3 -2
  203. package/src/components/AvatarGroup/AvatarGroup.tsx +2 -1
  204. package/src/components/Badge/Badge.tsx +2 -1
  205. package/src/components/Balance/Balance.tsx +18 -12
  206. package/src/components/BottomNav/BottomNav.tsx +2 -1
  207. package/src/components/BottomNavItem/BottomNavItem.tsx +3 -2
  208. package/src/components/BrandChip/BrandChip.tsx +3 -2
  209. package/src/components/BubbleChart/BubbleChart.tsx +2 -1
  210. package/src/components/Button/Button.tsx +3 -2
  211. package/src/components/ButtonGroup/ButtonGroup.tsx +2 -1
  212. package/src/components/Card/Card.tsx +4 -3
  213. package/src/components/CardAdvisory/CardAdvisory.tsx +3 -2
  214. package/src/components/CardBankAccount/CardBankAccount.tsx +2 -1
  215. package/src/components/CardCTA/CardCTA.tsx +3 -2
  216. package/src/components/CardFeedback/CardFeedback.tsx +11 -10
  217. package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +3 -2
  218. package/src/components/CardInsight/CardInsight.tsx +2 -1
  219. package/src/components/CardProviderInfo/CardProviderInfo.tsx +2 -1
  220. package/src/components/Carousel/Carousel.tsx +5 -4
  221. package/src/components/Checkbox/Checkbox.tsx +2 -1
  222. package/src/components/CheckboxGroup/CheckboxGroup.tsx +2 -1
  223. package/src/components/CheckboxItem/CheckboxItem.tsx +2 -1
  224. package/src/components/ChipGroup/ChipGroup.tsx +2 -1
  225. package/src/components/ChipSelect/ChipSelect.tsx +2 -1
  226. package/src/components/CircularProgressBar/CircularProgressBar.tsx +2 -1
  227. package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +2 -1
  228. package/src/components/CircularRating/CircularRating.tsx +3 -2
  229. package/src/components/ClusterBubble/ClusterBubble.tsx +2 -1
  230. package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +3 -2
  231. package/src/components/CoverageRing/CoverageRing.tsx +2 -1
  232. package/src/components/DebitCard/DebitCard.tsx +2 -1
  233. package/src/components/Disclaimer/Disclaimer.tsx +2 -1
  234. package/src/components/Divider/Divider.tsx +2 -1
  235. package/src/components/DonutChart/DonutChart.tsx +6 -5
  236. package/src/components/DonutChartSummary/DonutChartSummary.tsx +3 -2
  237. package/src/components/Drawer/Drawer.tsx +21 -1
  238. package/src/components/Dropdown/Dropdown.tsx +4 -3
  239. package/src/components/DropdownInput/DropdownInput.tsx +5 -4
  240. package/src/components/EmptyState/EmptyState.tsx +2 -1
  241. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +2 -1
  242. package/src/components/FilterBar/FilterBar.tsx +3 -2
  243. package/src/components/Form/Form.tsx +2 -1
  244. package/src/components/FormField/FormField.tsx +3 -2
  245. package/src/components/FullscreenModal/FullscreenModal.tsx +68 -10
  246. package/src/components/Gauge/Gauge.tsx +2 -1
  247. package/src/components/HStack/HStack.tsx +2 -1
  248. package/src/components/HoldingsCard/HoldingsCard.tsx +2 -1
  249. package/src/components/Icon/Icon.tsx +3 -2
  250. package/src/components/IconButton/IconButton.tsx +3 -2
  251. package/src/components/IconCapsule/IconCapsule.tsx +3 -2
  252. package/src/components/Image/Image.tsx +29 -5
  253. package/src/components/InputSearch/InputSearch.tsx +3 -2
  254. package/src/components/InstitutionBadge/InstitutionBadge.tsx +3 -2
  255. package/src/components/LazyList/LazyList.tsx +2 -1
  256. package/src/components/LinearMeter/LinearMeter.tsx +3 -2
  257. package/src/components/LinearProgress/LinearProgress.tsx +2 -1
  258. package/src/components/ListGroup/ListGroup.tsx +2 -1
  259. package/src/components/ListItem/ListItem.tsx +3 -2
  260. package/src/components/LottieIntroBlock/LottieIntroBlock.tsx +2 -1
  261. package/src/components/LottiePlayer/LottiePlayer.tsx +3 -2
  262. package/src/components/LottiePlayer/LottiePlayer.web.tsx +3 -2
  263. package/src/components/LottiePlayer/loadNativeLottieView.tsx +9 -13
  264. package/src/components/MediaCard/MediaCard.tsx +7 -6
  265. package/src/components/MerchantProfile/MerchantProfile.tsx +2 -1
  266. package/src/components/MessageField/MessageField.tsx +3 -2
  267. package/src/components/MetricLegendItem/MetricLegendItem.tsx +2 -1
  268. package/src/components/MoneyValue/MoneyValue.tsx +2 -1
  269. package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +5 -4
  270. package/src/components/NavArrow/NavArrow.tsx +3 -2
  271. package/src/components/NoteInput/NoteInput.tsx +2 -1
  272. package/src/components/Nudge/Nudge.tsx +3 -2
  273. package/src/components/Numpad/Numpad.tsx +2 -1
  274. package/src/components/OTP/OTP.tsx +3 -2
  275. package/src/components/Overlay/Overlay.tsx +114 -0
  276. package/src/components/PageHero/PageHero.tsx +2 -1
  277. package/src/components/PaymentFeedback/PaymentFeedback.tsx +2 -1
  278. package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +2 -1
  279. package/src/components/Popup/Popup.tsx +2 -1
  280. package/src/components/PortfolioHero/PortfolioHero.tsx +2 -1
  281. package/src/components/PoweredByLabel/PoweredByLabel.tsx +2 -1
  282. package/src/components/ProductLabel/ProductLabel.tsx +2 -1
  283. package/src/components/ProductOverview/ProductOverview.tsx +2 -1
  284. package/src/components/ProgressBadge/ProgressBadge.tsx +2 -1
  285. package/src/components/Radio/Radio.tsx +2 -1
  286. package/src/components/RangeTrack/RangeTrack.tsx +3 -2
  287. package/src/components/RechargeCard/RechargeCard.tsx +2 -1
  288. package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +2 -1
  289. package/src/components/Screen/Screen.tsx +2 -1
  290. package/src/components/Section/Section.tsx +6 -5
  291. package/src/components/SegmentedControl/SegmentedControl.tsx +3 -2
  292. package/src/components/SegmentedTrack/SegmentedTrack.tsx +5 -4
  293. package/src/components/Slot/Slot.tsx +2 -1
  294. package/src/components/Spinner/Spinner.tsx +2 -1
  295. package/src/components/StatGroup/StatGroup.tsx +3 -2
  296. package/src/components/StatItem/StatItem.tsx +2 -1
  297. package/src/components/StatusHero/StatusHero.tsx +2 -1
  298. package/src/components/Stepper/Step.tsx +2 -1
  299. package/src/components/Stepper/StepLabel.tsx +2 -1
  300. package/src/components/Stepper/Stepper.tsx +2 -1
  301. package/src/components/StrengthIndicator/StrengthIndicator.tsx +2 -1
  302. package/src/components/SuggestiveSearch/SuggestiveSearch.tsx +4 -3
  303. package/src/components/SummaryTile/SummaryTile.tsx +2 -1
  304. package/src/components/SupportText/SupportText.tsx +2 -1
  305. package/src/components/SupportText/SupportTextIcon.tsx +2 -1
  306. package/src/components/SwappableAmount/SwappableAmount.tsx +2 -1
  307. package/src/components/Tabs/TabItem.tsx +2 -1
  308. package/src/components/Tabs/Tabs.tsx +2 -1
  309. package/src/components/TestimonialsCard/TestimonialsCard.tsx +2 -1
  310. package/src/components/Text/Text.tsx +2 -1
  311. package/src/components/TextInput/TextInput.tsx +3 -2
  312. package/src/components/ThreadHero/ThreadHero.tsx +2 -1
  313. package/src/components/Title/Title.tsx +2 -1
  314. package/src/components/Toast/Toast.tsx +2 -1
  315. package/src/components/Toast/ToastProvider.tsx +2 -1
  316. package/src/components/Toast/useToast.ts +3 -2
  317. package/src/components/Toggle/Toggle.tsx +2 -1
  318. package/src/components/Tooltip/Tooltip.tsx +3 -2
  319. package/src/components/TransactionBubble/TransactionBubble.tsx +2 -1
  320. package/src/components/TransactionDetails/TransactionDetails.tsx +3 -2
  321. package/src/components/TransactionStatus/TransactionStatus.tsx +3 -2
  322. package/src/components/UpiHandle/UpiHandle.tsx +3 -2
  323. package/src/components/VStack/VStack.tsx +2 -1
  324. package/src/components/docs/modeControls.tsx +122 -0
  325. package/src/components/index.ts +1 -0
  326. package/src/design-tokens/JFSThemeProvider.tsx +4 -3
  327. package/src/design-tokens/figma-modes.generated.ts +396 -0
  328. package/src/design-tokens/index.ts +1 -0
  329. package/src/icons/registry.ts +1 -1
  330. package/src/skeleton/Skeleton.tsx +2 -1
  331. package/src/utils/react-utils.ts +3 -2
@@ -12,6 +12,7 @@ import {
12
12
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
13
13
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
14
14
  import { EMPTY_MODES } from '../../utils/react-utils'
15
+ import type { Modes } from '../../design-tokens'
15
16
 
16
17
  /** Where the value/label text sits relative to the circle. */
17
18
  export type ClusterBubbleLabelPlacement = 'inside' | 'outside' | 'auto'
@@ -72,7 +73,7 @@ export type ClusterBubbleProps = {
72
73
  /** Style override for the outer container. */
73
74
  style?: StyleProp<ViewStyle>
74
75
  /** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
75
- modes?: Record<string, any>
76
+ modes?: Modes
76
77
  /** Accessibility label. Defaults to a `value + label` composite. */
77
78
  accessibilityLabel?: string
78
79
  }
@@ -12,6 +12,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
12
12
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
13
13
  import { EMPTY_MODES } from '../../utils/react-utils'
14
14
  import MetricLegendItem from '../MetricLegendItem/MetricLegendItem'
15
+ import type { Modes } from '../../design-tokens'
15
16
 
16
17
  /**
17
18
  * One entry in the {@link CoverageBarComparisonProps.bars} array.
@@ -54,7 +55,7 @@ export type CoverageBarComparisonItem = {
54
55
  * Per-bar design token mode overrides. Merged on top of the parent `modes`
55
56
  * and the per-index `Emphasis / DataViz` defaults injected by the parent.
56
57
  */
57
- modes?: Record<string, any>
58
+ modes?: Modes
58
59
  /** Per-bar accessibility label. */
59
60
  accessibilityLabel?: string
60
61
  }
@@ -85,7 +86,7 @@ export type CoverageBarComparisonProps = {
85
86
  */
86
87
  legendGap?: number
87
88
  /** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
88
- modes?: Record<string, any>
89
+ modes?: Modes
89
90
  /** Container style override. */
90
91
  style?: StyleProp<ViewStyle>
91
92
  /** Style applied to the chart row (the bars container). */
@@ -10,6 +10,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
10
10
  import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
11
11
  import Button, { type ButtonProps } from '../Button/Button'
12
12
  import CircularProgressBar from '../CircularProgressBar/CircularProgressBar'
13
+ import type { Modes } from '../../design-tokens'
13
14
 
14
15
  type CoverageRingBaseProps = Omit<
15
16
  React.ComponentProps<typeof View>,
@@ -73,7 +74,7 @@ export type CoverageRingProps = CoverageRingBaseProps & {
73
74
  */
74
75
  children?: React.ReactNode
75
76
  /** Design token modes forwarded to token lookups and slot children. */
76
- modes?: Record<string, any>
77
+ modes?: Modes
77
78
  /** Container style override. */
78
79
  style?: StyleProp<ViewStyle>
79
80
  /** Override the support-text style inside the ring. */
@@ -3,6 +3,7 @@ import { View, Text, Image, type ViewStyle, type TextStyle, type ImageStyle, typ
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
5
  import { cloneChildrenWithModes, EMPTY_MODES } from '../../utils/react-utils'
6
+ import type { Modes } from '../../design-tokens'
6
7
 
7
8
  const defaultCardArt = require('./cf64a67d5075caa8924d20b4e4e650d47b3ee08b.png')
8
9
 
@@ -24,7 +25,7 @@ export type DebitCardProps = {
24
25
  /** Slot: custom content for the provider logo area (right side of header, after cardType text) */
25
26
  providerLogoSlot?: React.ReactNode;
26
27
  /** Mode configuration for design token resolution */
27
- modes?: Record<string, any>;
28
+ modes?: Modes;
28
29
  /** Container style overrides */
29
30
  style?: StyleProp<ViewStyle>;
30
31
  };
@@ -3,10 +3,11 @@ import { View, Text, type StyleProp, type ViewStyle, type TextStyle } from 'reac
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
5
  import { EMPTY_MODES } from '../../utils/react-utils'
6
+ import type { Modes } from '../../design-tokens'
6
7
 
7
8
  type DisclaimerProps = {
8
9
  disclaimer?: string;
9
- modes?: Record<string, any>;
10
+ modes?: Modes;
10
11
  style?: StyleProp<ViewStyle>;
11
12
  textStyle?: StyleProp<TextStyle>;
12
13
  accessibilityLabel?: string;
@@ -6,6 +6,7 @@ import {
6
6
  } from 'react-native'
7
7
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
8
8
  import { EMPTY_MODES } from '../../utils/react-utils'
9
+ import type { Modes } from '../../design-tokens'
9
10
 
10
11
  export type DividerDirection = 'horizontal' | 'vertical'
11
12
 
@@ -19,7 +20,7 @@ export type DividerProps = {
19
20
  /**
20
21
  * Mode configuration passed to the token resolver.
21
22
  */
22
- modes?: Record<string, any>
23
+ modes?: Modes
23
24
  /**
24
25
  * Optional style overrides for the divider
25
26
  */
@@ -11,6 +11,7 @@ import Svg, { Circle } from 'react-native-svg'
11
11
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
12
12
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
13
13
  import { EMPTY_MODES, flattenChildren } from '../../utils/react-utils'
14
+ import type { Modes } from '../../design-tokens'
14
15
 
15
16
  /**
16
17
  * Per-segment data definition for the data-driven `segments` prop.
@@ -32,7 +33,7 @@ export type DonutChartSegmentData = {
32
33
  * Per-segment design token mode overrides. Merged on top of parent
33
34
  * `modes` and the per-index `Appearance / DataViz` defaults.
34
35
  */
35
- modes?: Record<string, any>
36
+ modes?: Modes
36
37
  /** Per-segment accessibility label. */
37
38
  accessibilityLabel?: string
38
39
  }
@@ -73,7 +74,7 @@ export type DonutChartProps = {
73
74
  */
74
75
  gap?: number
75
76
  /** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
76
- modes?: Record<string, any>
77
+ modes?: Modes
77
78
  /** Override container styles. */
78
79
  style?: StyleProp<ViewStyle>
79
80
  /** Override default value text styles. */
@@ -142,7 +143,7 @@ function defaultAppearanceFor(index: number) {
142
143
  */
143
144
  function resolveSegmentColor(
144
145
  color: string | undefined,
145
- modes: Record<string, any>
146
+ modes: Modes
146
147
  ): string {
147
148
  if (color) return color
148
149
  return ((getVariableByName('dataViz/bg', modes) as string | null) ?? '#5d00b5')
@@ -176,7 +177,7 @@ type DonutChartSegmentProps = {
176
177
  * Design token modes for the segment. Merged with parent `modes` and
177
178
  * the per-index `Appearance / DataViz` defaults.
178
179
  */
179
- modes?: Record<string, any>
180
+ modes?: Modes
180
181
  /** Per-segment accessibility label. */
181
182
  accessibilityLabel?: string
182
183
  }
@@ -446,7 +447,7 @@ function buildArcs({
446
447
  totalValue: number
447
448
  circumference: number
448
449
  gapLength: number
449
- modes: Record<string, any>
450
+ modes: Modes
450
451
  }): ArcDescriptor[] {
451
452
  const arcs: ArcDescriptor[] = []
452
453
  const halfGap = gapLength / 2
@@ -5,6 +5,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
5
  import { EMPTY_MODES } from '../../utils/react-utils'
6
6
  import DonutChart, { type DonutChartSegmentData } from '../DonutChart/DonutChart'
7
7
  import MetricLegendItem from '../MetricLegendItem/MetricLegendItem'
8
+ import type { Modes } from '../../design-tokens'
8
9
 
9
10
  /**
10
11
  * One row of the `DonutChartSummary`. Each item drives BOTH a donut
@@ -42,7 +43,7 @@ export type DonutChartSummaryItem = {
42
43
  * (`Senary`, `Primary`, `Secondary`, `Tertiary`, `Quaternary`,
43
44
  * `Quinary`, then cycles).
44
45
  */
45
- modes?: Record<string, any>
46
+ modes?: Modes
46
47
  /** Accessibility label for the segment + legend row pairing. */
47
48
  accessibilityLabel?: string
48
49
  }
@@ -80,7 +81,7 @@ export type DonutChartSummaryProps = {
80
81
  */
81
82
  donutGap?: number
82
83
  /** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
83
- modes?: Record<string, any>
84
+ modes?: Modes
84
85
  /** Override outer container styles. */
85
86
  style?: StyleProp<ViewStyle>
86
87
  /** Override the legend container styles. */
@@ -15,6 +15,8 @@ import Animated, {
15
15
  } from 'react-native-reanimated'
16
16
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
17
17
  import { EMPTY_MODES } from '../../utils/react-utils'
18
+ import type { Modes } from '../../design-tokens'
19
+ import Overlay from '../Overlay/Overlay'
18
20
 
19
21
 
20
22
  const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView)
@@ -54,7 +56,7 @@ function rubberBand(value: number, min: number, max: number, friction: number =
54
56
 
55
57
  export type DrawerProps = {
56
58
 
57
- modes?: Record<string, any>
59
+ modes?: Modes
58
60
  style?: import('react-native').StyleProp<import('react-native').ViewStyle>
59
61
  title?: string
60
62
  /**
@@ -95,6 +97,19 @@ export type DrawerProps = {
95
97
  * expanded), so parent components can react programmatically.
96
98
  */
97
99
  onStateChange?: (state: 'collapsed' | 'expanded') => void
100
+ /**
101
+ * When `true`, renders a full-screen semi-transparent {@link Overlay} scrim
102
+ * behind the drawer sheet (dimming everything else on screen). Defaults to
103
+ * `false`, in which case nothing is rendered behind the sheet and behaviour
104
+ * is unchanged.
105
+ */
106
+ showOverlay?: boolean
107
+ /**
108
+ * Called when the overlay scrim (the area outside the sheet) is pressed.
109
+ * Only relevant when `showOverlay` is `true` — typically used to collapse
110
+ * or dismiss the drawer.
111
+ */
112
+ onOverlayPress?: () => void
98
113
  }
99
114
 
100
115
  /**
@@ -132,6 +147,8 @@ function DrawerInner({
132
147
  showsVerticalScrollIndicator = false,
133
148
  bottomInset = 80,
134
149
  onStateChange,
150
+ showOverlay = false,
151
+ onOverlayPress,
135
152
  }: DrawerProps, ref: React.Ref<DrawerHandle>) {
136
153
  const { height: screenHeight } = useWindowDimensions()
137
154
 
@@ -439,6 +456,9 @@ function DrawerInner({
439
456
  // GestureHandlerRootView must wrap the app root; this overlay only needs to
440
457
  // let touches fall through where the sheet isn't.
441
458
  <View style={[styles.host, style]} pointerEvents="box-none">
459
+ {/* Full-screen scrim rendered beneath the sheet. Opt-in via `showOverlay`;
460
+ when disabled nothing renders here and touches still fall through. */}
461
+ {showOverlay ? <Overlay modes={modes} {...(onOverlayPress ? { onPress: onOverlayPress } : {})} /> : null}
442
462
  <GestureDetector gesture={gesture}>
443
463
  <Animated.View
444
464
  style={[
@@ -15,6 +15,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
15
15
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
16
16
  import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
17
17
  import Icon from '../../icons/Icon'
18
+ import type { Modes } from '../../design-tokens'
18
19
 
19
20
  const IS_WEB = Platform.OS === 'web'
20
21
 
@@ -47,7 +48,7 @@ export type DropdownItemProps = {
47
48
  /** Optional custom child content (overrides `label`). */
48
49
  children?: React.ReactNode
49
50
  /** Modes for design token resolution. */
50
- modes?: Record<string, any>
51
+ modes?: Modes
51
52
  /** Style overrides for the item container. */
52
53
  style?: StyleProp<ViewStyle>
53
54
  /** Style overrides for the item label text. */
@@ -58,7 +59,7 @@ export type DropdownItemProps = {
58
59
  accessibilityHint?: string
59
60
  }
60
61
 
61
- function useDropdownItemTokens(modes: Record<string, any>) {
62
+ function useDropdownItemTokens(modes: Modes) {
62
63
  return useMemo(() => {
63
64
  // The `dropdownItem/background` token aliases through the
64
65
  // `Dropdown Item State` collection (Idle | Selected), so we resolve
@@ -250,7 +251,7 @@ export type DropdownProps = {
250
251
  */
251
252
  maxHeight?: number
252
253
  /** Modes for design token resolution. */
253
- modes?: Record<string, any>
254
+ modes?: Modes
254
255
  /** Style overrides for the popup container. */
255
256
  style?: StyleProp<ViewStyle>
256
257
  /** Accessibility label for the menu surface. */
@@ -27,6 +27,7 @@ import Icon from '../../icons/Icon'
27
27
  import SupportText from '../SupportText/SupportText'
28
28
  import type { SupportTextStatus } from '../SupportText/SupportTextIcon'
29
29
  import Dropdown, { DropdownItem, type DropdownItemProps } from '../Dropdown/Dropdown'
30
+ import type { Modes } from '../../design-tokens'
30
31
 
31
32
  const IS_WEB = Platform.OS === 'web'
32
33
 
@@ -131,7 +132,7 @@ export type DropdownInputProps = {
131
132
  /** Whether tapping the backdrop closes the menu. */
132
133
  closeOnBackdropPress?: boolean
133
134
  /** Modes for design token resolution. */
134
- modes?: Record<string, any>
135
+ modes?: Modes
135
136
  /** Style overrides for the outermost wrapper. */
136
137
  style?: StyleProp<ViewStyle>
137
138
  /** Style overrides for the input row. */
@@ -152,7 +153,7 @@ export type DropdownInputProps = {
152
153
  // Token resolution
153
154
  // ---------------------------------------------------------------------------
154
155
 
155
- function useChevronTokens(modes: Record<string, any>) {
156
+ function useChevronTokens(modes: Modes) {
156
157
  return useMemo(() => {
157
158
  const iconSize =
158
159
  parseInt(getVariableByName('input/iconSize', modes), 10) || 32
@@ -172,7 +173,7 @@ function toNumber(value: unknown, fallback: number): number {
172
173
  return fallback
173
174
  }
174
175
 
175
- function useFormFieldTokens(modes: Record<string, any>) {
176
+ function useFormFieldTokens(modes: Modes) {
176
177
  return useMemo(() => {
177
178
  const labelColor =
178
179
  (getVariableByName('formField/label/color', modes) as string) ||
@@ -829,7 +830,7 @@ function DropdownInput({
829
830
  transparent
830
831
  statusBarTranslucent
831
832
  navigationBarTranslucent
832
- animationType="fade"
833
+ animationType="none"
833
834
  onRequestClose={closeMenu}
834
835
  >
835
836
  <Pressable
@@ -5,6 +5,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
5
  import IconCapsule from '../IconCapsule/IconCapsule'
6
6
  import Button from '../Button/Button'
7
7
  import { EMPTY_MODES } from '../../utils/react-utils'
8
+ import type { Modes } from '../../design-tokens'
8
9
 
9
10
  export type EmptyStateProps = {
10
11
  /**
@@ -35,7 +36,7 @@ export type EmptyStateProps = {
35
36
  /**
36
37
  * Mode configuration for theming
37
38
  */
38
- modes?: Record<string, any>;
39
+ modes?: Modes;
39
40
  style?: StyleProp<ViewStyle>;
40
41
  testID?: string;
41
42
  }
@@ -10,6 +10,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
10
  import { EMPTY_MODES } from '../../utils/react-utils'
11
11
  import Checkbox from '../Checkbox/Checkbox'
12
12
  import Button from '../Button/Button'
13
+ import type { Modes } from '../../design-tokens'
13
14
 
14
15
  export type ExpandableCheckboxProps = {
15
16
  /** Long text label rendered next to the checkbox. */
@@ -35,7 +36,7 @@ export type ExpandableCheckboxProps = {
35
36
  /** Number of lines to show when collapsed. Defaults to `1`. */
36
37
  collapsedLines?: number
37
38
  /** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
38
- modes?: Record<string, any>
39
+ modes?: Modes
39
40
  /** Override outer container styles. */
40
41
  style?: StyleProp<ViewStyle>
41
42
  /** Override the label text styles. */
@@ -3,12 +3,13 @@ import { View, type StyleProp, type ViewStyle } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import TextInput from '../TextInput/TextInput'
5
5
  import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
6
+ import type { Modes } from '../../design-tokens'
6
7
 
7
8
  type RenderInputArgs = {
8
9
  placeholder: string;
9
10
  value: string;
10
11
  onChangeText?: ((text: string) => void) | undefined;
11
- modes: Record<string, any>;
12
+ modes: Modes;
12
13
  accessibilityLabel: string;
13
14
  accessibilityHint?: string | undefined;
14
15
  onFocus?: (e: any) => void;
@@ -30,7 +31,7 @@ type FilterBarProps = {
30
31
  * respect the higher-level FilterBar API.
31
32
  */
32
33
  renderInput?: (args: RenderInputArgs) => React.ReactNode;
33
- modes?: Record<string, any>;
34
+ modes?: Modes;
34
35
  style?: StyleProp<ViewStyle>;
35
36
  accessibilityLabel?: string;
36
37
  accessibilityHint?: string;
@@ -3,6 +3,7 @@ import { View, type StyleProp, type ViewStyle } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
5
  import { EMPTY_MODES } from '../../utils/react-utils'
6
+ import type { Modes } from '../../design-tokens'
6
7
 
7
8
  type FormContextValue = {
8
9
  validationErrors: Record<string, string | string[]>;
@@ -19,7 +20,7 @@ export type FormProps = {
19
20
  children: React.ReactNode;
20
21
  validationErrors?: Record<string, string | string[]>;
21
22
  onSubmit?: () => void;
22
- modes?: Record<string, any>;
23
+ modes?: Modes;
23
24
  style?: StyleProp<ViewStyle>;
24
25
  accessibilityLabel?: string;
25
26
  testID?: string;
@@ -15,6 +15,7 @@ import SupportText from '../SupportText/SupportText'
15
15
  import type { SupportTextStatus } from '../SupportText/SupportTextIcon'
16
16
  import Icon from '../../icons/Icon'
17
17
  import { useFormContext } from '../Form/Form'
18
+ import type { Modes } from '../../design-tokens'
18
19
 
19
20
  export type FormFieldType = 'text' | 'password' | 'email' | 'search' | 'number' | 'phone' | 'url'
20
21
 
@@ -76,7 +77,7 @@ export type FormFieldProps = {
76
77
  /** When true, focuses the input on mount. */
77
78
  autoFocus?: boolean
78
79
  /** Modes for design token resolution. */
79
- modes?: Record<string, any>
80
+ modes?: Modes
80
81
  /** Style overrides for the outermost wrapper. */
81
82
  style?: StyleProp<ViewStyle>
82
83
  /** Style overrides for the input row container. */
@@ -116,7 +117,7 @@ function toFontWeight(value: unknown, fallback: TextStyle['fontWeight']): TextSt
116
117
  return fallback
117
118
  }
118
119
 
119
- function useFormFieldTokens(modes: Record<string, any>) {
120
+ function useFormFieldTokens(modes: Modes) {
120
121
  return useMemo(() => {
121
122
  // Wrapper
122
123
  const gap = toNumber(getVariableByName('formField/gap', modes), 8)
@@ -1,8 +1,9 @@
1
- import React, { useMemo, useRef } from 'react'
1
+ import React, { useMemo, useRef, useState, useCallback } from 'react'
2
2
  import {
3
3
  View,
4
4
  Text,
5
5
  Animated,
6
+ type LayoutChangeEvent,
6
7
  type StyleProp,
7
8
  type ViewStyle,
8
9
  type TextStyle,
@@ -16,6 +17,7 @@ import Disclaimer from '../Disclaimer/Disclaimer'
16
17
  import IconButton from '../IconButton/IconButton'
17
18
  import ActionFooter from '../ActionFooter/ActionFooter'
18
19
  import Slot from '../Slot/Slot'
20
+ import type { Modes } from '../../design-tokens'
19
21
 
20
22
  // ---------------------------------------------------------------------------
21
23
  // Forced modes
@@ -99,7 +101,7 @@ export type FullscreenModalProps = {
99
101
  * and `context5` is always forced to `'Fullscreen Modal'` (non-overridable).
100
102
  * The resolved modes cascade to the body, hero media, and the `ActionFooter`.
101
103
  */
102
- modes?: Record<string, any>
104
+ modes?: Modes
103
105
  /** Style overrides for the outer container. */
104
106
  style?: StyleProp<ViewStyle>
105
107
  /** Style overrides for the transparent body wrapper. */
@@ -118,7 +120,7 @@ type HeroTextProps = {
118
120
  headline?: string
119
121
  supportingText?: string
120
122
  priceText?: string
121
- modes: Record<string, any>
123
+ modes: Modes
122
124
  }
123
125
 
124
126
  function HeroText({ eyebrow, headline, supportingText, priceText, modes }: HeroTextProps) {
@@ -300,11 +302,57 @@ function FullscreenModal({
300
302
  )
301
303
  const heroTranslateY = useMemo(() => Animated.multiply(scrollY, -1), [scrollY])
302
304
 
303
- const processedHeroMedia = useMemo(
304
- () =>
305
- heroMedia ? cloneChildrenWithModes(heroMedia, modes, FULLSCREEN_MODAL_FORCED_MODES) : null,
306
- [heroMedia, modes]
307
- )
305
+ // The hero media is a full-bleed background pinned to the top of the modal.
306
+ // Its wrapper is absolutely positioned (`top/left/right: 0`) so it never
307
+ // contributes to scroll height. We measure the modal's own width so we can
308
+ // give the hero media a DEFINITE { width, height } box (see
309
+ // `processedHeroMedia` below) — relying on the media's own `width: '100%'` +
310
+ // `aspectRatio` is unreliable inside an indefinite-height absolute box (RN's
311
+ // `<Image>` falls back to its intrinsic width and leaves a gap), so we size
312
+ // it explicitly here instead.
313
+ const [containerWidth, setContainerWidth] = useState(0)
314
+ const onContainerLayout = useCallback((e: LayoutChangeEvent) => {
315
+ const w = e.nativeEvent.layout.width
316
+ setContainerWidth((prev) => (prev !== w ? w : prev))
317
+ }, [])
318
+
319
+ const processedHeroMedia = useMemo(() => {
320
+ if (!heroMedia) return null
321
+ // Defer rendering the hero until we have measured the modal width. This
322
+ // matters for image sharpness: React Native decodes a bitmap once, on the
323
+ // first render, and caches it. If we rendered the media before knowing the
324
+ // final box, that first decode would be sized/sampled for the wrong box and
325
+ // the cached (downsampled) bitmap would then just be scaled up — blurry.
326
+ // Rendering only once the explicit { width, height } box is known means the
327
+ // very first decode is already full-resolution for the correct box.
328
+ if (containerWidth <= 0) return null
329
+ const withModes = cloneChildrenWithModes(heroMedia, modes, FULLSCREEN_MODAL_FORCED_MODES)
330
+
331
+ // Force the hero to fill the modal width edge to edge, top-aligned, with the
332
+ // height derived from the media's native aspect ratio.
333
+ //
334
+ // Why we inject explicit width/height instead of relying on the media's own
335
+ // `width: '100%'` + `aspectRatio`: the hero wrapper is absolutely positioned
336
+ // with an INDEFINITE height, and in that layout context React Native's
337
+ // `<Image>` falls back to its INTRINSIC width (so a 361px-wide asset renders
338
+ // 361px wide and leaves a gap on the right) rather than stretching to the
339
+ // parent. By computing `height = containerWidth / ratio` here and passing a
340
+ // DEFINITE { width, height } box (which makes `<Image>` skip aspectRatio and
341
+ // cover-fit into that exact box), the hero always fills the width with the
342
+ // correct ratio-derived height.
343
+ return React.Children.map(withModes, (child) => {
344
+ if (!React.isValidElement(child)) return child
345
+ const props = child.props as { ratio?: number; width?: unknown; height?: unknown }
346
+ const ratio = typeof props.ratio === 'number' && props.ratio > 0 ? props.ratio : undefined
347
+ // Only size media that exposes a numeric `ratio` and hasn't already been
348
+ // given an explicit box by the caller.
349
+ if (ratio == null || props.width != null || props.height != null) return child
350
+ return React.cloneElement(child, {
351
+ width: containerWidth,
352
+ height: containerWidth / ratio,
353
+ } as Partial<typeof props>)
354
+ })
355
+ }, [heroMedia, modes, containerWidth])
308
356
 
309
357
  const processedChildren = useMemo(
310
358
  () =>
@@ -369,7 +417,7 @@ function FullscreenModal({
369
417
  }
370
418
 
371
419
  return (
372
- <View style={[rootStyle, style]} testID={testID}>
420
+ <View style={[rootStyle, style]} testID={testID} onLayout={onContainerLayout}>
373
421
  {/*
374
422
  * Layout model:
375
423
  * - `processedHeroMedia` is a ROOT-LEVEL full-bleed background pinned to
@@ -387,7 +435,17 @@ function FullscreenModal({
387
435
  */}
388
436
  {processedHeroMedia ? (
389
437
  <Animated.View
390
- style={[heroBackgroundStyle, { transform: [{ translateY: heroTranslateY }] }]}
438
+ style={[
439
+ heroBackgroundStyle,
440
+ // Give the absolute wrapper a DEFINITE width (the measured modal
441
+ // width) so the media's `width: '100%'` + `aspectRatio` resolves to
442
+ // a true edge-to-edge fill with a ratio-derived height, top-aligned.
443
+ // Before the first layout pass `containerWidth` is 0 — fall back to
444
+ // stretching via `left/right: 0` so there is no flash of a mis-sized
445
+ // image.
446
+ containerWidth > 0 ? { width: containerWidth } : null,
447
+ { transform: [{ translateY: heroTranslateY }] },
448
+ ]}
391
449
  pointerEvents="none"
392
450
  >
393
451
  {processedHeroMedia}
@@ -5,6 +5,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
5
5
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
6
6
  import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
7
7
  import SupportText, { type SupportTextProps } from '../SupportText/SupportText'
8
+ import type { Modes } from '../../design-tokens'
8
9
 
9
10
  type GaugeBaseProps = Omit<React.ComponentProps<typeof View>, 'children' | 'style'>
10
11
 
@@ -32,7 +33,7 @@ export type GaugeProps = GaugeBaseProps & {
32
33
  /** Hides default support text when no custom readout slot is provided. */
33
34
  showSupportText?: boolean
34
35
  /** Design token modes forwarded to token lookups and slot children. */
35
- modes?: Record<string, any>
36
+ modes?: Modes
36
37
  /** Slot rendered in the center of the gauge arc. Receives `modes` recursively. */
37
38
  children?: React.ReactNode
38
39
  /** Container style override. */
@@ -3,6 +3,7 @@ import { View, StyleProp, ViewStyle, ViewProps } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
5
  import { cloneChildrenWithModes, EMPTY_MODES } from '../../utils/react-utils'
6
+ import type { Modes } from '../../design-tokens'
6
7
 
7
8
  export interface HStackProps extends ViewProps {
8
9
  /**
@@ -35,7 +36,7 @@ export interface HStackProps extends ViewProps {
35
36
  /**
36
37
  * Modes object to override default variable values.
37
38
  */
38
- modes?: Record<string, any>;
39
+ modes?: Modes;
39
40
  }
40
41
 
41
42
  /**
@@ -11,6 +11,7 @@ import {
11
11
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
12
12
  import Radio from '../Radio/Radio'
13
13
  import { EMPTY_MODES } from '../../utils/react-utils'
14
+ import type { Modes } from '../../design-tokens'
14
15
 
15
16
  export interface HoldingsCardDetailItem {
16
17
  label: string
@@ -33,7 +34,7 @@ export interface HoldingsCardProps {
33
34
  /** Called when the card is pressed (toggles selection). */
34
35
  onPress?: () => void
35
36
  /** Modes object for design-token resolution. */
36
- modes?: Record<string, any>
37
+ modes?: Modes
37
38
  /** Custom style for the outer container. */
38
39
  style?: StyleProp<ViewStyle>
39
40
  /** Test ID for testing. */
@@ -10,6 +10,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
10
10
  import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
11
11
  import BaseIcon from '../../icons/Icon'
12
12
  import type { UnifiedSource } from '../../utils/MediaSource'
13
+ import type { Modes } from '../../design-tokens'
13
14
 
14
15
  type IconProps = AccessibilityProps & {
15
16
  /**
@@ -43,7 +44,7 @@ type IconProps = AccessibilityProps & {
43
44
  * from the `icon/size` design token.
44
45
  */
45
46
  size?: number
46
- modes?: Record<string, any>
47
+ modes?: Modes
47
48
  style?: StyleProp<ViewStyle>
48
49
  }
49
50
 
@@ -53,7 +54,7 @@ interface IconTokens {
53
54
  iconSize: number
54
55
  }
55
56
 
56
- function resolveIconTokens(modes: Record<string, any>): IconTokens {
57
+ function resolveIconTokens(modes: Modes): IconTokens {
57
58
  const iconColor = (getVariableByName('icon/color', modes) || '#ad8444') as string
58
59
  const iconSize = (getVariableByName('icon/size', modes) || 18) as number
59
60
  const paddingLeft = (getVariableByName('icon/padding/left', modes) || 0) as number