jfs-components 0.1.8 → 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 (238) hide show
  1. package/CHANGELOG.md +16 -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/AreaLineChart/AreaLineChart.js +11 -7
  7. package/lib/commonjs/components/Badge/Badge.js +47 -8
  8. package/lib/commonjs/components/BrandChip/BrandChip.js +3 -3
  9. package/lib/commonjs/components/Button/Button.js +2 -1
  10. package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +2 -1
  11. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +3 -2
  12. package/lib/commonjs/components/CardCTA/CardCTA.js +197 -27
  13. package/lib/commonjs/components/CardInsight/CardInsight.js +5 -1
  14. package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +7 -3
  15. package/lib/commonjs/components/CircularProgressBarDoted/CircularProgressBarDoted.js +3 -2
  16. package/lib/commonjs/components/CircularRating/CircularRating.js +2 -1
  17. package/lib/commonjs/components/ClusterBubble/ClusterBubble.js +3 -2
  18. package/lib/commonjs/components/CompareTable/CompareTable.js +72 -43
  19. package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +3 -2
  20. package/lib/commonjs/components/DonutChart/DonutChart.js +4 -3
  21. package/lib/commonjs/components/Dropdown/Dropdown.js +3 -2
  22. package/lib/commonjs/components/DropdownInput/DropdownInput.js +3 -2
  23. package/lib/commonjs/components/ExpandableCheckbox/ExpandableCheckbox.js +2 -1
  24. package/lib/commonjs/components/FormField/FormField.js +42 -2
  25. package/lib/commonjs/components/Gauge/Gauge.js +1 -1
  26. package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +3 -2
  27. package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +2 -1
  28. package/lib/commonjs/components/ListGroup/ListGroup.js +2 -1
  29. package/lib/commonjs/components/ListItem/ListItem.js +3 -2
  30. package/lib/commonjs/components/MediaCard/MediaCard.js +4 -2
  31. package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +3 -2
  32. package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +6 -3
  33. package/lib/commonjs/components/PoweredByLabel/PoweredByLabel.js +3 -2
  34. package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +107 -33
  35. package/lib/commonjs/components/ProductOverview/ProductOverview.js +4 -3
  36. package/lib/commonjs/components/ProgressBadge/ProgressBadge.js +2 -2
  37. package/lib/commonjs/components/ProjectionMarker/ProjectionMarker.js +3 -2
  38. package/lib/commonjs/components/Section/Section.js +3 -2
  39. package/lib/commonjs/components/Slider/Slider.js +3 -2
  40. package/lib/commonjs/components/Stack/Stack.js +86 -0
  41. package/lib/commonjs/components/SuggestiveSearch/SuggestiveSearch.js +10 -1
  42. package/lib/commonjs/components/SummaryTile/SummaryTile.js +3 -2
  43. package/lib/commonjs/components/Table/Table.js +324 -0
  44. package/lib/commonjs/components/Text/Text.js +2 -1
  45. package/lib/commonjs/components/TextInput/TextInput.js +9 -1
  46. package/lib/commonjs/components/TextSegment/TextSegment.js +2 -1
  47. package/lib/commonjs/components/ThreadHero/ThreadHero.js +4 -5
  48. package/lib/commonjs/components/Title/Title.js +2 -1
  49. package/lib/commonjs/components/Toast/Toast.js +3 -2
  50. package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +2 -1
  51. package/lib/commonjs/components/TransactionStatus/TransactionStatus.js +3 -2
  52. package/lib/commonjs/components/UpiHandle/UpiHandle.js +2 -2
  53. package/lib/commonjs/components/index.js +44 -0
  54. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  55. package/lib/commonjs/design-tokens/figma-modes.generated.js +1 -0
  56. package/lib/commonjs/icons/registry.js +1 -1
  57. package/lib/commonjs/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.js +11 -3
  58. package/lib/commonjs/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.web.js +8 -4
  59. package/lib/commonjs/utils/react-utils.js +56 -0
  60. package/lib/commonjs/utils/web-platform-utils.js +59 -0
  61. package/lib/module/components/Accordion/Accordion.js +3 -2
  62. package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +5 -4
  63. package/lib/module/components/AccountCard/AccountCard.js +5 -4
  64. package/lib/module/components/AllocationComparisonChart/AllocationComparisonChart.js +10 -7
  65. package/lib/module/components/AreaLineChart/AreaLineChart.js +12 -8
  66. package/lib/module/components/Badge/Badge.js +49 -10
  67. package/lib/module/components/BrandChip/BrandChip.js +4 -4
  68. package/lib/module/components/Button/Button.js +3 -2
  69. package/lib/module/components/CardAdvisory/CardAdvisory.js +3 -2
  70. package/lib/module/components/CardBankAccount/CardBankAccount.js +4 -3
  71. package/lib/module/components/CardCTA/CardCTA.js +198 -28
  72. package/lib/module/components/CardInsight/CardInsight.js +5 -1
  73. package/lib/module/components/CircularProgressBar/CircularProgressBar.js +8 -4
  74. package/lib/module/components/CircularProgressBarDoted/CircularProgressBarDoted.js +4 -3
  75. package/lib/module/components/CircularRating/CircularRating.js +3 -2
  76. package/lib/module/components/ClusterBubble/ClusterBubble.js +4 -3
  77. package/lib/module/components/CompareTable/CompareTable.js +73 -44
  78. package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +4 -3
  79. package/lib/module/components/DonutChart/DonutChart.js +5 -4
  80. package/lib/module/components/Dropdown/Dropdown.js +4 -3
  81. package/lib/module/components/DropdownInput/DropdownInput.js +4 -3
  82. package/lib/module/components/ExpandableCheckbox/ExpandableCheckbox.js +2 -1
  83. package/lib/module/components/FormField/FormField.js +45 -5
  84. package/lib/module/components/Gauge/Gauge.js +1 -1
  85. package/lib/module/components/HoldingsCard/HoldingsCard.js +4 -3
  86. package/lib/module/components/InstitutionBadge/InstitutionBadge.js +3 -2
  87. package/lib/module/components/ListGroup/ListGroup.js +3 -2
  88. package/lib/module/components/ListItem/ListItem.js +4 -3
  89. package/lib/module/components/MediaCard/MediaCard.js +4 -2
  90. package/lib/module/components/MetricLegendItem/MetricLegendItem.js +4 -3
  91. package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +7 -4
  92. package/lib/module/components/PoweredByLabel/PoweredByLabel.js +4 -3
  93. package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +109 -35
  94. package/lib/module/components/ProductOverview/ProductOverview.js +5 -4
  95. package/lib/module/components/ProgressBadge/ProgressBadge.js +3 -3
  96. package/lib/module/components/ProjectionMarker/ProjectionMarker.js +4 -3
  97. package/lib/module/components/Section/Section.js +4 -3
  98. package/lib/module/components/Slider/Slider.js +4 -3
  99. package/lib/module/components/Stack/Stack.js +81 -0
  100. package/lib/module/components/SuggestiveSearch/SuggestiveSearch.js +10 -1
  101. package/lib/module/components/SummaryTile/SummaryTile.js +4 -3
  102. package/lib/module/components/Table/Table.js +315 -0
  103. package/lib/module/components/Text/Text.js +3 -2
  104. package/lib/module/components/TextInput/TextInput.js +9 -1
  105. package/lib/module/components/TextSegment/TextSegment.js +3 -2
  106. package/lib/module/components/ThreadHero/ThreadHero.js +5 -6
  107. package/lib/module/components/Title/Title.js +3 -2
  108. package/lib/module/components/Toast/Toast.js +4 -3
  109. package/lib/module/components/TransactionBubble/TransactionBubble.js +3 -2
  110. package/lib/module/components/TransactionStatus/TransactionStatus.js +4 -3
  111. package/lib/module/components/UpiHandle/UpiHandle.js +3 -3
  112. package/lib/module/components/index.js +2 -0
  113. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  114. package/lib/module/design-tokens/figma-modes.generated.js +1 -0
  115. package/lib/module/icons/registry.js +1 -1
  116. package/lib/module/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.js +11 -3
  117. package/lib/module/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.web.js +8 -4
  118. package/lib/module/utils/react-utils.js +54 -0
  119. package/lib/module/utils/web-platform-utils.js +58 -0
  120. package/lib/typescript/src/components/Accordion/Accordion.d.ts +7 -1
  121. package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +7 -1
  122. package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +7 -1
  123. package/lib/typescript/src/components/AllocationComparisonChart/AllocationComparisonChart.d.ts +7 -1
  124. package/lib/typescript/src/components/AreaLineChart/AreaLineChart.d.ts +8 -1
  125. package/lib/typescript/src/components/Badge/Badge.d.ts +32 -2
  126. package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +7 -1
  127. package/lib/typescript/src/components/Button/Button.d.ts +7 -1
  128. package/lib/typescript/src/components/CardAdvisory/CardAdvisory.d.ts +7 -1
  129. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +7 -1
  130. package/lib/typescript/src/components/CardCTA/CardCTA.d.ts +27 -5
  131. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +7 -1
  132. package/lib/typescript/src/components/CircularProgressBarDoted/CircularProgressBarDoted.d.ts +7 -1
  133. package/lib/typescript/src/components/CircularRating/CircularRating.d.ts +7 -1
  134. package/lib/typescript/src/components/ClusterBubble/ClusterBubble.d.ts +7 -1
  135. package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +7 -1
  136. package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +7 -1
  137. package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +7 -1
  138. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +7 -1
  139. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +6 -0
  140. package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +7 -1
  141. package/lib/typescript/src/components/HoldingsCard/HoldingsCard.d.ts +7 -1
  142. package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +7 -1
  143. package/lib/typescript/src/components/ListGroup/ListGroup.d.ts +7 -1
  144. package/lib/typescript/src/components/ListItem/ListItem.d.ts +7 -1
  145. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +7 -1
  146. package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +14 -2
  147. package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +7 -1
  148. package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +7 -1
  149. package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +7 -1
  150. package/lib/typescript/src/components/ProgressBadge/ProgressBadge.d.ts +7 -1
  151. package/lib/typescript/src/components/ProjectionMarker/ProjectionMarker.d.ts +7 -1
  152. package/lib/typescript/src/components/Section/Section.d.ts +7 -1
  153. package/lib/typescript/src/components/Slider/Slider.d.ts +6 -0
  154. package/lib/typescript/src/components/Stack/Stack.d.ts +81 -0
  155. package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +7 -1
  156. package/lib/typescript/src/components/Table/Table.d.ts +139 -0
  157. package/lib/typescript/src/components/Text/Text.d.ts +7 -1
  158. package/lib/typescript/src/components/TextSegment/TextSegment.d.ts +7 -1
  159. package/lib/typescript/src/components/ThreadHero/ThreadHero.d.ts +7 -1
  160. package/lib/typescript/src/components/Title/Title.d.ts +7 -1
  161. package/lib/typescript/src/components/Toast/Toast.d.ts +7 -1
  162. package/lib/typescript/src/components/TransactionBubble/TransactionBubble.d.ts +7 -1
  163. package/lib/typescript/src/components/TransactionStatus/TransactionStatus.d.ts +7 -1
  164. package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +7 -1
  165. package/lib/typescript/src/components/index.d.ts +4 -2
  166. package/lib/typescript/src/icons/registry.d.ts +1 -1
  167. package/lib/typescript/src/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.d.ts +31 -3
  168. package/lib/typescript/src/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.web.d.ts +18 -2
  169. package/lib/typescript/src/utils/react-utils.d.ts +37 -0
  170. package/lib/typescript/src/utils/web-platform-utils.d.ts +36 -0
  171. package/package.json +1 -1
  172. package/src/components/Accordion/Accordion.tsx +9 -2
  173. package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +10 -3
  174. package/src/components/AccountCard/AccountCard.tsx +10 -3
  175. package/src/components/AllocationComparisonChart/AllocationComparisonChart.tsx +14 -4
  176. package/src/components/AreaLineChart/AreaLineChart.tsx +15 -5
  177. package/src/components/Badge/Badge.tsx +78 -8
  178. package/src/components/BrandChip/BrandChip.tsx +9 -3
  179. package/src/components/Button/Button.tsx +9 -2
  180. package/src/components/CardAdvisory/CardAdvisory.tsx +9 -2
  181. package/src/components/CardBankAccount/CardBankAccount.tsx +9 -2
  182. package/src/components/CardCTA/CardCTA.tsx +214 -41
  183. package/src/components/CardInsight/CardInsight.tsx +7 -1
  184. package/src/components/CircularProgressBar/CircularProgressBar.tsx +14 -4
  185. package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +10 -3
  186. package/src/components/CircularRating/CircularRating.tsx +9 -2
  187. package/src/components/ClusterBubble/ClusterBubble.tsx +9 -2
  188. package/src/components/CompareTable/CompareTable.tsx +98 -50
  189. package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +9 -2
  190. package/src/components/DonutChart/DonutChart.tsx +10 -3
  191. package/src/components/Dropdown/Dropdown.tsx +9 -2
  192. package/src/components/DropdownInput/DropdownInput.tsx +9 -2
  193. package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +8 -1
  194. package/src/components/FormField/FormField.tsx +49 -4
  195. package/src/components/Gauge/Gauge.tsx +1 -1
  196. package/src/components/HoldingsCard/HoldingsCard.tsx +9 -2
  197. package/src/components/InstitutionBadge/InstitutionBadge.tsx +9 -2
  198. package/src/components/ListGroup/ListGroup.tsx +9 -2
  199. package/src/components/ListItem/ListItem.tsx +10 -3
  200. package/src/components/MediaCard/MediaCard.tsx +2 -2
  201. package/src/components/MetricLegendItem/MetricLegendItem.tsx +9 -2
  202. package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +17 -2
  203. package/src/components/PoweredByLabel/PoweredByLabel.tsx +9 -2
  204. package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +104 -37
  205. package/src/components/ProductOverview/ProductOverview.tsx +10 -3
  206. package/src/components/ProgressBadge/ProgressBadge.tsx +9 -3
  207. package/src/components/ProjectionMarker/ProjectionMarker.tsx +9 -2
  208. package/src/components/Section/Section.tsx +10 -3
  209. package/src/components/Slider/Slider.tsx +9 -2
  210. package/src/components/Stack/Stack.tsx +131 -0
  211. package/src/components/SuggestiveSearch/SuggestiveSearch.tsx +10 -1
  212. package/src/components/SummaryTile/SummaryTile.tsx +9 -2
  213. package/src/components/Table/Table.tsx +449 -0
  214. package/src/components/Text/Text.tsx +9 -2
  215. package/src/components/TextInput/TextInput.tsx +7 -1
  216. package/src/components/TextSegment/TextSegment.tsx +9 -2
  217. package/src/components/ThreadHero/ThreadHero.tsx +10 -3
  218. package/src/components/Title/Title.tsx +9 -2
  219. package/src/components/Toast/Toast.tsx +9 -2
  220. package/src/components/TransactionBubble/TransactionBubble.tsx +9 -2
  221. package/src/components/TransactionStatus/TransactionStatus.tsx +9 -2
  222. package/src/components/UpiHandle/UpiHandle.tsx +9 -3
  223. package/src/components/index.ts +23 -2
  224. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  225. package/src/design-tokens/figma-modes.generated.ts +1 -0
  226. package/src/icons/registry.ts +1 -1
  227. package/src/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.tsx +32 -3
  228. package/src/{components/ProductMerchandisingCard → utils/GlassFill}/GlassFill.web.tsx +25 -4
  229. package/src/utils/react-utils.ts +61 -0
  230. package/src/utils/web-platform-utils.ts +68 -0
  231. package/lib/commonjs/components/MediaCard/GlassFill.js +0 -62
  232. package/lib/commonjs/components/MediaCard/GlassFill.web.js +0 -48
  233. package/lib/module/components/MediaCard/GlassFill.js +0 -57
  234. package/lib/module/components/MediaCard/GlassFill.web.js +0 -43
  235. package/lib/typescript/src/components/MediaCard/GlassFill.d.ts +0 -47
  236. package/lib/typescript/src/components/MediaCard/GlassFill.web.d.ts +0 -20
  237. package/src/components/MediaCard/GlassFill.tsx +0 -89
  238. package/src/components/MediaCard/GlassFill.web.tsx +0 -53
