jfs-components 0.0.72 → 0.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +239 -0
  3. package/lib/commonjs/components/AccountCard/AccountCard.js +247 -0
  4. package/lib/commonjs/components/AppBar/AppBar.js +17 -11
  5. package/lib/commonjs/components/BrandChip/BrandChip.js +149 -0
  6. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +229 -0
  7. package/lib/commonjs/components/CardInsight/CardInsight.js +166 -0
  8. package/lib/commonjs/components/CheckboxGroup/CheckboxGroup.js +67 -0
  9. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +140 -0
  10. package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +56 -9
  11. package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +272 -0
  12. package/lib/commonjs/components/CoverageRing/CoverageRing.js +141 -0
  13. package/lib/commonjs/components/DonutChart/DonutChart.js +309 -0
  14. package/lib/commonjs/components/DonutChartSummary/DonutChartSummary.js +155 -0
  15. package/lib/commonjs/components/Dropdown/Dropdown.js +214 -0
  16. package/lib/commonjs/components/DropdownInput/DropdownInput.js +542 -0
  17. package/lib/commonjs/components/FormField/FormField.js +328 -178
  18. package/lib/commonjs/components/LinearMeter/LinearMeter.js +9 -28
  19. package/lib/commonjs/components/LinearProgress/LinearProgress.js +68 -0
  20. package/lib/commonjs/components/LottieIntroBlock/LottieIntroBlock.js +150 -0
  21. package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +95 -0
  22. package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +286 -0
  23. package/lib/commonjs/components/OTP/OTP.js +381 -37
  24. package/lib/commonjs/components/PageHero/PageHero.js +153 -0
  25. package/lib/commonjs/components/PoweredByLabel/PoweredByLabel.js +135 -0
  26. package/lib/commonjs/components/PoweredByLabel/finvu.png +0 -0
  27. package/lib/commonjs/components/ProductOverview/ProductOverview.js +147 -0
  28. package/lib/commonjs/components/RangeTrack/RangeTrack.js +269 -0
  29. package/lib/commonjs/components/SavingsGoalSummary/SavingsGoalSummary.js +181 -0
  30. package/lib/commonjs/components/SegmentedTrack/SegmentedTrack.js +171 -0
  31. package/lib/commonjs/components/StatGroup/StatGroup.js +128 -0
  32. package/lib/commonjs/components/StatItem/StatItem.js +65 -35
  33. package/lib/commonjs/components/StrengthIndicator/StrengthIndicator.js +157 -0
  34. package/lib/commonjs/components/SummaryTile/SummaryTile.js +150 -0
  35. package/lib/commonjs/components/Text/Text.js +9 -2
  36. package/lib/commonjs/components/Tooltip/Tooltip.js +34 -27
  37. package/lib/commonjs/components/index.js +231 -1
  38. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  39. package/lib/commonjs/icons/registry.js +1 -1
  40. package/lib/commonjs/utils/index.js +7 -0
  41. package/lib/commonjs/utils/number-utils.js +57 -0
  42. package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +233 -0
  43. package/lib/module/components/AccountCard/AccountCard.js +241 -0
  44. package/lib/module/components/AppBar/AppBar.js +17 -11
  45. package/lib/module/components/BrandChip/BrandChip.js +143 -0
  46. package/lib/module/components/CardBankAccount/CardBankAccount.js +223 -0
  47. package/lib/module/components/CardInsight/CardInsight.js +161 -0
  48. package/lib/module/components/CheckboxGroup/CheckboxGroup.js +62 -0
  49. package/lib/module/components/CheckboxItem/CheckboxItem.js +134 -0
  50. package/lib/module/components/CircularProgressBar/CircularProgressBar.js +56 -9
  51. package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +266 -0
  52. package/lib/module/components/CoverageRing/CoverageRing.js +136 -0
  53. package/lib/module/components/DonutChart/DonutChart.js +303 -0
  54. package/lib/module/components/DonutChartSummary/DonutChartSummary.js +150 -0
  55. package/lib/module/components/Dropdown/Dropdown.js +206 -0
  56. package/lib/module/components/DropdownInput/DropdownInput.js +536 -0
  57. package/lib/module/components/FormField/FormField.js +330 -180
  58. package/lib/module/components/LinearMeter/LinearMeter.js +9 -28
  59. package/lib/module/components/LinearProgress/LinearProgress.js +63 -0
  60. package/lib/module/components/LottieIntroBlock/LottieIntroBlock.js +144 -0
  61. package/lib/module/components/MetricLegendItem/MetricLegendItem.js +90 -0
  62. package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +281 -0
  63. package/lib/module/components/OTP/OTP.js +381 -38
  64. package/lib/module/components/PageHero/PageHero.js +147 -0
  65. package/lib/module/components/PoweredByLabel/PoweredByLabel.js +130 -0
  66. package/lib/module/components/PoweredByLabel/finvu.png +0 -0
  67. package/lib/module/components/ProductOverview/ProductOverview.js +142 -0
  68. package/lib/module/components/RangeTrack/RangeTrack.js +263 -0
  69. package/lib/module/components/SavingsGoalSummary/SavingsGoalSummary.js +175 -0
  70. package/lib/module/components/SegmentedTrack/SegmentedTrack.js +166 -0
  71. package/lib/module/components/StatGroup/StatGroup.js +123 -0
  72. package/lib/module/components/StatItem/StatItem.js +66 -36
  73. package/lib/module/components/StrengthIndicator/StrengthIndicator.js +152 -0
  74. package/lib/module/components/SummaryTile/SummaryTile.js +145 -0
  75. package/lib/module/components/Text/Text.js +9 -2
  76. package/lib/module/components/Tooltip/Tooltip.js +34 -27
  77. package/lib/module/components/index.js +28 -2
  78. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  79. package/lib/module/icons/registry.js +1 -1
  80. package/lib/module/utils/index.js +2 -1
  81. package/lib/module/utils/number-utils.js +53 -0
  82. package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +71 -0
  83. package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +81 -0
  84. package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +43 -0
  85. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +86 -0
  86. package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +48 -0
  87. package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +41 -0
  88. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +72 -0
  89. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +11 -1
  90. package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +105 -0
  91. package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +90 -0
  92. package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +117 -0
  93. package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +103 -0
  94. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +62 -0
  95. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +107 -0
  96. package/lib/typescript/src/components/FormField/FormField.d.ts +76 -19
  97. package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +17 -0
  98. package/lib/typescript/src/components/LottieIntroBlock/LottieIntroBlock.d.ts +58 -0
  99. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +37 -0
  100. package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +119 -0
  101. package/lib/typescript/src/components/OTP/OTP.d.ts +88 -2
  102. package/lib/typescript/src/components/PageHero/PageHero.d.ts +53 -0
  103. package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +70 -0
  104. package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +39 -0
  105. package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +173 -0
  106. package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +95 -0
  107. package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +108 -0
  108. package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +45 -0
  109. package/lib/typescript/src/components/StatItem/StatItem.d.ts +24 -7
  110. package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +58 -0
  111. package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +60 -0
  112. package/lib/typescript/src/components/Text/Text.d.ts +12 -2
  113. package/lib/typescript/src/components/Tooltip/Tooltip.d.ts +13 -2
  114. package/lib/typescript/src/components/index.d.ts +29 -3
  115. package/lib/typescript/src/icons/registry.d.ts +1 -1
  116. package/lib/typescript/src/utils/index.d.ts +1 -0
  117. package/lib/typescript/src/utils/number-utils.d.ts +29 -0
  118. package/package.json +1 -3
  119. package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +323 -0
  120. package/src/components/AccountCard/AccountCard.tsx +376 -0
  121. package/src/components/AppBar/AppBar.tsx +25 -14
  122. package/src/components/BrandChip/BrandChip.tsx +235 -0
  123. package/src/components/CardBankAccount/CardBankAccount.tsx +321 -0
  124. package/src/components/CardInsight/CardInsight.tsx +239 -0
  125. package/src/components/CheckboxGroup/CheckboxGroup.tsx +86 -0
  126. package/src/components/CheckboxItem/CheckboxItem.tsx +209 -0
  127. package/src/components/CircularProgressBar/CircularProgressBar.tsx +74 -9
  128. package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +378 -0
  129. package/src/components/CoverageRing/CoverageRing.tsx +225 -0
  130. package/src/components/DonutChart/DonutChart.tsx +503 -0
  131. package/src/components/DonutChartSummary/DonutChartSummary.tsx +256 -0
  132. package/src/components/Dropdown/Dropdown.tsx +331 -0
  133. package/src/components/DropdownInput/DropdownInput.tsx +819 -0
  134. package/src/components/FormField/FormField.tsx +542 -215
  135. package/src/components/LinearMeter/LinearMeter.tsx +9 -39
  136. package/src/components/LinearProgress/LinearProgress.tsx +92 -0
  137. package/src/components/LottieIntroBlock/LottieIntroBlock.tsx +202 -0
  138. package/src/components/MetricLegendItem/MetricLegendItem.tsx +167 -0
  139. package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +438 -0
  140. package/src/components/OTP/OTP.tsx +476 -29
  141. package/src/components/PageHero/PageHero.tsx +200 -0
  142. package/src/components/PoweredByLabel/PoweredByLabel.tsx +221 -0
  143. package/src/components/PoweredByLabel/finvu.png +0 -0
  144. package/src/components/ProductOverview/ProductOverview.tsx +236 -0
  145. package/src/components/RangeTrack/RangeTrack.tsx +394 -0
  146. package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +269 -0
  147. package/src/components/SegmentedTrack/SegmentedTrack.tsx +268 -0
  148. package/src/components/StatGroup/StatGroup.tsx +169 -0
  149. package/src/components/StatItem/StatItem.tsx +117 -40
  150. package/src/components/StrengthIndicator/StrengthIndicator.tsx +205 -0
  151. package/src/components/SummaryTile/SummaryTile.tsx +251 -0
  152. package/src/components/Text/Text.tsx +24 -3
  153. package/src/components/Tooltip/Tooltip.tsx +50 -25
  154. package/src/components/index.ts +47 -3
  155. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  156. package/src/icons/registry.ts +1 -1
  157. package/src/utils/index.ts +1 -0
  158. package/src/utils/number-utils.ts +60 -0
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _reactUtils = require("../../utils/react-utils");
11
+ var _numberUtils = require("../../utils/number-utils");
12
+ var _Title = _interopRequireDefault(require("../Title/Title"));
13
+ var _LinearProgress = _interopRequireDefault(require("../LinearProgress/LinearProgress"));
14
+ var _MetricLegendItem = _interopRequireDefault(require("../MetricLegendItem/MetricLegendItem"));
15
+ var _jsxRuntime = require("react/jsx-runtime");
16
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
18
+ /**
19
+ * A single row in the savings-goal legend (current vs. target).
20
+ *
21
+ * `value` is a **numeric amount** (e.g. `240000`). It serves two purposes:
22
+ *
23
+ * 1. Display: rendered on the right side of the row using Indian numeric
24
+ * notation via {@link formatIndianNumber} and prefixed with `currency`
25
+ * (e.g. `240000` → `"₹2.4L"`).
26
+ * 2. Progress derivation: the bar fills to `current.value / target.value`
27
+ * automatically. There is no separate `progress` prop.
28
+ *
29
+ * Pass `value: undefined` to render a label-only row (the underlying
30
+ * {@link MetricLegendItem} hides the right slot in that case).
31
+ */
32
+
33
+ const DEFAULT_LEGEND_PADDING = 8;
34
+ const DEFAULT_MODES = Object.freeze({
35
+ 'LinearProgress Size': 'L'
36
+ });
37
+ const DEFAULT_CURRENT = {
38
+ label: 'Current (4 months)',
39
+ value: 240000
40
+ };
41
+ const DEFAULT_TARGET = {
42
+ label: 'Recommended (8 months)',
43
+ value: 480000
44
+ };
45
+
46
+ /**
47
+ * `SavingsGoalSummary` visualises progress toward a savings goal as:
48
+ *
49
+ * 1. A `Title` showing the percentage — **computed automatically** from
50
+ * `current.value / target.value`. There is no `progress` prop; the
51
+ * component owns the calculation so the title, bar and legend are always
52
+ * in sync.
53
+ * 2. A `LinearProgress` bar driven by the same derived ratio.
54
+ * 3. A two-row legend comparing **current** vs. **target**, where each numeric
55
+ * `value` is auto-formatted with Indian notation
56
+ * ({@link formatIndianNumber}) and prefixed with the `currency` symbol.
57
+ *
58
+ * The component is intentionally narrow in scope — it is the body of a savings
59
+ * insight card. Wrap it in `CardInsight` (or any container of your choice) to
60
+ * add a heading, badge or footer.
61
+ *
62
+ * @component
63
+ * @param {SavingsGoalSummaryProps} props
64
+ */
65
+ function SavingsGoalSummary({
66
+ currency = '₹',
67
+ current = DEFAULT_CURRENT,
68
+ target = DEFAULT_TARGET,
69
+ children,
70
+ modes = _reactUtils.EMPTY_MODES,
71
+ style,
72
+ titleStyle,
73
+ legendStyle
74
+ }) {
75
+ // Merge caller modes on top of the defaults so callers can override
76
+ // (e.g. switch to `LinearProgress Size: M`) while still receiving the
77
+ // sensible component-level default.
78
+ const mergedModes = (0, _react.useMemo)(() => modes === _reactUtils.EMPTY_MODES ? DEFAULT_MODES : {
79
+ ...DEFAULT_MODES,
80
+ ...modes
81
+ }, [modes]);
82
+
83
+ // Resolve the `LinearProgress` track / indicator colours so the legend
84
+ // dots automatically stay in sync with the progress bar without callers
85
+ // needing to plumb through `indicatorColor`.
86
+ //
87
+ // The token names AND the merge strategy must match `LinearProgress.tsx`
88
+ // exactly, otherwise the dot colours can drift from the bar:
89
+ // • Token aliases live in the `Emphasis` collection (modes High|Medium|Low),
90
+ // NOT `Emphasis / DataViz` — passing the wrong mode key would collapse
91
+ // both dots to the same default-mode colour.
92
+ // • Defaults are placed *before* `mergedModes` is spread, so callers can
93
+ // still override `Emphasis` via the `modes` prop (matches
94
+ // `LinearProgress`'s philosophy).
95
+ const indicatorColorFromTokens = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/indicator/background', {
96
+ Emphasis: 'High',
97
+ ...mergedModes
98
+ }) ?? '#5d00b5';
99
+ const trackColorFromTokens = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/track/background', {
100
+ Emphasis: 'Low',
101
+ ...mergedModes
102
+ }) ?? '#ede7ff';
103
+
104
+ // Single source of truth for the bar fill, the title percentage and the
105
+ // formatted legend amounts. There is intentionally no consumer-facing
106
+ // `progress` prop — the only way to change the bar is to change the
107
+ // numeric `current` / `target` values. This keeps the three views (title,
108
+ // bar, legend) impossible to desynchronise.
109
+ const resolvedProgress = (0, _react.useMemo)(() => {
110
+ const cv = current?.value;
111
+ const tv = target?.value;
112
+ if (typeof cv !== 'number' || typeof tv !== 'number' || tv <= 0) {
113
+ return 0;
114
+ }
115
+ return Math.min(Math.max(cv / tv, 0), 1);
116
+ }, [current, target]);
117
+ const percentageLabel = `${Math.round(resolvedProgress * 100)}%`;
118
+ const gap = (0, _figmaVariablesResolver.getVariableByName)('savingsGoalSummary/gap', mergedModes) ?? 23;
119
+ const legendGap = (0, _figmaVariablesResolver.getVariableByName)('savingsGoalSummary/legend/gap', mergedModes) ?? 16;
120
+ const customLegend = children ? (0, _reactUtils.cloneChildrenWithModes)(children, mergedModes) : null;
121
+ const defaultLegend = !customLegend && (current || target) ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
122
+ children: [current && /*#__PURE__*/(0, _jsxRuntime.jsx)(_MetricLegendItem.default, {
123
+ modes: mergedModes,
124
+ label: current.label,
125
+ value: formatLegendValue(current.value, currency),
126
+ indicatorColor: current.indicatorColor ?? indicatorColorFromTokens
127
+ }), target && /*#__PURE__*/(0, _jsxRuntime.jsx)(_MetricLegendItem.default, {
128
+ modes: mergedModes,
129
+ label: target.label,
130
+ value: formatLegendValue(target.value, currency),
131
+ indicatorColor: target.indicatorColor ?? trackColorFromTokens
132
+ })]
133
+ }) : null;
134
+ const legendNode = customLegend ?? defaultLegend;
135
+ const showLegend = legendNode != null;
136
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
137
+ style: [{
138
+ width: '100%',
139
+ gap,
140
+ alignItems: 'stretch'
141
+ }, style],
142
+ accessibilityLabel: `Savings goal progress, ${percentageLabel}`,
143
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Title.default, {
144
+ title: percentageLabel,
145
+ modes: mergedModes,
146
+ style: TITLE_CONTAINER_STYLE,
147
+ textStyle: titleStyle
148
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_LinearProgress.default, {
149
+ value: resolvedProgress,
150
+ modes: mergedModes
151
+ }), showLegend && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
152
+ style: [{
153
+ width: '100%',
154
+ padding: DEFAULT_LEGEND_PADDING,
155
+ gap: legendGap,
156
+ alignItems: 'stretch'
157
+ }, legendStyle],
158
+ children: legendNode
159
+ })]
160
+ });
161
+ }
162
+
163
+ /**
164
+ * Format a single legend `value` for display. Returns `undefined` when the
165
+ * value is missing so the underlying {@link MetricLegendItem} hides the right
166
+ * slot (matches the Figma `data` toggle = off).
167
+ */
168
+ function formatLegendValue(value, currency) {
169
+ if (typeof value !== 'number') return undefined;
170
+ return (0, _numberUtils.formatIndianNumber)(value, {
171
+ prefix: currency
172
+ });
173
+ }
174
+
175
+ // Neutralise the `Title` component's default page-level padding so it sits
176
+ // flush inside the summary card (the parent container owns spacing via `gap`).
177
+ const TITLE_CONTAINER_STYLE = {
178
+ paddingHorizontal: 0,
179
+ paddingVertical: 0
180
+ };
181
+ var _default = exports.default = SavingsGoalSummary;
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SegmentedTrackSegment = SegmentedTrackSegment;
7
+ exports.default = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _reactNative = require("react-native");
10
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
12
+ var _reactUtils = require("../../utils/react-utils");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ /**
16
+ * Per-segment data definition for the data-driven `segments` prop.
17
+ *
18
+ * Use `value` for proportional widths (segments share width by their value
19
+ * relative to the sum). When `value` is omitted, segments share the row
20
+ * equally (`flex: 1`).
21
+ *
22
+ * Use `modes` to override the per-segment design-token mode — typically the
23
+ * `Appearance / DataViz` mode for color theming, or `Emphasis / DataViz` to
24
+ * change the emphasis level. The parent already injects per-index defaults
25
+ * (segment 0 = High, 1 = Medium, 2 = Low, then cycling) so callers only need
26
+ * to pass `modes` when they want a different result.
27
+ */
28
+
29
+ /**
30
+ * Default per-index Emphasis modes applied to every segment when the caller
31
+ * does not provide its own `Emphasis / DataViz` override. Cycles for >3
32
+ * segments so additional segments fall back to the same High/Medium/Low
33
+ * rotation.
34
+ */
35
+ const DEFAULT_EMPHASIS_CYCLE = ['High', 'Medium', 'Low'];
36
+ const DEFAULT_SEGMENTS = [{}, {}, {}];
37
+
38
+ /**
39
+ * Compute the default `Emphasis / DataViz` mode for a segment at `index`.
40
+ * Cycles through {@link DEFAULT_EMPHASIS_CYCLE} so any number of segments
41
+ * gets a sensible default.
42
+ */
43
+ function defaultEmphasisFor(index) {
44
+ return DEFAULT_EMPHASIS_CYCLE[index % DEFAULT_EMPHASIS_CYCLE.length];
45
+ }
46
+ function SegmentedTrackSegment({
47
+ value = 1,
48
+ color,
49
+ modes = _reactUtils.EMPTY_MODES,
50
+ style,
51
+ accessibilityLabel
52
+ }) {
53
+ const resolvedColor = color ?? (0, _figmaVariablesResolver.getVariableByName)('dataViz/bg', modes) ?? '#5d00b5';
54
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
55
+ accessibilityLabel: accessibilityLabel,
56
+ style: [{
57
+ flex: value,
58
+ minWidth: 1,
59
+ height: '100%',
60
+ backgroundColor: resolvedColor
61
+ }, style]
62
+ });
63
+ }
64
+
65
+ /**
66
+ * `SegmentedTrack` renders a horizontal pill-shaped row of categorical
67
+ * segments. Use it for distribution / share-of breakdowns where each
68
+ * segment is a sibling category (not a directional or temporal progress).
69
+ *
70
+ * Defaults to three equal segments tinted at descending Emphasis levels
71
+ * (`High`, `Medium`, `Low`) so the shape reads as a single concept split
72
+ * three ways. Consumers can either pass the data-driven `segments` prop or
73
+ * a fully custom `children` slot of `SegmentedTrack.Segment`s.
74
+ *
75
+ * Each segment resolves its color through the `dataViz/bg` token, which
76
+ * cascades through `Emphasis / DataViz` and `Appearance / DataViz`. Pass
77
+ * `modes` per segment (or override `Appearance / DataViz` at the parent
78
+ * level via `modes`) to retheme the row without touching colors directly.
79
+ *
80
+ * @component
81
+ * @param {SegmentedTrackProps} props
82
+ */
83
+ function SegmentedTrack({
84
+ segments,
85
+ children,
86
+ modes: propModes = _reactUtils.EMPTY_MODES,
87
+ style,
88
+ segmentStyle,
89
+ accessibilityLabel
90
+ }) {
91
+ const {
92
+ modes: globalModes
93
+ } = (0, _JFSThemeProvider.useTokens)();
94
+ const modes = {
95
+ ...globalModes,
96
+ ...propModes
97
+ };
98
+ const trackHeight = (0, _figmaVariablesResolver.getVariableByName)('segmentedTrack/height', modes) ?? 24;
99
+ const trackRadius = (0, _figmaVariablesResolver.getVariableByName)('segmentedTrack/radius', modes) ?? 999;
100
+ const renderedSegments = renderSegments({
101
+ segments,
102
+ children,
103
+ modes,
104
+ segmentStyle
105
+ });
106
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
107
+ accessibilityRole: "image",
108
+ accessibilityLabel: accessibilityLabel,
109
+ style: [{
110
+ flexDirection: 'row',
111
+ alignItems: 'stretch',
112
+ height: trackHeight,
113
+ borderRadius: trackRadius,
114
+ overflow: 'hidden',
115
+ width: '100%',
116
+ backgroundColor: 'transparent'
117
+ }, style],
118
+ children: renderedSegments
119
+ });
120
+ }
121
+
122
+ /**
123
+ * Build the slot children. When the caller passes JSX `children`, every
124
+ * top-level element is treated as one segment and receives merged `modes`
125
+ * (parent + per-index Emphasis default + the child's own `modes` taking
126
+ * priority). Otherwise the data-driven `segments` array is rendered.
127
+ */
128
+ function renderSegments({
129
+ segments,
130
+ children,
131
+ modes,
132
+ segmentStyle
133
+ }) {
134
+ if (children !== undefined && children !== null) {
135
+ const flat = (0, _reactUtils.flattenChildren)(children);
136
+ return flat.map((child, index) => {
137
+ if (! /*#__PURE__*/_react.default.isValidElement(child)) {
138
+ return child;
139
+ }
140
+ const childProps = child.props ?? {};
141
+ const childModes = childProps.modes;
142
+ const mergedModes = {
143
+ ...modes,
144
+ 'Emphasis / DataViz': defaultEmphasisFor(index),
145
+ ...(childModes || {})
146
+ };
147
+ return /*#__PURE__*/_react.default.cloneElement(child, {
148
+ ...childProps,
149
+ modes: mergedModes,
150
+ key: child.key ?? `segment-${index}`
151
+ });
152
+ });
153
+ }
154
+ const list = segments && segments.length > 0 ? segments : DEFAULT_SEGMENTS;
155
+ return list.map((segment, index) => {
156
+ const segmentModes = {
157
+ ...modes,
158
+ 'Emphasis / DataViz': defaultEmphasisFor(index),
159
+ ...(segment.modes || {})
160
+ };
161
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(SegmentedTrackSegment, {
162
+ value: segment.value ?? 1,
163
+ color: segment.color,
164
+ modes: segmentModes,
165
+ style: [segmentStyle, segment.style],
166
+ accessibilityLabel: segment.accessibilityLabel
167
+ }, segment.key ?? `segment-${index}`);
168
+ });
169
+ }
170
+ SegmentedTrack.Segment = SegmentedTrackSegment;
171
+ var _default = exports.default = SegmentedTrack;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _reactUtils = require("../../utils/react-utils");
11
+ var _StatItem = _interopRequireDefault(require("../StatItem/StatItem"));
12
+ var _Divider = _interopRequireDefault(require("../Divider/Divider"));
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ const DEFAULT_ITEMS = [{
16
+ label: 'Updates',
17
+ value: 'Daily'
18
+ }, {
19
+ label: 'Data range',
20
+ value: '24 months'
21
+ }, {
22
+ label: 'Validity',
23
+ value: '24 months'
24
+ }, {
25
+ label: 'Stored for',
26
+ value: '1 month'
27
+ }];
28
+
29
+ /**
30
+ * StatGroup renders a card-style container holding a horizontal row of
31
+ * `StatItem`s separated by vertical dividers. It is typically used to surface
32
+ * 3–5 short metrics (e.g. validity, data range, storage) at a glance.
33
+ *
34
+ * Pass `items` for the simple data-driven case, or use the `children` slot
35
+ * for full control over the row contents (the component still auto-inserts
36
+ * vertical dividers between top-level children).
37
+ *
38
+ * @component
39
+ * @param {StatGroupProps} props
40
+ */
41
+ function StatGroup({
42
+ items,
43
+ children,
44
+ modes = _reactUtils.EMPTY_MODES,
45
+ style
46
+ }) {
47
+ const background = (0, _figmaVariablesResolver.getVariableByName)('statGroup/background', modes) ?? '#ffffff';
48
+ const strokeColor = (0, _figmaVariablesResolver.getVariableByName)('statGroup/stroke/color', modes) ?? '#ebebed';
49
+ const strokeSize = (0, _figmaVariablesResolver.getVariableByName)('statGroup/stroke/size', modes) ?? 1;
50
+ const radius = (0, _figmaVariablesResolver.getVariableByName)('statGroup/radius', modes) ?? 12;
51
+ const paddingTop = (0, _figmaVariablesResolver.getVariableByName)('statGroup/padding/top', modes) ?? 16;
52
+ const paddingRight = (0, _figmaVariablesResolver.getVariableByName)('statGroup/padding/right', modes) ?? 0;
53
+ const paddingBottom = (0, _figmaVariablesResolver.getVariableByName)('statGroup/padding/bottom', modes) ?? 12;
54
+ const paddingLeft = (0, _figmaVariablesResolver.getVariableByName)('statGroup/padding/left', modes) ?? 0;
55
+ const containerStyle = {
56
+ backgroundColor: background,
57
+ borderColor: strokeColor,
58
+ borderWidth: strokeSize,
59
+ borderStyle: 'solid',
60
+ borderRadius: radius,
61
+ paddingTop,
62
+ paddingRight,
63
+ paddingBottom,
64
+ paddingLeft,
65
+ overflow: 'hidden'
66
+ };
67
+ const slotChildren = renderSlotChildren({
68
+ items,
69
+ children,
70
+ modes
71
+ });
72
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
73
+ style: [containerStyle, style],
74
+ accessibilityRole: "summary",
75
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
76
+ style: {
77
+ flexDirection: 'row',
78
+ alignItems: 'stretch',
79
+ width: '100%'
80
+ },
81
+ children: slotChildren
82
+ })
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Build the row of items: render either the supplied children or the
88
+ * `items` array, wrap each entry so it grows equally, and inject a vertical
89
+ * `Divider` between siblings.
90
+ */
91
+ function renderSlotChildren({
92
+ items,
93
+ children,
94
+ modes
95
+ }) {
96
+ let nodes;
97
+ if (children !== undefined && children !== null) {
98
+ const cloned = (0, _reactUtils.cloneChildrenWithModes)(children, modes);
99
+ nodes = (0, _reactUtils.flattenChildren)(cloned);
100
+ } else {
101
+ const list = items && items.length > 0 ? items : DEFAULT_ITEMS;
102
+ nodes = list.map((item, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_StatItem.default, {
103
+ label: item.label,
104
+ value: item.value,
105
+ labelPosition: "Bottom",
106
+ modes: modes
107
+ }, item.key ?? `${item.label ?? 'item'}-${index}`));
108
+ }
109
+ const result = [];
110
+ nodes.forEach((node, index) => {
111
+ if (index > 0) {
112
+ result.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
113
+ direction: "vertical",
114
+ modes: modes
115
+ }, `divider-${index}`));
116
+ }
117
+ result.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
118
+ style: {
119
+ flex: 1,
120
+ minWidth: 0,
121
+ alignSelf: 'center'
122
+ },
123
+ children: node
124
+ }, `slot-${index}`));
125
+ });
126
+ return result;
127
+ }
128
+ var _default = exports.default = StatGroup;
@@ -11,8 +11,12 @@ var _reactUtils = require("../../utils/react-utils");
11
11
  var _jsxRuntime = require("react/jsx-runtime");
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
13
  /**
14
- * StatItem displays a label/value pair with the value in a large, bold style.
15
- * Useful for metrics, product stats, or KPI callouts.
14
+ * StatItem displays a label/value pair, useful for product stats, metrics
15
+ * or KPI callouts.
16
+ *
17
+ * Supports two layouts via the `labelPosition` variant:
18
+ * - `'Top'` — Small label above a large prominent value (default).
19
+ * - `'Bottom'` — Value above a smaller label, content centered.
16
20
  *
17
21
  * @component
18
22
  * @param {StatItemProps} props
@@ -20,43 +24,69 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
20
24
  function StatItem({
21
25
  label = 'Purity verified by NABL',
22
26
  value = '99.99%',
27
+ labelPosition = 'Top',
23
28
  modes = _reactUtils.EMPTY_MODES,
24
- style
29
+ style,
30
+ labelStyle,
31
+ valueStyle
25
32
  }) {
26
- const gap = (0, _figmaVariablesResolver.getVariableByName)('statItem/gap', modes) ?? 2;
27
- const labelForeground = (0, _figmaVariablesResolver.getVariableByName)('statItem/label/foreground', modes) ?? '#1a1c1f';
33
+ const isBottom = labelPosition === 'Bottom';
34
+
35
+ // The Figma `Bottom` variant overrides token values locally inside the
36
+ // component (it is not exposed in the design-tokens JSON), so the resolved
37
+ // token values reflect only the `Top` variant. For the `Bottom` variant we
38
+ // therefore use hardcoded literals that match the Figma design, while still
39
+ // allowing the resolver to surface any future mode-based overrides for the
40
+ // `Top` variant.
41
+ const gap = isBottom ? 6 : (0, _figmaVariablesResolver.getVariableByName)('statItem/gap', modes) ?? 2;
42
+ const labelForeground = isBottom ? '#24262b' : (0, _figmaVariablesResolver.getVariableByName)('statItem/label/foreground', modes) ?? '#1a1c1f';
28
43
  const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('statItem/label/fontFamily', modes) ?? 'JioType Var';
29
- const labelFontSize = (0, _figmaVariablesResolver.getVariableByName)('statItem/label/fontSize', modes) ?? 12;
30
- const labelFontWeight = (0, _figmaVariablesResolver.getVariableByName)('statItem/label/fontWeight', modes) ?? '500';
31
- const labelLineHeight = (0, _figmaVariablesResolver.getVariableByName)('statItem/label/lineHeight', modes) ?? 16;
32
- const valueForeground = (0, _figmaVariablesResolver.getVariableByName)('statItem/value/foreground', modes) ?? '#0d0d0f';
44
+ const labelFontSize = isBottom ? 10 : (0, _figmaVariablesResolver.getVariableByName)('statItem/label/fontSize', modes) ?? 12;
45
+ const labelFontWeightRaw = isBottom ? 400 : (0, _figmaVariablesResolver.getVariableByName)('statItem/label/fontWeight', modes) ?? 500;
46
+ const labelFontWeight = String(labelFontWeightRaw);
47
+ const labelLineHeight = isBottom ? 13 : (0, _figmaVariablesResolver.getVariableByName)('statItem/label/lineHeight', modes) ?? 16;
48
+ const valueForeground = isBottom ? '#141414' : (0, _figmaVariablesResolver.getVariableByName)('statItem/value/foreground', modes) ?? '#0d0d0f';
33
49
  const valueFontFamily = (0, _figmaVariablesResolver.getVariableByName)('statItem/value/fontFamily', modes) ?? 'JioType Var';
34
- const valueFontSize = (0, _figmaVariablesResolver.getVariableByName)('statItem/value/fontSize', modes) ?? 26;
35
- const valueFontWeight = (0, _figmaVariablesResolver.getVariableByName)('statItem/value/fontWeight', modes) ?? '900';
36
- const valueLineHeight = (0, _figmaVariablesResolver.getVariableByName)('statItem/value/lineHeight', modes) ?? 26;
37
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
38
- style: [{
39
- gap: gap
40
- }, style],
41
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
42
- style: {
43
- color: labelForeground,
44
- fontFamily: labelFontFamily,
45
- fontSize: labelFontSize,
46
- fontWeight: String(labelFontWeight),
47
- lineHeight: labelLineHeight
48
- },
49
- children: label
50
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
51
- style: {
52
- color: valueForeground,
53
- fontFamily: valueFontFamily,
54
- fontSize: valueFontSize,
55
- fontWeight: String(valueFontWeight),
56
- lineHeight: valueLineHeight
57
- },
58
- children: value
59
- })]
50
+ const valueFontSize = isBottom ? 12 : (0, _figmaVariablesResolver.getVariableByName)('statItem/value/fontSize', modes) ?? 26;
51
+ const valueFontWeightRaw = isBottom ? 500 : (0, _figmaVariablesResolver.getVariableByName)('statItem/value/fontWeight', modes) ?? 900;
52
+ const valueFontWeight = String(valueFontWeightRaw);
53
+ const valueLineHeight = isBottom ? 16 : (0, _figmaVariablesResolver.getVariableByName)('statItem/value/lineHeight', modes) ?? 26;
54
+ const containerStyle = {
55
+ gap,
56
+ alignItems: isBottom ? 'center' : 'flex-start',
57
+ justifyContent: isBottom ? 'center' : 'flex-start'
58
+ };
59
+ const labelTextStyle = {
60
+ color: labelForeground,
61
+ fontFamily: labelFontFamily,
62
+ fontSize: labelFontSize,
63
+ fontWeight: labelFontWeight,
64
+ lineHeight: labelLineHeight,
65
+ textAlign: isBottom ? 'center' : 'left'
66
+ };
67
+ const valueTextStyle = {
68
+ color: valueForeground,
69
+ fontFamily: valueFontFamily,
70
+ fontSize: valueFontSize,
71
+ fontWeight: valueFontWeight,
72
+ lineHeight: valueLineHeight,
73
+ textAlign: isBottom ? 'center' : 'left'
74
+ };
75
+ const labelNode = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
76
+ style: [labelTextStyle, labelStyle],
77
+ children: label
78
+ });
79
+ const valueNode = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
80
+ style: [valueTextStyle, valueStyle],
81
+ children: value
82
+ });
83
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
84
+ style: [containerStyle, style],
85
+ children: isBottom ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
86
+ children: [valueNode, labelNode]
87
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
88
+ children: [labelNode, valueNode]
89
+ })
60
90
  });
61
91
  }
62
92
  var _default = exports.default = StatItem;