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