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,396 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { View, Text, Pressable, Platform } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils';
7
+ import Accordion from '../Accordion/Accordion';
8
+ import Table from '../Table/Table';
9
+ import Image from '../Image/Image';
10
+ import IconButton from '../IconButton/IconButton';
11
+ import Icon from '../../icons/Icon';
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ /**
14
+ * Brand link colour used by the selection-card CTA. The Figma node resolves
15
+ * `button/foreground` to this value, but no reproducible token mode currently
16
+ * produces it (the published token store is out of sync), so it is pinned here
17
+ * to stay faithful to the design.
18
+ */
19
+ const BRAND_LINK_COLOR = '#5d00b5';
20
+
21
+ /**
22
+ * Selection-card close control (Figma node 5568:3492). It is an `IconButton`
23
+ * pinned to the card's top-right corner. The Figma node resolves its
24
+ * `iconButton/background` and border to fully transparent (`#ebebed00` /
25
+ * `#ffffff00`) — values no token mode reproduces — so they are overridden here.
26
+ * Size (40px) and icon are left to the `IconButton`'s own token resolution
27
+ * (padding 11 · 2 + icon 18).
28
+ */
29
+ /** Add-a-card icon button fill + icon (Figma node 5568:3494 direct overrides). */
30
+ const ADD_BUTTON_BG = '#545961';
31
+ const ADD_BUTTON_ICON_COLOR = '#ffffff';
32
+ const closeButtonStyle = {
33
+ position: 'absolute',
34
+ top: 1,
35
+ right: 0,
36
+ backgroundColor: 'transparent',
37
+ borderColor: 'transparent'
38
+ };
39
+
40
+ /** Keeps every text layer on a single line on web. */
41
+ const NO_WRAP_TEXT = {
42
+ flexShrink: 0,
43
+ ...(Platform.OS === 'web' ? {
44
+ whiteSpace: 'nowrap'
45
+ } : {})
46
+ };
47
+ const toWeight = w => typeof w === 'number' ? `${w}` : w;
48
+
49
+ /**
50
+ * A single product/plan column rendered as a selection card at the top of the
51
+ * table. The card order maps 1:1 to each {@link CompareTableRow}'s `values`.
52
+ */
53
+
54
+ /**
55
+ * Value rendered inside a comparison cell.
56
+ * - `string` / `number` → rendered as value text.
57
+ * - `false` → renders the muted "not available" cross icon.
58
+ * - any React element → rendered as-is (e.g. a `Badge`, `MoneyValue`, icon…).
59
+ * - `null` / `undefined` / `true` → empty cell.
60
+ */
61
+
62
+ /**
63
+ * A collapsible section. Each section renders as an `Accordion` whose body is a
64
+ * comparison table that spans the same columns as the selection cards.
65
+ */
66
+
67
+ const DEFAULT_COLUMNS = [{
68
+ label: 'Plan A',
69
+ actionLabel: 'View details',
70
+ onRemove: () => {}
71
+ }, {
72
+ label: 'Plan B',
73
+ actionLabel: 'View details',
74
+ onRemove: () => {}
75
+ }];
76
+ const DEFAULT_SECTIONS = [{
77
+ title: 'Fees & charges',
78
+ header: 'Annual fees',
79
+ defaultExpanded: true,
80
+ rows: [{
81
+ values: ['₹0', '₹499']
82
+ }, {
83
+ values: ['Free', 'Up to ₹1,300']
84
+ }, {
85
+ values: ['1x', '1.25x']
86
+ }]
87
+ }];
88
+
89
+ /**
90
+ * CompareTable renders a product comparison surface: a row of selection cards
91
+ * (one per column) followed by one or more collapsible sections, each holding a
92
+ * comparison table whose cells line up beneath their column.
93
+ *
94
+ * The selection card is an internal sub-component and is intentionally not
95
+ * exported — it should only be used through `CompareTable`. Implementation of
96
+ * Figma node `5568:3496` (`Compare table`) with sub-component `5568:3487`
97
+ * (`selectioncard`).
98
+ *
99
+ * @component
100
+ */
101
+ function CompareTable({
102
+ columns = DEFAULT_COLUMNS,
103
+ sections = DEFAULT_SECTIONS,
104
+ onAddColumn,
105
+ addColumnLabel = 'Add a card',
106
+ maxColumns = 4,
107
+ modes = EMPTY_MODES,
108
+ style,
109
+ disableTruncation
110
+ }) {
111
+ // --- selection card tokens ------------------------------------------------
112
+ const cardBg = getVariableByName('selectionCard/background/color', modes) ?? '#ffffff';
113
+ const cardBorderColor = getVariableByName('selectionCard/border/color', modes) ?? '#eeeeee';
114
+ const cardBorderSize = getVariableByName('selectionCard/border/size', modes) ?? 1;
115
+ const cardGap = getVariableByName('selectionCard/gap', modes) ?? 12;
116
+ const cardPaddingH = getVariableByName('selectionCard/padding/horizontal', modes) ?? 20;
117
+ const cardPaddingV = getVariableByName('selectionCard/padding/vertical', modes) ?? 20;
118
+ const cardLabelColor = getVariableByName('selectionCard/label/color', modes) ?? '#000000';
119
+ const cardLabelFontSize = getVariableByName('selectionCard/label/fontsize', modes) ?? 14;
120
+ const cardLabelFontFamily = getVariableByName('selectionCard/label/fontfamily', modes) ?? 'JioType Var';
121
+ const cardLabelFontWeight = getVariableByName('selectionCard/label/fontweight', modes) ?? 700;
122
+ const imageRadius = getVariableByName('image/radius', modes) ?? 8;
123
+ // `selectionCard/radius` (Figma node 5568:3487) rounds the card corners.
124
+ // The published token store is still out of sync (the variable resolves to
125
+ // `0` in the design), so the read falls back to `0` and will pick up a
126
+ // rounded value automatically once the store syncs.
127
+ const cardRadius = getVariableByName('selectionCard/radius', modes) ?? 0;
128
+
129
+ // --- add-a-card icon button tokens ---------------------------------------
130
+ // padding/size/border come from the shared iconButton tokens; the filled
131
+ // background (#545961) and white icon are the Figma node's direct overrides
132
+ // (no token mode reproduces them), so they are pinned to match the design.
133
+ const addBorderColor = getVariableByName('iconButton/border/color', modes) ?? 'rgba(255,255,255,0)';
134
+ const addBorderSize = getVariableByName('iconButton/border/size', modes) ?? 1;
135
+ const addPadding = getVariableByName('iconButton/padding', modes) ?? 11;
136
+ const addIconSize = getVariableByName('iconButton/icon/size', modes) ?? 18;
137
+ // `iconButton/radius` is the design-token sentinel `9999` ("perfect
138
+ // circle"), mirroring IconButton's own resolution.
139
+ const addRadius = getVariableByName('iconButton/radius', modes) ?? 9999;
140
+ const addBg = ADD_BUTTON_BG;
141
+ const addIconColor = ADD_BUTTON_ICON_COLOR;
142
+
143
+ // --- table header tokens --------------------------------------------------
144
+ const headerBg = getVariableByName('comparetableHeader/background/color', modes) ?? '#f5f5f5';
145
+ const headerLabelColor = getVariableByName('comparetableHeader/label/color', modes) ?? '#000000';
146
+ const headerFontSize = getVariableByName('comparetableHeader/label/fontsize', modes) ?? 14;
147
+ const headerFontFamily = getVariableByName('comparetableHeader/label/fontfamily', modes) ?? 'JioType Var';
148
+ const headerFontWeight = getVariableByName('comparetableHeader/label/fontweight', modes) ?? 600;
149
+ const headerPaddingH = getVariableByName('comparetableHeader/padding/horizontal', modes) ?? 12;
150
+ const headerPaddingV = getVariableByName('comparetableHeader/padding/vertical', modes) ?? 12;
151
+
152
+ // --- table cell tokens ----------------------------------------------------
153
+ const cellBorderColor = getVariableByName('compareTableCell/border/color', modes) ?? '#eeeeee';
154
+ const cellBorderSize = getVariableByName('compareTableCell/border/size', modes) ?? 1;
155
+ const cellBg = getVariableByName('compareTableCell/background/color', modes) ?? '#ffffff';
156
+ const cellLabelColor = getVariableByName('compareTableCell/label/color', modes) ?? '#000000';
157
+ const cellFontSize = getVariableByName('compareTableCell/label/fontsize', modes) ?? 14;
158
+ const cellFontFamily = getVariableByName('compareTableCell/label/fontfamily', modes) ?? 'JioType Var';
159
+ const cellFontWeight = getVariableByName('compareTableCell/label/fontweight', modes) ?? 400;
160
+ const cellPaddingH = getVariableByName('compareTableCell/padding/horizontal', modes) ?? 12;
161
+ const cellPaddingV = getVariableByName('compareTableCell/padding/vertical', modes) ?? 12;
162
+ const columnCount = columns.length;
163
+ const showAddCard = onAddColumn != null && columnCount < maxColumns;
164
+ /** Grid columns shared by the selection-card row and every table row. */
165
+ const gridColumnCount = columnCount + (showAddCard ? 1 : 0);
166
+ const cardLabelStyle = {
167
+ ...NO_WRAP_TEXT,
168
+ color: cardLabelColor,
169
+ fontSize: cardLabelFontSize,
170
+ fontFamily: cardLabelFontFamily,
171
+ fontWeight: toWeight(cardLabelFontWeight),
172
+ lineHeight: cardLabelFontSize * 1.1,
173
+ textAlign: 'center'
174
+ };
175
+ const linkStyle = {
176
+ ...NO_WRAP_TEXT,
177
+ color: BRAND_LINK_COLOR,
178
+ fontFamily: cardLabelFontFamily,
179
+ fontSize: 14,
180
+ fontWeight: '700',
181
+ lineHeight: 22
182
+ };
183
+ const headerTextStyle = {
184
+ color: headerLabelColor,
185
+ fontSize: headerFontSize,
186
+ fontFamily: headerFontFamily,
187
+ fontWeight: toWeight(headerFontWeight)
188
+ };
189
+ const cellTextStyle = {
190
+ color: cellLabelColor,
191
+ fontSize: cellFontSize,
192
+ fontFamily: cellFontFamily,
193
+ fontWeight: toWeight(cellFontWeight)
194
+ };
195
+ const cardStyle = {
196
+ flex: 1,
197
+ minWidth: 0,
198
+ minHeight: 147,
199
+ backgroundColor: cardBg,
200
+ borderRadius: cardRadius,
201
+ alignItems: 'center',
202
+ justifyContent: 'center',
203
+ gap: cardGap,
204
+ paddingHorizontal: cardPaddingH,
205
+ paddingVertical: cardPaddingV
206
+ };
207
+ const renderCard = (column, index) => {
208
+ const isLast = index === columnCount - 1 && !showAddCard;
209
+ return /*#__PURE__*/_jsxs(View, {
210
+ style: [cardStyle, {
211
+ borderBottomWidth: cardBorderSize,
212
+ borderBottomColor: cardBorderColor,
213
+ borderRightWidth: isLast ? 0 : cardBorderSize,
214
+ borderRightColor: cardBorderColor
215
+ }],
216
+ children: [column.imageSource != null && /*#__PURE__*/_jsx(Image, {
217
+ imageSource: column.imageSource,
218
+ width: 66,
219
+ height: 44,
220
+ borderRadius: imageRadius,
221
+ resizeMode: "cover",
222
+ accessibilityLabel: column.label
223
+ }), column.label != null && /*#__PURE__*/_jsx(Text, {
224
+ style: cardLabelStyle,
225
+ ...resolveTruncation(disableTruncation, 2),
226
+ children: column.label
227
+ }), column.actionLabel != null && /*#__PURE__*/_jsx(Pressable, {
228
+ onPress: column.onActionPress,
229
+ accessibilityRole: "button",
230
+ accessibilityLabel: column.actionLabel,
231
+ hitSlop: 6,
232
+ children: /*#__PURE__*/_jsx(Text, {
233
+ style: linkStyle,
234
+ children: column.actionLabel
235
+ })
236
+ }), column.onRemove != null &&
237
+ /*#__PURE__*/
238
+ // Figma node 5568:3492 — an Icon Button (not a capsule):
239
+ // padding 11 + icon 18 → 40px circle, transparent background,
240
+ // absolutely pinned to the card's top-right (right:0, top:1).
241
+ _jsx(IconButton, {
242
+ iconName: "ic_close",
243
+ onPress: column.onRemove,
244
+ modes: modes,
245
+ accessibilityLabel: `Remove ${column.label ?? 'column'}`,
246
+ style: closeButtonStyle
247
+ })]
248
+ }, column.key ?? column.label ?? index);
249
+ };
250
+ const renderAddCard = () => /*#__PURE__*/_jsxs(Pressable, {
251
+ onPress: onAddColumn,
252
+ accessibilityRole: "button",
253
+ accessibilityLabel: addColumnLabel,
254
+ style: [cardStyle, {
255
+ borderBottomWidth: cardBorderSize,
256
+ borderBottomColor: cardBorderColor
257
+ }],
258
+ children: [/*#__PURE__*/_jsx(View, {
259
+ style: {
260
+ width: addPadding * 2 + addIconSize,
261
+ height: addPadding * 2 + addIconSize,
262
+ borderRadius: addRadius,
263
+ borderWidth: addBorderSize,
264
+ borderColor: addBorderColor,
265
+ backgroundColor: addBg,
266
+ alignItems: 'center',
267
+ justifyContent: 'center'
268
+ },
269
+ children: /*#__PURE__*/_jsx(Icon, {
270
+ name: "ic_add",
271
+ size: addIconSize,
272
+ color: addIconColor,
273
+ accessibilityElementsHidden: true,
274
+ importantForAccessibility: "no"
275
+ })
276
+ }), /*#__PURE__*/_jsx(Text, {
277
+ style: cardLabelStyle,
278
+ ...resolveTruncation(disableTruncation, 1),
279
+ children: addColumnLabel
280
+ })]
281
+ }, "__add_card__");
282
+ const renderCellContent = (value, cellKey) => {
283
+ if (value === false) {
284
+ return /*#__PURE__*/_jsx(Icon, {
285
+ name: "ic_close",
286
+ size: cellFontSize + 2,
287
+ color: cellBorderColor
288
+ }, cellKey);
289
+ }
290
+ if (value === null || value === undefined || value === true) {
291
+ return null;
292
+ }
293
+ if (typeof value === 'string' || typeof value === 'number') {
294
+ return /*#__PURE__*/_jsx(Text, {
295
+ style: cellTextStyle,
296
+ children: value
297
+ }, cellKey);
298
+ }
299
+ return cloneChildrenWithModes(value, modes);
300
+ };
301
+
302
+ // Renders a section's comparison grid using the shared `Table` component.
303
+ // CompareTable keeps ownership of token resolution and passes the resolved
304
+ // values as style overrides so the appearance is byte-identical to the
305
+ // previous hand-rolled grid (full outer border + suppressed last-edge
306
+ // dividers), while reusing Table's structure and `modes` cascade.
307
+ //
308
+ // When the "Add a card" tile is visible, each table row appends an empty
309
+ // trailing cell with the same flex weight so data columns stay 1:1 beneath
310
+ // their selection card.
311
+ const renderTableCell = (content, colIndex, isLastRow, key) => {
312
+ const isLastCol = colIndex === gridColumnCount - 1;
313
+ return /*#__PURE__*/_jsx(Table.Cell, {
314
+ modes: modes,
315
+ flex: 1,
316
+ align: "left",
317
+ isLastColumn: isLastCol,
318
+ isLastRow: isLastRow,
319
+ style: {
320
+ backgroundColor: cellBg,
321
+ borderColor: cellBorderColor,
322
+ borderRightWidth: isLastCol ? 0 : cellBorderSize,
323
+ borderBottomWidth: isLastRow ? 0 : cellBorderSize,
324
+ paddingHorizontal: cellPaddingH,
325
+ paddingVertical: cellPaddingV
326
+ },
327
+ children: content
328
+ }, key);
329
+ };
330
+ const renderTable = section => /*#__PURE__*/_jsxs(Table, {
331
+ modes: modes,
332
+ style: {
333
+ width: '100%',
334
+ borderWidth: cellBorderSize,
335
+ borderColor: cellBorderColor
336
+ },
337
+ children: [section.header != null && /*#__PURE__*/_jsx(Table.Header, {
338
+ modes: modes,
339
+ style: {
340
+ borderBottomWidth: cellBorderSize,
341
+ borderBottomColor: cellBorderColor
342
+ },
343
+ children: /*#__PURE__*/_jsx(Table.HeaderCell, {
344
+ modes: modes,
345
+ flex: 1,
346
+ style: {
347
+ backgroundColor: headerBg,
348
+ paddingHorizontal: headerPaddingH,
349
+ paddingVertical: headerPaddingV
350
+ },
351
+ children: /*#__PURE__*/_jsx(Text, {
352
+ style: headerTextStyle,
353
+ children: section.header
354
+ })
355
+ })
356
+ }), /*#__PURE__*/_jsx(Table.Body, {
357
+ modes: modes,
358
+ children: section.rows.map((row, rowIndex) => {
359
+ const isLastRow = rowIndex === section.rows.length - 1;
360
+ return /*#__PURE__*/_jsxs(Table.Row, {
361
+ modes: modes,
362
+ children: [Array.from({
363
+ length: columnCount
364
+ }).map((_, colIndex) => renderTableCell(renderCellContent(row.values?.[colIndex], `${rowIndex}-${colIndex}`), colIndex, isLastRow, colIndex)), showAddCard && renderTableCell(null, gridColumnCount - 1, isLastRow, '__add_spacer__')]
365
+ }, row.key ?? rowIndex);
366
+ })
367
+ })]
368
+ });
369
+ return /*#__PURE__*/_jsxs(View, {
370
+ style: [{
371
+ width: '100%',
372
+ backgroundColor: cardBg,
373
+ borderWidth: 1,
374
+ borderColor: '#e8e8e8',
375
+ overflow: 'hidden'
376
+ }, style],
377
+ children: [(columnCount > 0 || showAddCard) && /*#__PURE__*/_jsxs(View, {
378
+ style: {
379
+ flexDirection: 'row',
380
+ width: '100%'
381
+ },
382
+ children: [columns.map(renderCard), showAddCard && renderAddCard()]
383
+ }), /*#__PURE__*/_jsx(View, {
384
+ style: {
385
+ width: '100%'
386
+ },
387
+ children: sections.map((section, index) => /*#__PURE__*/_jsx(Accordion, {
388
+ title: section.title,
389
+ defaultExpanded: section.defaultExpanded ?? index === 0,
390
+ modes: modes,
391
+ children: renderTable(section)
392
+ }, section.key ?? section.title ?? index))
393
+ })]
394
+ });
395
+ }
396
+ export default CompareTable;
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+
3
+ import React, { useMemo } from 'react';
4
+ import { Pressable, View } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
7
+ import { EMPTY_MODES } from '../../utils/react-utils';
8
+ import { usePressableWebSupport } from '../../utils/web-platform-utils';
9
+ import Button from '../Button/Button';
10
+ import Image from '../Image/Image';
11
+ import IconCapsule from '../IconCapsule/IconCapsule';
12
+
13
+ /**
14
+ * A single slot in the {@link ComparisonBar}. Each item is either empty (the
15
+ * "Add" state — a tappable `+` capsule) or filled with an image (the
16
+ * "Image Added" state — the image plus a dismiss capsule in the corner).
17
+ *
18
+ * The presence of {@link ComparisonBarItem.imageSource} is what toggles the
19
+ * state: provide a source to show the image, leave it `undefined`/`null` to
20
+ * show the empty add slot. This keeps the component fully controlled — the
21
+ * `ComparisonBar` never owns the image state itself, so the consumer decides
22
+ * (e.g. after opening a file/asset picker) when and how an item flips between
23
+ * the two states.
24
+ */
25
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
26
+ const ITEM_WIDTH = 45;
27
+ const ITEM_HEIGHT = 44;
28
+ function resolveTokens(modes) {
29
+ const cardGap = getVariableByName('compareFloatCard/gap', modes) ?? 12;
30
+ const cardPadH = getVariableByName('compareFloatCard/padding/horizontal', modes) ?? 12;
31
+ const cardPadV = getVariableByName('compareFloatCard/padding/vertical', modes) ?? 10;
32
+ const cardRadius = getVariableByName('compareFloatCard/radius', modes) ?? 12;
33
+ const cardBackground = getVariableByName('compareFloatCard/background', modes) ?? '#ffffff';
34
+ const cardBorderColor = getVariableByName('compareFloatCard/border/color', modes) ?? '#f5f5f5';
35
+ const itemPadH = getVariableByName('compareCardItem/padding/horizontal', modes) ?? 6;
36
+ const itemPadV = getVariableByName('compareCardItem/padding/vertical', modes) ?? 8;
37
+ const itemRadius = getVariableByName('compareCardItem/radius', modes) ?? 8;
38
+ const itemBackground = getVariableByName('compareCardItem/background', modes) ?? '#ebebed';
39
+ const imageRadius = getVariableByName('image/radius', modes) ?? 8;
40
+ return {
41
+ card: {
42
+ flexDirection: 'row',
43
+ alignItems: 'center',
44
+ gap: cardGap,
45
+ paddingHorizontal: cardPadH,
46
+ paddingVertical: cardPadV,
47
+ borderRadius: cardRadius,
48
+ borderWidth: 1,
49
+ borderColor: cardBorderColor,
50
+ backgroundColor: cardBackground,
51
+ alignSelf: 'flex-start'
52
+ },
53
+ item: {
54
+ width: ITEM_WIDTH,
55
+ height: ITEM_HEIGHT,
56
+ borderRadius: itemRadius,
57
+ backgroundColor: itemBackground,
58
+ paddingHorizontal: itemPadH,
59
+ paddingVertical: itemPadV,
60
+ alignItems: 'center',
61
+ justifyContent: 'center'
62
+ },
63
+ itemImageState: {
64
+ paddingHorizontal: itemPadH,
65
+ paddingVertical: itemPadV
66
+ },
67
+ imageRadius
68
+ };
69
+ }
70
+ /**
71
+ * Internal slot renderer for {@link ComparisonBar}. Intentionally NOT exported
72
+ * — it is meaningless outside of a `ComparisonBar` (its layout, sizing and
73
+ * remove affordance all assume the surrounding card) and is kept private so
74
+ * the public surface stays a single, cohesive component.
75
+ */
76
+ function Additem({
77
+ item,
78
+ index,
79
+ tokens,
80
+ addCapsuleModes,
81
+ closeCapsuleModes,
82
+ onPress,
83
+ onRemove
84
+ }) {
85
+ const hasImage = item.imageSource != null && item.imageSource !== '';
86
+ const id = item.id ?? index;
87
+ const addWebProps = usePressableWebSupport({
88
+ restProps: {},
89
+ onPress: () => onPress?.(id, index),
90
+ disabled: false,
91
+ accessibilityLabel: item.accessibilityLabel ?? 'Add item to comparison'
92
+ });
93
+ const removeWebProps = usePressableWebSupport({
94
+ restProps: {},
95
+ onPress: () => onRemove?.(id, index),
96
+ disabled: false,
97
+ accessibilityLabel: item.accessibilityLabel ?? 'Remove item from comparison'
98
+ });
99
+ if (!hasImage) {
100
+ return /*#__PURE__*/_jsx(Pressable, {
101
+ style: tokens.item,
102
+ accessibilityRole: "button",
103
+ accessibilityLabel: item.accessibilityLabel ?? 'Add item to comparison',
104
+ onPress: () => onPress?.(id, index),
105
+ ...addWebProps,
106
+ children: /*#__PURE__*/_jsx(IconCapsule, {
107
+ iconName: "ic_add",
108
+ modes: addCapsuleModes,
109
+ style: ADD_CAPSULE_STYLE
110
+ })
111
+ });
112
+ }
113
+
114
+ // Mobile-first: the entire filled slot is the remove target, not just the
115
+ // tiny close capsule (which a fingertip struggles to hit). The capsule stays
116
+ // purely as a visual affordance and is marked non-interactive so it never
117
+ // intercepts the press from the surrounding Pressable.
118
+ return /*#__PURE__*/_jsxs(Pressable, {
119
+ style: [tokens.item, tokens.itemImageState],
120
+ accessibilityRole: "button",
121
+ accessibilityLabel: item.accessibilityLabel ?? 'Remove item from comparison',
122
+ onPress: () => onRemove?.(id, index),
123
+ ...removeWebProps,
124
+ children: [/*#__PURE__*/_jsx(Image, {
125
+ imageSource: item.imageSource,
126
+ width: "100%",
127
+ height: "100%",
128
+ borderRadius: tokens.imageRadius,
129
+ resizeMode: "cover",
130
+ accessibilityLabel: item.accessibilityLabel ?? 'Comparison item image'
131
+ }), /*#__PURE__*/_jsx(View, {
132
+ style: CLOSE_CAPSULE_WRAPPER_STYLE,
133
+ pointerEvents: "none",
134
+ children: /*#__PURE__*/_jsx(IconCapsule, {
135
+ iconName: "ic_close",
136
+ modes: closeCapsuleModes
137
+ })
138
+ })]
139
+ });
140
+ }
141
+
142
+ // The Add capsule is the transparent IconCapsule variant from Figma (the gray
143
+ // item box is the visible surface); its size/icon come from the resolved
144
+ // `Icon Capsule Size: S` tokens, we only flatten the background/border here.
145
+ const ADD_CAPSULE_STYLE = {
146
+ backgroundColor: 'transparent',
147
+ borderColor: 'transparent'
148
+ };
149
+
150
+ // Positions the dismiss IconCapsule in the slot's top-right corner. The capsule
151
+ // itself (size/background/icon) is fully token-driven via `closeCapsuleModes`.
152
+ const CLOSE_CAPSULE_WRAPPER_STYLE = {
153
+ position: 'absolute',
154
+ top: 1,
155
+ right: 1
156
+ };
157
+
158
+ // Mode overrides applied on top of the consumer's `modes` for each capsule.
159
+ // These mirror the Figma component's IconCapsule variant selections so the
160
+ // sizing and colours come from design tokens instead of magic numbers.
161
+ const ADD_CAPSULE_MODE_OVERRIDES = {
162
+ 'Icon Capsule Size': 'XS'
163
+ };
164
+ const CLOSE_CAPSULE_MODE_OVERRIDES = {
165
+ AppearanceBrand: 'Neutral',
166
+ Emphasis: 'Medium',
167
+ 'Icon Capsule Size': 'XS'
168
+ };
169
+
170
+ /**
171
+ * ComparisonBar — a floating card that lets a user assemble a set of items to
172
+ * compare, then trigger the comparison.
173
+ *
174
+ * Each slot is fully controlled via its `imageSource`: an empty slot shows a
175
+ * tappable `+` (the "Add" state) and a filled slot shows the image with a
176
+ * dismiss capsule (the "Image Added" state). The component never sources or
177
+ * stores images itself — when an empty slot is pressed it fires `onItemPress`
178
+ * with the item's id/index so the consumer can open whatever picker is
179
+ * appropriate and then update that item's `imageSource` to flip its state.
180
+ * Tapping a filled slot (anywhere on it — a mobile-friendly hit target, with
181
+ * the dismiss capsule as a visual affordance) fires `onItemRemove` so the
182
+ * consumer can clear the source again.
183
+ *
184
+ * @example
185
+ * ```tsx
186
+ * const [items, setItems] = useState<ComparisonBarItem[]>([
187
+ * { id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'd' },
188
+ * ])
189
+ *
190
+ * <ComparisonBar
191
+ * items={items}
192
+ * onItemPress={async (id) => {
193
+ * const uri = await openImagePicker()
194
+ * setItems(prev => prev.map(it => it.id === id ? { ...it, imageSource: uri } : it))
195
+ * }}
196
+ * onItemRemove={(id) =>
197
+ * setItems(prev => prev.map(it => it.id === id ? { ...it, imageSource: null } : it))
198
+ * }
199
+ * onCompare={runComparison}
200
+ * />
201
+ * ```
202
+ */
203
+ function ComparisonBar({
204
+ items,
205
+ onItemPress,
206
+ onItemRemove,
207
+ onCompare,
208
+ compareLabel = 'Compare',
209
+ compareDisabled,
210
+ disableCompareWhenEmpty = true,
211
+ modes: propModes = EMPTY_MODES,
212
+ style
213
+ }) {
214
+ const {
215
+ modes: globalModes
216
+ } = useTokens();
217
+ const modes = useMemo(() => globalModes === EMPTY_MODES && propModes === EMPTY_MODES ? EMPTY_MODES : {
218
+ ...globalModes,
219
+ ...propModes
220
+ }, [globalModes, propModes]);
221
+ const tokens = useMemo(() => resolveTokens(modes), [modes]);
222
+
223
+ // Capsule modes = consumer modes + this component's fixed IconCapsule variant
224
+ // selections. Memoized so each `Additem`'s `IconCapsule` keeps a stable
225
+ // `modes` identity and hits the resolver cache.
226
+ const addCapsuleModes = useMemo(() => ({
227
+ ...modes,
228
+ ...ADD_CAPSULE_MODE_OVERRIDES
229
+ }), [modes]);
230
+ const closeCapsuleModes = useMemo(() => ({
231
+ ...modes,
232
+ ...CLOSE_CAPSULE_MODE_OVERRIDES
233
+ }), [modes]);
234
+
235
+ // An explicit `compareDisabled` always wins (functional disable — the tap is
236
+ // truly blocked, not merely dimmed). Otherwise auto-disable while no slot has
237
+ // an image, since there is nothing to compare yet.
238
+ const hasAnyImage = useMemo(() => items.some(it => it.imageSource != null && it.imageSource !== ''), [items]);
239
+ const isCompareDisabled = compareDisabled ?? (disableCompareWhenEmpty && !hasAnyImage);
240
+ return /*#__PURE__*/_jsxs(View, {
241
+ style: [tokens.card, style],
242
+ children: [items.map((item, index) => /*#__PURE__*/_jsx(Additem, {
243
+ item: item,
244
+ index: index,
245
+ tokens: tokens,
246
+ addCapsuleModes: addCapsuleModes,
247
+ closeCapsuleModes: closeCapsuleModes,
248
+ onPress: onItemPress,
249
+ onRemove: onItemRemove
250
+ }, item.id ?? index)), /*#__PURE__*/_jsx(Button, {
251
+ label: compareLabel,
252
+ modes: modes,
253
+ disabled: isCompareDisabled,
254
+ ...(onCompare !== undefined ? {
255
+ onPress: onCompare
256
+ } : {})
257
+ })]
258
+ });
259
+ }
260
+ export default /*#__PURE__*/React.memo(ComparisonBar);
@@ -5,7 +5,7 @@ import { View, Text } from 'react-native';
5
5
  import Svg, { Rect } from 'react-native-svg';
6
6
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
7
7
  import { useTokens } from '../../design-tokens/JFSThemeProvider';
8
- import { EMPTY_MODES } from '../../utils/react-utils';
8
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils';
9
9
  import MetricLegendItem from '../MetricLegendItem/MetricLegendItem';
10
10
 
11
11
  /**
@@ -136,7 +136,8 @@ function CoverageBarComparison({
136
136
  chartStyle,
137
137
  legendStyle,
138
138
  labelStyle,
139
- accessibilityLabel
139
+ accessibilityLabel,
140
+ disableTruncation
140
141
  }) {
141
142
  const {
142
143
  modes: globalModes
@@ -222,7 +223,7 @@ function CoverageBarComparison({
222
223
  minWidth: 1
223
224
  },
224
225
  children: [hasLabel ? /*#__PURE__*/_jsx(Text, {
225
- numberOfLines: 1,
226
+ ...resolveTruncation(disableTruncation, 1),
226
227
  style: [computedLabelStyle, labelStyle],
227
228
  children: original.label
228
229
  }) : null, /*#__PURE__*/_jsx(BarShape, {