jfs-components 0.1.2 → 0.1.12

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 (287) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/lib/commonjs/components/Accordion/Accordion.js +2 -1
  3. package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +4 -3
  4. package/lib/commonjs/components/AccountCard/AccountCard.js +4 -3
  5. package/lib/commonjs/components/AllocationComparisonChart/AllocationComparisonChart.js +9 -6
  6. package/lib/commonjs/components/AmountInput/AmountInput.js +8 -5
  7. package/lib/commonjs/components/AreaLineChart/AreaLineChart.js +11 -7
  8. package/lib/commonjs/components/Badge/Badge.js +47 -8
  9. package/lib/commonjs/components/BenefitCard/BenefitCard.js +231 -0
  10. package/lib/commonjs/components/BrandChip/BrandChip.js +3 -3
  11. package/lib/commonjs/components/Button/Button.js +2 -1
  12. package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +2 -1
  13. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +3 -2
  14. package/lib/commonjs/components/CardCTA/CardCTA.js +197 -27
  15. package/lib/commonjs/components/CardInsight/CardInsight.js +5 -1
  16. package/lib/commonjs/components/CcCard/CcCard.js +470 -0
  17. package/lib/commonjs/components/Checkbox/Checkbox.js +4 -3
  18. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +4 -3
  19. package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +7 -3
  20. package/lib/commonjs/components/CircularProgressBarDoted/CircularProgressBarDoted.js +3 -2
  21. package/lib/commonjs/components/CircularRating/CircularRating.js +2 -1
  22. package/lib/commonjs/components/ClusterBubble/ClusterBubble.js +3 -2
  23. package/lib/commonjs/components/CompareTable/CompareTable.js +401 -0
  24. package/lib/commonjs/components/ComparisonBar/ComparisonBar.js +266 -0
  25. package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +3 -2
  26. package/lib/commonjs/components/DonutChart/DonutChart.js +4 -3
  27. package/lib/commonjs/components/Dropdown/Dropdown.js +3 -2
  28. package/lib/commonjs/components/DropdownInput/DropdownInput.js +38 -5
  29. package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +2 -1
  30. package/lib/commonjs/components/FormField/FormField.js +45 -4
  31. package/lib/commonjs/components/Gauge/Gauge.js +1 -1
  32. package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +3 -2
  33. package/lib/commonjs/components/InputSearch/InputSearch.js +6 -4
  34. package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +2 -1
  35. package/lib/commonjs/components/ListGroup/ListGroup.js +2 -1
  36. package/lib/commonjs/components/ListItem/ListItem.js +3 -2
  37. package/lib/commonjs/components/MediaCard/MediaCard.js +4 -2
  38. package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +3 -2
  39. package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +6 -3
  40. package/lib/commonjs/components/NoteInput/NoteInput.js +6 -5
  41. package/lib/commonjs/components/PdpCcCard/PdpCcCard.js +273 -0
  42. package/lib/commonjs/components/PoweredByLabel/PoweredByLabel.js +3 -2
  43. package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +427 -0
  44. package/lib/commonjs/components/ProductOverview/ProductOverview.js +4 -3
  45. package/lib/commonjs/components/ProgressBadge/ProgressBadge.js +2 -2
  46. package/lib/commonjs/components/ProjectionMarker/ProjectionMarker.js +162 -0
  47. package/lib/commonjs/components/Radio/Radio.js +5 -5
  48. package/lib/commonjs/components/Section/Section.js +3 -2
  49. package/lib/commonjs/components/Slider/Slider.js +474 -0
  50. package/lib/commonjs/components/Stack/Stack.js +86 -0
  51. package/lib/commonjs/components/SuggestiveSearch/SuggestiveSearch.js +10 -1
  52. package/lib/commonjs/components/SummaryTile/SummaryTile.js +3 -2
  53. package/lib/commonjs/components/Table/Table.js +324 -0
  54. package/lib/commonjs/components/Text/Text.js +2 -1
  55. package/lib/commonjs/components/TextInput/TextInput.js +22 -9
  56. package/lib/commonjs/components/TextSegment/TextSegment.js +119 -0
  57. package/lib/commonjs/components/ThreadHero/ThreadHero.js +4 -5
  58. package/lib/commonjs/components/Title/Title.js +2 -1
  59. package/lib/commonjs/components/Toast/Toast.js +3 -2
  60. package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +2 -1
  61. package/lib/commonjs/components/TransactionStatus/TransactionStatus.js +3 -2
  62. package/lib/commonjs/components/UpiHandle/UpiHandle.js +2 -2
  63. package/lib/commonjs/components/index.js +107 -0
  64. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  65. package/lib/commonjs/design-tokens/figma-modes.generated.js +39 -9
  66. package/lib/commonjs/icons/registry.js +1 -1
  67. package/lib/commonjs/utils/GlassFill/GlassFill.js +271 -0
  68. package/lib/commonjs/utils/GlassFill/GlassFill.web.js +120 -0
  69. package/lib/commonjs/utils/react-utils.js +78 -0
  70. package/lib/commonjs/utils/web-platform-utils.js +59 -0
  71. package/lib/module/components/Accordion/Accordion.js +3 -2
  72. package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +5 -4
  73. package/lib/module/components/AccountCard/AccountCard.js +5 -4
  74. package/lib/module/components/AllocationComparisonChart/AllocationComparisonChart.js +10 -7
  75. package/lib/module/components/AmountInput/AmountInput.js +6 -4
  76. package/lib/module/components/AreaLineChart/AreaLineChart.js +12 -8
  77. package/lib/module/components/Badge/Badge.js +49 -10
  78. package/lib/module/components/BenefitCard/BenefitCard.js +225 -0
  79. package/lib/module/components/BrandChip/BrandChip.js +4 -4
  80. package/lib/module/components/Button/Button.js +3 -2
  81. package/lib/module/components/CardAdvisory/CardAdvisory.js +3 -2
  82. package/lib/module/components/CardBankAccount/CardBankAccount.js +4 -3
  83. package/lib/module/components/CardCTA/CardCTA.js +198 -28
  84. package/lib/module/components/CardInsight/CardInsight.js +5 -1
  85. package/lib/module/components/CcCard/CcCard.js +464 -0
  86. package/lib/module/components/Checkbox/Checkbox.js +5 -4
  87. package/lib/module/components/CheckboxItem/CheckboxItem.js +5 -4
  88. package/lib/module/components/CircularProgressBar/CircularProgressBar.js +8 -4
  89. package/lib/module/components/CircularProgressBarDoted/CircularProgressBarDoted.js +4 -3
  90. package/lib/module/components/CircularRating/CircularRating.js +3 -2
  91. package/lib/module/components/ClusterBubble/ClusterBubble.js +4 -3
  92. package/lib/module/components/CompareTable/CompareTable.js +396 -0
  93. package/lib/module/components/ComparisonBar/ComparisonBar.js +260 -0
  94. package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +4 -3
  95. package/lib/module/components/DonutChart/DonutChart.js +5 -4
  96. package/lib/module/components/Dropdown/Dropdown.js +4 -3
  97. package/lib/module/components/DropdownInput/DropdownInput.js +40 -7
  98. package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +2 -1
  99. package/lib/module/components/FormField/FormField.js +48 -7
  100. package/lib/module/components/Gauge/Gauge.js +1 -1
  101. package/lib/module/components/HoldingsCard/HoldingsCard.js +4 -3
  102. package/lib/module/components/InputSearch/InputSearch.js +6 -4
  103. package/lib/module/components/InstitutionBadge/InstitutionBadge.js +3 -2
  104. package/lib/module/components/ListGroup/ListGroup.js +3 -2
  105. package/lib/module/components/ListItem/ListItem.js +4 -3
  106. package/lib/module/components/MediaCard/MediaCard.js +4 -2
  107. package/lib/module/components/MetricLegendItem/MetricLegendItem.js +4 -3
  108. package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +7 -4
  109. package/lib/module/components/NoteInput/NoteInput.js +7 -6
  110. package/lib/module/components/PdpCcCard/PdpCcCard.js +267 -0
  111. package/lib/module/components/PoweredByLabel/PoweredByLabel.js +4 -3
  112. package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +421 -0
  113. package/lib/module/components/ProductOverview/ProductOverview.js +5 -4
  114. package/lib/module/components/ProgressBadge/ProgressBadge.js +3 -3
  115. package/lib/module/components/ProjectionMarker/ProjectionMarker.js +157 -0
  116. package/lib/module/components/Radio/Radio.js +5 -4
  117. package/lib/module/components/Section/Section.js +4 -3
  118. package/lib/module/components/Slider/Slider.js +469 -0
  119. package/lib/module/components/Stack/Stack.js +81 -0
  120. package/lib/module/components/SuggestiveSearch/SuggestiveSearch.js +10 -1
  121. package/lib/module/components/SummaryTile/SummaryTile.js +4 -3
  122. package/lib/module/components/Table/Table.js +315 -0
  123. package/lib/module/components/Text/Text.js +3 -2
  124. package/lib/module/components/TextInput/TextInput.js +24 -11
  125. package/lib/module/components/TextSegment/TextSegment.js +114 -0
  126. package/lib/module/components/ThreadHero/ThreadHero.js +5 -6
  127. package/lib/module/components/Title/Title.js +3 -2
  128. package/lib/module/components/Toast/Toast.js +4 -3
  129. package/lib/module/components/TransactionBubble/TransactionBubble.js +3 -2
  130. package/lib/module/components/TransactionStatus/TransactionStatus.js +4 -3
  131. package/lib/module/components/UpiHandle/UpiHandle.js +3 -3
  132. package/lib/module/components/index.js +11 -0
  133. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  134. package/lib/module/design-tokens/figma-modes.generated.js +39 -9
  135. package/lib/module/icons/registry.js +1 -1
  136. package/lib/module/utils/GlassFill/GlassFill.js +265 -0
  137. package/lib/module/utils/GlassFill/GlassFill.web.js +115 -0
  138. package/lib/module/utils/react-utils.js +75 -0
  139. package/lib/module/utils/web-platform-utils.js +58 -0
  140. package/lib/typescript/src/components/Accordion/Accordion.d.ts +7 -1
  141. package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +7 -1
  142. package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +7 -1
  143. package/lib/typescript/src/components/AllocationComparisonChart/AllocationComparisonChart.d.ts +7 -1
  144. package/lib/typescript/src/components/AmountInput/AmountInput.d.ts +3 -2
  145. package/lib/typescript/src/components/AreaLineChart/AreaLineChart.d.ts +8 -1
  146. package/lib/typescript/src/components/Badge/Badge.d.ts +32 -2
  147. package/lib/typescript/src/components/BenefitCard/BenefitCard.d.ts +93 -0
  148. package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +7 -1
  149. package/lib/typescript/src/components/Button/Button.d.ts +7 -1
  150. package/lib/typescript/src/components/CardAdvisory/CardAdvisory.d.ts +7 -1
  151. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +7 -1
  152. package/lib/typescript/src/components/CardCTA/CardCTA.d.ts +27 -5
  153. package/lib/typescript/src/components/CcCard/CcCard.d.ts +137 -0
  154. package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +3 -2
  155. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +2 -2
  156. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +7 -1
  157. package/lib/typescript/src/components/CircularProgressBarDoted/CircularProgressBarDoted.d.ts +7 -1
  158. package/lib/typescript/src/components/CircularRating/CircularRating.d.ts +7 -1
  159. package/lib/typescript/src/components/ClusterBubble/ClusterBubble.d.ts +7 -1
  160. package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +94 -0
  161. package/lib/typescript/src/components/ComparisonBar/ComparisonBar.d.ts +118 -0
  162. package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +7 -1
  163. package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +7 -1
  164. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +7 -1
  165. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +26 -1
  166. package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +7 -1
  167. package/lib/typescript/src/components/FormField/FormField.d.ts +2 -2
  168. package/lib/typescript/src/components/HoldingsCard/HoldingsCard.d.ts +7 -1
  169. package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +23 -2
  170. package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +7 -1
  171. package/lib/typescript/src/components/ListGroup/ListGroup.d.ts +7 -1
  172. package/lib/typescript/src/components/ListItem/ListItem.d.ts +7 -1
  173. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +7 -1
  174. package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +14 -2
  175. package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +19 -2
  176. package/lib/typescript/src/components/PdpCcCard/PdpCcCard.d.ts +84 -0
  177. package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +7 -1
  178. package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +87 -0
  179. package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +7 -1
  180. package/lib/typescript/src/components/ProgressBadge/ProgressBadge.d.ts +7 -1
  181. package/lib/typescript/src/components/ProjectionMarker/ProjectionMarker.d.ts +88 -0
  182. package/lib/typescript/src/components/Radio/Radio.d.ts +3 -2
  183. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +2 -2
  184. package/lib/typescript/src/components/Section/Section.d.ts +7 -1
  185. package/lib/typescript/src/components/Slider/Slider.d.ts +105 -0
  186. package/lib/typescript/src/components/Stack/Stack.d.ts +81 -0
  187. package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +7 -1
  188. package/lib/typescript/src/components/Table/Table.d.ts +139 -0
  189. package/lib/typescript/src/components/Text/Text.d.ts +7 -1
  190. package/lib/typescript/src/components/TextInput/TextInput.d.ts +9 -29
  191. package/lib/typescript/src/components/TextSegment/TextSegment.d.ts +106 -0
  192. package/lib/typescript/src/components/ThreadHero/ThreadHero.d.ts +7 -1
  193. package/lib/typescript/src/components/Title/Title.d.ts +7 -1
  194. package/lib/typescript/src/components/Toast/Toast.d.ts +7 -1
  195. package/lib/typescript/src/components/TransactionBubble/TransactionBubble.d.ts +7 -1
  196. package/lib/typescript/src/components/TransactionStatus/TransactionStatus.d.ts +7 -1
  197. package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +7 -1
  198. package/lib/typescript/src/components/index.d.ts +14 -3
  199. package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +22 -2
  200. package/lib/typescript/src/icons/registry.d.ts +1 -1
  201. package/lib/typescript/src/utils/GlassFill/GlassFill.d.ts +84 -0
  202. package/lib/typescript/src/utils/GlassFill/GlassFill.web.d.ts +43 -0
  203. package/lib/typescript/src/utils/react-utils.d.ts +47 -0
  204. package/lib/typescript/src/utils/web-platform-utils.d.ts +36 -0
  205. package/package.json +2 -1
  206. package/src/components/Accordion/Accordion.tsx +9 -2
  207. package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +10 -3
  208. package/src/components/AccountCard/AccountCard.tsx +10 -3
  209. package/src/components/AllocationComparisonChart/AllocationComparisonChart.tsx +14 -4
  210. package/src/components/AmountInput/AmountInput.tsx +7 -5
  211. package/src/components/AreaLineChart/AreaLineChart.tsx +15 -5
  212. package/src/components/Badge/Badge.tsx +78 -8
  213. package/src/components/BenefitCard/BenefitCard.tsx +309 -0
  214. package/src/components/BrandChip/BrandChip.tsx +9 -3
  215. package/src/components/Button/Button.tsx +9 -2
  216. package/src/components/CardAdvisory/CardAdvisory.tsx +9 -2
  217. package/src/components/CardBankAccount/CardBankAccount.tsx +9 -2
  218. package/src/components/CardCTA/CardCTA.tsx +214 -41
  219. package/src/components/CardInsight/CardInsight.tsx +7 -1
  220. package/src/components/CcCard/CcCard.tsx +598 -0
  221. package/src/components/Checkbox/Checkbox.tsx +5 -4
  222. package/src/components/CheckboxItem/CheckboxItem.tsx +5 -4
  223. package/src/components/CircularProgressBar/CircularProgressBar.tsx +14 -4
  224. package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +10 -3
  225. package/src/components/CircularRating/CircularRating.tsx +9 -2
  226. package/src/components/ClusterBubble/ClusterBubble.tsx +9 -2
  227. package/src/components/CompareTable/CompareTable.tsx +525 -0
  228. package/src/components/ComparisonBar/ComparisonBar.tsx +356 -0
  229. package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +9 -2
  230. package/src/components/DonutChart/DonutChart.tsx +10 -3
  231. package/src/components/Dropdown/Dropdown.tsx +9 -2
  232. package/src/components/DropdownInput/DropdownInput.tsx +64 -5
  233. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +8 -1
  234. package/src/components/FormField/FormField.tsx +52 -6
  235. package/src/components/Gauge/Gauge.tsx +1 -1
  236. package/src/components/HoldingsCard/HoldingsCard.tsx +9 -2
  237. package/src/components/InputSearch/InputSearch.tsx +8 -5
  238. package/src/components/InstitutionBadge/InstitutionBadge.tsx +9 -2
  239. package/src/components/ListGroup/ListGroup.tsx +9 -2
  240. package/src/components/ListItem/ListItem.tsx +10 -3
  241. package/src/components/MediaCard/MediaCard.tsx +2 -2
  242. package/src/components/MetricLegendItem/MetricLegendItem.tsx +9 -2
  243. package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +17 -2
  244. package/src/components/NoteInput/NoteInput.tsx +8 -6
  245. package/src/components/PdpCcCard/PdpCcCard.tsx +356 -0
  246. package/src/components/PoweredByLabel/PoweredByLabel.tsx +9 -2
  247. package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +490 -0
  248. package/src/components/ProductOverview/ProductOverview.tsx +10 -3
  249. package/src/components/ProgressBadge/ProgressBadge.tsx +9 -3
  250. package/src/components/ProjectionMarker/ProjectionMarker.tsx +284 -0
  251. package/src/components/Radio/Radio.tsx +5 -4
  252. package/src/components/Section/Section.tsx +10 -3
  253. package/src/components/Slider/Slider.tsx +635 -0
  254. package/src/components/Stack/Stack.tsx +131 -0
  255. package/src/components/SuggestiveSearch/SuggestiveSearch.tsx +10 -1
  256. package/src/components/SummaryTile/SummaryTile.tsx +9 -2
  257. package/src/components/Table/Table.tsx +449 -0
  258. package/src/components/Text/Text.tsx +9 -2
  259. package/src/components/TextInput/TextInput.tsx +22 -12
  260. package/src/components/TextSegment/TextSegment.tsx +173 -0
  261. package/src/components/ThreadHero/ThreadHero.tsx +10 -3
  262. package/src/components/Title/Title.tsx +9 -2
  263. package/src/components/Toast/Toast.tsx +9 -2
  264. package/src/components/TransactionBubble/TransactionBubble.tsx +9 -2
  265. package/src/components/TransactionStatus/TransactionStatus.tsx +9 -2
  266. package/src/components/UpiHandle/UpiHandle.tsx +9 -3
  267. package/src/components/index.ts +33 -3
  268. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  269. package/src/design-tokens/figma-modes.generated.ts +39 -9
  270. package/src/icons/registry.ts +1 -1
  271. package/src/utils/GlassFill/GlassFill.tsx +305 -0
  272. package/src/utils/GlassFill/GlassFill.web.tsx +148 -0
  273. package/src/utils/react-utils.ts +84 -0
  274. package/src/utils/web-platform-utils.ts +68 -0
  275. package/lib/commonjs/components/MediaCard/GlassFill.js +0 -62
  276. package/lib/commonjs/components/MediaCard/GlassFill.web.js +0 -48
  277. package/lib/module/components/MediaCard/GlassFill.js +0 -57
  278. package/lib/module/components/MediaCard/GlassFill.web.js +0 -43
  279. package/lib/typescript/scripts/extract-component-tokens.d.ts +0 -9
  280. package/lib/typescript/scripts/generate-component-docs.d.ts +0 -9
  281. package/lib/typescript/scripts/generate-icon-registry.d.ts +0 -3
  282. package/lib/typescript/scripts/generate-mode-types.d.ts +0 -2
  283. package/lib/typescript/scripts/retype-modes.d.cts +0 -2
  284. package/lib/typescript/src/components/MediaCard/GlassFill.d.ts +0 -47
  285. package/lib/typescript/src/components/MediaCard/GlassFill.web.d.ts +0 -20
  286. package/src/components/MediaCard/GlassFill.tsx +0 -89
  287. package/src/components/MediaCard/GlassFill.web.tsx +0 -53
