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.
Files changed (141) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +239 -0
  3. package/lib/commonjs/components/BrandChip/BrandChip.js +149 -0
  4. package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +2 -2
  5. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +213 -0
  6. package/lib/commonjs/components/CardFinancialCondition/CardFinancialCondition.js +213 -0
  7. package/lib/commonjs/components/CardInsight/CardInsight.js +166 -0
  8. package/lib/commonjs/components/Carousel/Carousel.js +9 -7
  9. package/lib/commonjs/components/CheckboxGroup/CheckboxGroup.js +67 -0
  10. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +125 -0
  11. package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +56 -9
  12. package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +272 -0
  13. package/lib/commonjs/components/CoverageRing/CoverageRing.js +141 -0
  14. package/lib/commonjs/components/DonutChart/DonutChart.js +309 -0
  15. package/lib/commonjs/components/DonutChartSummary/DonutChartSummary.js +155 -0
  16. package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -2
  17. package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +132 -0
  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/MetricLegendItem/MetricLegendItem.js +95 -0
  21. package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +286 -0
  22. package/lib/commonjs/components/OTP/OTP.js +381 -37
  23. package/lib/commonjs/components/ProductOverview/ProductOverview.js +147 -0
  24. package/lib/commonjs/components/Radio/Radio.js +194 -0
  25. package/lib/commonjs/components/RadioButton/RadioButton.js +21 -188
  26. package/lib/commonjs/components/RangeTrack/RangeTrack.js +269 -0
  27. package/lib/commonjs/components/SavingsGoalSummary/SavingsGoalSummary.js +181 -0
  28. package/lib/commonjs/components/SegmentedTrack/SegmentedTrack.js +171 -0
  29. package/lib/commonjs/components/StatGroup/StatGroup.js +128 -0
  30. package/lib/commonjs/components/StatItem/StatItem.js +65 -35
  31. package/lib/commonjs/components/StrengthIndicator/StrengthIndicator.js +157 -0
  32. package/lib/commonjs/components/SummaryTile/SummaryTile.js +150 -0
  33. package/lib/commonjs/components/index.js +192 -1
  34. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  35. package/lib/commonjs/icons/registry.js +1 -1
  36. package/lib/commonjs/utils/index.js +7 -0
  37. package/lib/commonjs/utils/number-utils.js +57 -0
  38. package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +233 -0
  39. package/lib/module/components/BrandChip/BrandChip.js +143 -0
  40. package/lib/module/components/CardAdvisory/CardAdvisory.js +2 -2
  41. package/lib/module/components/CardBankAccount/CardBankAccount.js +208 -0
  42. package/lib/module/components/CardFinancialCondition/CardFinancialCondition.js +207 -0
  43. package/lib/module/components/CardInsight/CardInsight.js +161 -0
  44. package/lib/module/components/Carousel/Carousel.js +9 -7
  45. package/lib/module/components/CheckboxGroup/CheckboxGroup.js +62 -0
  46. package/lib/module/components/CheckboxItem/CheckboxItem.js +119 -0
  47. package/lib/module/components/CircularProgressBar/CircularProgressBar.js +56 -9
  48. package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +266 -0
  49. package/lib/module/components/CoverageRing/CoverageRing.js +136 -0
  50. package/lib/module/components/DonutChart/DonutChart.js +303 -0
  51. package/lib/module/components/DonutChartSummary/DonutChartSummary.js +150 -0
  52. package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -2
  53. package/lib/module/components/InstitutionBadge/InstitutionBadge.js +127 -0
  54. package/lib/module/components/LinearMeter/LinearMeter.js +9 -28
  55. package/lib/module/components/LinearProgress/LinearProgress.js +63 -0
  56. package/lib/module/components/MetricLegendItem/MetricLegendItem.js +90 -0
  57. package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +281 -0
  58. package/lib/module/components/OTP/OTP.js +381 -38
  59. package/lib/module/components/ProductOverview/ProductOverview.js +142 -0
  60. package/lib/module/components/Radio/Radio.js +188 -0
  61. package/lib/module/components/RadioButton/RadioButton.js +20 -185
  62. package/lib/module/components/RangeTrack/RangeTrack.js +263 -0
  63. package/lib/module/components/SavingsGoalSummary/SavingsGoalSummary.js +175 -0
  64. package/lib/module/components/SegmentedTrack/SegmentedTrack.js +166 -0
  65. package/lib/module/components/StatGroup/StatGroup.js +123 -0
  66. package/lib/module/components/StatItem/StatItem.js +66 -36
  67. package/lib/module/components/StrengthIndicator/StrengthIndicator.js +152 -0
  68. package/lib/module/components/SummaryTile/SummaryTile.js +145 -0
  69. package/lib/module/components/index.js +28 -1
  70. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  71. package/lib/module/icons/registry.js +1 -1
  72. package/lib/module/utils/index.js +2 -1
  73. package/lib/module/utils/number-utils.js +53 -0
  74. package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +71 -0
  75. package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +43 -0
  76. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +79 -0
  77. package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +50 -0
  78. package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +48 -0
  79. package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +41 -0
  80. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +56 -0
  81. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +11 -1
  82. package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +105 -0
  83. package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +90 -0
  84. package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +117 -0
  85. package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +103 -0
  86. package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +30 -0
  87. package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +17 -0
  88. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +37 -0
  89. package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +119 -0
  90. package/lib/typescript/src/components/OTP/OTP.d.ts +88 -2
  91. package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +39 -0
  92. package/lib/typescript/src/components/Radio/Radio.d.ts +30 -0
  93. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +20 -28
  94. package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +173 -0
  95. package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +95 -0
  96. package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +108 -0
  97. package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +45 -0
  98. package/lib/typescript/src/components/StatItem/StatItem.d.ts +24 -7
  99. package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +58 -0
  100. package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +60 -0
  101. package/lib/typescript/src/components/index.d.ts +29 -2
  102. package/lib/typescript/src/icons/registry.d.ts +1 -1
  103. package/lib/typescript/src/utils/index.d.ts +1 -0
  104. package/lib/typescript/src/utils/number-utils.d.ts +29 -0
  105. package/package.json +1 -1
  106. package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +323 -0
  107. package/src/components/BrandChip/BrandChip.tsx +235 -0
  108. package/src/components/CardAdvisory/CardAdvisory.tsx +2 -2
  109. package/src/components/CardBankAccount/CardBankAccount.tsx +295 -0
  110. package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +366 -0
  111. package/src/components/CardInsight/CardInsight.tsx +239 -0
  112. package/src/components/Carousel/Carousel.tsx +14 -6
  113. package/src/components/CheckboxGroup/CheckboxGroup.tsx +86 -0
  114. package/src/components/CheckboxItem/CheckboxItem.tsx +174 -0
  115. package/src/components/CircularProgressBar/CircularProgressBar.tsx +74 -9
  116. package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +378 -0
  117. package/src/components/CoverageRing/CoverageRing.tsx +225 -0
  118. package/src/components/DonutChart/DonutChart.tsx +503 -0
  119. package/src/components/DonutChartSummary/DonutChartSummary.tsx +256 -0
  120. package/src/components/HoldingsCard/HoldingsCard.tsx +2 -2
  121. package/src/components/InstitutionBadge/InstitutionBadge.tsx +216 -0
  122. package/src/components/LinearMeter/LinearMeter.tsx +9 -39
  123. package/src/components/LinearProgress/LinearProgress.tsx +92 -0
  124. package/src/components/MetricLegendItem/MetricLegendItem.tsx +167 -0
  125. package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +438 -0
  126. package/src/components/OTP/OTP.tsx +476 -29
  127. package/src/components/ProductOverview/ProductOverview.tsx +236 -0
  128. package/src/components/Radio/Radio.tsx +227 -0
  129. package/src/components/RadioButton/RadioButton.tsx +23 -225
  130. package/src/components/RangeTrack/RangeTrack.tsx +394 -0
  131. package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +269 -0
  132. package/src/components/SegmentedTrack/SegmentedTrack.tsx +268 -0
  133. package/src/components/StatGroup/StatGroup.tsx +169 -0
  134. package/src/components/StatItem/StatItem.tsx +117 -40
  135. package/src/components/StrengthIndicator/StrengthIndicator.tsx +205 -0
  136. package/src/components/SummaryTile/SummaryTile.tsx +251 -0
  137. package/src/components/index.ts +39 -2
  138. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  139. package/src/icons/registry.ts +1 -1
  140. package/src/utils/index.ts +1 -0
  141. package/src/utils/number-utils.ts +60 -0