@@ -13,7 +13,7 @@ import {
13
13
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
14
14
  import NavArrow from '../NavArrow/NavArrow'
15
15
  import { usePressableWebSupport, type WebAccessibilityProps } from '../../utils/web-platform-utils'
16
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
16
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
17
17
  import type { Modes } from '../../design-tokens'
18
18
 
19
19
  type ListItemProps = {
@@ -45,6 +45,12 @@ type ListItemProps = {
45
45
  * Web-specific accessibility props (only used on web platform)
46
46
  */
47
47
  webAccessibilityProps?: WebAccessibilityProps;
48
+ /**
49
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
50
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
51
+ * lines as it needs even when horizontal space is tight.
52
+ */
53
+ disableTruncation?: boolean;
48
54
  } & React.ComponentProps<typeof View>;
49
55
 
50
56
  // ---------------------------------------------------------------------------
@@ -230,6 +236,7 @@ function ListItemImpl({
230
236
  accessibilityHint,
231
237
  accessibilityState,
232
238
  webAccessibilityProps,
239
+ disableTruncation,
233
240
  ...rest
234
241
  }: ListItemProps) {
235
242
  const tokens = useMemo(() => resolveListItemTokens(modes), [modes])
@@ -314,7 +321,7 @@ function ListItemImpl({
314
321
  ? [tokens.supportTextStyle, verticalSupportTextOverride]
315
322
  : tokens.supportTextStyle
316
323
  }
317
- numberOfLines={layout === 'Horizontal' ? 2 : undefined}
324
+ {...resolveTruncation(disableTruncation, layout === 'Horizontal' ? 2 : undefined)}
318
325
  >
319
326
  {displayText}
320
327
  </Text>
@@ -382,7 +389,7 @@ function ListItemImpl({
382
389
  >
383
390
  <Text
384
391
  style={tokens.titleTextStyle}
385
- numberOfLines={1}
392
+ {...resolveTruncation(disableTruncation, 1)}
386
393
  >
387
394
  {title}
388
395
  </Text>
@@ -2,7 +2,7 @@ import React, { createContext, useContext } from 'react'
2
2
  import { View, Text, StyleSheet, type ViewStyle, type TextStyle, type StyleProp, type ImageSourcePropType } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
4
  import Image from '../Image/Image'
5
- import GlassFill, { type GlassTint } from './GlassFill'
5
+ import GlassFill, { type GlassTint } from '../../utils/GlassFill/GlassFill'
6
6
  import { EMPTY_MODES } from '../../utils/react-utils'
7
7
  import type { Modes } from '../../design-tokens'
8
8
 
@@ -225,7 +225,7 @@ export function Footer({ children, style, modes: propModes }: { children?: React
225
225
  ]}
226
226
  pointerEvents="box-none"
227
227
  >
228
- <GlassFill tint={tint} intensity={intensity} overlayColor={glassBgColor} />
228
+ <GlassFill tint={tint} intensity={intensity} overlayColor={glassBgColor} webBlurScale={0.3} webBlurMaxPx={30} />
229
229
 
230
230
  <View
231
231
  style={{
@@ -7,7 +7,7 @@ import {
7
7
  type TextStyle,
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
- import { EMPTY_MODES } from '../../utils/react-utils'
10
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
11
11
  import type { Modes } from '../../design-tokens'
12
12
 
13
13
  export type MetricLegendItemProps = {
@@ -39,6 +39,12 @@ export type MetricLegendItemProps = {
39
39
  labelStyle?: StyleProp<TextStyle>
40
40
  /** Override the value text styles. */
41
41
  valueStyle?: StyleProp<TextStyle>
42
+ /**
43
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
44
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
45
+ * lines as it needs even when horizontal space is tight.
46
+ */
47
+ disableTruncation?: boolean
42
48
  }
43
49
 
44
50
  /**
@@ -59,6 +65,7 @@ function MetricLegendItem({
59
65
  indicatorStyle,
60
66
  labelStyle,
61
67
  valueStyle,
68
+ disableTruncation,
62
69
  }: MetricLegendItemProps) {
63
70
  const gap = (getVariableByName('metricLegendItem/gap', modes) as number | null) ?? 4
64
71
  const textWrapGap =
@@ -169,7 +176,7 @@ function MetricLegendItem({
169
176
  },
170
177
  valueStyle,
171
178
  ]}
172
- numberOfLines={1}
179
+ {...resolveTruncation(disableTruncation, 1)}
173
180
  >
174
181
  {value}
175
182
  </Text>
@@ -8,7 +8,7 @@ import {
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
10
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
11
- import { EMPTY_MODES } from '../../utils/react-utils'
11
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
12
12
  import MetricLegendItem from '../MetricLegendItem/MetricLegendItem'
13
13
  import type { Modes } from '../../design-tokens'
14
14
 
@@ -83,6 +83,12 @@ export type MonthlyStatusGridProps = {
83
83
  legendStyle?: StyleProp<ViewStyle>
84
84
  /** Accessibility label for the entire component. */
85
85
  accessibilityLabel?: string
86
+ /**
87
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
88
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
89
+ * lines as it needs even when horizontal space is tight.
90
+ */
91
+ disableTruncation?: boolean
86
92
  }
87
93
 
88
94
  const DEFAULT_MONTH_LABELS: readonly string[] = [
@@ -170,6 +176,12 @@ export type CalendarGlyphProps = {
170
176
  labelStyle?: StyleProp<TextStyle>
171
177
  /** Accessibility label. Defaults to `"{label}, {status}"`. */
172
178
  accessibilityLabel?: string
179
+ /**
180
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
181
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
182
+ * lines as it needs even when horizontal space is tight.
183
+ */
184
+ disableTruncation?: boolean
173
185
  }
174
186
 
175
187
  /**
@@ -186,6 +198,7 @@ function CalendarGlyph({
186
198
  style,
187
199
  labelStyle,
188
200
  accessibilityLabel,
201
+ disableTruncation,
189
202
  }: CalendarGlyphProps) {
190
203
  const { modes: globalModes } = useTokens()
191
204
  const modes = React.useMemo(
@@ -244,7 +257,7 @@ function CalendarGlyph({
244
257
  ]}
245
258
  >
246
259
  <Text
247
- numberOfLines={1}
260
+ {...resolveTruncation(disableTruncation, 1)}
248
261
  style={[
249
262
  {
250
263
  color: foreground,
@@ -312,6 +325,7 @@ function MonthlyStatusGrid({
312
325
  labelStyle,
313
326
  legendStyle,
314
327
  accessibilityLabel,
328
+ disableTruncation,
315
329
  }: MonthlyStatusGridProps) {
316
330
  const { modes: globalModes } = useTokens()
317
331
  const modes = React.useMemo(
@@ -391,6 +405,7 @@ function MonthlyStatusGrid({
391
405
  label={label}
392
406
  status={month.status}
393
407
  modes={glyphModes}
408
+ disableTruncation={disableTruncation}
394
409
  {...(glyphStyle !== undefined ? { style: glyphStyle } : {})}
395
410
  {...(labelStyle !== undefined ? { labelStyle } : {})}
396
411
  {...(month.accessibilityLabel !== undefined
@@ -9,7 +9,7 @@ import {
9
9
  } from 'react-native'
10
10
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
11
11
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
12
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
12
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
13
13
  import MediaSource, { type UnifiedSource } from '../../utils/MediaSource'
14
14
  import type { Modes } from '../../design-tokens'
15
15
 
@@ -65,6 +65,12 @@ export type PoweredByLabelProps = {
65
65
  * (which is decorative) does not need to be announced separately.
66
66
  */
67
67
  accessibilityLabel?: string
68
+ /**
69
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
70
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
71
+ * lines as it needs even when horizontal space is tight.
72
+ */
73
+ disableTruncation?: boolean
68
74
  }
69
75
 
70
76
  const toNumber = (value: unknown, fallback: number): number => {
@@ -115,6 +121,7 @@ function PoweredByLabel({
115
121
  textStyle,
116
122
  imageStyle,
117
123
  accessibilityLabel,
124
+ disableTruncation,
118
125
  }: PoweredByLabelProps) {
119
126
  const { modes: globalModes } = useTokens()
120
127
  const modes = useMemo(
@@ -210,7 +217,7 @@ function PoweredByLabel({
210
217
  style={[labelTextStyle, textStyle]}
211
218
  accessibilityElementsHidden={true}
212
219
  importantForAccessibility="no"
213
- numberOfLines={1}
220
+ {...resolveTruncation(disableTruncation, 1)}
214
221
  >
215
222
  {label}
216
223
  </Text>
@@ -4,21 +4,31 @@ import {
4
4
  Text,
5
5
  Pressable,
6
6
  StyleSheet,
7
+ Platform,
8
+ Image as RNImage,
7
9
  type ViewStyle,
8
10
  type TextStyle,
9
11
  type StyleProp,
10
12
  type ImageSourcePropType,
11
13
  } from 'react-native'
14
+ import MaskedView from '@react-native-masked-view/masked-view'
12
15
  import Svg, { Defs, LinearGradient, Stop, Rect } from 'react-native-svg'
13
16
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
14
- import { EMPTY_MODES } from '../../utils/react-utils'
17
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
15
18
  import Avatar from '../Avatar/Avatar'
16
19
  import Badge from '../Badge/Badge'
17
20
  import Button from '../Button/Button'
18
21
  import Image from '../Image/Image'
19
- import GlassFill from './GlassFill'
22
+ import GlassFill from '../../utils/GlassFill/GlassFill'
20
23
  import type { Modes } from '../../design-tokens'
21
24
 
25
+ function normalizeImageSource(
26
+ src: ImageSourcePropType | string | undefined
27
+ ): ImageSourcePropType | undefined {
28
+ if (src == null) return undefined
29
+ return typeof src === 'string' ? { uri: src } : src
30
+ }
31
+
22
32
  export interface ProductMerchandisingCardProps {
23
33
  /**
24
34
  * Background media for the card. Accepts a URL string or any RN
@@ -73,6 +83,12 @@ export interface ProductMerchandisingCardProps {
73
83
  style?: StyleProp<ViewStyle>
74
84
  /** Accessibility label for the card. */
75
85
  accessibilityLabel?: string
86
+ /**
87
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
88
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
89
+ * lines as it needs even when horizontal space is tight.
90
+ */
91
+ disableTruncation?: boolean
76
92
  }
77
93
 
78
94
  /**
@@ -116,10 +132,15 @@ function ProductMerchandisingCard({
116
132
  modes = EMPTY_MODES,
117
133
  style,
118
134
  accessibilityLabel,
135
+ disableTruncation,
119
136
  }: ProductMerchandisingCardProps) {
120
- // Unique gradient id so multiple cards on one (web) document never collide.
137
+ // Unique gradient ids so multiple cards on one (web) document never collide.
121
138
  const rawId = useId()
122
- const scrimId = `pmc-footer-scrim-${rawId.replace(/[^a-zA-Z0-9_-]/g, '')}`
139
+ const safeId = rawId.replace(/[^a-zA-Z0-9_-]/g, '')
140
+ const scrimId = `pmc-footer-scrim-${safeId}`
141
+ const blurMaskId = `pmc-footer-blurmask-${safeId}`
142
+
143
+ const normalizedImageSource = useMemo(() => normalizeImageSource(imageSource), [imageSource])
123
144
 
124
145
  const tokens = useMemo(() => resolveTokens(modes), [modes])
125
146
 
@@ -159,23 +180,26 @@ function ProductMerchandisingCard({
159
180
  )
160
181
  : null
161
182
 
183
+ // The footer "special badge" is now the shared <Badge type="glass">. The
184
+ // hardcoded literals that defined its look (warm frosted overlay, gentle
185
+ // 5px blur, 6/2 padding, 4px radius, weight-500 white label) are preserved
186
+ // 1:1 via the glass overrides + `style`/`labelStyle`, and the optional
187
+ // `specialBadgeIcon` maps to Badge's `leading` slot — so every existing
188
+ // instantiation renders byte-for-byte the same as before.
162
189
  const footerSpecialBadge =
163
190
  specialBadge ??
164
191
  (specialBadgeLabel != null ? (
165
- <View style={styles.specialBadge}>
166
- <GlassFill
167
- tint="light"
168
- intensity={SPECIAL_BADGE_INTENSITY}
169
- overlayColor={SPECIAL_BADGE_BG}
170
- style={styles.specialBadgeFill}
171
- />
172
- {specialBadgeIcon != null ? (
173
- <View style={styles.specialBadgeIcon}>{specialBadgeIcon}</View>
174
- ) : null}
175
- <Text style={tokens.specialBadgeText} numberOfLines={1}>
176
- {specialBadgeLabel}
177
- </Text>
178
- </View>
192
+ <Badge
193
+ type="glass"
194
+ label={specialBadgeLabel}
195
+ leading={specialBadgeIcon}
196
+ glassOverlayColor={SPECIAL_BADGE_BG}
197
+ glassIntensity={SPECIAL_BADGE_INTENSITY}
198
+ modes={modes}
199
+ style={styles.specialBadge}
200
+ labelStyle={tokens.specialBadgeText}
201
+ {...(disableTruncation != null ? { disableTruncation } : null)}
202
+ />
179
203
  ) : null)
180
204
 
181
205
  // The Figma CTA uses the brand "Secondary" appearance (purple fill, white
@@ -209,11 +233,49 @@ function ProductMerchandisingCard({
209
233
  </View>
210
234
 
211
235
  <View style={tokens.footer} pointerEvents="box-none">
212
- {/* Progressive background blur: clear at the top, ramping to a
213
- soft blur at the bottom (native MaskedView+BlurView / web
214
- backdrop-filter + mask-image). */}
215
- <GlassFill tint="dark" intensity={tokens.blurIntensity} progressive />
216
- {/* Transparent -> black gradient scrim, identical on all platforms. */}
236
+ {/* Progressive blur clear at the top of the footer, ramping to
237
+ a soft blur at the bottom. Rather than the unmaintained native
238
+ BlurView (which renders as a flat black tint on Android +
239
+ Fabric and can hide the image on iOS), we reveal a *blurred
240
+ copy of the card's own image* through a vertical gradient
241
+ mask. `Image.blurRadius` is a built-in RN prop with a real
242
+ Gaussian blur on BOTH iOS and Android and needs no native
243
+ module. The blurred copy is pinned to the card's bottom at the
244
+ full card height so it lines up pixel-for-pixel with the
245
+ full-bleed background, and the mask makes the blur swell in
246
+ smoothly toward the bottom (true progressive blur). */}
247
+ {normalizedImageSource != null ? (
248
+ <View style={StyleSheet.absoluteFill} pointerEvents="none">
249
+ <MaskedView
250
+ style={StyleSheet.absoluteFill}
251
+ maskElement={
252
+ <Svg width="100%" height="100%">
253
+ <Defs>
254
+ <LinearGradient id={blurMaskId} x1="0" y1="0" x2="0" y2="1">
255
+ <Stop offset="0" stopColor="#000000" stopOpacity={0} />
256
+ <Stop offset="0.35" stopColor="#000000" stopOpacity={0.5} />
257
+ <Stop offset="0.7" stopColor="#000000" stopOpacity={0.92} />
258
+ <Stop offset="1" stopColor="#000000" stopOpacity={1} />
259
+ </LinearGradient>
260
+ </Defs>
261
+ <Rect x="0" y="0" width="100%" height="100%" fill={`url(#${blurMaskId})`} />
262
+ </Svg>
263
+ }
264
+ >
265
+ <RNImage
266
+ source={normalizedImageSource}
267
+ blurRadius={tokens.imageBlurRadius}
268
+ resizeMode="cover"
269
+ style={{ position: 'absolute', left: 0, right: 0, bottom: 0, width: '100%', height }}
270
+ />
271
+ </MaskedView>
272
+ </View>
273
+ ) : (
274
+ <GlassFill tint="dark" intensity={tokens.blurIntensity} progressive />
275
+ )}
276
+ {/* Transparent -> black gradient scrim for text legibility,
277
+ identical on all platforms. Kept lighter than a solid fill so
278
+ the blurred image stays visible behind the footer text. */}
217
279
  <View style={[StyleSheet.absoluteFill, styles.scrim]} pointerEvents="none">
218
280
  <Svg width="100%" height="100%">
219
281
  <Defs>
@@ -230,11 +292,11 @@ function ProductMerchandisingCard({
230
292
 
231
293
  <View style={styles.footerRow}>
232
294
  <View style={tokens.textWrap}>
233
- <Text style={tokens.title} numberOfLines={1}>
295
+ <Text style={tokens.title} {...resolveTruncation(disableTruncation, 1)}>
234
296
  {title}
235
297
  </Text>
236
298
  {subtitle != null ? (
237
- <Text style={tokens.subtitle} numberOfLines={1}>
299
+ <Text style={tokens.subtitle} {...resolveTruncation(disableTruncation, 1)}>
238
300
  {subtitle}
239
301
  </Text>
240
302
  ) : null}
@@ -286,6 +348,7 @@ const SPECIAL_BADGE_INTENSITY = 17 // ~5px CSS blur / ~2 native blurAmount
286
348
  interface ResolvedTokens {
287
349
  radius: number
288
350
  blurIntensity: number
351
+ imageBlurRadius: number
289
352
  header: ViewStyle
290
353
  footer: ViewStyle
291
354
  textWrap: ViewStyle
@@ -331,9 +394,20 @@ function resolveTokens(modes: Modes): ResolvedTokens {
331
394
  const sbFamily = asStr(getVariableByName('productMerchandisingcard/specialbadge/text/fontfamily', modes), 'JioType Var')
332
395
  const sbWeight = asStr(getVariableByName('productMerchandisingcard/specialbadge/text/fontweight', modes), '500')
333
396
 
397
+ // `Image.blurRadius` is interpreted differently per platform — iOS applies a
398
+ // strong Gaussian while Android's IterativeBoxBlur is gentler at the same
399
+ // numeric radius — so we tune each platform to land on the same perceived
400
+ // "minimal" frosted strength as the Figma design.
401
+ const imageBlurRadius = Platform.select({
402
+ ios: Math.max(6, Math.round(blurRadius * 0.5)),
403
+ android: Math.max(12, Math.round(blurRadius * 0.95)),
404
+ default: Math.max(8, Math.round(blurRadius * 0.6)),
405
+ }) as number
406
+
334
407
  return {
335
408
  radius,
336
409
  blurIntensity: Math.max(0, Math.min(100, Math.round(blurRadius * BLUR_INTENSITY_FACTOR))),
410
+ imageBlurRadius,
337
411
  header: {
338
412
  flexDirection: 'row',
339
413
  alignItems: 'flex-start',
@@ -398,22 +472,15 @@ const styles = StyleSheet.create({
398
472
  // the intended fade strength.
399
473
  opacity: 0.9,
400
474
  },
475
+ // Overrides layered on top of <Badge type="glass">. Badge already supplies
476
+ // the row layout + 4px gap (when a leading icon is present), `overflow:
477
+ // 'hidden'`, `alignSelf: 'flex-start'` and `alignItems: 'center'`; these
478
+ // pin the special badge's literal Figma box (6/2 padding, 4px radius)
479
+ // regardless of the badge size tokens resolved by the active modes.
401
480
  specialBadge: {
402
- flexDirection: 'row',
403
- alignItems: 'center',
404
- gap: 4,
405
481
  paddingHorizontal: 6,
406
482
  paddingVertical: 2,
407
483
  borderRadius: 4,
408
- overflow: 'hidden',
409
- alignSelf: 'flex-start',
410
- },
411
- specialBadgeFill: {
412
- borderRadius: 4,
413
- },
414
- specialBadgeIcon: {
415
- justifyContent: 'center',
416
- alignItems: 'center',
417
484
  },
418
485
  pressed: {
419
486
  opacity: 0.92,
@@ -8,7 +8,7 @@ import {
8
8
  type ImageSourcePropType,
9
9
  } from 'react-native'
10
10
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
11
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
11
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
12
12
  import Image from '../Image/Image'
13
13
  import ProductLabel from '../ProductLabel/ProductLabel'
14
14
  import type { Modes } from '../../design-tokens'
@@ -47,6 +47,12 @@ export type ProductOverviewProps = {
47
47
  * for badges, callouts, etc. Receives the same `modes` as the parent.
48
48
  */
49
49
  children?: React.ReactNode
50
+ /**
51
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
52
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
53
+ * lines as it needs even when horizontal space is tight.
54
+ */
55
+ disableTruncation?: boolean
50
56
  }
51
57
 
52
58
  const DEFAULT_STATS: ProductOverviewStat[] = [
@@ -65,6 +71,7 @@ const ProductOverview = ({
65
71
  modes = EMPTY_MODES,
66
72
  style,
67
73
  children,
74
+ disableTruncation,
68
75
  }: ProductOverviewProps) => {
69
76
  const padding = (getVariableByName('productOverview/padding', modes) as number | null) ?? 24
70
77
  const gap = (getVariableByName('productOverview/gap', modes) as number | null) ?? 12
@@ -220,10 +227,10 @@ const ProductOverview = ({
220
227
  overflow: 'hidden',
221
228
  }}
222
229
  >
223
- <Text style={statValueStyle} numberOfLines={1}>
230
+ <Text style={statValueStyle} {...resolveTruncation(disableTruncation, 1)}>
224
231
  {stat.value}
225
232
  </Text>
226
- <Text style={statLabelStyle} numberOfLines={1}>
233
+ <Text style={statLabelStyle} {...resolveTruncation(disableTruncation, 1)}>
227
234
  {stat.label}
228
235
  </Text>
229
236
  </View>
@@ -8,7 +8,7 @@ import {
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
10
  import Icon from '../../icons/Icon'
11
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
11
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
12
12
  import type { Modes } from '../../design-tokens'
13
13
 
14
14
  export type ProgressBadgeProps = {
@@ -26,6 +26,12 @@ export type ProgressBadgeProps = {
26
26
  textStyle?: StyleProp<TextStyle>
27
27
  /** Accessibility label for screen readers */
28
28
  accessibilityLabel?: string
29
+ /**
30
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
31
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
32
+ * lines as it needs even when horizontal space is tight.
33
+ */
34
+ disableTruncation?: boolean
29
35
  } & React.ComponentProps<typeof View>
30
36
 
31
37
  /**
@@ -51,6 +57,7 @@ function ProgressBadge({
51
57
  style,
52
58
  textStyle: textStyleOverride,
53
59
  accessibilityLabel,
60
+ disableTruncation,
54
61
  ...rest
55
62
  }: ProgressBadgeProps) {
56
63
  // Resolve layout tokens
@@ -158,8 +165,7 @@ function ProgressBadge({
158
165
  ) : null}
159
166
  <Text
160
167
  style={[textStyle, textStyleOverride]}
161
- numberOfLines={1}
162
- ellipsizeMode="tail"
168
+ {...resolveTruncation(disableTruncation, 1, 'tail')}
163
169
  accessibilityElementsHidden={true}
164
170
  importantForAccessibility="no"
165
171
  >
@@ -7,7 +7,7 @@ import {
7
7
  type TextStyle,
8
8
  } from 'react-native'
9
9
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
10
- import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
10
+ import { EMPTY_MODES, cloneChildrenWithModes, resolveTruncation } from '../../utils/react-utils'
11
11
  import type { Modes } from '../../design-tokens'
12
12
  import Divider from '../Divider/Divider'
13
13
 
@@ -61,6 +61,12 @@ export type ProjectionMarkerProps = {
61
61
  rateStyle?: StyleProp<TextStyle>
62
62
  /** Accessibility label for the whole marker. */
63
63
  accessibilityLabel?: string
64
+ /**
65
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
66
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
67
+ * lines as it needs even when horizontal space is tight.
68
+ */
69
+ disableTruncation?: boolean
64
70
  }
65
71
 
66
72
  const isTextValue = (value: React.ReactNode): value is string | number =>
@@ -106,6 +112,7 @@ function ProjectionMarker({
106
112
  durationStyle,
107
113
  rateStyle,
108
114
  accessibilityLabel,
115
+ disableTruncation,
109
116
  }: ProjectionMarkerProps) {
110
117
  const titleColor =
111
118
  (getVariableByName('projectionMarker/title/color', modes) as string | null) ?? '#000000'
@@ -169,7 +176,7 @@ function ProjectionMarker({
169
176
  if (value === null || value === undefined) return null
170
177
  if (isTextValue(value)) {
171
178
  return (
172
- <Text style={[titleTextStyle, overrideStyle]} numberOfLines={1}>
179
+ <Text style={[titleTextStyle, overrideStyle]} {...resolveTruncation(disableTruncation, 1)}>
173
180
  {value}
174
181
  </Text>
175
182
  )
@@ -14,7 +14,7 @@ import NavArrow from '../NavArrow/NavArrow'
14
14
  import IconCapsule from '../IconCapsule/IconCapsule'
15
15
  import ListItem from '../ListItem/ListItem'
16
16
  import { usePressableWebSupport, type WebAccessibilityProps } from '../../utils/web-platform-utils'
17
- import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils'
17
+ import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren, resolveTruncation } from '../../utils/react-utils'
18
18
  import type { Modes } from '../../design-tokens'
19
19
 
20
20
  // Match Button: delay the press visual on iOS so a scroll-cancelled touch
@@ -366,6 +366,12 @@ type SectionProps = {
366
366
  * Web-specific accessibility props (only used on web platform)
367
367
  */
368
368
  webAccessibilityProps?: WebAccessibilityProps;
369
+ /**
370
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
371
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
372
+ * lines as it needs even when horizontal space is tight.
373
+ */
374
+ disableTruncation?: boolean;
369
375
  } & React.ComponentProps<typeof View>;
370
376
 
371
377
  /**
@@ -483,6 +489,7 @@ function Section({
483
489
  accessibilityLabel: _accessibilityLabel,
484
490
  accessibilityHint,
485
491
  webAccessibilityProps,
492
+ disableTruncation,
486
493
  ...rest
487
494
  }: SectionProps) {
488
495
  // Focus and hover are still mirrored in React because they are visible,
@@ -527,7 +534,7 @@ function Section({
527
534
  <View style={headerWrapStyle}>
528
535
  <Text
529
536
  style={tokens.titleStyle}
530
- numberOfLines={1}
537
+ {...resolveTruncation(disableTruncation, 1)}
531
538
  accessibilityElementsHidden={true}
532
539
  importantForAccessibility="no"
533
540
  >
@@ -540,7 +547,7 @@ function Section({
540
547
  {showSupportText && (
541
548
  <Text
542
549
  style={tokens.supportTextStyle}
543
- numberOfLines={2}
550
+ {...resolveTruncation(disableTruncation, 2)}
544
551
  accessibilityElementsHidden={true}
545
552
  importantForAccessibility="no"
546
553
  >
@@ -19,7 +19,7 @@ import {
19
19
  } from 'react-native'
20
20
  import Svg, { Path } from 'react-native-svg'
21
21
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
22
- import { EMPTY_MODES } from '../../utils/react-utils'
22
+ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils'
23
23
  import type { Modes } from '../../design-tokens'
24
24
 
25
25
  /**
@@ -100,6 +100,12 @@ export interface SliderProps {
100
100
  style?: StyleProp<ViewStyle>
101
101
  /** Accessibility label for screen readers. */
102
102
  accessibilityLabel?: string
103
+ /**
104
+ * When `true`, disables text truncation: the trailing ellipsis (`…`) is never
105
+ * shown and any `numberOfLines` clamp is ignored, so the text wraps to as many
106
+ * lines as it needs even when horizontal space is tight.
107
+ */
108
+ disableTruncation?: boolean
103
109
  }
104
110
 
105
111
  const clamp = (n: number, min: number, max: number) => Math.min(Math.max(n, min), max)
@@ -151,6 +157,7 @@ const Slider = forwardRef<SliderHandle, SliderProps>(function Slider(
151
157
  modes = EMPTY_MODES,
152
158
  style,
153
159
  accessibilityLabel,
160
+ disableTruncation,
154
161
  },
155
162
  ref
156
163
  ) {
@@ -365,7 +372,7 @@ const Slider = forwardRef<SliderHandle, SliderProps>(function Slider(
365
372
  {renderTooltip ? (
366
373
  renderTooltip(currentValue)
367
374
  ) : (
368
- <Text style={tokens.tooltipLabel} numberOfLines={1}>
375
+ <Text style={tokens.tooltipLabel} {...resolveTruncation(disableTruncation, 1)}>
369
376
  {valueText}
370
377
  </Text>
371
378
  )}