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,525 @@
1
+ import React from 'react'
2
+ import {
3
+ View,
4
+ Text,
5
+ Pressable,
6
+ Platform,
7
+ type ImageSourcePropType,
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, resolveTruncation } from '../../utils/react-utils'
14
+ import Accordion from '../Accordion/Accordion'
15
+ import Table from '../Table/Table'
16
+ import Image from '../Image/Image'
17
+ import IconButton from '../IconButton/IconButton'
18
+ import Icon from '../../icons/Icon'
19
+ import type { Modes } from '../../design-tokens'
20
+
21
+ /**
22
+ * Brand link colour used by the selection-card CTA. The Figma node resolves
23
+ * `button/foreground` to this value, but no reproducible token mode currently
24
+ * produces it (the published token store is out of sync), so it is pinned here
25
+ * to stay faithful to the design.
26
+ */
27
+ const BRAND_LINK_COLOR = '#5d00b5'
28
+
29
+ /**
30
+ * Selection-card close control (Figma node 5568:3492). It is an `IconButton`
31
+ * pinned to the card's top-right corner. The Figma node resolves its
32
+ * `iconButton/background` and border to fully transparent (`#ebebed00` /
33
+ * `#ffffff00`) — values no token mode reproduces — so they are overridden here.
34
+ * Size (40px) and icon are left to the `IconButton`'s own token resolution
35
+ * (padding 11 · 2 + icon 18).
36
+ */
37
+ /** Add-a-card icon button fill + icon (Figma node 5568:3494 direct overrides). */
38
+ const ADD_BUTTON_BG = '#545961'
39
+ const ADD_BUTTON_ICON_COLOR = '#ffffff'
40
+
41
+ const closeButtonStyle: ViewStyle = {
42
+ position: 'absolute',
43
+ top: 1,
44
+ right: 0,
45
+ backgroundColor: 'transparent',
46
+ borderColor: 'transparent',
47
+ }
48
+
49
+ /** Keeps every text layer on a single line on web. */
50
+ const NO_WRAP_TEXT: TextStyle = {
51
+ flexShrink: 0,
52
+ ...(Platform.OS === 'web' ? { whiteSpace: 'nowrap' as const } : {}),
53
+ }
54
+
55
+ const toWeight = (w: number | string) =>
56
+ (typeof w === 'number' ? `${w}` : w) as TextStyle['fontWeight']
57
+
58
+ /**
59
+ * A single product/plan column rendered as a selection card at the top of the
60
+ * table. The card order maps 1:1 to each {@link CompareTableRow}'s `values`.
61
+ */
62
+ export type CompareTableColumn = {
63
+ /** Product / plan name shown under the image. */
64
+ label?: string;
65
+ /** Thumbnail / logo image. Accepts a URL string or an RN image source. */
66
+ imageSource?: ImageSourcePropType | string;
67
+ /** CTA link text (e.g. "View details"). Omit to hide the link. */
68
+ actionLabel?: string;
69
+ /** Handler for the CTA link. Implies the link is shown. */
70
+ onActionPress?: () => void;
71
+ /** When provided, renders a tappable close icon to remove the column. */
72
+ onRemove?: () => void;
73
+ /** Stable key. Falls back to the label / index. */
74
+ key?: React.Key;
75
+ };
76
+
77
+ /**
78
+ * Value rendered inside a comparison cell.
79
+ * - `string` / `number` → rendered as value text.
80
+ * - `false` → renders the muted "not available" cross icon.
81
+ * - any React element → rendered as-is (e.g. a `Badge`, `MoneyValue`, icon…).
82
+ * - `null` / `undefined` / `true` → empty cell.
83
+ */
84
+ export type CompareTableCellValue =
85
+ | string
86
+ | number
87
+ | boolean
88
+ | null
89
+ | undefined
90
+ | React.ReactElement;
91
+
92
+ export type CompareTableRow = {
93
+ /** One value per column, in the same order as `columns`. */
94
+ values: CompareTableCellValue[];
95
+ /** Stable key. Falls back to the index. */
96
+ key?: React.Key;
97
+ };
98
+
99
+ /**
100
+ * A collapsible section. Each section renders as an `Accordion` whose body is a
101
+ * comparison table that spans the same columns as the selection cards.
102
+ */
103
+ export type CompareTableSection = {
104
+ /** Accordion header label, e.g. "Fees & charges". */
105
+ title: string;
106
+ /** Optional full-width header row shown at the top of the table body. */
107
+ header?: string;
108
+ /** Comparison rows; each row's `values` map 1:1 to `columns`. */
109
+ rows: CompareTableRow[];
110
+ /** Initial expanded state. Defaults to `true` for the first section. */
111
+ defaultExpanded?: boolean;
112
+ /** Stable key. Falls back to the title / index. */
113
+ key?: React.Key;
114
+ };
115
+
116
+ export type CompareTableProps = {
117
+ /**
118
+ * Product / plan columns rendered as selection cards. Their order maps 1:1
119
+ * to each row's `values` array. Supports any number of columns.
120
+ */
121
+ columns?: CompareTableColumn[];
122
+ /** Collapsible comparison sections. */
123
+ sections?: CompareTableSection[];
124
+ /**
125
+ * When provided, renders an "Add a card" tile after the columns. Hidden once
126
+ * `columns.length` reaches `maxColumns`.
127
+ */
128
+ onAddColumn?: () => void;
129
+ /** Label for the add-a-card tile. @default 'Add a card' */
130
+ addColumnLabel?: string;
131
+ /** Maximum number of columns before the add tile is hidden. @default 4 */
132
+ maxColumns?: number;
133
+ /** Design token modes for theming (e.g. `{ "Color Mode": "Light" }`). */
134
+ modes?: Modes;
135
+ /** Override the outer container style. */
136
+ style?: StyleProp<ViewStyle>;
137
+ /**
138
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
139
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
140
+ * lines as it needs even when horizontal space is tight.
141
+ */
142
+ disableTruncation?: boolean;
143
+ };
144
+
145
+ const DEFAULT_COLUMNS: CompareTableColumn[] = [
146
+ { label: 'Plan A', actionLabel: 'View details', onRemove: () => {} },
147
+ { label: 'Plan B', actionLabel: 'View details', onRemove: () => {} },
148
+ ]
149
+
150
+ const DEFAULT_SECTIONS: CompareTableSection[] = [
151
+ {
152
+ title: 'Fees & charges',
153
+ header: 'Annual fees',
154
+ defaultExpanded: true,
155
+ rows: [
156
+ { values: ['₹0', '₹499'] },
157
+ { values: ['Free', 'Up to ₹1,300'] },
158
+ { values: ['1x', '1.25x'] },
159
+ ],
160
+ },
161
+ ]
162
+
163
+ /**
164
+ * CompareTable renders a product comparison surface: a row of selection cards
165
+ * (one per column) followed by one or more collapsible sections, each holding a
166
+ * comparison table whose cells line up beneath their column.
167
+ *
168
+ * The selection card is an internal sub-component and is intentionally not
169
+ * exported — it should only be used through `CompareTable`. Implementation of
170
+ * Figma node `5568:3496` (`Compare table`) with sub-component `5568:3487`
171
+ * (`selectioncard`).
172
+ *
173
+ * @component
174
+ */
175
+ function CompareTable({
176
+ columns = DEFAULT_COLUMNS,
177
+ sections = DEFAULT_SECTIONS,
178
+ onAddColumn,
179
+ addColumnLabel = 'Add a card',
180
+ maxColumns = 4,
181
+ modes = EMPTY_MODES,
182
+ style,
183
+ disableTruncation,
184
+ }: CompareTableProps) {
185
+ // --- selection card tokens ------------------------------------------------
186
+ const cardBg = (getVariableByName('selectionCard/background/color', modes) as string) ?? '#ffffff'
187
+ const cardBorderColor = (getVariableByName('selectionCard/border/color', modes) as string) ?? '#eeeeee'
188
+ const cardBorderSize = (getVariableByName('selectionCard/border/size', modes) as number) ?? 1
189
+ const cardGap = (getVariableByName('selectionCard/gap', modes) as number) ?? 12
190
+ const cardPaddingH = (getVariableByName('selectionCard/padding/horizontal', modes) as number) ?? 20
191
+ const cardPaddingV = (getVariableByName('selectionCard/padding/vertical', modes) as number) ?? 20
192
+ const cardLabelColor = (getVariableByName('selectionCard/label/color', modes) as string) ?? '#000000'
193
+ const cardLabelFontSize = (getVariableByName('selectionCard/label/fontsize', modes) as number) ?? 14
194
+ const cardLabelFontFamily = (getVariableByName('selectionCard/label/fontfamily', modes) as string) ?? 'JioType Var'
195
+ const cardLabelFontWeight = (getVariableByName('selectionCard/label/fontweight', modes) as number | string) ?? 700
196
+ const imageRadius = (getVariableByName('image/radius', modes) as number) ?? 8
197
+ // `selectionCard/radius` (Figma node 5568:3487) rounds the card corners.
198
+ // The published token store is still out of sync (the variable resolves to
199
+ // `0` in the design), so the read falls back to `0` and will pick up a
200
+ // rounded value automatically once the store syncs.
201
+ const cardRadius = (getVariableByName('selectionCard/radius', modes) as number) ?? 0
202
+
203
+ // --- add-a-card icon button tokens ---------------------------------------
204
+ // padding/size/border come from the shared iconButton tokens; the filled
205
+ // background (#545961) and white icon are the Figma node's direct overrides
206
+ // (no token mode reproduces them), so they are pinned to match the design.
207
+ const addBorderColor = (getVariableByName('iconButton/border/color', modes) as string) ?? 'rgba(255,255,255,0)'
208
+ const addBorderSize = (getVariableByName('iconButton/border/size', modes) as number) ?? 1
209
+ const addPadding = (getVariableByName('iconButton/padding', modes) as number) ?? 11
210
+ const addIconSize = (getVariableByName('iconButton/icon/size', modes) as number) ?? 18
211
+ // `iconButton/radius` is the design-token sentinel `9999` ("perfect
212
+ // circle"), mirroring IconButton's own resolution.
213
+ const addRadius = (getVariableByName('iconButton/radius', modes) as number) ?? 9999
214
+ const addBg = ADD_BUTTON_BG
215
+ const addIconColor = ADD_BUTTON_ICON_COLOR
216
+
217
+ // --- table header tokens --------------------------------------------------
218
+ const headerBg = (getVariableByName('comparetableHeader/background/color', modes) as string) ?? '#f5f5f5'
219
+ const headerLabelColor = (getVariableByName('comparetableHeader/label/color', modes) as string) ?? '#000000'
220
+ const headerFontSize = (getVariableByName('comparetableHeader/label/fontsize', modes) as number) ?? 14
221
+ const headerFontFamily = (getVariableByName('comparetableHeader/label/fontfamily', modes) as string) ?? 'JioType Var'
222
+ const headerFontWeight = (getVariableByName('comparetableHeader/label/fontweight', modes) as number | string) ?? 600
223
+ const headerPaddingH = (getVariableByName('comparetableHeader/padding/horizontal', modes) as number) ?? 12
224
+ const headerPaddingV = (getVariableByName('comparetableHeader/padding/vertical', modes) as number) ?? 12
225
+
226
+ // --- table cell tokens ----------------------------------------------------
227
+ const cellBorderColor = (getVariableByName('compareTableCell/border/color', modes) as string) ?? '#eeeeee'
228
+ const cellBorderSize = (getVariableByName('compareTableCell/border/size', modes) as number) ?? 1
229
+ const cellBg = (getVariableByName('compareTableCell/background/color', modes) as string) ?? '#ffffff'
230
+ const cellLabelColor = (getVariableByName('compareTableCell/label/color', modes) as string) ?? '#000000'
231
+ const cellFontSize = (getVariableByName('compareTableCell/label/fontsize', modes) as number) ?? 14
232
+ const cellFontFamily = (getVariableByName('compareTableCell/label/fontfamily', modes) as string) ?? 'JioType Var'
233
+ const cellFontWeight = (getVariableByName('compareTableCell/label/fontweight', modes) as number | string) ?? 400
234
+ const cellPaddingH = (getVariableByName('compareTableCell/padding/horizontal', modes) as number) ?? 12
235
+ const cellPaddingV = (getVariableByName('compareTableCell/padding/vertical', modes) as number) ?? 12
236
+
237
+ const columnCount = columns.length
238
+ const showAddCard = onAddColumn != null && columnCount < maxColumns
239
+ /** Grid columns shared by the selection-card row and every table row. */
240
+ const gridColumnCount = columnCount + (showAddCard ? 1 : 0)
241
+
242
+ const cardLabelStyle: TextStyle = {
243
+ ...NO_WRAP_TEXT,
244
+ color: cardLabelColor,
245
+ fontSize: cardLabelFontSize,
246
+ fontFamily: cardLabelFontFamily,
247
+ fontWeight: toWeight(cardLabelFontWeight),
248
+ lineHeight: cardLabelFontSize * 1.1,
249
+ textAlign: 'center',
250
+ }
251
+
252
+ const linkStyle: TextStyle = {
253
+ ...NO_WRAP_TEXT,
254
+ color: BRAND_LINK_COLOR,
255
+ fontFamily: cardLabelFontFamily,
256
+ fontSize: 14,
257
+ fontWeight: '700',
258
+ lineHeight: 22,
259
+ }
260
+
261
+ const headerTextStyle: TextStyle = {
262
+ color: headerLabelColor,
263
+ fontSize: headerFontSize,
264
+ fontFamily: headerFontFamily,
265
+ fontWeight: toWeight(headerFontWeight),
266
+ }
267
+
268
+ const cellTextStyle: TextStyle = {
269
+ color: cellLabelColor,
270
+ fontSize: cellFontSize,
271
+ fontFamily: cellFontFamily,
272
+ fontWeight: toWeight(cellFontWeight),
273
+ }
274
+
275
+ const cardStyle: ViewStyle = {
276
+ flex: 1,
277
+ minWidth: 0,
278
+ minHeight: 147,
279
+ backgroundColor: cardBg,
280
+ borderRadius: cardRadius,
281
+ alignItems: 'center',
282
+ justifyContent: 'center',
283
+ gap: cardGap,
284
+ paddingHorizontal: cardPaddingH,
285
+ paddingVertical: cardPaddingV,
286
+ }
287
+
288
+ const renderCard = (column: CompareTableColumn, index: number) => {
289
+ const isLast = index === columnCount - 1 && !showAddCard
290
+ return (
291
+ <View
292
+ key={column.key ?? column.label ?? index}
293
+ style={[
294
+ cardStyle,
295
+ {
296
+ borderBottomWidth: cardBorderSize,
297
+ borderBottomColor: cardBorderColor,
298
+ borderRightWidth: isLast ? 0 : cardBorderSize,
299
+ borderRightColor: cardBorderColor,
300
+ },
301
+ ]}
302
+ >
303
+ {column.imageSource != null && (
304
+ <Image
305
+ imageSource={column.imageSource}
306
+ width={66}
307
+ height={44}
308
+ borderRadius={imageRadius}
309
+ resizeMode="cover"
310
+ accessibilityLabel={column.label}
311
+ />
312
+ )}
313
+ {column.label != null && (
314
+ <Text style={cardLabelStyle} {...resolveTruncation(disableTruncation, 2)}>
315
+ {column.label}
316
+ </Text>
317
+ )}
318
+ {column.actionLabel != null && (
319
+ <Pressable
320
+ onPress={column.onActionPress}
321
+ accessibilityRole="button"
322
+ accessibilityLabel={column.actionLabel}
323
+ hitSlop={6}
324
+ >
325
+ <Text style={linkStyle}>{column.actionLabel}</Text>
326
+ </Pressable>
327
+ )}
328
+ {column.onRemove != null && (
329
+ // Figma node 5568:3492 — an Icon Button (not a capsule):
330
+ // padding 11 + icon 18 → 40px circle, transparent background,
331
+ // absolutely pinned to the card's top-right (right:0, top:1).
332
+ <IconButton
333
+ iconName="ic_close"
334
+ onPress={column.onRemove}
335
+ modes={modes}
336
+ accessibilityLabel={`Remove ${column.label ?? 'column'}`}
337
+ style={closeButtonStyle}
338
+ />
339
+ )}
340
+ </View>
341
+ )
342
+ }
343
+
344
+ const renderAddCard = () => (
345
+ <Pressable
346
+ key="__add_card__"
347
+ onPress={onAddColumn}
348
+ accessibilityRole="button"
349
+ accessibilityLabel={addColumnLabel}
350
+ style={[cardStyle, { borderBottomWidth: cardBorderSize, borderBottomColor: cardBorderColor }]}
351
+ >
352
+ <View
353
+ style={{
354
+ width: addPadding * 2 + addIconSize,
355
+ height: addPadding * 2 + addIconSize,
356
+ borderRadius: addRadius,
357
+ borderWidth: addBorderSize,
358
+ borderColor: addBorderColor,
359
+ backgroundColor: addBg,
360
+ alignItems: 'center',
361
+ justifyContent: 'center',
362
+ }}
363
+ >
364
+ <Icon
365
+ name="ic_add"
366
+ size={addIconSize}
367
+ color={addIconColor}
368
+ accessibilityElementsHidden
369
+ importantForAccessibility="no"
370
+ />
371
+ </View>
372
+ <Text style={cardLabelStyle} {...resolveTruncation(disableTruncation, 1)}>
373
+ {addColumnLabel}
374
+ </Text>
375
+ </Pressable>
376
+ )
377
+
378
+ const renderCellContent = (value: CompareTableCellValue, cellKey: React.Key) => {
379
+ if (value === false) {
380
+ return (
381
+ <Icon
382
+ key={cellKey}
383
+ name="ic_close"
384
+ size={cellFontSize + 2}
385
+ color={cellBorderColor}
386
+ />
387
+ )
388
+ }
389
+ if (value === null || value === undefined || value === true) {
390
+ return null
391
+ }
392
+ if (typeof value === 'string' || typeof value === 'number') {
393
+ return (
394
+ <Text key={cellKey} style={cellTextStyle}>
395
+ {value}
396
+ </Text>
397
+ )
398
+ }
399
+ return cloneChildrenWithModes(value, modes)
400
+ }
401
+
402
+ // Renders a section's comparison grid using the shared `Table` component.
403
+ // CompareTable keeps ownership of token resolution and passes the resolved
404
+ // values as style overrides so the appearance is byte-identical to the
405
+ // previous hand-rolled grid (full outer border + suppressed last-edge
406
+ // dividers), while reusing Table's structure and `modes` cascade.
407
+ //
408
+ // When the "Add a card" tile is visible, each table row appends an empty
409
+ // trailing cell with the same flex weight so data columns stay 1:1 beneath
410
+ // their selection card.
411
+ const renderTableCell = (
412
+ content: React.ReactNode,
413
+ colIndex: number,
414
+ isLastRow: boolean,
415
+ key: React.Key,
416
+ ) => {
417
+ const isLastCol = colIndex === gridColumnCount - 1
418
+ return (
419
+ <Table.Cell
420
+ key={key}
421
+ modes={modes}
422
+ flex={1}
423
+ align="left"
424
+ isLastColumn={isLastCol}
425
+ isLastRow={isLastRow}
426
+ style={{
427
+ backgroundColor: cellBg,
428
+ borderColor: cellBorderColor,
429
+ borderRightWidth: isLastCol ? 0 : cellBorderSize,
430
+ borderBottomWidth: isLastRow ? 0 : cellBorderSize,
431
+ paddingHorizontal: cellPaddingH,
432
+ paddingVertical: cellPaddingV,
433
+ }}
434
+ >
435
+ {content}
436
+ </Table.Cell>
437
+ )
438
+ }
439
+
440
+ const renderTable = (section: CompareTableSection) => (
441
+ <Table
442
+ modes={modes}
443
+ style={{
444
+ width: '100%',
445
+ borderWidth: cellBorderSize,
446
+ borderColor: cellBorderColor,
447
+ }}
448
+ >
449
+ {section.header != null && (
450
+ <Table.Header
451
+ modes={modes}
452
+ style={{ borderBottomWidth: cellBorderSize, borderBottomColor: cellBorderColor }}
453
+ >
454
+ <Table.HeaderCell
455
+ modes={modes}
456
+ flex={1}
457
+ style={{
458
+ backgroundColor: headerBg,
459
+ paddingHorizontal: headerPaddingH,
460
+ paddingVertical: headerPaddingV,
461
+ }}
462
+ >
463
+ <Text style={headerTextStyle}>{section.header}</Text>
464
+ </Table.HeaderCell>
465
+ </Table.Header>
466
+ )}
467
+ <Table.Body modes={modes}>
468
+ {section.rows.map((row, rowIndex) => {
469
+ const isLastRow = rowIndex === section.rows.length - 1
470
+ return (
471
+ <Table.Row key={row.key ?? rowIndex} modes={modes}>
472
+ {Array.from({ length: columnCount }).map((_, colIndex) =>
473
+ renderTableCell(
474
+ renderCellContent(row.values?.[colIndex], `${rowIndex}-${colIndex}`),
475
+ colIndex,
476
+ isLastRow,
477
+ colIndex,
478
+ ),
479
+ )}
480
+ {showAddCard &&
481
+ renderTableCell(null, gridColumnCount - 1, isLastRow, '__add_spacer__')}
482
+ </Table.Row>
483
+ )
484
+ })}
485
+ </Table.Body>
486
+ </Table>
487
+ )
488
+
489
+ return (
490
+ <View
491
+ style={[
492
+ {
493
+ width: '100%',
494
+ backgroundColor: cardBg,
495
+ borderWidth: 1,
496
+ borderColor: '#e8e8e8',
497
+ overflow: 'hidden',
498
+ },
499
+ style,
500
+ ]}
501
+ >
502
+ {(columnCount > 0 || showAddCard) && (
503
+ <View style={{ flexDirection: 'row', width: '100%' }}>
504
+ {columns.map(renderCard)}
505
+ {showAddCard && renderAddCard()}
506
+ </View>
507
+ )}
508
+
509
+ <View style={{ width: '100%' }}>
510
+ {sections.map((section, index) => (
511
+ <Accordion
512
+ key={section.key ?? section.title ?? index}
513
+ title={section.title}
514
+ defaultExpanded={section.defaultExpanded ?? index === 0}
515
+ modes={modes}
516
+ >
517
+ {renderTable(section)}
518
+ </Accordion>
519
+ ))}
520
+ </View>
521
+ </View>
522
+ )
523
+ }
524
+
525
+ export default CompareTable