@@ -0,0 +1,132 @@
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 _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
11
+ var _reactUtils = require("../../utils/react-utils");
12
+ var _MediaSource = _interopRequireDefault(require("../../utils/MediaSource"));
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ 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); }
16
+ // Default avatar asset (shared with the Avatar component) so that
17
+ // InstitutionBadge has a sensible visual fallback when no `source` is
18
+ // provided in stories or playgrounds.
19
+ const DEFAULT_AVATAR_IMAGE = require('../Avatar/31595e70c4181263f9971590224b12934b280c9b.png');
20
+ const toNumber = (value, fallback) => {
21
+ if (typeof value === 'number') {
22
+ return Number.isFinite(value) ? value : fallback;
23
+ }
24
+ if (typeof value === 'string') {
25
+ const parsed = Number(value);
26
+ return Number.isFinite(parsed) ? parsed : fallback;
27
+ }
28
+ return fallback;
29
+ };
30
+ const toFontWeight = (value, fallback) => {
31
+ if (typeof value === 'number') {
32
+ return String(value);
33
+ }
34
+ if (typeof value === 'string') {
35
+ return value;
36
+ }
37
+ return fallback;
38
+ };
39
+ function resolveInstitutionBadgeTokens(modes) {
40
+ const gap = toNumber((0, _figmaVariablesResolver.getVariableByName)('institutionBadge/gap', modes), 8);
41
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('institutionBadge/foreground', modes) || '#080d1a';
42
+ const fontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('institutionBadge/fontSize', modes), 14);
43
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('institutionBadge/fontFamily', modes) || 'JioType Var';
44
+ const lineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('institutionBadge/lineHeight', modes), 18);
45
+ const fontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('institutionBadge/fontWeight', modes), '500');
46
+
47
+ // Avatar wrapper styled from shared `avatar/*` tokens so the badge stays
48
+ // visually consistent with other Avatar-bearing components.
49
+ const avatarSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('avatar/size', modes), 36);
50
+ const avatarRadiusRaw = toNumber((0, _figmaVariablesResolver.getVariableByName)('avatar/radius', modes), 9999);
51
+ // 9999 is the design-token sentinel for "perfect circle".
52
+ const avatarRadius = avatarRadiusRaw === 9999 ? avatarSize / 2 : avatarRadiusRaw;
53
+ const avatarBorderColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/border/color', modes) || 'rgba(255,255,255,0)';
54
+ const avatarBorderSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('avatar/border/size', modes), 1);
55
+ return {
56
+ containerStyle: {
57
+ alignItems: 'center',
58
+ flexDirection: 'row',
59
+ gap
60
+ },
61
+ avatarStyle: {
62
+ width: avatarSize,
63
+ height: avatarSize,
64
+ borderRadius: avatarRadius,
65
+ borderWidth: avatarBorderSize,
66
+ borderColor: avatarBorderColor,
67
+ overflow: 'hidden'
68
+ },
69
+ avatarSize,
70
+ labelStyle: {
71
+ color: foreground,
72
+ fontFamily,
73
+ fontSize,
74
+ fontWeight,
75
+ lineHeight
76
+ }
77
+ };
78
+ }
79
+
80
+ // Default Avatar Size = M (36px in tokens) — matches the Figma badge. Callers
81
+ // can override via `modes` if needed.
82
+ const DEFAULT_AVATAR_MODE = 'M';
83
+ function InstitutionBadge({
84
+ label = 'State Bank of India',
85
+ source,
86
+ avatarSlot,
87
+ modes: propModes = _reactUtils.EMPTY_MODES,
88
+ style,
89
+ labelStyle,
90
+ accessibilityLabel,
91
+ ...rest
92
+ }) {
93
+ const {
94
+ modes: globalModes
95
+ } = (0, _JFSThemeProvider.useTokens)();
96
+ const modes = (0, _react.useMemo)(() => globalModes === _reactUtils.EMPTY_MODES && propModes === _reactUtils.EMPTY_MODES ? _reactUtils.EMPTY_MODES : {
97
+ ...globalModes,
98
+ ...propModes
99
+ }, [globalModes, propModes]);
100
+ const avatarModes = (0, _react.useMemo)(() => ({
101
+ 'Avatar Size': DEFAULT_AVATAR_MODE,
102
+ ...modes
103
+ }), [modes]);
104
+ const tokens = (0, _react.useMemo)(() => resolveInstitutionBadgeTokens(avatarModes), [avatarModes]);
105
+ const processedAvatarSlot = (0, _react.useMemo)(() => {
106
+ if (!avatarSlot) return null;
107
+ const processed = (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(avatarSlot), avatarModes);
108
+ return processed.length === 1 ? processed[0] : processed;
109
+ }, [avatarSlot, avatarModes]);
110
+ const resolvedSource = source ?? DEFAULT_AVATAR_IMAGE;
111
+ const defaultAccessibilityLabel = accessibilityLabel ?? label;
112
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
113
+ accessibilityLabel: defaultAccessibilityLabel,
114
+ style: [tokens.containerStyle, style],
115
+ ...rest,
116
+ children: [processedAvatarSlot || /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
117
+ style: tokens.avatarStyle,
118
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_MediaSource.default, {
119
+ source: resolvedSource,
120
+ size: tokens.avatarSize,
121
+ resizeMode: "cover",
122
+ accessibilityElementsHidden: true,
123
+ importantForAccessibility: "no"
124
+ })
125
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
126
+ style: [tokens.labelStyle, labelStyle],
127
+ numberOfLines: 1,
128
+ children: label
129
+ })]
130
+ });
131
+ }
132
+ var _default = exports.default = /*#__PURE__*/_react.default.memo(InstitutionBadge);
@@ -9,6 +9,7 @@ var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
10
  var _reactUtils = require("../../utils/react-utils");