@@ -1,5 +1,6 @@
1
- import React, { useCallback, useMemo, useState } from 'react'
1
+ import React, { forwardRef, useCallback, useMemo, useRef, useState } from 'react'
2
2
  import {
3
+ Platform,
3
4
  View,
4
5
  Text,
5
6
  TextInput as RNTextInput,
@@ -10,7 +11,8 @@ import {
10
11
  } from 'react-native'
11
12
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
12
13
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
13
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
14
+ import { EMPTY_MODES, cloneChildrenWithModes, mergeRefs } from '../../utils/react-utils'
15
+ import { useWebOutsidePress } from '../../utils/web-platform-utils'
14
16
  import SupportText from '../SupportText/SupportText'
15
17
  import type { SupportTextStatus } from '../SupportText/SupportTextIcon'
16
18
  import Icon from '../../icons/Icon'
@@ -301,7 +303,7 @@ function firstError(error: string | string[] | undefined): string | undefined {
301
303
  // Component
302
304
  // ---------------------------------------------------------------------------
303
305
 
304
- function FormField({
306
+ const FormField = forwardRef<RNTextInput, FormFieldProps>(function FormField({
305
307
  label,
306
308
  placeholder,
307
309
  value,
@@ -329,7 +331,7 @@ function FormField({
329
331
  accessibilityLabel,
330
332
  accessibilityHint,
331
333
  testID,
332
- }: FormFieldProps) {
334
+ }: FormFieldProps, ref: React.Ref<RNTextInput>) {
333
335
  // -- Form context integration -------------------------------------------
334
336
  const formCtx = useFormContext()
335
337
  const formError =
@@ -347,6 +349,25 @@ function FormField({
347
349
  const [isFocused, setIsFocused] = useState(false)
348
350
  const interactive = !isDisabled && !isReadOnly
349
351
 
352
+ // Internal handles so we can (a) imperatively blur the input and (b) detect
353
+ // outside presses. The forwarded `ref` is merged in below, so the public
354
+ // ref API (focus/blur/clear/isFocused) is unchanged for consumers.
355
+ const inputRef = useRef<RNTextInput>(null)
356
+ const rootRef = useRef<View>(null)
357
+ // Stable merged ref so React doesn't detach/reattach (and momentarily null
358
+ // `inputRef.current`) on every render.
359
+ const mergedInputRef = useMemo(() => mergeRefs(inputRef, ref), [ref])
360
+
361
+ // Web: pressing an INTERACTIVE element outside the field (Button, link,
362
+ // another pressable) often does not move DOM focus, so the native `blur`
363
+ // never fires and the field stays visually "Active". Force a blur on any
364
+ // outside pointer press while focused. No-op on native.
365
+ useWebOutsidePress(
366
+ rootRef,
367
+ useCallback(() => inputRef.current?.blur(), []),
368
+ isFocused,
369
+ )
370
+
350
371
  // FormField States cascade — error > read only/disabled > active (focused) > idle.
351
372
  // Disabled maps to "Read Only" since there is no dedicated disabled mode and
352
373
  // the visual treatment is closest. This is only the DEFAULT — an explicit
@@ -478,7 +499,30 @@ function FormField({
478
499
  color: tokens.inputTextColor,
479
500
  fontFamily: tokens.inputFontFamily,
480
501
  fontSize: tokens.inputFontSize,
481
- lineHeight: tokens.inputLineHeight,
502
+ // ⚠️ DO NOT change to an unconditional `lineHeight: tokens.inputLineHeight`.
503
+ // This has regressed twice — read this before "simplifying" it.
504
+ //
505
+ // `inputLineHeight` comes from the Figma token `formField/input/label`
506
+ // ("16/45"), which is a 16px font inside a 45px ROW, i.e. it is the row
507
+ // HEIGHT, not the text leading. The row height is already applied via
508
+ // `inputRowStyle.minHeight` + `alignItems: 'center'`, so the text never
509
+ // needs this value as its own `lineHeight`.
510
+ //
511
+ // Passing a `lineHeight` (45) that is much larger than `fontSize` (16)
512
+ // onto a single-line RNTextInput breaks ONLY iOS: iOS puts ALL the extra
513
+ // vertical space ABOVE the glyphs, so the text/placeholder sinks to the
514
+ // bottom of the box instead of centering. Android and Web distribute the
515
+ // space evenly and look correct. This is a long-standing iOS native
516
+ // font-metrics bug in UITextField — see facebook/react-native#39145 and
517
+ // #28012; the documented workaround is exactly "drop lineHeight on the
518
+ // single-line input and let a wrapper center it". A single-line UITextField
519
+ // with no lineHeight centers its text natively (see react-native#56774).
520
+ //
521
+ // So: omit lineHeight on iOS (native centering via the row), and keep the
522
+ // token value on Android/Web where it already renders correctly.
523
+ ...(Platform.OS === 'ios'
524
+ ? null
525
+ : { lineHeight: tokens.inputLineHeight }),
482
526
  fontWeight: tokens.inputFontWeight,
483
527
  padding: 0,
484
528
  margin: 0,
@@ -530,6 +574,7 @@ function FormField({
530
574
 
531
575
  return (
532
576
  <View
577
+ ref={rootRef}
533
578
  style={[wrapperStyle, style]}
534
579
  pointerEvents={isDisabled ? 'none' : 'auto'}
535
580
  testID={testID}
@@ -552,6 +597,7 @@ function FormField({
552
597
  </View>
553
598
  )}
554
599
  <RNTextInput
600
+ ref={mergedInputRef}
555
601
  style={[inputTextStyles, inputTextStyle]}
556
602
  value={value ?? ''}
557
603
  onChangeText={handleChangeText}
@@ -590,6 +636,6 @@ function FormField({
590
636
  )}
591
637
  </View>
592
638
  )
593
- }
639
+ })
594
640
 
595
641
  export default FormField
@@ -91,7 +91,7 @@ const toFontWeight = (value: unknown, fallback: TextStyle['fontWeight']) => {
91
91
 
92
92
  const getStrokeColor = (style: StyleProp<ViewStyle>, fallback: string) => {
93
93
  const flattened = StyleSheet.flatten(style)
94
- return typeof flattened.backgroundColor === 'string'
94
+ return flattened && typeof flattened.backgroundColor === 'string'
95
95
  ? flattened.backgroundColor
96
96
  : fallback
97
97
  }
@@ -10,7 +10,7 @@ import {
10
10
  } from 'react-native'
11
11
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
12
12
  import Radio from '../Radio/Radio'
13
- import { EMPTY_MODES } from '../../utils/react-utils'
13
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
14
14
  import type { Modes } from '../../design-tokens'
15
15
 
16
16
  export interface HoldingsCardDetailItem {
@@ -39,6 +39,12 @@ export interface HoldingsCardProps {
39
39
  style?: StyleProp<ViewStyle>
40
40
  /** Test ID for testing. */
41
41
  testID?: string
42
+ /**
43
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
44
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
45
+ * lines as it needs even when horizontal space is tight.
46
+ */
47
+ disableTruncation?: boolean
42
48
  }
43
49
 
44
50
  const GRID_COLUMNS = 3
@@ -62,6 +68,7 @@ export default function HoldingsCard({
62
68
  modes = EMPTY_MODES,
63
69
  style,
64
70
  testID,
71
+ disableTruncation,
65
72
  }: HoldingsCardProps) {
66
73
  // ---- Container tokens ----
67
74
  const containerFill = getVariableByName('holdingsCard/container/fill', modes) || '#fef4e5'
@@ -268,7 +275,7 @@ export default function HoldingsCard({
268
275
  lineHeight: detailValueLineHeight,
269
276
  fontWeight: detailValueFontWeight as any,
270
277
  }}
271
- numberOfLines={1}
278
+ {...resolveTruncation(disableTruncation, 1)}
272
279
  >
273
280
  {item.value}
274
281
  </Text>
@@ -1,5 +1,5 @@
1
- import React, { useState } from 'react'
2
- import { View, Text, Pressable, type StyleProp, type ViewStyle, type TextStyle, type TextInputProps as RNTextInputProps } from 'react-native'
1
+ import React, { forwardRef, useState } from 'react'
2
+ import { View, Text, Pressable, TextInput as RNTextInput, type StyleProp, type ViewStyle, type TextStyle, type TextInputProps as RNTextInputProps } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import { EMPTY_MODES } from '../../utils/react-utils'
5
5
  import Icon from '../../icons/Icon'
@@ -81,7 +81,7 @@ export type InputSearchProps = {
81
81
  accessibilityHint?: string;
82
82
  } & Omit<RNTextInputProps, 'style' | 'onChangeText' | 'onFocus' | 'onBlur' | 'placeholder' | 'value'>;
83
83
 
84
- export default function InputSearch({
84
+ const InputSearch = forwardRef<RNTextInput, InputSearchProps>(function InputSearch({
85
85
  supportText = true,
86
86
  supportTextLabel = "Support Text",
87
87
  supportTextIcon = "ic_info",
@@ -96,7 +96,7 @@ export default function InputSearch({
96
96
  trailing,
97
97
  inputStyle,
98
98
  ...rest
99
- }: InputSearchProps) {
99
+ }: InputSearchProps, ref: React.Ref<RNTextInput>) {
100
100
  const [isFocused, setIsFocused] = useState(false)
101
101
 
102
102
  // Hardcode InputState based on the state prop, ignoring any external InputState passed in modes
@@ -156,6 +156,7 @@ export default function InputSearch({
156
156
  gap: formFieldGap,
157
157
  }, containerStyle]}>
158
158
  <TextInput
159
+ ref={ref}
159
160
  placeholder={placeholder}
160
161
  value={value || ''}
161
162
  onChangeText={onChangeText || (() => { })}
@@ -178,4 +179,6 @@ export default function InputSearch({
178
179
  )}
179
180
  </View>
180
181
  )
181
- }
182
+ })
183
+
184
+ export default InputSearch
@@ -8,7 +8,7 @@ import {
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
10
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
11
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
11
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
12
12
  import MediaSource, { type UnifiedSource } from '../../utils/MediaSource'
13
13
  import type { Modes } from '../../design-tokens'
14
14
 
@@ -43,6 +43,12 @@ export type InstitutionBadgeProps = InstitutionBadgeBaseProps & {
43
43
  labelStyle?: StyleProp<TextStyle>
44
44
  /** Accessibility label. Defaults to `label`. */
45
45
  accessibilityLabel?: string
46
+ /**
47
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
48
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
49
+ * lines as it needs even when horizontal space is tight.
50
+ */
51
+ disableTruncation?: boolean
46
52
  }
47
53
 
48
54
  interface InstitutionBadgeTokens {
@@ -155,6 +161,7 @@ function InstitutionBadge({
155
161
  style,
156
162
  labelStyle,
157
163
  accessibilityLabel,
164
+ disableTruncation,
158
165
  ...rest
159
166
  }: InstitutionBadgeProps) {
160
167
  const { modes: globalModes } = useTokens()
@@ -207,7 +214,7 @@ function InstitutionBadge({
207
214
  />
208
215
  </View>
209
216
  )}
210
- <Text style={[tokens.labelStyle, labelStyle]} numberOfLines={1}>
217
+ <Text style={[tokens.labelStyle, labelStyle]} {...resolveTruncation(disableTruncation, 1)}>
211
218
  {label}
212
219
  </Text>
213
220
  </View>
@@ -6,7 +6,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
6
6
  * Helper function to recursively clone children and pass modes prop to components that accept it.
7
7
  * This ensures that all child components in slots receive the modes prop from the parent.
8
8
  */
9
- import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils'
9
+ import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren, resolveTruncation } from '../../utils/react-utils'
10
10
  import type { Modes } from '../../design-tokens'
11
11
 
12
12
  type ListGroupProps = {
@@ -17,6 +17,12 @@ type ListGroupProps = {
17
17
  style?: StyleProp<ViewStyle>;
18
18
  accessibilityLabel?: string;
19
19
  accessibilityHint?: string;
20
+ /**
21
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
22
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
23
+ * lines as it needs even when horizontal space is tight.
24
+ */
25
+ disableTruncation?: boolean;
20
26
  } & Omit<React.ComponentProps<typeof View>, 'children'>;
21
27
 
22
28
  /**
@@ -52,6 +58,7 @@ function ListGroup({
52
58
  style,
53
59
  accessibilityLabel,
54
60
  accessibilityHint,
61
+ disableTruncation,
55
62
  ...rest
56
63
  }: ListGroupProps) {
57
64
  // Resolve container tokens
@@ -113,7 +120,7 @@ function ListGroup({
113
120
  {label ? (
114
121
  <Text
115
122
  style={[labelStyle, processedSlot && { marginBottom: gap }]}
116
- numberOfLines={1}
123
+ {...resolveTruncation(disableTruncation, 1)}
117
124
  accessibilityElementsHidden={true}
118
125
  importantForAccessibility="no"
119
126
  >
@@ -13,7 +13,7 @@ import {
13
13
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
14
14
  import NavArrow from '../NavArrow/NavArrow'
15
15
  import { usePressableWebSupport, type WebAccessibilityProps } from '../../utils/web-platform-utils'
16
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
16
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
17
17
  import type { Modes } from '../../design-tokens'
18
18
 
19
19
  type ListItemProps = {
@@ -45,6 +45,12 @@ type ListItemProps = {
45
45
  * Web-specific accessibility props (only used on web platform)
46
46
  */
47
47
  webAccessibilityProps?: WebAccessibilityProps;
48
+ /**
49
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
50
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
51
+ * lines as it needs even when horizontal space is tight.
52
+ */
53
+ disableTruncation?: boolean;
48
54
  } & React.ComponentProps<typeof View>;
49
55
 
50
56
  // ---------------------------------------------------------------------------
@@ -230,6 +236,7 @@ function ListItemImpl({
230
236
  accessibilityHint,
231
237
  accessibilityState,
232
238
  webAccessibilityProps,
239
+ disableTruncation,
233
240
  ...rest
234
241
  }: ListItemProps) {
235
242
  const tokens = useMemo(() => resolveListItemTokens(modes), [modes])
@@ -314,7 +321,7 @@ function ListItemImpl({
314
321
  ? [tokens.supportTextStyle, verticalSupportTextOverride]
315
322
  : tokens.supportTextStyle
316
323
  }
317
- numberOfLines={layout === 'Horizontal' ? 2 : undefined}
324
+ {...resolveTruncation(disableTruncation, layout === 'Horizontal' ? 2 : undefined)}
318
325
  >
319
326
  {displayText}
320
327
  </Text>
@@ -382,7 +389,7 @@ function ListItemImpl({
382
389
  >
383
390
  <Text
384
391
  style={tokens.titleTextStyle}
385
- numberOfLines={1}
392
+ {...resolveTruncation(disableTruncation, 1)}
386
393
  >
387
394
  {title}
388
395
  </Text>
@@ -2,7 +2,7 @@ import React, { createContext, useContext } from 'react'
2
2
  import { View, Text, StyleSheet, type ViewStyle, type TextStyle, type StyleProp, type ImageSourcePropType } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import Image from '../Image/Image'
5
- import GlassFill, { type GlassTint } from './GlassFill'
5
+ import GlassFill, { type GlassTint } from '../../utils/GlassFill/GlassFill'
6
6
  import { EMPTY_MODES } from '../../utils/react-utils'
7
7
  import type { Modes } from '../../design-tokens'
8
8
 
@@ -225,7 +225,7 @@ export function Footer({ children, style, modes: propModes }: { children?: React
225
225
  ]}
226
226
  pointerEvents="box-none"
227
227
  >
228
- <GlassFill tint={tint} intensity={intensity} overlayColor={glassBgColor} />
228
+ <GlassFill tint={tint} intensity={intensity} overlayColor={glassBgColor} webBlurScale={0.3} webBlurMaxPx={30} />
229
229
 
230
230
  <View
231
231
  style={{
@@ -7,7 +7,7 @@ import {
7
7
  type TextStyle,
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
- import { EMPTY_MODES } from '../../utils/react-utils'
10
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
11
11
  import type { Modes } from '../../design-tokens'
12
12
 
13
13
  export type MetricLegendItemProps = {
@@ -39,6 +39,12 @@ export type MetricLegendItemProps = {
39
39
  labelStyle?: StyleProp<TextStyle>
40
40
  /** Override the value text styles. */
41
41
  valueStyle?: StyleProp<TextStyle>
42
+ /**
43
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
44
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
45
+ * lines as it needs even when horizontal space is tight.
46
+ */
47
+ disableTruncation?: boolean
42
48
  }
43
49
 
44
50
  /**
@@ -59,6 +65,7 @@ function MetricLegendItem({
59
65
  indicatorStyle,
60
66
  labelStyle,
61
67
  valueStyle,
68
+ disableTruncation,
62
69
  }: MetricLegendItemProps) {
63
70
  const gap = (getVariableByName('metricLegendItem/gap', modes) as number | null) ?? 4
64
71
  const textWrapGap =
@@ -169,7 +176,7 @@ function MetricLegendItem({
169
176
  },
170
177
  valueStyle,
171
178
  ]}
172
- numberOfLines={1}
179
+ {...resolveTruncation(disableTruncation, 1)}
173
180
  >
174
181
  {value}
175
182
  </Text>
@@ -8,7 +8,7 @@ import {
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
10
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
11
- import { EMPTY_MODES } from '../../utils/react-utils'
11
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
12
12
  import MetricLegendItem from '../MetricLegendItem/MetricLegendItem'
13
13
  import type { Modes } from '../../design-tokens'
14
14
 
@@ -83,6 +83,12 @@ export type MonthlyStatusGridProps = {
83
83
  legendStyle?: StyleProp<ViewStyle>
84
84
  /** Accessibility label for the entire component. */
85
85
  accessibilityLabel?: string
86
+ /**
87
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
88
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
89
+ * lines as it needs even when horizontal space is tight.
90
+ */
91
+ disableTruncation?: boolean
86
92
  }
87
93
 
88
94
  const DEFAULT_MONTH_LABELS: readonly string[] = [
@@ -170,6 +176,12 @@ export type CalendarGlyphProps = {
170
176
  labelStyle?: StyleProp<TextStyle>
171
177
  /** Accessibility label. Defaults to `"{label}, {status}"`. */
172
178
  accessibilityLabel?: string
179
+ /**
180
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
181
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
182
+ * lines as it needs even when horizontal space is tight.
183
+ */
184
+ disableTruncation?: boolean
173
185
  }
174
186
 
175
187
  /**
@@ -186,6 +198,7 @@ function CalendarGlyph({
186
198
  style,
187
199
  labelStyle,
188
200
  accessibilityLabel,
201
+ disableTruncation,
189
202
  }: CalendarGlyphProps) {
190
203
  const { modes: globalModes } = useTokens()
191
204
  const modes = React.useMemo(
@@ -244,7 +257,7 @@ function CalendarGlyph({
244
257
  ]}
245
258
  >
246
259
  <Text
247
- numberOfLines={1}
260
+ {...resolveTruncation(disableTruncation, 1)}
248
261
  style={[
249
262
  {
250
263
  color: foreground,
@@ -312,6 +325,7 @@ function MonthlyStatusGrid({
312
325
  labelStyle,
313
326
  legendStyle,
314
327
  accessibilityLabel,
328
+ disableTruncation,
315
329
  }: MonthlyStatusGridProps) {
316
330
  const { modes: globalModes } = useTokens()
317
331
  const modes = React.useMemo(
@@ -391,6 +405,7 @@ function MonthlyStatusGrid({
391
405
  label={label}
392
406
  status={month.status}
393
407
  modes={glyphModes}
408
+ disableTruncation={disableTruncation}
394
409
  {...(glyphStyle !== undefined ? { style: glyphStyle } : {})}
395
410
  {...(labelStyle !== undefined ? { labelStyle } : {})}
396
411
  {...(month.accessibilityLabel !== undefined
@@ -1,4 +1,4 @@
1
- import React, { useState, useRef, useEffect } from 'react'
1
+ import React, { forwardRef, useState, useRef } from 'react'
2
2
  import {
3
3
  View,
4
4
  TextInput as RNTextInput,
@@ -11,7 +11,7 @@ import {
11
11
  type TextInputProps,
12
12
  } from 'react-native'
13
13
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
14
- import { EMPTY_MODES } from '../../utils/react-utils'
14
+ import { EMPTY_MODES, mergeRefs } from '../../utils/react-utils'
15
15
  import type { Modes } from '../../design-tokens'
16
16
 
17
17
  export type NoteInputProps = {
@@ -35,7 +35,7 @@ export type NoteInputProps = {
35
35
  * NoteInput component representing an interactive "Add note" badge style field.
36
36
  * Allows the user to click, clears the placeholder text, and shows a blinking cursor when focused.
37
37
  */
38
- export default function NoteInput({
38
+ const NoteInput = forwardRef<RNTextInput, NoteInputProps>(function NoteInput({
39
39
  value = '',
40
40
  placeholder = 'Add note',
41
41
  onChangeText,
@@ -46,7 +46,7 @@ export default function NoteInput({
46
46
  onFocus,
47
47
  onBlur,
48
48
  ...rest
49
- }: NoteInputProps) {
49
+ }: NoteInputProps, ref: React.Ref<RNTextInput>) {
50
50
  const [internalFocused, setInternalFocused] = useState(false)
51
51
  const inputRef = useRef<RNTextInput>(null)
52
52
 
@@ -120,7 +120,7 @@ export default function NoteInput({
120
120
  {internalFocused ? (value || ' ') : (value || placeholder)}
121
121
  </Text>
122
122
  <RNTextInput
123
- ref={inputRef}
123
+ ref={mergeRefs(inputRef, ref)}
124
124
  value={value}
125
125
  onChangeText={onChangeText}
126
126
  placeholder={internalFocused ? '' : placeholder}
@@ -145,4 +145,6 @@ export default function NoteInput({
145
145
  </View>
146
146
  </Pressable>
147
147
  )
148
- }
148
+ })
149
+
150
+ export default NoteInput