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
@@ -0,0 +1,131 @@
1
+ import React, { useMemo } from 'react'
2
+ import { View, type StyleProp, type ViewProps, type ViewStyle } from 'react-native'
3
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
+ import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
+ import { cloneChildrenWithModes, EMPTY_MODES, injectChildStyle } from '../../utils/react-utils'
6
+ import type { Modes } from '../../design-tokens'
7
+
8
+ export type StackLayoutDirection = 'vertical' | 'horizontal'
9
+
10
+ export type StackProps = ViewProps & {
11
+ /**
12
+ * Content laid out inside the stack. `modes` are cascaded to every child via
13
+ * {@link cloneChildrenWithModes}.
14
+ */
15
+ children?: React.ReactNode
16
+ /**
17
+ * Main-axis direction for stack children. Matches the Figma Slot variant:
18
+ * - `vertical` (default): stacks children in a column
19
+ * - `horizontal`: arranges children in a row
20
+ */
21
+ layoutDirection?: StackLayoutDirection
22
+ /**
23
+ * Alignment along the cross axis.
24
+ * Defaults to `stretch` for vertical and `flex-start` for horizontal.
25
+ */
26
+ alignCrossAxis?: ViewStyle['alignItems']
27
+ /**
28
+ * Distribution along the main axis (maps to `justifyContent`).
29
+ */
30
+ justifyMainAxis?: ViewStyle['justifyContent']
31
+ /**
32
+ * Only meaningful when `layoutDirection` is `horizontal`.
33
+ *
34
+ * When true, forces every child to share the height of the tallest child. The
35
+ * height is enforced by the stack itself (`alignItems: 'stretch'` plus an
36
+ * injected `alignSelf: 'stretch'` on each child), so children can no longer
37
+ * opt out via their own `alignSelf`. Children with an explicit `height` keep
38
+ * that height, since a fixed cross-axis dimension defeats stretch in Yoga.
39
+ *
40
+ * Overrides `alignCrossAxis` when it applies.
41
+ */
42
+ equalHeight?: boolean
43
+ /**
44
+ * Only meaningful when `layoutDirection` is `vertical`.
45
+ *
46
+ * When true, forces every child to fill the full width of the stack. The width
47
+ * is enforced by the stack itself (`alignItems: 'stretch'` plus an injected
48
+ * `alignSelf: 'stretch'` on each child), so children can no longer opt out via
49
+ * their own `alignSelf`. Children with an explicit `width` keep that width,
50
+ * since a fixed cross-axis dimension defeats stretch in Yoga.
51
+ *
52
+ * Overrides `alignCrossAxis` when it applies.
53
+ */
54
+ fillWidth?: boolean
55
+ /**
56
+ * Mode configuration passed to the token resolver and cascaded to children.
57
+ */
58
+ modes?: Modes
59
+ style?: StyleProp<ViewStyle>
60
+ }
61
+
62
+ /**
63
+ * Stack — a token-driven layout container for grouped content.
64
+ *
65
+ * Use `Stack` instead of a raw `View` when you need a vertical or horizontal
66
+ * stack with design-token gap spacing and automatic `modes` propagation to
67
+ * children. Typical usage is nesting a column of actions inside a
68
+ * direction-locked parent such as `ActionFooter`:
69
+ *
70
+ * @example
71
+ * ```tsx
72
+ * <ActionFooter modes={modes}>
73
+ * <Stack layoutDirection="vertical" modes={modes}>
74
+ * <Button label="Continue" modes={primaryModes} />
75
+ * <Disclaimer disclaimer="Terms apply." modes={modes} />
76
+ * </Stack>
77
+ * </ActionFooter>
78
+ * ```
79
+ *
80
+ * @remarks
81
+ * Previously named `Slot`. The `Slot` export is preserved as a deprecated alias
82
+ * for backward compatibility.
83
+ */
84
+ function Stack({
85
+ children,
86
+ layoutDirection = 'vertical',
87
+ alignCrossAxis,
88
+ justifyMainAxis,
89
+ equalHeight = false,
90
+ fillWidth = false,
91
+ modes: propModes = EMPTY_MODES,
92
+ style,
93
+ ...rest
94
+ }: StackProps) {
95
+ const { modes: globalModes } = useTokens()
96
+ const modes = useMemo(() => ({ ...globalModes, ...propModes }), [globalModes, propModes])
97
+
98
+ const { containerStyle, processedChildren } = useMemo(() => {
99
+ const gap = (getVariableByName('slot/gap', modes) ?? 8) as number
100
+ const isHorizontal = layoutDirection === 'horizontal'
101
+
102
+ // Cross-axis stretch maps to "equal height" for a row and "fill width" for a
103
+ // column. Honour whichever flag matches the active direction.
104
+ const stretchCrossAxis = isHorizontal ? equalHeight : fillWidth
105
+
106
+ const container: ViewStyle = {
107
+ flexDirection: isHorizontal ? 'row' : 'column',
108
+ alignItems: stretchCrossAxis
109
+ ? 'stretch'
110
+ : alignCrossAxis ?? (isHorizontal ? 'flex-start' : 'stretch'),
111
+ justifyContent: justifyMainAxis ?? (isHorizontal ? 'center' : undefined),
112
+ alignSelf: 'stretch',
113
+ gap,
114
+ }
115
+
116
+ const moded = children ? cloneChildrenWithModes(children, modes) : null
117
+ const processed = stretchCrossAxis && moded
118
+ ? injectChildStyle(moded, { alignSelf: 'stretch' })
119
+ : moded
120
+
121
+ return { containerStyle: container, processedChildren: processed }
122
+ }, [children, modes, layoutDirection, alignCrossAxis, justifyMainAxis, equalHeight, fillWidth])
123
+
124
+ return (
125
+ <View style={[containerStyle, style]} {...rest}>
126
+ {processedChildren}
127
+ </View>
128
+ )
129
+ }
130
+
131
+ export default React.memo(Stack)
@@ -560,7 +560,16 @@ function SuggestiveSearch({
560
560
  color: tokens.inputTextColor,
561
561
  fontFamily: tokens.inputFontFamily,
562
562
  fontSize: tokens.inputFontSize,
563
- lineHeight: tokens.inputLineHeight,
563
+ // iOS-only quirk: a single-line RNTextInput with `lineHeight` (45) far
564
+ // larger than `fontSize` (16) sinks the text to the bottom of the box
565
+ // instead of centering — iOS puts all the extra space ABOVE the glyphs.
566
+ // The row already owns the 45px height via `minHeight` + centering, so
567
+ // omit lineHeight on iOS (UITextField centers natively) and keep the
568
+ // token value on Android/Web where it renders correctly. Same fix as
569
+ // FormField — see facebook/react-native#39145 / #28012.
570
+ ...(Platform.OS === 'ios'
571
+ ? null
572
+ : { lineHeight: tokens.inputLineHeight }),
564
573
  fontWeight: tokens.inputFontWeight as TextStyle['fontWeight'],
565
574
  padding: 0,
566
575
  margin: 0,
@@ -9,7 +9,7 @@ import {
9
9
  type PressableStateCallbackType,
10
10
  } from 'react-native'
11
11
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
12
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
12
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
13
13
  import Button from '../Button/Button'
14
14
  import NavArrow from '../NavArrow/NavArrow'
15
15
  import StrengthIndicator, {
@@ -60,6 +60,12 @@ export type SummaryTileProps = {
60
60
  descriptionStyle?: StyleProp<TextStyle>
61
61
  /** Accessibility label override (defaults to `title`). */
62
62
  accessibilityLabel?: string
63
+ /**
64
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
65
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
66
+ * lines as it needs even when horizontal space is tight.
67
+ */
68
+ disableTruncation?: boolean
63
69
  }
64
70
 
65
71
  /**
@@ -84,6 +90,7 @@ function SummaryTile({
84
90
  titleStyle,
85
91
  descriptionStyle,
86
92
  accessibilityLabel,
93
+ disableTruncation,
87
94
  }: SummaryTileProps) {
88
95
  const containerGap =
89
96
  (getVariableByName('summaryTile/gap', modes) as number | null) ?? 8
@@ -179,7 +186,7 @@ function SummaryTile({
179
186
  {title ? (
180
187
  <Text
181
188
  style={[titleTextStyle, titleStyle]}
182
- numberOfLines={1}
189
+ {...resolveTruncation(disableTruncation, 1)}
183
190
  >
184
191
  {title}
185
192
  </Text>
@@ -0,0 +1,449 @@
1
+ import React from 'react'
2
+ import {
3
+ View,
4
+ Text,
5
+ Pressable,
6
+ ScrollView,
7
+ Platform,
8
+ type StyleProp,
9
+ type ViewStyle,
10
+ type TextStyle,
11
+ } from 'react-native'
12
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
13
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
14
+ import type { Modes } from '../../design-tokens'
15
+
16
+ /* -------------------------------------------------------------------------------------------------
17
+ * Shared types & token resolution
18
+ * -----------------------------------------------------------------------------------------------*/
19
+
20
+ export type TableCellAlign = 'left' | 'center' | 'right'
21
+
22
+ /** Resolved styling for a header cell and a body cell, derived from design tokens. */
23
+ type ResolvedTableTokens = {
24
+ headerBg: string
25
+ headerText: TextStyle
26
+ headerPaddingH: number
27
+ headerPaddingV: number
28
+ cellBg: string
29
+ cellText: TextStyle
30
+ cellPaddingH: number
31
+ cellPaddingV: number
32
+ borderColor: string
33
+ borderSize: number
34
+ }
35
+
36
+ const toWeight = (w: number | string): TextStyle['fontWeight'] =>
37
+ (typeof w === 'number' ? `${w}` : w) as TextStyle['fontWeight']
38
+
39
+ /**
40
+ * Resolve every token the table family needs in one place. Sub-components call
41
+ * this with their cascaded `modes` so they render correctly both inside a
42
+ * `Table` and when used standalone. Fallbacks mirror the Figma node values
43
+ * (`tableCell/*`, `tableHeader/*`) so the component is faithful even before the
44
+ * tokens are published to the local store.
45
+ */
46
+ function resolveTableTokens(modes: Modes): ResolvedTableTokens {
47
+ const headerFontFamily =
48
+ (getVariableByName('tableHeader/label/fontfamily', modes) as string) ?? 'JioType Var'
49
+ const headerFontSize = (getVariableByName('tableHeader/label/fontsize', modes) as number) ?? 14
50
+ const headerFontWeight =
51
+ (getVariableByName('tableHeader/label/fontweight', modes) as number | string) ?? 600
52
+
53
+ const cellFontFamily =
54
+ (getVariableByName('tableCell/label/fontfamily', modes) as string) ?? 'JioType Var'
55
+ const cellFontSize = (getVariableByName('tableCell/label/fontsize', modes) as number) ?? 14
56
+ const cellFontWeight =
57
+ (getVariableByName('tableCell/label/fontweight', modes) as number | string) ?? 400
58
+
59
+ return {
60
+ headerBg: (getVariableByName('tableHeader/background/color', modes) as string) ?? '#f5f5f5',
61
+ headerPaddingH: (getVariableByName('tableHeader/padding/horizontal', modes) as number) ?? 12,
62
+ headerPaddingV: (getVariableByName('tableHeader/padding/vertical', modes) as number) ?? 12,
63
+ headerText: {
64
+ color: (getVariableByName('tableHeader/label/color', modes) as string) ?? '#000000',
65
+ fontFamily: headerFontFamily,
66
+ fontSize: headerFontSize,
67
+ fontWeight: toWeight(headerFontWeight),
68
+ lineHeight: 20,
69
+ },
70
+ cellBg: (getVariableByName('tableCell/background/color', modes) as string) ?? '#ffffff',
71
+ cellPaddingH: (getVariableByName('tableCell/padding/horizontal', modes) as number) ?? 12,
72
+ cellPaddingV: (getVariableByName('tableCell/padding/vertical', modes) as number) ?? 12,
73
+ cellText: {
74
+ color: (getVariableByName('tableCell/label/color', modes) as string) ?? '#000000',
75
+ fontFamily: cellFontFamily,
76
+ fontSize: cellFontSize,
77
+ fontWeight: toWeight(cellFontWeight),
78
+ lineHeight: 20,
79
+ },
80
+ borderColor: (getVariableByName('tableCell/border/color', modes) as string) ?? '#eeeeee',
81
+ borderSize: (getVariableByName('tableCell/border/size', modes) as number) ?? 1,
82
+ }
83
+ }
84
+
85
+ const alignToJustify = (align: TableCellAlign): ViewStyle['justifyContent'] =>
86
+ align === 'center' ? 'center' : align === 'right' ? 'flex-end' : 'flex-start'
87
+
88
+ /** Renders text children through the resolved label style; passes elements through untouched. */
89
+ function renderCellContent(
90
+ children: React.ReactNode,
91
+ textStyle: TextStyle,
92
+ align: TableCellAlign,
93
+ modes: Modes,
94
+ ): React.ReactNode {
95
+ if (children == null || children === false) return null
96
+ if (typeof children === 'string' || typeof children === 'number') {
97
+ return <Text style={[textStyle, { textAlign: align }]}>{children}</Text>
98
+ }
99
+ return cloneChildrenWithModes(children, modes)
100
+ }
101
+
102
+ /* -------------------------------------------------------------------------------------------------
103
+ * Table.Cell — body cell (Figma `table-cell`, node 603:23)
104
+ * -----------------------------------------------------------------------------------------------*/
105
+
106
+ export type TableCellProps = {
107
+ children?: React.ReactNode
108
+ /** Horizontal alignment of the cell content. @default 'left' */
109
+ align?: TableCellAlign
110
+ /** Fixed cell width. Omit to let the cell flex. */
111
+ width?: number
112
+ /** Flex-grow weight when `width` is not set. @default 1 */
113
+ flex?: number
114
+ /** Drop the right divider (used for the last column). @default false */
115
+ isLastColumn?: boolean
116
+ /** Drop the bottom divider (used for the last row). @default false */
117
+ isLastRow?: boolean
118
+ modes?: Modes
119
+ style?: StyleProp<ViewStyle>
120
+ }
121
+
122
+ /**
123
+ * A single body cell. White background with a bottom + right divider, matching
124
+ * the Figma `table-cell` sub-component. String/number children are rendered
125
+ * with the token label style; any element is rendered as-is.
126
+ */
127
+ function TableCell({
128
+ children,
129
+ align = 'left',
130
+ width,
131
+ flex = 1,
132
+ isLastColumn = false,
133
+ isLastRow = false,
134
+ modes = EMPTY_MODES,
135
+ style,
136
+ }: TableCellProps) {
137
+ const t = resolveTableTokens(modes)
138
+ return (
139
+ <View
140
+ style={[
141
+ {
142
+ backgroundColor: t.cellBg,
143
+ flexDirection: 'row',
144
+ alignItems: 'center',
145
+ justifyContent: alignToJustify(align),
146
+ paddingHorizontal: t.cellPaddingH,
147
+ paddingVertical: t.cellPaddingV,
148
+ borderColor: t.borderColor,
149
+ borderBottomWidth: isLastRow ? 0 : t.borderSize,
150
+ borderRightWidth: isLastColumn ? 0 : t.borderSize,
151
+ ...(width != null ? { width } : { flex, minWidth: 0 }),
152
+ },
153
+ style,
154
+ ]}
155
+ >
156
+ {renderCellContent(children, t.cellText, align, modes)}
157
+ </View>
158
+ )
159
+ }
160
+
161
+ /* -------------------------------------------------------------------------------------------------
162
+ * Table.HeaderCell — header cell (Figma `table header wrap`, node 603:21)
163
+ * -----------------------------------------------------------------------------------------------*/
164
+
165
+ export type TableHeaderCellProps = {
166
+ children?: React.ReactNode
167
+ /** Horizontal alignment of the header content. @default 'left' */
168
+ align?: TableCellAlign
169
+ /** Fixed cell width. Omit to let the cell flex. */
170
+ width?: number
171
+ /** Flex-grow weight when `width` is not set. @default 1 */
172
+ flex?: number
173
+ modes?: Modes
174
+ style?: StyleProp<ViewStyle>
175
+ }
176
+
177
+ /**
178
+ * A single header cell. Muted background with the bold token label style,
179
+ * matching the Figma `table header wrap` sub-component. Header cells carry no
180
+ * dividers; the header row draws a single bottom divider beneath them.
181
+ */
182
+ function TableHeaderCell({
183
+ children,
184
+ align = 'left',
185
+ width,
186
+ flex = 1,
187
+ modes = EMPTY_MODES,
188
+ style,
189
+ }: TableHeaderCellProps) {
190
+ const t = resolveTableTokens(modes)
191
+ return (
192
+ <View
193
+ style={[
194
+ {
195
+ backgroundColor: t.headerBg,
196
+ flexDirection: 'row',
197
+ alignItems: 'center',
198
+ justifyContent: alignToJustify(align),
199
+ paddingHorizontal: t.headerPaddingH,
200
+ paddingVertical: t.headerPaddingV,
201
+ ...(width != null ? { width } : { flex, minWidth: 0 }),
202
+ },
203
+ style,
204
+ ]}
205
+ >
206
+ {renderCellContent(children, t.headerText, align, modes)}
207
+ </View>
208
+ )
209
+ }
210
+
211
+ /* -------------------------------------------------------------------------------------------------
212
+ * Table.Header — row of header cells with a bottom divider
213
+ * -----------------------------------------------------------------------------------------------*/
214
+
215
+ export type TableHeaderProps = {
216
+ children?: React.ReactNode
217
+ modes?: Modes
218
+ style?: StyleProp<ViewStyle>
219
+ }
220
+
221
+ function TableHeader({ children, modes = EMPTY_MODES, style }: TableHeaderProps) {
222
+ const t = resolveTableTokens(modes)
223
+ return (
224
+ <View
225
+ style={[
226
+ {
227
+ flexDirection: 'row',
228
+ width: '100%',
229
+ borderBottomWidth: t.borderSize,
230
+ borderBottomColor: t.borderColor,
231
+ },
232
+ style,
233
+ ]}
234
+ >
235
+ {cloneChildrenWithModes(children, modes)}
236
+ </View>
237
+ )
238
+ }
239
+
240
+ /* -------------------------------------------------------------------------------------------------
241
+ * Table.Row — row of body cells
242
+ * -----------------------------------------------------------------------------------------------*/
243
+
244
+ export type TableRowProps = {
245
+ children?: React.ReactNode
246
+ /** When provided, the whole row becomes pressable. */
247
+ onPress?: () => void
248
+ modes?: Modes
249
+ style?: StyleProp<ViewStyle>
250
+ }
251
+
252
+ function TableRow({ children, onPress, modes = EMPTY_MODES, style }: TableRowProps) {
253
+ const rowStyle: ViewStyle = { flexDirection: 'row', width: '100%' }
254
+ const content = cloneChildrenWithModes(children, modes)
255
+ if (onPress) {
256
+ return (
257
+ <Pressable
258
+ onPress={onPress}
259
+ accessibilityRole="button"
260
+ style={({ pressed }) => [rowStyle, pressed ? { opacity: 0.6 } : null, style]}
261
+ >
262
+ {content}
263
+ </Pressable>
264
+ )
265
+ }
266
+ return <View style={[rowStyle, style]}>{content}</View>
267
+ }
268
+
269
+ /* -------------------------------------------------------------------------------------------------
270
+ * Table.Body — column container for rows
271
+ * -----------------------------------------------------------------------------------------------*/
272
+
273
+ export type TableBodyProps = {
274
+ children?: React.ReactNode
275
+ modes?: Modes
276
+ style?: StyleProp<ViewStyle>
277
+ }
278
+
279
+ function TableBody({ children, modes = EMPTY_MODES, style }: TableBodyProps) {
280
+ return <View style={[{ width: '100%' }, style]}>{cloneChildrenWithModes(children, modes)}</View>
281
+ }
282
+
283
+ /* -------------------------------------------------------------------------------------------------
284
+ * Table — root (Figma `Table`, node 5732:3710)
285
+ * -----------------------------------------------------------------------------------------------*/
286
+
287
+ /**
288
+ * Column definition for the data-driven `Table` API. `T` is the shape of one
289
+ * row record.
290
+ */
291
+ export type TableColumn<T> = {
292
+ /** Stable key; also used to read `row[key]` when no `render` is provided. */
293
+ key: string
294
+ /** Header label. Defaults to `key`. */
295
+ header?: React.ReactNode
296
+ /** Cell + header horizontal alignment. @default 'left' */
297
+ align?: TableCellAlign
298
+ /** Header-only alignment override. Defaults to `align`. */
299
+ headerAlign?: TableCellAlign
300
+ /** Fixed column width. Omit to let the column flex. */
301
+ width?: number
302
+ /** Flex-grow weight when `width` is not set. @default 1 */
303
+ flex?: number
304
+ /** Custom cell renderer. Falls back to `row[key]` as text. */
305
+ render?: (row: T, rowIndex: number) => React.ReactNode
306
+ }
307
+
308
+ export type TableProps<T = Record<string, unknown>> = {
309
+ /** Column definitions for the data-driven API. */
310
+ columns?: TableColumn<T>[]
311
+ /** Row records, one per table row. */
312
+ data?: T[]
313
+ /**
314
+ * Composition children (`Table.Header`, `Table.Body`, `Table.Row`,
315
+ * `Table.Cell`, `Table.HeaderCell`). When provided, `columns`/`data` are
316
+ * ignored and the children are rendered as-is.
317
+ */
318
+ children?: React.ReactNode
319
+ /** Show the header row in the data-driven API. @default true */
320
+ showHeader?: boolean
321
+ /** Resolve a stable key per row. Defaults to the row index. */
322
+ getRowKey?: (row: T, index: number) => React.Key
323
+ /** Called when a row is pressed (data-driven API). Makes rows pressable. */
324
+ onRowPress?: (row: T, index: number) => void
325
+ /**
326
+ * Wrap the table in a horizontal `ScrollView`. Use with fixed-width columns
327
+ * for wide tables that exceed the viewport on mobile. @default false
328
+ */
329
+ scrollable?: boolean
330
+ /** Accessibility label for the table container. */
331
+ accessibilityLabel?: string
332
+ /** Design token modes for theming (e.g. `{ "Color Mode": "Light" }`). */
333
+ modes?: Modes
334
+ /** Override the outer container style. */
335
+ style?: StyleProp<ViewStyle>
336
+ }
337
+
338
+ /**
339
+ * Table renders structured rows and columns. It supports two complementary
340
+ * usage styles that share the same token-driven styling:
341
+ *
342
+ * 1. **Data-driven** (recommended): pass `columns` + `data`. The header and body
343
+ * are built for you, columns stay aligned, and per-column `align`/`width`/
344
+ * `flex`/`render` give full control.
345
+ *
346
+ * 2. **Composition**: pass `Table.Header` / `Table.Body` / `Table.Row` /
347
+ * `Table.Cell` / `Table.HeaderCell` as children for bespoke layouts. These
348
+ * sub-components are also exported standalone.
349
+ *
350
+ * Implementation of Figma node `5732:3710` (`Table`) with sub-components
351
+ * `603:23` (`table-cell`) and `603:21` (`table header wrap`).
352
+ *
353
+ * @component
354
+ */
355
+ function Table<T = Record<string, unknown>>({
356
+ columns,
357
+ data,
358
+ children,
359
+ showHeader = true,
360
+ getRowKey,
361
+ onRowPress,
362
+ scrollable = false,
363
+ accessibilityLabel,
364
+ modes = EMPTY_MODES,
365
+ style,
366
+ }: TableProps<T>) {
367
+ const isComposition = children != null
368
+
369
+ const body = isComposition ? (
370
+ cloneChildrenWithModes(children, modes)
371
+ ) : (
372
+ <>
373
+ {showHeader && columns && columns.length > 0 && (
374
+ <TableHeader modes={modes}>
375
+ {columns.map((col) => (
376
+ <TableHeaderCell
377
+ key={col.key}
378
+ align={col.headerAlign ?? col.align ?? 'left'}
379
+ width={col.width}
380
+ flex={col.flex ?? 1}
381
+ modes={modes}
382
+ >
383
+ {col.header ?? col.key}
384
+ </TableHeaderCell>
385
+ ))}
386
+ </TableHeader>
387
+ )}
388
+ {columns && data && data.length > 0 && (
389
+ <TableBody modes={modes}>
390
+ {data.map((row, rowIndex) => {
391
+ const isLastRow = rowIndex === data.length - 1
392
+ return (
393
+ <TableRow
394
+ key={getRowKey?.(row, rowIndex) ?? rowIndex}
395
+ onPress={onRowPress ? () => onRowPress(row, rowIndex) : undefined}
396
+ modes={modes}
397
+ >
398
+ {columns.map((col, colIndex) => (
399
+ <TableCell
400
+ key={col.key}
401
+ align={col.align ?? 'left'}
402
+ width={col.width}
403
+ flex={col.flex ?? 1}
404
+ isLastColumn={colIndex === columns.length - 1}
405
+ isLastRow={isLastRow}
406
+ modes={modes}
407
+ >
408
+ {col.render
409
+ ? col.render(row, rowIndex)
410
+ : (row as Record<string, unknown>)[col.key] as React.ReactNode}
411
+ </TableCell>
412
+ ))}
413
+ </TableRow>
414
+ )
415
+ })}
416
+ </TableBody>
417
+ )}
418
+ </>
419
+ )
420
+
421
+ const container = (
422
+ <View
423
+ accessibilityRole={Platform.OS === 'web' ? ('table' as any) : undefined}
424
+ accessibilityLabel={accessibilityLabel}
425
+ style={[{ overflow: 'hidden' }, !scrollable && { width: '100%' }, style]}
426
+ >
427
+ {body}
428
+ </View>
429
+ )
430
+
431
+ if (scrollable) {
432
+ return (
433
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
434
+ {container}
435
+ </ScrollView>
436
+ )
437
+ }
438
+ return container
439
+ }
440
+
441
+ Table.Header = TableHeader
442
+ Table.HeaderCell = TableHeaderCell
443
+ Table.Body = TableBody
444
+ Table.Row = TableRow
445
+ Table.Cell = TableCell
446
+
447
+ export { TableHeader, TableHeaderCell, TableBody, TableRow, TableCell }
448
+
449
+ export default Table
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
  import { Text as RNText, type TextStyle, type StyleProp } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
- import { EMPTY_MODES } from '../../utils/react-utils'
4
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
5
5
  import Skeleton from '../../skeleton/Skeleton'
6
6
  import { useSkeleton } from '../../skeleton/SkeletonGroup'
7
7
  import type { Modes } from '../../design-tokens'
@@ -26,6 +26,12 @@ export type TextProps = {
26
26
  style?: StyleProp<TextStyle>
27
27
  /** Number of lines to limit the text to. */
28
28
  numberOfLines?: number
29
+ /**
30
+ * When `true`, disables text truncation entirely: the trailing ellipsis (`…`)
31
+ * is never shown and any `numberOfLines` clamp is ignored, so the text wraps
32
+ * to as many lines as it needs even when horizontal space is tight.
33
+ */
34
+ disableTruncation?: boolean
29
35
  /**
30
36
  * Explicit per-instance loading override. When `true`, this `Text` renders
31
37
  * a skeleton placeholder regardless of any surrounding `<SkeletonGroup>`.
@@ -59,6 +65,7 @@ function Text({
59
65
  modes = EMPTY_MODES,
60
66
  style,
61
67
  numberOfLines,
68
+ disableTruncation,
62
69
  loading,
63
70
  skeletonWidth,
64
71
  skeletonLines,
@@ -124,7 +131,7 @@ function Text({
124
131
  return (
125
132
  <RNText
126
133
  style={[textStyle, style]}
127
- numberOfLines={numberOfLines}
134
+ {...resolveTruncation(disableTruncation, numberOfLines)}
128
135
  >
129
136
  {content}
130
137
  </RNText>