11
11
  var _MoneyValue = _interopRequireDefault(require("../MoneyValue/MoneyValue"));
12
+ var _LinearProgress = _interopRequireDefault(require("../LinearProgress/LinearProgress"));
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  const LinearMeterLabel = ({
@@ -46,14 +47,6 @@ const LinearMeter = ({
46
47
  ...rest
47
48
  }) => {
48
49
  const gap = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/gap', modes);
49
- // Track tokens
50
- const trackBg = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/track/background', modes);
51
- const trackHeight = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/track/height', modes);
52
- const trackRadius = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/track/radius', modes);
53
-
54
- // Indicator tokens
55
- const indicatorBg = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/indicator/background', modes);
56
- const indicatorRadius = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/indicator/radius', modes);
57
50
 
58
51
  // Wrap tokens
59
52
  const wrapGap = (0, _figmaVariablesResolver.getVariableByName)('linearMeter/wrap/gap', modes);
@@ -91,10 +84,6 @@ const LinearMeter = ({
91
84
  })]
92
85
  });
93
86
  const content = children ? childrenWithModes : defaultContent;
94
-
95
- // Calculate width percentage
96
- const clampedValue = Math.min(Math.max(value, 0), 1);
97
- const widthPercent = `${clampedValue * 100}%`;
98
87
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
99
88
  style: [{
100
89
  flexDirection: 'row',
@@ -102,22 +91,14 @@ const LinearMeter = ({
102
91
  gap
103
92
  }, style],
104
93
  ...rest,
105
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
106
- style: [{
107
- flex: 1,
108
- height: trackHeight,
109
- backgroundColor: trackBg,
110
- borderRadius: trackRadius,
111
- overflow: 'hidden' // Ensure indicator stays inside
112
- }, trackStyle],
113
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
114
- style: [{
115
- width: widthPercent,
116
- height: '100%',
117
- backgroundColor: indicatorBg,
118
- borderRadius: indicatorRadius
119
- }, indicatorStyle]
120
- })
94
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_LinearProgress.default, {
95
+ value: value,
96
+ modes: modes,
97
+ style: {
98
+ flex: 1
99
+ },
100
+ trackStyle: trackStyle,
101
+ indicatorStyle: indicatorStyle
121
102
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
122
103
  style: {
123
104
  flexDirection: 'row',
@@ -0,0 +1,68 @@
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 _jsxRuntime = require("react/jsx-runtime");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ const LinearProgress = ({
14
+ value = 0,
15
+ modes = _reactUtils.EMPTY_MODES,
16
+ style,
17
+ trackStyle,
18
+ indicatorStyle,
19
+ ...rest
20
+ }) => {
21
+ // The track and the progress indicator are intentionally rendered at
22
+ // different emphasis levels by default: the track sits in the
23
+ // background as a low-emphasis surface, while the progress indicator
24
+ // is the high-emphasis foreground. Defaults are placed *before* the
25
+ // user-provided modes spread, so callers can still override
26
+ // `Emphasis / DataViz` (or any other mode) via the `modes` prop.
27
+ const trackModes = {
28
+ 'Emphasis': 'Low',
29
+ ...modes
30
+ };
31
+ const progressModes = {
32
+ 'Emphasis': 'High',
33
+ ...modes
34
+ };
35
+ const trackHeight = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/track/height', trackModes) ?? 8;
36
+ const trackRadius = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/track/radius', trackModes) ?? 999;
37
+ const trackBg = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/track/background', trackModes) ?? '#ede7ff';
38
+ const indicatorHeight = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/indicator/height', progressModes) ?? 8;
39
+ const indicatorRadius = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/indicator/radius', progressModes) ?? 999;
40
+ const indicatorBg = (0, _figmaVariablesResolver.getVariableByName)('linearProgress/indicator/background', progressModes) ?? '#5d00b5';
41
+ const clampedValue = Math.min(Math.max(value, 0), 1);
42
+ const widthPercent = `${clampedValue * 100}%`;
43
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
44
+ style: [{
45
+ height: trackHeight,
46
+ backgroundColor: trackBg,
47
+ borderRadius: trackRadius,
48
+ overflow: 'hidden',
49
+ width: '100%'
50
+ }, style, trackStyle],
51
+ accessibilityRole: "progressbar",
52
+ accessibilityValue: {
53
+ min: 0,
54
+ max: 1,
55
+ now: clampedValue
56
+ },
57
+ ...rest,
58
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
59
+ style: [{
60
+ width: widthPercent,
61
+ height: indicatorHeight,
62
+ backgroundColor: indicatorBg,
63
+ borderRadius: indicatorRadius
64
+ }, indicatorStyle]
65
+ })
66
+ });
67
+ };
68
+ var _default = exports.default = LinearProgress;
@@ -0,0 +1,95 @@
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 _jsxRuntime = require("react/jsx-runtime");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ /**
14
+ * MetricLegendItem renders a horizontal row consisting of a small colored
15
+ * indicator dot, a label and an optional value. It is used in chart legends
16
+ * and similar metric callouts.
17
+ *
18
+ * @component
19
+ * @param {MetricLegendItemProps} props
20
+ */
21
+ function MetricLegendItem({
22
+ label = 'Current (4 months)',
23
+ value,
24
+ indicatorColor,
25
+ modes = _reactUtils.EMPTY_MODES,
26
+ style,
27
+ indicatorStyle,
28
+ labelStyle,
29
+ valueStyle
30
+ }) {
31
+ const gap = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/gap', modes) ?? 4;
32
+ const textWrapGap = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/textWrap/gap', modes) ?? 4;
33
+ const indicatorSize = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/indicator/size', modes) ?? 8;
34
+ const indicatorRadius = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/indicator/radius', modes) ?? 999;
35
+ const indicatorBg = indicatorColor ?? (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/indicator/bg', modes) ?? '#f7ab21';
36
+ const labelColor = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/label/color', modes) ?? '#000000';
37
+ const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/label/fontFamily', modes) ?? 'JioType Var';
38
+ const labelFontSize = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/label/fontSize', modes) ?? 12;
39
+ const labelLineHeight = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/label/lineHeight', modes) ?? 16;
40
+ const labelFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/label/fontWeight', modes) ?? 400;
41
+ const labelFontWeight = String(labelFontWeightRaw);
42
+ const valueColor = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/value/color', modes) ?? '#000000';
43
+ const valueFontFamily = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/value/fontFamily', modes) ?? 'JioType Var';
44
+ const valueFontSize = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/value/fontSize', modes) ?? 12;
45
+ const valueLineHeight = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/value/lineHeight', modes) ?? 16;
46
+ const valueFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('metricLegendItem/value/fontWeight', modes) ?? 500;
47
+ const valueFontWeight = String(valueFontWeightRaw);
48
+ const showValue = value !== undefined && value !== null && value !== false;
49
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
50
+ style: [{
51
+ flexDirection: 'row',
52
+ alignItems: 'center',
53
+ gap
54
+ }, style],
55
+ accessibilityRole: "text",
56
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
57
+ style: [{
58
+ width: indicatorSize,
59
+ height: indicatorSize,
60
+ borderRadius: indicatorRadius,
61
+ backgroundColor: indicatorBg
62
+ }, indicatorStyle]
63
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
64
+ style: {
65
+ flex: 1,
66
+ flexDirection: 'row',
67
+ alignItems: 'center',
68
+ gap: textWrapGap,
69
+ minWidth: 0
70
+ },
71
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
72
+ style: [{
73
+ flex: 1,
74
+ color: labelColor,
75
+ fontFamily: labelFontFamily,
76
+ fontSize: labelFontSize,
77
+ lineHeight: labelLineHeight,
78
+ fontWeight: labelFontWeight
79
+ }, labelStyle],
80
+ children: label
81
+ }), showValue && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
82
+ style: [{
83
+ color: valueColor,
84
+ fontFamily: valueFontFamily,
85
+ fontSize: valueFontSize,
86
+ lineHeight: valueLineHeight,
87
+ fontWeight: valueFontWeight
88
+ }, valueStyle],
89
+ numberOfLines: 1,
90
+ children: value
91
+ })]
92
+ })]
93
+ });
94
+ }
95
+ var _default = exports.default = MetricLegendItem;
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CalendarGlyph = CalendarGlyph;
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 _MetricLegendItem = _interopRequireDefault(require("../MetricLegendItem/MetricLegendItem"));
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
+ /**
17
+ * The three semantic states a calendar glyph can be in. Maps 1:1 to the
18
+ * Figma `Calendar Glyph State` collection modes (`Idle`, `notSaved`,
19
+ * `saved`) and drives both the glyph fill/foreground tokens and the
20
+ * matching legend dot.
21
+ */
22
+
23
+ /** One month entry in the grid. */
24
+
25
+ const DEFAULT_MONTH_LABELS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
26
+ const DEFAULT_LEGEND_LABELS = Object.freeze({
27
+ Idle: 'No data',
28
+ notSaved: 'Not saved',
29
+ saved: 'Saved'
30
+ });
31
+ const DEFAULT_LEGEND_STATUSES = ['Idle', 'notSaved', 'saved'];
32
+ const DEFAULT_MONTHS = DEFAULT_MONTH_LABELS.map(label => ({
33
+ label,
34
+ status: 'Idle'
35
+ }));
36
+
37
+ /**
38
+ * Default tokens used as the safe fallbacks when token resolution returns
39
+ * `null` (e.g. modes are missing or the resolver hasn't been initialized).
40
+ * They mirror the Figma source values for the `Calendar Glyph State` modes.
41
+ */
42
+ const FALLBACK_BG = {
43
+ Idle: '#e0e0e3',
44
+ notSaved: '#b84fbd',
45
+ saved: '#5d00b5'
46
+ };
47
+ const FALLBACK_FG = {
48
+ Idle: '#000000',
49
+ notSaved: '#ffffff',
50
+ saved: '#ffffff'
51
+ };
52
+ const toNumber = (value, fallback) => {
53
+ if (typeof value === 'number') {
54
+ return Number.isFinite(value) ? value : fallback;
55
+ }
56
+ if (typeof value === 'string') {
57
+ const parsed = Number(value);
58
+ return Number.isFinite(parsed) ? parsed : fallback;
59
+ }
60
+ return fallback;
61
+ };
62
+ const toFontWeight = (value, fallback) => {
63
+ if (typeof value === 'number') {
64
+ return String(value);
65
+ }
66
+ if (typeof value === 'string') {
67
+ return value;
68
+ }
69
+ return fallback;
70
+ };
71
+ /**
72
+ * Single calendar-month glyph: a small pill with a status-driven background
73
+ * and foreground, and a centered month label. Exposed for callers who want
74
+ * to compose glyphs themselves; most consumers should use
75
+ * {@link MonthlyStatusGrid} instead, which keeps the count, layout and
76
+ * legend in sync automatically.
77
+ */
78
+ function CalendarGlyph({
79
+ label = 'Jan',
80
+ status = 'Idle',
81
+ modes: propModes = _reactUtils.EMPTY_MODES,
82
+ style,
83
+ labelStyle,
84
+ accessibilityLabel
85
+ }) {
86
+ const {
87
+ modes: globalModes
88
+ } = (0, _JFSThemeProvider.useTokens)();
89
+ const modes = _react.default.useMemo(() => ({
90
+ ...globalModes,
91
+ ...propModes,
92
+ 'Calendar Glyph State': status
93
+ }), [globalModes, propModes, status]);
94
+ const width = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/width', modes), 46);
95
+ const height = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/height', modes), 46);
96
+ const radius = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/radius', modes), 29);
97
+ const paddingTop = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/padding/top', modes), 16);
98
+ const paddingBottom = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/padding/bottom', modes), 16);
99
+ const paddingLeft = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/padding/left', modes), 13);
100
+ const paddingRight = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/padding/right', modes), 12);
101
+ const gap = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/gap', modes), 0);
102
+ const background = (0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/background', modes) ?? FALLBACK_BG[status];
103
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/foreground', modes) ?? FALLBACK_FG[status];
104
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/fontFamily', modes) ?? 'JioType Var';
105
+ const fontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/fontSize', modes), 12);
106
+ const lineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/lineHeight', modes), 14);
107
+ const fontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/fontWeight', modes), '500');
108
+ const defaultAccessibilityLabel = accessibilityLabel ?? `${typeof label === 'string' ? label : 'Month'}, ${DEFAULT_LEGEND_LABELS[status].toLowerCase()}`;
109
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
110
+ accessibilityLabel: defaultAccessibilityLabel,
111
+ style: [{
112
+ // Use min* so the pill is always at least the Figma size, but
113
+ // grows naturally when the label is wider (e.g. localized
114
+ // months). Avoids the ellipsis-truncation that happens when a
115
+ // 3-letter label barely overflows the strict inner width.
116
+ minWidth: width,
117
+ minHeight: height,
118
+ borderRadius: radius,
119
+ backgroundColor: background,
120
+ paddingTop,
121
+ paddingBottom,
122
+ paddingLeft,
123
+ paddingRight,
124
+ alignItems: 'center',
125
+ justifyContent: 'center',
126
+ gap
127
+ }, style],
128
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
129
+ numberOfLines: 1,
130
+ style: [{
131
+ color: foreground,
132
+ fontFamily,
133
+ fontSize,
134
+ lineHeight,
135
+ fontWeight,
136
+ textAlign: 'center'
137
+ }, labelStyle],
138
+ children: label
139
+ })
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Resolve the canonical color pair for a status. Used by both the glyph and
145
+ * the matching legend item so they can never visually drift apart.
146
+ */
147
+ function resolveStatusColors(status, modes) {
148
+ const statusModes = {
149
+ ...modes,
150
+ 'Calendar Glyph State': status
151
+ };
152
+ const bg = (0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/background', statusModes) ?? FALLBACK_BG[status];
153
+ const fg = (0, _figmaVariablesResolver.getVariableByName)('calendarGlyph/foreground', statusModes) ?? FALLBACK_FG[status];
154
+ return {
155
+ bg,
156
+ fg,
157
+ statusModes
158
+ };
159
+ }
160
+
161
+ /**
162
+ * `MonthlyStatusGrid` shows a year (or any contiguous range of months) as a
163
+ * grid of small pill-shaped calendar glyphs, each colored by its semantic
164
+ * status (`Idle` = "No data", `notSaved` = "Not saved", `saved` = "Saved").
165
+ * A legend below the grid explains the colors.
166
+ *
167
+ * Cohesiveness guarantees:
168
+ * - The number of glyphs is **always** `months.length`. There is no way to
169
+ * render a glyph that has no underlying status.
170
+ * - The legend dot color for a status is resolved through the **same**
171
+ * `calendarGlyph/background` token + `Calendar Glyph State` mode as the
172
+ * glyph itself, so the visual mapping cannot drift.
173
+ *
174
+ * The chart is rendered with plain RN primitives (`View` + `Text`); SVG is
175
+ * unnecessary here because the glyph shape is a simple rounded rectangle.
176
+ *
177
+ * @component
178
+ */
179
+ function MonthlyStatusGrid({
180
+ months = DEFAULT_MONTHS,
181
+ columns = 4,
182
+ legend,
183
+ legendStatuses = DEFAULT_LEGEND_STATUSES,
184
+ modes: propModes = _reactUtils.EMPTY_MODES,
185
+ style,
186
+ monthsStyle,
187
+ rowStyle,
188
+ glyphStyle,
189
+ labelStyle,
190
+ legendStyle,
191
+ accessibilityLabel
192
+ }) {
193
+ const {
194
+ modes: globalModes
195
+ } = (0, _JFSThemeProvider.useTokens)();
196
+ const modes = _react.default.useMemo(() => ({
197
+ ...globalModes,
198
+ ...propModes
199
+ }), [globalModes, propModes]);
200
+ const gridGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('monthlyStatusGrid/gap', modes), 16);
201
+ const rowGap = toNumber((0, _figmaVariablesResolver.getVariableByName)('monthlyStatusGrid/months/gap', modes), 12);
202
+ const safeColumns = Math.max(1, Math.floor(columns));
203
+
204
+ // Group months into rows of `safeColumns`. Render-time only; cheap.
205
+ const rows = _react.default.useMemo(() => {
206
+ const out = [];
207
+ for (let i = 0; i < months.length; i += safeColumns) {
208
+ out.push(months.slice(i, i + safeColumns));
209
+ }
210
+ return out;
211
+ }, [months, safeColumns]);
212
+ const showLegend = legend !== false;
213
+ const legendOverrides = legend && typeof legend === 'object' ? legend : {};
214
+ const defaultAccessibilityLabel = accessibilityLabel ?? `Monthly status grid: ${months.length} month${months.length === 1 ? '' : 's'}`;
215
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
216
+ accessibilityLabel: defaultAccessibilityLabel,
217
+ style: [{
218
+ width: '100%',
219
+ gap: gridGap,
220
+ alignItems: 'stretch',
221
+ justifyContent: 'center'
222
+ }, style],
223
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
224
+ style: [{
225
+ width: '100%',
226
+ gap: rowGap,
227
+ alignItems: 'stretch'
228
+ }, monthsStyle],
229
+ children: rows.map((row, rowIndex) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
230
+ style: [{
231
+ flexDirection: 'row',
232
+ alignItems: 'center',
233
+ justifyContent: 'space-between',
234
+ width: '100%'
235
+ }, rowStyle],
236
+ children: row.map((month, colIndex) => {
237
+ const absoluteIndex = rowIndex * safeColumns + colIndex;
238
+ const fallbackLabel = DEFAULT_MONTH_LABELS[absoluteIndex % DEFAULT_MONTH_LABELS.length];
239
+ const label = month.label ?? fallbackLabel;
240
+ const glyphModes = month.modes ? {
241
+ ...modes,
242
+ ...month.modes
243
+ } : modes;
244
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(CalendarGlyph, {
245
+ label: label,
246
+ status: month.status,
247
+ modes: glyphModes,
248
+ ...(glyphStyle !== undefined ? {
249
+ style: glyphStyle
250
+ } : {}),
251
+ ...(labelStyle !== undefined ? {
252
+ labelStyle
253
+ } : {}),
254
+ ...(month.accessibilityLabel !== undefined ? {
255
+ accessibilityLabel: month.accessibilityLabel
256
+ } : {})
257
+ }, month.key ?? `glyph-${absoluteIndex}`);
258
+ })
259
+ }, `row-${rowIndex}`))
260
+ }), showLegend ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
261
+ style: [{
262
+ flexDirection: 'row',
263
+ alignItems: 'center',
264
+ justifyContent: 'space-between',
265
+ width: '100%'
266
+ }, legendStyle],
267
+ children: legendStatuses.map(status => {
268
+ const {
269
+ bg,
270
+ statusModes
271
+ } = resolveStatusColors(status, modes);
272
+ const label = legendOverrides[status] ?? DEFAULT_LEGEND_LABELS[status];
273
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MetricLegendItem.default, {
274
+ label: label,
275
+ indicatorColor: bg,
276
+ modes: statusModes,
277
+ style: {
278
+ flex: 1,
279
+ minWidth: 0
280
+ }
281
+ }, `legend-${status}`);
282
+ })
283
+ }) : null]
284
+ });
285
+ }
286
+ var _default = exports.default = MonthlyStatusGrid;