jfs-components 0.0.71 → 0.0.73
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 +60 -0
- package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +239 -0
- package/lib/commonjs/components/BrandChip/BrandChip.js +149 -0
- package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +2 -2
- package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +213 -0
- package/lib/commonjs/components/CardFinancialCondition/CardFinancialCondition.js +213 -0
- package/lib/commonjs/components/CardInsight/CardInsight.js +166 -0
- package/lib/commonjs/components/Carousel/Carousel.js +9 -7
- package/lib/commonjs/components/CheckboxGroup/CheckboxGroup.js +67 -0
- package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +125 -0
- package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +56 -9
- package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +272 -0
- package/lib/commonjs/components/CoverageRing/CoverageRing.js +141 -0
- package/lib/commonjs/components/DonutChart/DonutChart.js +309 -0
- package/lib/commonjs/components/DonutChartSummary/DonutChartSummary.js +155 -0
- package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -2
- package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +132 -0
- package/lib/commonjs/components/LinearMeter/LinearMeter.js +9 -28
- package/lib/commonjs/components/LinearProgress/LinearProgress.js +68 -0
- package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +95 -0
- package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +286 -0
- package/lib/commonjs/components/OTP/OTP.js +381 -37
- package/lib/commonjs/components/ProductOverview/ProductOverview.js +147 -0
- package/lib/commonjs/components/Radio/Radio.js +194 -0
- package/lib/commonjs/components/RadioButton/RadioButton.js +21 -188
- package/lib/commonjs/components/RangeTrack/RangeTrack.js +269 -0
- package/lib/commonjs/components/SavingsGoalSummary/SavingsGoalSummary.js +181 -0
- package/lib/commonjs/components/SegmentedTrack/SegmentedTrack.js +171 -0
- package/lib/commonjs/components/StatGroup/StatGroup.js +128 -0
- package/lib/commonjs/components/StatItem/StatItem.js +65 -35
- package/lib/commonjs/components/StrengthIndicator/StrengthIndicator.js +157 -0
- package/lib/commonjs/components/SummaryTile/SummaryTile.js +150 -0
- package/lib/commonjs/components/index.js +192 -1
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/index.js +7 -0
- package/lib/commonjs/utils/number-utils.js +57 -0
- package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +233 -0
- package/lib/module/components/BrandChip/BrandChip.js +143 -0
- package/lib/module/components/CardAdvisory/CardAdvisory.js +2 -2
- package/lib/module/components/CardBankAccount/CardBankAccount.js +208 -0
- package/lib/module/components/CardFinancialCondition/CardFinancialCondition.js +207 -0
- package/lib/module/components/CardInsight/CardInsight.js +161 -0
- package/lib/module/components/Carousel/Carousel.js +9 -7
- package/lib/module/components/CheckboxGroup/CheckboxGroup.js +62 -0
- package/lib/module/components/CheckboxItem/CheckboxItem.js +119 -0
- package/lib/module/components/CircularProgressBar/CircularProgressBar.js +56 -9
- package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +266 -0
- package/lib/module/components/CoverageRing/CoverageRing.js +136 -0
- package/lib/module/components/DonutChart/DonutChart.js +303 -0
- package/lib/module/components/DonutChartSummary/DonutChartSummary.js +150 -0
- package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -2
- package/lib/module/components/InstitutionBadge/InstitutionBadge.js +127 -0
- package/lib/module/components/LinearMeter/LinearMeter.js +9 -28
- package/lib/module/components/LinearProgress/LinearProgress.js +63 -0
- package/lib/module/components/MetricLegendItem/MetricLegendItem.js +90 -0
- package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +281 -0
- package/lib/module/components/OTP/OTP.js +381 -38
- package/lib/module/components/ProductOverview/ProductOverview.js +142 -0
- package/lib/module/components/Radio/Radio.js +188 -0
- package/lib/module/components/RadioButton/RadioButton.js +20 -185
- package/lib/module/components/RangeTrack/RangeTrack.js +263 -0
- package/lib/module/components/SavingsGoalSummary/SavingsGoalSummary.js +175 -0
- package/lib/module/components/SegmentedTrack/SegmentedTrack.js +166 -0
- package/lib/module/components/StatGroup/StatGroup.js +123 -0
- package/lib/module/components/StatItem/StatItem.js +66 -36
- package/lib/module/components/StrengthIndicator/StrengthIndicator.js +152 -0
- package/lib/module/components/SummaryTile/SummaryTile.js +145 -0
- package/lib/module/components/index.js +28 -1
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/index.js +2 -1
- package/lib/module/utils/number-utils.js +53 -0
- package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +71 -0
- package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +43 -0
- package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +79 -0
- package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +50 -0
- package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +48 -0
- package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +41 -0
- package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +56 -0
- package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +11 -1
- package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +105 -0
- package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +90 -0
- package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +117 -0
- package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +103 -0
- package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +30 -0
- package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +17 -0
- package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +37 -0
- package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +119 -0
- package/lib/typescript/src/components/OTP/OTP.d.ts +88 -2
- package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +39 -0
- package/lib/typescript/src/components/Radio/Radio.d.ts +30 -0
- package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +20 -28
- package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +173 -0
- package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +95 -0
- package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +108 -0
- package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +45 -0
- package/lib/typescript/src/components/StatItem/StatItem.d.ts +24 -7
- package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +58 -0
- package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +60 -0
- package/lib/typescript/src/components/index.d.ts +29 -2
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/utils/index.d.ts +1 -0
- package/lib/typescript/src/utils/number-utils.d.ts +29 -0
- package/package.json +1 -1
- package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +323 -0
- package/src/components/BrandChip/BrandChip.tsx +235 -0
- package/src/components/CardAdvisory/CardAdvisory.tsx +2 -2
- package/src/components/CardBankAccount/CardBankAccount.tsx +295 -0
- package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +366 -0
- package/src/components/CardInsight/CardInsight.tsx +239 -0
- package/src/components/Carousel/Carousel.tsx +14 -6
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +86 -0
- package/src/components/CheckboxItem/CheckboxItem.tsx +174 -0
- package/src/components/CircularProgressBar/CircularProgressBar.tsx +74 -9
- package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +378 -0
- package/src/components/CoverageRing/CoverageRing.tsx +225 -0
- package/src/components/DonutChart/DonutChart.tsx +503 -0
- package/src/components/DonutChartSummary/DonutChartSummary.tsx +256 -0
- package/src/components/HoldingsCard/HoldingsCard.tsx +2 -2
- package/src/components/InstitutionBadge/InstitutionBadge.tsx +216 -0
- package/src/components/LinearMeter/LinearMeter.tsx +9 -39
- package/src/components/LinearProgress/LinearProgress.tsx +92 -0
- package/src/components/MetricLegendItem/MetricLegendItem.tsx +167 -0
- package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +438 -0
- package/src/components/OTP/OTP.tsx +476 -29
- package/src/components/ProductOverview/ProductOverview.tsx +236 -0
- package/src/components/Radio/Radio.tsx +227 -0
- package/src/components/RadioButton/RadioButton.tsx +23 -225
- package/src/components/RangeTrack/RangeTrack.tsx +394 -0
- package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +269 -0
- package/src/components/SegmentedTrack/SegmentedTrack.tsx +268 -0
- package/src/components/StatGroup/StatGroup.tsx +169 -0
- package/src/components/StatItem/StatItem.tsx +117 -40
- package/src/components/StrengthIndicator/StrengthIndicator.tsx +205 -0
- package/src/components/SummaryTile/SummaryTile.tsx +251 -0
- package/src/components/index.ts +39 -2
- package/src/design-tokens/Coin Variables-variables-full.json +1 -1
- package/src/icons/registry.ts +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/number-utils.ts +60 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View, type StyleProp, type ViewStyle } from 'react-native'
|
|
3
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
5
|
+
import CheckboxItem from '../CheckboxItem/CheckboxItem'
|
|
6
|
+
|
|
7
|
+
export type CheckboxGroupProps = {
|
|
8
|
+
/**
|
|
9
|
+
* Slot — a list of `CheckboxItem` (or compatible) elements to render inside
|
|
10
|
+
* the group. The `modes` prop is automatically forwarded to each child.
|
|
11
|
+
*
|
|
12
|
+
* When omitted, three default placeholder `CheckboxItem`s are rendered to
|
|
13
|
+
* mirror the Figma reference for the empty/initial state.
|
|
14
|
+
*/
|
|
15
|
+
children?: React.ReactNode
|
|
16
|
+
/** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
|
|
17
|
+
modes?: Record<string, any>
|
|
18
|
+
/** Override container styles. */
|
|
19
|
+
style?: StyleProp<ViewStyle>
|
|
20
|
+
/** Accessibility label for the surrounding group. */
|
|
21
|
+
accessibilityLabel?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* CheckboxGroup composes a vertical stack of `CheckboxItem`s. Spacing and
|
|
26
|
+
* padding are driven by the `checkboxGroup/*` design tokens so groups stay
|
|
27
|
+
* visually consistent across screens.
|
|
28
|
+
*
|
|
29
|
+
* The `modes` prop is forwarded recursively to all children — including
|
|
30
|
+
* `CheckboxItem`s and any element rendered inside their `endSlot`.
|
|
31
|
+
*
|
|
32
|
+
* @component
|
|
33
|
+
* @param {CheckboxGroupProps} props
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* <CheckboxGroup modes={{ 'Color Mode': 'Light' }}>
|
|
38
|
+
* <CheckboxItem label="Fixed deposit • 0245" />
|
|
39
|
+
* <CheckboxItem label="Recurring deposit • 1182" />
|
|
40
|
+
* <CheckboxItem label="Mutual fund • Equity" />
|
|
41
|
+
* </CheckboxGroup>
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function CheckboxGroup({
|
|
45
|
+
children,
|
|
46
|
+
modes = EMPTY_MODES,
|
|
47
|
+
style,
|
|
48
|
+
accessibilityLabel,
|
|
49
|
+
}: CheckboxGroupProps) {
|
|
50
|
+
const gap = (getVariableByName('checkboxGroup/gap', modes) as number | null) ?? 12
|
|
51
|
+
const paddingHorizontal =
|
|
52
|
+
(getVariableByName('checkboxGroup/padding/horizontal', modes) as number | null) ?? 0
|
|
53
|
+
const paddingVertical =
|
|
54
|
+
(getVariableByName('checkboxGroup/padding/vertical', modes) as number | null) ?? 0
|
|
55
|
+
|
|
56
|
+
const containerStyle: ViewStyle = {
|
|
57
|
+
width: '100%',
|
|
58
|
+
flexDirection: 'column',
|
|
59
|
+
alignItems: 'stretch',
|
|
60
|
+
gap,
|
|
61
|
+
paddingHorizontal,
|
|
62
|
+
paddingVertical,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const items = children ? (
|
|
66
|
+
cloneChildrenWithModes(children, modes)
|
|
67
|
+
) : (
|
|
68
|
+
<>
|
|
69
|
+
<CheckboxItem modes={modes} />
|
|
70
|
+
<CheckboxItem modes={modes} />
|
|
71
|
+
<CheckboxItem modes={modes} />
|
|
72
|
+
</>
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<View
|
|
77
|
+
style={[containerStyle, style]}
|
|
78
|
+
accessibilityRole="list"
|
|
79
|
+
accessibilityLabel={accessibilityLabel}
|
|
80
|
+
>
|
|
81
|
+
{items}
|
|
82
|
+
</View>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default CheckboxGroup
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
Pressable,
|
|
6
|
+
type StyleProp,
|
|
7
|
+
type ViewStyle,
|
|
8
|
+
type TextStyle,
|
|
9
|
+
} from 'react-native'
|
|
10
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
11
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
12
|
+
import Checkbox from '../Checkbox/Checkbox'
|
|
13
|
+
|
|
14
|
+
export type CheckboxItemProps = {
|
|
15
|
+
/** Whether the checkbox is checked (controlled). */
|
|
16
|
+
checked?: boolean
|
|
17
|
+
/** Initial checked state (uncontrolled). */
|
|
18
|
+
defaultChecked?: boolean
|
|
19
|
+
/** Callback fired when the checked state changes. */
|
|
20
|
+
onValueChange?: (checked: boolean) => void
|
|
21
|
+
/** Whether the row is disabled — both the checkbox and row press handler are disabled. */
|
|
22
|
+
disabled?: boolean
|
|
23
|
+
/** The label text rendered next to the checkbox. */
|
|
24
|
+
label?: React.ReactNode
|
|
25
|
+
/**
|
|
26
|
+
* Optional content rendered on the right side (e.g. a `Button`). When provided,
|
|
27
|
+
* it receives the same `modes` as the parent. Wrapped in a fixed-width container
|
|
28
|
+
* matching the Figma `endSlot` design.
|
|
29
|
+
*/
|
|
30
|
+
endSlot?: React.ReactNode
|
|
31
|
+
/** Width of the end slot container in pixels. Defaults to 80 to match the Figma reference. */
|
|
32
|
+
endSlotWidth?: number
|
|
33
|
+
/** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
|
|
34
|
+
modes?: Record<string, any>
|
|
35
|
+
/** Override container styles. */
|
|
36
|
+
style?: StyleProp<ViewStyle>
|
|
37
|
+
/** Override the label text styles. */
|
|
38
|
+
labelStyle?: StyleProp<TextStyle>
|
|
39
|
+
/** Accessibility label for screen readers. Defaults to the `label` prop when it is a string. */
|
|
40
|
+
accessibilityLabel?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* CheckboxItem composes a `Checkbox`, a label and an optional `endSlot` into a
|
|
45
|
+
* single horizontal pressable row. Pressing anywhere on the row (outside of the
|
|
46
|
+
* `endSlot`) toggles the checkbox, mirroring the typical native form pattern.
|
|
47
|
+
*
|
|
48
|
+
* Mirrors the Figma "Checkbox Item" component and uses the `checkboxItem/*`
|
|
49
|
+
* design tokens for typography and spacing.
|
|
50
|
+
*
|
|
51
|
+
* @component
|
|
52
|
+
* @param {CheckboxItemProps} props
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* const [checked, setChecked] = useState(false)
|
|
57
|
+
*
|
|
58
|
+
* <CheckboxItem
|
|
59
|
+
* label="Fixed deposit • 0245"
|
|
60
|
+
* checked={checked}
|
|
61
|
+
* onValueChange={setChecked}
|
|
62
|
+
* modes={{ 'Color Mode': 'Light' }}
|
|
63
|
+
* />
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
function CheckboxItem({
|
|
67
|
+
checked: controlledChecked,
|
|
68
|
+
defaultChecked = false,
|
|
69
|
+
onValueChange,
|
|
70
|
+
disabled = false,
|
|
71
|
+
label = 'Fixed deposit • 0245',
|
|
72
|
+
endSlot,
|
|
73
|
+
endSlotWidth = 80,
|
|
74
|
+
modes = EMPTY_MODES,
|
|
75
|
+
style,
|
|
76
|
+
labelStyle,
|
|
77
|
+
accessibilityLabel,
|
|
78
|
+
}: CheckboxItemProps) {
|
|
79
|
+
const isControlled = controlledChecked !== undefined
|
|
80
|
+
const [internalChecked, setInternalChecked] = useState(defaultChecked)
|
|
81
|
+
const isChecked = isControlled ? controlledChecked : internalChecked
|
|
82
|
+
|
|
83
|
+
const handleToggle = useCallback(() => {
|
|
84
|
+
if (disabled) return
|
|
85
|
+
const next = !isChecked
|
|
86
|
+
if (!isControlled) {
|
|
87
|
+
setInternalChecked(next)
|
|
88
|
+
}
|
|
89
|
+
onValueChange?.(next)
|
|
90
|
+
}, [disabled, isChecked, isControlled, onValueChange])
|
|
91
|
+
|
|
92
|
+
const gap = (getVariableByName('checkboxItem/gap', modes) as number | null) ?? 8
|
|
93
|
+
const paddingHorizontal =
|
|
94
|
+
(getVariableByName('checkboxItem/padding/horizontal', modes) as number | null) ?? 0
|
|
95
|
+
const paddingVertical =
|
|
96
|
+
(getVariableByName('checkboxItem/padding/vertical', modes) as number | null) ?? 0
|
|
97
|
+
|
|
98
|
+
const labelColor =
|
|
99
|
+
(getVariableByName('checkboxItem/foreground', modes) as string | null) ?? '#1a1c1f'
|
|
100
|
+
const labelFontFamily =
|
|
101
|
+
(getVariableByName('checkboxItem/label/fontFamily', modes) as string | null) ?? 'JioType Var'
|
|
102
|
+
const labelFontSize =
|
|
103
|
+
(getVariableByName('checkboxItem/label/fontSize', modes) as number | null) ?? 14
|
|
104
|
+
const labelLineHeight =
|
|
105
|
+
(getVariableByName('checkboxItem/label/lineHeight', modes) as number | null) ?? 19
|
|
106
|
+
const labelFontWeightRaw =
|
|
107
|
+
getVariableByName('checkboxItem/label/fontWeight', modes) ?? 400
|
|
108
|
+
const labelFontWeight = String(labelFontWeightRaw) as TextStyle['fontWeight']
|
|
109
|
+
|
|
110
|
+
const containerStyle: ViewStyle = {
|
|
111
|
+
flexDirection: 'row',
|
|
112
|
+
alignItems: 'center',
|
|
113
|
+
gap,
|
|
114
|
+
paddingHorizontal,
|
|
115
|
+
paddingVertical,
|
|
116
|
+
width: '100%',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const resolvedLabelStyle: TextStyle = {
|
|
120
|
+
flex: 1,
|
|
121
|
+
minWidth: 0,
|
|
122
|
+
color: labelColor,
|
|
123
|
+
fontFamily: labelFontFamily,
|
|
124
|
+
fontSize: labelFontSize,
|
|
125
|
+
lineHeight: labelLineHeight,
|
|
126
|
+
fontWeight: labelFontWeight,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const a11yLabel =
|
|
130
|
+
accessibilityLabel ?? (typeof label === 'string' ? label : undefined)
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<Pressable
|
|
134
|
+
style={[containerStyle, style]}
|
|
135
|
+
onPress={handleToggle}
|
|
136
|
+
disabled={disabled}
|
|
137
|
+
accessibilityRole="checkbox"
|
|
138
|
+
accessibilityState={{ checked: isChecked, disabled }}
|
|
139
|
+
accessibilityLabel={a11yLabel}
|
|
140
|
+
>
|
|
141
|
+
<Checkbox
|
|
142
|
+
checked={isChecked}
|
|
143
|
+
disabled={disabled}
|
|
144
|
+
onValueChange={handleToggle}
|
|
145
|
+
modes={modes}
|
|
146
|
+
accessibilityLabel={a11yLabel}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
{label != null && label !== false ? (
|
|
150
|
+
typeof label === 'string' || typeof label === 'number' ? (
|
|
151
|
+
<Text style={[resolvedLabelStyle, labelStyle]} selectable={false}>
|
|
152
|
+
{label}
|
|
153
|
+
</Text>
|
|
154
|
+
) : (
|
|
155
|
+
<View style={{ flex: 1, minWidth: 0 }}>{label}</View>
|
|
156
|
+
)
|
|
157
|
+
) : null}
|
|
158
|
+
|
|
159
|
+
{endSlot ? (
|
|
160
|
+
<View
|
|
161
|
+
style={{
|
|
162
|
+
width: endSlotWidth,
|
|
163
|
+
flexShrink: 0,
|
|
164
|
+
alignItems: 'stretch',
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
{cloneChildrenWithModes(endSlot, modes)}
|
|
168
|
+
</View>
|
|
169
|
+
) : null}
|
|
170
|
+
</Pressable>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export default CheckboxItem
|
|
@@ -17,6 +17,14 @@ export type CircularProgressBarProps = CircularProgressBarBaseProps & {
|
|
|
17
17
|
state?: CircularProgressBarState | boolean
|
|
18
18
|
/** Optional formatted value shown in the active state. */
|
|
19
19
|
valueLabel?: string
|
|
20
|
+
/**
|
|
21
|
+
* Optional small label rendered above the value inside the ring. Useful for
|
|
22
|
+
* sizes that have enough room for both a caption and a value (e.g. the
|
|
23
|
+
* `circularProgressBar Size: M` mode from Figma). When omitted, only the
|
|
24
|
+
* value is shown — keeping the default S-size compatible with existing
|
|
25
|
+
* callers.
|
|
26
|
+
*/
|
|
27
|
+
supportText?: string
|
|
20
28
|
/** Design token modes forwarded to token lookups. */
|
|
21
29
|
modes?: Record<string, any>
|
|
22
30
|
/** Container style override. */
|
|
@@ -27,6 +35,8 @@ export type CircularProgressBarProps = CircularProgressBarBaseProps & {
|
|
|
27
35
|
progressStyle?: StyleProp<ViewStyle>
|
|
28
36
|
/** Value text style override. */
|
|
29
37
|
valueStyle?: StyleProp<TextStyle>
|
|
38
|
+
/** Support text style override. */
|
|
39
|
+
supportTextStyle?: StyleProp<TextStyle>
|
|
30
40
|
/** Accessibility label for the whole progress component. */
|
|
31
41
|
accessibilityLabel?: string
|
|
32
42
|
}
|
|
@@ -71,16 +81,29 @@ function CircularProgressBar({
|
|
|
71
81
|
value = 70,
|
|
72
82
|
state = 'Inactive',
|
|
73
83
|
valueLabel,
|
|
84
|
+
supportText,
|
|
74
85
|
modes: propModes = EMPTY_MODES,
|
|
75
86
|
style,
|
|
76
87
|
trackStyle,
|
|
77
88
|
progressStyle,
|
|
78
89
|
valueStyle,
|
|
90
|
+
supportTextStyle,
|
|
79
91
|
accessibilityLabel,
|
|
80
92
|
...rest
|
|
81
93
|
}: CircularProgressBarProps) {
|
|
82
94
|
const { modes: globalModes } = useTokens()
|
|
83
95
|
const modes = { ...globalModes, ...propModes }
|
|
96
|
+
// The Figma `circularProgressBar/track/color` variable aliases to the same
|
|
97
|
+
// chain as `progress/color`, so user-selected Brand modes collapse the
|
|
98
|
+
// track and progress to a single hue. The Figma source of truth always
|
|
99
|
+
// renders the track as a neutral gray, so we force Neutral/Medium when
|
|
100
|
+
// resolving the track color while keeping the user modes for everything
|
|
101
|
+
// else.
|
|
102
|
+
const trackModes = {
|
|
103
|
+
...modes,
|
|
104
|
+
'AppearanceBrand': 'Neutral',
|
|
105
|
+
'Emphasis': 'Medium',
|
|
106
|
+
}
|
|
84
107
|
|
|
85
108
|
const isActive = state === true || state === 'Active'
|
|
86
109
|
const normalizedValue = clamp(value, 0, 100)
|
|
@@ -92,7 +115,7 @@ function CircularProgressBar({
|
|
|
92
115
|
|
|
93
116
|
const trackColor = getStrokeColor(
|
|
94
117
|
trackStyle,
|
|
95
|
-
getVariableByName('circularProgressBar/track/color',
|
|
118
|
+
getVariableByName('circularProgressBar/track/color', trackModes) as string || '#ebebed'
|
|
96
119
|
)
|
|
97
120
|
const progressColor = getStrokeColor(
|
|
98
121
|
progressStyle,
|
|
@@ -102,10 +125,17 @@ function CircularProgressBar({
|
|
|
102
125
|
const iconSize = toNumber(getVariableByName('circularProgressBar/icon/size', modes), 24)
|
|
103
126
|
|
|
104
127
|
const foreground = getVariableByName('circularProgressBar/foreground', modes) as string || '#0d0d0f'
|
|
105
|
-
const fontSize = toNumber(getVariableByName('circularProgressBar/fontSize', modes), 18)
|
|
128
|
+
const fontSize = toNumber(getVariableByName('circularProgressBar/value/fontSize', modes), 18)
|
|
106
129
|
const fontFamily = getVariableByName('circularProgressBar/fontFamily', modes) as string || 'JioType Var'
|
|
107
|
-
const lineHeight = toNumber(getVariableByName('circularProgressBar/lineHeight', modes), 21)
|
|
108
|
-
const fontWeight = toFontWeight(getVariableByName('circularProgressBar/fontWeight', modes), '700')
|
|
130
|
+
const lineHeight = toNumber(getVariableByName('circularProgressBar/value/lineHeight', modes), 21)
|
|
131
|
+
const fontWeight = toFontWeight(getVariableByName('circularProgressBar/value/fontWeight', modes), '700')
|
|
132
|
+
|
|
133
|
+
const supportFontSize = toNumber(getVariableByName('circularProgressBar/supportText/fontSize', modes), 11)
|
|
134
|
+
const supportLineHeight = toNumber(getVariableByName('circularProgressBar/supportText/lineHeight', modes), 13)
|
|
135
|
+
const supportFontWeight = toFontWeight(
|
|
136
|
+
getVariableByName('circularProgressBar/supportText/fontWeight', modes),
|
|
137
|
+
'500'
|
|
138
|
+
)
|
|
109
139
|
|
|
110
140
|
const computedContainerStyle: ViewStyle = {
|
|
111
141
|
alignItems: 'center',
|
|
@@ -115,13 +145,35 @@ function CircularProgressBar({
|
|
|
115
145
|
width: size,
|
|
116
146
|
}
|
|
117
147
|
|
|
148
|
+
// The text stack (support text + value) is centered inside the ring using
|
|
149
|
+
// an absolutely-positioned column. Keeping the wrapper absolute (rather
|
|
150
|
+
// than the individual texts, as in earlier versions) lets multi-line stacks
|
|
151
|
+
// render correctly without sub-pixel misalignment.
|
|
152
|
+
const textStackStyle: ViewStyle = {
|
|
153
|
+
alignItems: 'center',
|
|
154
|
+
justifyContent: 'center',
|
|
155
|
+
left: 0,
|
|
156
|
+
position: 'absolute',
|
|
157
|
+
right: 0,
|
|
158
|
+
top: 0,
|
|
159
|
+
bottom: 0,
|
|
160
|
+
}
|
|
161
|
+
|
|
118
162
|
const computedValueStyle: TextStyle = {
|
|
119
163
|
color: foreground,
|
|
120
164
|
fontFamily,
|
|
121
165
|
fontSize,
|
|
122
166
|
fontWeight,
|
|
123
167
|
lineHeight,
|
|
124
|
-
|
|
168
|
+
textAlign: 'center',
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const computedSupportTextStyle: TextStyle = {
|
|
172
|
+
color: foreground,
|
|
173
|
+
fontFamily,
|
|
174
|
+
fontSize: supportFontSize,
|
|
175
|
+
fontWeight: supportFontWeight,
|
|
176
|
+
lineHeight: supportLineHeight,
|
|
125
177
|
textAlign: 'center',
|
|
126
178
|
}
|
|
127
179
|
|
|
@@ -132,8 +184,14 @@ function CircularProgressBar({
|
|
|
132
184
|
}
|
|
133
185
|
|
|
134
186
|
const displayValue = valueLabel ?? String(Math.round(normalizedValue))
|
|
187
|
+
const hasSupportText = typeof supportText === 'string' && supportText.length > 0
|
|
135
188
|
const defaultAccessibilityLabel =
|
|
136
|
-
accessibilityLabel ??
|
|
189
|
+
accessibilityLabel ??
|
|
190
|
+
(isActive
|
|
191
|
+
? hasSupportText
|
|
192
|
+
? `${supportText}, ${displayValue} out of 100`
|
|
193
|
+
: `${displayValue} out of 100`
|
|
194
|
+
: 'Inactive progress')
|
|
137
195
|
|
|
138
196
|
return (
|
|
139
197
|
<View
|
|
@@ -171,9 +229,16 @@ function CircularProgressBar({
|
|
|
171
229
|
</Svg>
|
|
172
230
|
|
|
173
231
|
{isActive ? (
|
|
174
|
-
<
|
|
175
|
-
{
|
|
176
|
-
|
|
232
|
+
<View style={textStackStyle} pointerEvents="none">
|
|
233
|
+
{hasSupportText ? (
|
|
234
|
+
<Text style={[computedSupportTextStyle, supportTextStyle]} numberOfLines={1}>
|
|
235
|
+
{supportText}
|
|
236
|
+
</Text>
|
|
237
|
+
) : null}
|
|
238
|
+
<Text style={[computedValueStyle, valueStyle]} numberOfLines={1}>
|
|
239
|
+
{displayValue}
|
|
240
|
+
</Text>
|
|
241
|
+
</View>
|
|
177
242
|
) : (
|
|
178
243
|
<IconMinus
|
|
179
244
|
width={iconSize}
|