jfs-components 0.0.72 → 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 +11 -0
- package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +239 -0
- package/lib/commonjs/components/BrandChip/BrandChip.js +149 -0
- package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +213 -0
- package/lib/commonjs/components/CardInsight/CardInsight.js +166 -0
- 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/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/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 +171 -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/CardBankAccount/CardBankAccount.js +208 -0
- package/lib/module/components/CardInsight/CardInsight.js +161 -0
- 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/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/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 +21 -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/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/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/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 +22 -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/CardBankAccount/CardBankAccount.tsx +295 -0
- package/src/components/CardInsight/CardInsight.tsx +239 -0
- 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/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/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 +32 -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,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils';
|
|
7
|
+
import StatItem from '../StatItem/StatItem';
|
|
8
|
+
import Divider from '../Divider/Divider';
|
|
9
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
const DEFAULT_ITEMS = [{
|
|
11
|
+
label: 'Updates',
|
|
12
|
+
value: 'Daily'
|
|
13
|
+
}, {
|
|
14
|
+
label: 'Data range',
|
|
15
|
+
value: '24 months'
|
|
16
|
+
}, {
|
|
17
|
+
label: 'Validity',
|
|
18
|
+
value: '24 months'
|
|
19
|
+
}, {
|
|
20
|
+
label: 'Stored for',
|
|
21
|
+
value: '1 month'
|
|
22
|
+
}];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* StatGroup renders a card-style container holding a horizontal row of
|
|
26
|
+
* `StatItem`s separated by vertical dividers. It is typically used to surface
|
|
27
|
+
* 3–5 short metrics (e.g. validity, data range, storage) at a glance.
|
|
28
|
+
*
|
|
29
|
+
* Pass `items` for the simple data-driven case, or use the `children` slot
|
|
30
|
+
* for full control over the row contents (the component still auto-inserts
|
|
31
|
+
* vertical dividers between top-level children).
|
|
32
|
+
*
|
|
33
|
+
* @component
|
|
34
|
+
* @param {StatGroupProps} props
|
|
35
|
+
*/
|
|
36
|
+
function StatGroup({
|
|
37
|
+
items,
|
|
38
|
+
children,
|
|
39
|
+
modes = EMPTY_MODES,
|
|
40
|
+
style
|
|
41
|
+
}) {
|
|
42
|
+
const background = getVariableByName('statGroup/background', modes) ?? '#ffffff';
|
|
43
|
+
const strokeColor = getVariableByName('statGroup/stroke/color', modes) ?? '#ebebed';
|
|
44
|
+
const strokeSize = getVariableByName('statGroup/stroke/size', modes) ?? 1;
|
|
45
|
+
const radius = getVariableByName('statGroup/radius', modes) ?? 12;
|
|
46
|
+
const paddingTop = getVariableByName('statGroup/padding/top', modes) ?? 16;
|
|
47
|
+
const paddingRight = getVariableByName('statGroup/padding/right', modes) ?? 0;
|
|
48
|
+
const paddingBottom = getVariableByName('statGroup/padding/bottom', modes) ?? 12;
|
|
49
|
+
const paddingLeft = getVariableByName('statGroup/padding/left', modes) ?? 0;
|
|
50
|
+
const containerStyle = {
|
|
51
|
+
backgroundColor: background,
|
|
52
|
+
borderColor: strokeColor,
|
|
53
|
+
borderWidth: strokeSize,
|
|
54
|
+
borderStyle: 'solid',
|
|
55
|
+
borderRadius: radius,
|
|
56
|
+
paddingTop,
|
|
57
|
+
paddingRight,
|
|
58
|
+
paddingBottom,
|
|
59
|
+
paddingLeft,
|
|
60
|
+
overflow: 'hidden'
|
|
61
|
+
};
|
|
62
|
+
const slotChildren = renderSlotChildren({
|
|
63
|
+
items,
|
|
64
|
+
children,
|
|
65
|
+
modes
|
|
66
|
+
});
|
|
67
|
+
return /*#__PURE__*/_jsx(View, {
|
|
68
|
+
style: [containerStyle, style],
|
|
69
|
+
accessibilityRole: "summary",
|
|
70
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
71
|
+
style: {
|
|
72
|
+
flexDirection: 'row',
|
|
73
|
+
alignItems: 'stretch',
|
|
74
|
+
width: '100%'
|
|
75
|
+
},
|
|
76
|
+
children: slotChildren
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Build the row of items: render either the supplied children or the
|
|
83
|
+
* `items` array, wrap each entry so it grows equally, and inject a vertical
|
|
84
|
+
* `Divider` between siblings.
|
|
85
|
+
*/
|
|
86
|
+
function renderSlotChildren({
|
|
87
|
+
items,
|
|
88
|
+
children,
|
|
89
|
+
modes
|
|
90
|
+
}) {
|
|
91
|
+
let nodes;
|
|
92
|
+
if (children !== undefined && children !== null) {
|
|
93
|
+
const cloned = cloneChildrenWithModes(children, modes);
|
|
94
|
+
nodes = flattenChildren(cloned);
|
|
95
|
+
} else {
|
|
96
|
+
const list = items && items.length > 0 ? items : DEFAULT_ITEMS;
|
|
97
|
+
nodes = list.map((item, index) => /*#__PURE__*/_jsx(StatItem, {
|
|
98
|
+
label: item.label,
|
|
99
|
+
value: item.value,
|
|
100
|
+
labelPosition: "Bottom",
|
|
101
|
+
modes: modes
|
|
102
|
+
}, item.key ?? `${item.label ?? 'item'}-${index}`));
|
|
103
|
+
}
|
|
104
|
+
const result = [];
|
|
105
|
+
nodes.forEach((node, index) => {
|
|
106
|
+
if (index > 0) {
|
|
107
|
+
result.push(/*#__PURE__*/_jsx(Divider, {
|
|
108
|
+
direction: "vertical",
|
|
109
|
+
modes: modes
|
|
110
|
+
}, `divider-${index}`));
|
|
111
|
+
}
|
|
112
|
+
result.push(/*#__PURE__*/_jsx(View, {
|
|
113
|
+
style: {
|
|
114
|
+
flex: 1,
|
|
115
|
+
minWidth: 0,
|
|
116
|
+
alignSelf: 'center'
|
|
117
|
+
},
|
|
118
|
+
children: node
|
|
119
|
+
}, `slot-${index}`));
|
|
120
|
+
});
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
export default StatGroup;
|
|
@@ -4,10 +4,14 @@ import React from 'react';
|
|
|
4
4
|
import { View, Text } from 'react-native';
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
6
|
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
7
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
8
|
/**
|
|
9
|
-
* StatItem displays a label/value pair
|
|
10
|
-
*
|
|
9
|
+
* StatItem displays a label/value pair, useful for product stats, metrics
|
|
10
|
+
* or KPI callouts.
|
|
11
|
+
*
|
|
12
|
+
* Supports two layouts via the `labelPosition` variant:
|
|
13
|
+
* - `'Top'` — Small label above a large prominent value (default).
|
|
14
|
+
* - `'Bottom'` — Value above a smaller label, content centered.
|
|
11
15
|
*
|
|
12
16
|
* @component
|
|
13
17
|
* @param {StatItemProps} props
|
|
@@ -15,43 +19,69 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
19
|
function StatItem({
|
|
16
20
|
label = 'Purity verified by NABL',
|
|
17
21
|
value = '99.99%',
|
|
22
|
+
labelPosition = 'Top',
|
|
18
23
|
modes = EMPTY_MODES,
|
|
19
|
-
style
|
|
24
|
+
style,
|
|
25
|
+
labelStyle,
|
|
26
|
+
valueStyle
|
|
20
27
|
}) {
|
|
21
|
-
const
|
|
22
|
-
|
|
28
|
+
const isBottom = labelPosition === 'Bottom';
|
|
29
|
+
|
|
30
|
+
// The Figma `Bottom` variant overrides token values locally inside the
|
|
31
|
+
// component (it is not exposed in the design-tokens JSON), so the resolved
|
|
32
|
+
// token values reflect only the `Top` variant. For the `Bottom` variant we
|
|
33
|
+
// therefore use hardcoded literals that match the Figma design, while still
|
|
34
|
+
// allowing the resolver to surface any future mode-based overrides for the
|
|
35
|
+
// `Top` variant.
|
|
36
|
+
const gap = isBottom ? 6 : getVariableByName('statItem/gap', modes) ?? 2;
|
|
37
|
+
const labelForeground = isBottom ? '#24262b' : getVariableByName('statItem/label/foreground', modes) ?? '#1a1c1f';
|
|
23
38
|
const labelFontFamily = getVariableByName('statItem/label/fontFamily', modes) ?? 'JioType Var';
|
|
24
|
-
const labelFontSize = getVariableByName('statItem/label/fontSize', modes) ?? 12;
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
39
|
+
const labelFontSize = isBottom ? 10 : getVariableByName('statItem/label/fontSize', modes) ?? 12;
|
|
40
|
+
const labelFontWeightRaw = isBottom ? 400 : getVariableByName('statItem/label/fontWeight', modes) ?? 500;
|
|
41
|
+
const labelFontWeight = String(labelFontWeightRaw);
|
|
42
|
+
const labelLineHeight = isBottom ? 13 : getVariableByName('statItem/label/lineHeight', modes) ?? 16;
|
|
43
|
+
const valueForeground = isBottom ? '#141414' : getVariableByName('statItem/value/foreground', modes) ?? '#0d0d0f';
|
|
28
44
|
const valueFontFamily = getVariableByName('statItem/value/fontFamily', modes) ?? 'JioType Var';
|
|
29
|
-
const valueFontSize = getVariableByName('statItem/value/fontSize', modes) ?? 26;
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
const valueFontSize = isBottom ? 12 : getVariableByName('statItem/value/fontSize', modes) ?? 26;
|
|
46
|
+
const valueFontWeightRaw = isBottom ? 500 : getVariableByName('statItem/value/fontWeight', modes) ?? 900;
|
|
47
|
+
const valueFontWeight = String(valueFontWeightRaw);
|
|
48
|
+
const valueLineHeight = isBottom ? 16 : getVariableByName('statItem/value/lineHeight', modes) ?? 26;
|
|
49
|
+
const containerStyle = {
|
|
50
|
+
gap,
|
|
51
|
+
alignItems: isBottom ? 'center' : 'flex-start',
|
|
52
|
+
justifyContent: isBottom ? 'center' : 'flex-start'
|
|
53
|
+
};
|
|
54
|
+
const labelTextStyle = {
|
|
55
|
+
color: labelForeground,
|
|
56
|
+
fontFamily: labelFontFamily,
|
|
57
|
+
fontSize: labelFontSize,
|
|
58
|
+
fontWeight: labelFontWeight,
|
|
59
|
+
lineHeight: labelLineHeight,
|
|
60
|
+
textAlign: isBottom ? 'center' : 'left'
|
|
61
|
+
};
|
|
62
|
+
const valueTextStyle = {
|
|
63
|
+
color: valueForeground,
|
|
64
|
+
fontFamily: valueFontFamily,
|
|
65
|
+
fontSize: valueFontSize,
|
|
66
|
+
fontWeight: valueFontWeight,
|
|
67
|
+
lineHeight: valueLineHeight,
|
|
68
|
+
textAlign: isBottom ? 'center' : 'left'
|
|
69
|
+
};
|
|
70
|
+
const labelNode = /*#__PURE__*/_jsx(Text, {
|
|
71
|
+
style: [labelTextStyle, labelStyle],
|
|
72
|
+
children: label
|
|
73
|
+
});
|
|
74
|
+
const valueNode = /*#__PURE__*/_jsx(Text, {
|
|
75
|
+
style: [valueTextStyle, valueStyle],
|
|
76
|
+
children: value
|
|
77
|
+
});
|
|
78
|
+
return /*#__PURE__*/_jsx(View, {
|
|
79
|
+
style: [containerStyle, style],
|
|
80
|
+
children: isBottom ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
81
|
+
children: [valueNode, labelNode]
|
|
82
|
+
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
83
|
+
children: [labelNode, valueNode]
|
|
84
|
+
})
|
|
55
85
|
});
|
|
56
86
|
}
|
|
57
87
|
export default StatItem;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { View } from 'react-native';
|
|
5
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Confidence levels supported by the indicator. Mirrors the Figma `Confidence`
|
|
10
|
+
* mode collection exactly (`High` | `Medium` | `Low` | `None`).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Accepted shape for the `confidence` prop. Either:
|
|
15
|
+
* - one of the named levels (`'High' | 'Medium' | 'Low' | 'None'`), or
|
|
16
|
+
* - a float in `[0, 1]`. Floats are bucketed to the nearest level using
|
|
17
|
+
* midpoint thresholds (1/6, 1/2, 5/6) so anchor values land squarely:
|
|
18
|
+
* `0` → `None`, `~0.33` → `Low`, `~0.66` → `Medium`, `1` → `High`.
|
|
19
|
+
* Values outside `[0, 1]` are clamped.
|
|
20
|
+
*/
|
|
21
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
|
+
const BAR_SIZES = ['small', 'medium', 'large'];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Maps an overall confidence level to per-bar confidence modes. Bars are
|
|
26
|
+
* filled from the smallest (left) to the largest (right) as confidence
|
|
27
|
+
* rises, with each lit bar tinted at its own confidence level so the
|
|
28
|
+
* indicator visually communicates *which* level the value is at — not just
|
|
29
|
+
* how many bars are lit.
|
|
30
|
+
*
|
|
31
|
+
* High -> [High, High, High] (3/3 lit, bright)
|
|
32
|
+
* Medium -> [Medium, Medium, None] (2/3 lit, mid intensity)
|
|
33
|
+
* Low -> [Low, None, None] (1/3 lit, low intensity)
|
|
34
|
+
* None -> [None, None, None] (0/3 lit)
|
|
35
|
+
*
|
|
36
|
+
* Each bar resolves its color through `getVariableByName` with its own
|
|
37
|
+
* per-bar `Confidence` mode, so the mapping survives any token updates in
|
|
38
|
+
* the Figma variables export.
|
|
39
|
+
*/
|
|
40
|
+
const CONFIDENCE_TO_BARS = {
|
|
41
|
+
High: ['High', 'High', 'High'],
|
|
42
|
+
Medium: ['Medium', 'Medium', 'None'],
|
|
43
|
+
Low: ['Low', 'None', 'None'],
|
|
44
|
+
None: ['None', 'None', 'None']
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Fallback colors used when the `strengthIndicator/*` design tokens have not
|
|
49
|
+
* yet been imported into `Coin Variables-variables-full.json`. The `High`
|
|
50
|
+
* fallback matches the Figma export (`#25ab21`); the intermediate levels
|
|
51
|
+
* use progressively lighter greens, and `None` uses a neutral gray for
|
|
52
|
+
* unlit bars. Once the tokens land, `getVariableByName` returns the
|
|
53
|
+
* canonical value and these fallbacks are bypassed.
|
|
54
|
+
*/
|
|
55
|
+
const FALLBACK_BAR_COLOR = {
|
|
56
|
+
High: '#25ab21',
|
|
57
|
+
Medium: '#5cc257',
|
|
58
|
+
Low: '#a8dba2',
|
|
59
|
+
None: '#d9d9dd'
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Bucket a float `[0, 1]` into the nearest named confidence level using
|
|
64
|
+
* midpoint thresholds between the four anchor values (`0`, `1/3`, `2/3`,
|
|
65
|
+
* `1`). Out-of-range values are clamped.
|
|
66
|
+
*/
|
|
67
|
+
function floatToConfidence(value) {
|
|
68
|
+
const clamped = Math.min(Math.max(value, 0), 1);
|
|
69
|
+
if (clamped > 5 / 6) return 'High';
|
|
70
|
+
if (clamped > 1 / 2) return 'Medium';
|
|
71
|
+
if (clamped > 1 / 6) return 'Low';
|
|
72
|
+
return 'None';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Normalize the union `confidence` prop into a single named level.
|
|
77
|
+
* Strings pass through; numbers are bucketed via {@link floatToConfidence}.
|
|
78
|
+
* Anything else (e.g. `null`/`undefined`) defaults to `'High'` to match
|
|
79
|
+
* Figma's default mode.
|
|
80
|
+
*/
|
|
81
|
+
function resolveConfidence(value) {
|
|
82
|
+
if (typeof value === 'number') return floatToConfidence(value);
|
|
83
|
+
if (value === 'High' || value === 'Medium' || value === 'Low' || value === 'None') {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
return 'High';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* StrengthIndicator renders three fixed-size, ascending bars that
|
|
91
|
+
* communicate a discrete confidence/strength level — typically used to
|
|
92
|
+
* signal model confidence, signal quality, or password strength.
|
|
93
|
+
*
|
|
94
|
+
* Sizes are intentionally fixed (matching the Figma spec): 3px-wide bars
|
|
95
|
+
* 6/9/12px tall with a 2px gap and 2px container padding.
|
|
96
|
+
*
|
|
97
|
+
* Pass a single `confidence` value (named enum *or* float `[0, 1]`); the
|
|
98
|
+
* component normalizes it to a level, maps that level to a per-bar
|
|
99
|
+
* confidence mode, and resolves each bar's color through design tokens
|
|
100
|
+
* (`strengthIndicator/bar/<size>/background`).
|
|
101
|
+
*
|
|
102
|
+
* @component
|
|
103
|
+
* @param {StrengthIndicatorProps} props
|
|
104
|
+
*/
|
|
105
|
+
function StrengthIndicator({
|
|
106
|
+
confidence = 'High',
|
|
107
|
+
modes = EMPTY_MODES,
|
|
108
|
+
style,
|
|
109
|
+
...rest
|
|
110
|
+
}) {
|
|
111
|
+
const containerGap = getVariableByName('strengthIndicator/container/gap', modes) ?? 2;
|
|
112
|
+
const containerPadding = getVariableByName('strengthIndicator/container/padding', modes) ?? 2;
|
|
113
|
+
const barWidth = getVariableByName('strengthIndicator/bar/width', modes) ?? 3;
|
|
114
|
+
const barRadius = getVariableByName('strengthIndicator/bar/radius', modes) ?? 1;
|
|
115
|
+
const barHeights = {
|
|
116
|
+
small: getVariableByName('strengthIndicator/bar/height/small', modes) ?? 6,
|
|
117
|
+
medium: getVariableByName('strengthIndicator/bar/height/medium', modes) ?? 9,
|
|
118
|
+
large: getVariableByName('strengthIndicator/bar/height/large', modes) ?? 12
|
|
119
|
+
};
|
|
120
|
+
const resolvedLevel = resolveConfidence(confidence);
|
|
121
|
+
const perBarConfidence = CONFIDENCE_TO_BARS[resolvedLevel];
|
|
122
|
+
const containerStyle = {
|
|
123
|
+
flexDirection: 'row',
|
|
124
|
+
alignItems: 'flex-end',
|
|
125
|
+
gap: containerGap,
|
|
126
|
+
padding: containerPadding
|
|
127
|
+
};
|
|
128
|
+
return /*#__PURE__*/_jsx(View, {
|
|
129
|
+
style: [containerStyle, style],
|
|
130
|
+
accessibilityRole: "image",
|
|
131
|
+
accessibilityLabel: `Strength indicator: ${resolvedLevel} confidence`,
|
|
132
|
+
...rest,
|
|
133
|
+
children: BAR_SIZES.map((size, index) => {
|
|
134
|
+
const barConfidence = perBarConfidence[index] ?? 'None';
|
|
135
|
+
const barModes = {
|
|
136
|
+
...modes,
|
|
137
|
+
Confidence: barConfidence
|
|
138
|
+
};
|
|
139
|
+
const tokenColor = getVariableByName(`strengthIndicator/bar/${size}/background`, barModes);
|
|
140
|
+
const backgroundColor = tokenColor ?? FALLBACK_BAR_COLOR[barConfidence];
|
|
141
|
+
return /*#__PURE__*/_jsx(View, {
|
|
142
|
+
style: {
|
|
143
|
+
width: barWidth,
|
|
144
|
+
height: barHeights[size],
|
|
145
|
+
borderRadius: barRadius,
|
|
146
|
+
backgroundColor
|
|
147
|
+
}
|
|
148
|
+
}, size);
|
|
149
|
+
})
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
export default StrengthIndicator;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { View, Text, Pressable } from 'react-native';
|
|
5
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
|
|
7
|
+
import Button from '../Button/Button';
|
|
8
|
+
import NavArrow from '../NavArrow/NavArrow';
|
|
9
|
+
import StrengthIndicator from '../StrengthIndicator/StrengthIndicator';
|
|
10
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
/**
|
|
12
|
+
* SummaryTile composes a title (with an inline `StrengthIndicator`), a
|
|
13
|
+
* supporting description and an action slot into a compact horizontal row,
|
|
14
|
+
* commonly used at the top of dashboard cards (e.g. "Spending — know your
|
|
15
|
+
* spending and savings"). An optional trailing chevron and tile-level
|
|
16
|
+
* `onPress` handler turn the whole row into a navigational entry point.
|
|
17
|
+
*
|
|
18
|
+
* @component
|
|
19
|
+
* @param {SummaryTileProps} props
|
|
20
|
+
*/
|
|
21
|
+
function SummaryTile({
|
|
22
|
+
title = 'Spending',
|
|
23
|
+
description = 'Know your spending and savings',
|
|
24
|
+
confidence = 'None',
|
|
25
|
+
chevron = false,
|
|
26
|
+
children,
|
|
27
|
+
onPress,
|
|
28
|
+
modes = EMPTY_MODES,
|
|
29
|
+
style,
|
|
30
|
+
titleStyle,
|
|
31
|
+
descriptionStyle,
|
|
32
|
+
accessibilityLabel
|
|
33
|
+
}) {
|
|
34
|
+
const containerGap = getVariableByName('summaryTile/gap', modes) ?? 8;
|
|
35
|
+
const containerPadding = getVariableByName('summaryTile/padding', modes) ?? 0;
|
|
36
|
+
const contentGap = getVariableByName('summaryTile/content/gap', modes) ?? 8;
|
|
37
|
+
const titleWrapGap = getVariableByName('summaryTile/titleWrap/gap', modes) ?? 4;
|
|
38
|
+
const titleColor = getVariableByName('summaryTile/title/color', modes) ?? '#0d0d0f';
|
|
39
|
+
const titleFontFamily = getVariableByName('summaryTile/title/fontFamily', modes) ?? 'JioType Var';
|
|
40
|
+
const titleFontSize = getVariableByName('summaryTile/title/fontSize', modes) ?? 16;
|
|
41
|
+
const titleFontWeight = getVariableByName('summaryTile/title/fontWeight', modes) ?? 700;
|
|
42
|
+
const titleLineHeight = getVariableByName('summaryTile/title/lineHeight', modes) ?? 18;
|
|
43
|
+
const descriptionColor = getVariableByName('summaryTile/description/color', modes) ?? '#24262b';
|
|
44
|
+
const descriptionFontFamily = getVariableByName('summaryTile/description/fontFamily', modes) ?? 'JioType Var';
|
|
45
|
+
const descriptionFontSize = getVariableByName('summaryTile/description/fontSize', modes) ?? 12;
|
|
46
|
+
const descriptionFontWeight = getVariableByName('summaryTile/description/fontWeight', modes) ?? 500;
|
|
47
|
+
const descriptionLineHeight = getVariableByName('summaryTile/description/lineHeight', modes) ?? 16;
|
|
48
|
+
const titleTextStyle = {
|
|
49
|
+
color: titleColor,
|
|
50
|
+
fontFamily: titleFontFamily,
|
|
51
|
+
fontSize: titleFontSize,
|
|
52
|
+
fontWeight: String(titleFontWeight),
|
|
53
|
+
lineHeight: titleLineHeight
|
|
54
|
+
};
|
|
55
|
+
const descriptionTextStyle = {
|
|
56
|
+
color: descriptionColor,
|
|
57
|
+
fontFamily: descriptionFontFamily,
|
|
58
|
+
fontSize: descriptionFontSize,
|
|
59
|
+
fontWeight: String(descriptionFontWeight),
|
|
60
|
+
lineHeight: descriptionLineHeight
|
|
61
|
+
};
|
|
62
|
+
const showIndicator = confidence !== null;
|
|
63
|
+
|
|
64
|
+
// When the entire tile is pressable, the default `Button` slot is
|
|
65
|
+
// suppressed so we don't render a `<button>` inside another `<button>`
|
|
66
|
+
// (which is invalid HTML and triggers a React hydration warning on
|
|
67
|
+
// web). Consumers can still pass an explicit non-button node via
|
|
68
|
+
// `children` if they want a visible affordance alongside `onPress`.
|
|
69
|
+
const isPressable = onPress != null;
|
|
70
|
+
const actionSlot = children !== undefined ? children !== null ? /*#__PURE__*/_jsx(_Fragment, {
|
|
71
|
+
children: cloneChildrenWithModes(children, modes)
|
|
72
|
+
}) : null : isPressable ? null : /*#__PURE__*/_jsx(Button, {
|
|
73
|
+
label: "Button",
|
|
74
|
+
modes: {
|
|
75
|
+
'AppearanceBrand': 'Secondary',
|
|
76
|
+
...modes,
|
|
77
|
+
'Button / Size': 'S'
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
const tileContent = /*#__PURE__*/_jsxs(_Fragment, {
|
|
81
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
82
|
+
style: {
|
|
83
|
+
flex: 1,
|
|
84
|
+
minWidth: 0,
|
|
85
|
+
flexDirection: 'column',
|
|
86
|
+
gap: contentGap,
|
|
87
|
+
alignItems: 'flex-start'
|
|
88
|
+
},
|
|
89
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
90
|
+
style: {
|
|
91
|
+
flexDirection: 'row',
|
|
92
|
+
alignItems: 'center',
|
|
93
|
+
gap: titleWrapGap,
|
|
94
|
+
width: '100%'
|
|
95
|
+
},
|
|
96
|
+
children: [title ? /*#__PURE__*/_jsx(Text, {
|
|
97
|
+
style: [titleTextStyle, titleStyle],
|
|
98
|
+
numberOfLines: 1,
|
|
99
|
+
children: title
|
|
100
|
+
}) : null, showIndicator ? /*#__PURE__*/_jsx(StrengthIndicator, {
|
|
101
|
+
confidence: confidence,
|
|
102
|
+
modes: modes
|
|
103
|
+
}) : null]
|
|
104
|
+
}), description ? /*#__PURE__*/_jsx(Text, {
|
|
105
|
+
style: [descriptionTextStyle, descriptionStyle],
|
|
106
|
+
children: description
|
|
107
|
+
}) : null]
|
|
108
|
+
}), actionSlot != null ? /*#__PURE__*/_jsx(View, {
|
|
109
|
+
style: {
|
|
110
|
+
flexDirection: 'row',
|
|
111
|
+
alignItems: 'center'
|
|
112
|
+
},
|
|
113
|
+
children: actionSlot
|
|
114
|
+
}) : null, chevron ? /*#__PURE__*/_jsx(NavArrow, {
|
|
115
|
+
direction: "Forward",
|
|
116
|
+
modes: modes
|
|
117
|
+
}) : null]
|
|
118
|
+
});
|
|
119
|
+
const containerLayoutStyle = {
|
|
120
|
+
flexDirection: 'row',
|
|
121
|
+
alignItems: 'center',
|
|
122
|
+
gap: containerGap,
|
|
123
|
+
padding: containerPadding,
|
|
124
|
+
width: '100%'
|
|
125
|
+
};
|
|
126
|
+
if (onPress) {
|
|
127
|
+
return /*#__PURE__*/_jsx(Pressable, {
|
|
128
|
+
onPress: onPress,
|
|
129
|
+
accessibilityRole: "button",
|
|
130
|
+
accessibilityLabel: accessibilityLabel ?? title,
|
|
131
|
+
style: ({
|
|
132
|
+
pressed
|
|
133
|
+
}) => [containerLayoutStyle, style, pressed ? {
|
|
134
|
+
opacity: 0.7
|
|
135
|
+
} : null],
|
|
136
|
+
children: tileContent
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return /*#__PURE__*/_jsx(View, {
|
|
140
|
+
style: [containerLayoutStyle, style],
|
|
141
|
+
accessibilityLabel: accessibilityLabel,
|
|
142
|
+
children: tileContent
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
export default SummaryTile;
|
|
@@ -7,13 +7,18 @@ export { default as AvatarGroup } from './AvatarGroup/AvatarGroup';
|
|
|
7
7
|
export { default as Badge } from './Badge/Badge';
|
|
8
8
|
export { default as BottomNav } from './BottomNav/BottomNav';
|
|
9
9
|
export { default as BottomNavItem } from './BottomNavItem/BottomNavItem';
|
|
10
|
+
export { default as BrandChip } from './BrandChip/BrandChip';
|
|
10
11
|
export { default as Button } from './Button/Button';
|
|
11
12
|
export { default as Card } from './Card/Card';
|
|
12
13
|
export { default as CardAdvisory } from './CardAdvisory/CardAdvisory';
|
|
14
|
+
export { default as CardBankAccount } from './CardBankAccount/CardBankAccount';
|
|
13
15
|
export { default as Carousel } from './Carousel/Carousel';
|
|
14
16
|
export { default as Checkbox } from './Checkbox/Checkbox';
|
|
17
|
+
export { default as CheckboxItem } from './CheckboxItem/CheckboxItem';
|
|
18
|
+
export { default as CheckboxGroup } from './CheckboxGroup/CheckboxGroup';
|
|
15
19
|
export { default as CardFeedback } from './CardFeedback/CardFeedback';
|
|
16
20
|
export { default as CardFinancialCondition } from './CardFinancialCondition/CardFinancialCondition';
|
|
21
|
+
export { default as CardInsight } from './CardInsight/CardInsight';
|
|
17
22
|
export { default as Disclaimer } from './Disclaimer/Disclaimer';
|
|
18
23
|
export { default as Divider } from './Divider/Divider';
|
|
19
24
|
export { default as Drawer } from './Drawer/Drawer';
|
|
@@ -26,6 +31,9 @@ export { default as FormField } from './FormField/FormField';
|
|
|
26
31
|
export { default as CircularProgressBar } from './CircularProgressBar/CircularProgressBar';
|
|
27
32
|
export { default as CircularProgressBarDoted } from './CircularProgressBarDoted/CircularProgressBarDoted';
|
|
28
33
|
export { default as CircularRating } from './CircularRating/CircularRating';
|
|
34
|
+
export { default as CoverageRing } from './CoverageRing/CoverageRing';
|
|
35
|
+
export { default as CoverageBarComparison } from './CoverageBarComparison/CoverageBarComparison';
|
|
36
|
+
export { default as MonthlyStatusGrid, CalendarGlyph } from './MonthlyStatusGrid/MonthlyStatusGrid';
|
|
29
37
|
export { default as Gauge } from './Gauge/Gauge';
|
|
30
38
|
export { default as HoldingsCard } from './HoldingsCard/HoldingsCard';
|
|
31
39
|
export { default as HStack } from './HStack/HStack';
|
|
@@ -34,10 +42,12 @@ export { default as IconCapsule } from './IconCapsule/IconCapsule';
|
|
|
34
42
|
export { default as Image } from './Image/Image';
|
|
35
43
|
export { default as LazyList } from './LazyList/LazyList';
|
|
36
44
|
export { default as LinearMeter } from './LinearMeter/LinearMeter';
|
|
45
|
+
export { default as LinearProgress } from './LinearProgress/LinearProgress';
|
|
37
46
|
export { default as ListGroup } from './ListGroup/ListGroup';
|
|
38
47
|
export { default as ListItem } from './ListItem/ListItem';
|
|
39
48
|
export { default as MediaCard } from './MediaCard/MediaCard';
|
|
40
49
|
export { default as MerchantProfile } from './MerchantProfile/MerchantProfile';
|
|
50
|
+
export { default as MetricLegendItem } from './MetricLegendItem/MetricLegendItem';
|
|
41
51
|
export { default as MoneyValue } from './MoneyValue/MoneyValue';
|
|
42
52
|
export { default as NoteInput } from './NoteInput/NoteInput';
|
|
43
53
|
export { default as Nudge } from './Nudge/Nudge';
|
|
@@ -61,6 +71,7 @@ export { default as VStack } from './VStack/VStack';
|
|
|
61
71
|
export { default as ChipGroup } from './ChipGroup/ChipGroup';
|
|
62
72
|
export { default as EmptyState } from './EmptyState/EmptyState';
|
|
63
73
|
export { default as Accordion } from './Accordion/Accordion';
|
|
74
|
+
export { default as AccordionCheckbox } from './AccordionCheckbox/AccordionCheckbox';
|
|
64
75
|
export { default as ActionTile } from './ActionTile/ActionTile';
|
|
65
76
|
export { default as Balance } from './Balance/Balance';
|
|
66
77
|
export { default as ButtonGroup } from './ButtonGroup/ButtonGroup';
|
|
@@ -77,6 +88,11 @@ export { default as Radio } from './Radio/Radio';
|
|
|
77
88
|
*/
|
|
78
89
|
export { default as RadioButton } from './RadioButton/RadioButton';
|
|
79
90
|
export { default as RechargeCard } from './RechargeCard/RechargeCard';
|
|
91
|
+
export { default as SavingsGoalSummary } from './SavingsGoalSummary/SavingsGoalSummary';
|
|
92
|
+
export { default as DonutChart, DonutChartSegment } from './DonutChart/DonutChart';
|
|
93
|
+
export { default as DonutChartSummary } from './DonutChartSummary/DonutChartSummary';
|
|
94
|
+
export { default as RangeTrack } from './RangeTrack/RangeTrack';
|
|
95
|
+
export { default as SegmentedTrack, SegmentedTrackSegment } from './SegmentedTrack/SegmentedTrack';
|
|
80
96
|
export { default as Tabs } from './Tabs/Tabs';
|
|
81
97
|
export { default as TabItem } from './Tabs/TabItem';
|
|
82
98
|
export { default as Toast } from './Toast/Toast';
|
|
@@ -86,11 +102,15 @@ export { default as AmountInput } from './AmountInput/AmountInput';
|
|
|
86
102
|
export { default as Popup } from './Popup/Popup';
|
|
87
103
|
export { default as PortfolioHero } from './PortfolioHero/PortfolioHero';
|
|
88
104
|
export { default as ProductLabel } from './ProductLabel/ProductLabel';
|
|
105
|
+
export { default as ProductOverview } from './ProductOverview/ProductOverview';
|
|
89
106
|
export { default as ProgressBadge } from './ProgressBadge/ProgressBadge';
|
|
90
107
|
export { default as SwappableAmount } from './SwappableAmount/SwappableAmount';
|
|
91
|
-
export { default as OTP } from './OTP/OTP';
|
|
108
|
+
export { default as OTP, OTPResend, useOtpResend } from './OTP/OTP';
|
|
92
109
|
export { default as PaymentFeedback } from './PaymentFeedback/PaymentFeedback';
|
|
93
110
|
export { default as StatItem } from './StatItem/StatItem';
|
|
111
|
+
export { default as StatGroup } from './StatGroup/StatGroup';
|
|
112
|
+
export { default as StrengthIndicator } from './StrengthIndicator/StrengthIndicator';
|
|
113
|
+
export { default as SummaryTile } from './SummaryTile/SummaryTile';
|
|
94
114
|
export { default as Text } from './Text/Text';
|
|
95
115
|
export { default as SegmentedControl } from './SegmentedControl/SegmentedControl';
|
|
96
116
|
export { default as Toggle } from './Toggle/Toggle';
|