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
@@ -21,6 +21,13 @@ Object.defineProperty(exports, "flattenChildren", {
21
21
  return _reactUtils.flattenChildren;
22
22
  }
23
23
  });
24
+ Object.defineProperty(exports, "formatIndianNumber", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _numberUtils.formatIndianNumber;
28
+ }
29
+ });
24
30
  var _reactUtils = require("./react-utils");
25
31
  var _MediaSource = _interopRequireDefault(require("./MediaSource"));
32
+ var _numberUtils = require("./number-utils");
26
33
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.formatIndianNumber = formatIndianNumber;
7
+ /**
8
+ * Format a number using the Indian numeric system.
9
+ *
10
+ * - Below 1 lakh (100,000): standard Indian-locale comma grouping (e.g. `12,400`).
11
+ * - 1 lakh up to (but excluding) 1 crore: shorthand `L` (e.g. `2.4L`).
12
+ * - 1 crore and above: shorthand `Cr` (e.g. `1.2Cr`).
13
+ *
14
+ * Trailing zero decimals are trimmed, so `100000` becomes `1L` rather than `1.0L`.
15
+ * Negative values keep the sign (`-2.4L`). Non-finite inputs (`NaN`, `Infinity`)
16
+ * are returned via `String(value)` so callers can decide how to handle them.
17
+ *
18
+ * @example formatIndianNumber(240000) // "2.4L"
19
+ * @example formatIndianNumber(12400) // "12,400"
20
+ * @example formatIndianNumber(15000000) // "1.5Cr"
21
+ * @example formatIndianNumber(-100000) // "-1L"
22
+ * @example formatIndianNumber(99999) // "99,999"
23
+ *
24
+ * @param value The number to format.
25
+ * @param options Optional formatting overrides.
26
+ * @param options.decimals Maximum number of decimal places used in the
27
+ * shorthand `L` / `Cr` form. Defaults to `1`.
28
+ * @param options.prefix String to prefix the output with — useful for a
29
+ * currency symbol, e.g. `'₹'`. Defaults to `''`.
30
+ */
31
+ function formatIndianNumber(value, options = {}) {
32
+ if (!Number.isFinite(value)) return String(value);
33
+ const {
34
+ decimals = 1,
35
+ prefix = ''
36
+ } = options;
37
+ const sign = value < 0 ? '-' : '';
38
+ const absValue = Math.abs(value);
39
+ const CRORE = 10_000_000;
40
+ const LAKH = 100_000;
41
+ if (absValue >= CRORE) {
42
+ return `${sign}${prefix}${trimTrailingZeros((absValue / CRORE).toFixed(Math.max(0, decimals)))}Cr`;
43
+ }
44
+ if (absValue >= LAKH) {
45
+ return `${sign}${prefix}${trimTrailingZeros((absValue / LAKH).toFixed(Math.max(0, decimals)))}L`;
46
+ }
47
+
48
+ // For sub-lakh values, fall back to the native Indian comma grouping.
49
+ // `toLocaleString` with `en-IN` gives 1,23,456 — exactly what we want.
50
+ return `${prefix}${value.toLocaleString('en-IN', {
51
+ maximumFractionDigits: 0
52
+ })}`;
53
+ }
54
+ function trimTrailingZeros(numericString) {
55
+ if (!numericString.includes('.')) return numericString;
56
+ return numericString.replace(/\.?0+$/, '');
57
+ }
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+
3
+ import React, { useCallback, useState } from 'react';
4
+ import { View, Text, Pressable, LayoutAnimation, Platform, UIManager } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
7
+ import Checkbox from '../Checkbox/Checkbox';
8
+ import Divider from '../Divider/Divider';
9
+ import Icon from '../../icons/Icon';
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
+ if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
12
+ UIManager.setLayoutAnimationEnabledExperimental(true);
13
+ }
14
+ /**
15
+ * AccordionCheckbox composes a header (with a `Checkbox`, title, subtitle and
16
+ * chevron) and a collapsible content slot. It mirrors the Figma
17
+ * "Accordion Checkbox" component.
18
+ *
19
+ * Two independent interactions live inside the header:
20
+ * - **Pressing the checkbox** toggles the parent checked state via
21
+ * `onCheckedChange` (typically used for "select all" behaviour).
22
+ * - **Pressing anywhere else on the header** toggles the expanded state via
23
+ * `onExpandedChange`.
24
+ *
25
+ * When expanded, a divider is shown and `children` are rendered with `modes`
26
+ * automatically forwarded through `cloneChildrenWithModes`.
27
+ *
28
+ * @component
29
+ * @param {AccordionCheckboxProps} props
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <AccordionCheckbox
34
+ * title="Axis Bank"
35
+ * subtitle="3 accounts"
36
+ * defaultExpanded
37
+ * defaultChecked
38
+ * modes={{ 'Color Mode': 'Light' }}
39
+ * >
40
+ * <CheckboxGroup>
41
+ * <CheckboxItem label="Fixed deposit • 0245" />
42
+ * <CheckboxItem label="Recurring deposit • 1182" />
43
+ * <CheckboxItem label="Mutual fund • Equity" />
44
+ * </CheckboxGroup>
45
+ * </AccordionCheckbox>
46
+ * ```
47
+ */
48
+ function AccordionCheckbox({
49
+ title = 'Axis Bank',
50
+ subtitle = '3 accounts',
51
+ defaultExpanded = false,
52
+ expanded: controlledExpanded,
53
+ onExpandedChange,
54
+ defaultChecked = false,
55
+ checked: controlledChecked,
56
+ onCheckedChange,
57
+ disabled = false,
58
+ children,
59
+ modes = EMPTY_MODES,
60
+ style,
61
+ accessibilityLabel
62
+ }) {
63
+ const isExpandedControlled = controlledExpanded !== undefined;
64
+ const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);
65
+ const isExpanded = isExpandedControlled ? controlledExpanded : internalExpanded;
66
+ const isCheckedControlled = controlledChecked !== undefined;
67
+ const [internalChecked, setInternalChecked] = useState(defaultChecked);
68
+ const isChecked = isCheckedControlled ? controlledChecked : internalChecked;
69
+ const handleToggleExpanded = useCallback(() => {
70
+ if (disabled) return;
71
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
72
+ const next = !isExpanded;
73
+ if (!isExpandedControlled) {
74
+ setInternalExpanded(next);
75
+ }
76
+ onExpandedChange?.(next);
77
+ }, [disabled, isExpanded, isExpandedControlled, onExpandedChange]);
78
+ const handleToggleChecked = useCallback(next => {
79
+ if (disabled) return;
80
+ if (!isCheckedControlled) {
81
+ setInternalChecked(next);
82
+ }
83
+ onCheckedChange?.(next);
84
+ }, [disabled, isCheckedControlled, onCheckedChange]);
85
+ const background = getVariableByName('accordionCheckbox/background', modes) ?? '#ffffff';
86
+ const radius = getVariableByName('accordionCheckbox/radius', modes) ?? 12;
87
+ const paddingHorizontal = getVariableByName('accordionCheckbox/padding/horizontal', modes) ?? 12;
88
+ const paddingVertical = getVariableByName('accordionCheckbox/padding/vertical', modes) ?? 16;
89
+ const containerGap = getVariableByName('accordionCheckbox/gap', modes) ?? 12;
90
+ const borderColor = getVariableByName('accordionCheckbox/border/color', modes) ?? '#ebebed';
91
+ const borderSize = getVariableByName('accordionCheckbox/border/size', modes) ?? 1;
92
+ const headerGap = getVariableByName('accordionCheckbox/header/gap', modes) ?? 12;
93
+ const headerPaddingHorizontal = getVariableByName('accordionCheckbox/header/padding/horizontal', modes) ?? 0;
94
+ const headerPaddingVertical = getVariableByName('accordionCheckbox/header/padding/vertical', modes) ?? 0;
95
+ const headerWrapGap = getVariableByName('accordionCheckbox/header/wrap/gap', modes) ?? 12;
96
+ const textWrapGap = getVariableByName('accordionCheckbox/textWrap/gap', modes) ?? 2;
97
+ const titleColor = getVariableByName('accordionCheckbox/title/color', modes) ?? '#000000';
98
+ const titleFontSize = getVariableByName('accordionCheckbox/title/fontSize', modes) ?? 14;
99
+ const titleFontFamily = getVariableByName('accordionCheckbox/title/fontFamily', modes) ?? 'JioType Var';
100
+ const titleLineHeight = getVariableByName('accordionCheckbox/title/lineHeight', modes) ?? 18;
101
+ const titleFontWeightRaw = getVariableByName('accordionCheckbox/title/fontWeight', modes) ?? 600;
102
+ const titleFontWeight = String(titleFontWeightRaw);
103
+ const subtitleColor = getVariableByName('accordionCheckbox/subtitle/color', modes) ?? '#23190a';
104
+ const subtitleFontSize = getVariableByName('accordionCheckbox/subtitle/fontSize', modes) ?? 12;
105
+ const subtitleFontFamily = getVariableByName('accordionCheckbox/subtitle/fontFamily', modes) ?? 'JioType Var';
106
+ const subtitleLineHeight = getVariableByName('accordionCheckbox/subtitle/lineHeight', modes) ?? 16;
107
+ const subtitleFontWeightRaw = getVariableByName('accordionCheckbox/subtitle/fontWeight', modes) ?? 500;
108
+ const subtitleFontWeight = String(subtitleFontWeightRaw);
109
+ const iconColor = getVariableByName('accordionCheckbox/icon/color', modes) ?? '#000000';
110
+ const iconSize = getVariableByName('accordionCheckbox/icon/size', modes) ?? 24;
111
+ const contentGap = getVariableByName('accordionCheckbox/content/gap', modes) ?? 0;
112
+ const contentPaddingTop = getVariableByName('accordionCheckbox/content/padding/top', modes) ?? 8;
113
+ const contentPaddingBottom = getVariableByName('accordionCheckbox/content/padding/bottom', modes) ?? 0;
114
+ const contentPaddingHorizontal = getVariableByName('accordionCheckbox/content/padding/horizontal', modes) ?? 0;
115
+ const containerStyle = {
116
+ backgroundColor: background,
117
+ borderRadius: radius,
118
+ paddingHorizontal,
119
+ paddingVertical,
120
+ flexDirection: 'column',
121
+ alignItems: 'stretch',
122
+ gap: containerGap,
123
+ overflow: 'hidden',
124
+ ...(isExpanded ? {
125
+ borderWidth: borderSize,
126
+ borderColor
127
+ } : null),
128
+ ...(disabled ? {
129
+ opacity: 0.6
130
+ } : null)
131
+ };
132
+ const headerStyle = {
133
+ flexDirection: 'row',
134
+ alignItems: 'center',
135
+ gap: headerGap,
136
+ paddingHorizontal: headerPaddingHorizontal,
137
+ paddingVertical: headerPaddingVertical
138
+ };
139
+ const wrapStyle = {
140
+ flex: 1,
141
+ minWidth: 0,
142
+ flexDirection: 'row',
143
+ alignItems: 'center',
144
+ gap: headerWrapGap
145
+ };
146
+ const textWrapStyle = {
147
+ flex: 1,
148
+ minWidth: 0,
149
+ flexDirection: 'column',
150
+ alignItems: 'flex-start',
151
+ gap: textWrapGap
152
+ };
153
+ const titleStyle = {
154
+ color: titleColor,
155
+ fontSize: titleFontSize,
156
+ lineHeight: titleLineHeight,
157
+ fontFamily: titleFontFamily,
158
+ fontWeight: titleFontWeight
159
+ };
160
+ const subtitleStyle = {
161
+ color: subtitleColor,
162
+ fontSize: subtitleFontSize,
163
+ lineHeight: subtitleLineHeight,
164
+ fontFamily: subtitleFontFamily,
165
+ fontWeight: subtitleFontWeight
166
+ };
167
+ const contentStyle = {
168
+ flexDirection: 'column',
169
+ alignItems: 'stretch',
170
+ justifyContent: 'center',
171
+ gap: contentGap,
172
+ paddingTop: contentPaddingTop,
173
+ paddingBottom: contentPaddingBottom,
174
+ paddingHorizontal: contentPaddingHorizontal
175
+ };
176
+ const a11yLabel = accessibilityLabel ?? title;
177
+ return /*#__PURE__*/_jsxs(View, {
178
+ style: [containerStyle, style],
179
+ children: [/*#__PURE__*/_jsxs(Pressable, {
180
+ onPress: handleToggleExpanded,
181
+ disabled: disabled,
182
+ accessibilityRole: "button",
183
+ accessibilityState: {
184
+ expanded: isExpanded,
185
+ disabled
186
+ },
187
+ accessibilityLabel: a11yLabel,
188
+ accessibilityHint: isExpanded ? 'Collapse' : 'Expand',
189
+ style: ({
190
+ pressed
191
+ }) => [headerStyle, pressed && !disabled ? {
192
+ opacity: 0.9
193
+ } : null],
194
+ children: [/*#__PURE__*/_jsxs(View, {
195
+ style: wrapStyle,
196
+ children: [/*#__PURE__*/_jsx(Checkbox, {
197
+ checked: isChecked,
198
+ onValueChange: handleToggleChecked,
199
+ disabled: disabled,
200
+ modes: modes,
201
+ accessibilityLabel: typeof title === 'string' ? `Select ${title}` : undefined
202
+ }), /*#__PURE__*/_jsxs(View, {
203
+ style: textWrapStyle,
204
+ children: [/*#__PURE__*/_jsx(Text, {
205
+ style: titleStyle,
206
+ numberOfLines: 1,
207
+ selectable: false,
208
+ children: title
209
+ }), subtitle ? /*#__PURE__*/_jsx(Text, {
210
+ style: subtitleStyle,
211
+ numberOfLines: 1,
212
+ selectable: false,
213
+ children: subtitle
214
+ }) : null]
215
+ })]
216
+ }), /*#__PURE__*/_jsx(Icon, {
217
+ name: isExpanded ? 'ic_chevron_up' : 'ic_chevron_down',
218
+ size: iconSize,
219
+ color: iconColor,
220
+ accessibilityElementsHidden: true,
221
+ importantForAccessibility: "no"
222
+ })]
223
+ }), isExpanded ? /*#__PURE__*/_jsxs(_Fragment, {
224
+ children: [/*#__PURE__*/_jsx(Divider, {
225
+ modes: modes
226
+ }), children ? /*#__PURE__*/_jsx(View, {
227
+ style: contentStyle,
228
+ children: cloneChildrenWithModes(children, modes)
229
+ }) : null]
230
+ }) : null]
231
+ });
232
+ }
233
+ export default AccordionCheckbox;
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+
3
+ import React, { useMemo } from 'react';
4
+ import { Pressable, Text, View } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
7
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
8
+ import Avatar from '../Avatar/Avatar';
9
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
10
+ const toNumber = (value, fallback) => {
11
+ if (typeof value === 'number') {
12
+ return Number.isFinite(value) ? value : fallback;
13
+ }
14
+ if (typeof value === 'string') {
15
+ const parsed = Number(value);
16
+ return Number.isFinite(parsed) ? parsed : fallback;
17
+ }
18
+ return fallback;
19
+ };
20
+ const toFontWeight = (value, fallback) => {
21
+ if (typeof value === 'number') return String(value);
22
+ if (typeof value === 'string') return value;
23
+ return fallback;
24
+ };
25
+ function resolveBrandChipTokens(modes) {
26
+ const background = getVariableByName('brandChip/background', modes) ?? '#ffffff';
27
+ const foreground = getVariableByName('brandChip/foreground', modes) ?? '#0d0d0f';
28
+ const borderColor = getVariableByName('brandChip/border/color', modes) ?? '#e0e0e3';
29
+ const borderSize = toNumber(getVariableByName('brandChip/border/size', modes), 1);
30
+ const gap = toNumber(getVariableByName('brandChip/gap', modes), 8);
31
+ const paddingLeft = toNumber(getVariableByName('brandChip/padding/left', modes), 8);
32
+ const paddingRight = toNumber(getVariableByName('brandChip/padding/right', modes), 12);
33
+ const paddingVertical = toNumber(getVariableByName('brandChip/padding/vertical', modes), 5);
34
+ // The Figma token uses 25000 as a sentinel for "always pill-shaped".
35
+ // Cap it to a value React Native renders predictably.
36
+ const radiusRaw = toNumber(getVariableByName('brandChip/radius', modes), 9999);
37
+ const radius = radiusRaw >= 9999 ? 9999 : radiusRaw;
38
+ const fontFamily = getVariableByName('brandChip/label/fontFamily', modes) ?? 'JioType Var';
39
+ const fontSize = toNumber(getVariableByName('brandChip/label/fontSize', modes), 16);
40
+ const lineHeight = toNumber(getVariableByName('brandChip/label/lineHeight', modes), 21);
41
+ const fontWeight = toFontWeight(getVariableByName('brandChip/label/fontWeight', modes), '500');
42
+ return {
43
+ containerStyle: {
44
+ flexDirection: 'row',
45
+ alignItems: 'center',
46
+ alignSelf: 'flex-start',
47
+ backgroundColor: background,
48
+ borderColor,
49
+ borderWidth: borderSize,
50
+ borderStyle: 'solid',
51
+ borderRadius: radius,
52
+ paddingLeft,
53
+ paddingRight,
54
+ paddingTop: paddingVertical,
55
+ paddingBottom: paddingVertical,
56
+ gap
57
+ },
58
+ labelStyle: {
59
+ color: foreground,
60
+ fontFamily,
61
+ fontSize,
62
+ fontWeight,
63
+ lineHeight
64
+ }
65
+ };
66
+ }
67
+
68
+ // The Figma reference renders the avatar at 29px which is the `S` size in
69
+ // the Avatar Size collection. Callers can override via `modes`.
70
+ const DEFAULT_AVATAR_SIZE_MODE = 'S';
71
+
72
+ /**
73
+ * `BrandChip` renders a compact pill that pairs a small institution avatar
74
+ * with a short identifier label (e.g. `"Axis Bank • 0245"`). It's typically
75
+ * used to surface the currently-selected linked account in headers, sticky
76
+ * bars, or selectors.
77
+ *
78
+ * All visual values resolve through the `brandChip/*` design tokens with
79
+ * sensible Figma defaults so the chip renders correctly out of the box.
80
+ *
81
+ * @component
82
+ * @param {BrandChipProps} props
83
+ */
84
+ function BrandChip({
85
+ label = 'Axis Bank • 0245',
86
+ imageSource,
87
+ avatarSlot,
88
+ onPress,
89
+ modes: propModes = EMPTY_MODES,
90
+ style,
91
+ labelStyle,
92
+ accessibilityLabel
93
+ }) {
94
+ const {
95
+ modes: globalModes
96
+ } = useTokens();
97
+ const modes = useMemo(() => globalModes === EMPTY_MODES && propModes === EMPTY_MODES ? EMPTY_MODES : {
98
+ ...globalModes,
99
+ ...propModes
100
+ }, [globalModes, propModes]);
101
+ const avatarModes = useMemo(() => ({
102
+ 'Avatar Size': DEFAULT_AVATAR_SIZE_MODE,
103
+ ...modes
104
+ }), [modes]);
105
+ const tokens = useMemo(() => resolveBrandChipTokens(modes), [modes]);
106
+ const processedAvatarSlot = useMemo(() => {
107
+ if (!avatarSlot) return null;
108
+ const processed = cloneChildrenWithModes(avatarSlot, avatarModes);
109
+ return processed.length === 1 ? processed[0] : processed;
110
+ }, [avatarSlot, avatarModes]);
111
+ const avatarNode = processedAvatarSlot ?? (imageSource !== undefined ? /*#__PURE__*/_jsx(Avatar, {
112
+ style: "Image",
113
+ imageSource: imageSource,
114
+ modes: avatarModes
115
+ }) : /*#__PURE__*/_jsx(Avatar, {
116
+ style: "Image",
117
+ modes: avatarModes
118
+ }));
119
+ const a11yLabel = accessibilityLabel ?? label;
120
+ const content = /*#__PURE__*/_jsxs(_Fragment, {
121
+ children: [avatarNode, /*#__PURE__*/_jsx(Text, {
122
+ style: [tokens.labelStyle, labelStyle],
123
+ numberOfLines: 1,
124
+ ellipsizeMode: "tail",
125
+ children: label
126
+ })]
127
+ });
128
+ if (onPress) {
129
+ return /*#__PURE__*/_jsx(Pressable, {
130
+ accessibilityRole: "button",
131
+ accessibilityLabel: a11yLabel,
132
+ onPress: onPress,
133
+ style: [tokens.containerStyle, style],
134
+ children: content
135
+ });
136
+ }
137
+ return /*#__PURE__*/_jsx(View, {
138
+ accessibilityLabel: a11yLabel,
139
+ style: [tokens.containerStyle, style],
140
+ children: content
141
+ });
142
+ }
143
+ export default /*#__PURE__*/React.memo(BrandChip);
@@ -31,8 +31,8 @@ const toFontWeight = (value, fallback) => {
31
31
  function resolveCardAdvisoryTokens(modes) {
32
32
  const width = toNumber(getVariableByName('cardAdvisory/width', modes), 360);
33
33
  const gap = toNumber(getVariableByName('cardAdvisory/gap', modes), 16);
34
- const paddingHorizontal = toNumber(getVariableByName('cardAdvisory/padding/horizontal', modes), 16);
35
- const paddingVertical = toNumber(getVariableByName('cardAdvisory/padding/vertical', modes), 12);
34
+ const paddingHorizontal = toNumber(getVariableByName('cardAdvisory/padding/horizontal', modes), 0);
35
+ const paddingVertical = toNumber(getVariableByName('cardAdvisory/padding/vertical', modes), 0);
36
36
  const radius = toNumber(getVariableByName('cardAdvisory/radius', modes), 0);
37
37
  const background = getVariableByName('cardAdvisory/background', modes) || '#ffffff';
38
38
  const mainContentGap = toNumber(getVariableByName('cardAdvisory/mainContent/gap', modes), 16);
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { View, Text } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
7
+ import Badge from '../Badge/Badge';
8
+ import Button from '../Button/Button';
9
+ import InstitutionBadge from '../InstitutionBadge/InstitutionBadge';
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ const DEFAULT_ITEMS = [{
12
+ label: 'Account type',
13
+ value: 'Korem ipsum'
14
+ }, {
15
+ label: 'Account number',
16
+ value: 'Korem ipsum'
17
+ }, {
18
+ label: 'Last updated',
19
+ value: 'Korem ipsum'
20
+ }];
21
+ const toNumber = (value, fallback) => {
22
+ if (typeof value === 'number') return Number.isFinite(value) ? value : fallback;
23
+ if (typeof value === 'string') {
24
+ const parsed = Number(value);
25
+ return Number.isFinite(parsed) ? parsed : fallback;
26
+ }
27
+ return fallback;
28
+ };
29
+ const toFontWeight = (value, fallback) => {
30
+ if (typeof value === 'number') return String(value);
31
+ if (typeof value === 'string') return value;
32
+ return fallback;
33
+ };
34
+
35
+ /**
36
+ * `CardBankAccount` renders a bank account summary card composed of:
37
+ *
38
+ * 1. A header with an `InstitutionBadge` (avatar + bank name) and an
39
+ * optional trailing `Badge`.
40
+ * 2. A configurable list of label/value rows describing the account.
41
+ * 3. A footer `Button` for the primary action.
42
+ *
43
+ * All values resolve through the `bankAccountCard/*` design tokens with
44
+ * sensible Figma defaults so the card renders correctly out of the box.
45
+ *
46
+ * @component
47
+ * @param {CardBankAccountProps} props
48
+ */
49
+ function CardBankAccount({
50
+ institutionName = 'State Bank of India',
51
+ institutionAvatar,
52
+ badge,
53
+ headerSlot,
54
+ items = DEFAULT_ITEMS,
55
+ children,
56
+ buttonLabel = 'Button',
57
+ onButtonPress,
58
+ footer,
59
+ modes = EMPTY_MODES,
60
+ style,
61
+ accessibilityLabel
62
+ }) {
63
+ const background = getVariableByName('bankAccountCard/background', modes) ?? '#ffffff';
64
+ const radius = toNumber(getVariableByName('bankAccountCard/radius', modes), 16);
65
+ const paddingHorizontal = toNumber(getVariableByName('bankAccountCard/padding/horizontal', modes), 12);
66
+ const paddingVertical = toNumber(getVariableByName('bankAccountCard/padding/vertical', modes), 16);
67
+ const gap = toNumber(getVariableByName('bankAccountCard/gap', modes), 16);
68
+ const headerGap = toNumber(getVariableByName('bankAccountCard/header/gap', modes), 8);
69
+ const listGroupGap = toNumber(getVariableByName('listGroup/gap', modes), 12);
70
+ const rowGap = toNumber(getVariableByName('listItem/gap', modes), 8);
71
+ const titleColor = getVariableByName('listItem/title/color', modes) ?? '#0f0d0a';
72
+ const titleFontFamily = getVariableByName('listItem/title/fontFamily', modes) ?? 'JioType Var';
73
+ const titleFontSize = toNumber(getVariableByName('listItem/title/fontSize', modes), 14);
74
+ const titleLineHeight = toNumber(getVariableByName('listItem/title/lineHeight', modes), 16);
75
+ const titleFontWeight = toFontWeight(getVariableByName('listItem/title/fontWeight', modes), '700');
76
+ const valueColor = getVariableByName('text/foreground', modes) ?? '#000000';
77
+ const valueFontFamily = getVariableByName('text/fontFamily', modes) ?? 'JioType Var';
78
+ const valueFontSize = toNumber(getVariableByName('text/fontSize', modes), 14);
79
+ const valueLineHeight = toNumber(getVariableByName('text/lineHeight', modes), 20);
80
+ const valueLetterSpacing = toNumber(getVariableByName('text/letterSpacing', modes), -0.5);
81
+ const valueFontWeight = toFontWeight(getVariableByName('text/fontWeight', modes), '500');
82
+ const labelStyle = {
83
+ color: titleColor,
84
+ fontFamily: titleFontFamily,
85
+ fontSize: titleFontSize,
86
+ lineHeight: titleLineHeight,
87
+ fontWeight: titleFontWeight
88
+ };
89
+ const valueTextStyle = {
90
+ color: valueColor,
91
+ fontFamily: valueFontFamily,
92
+ fontSize: valueFontSize,
93
+ lineHeight: valueLineHeight,
94
+ letterSpacing: valueLetterSpacing,
95
+ fontWeight: valueFontWeight
96
+ };
97
+ const renderBadge = () => {
98
+ if (badge === false || badge === null || badge === undefined) return null;
99
+ if (typeof badge === 'string') {
100
+ return /*#__PURE__*/_jsx(Badge, {
101
+ label: badge,
102
+ modes: modes
103
+ });
104
+ }
105
+ const processed = cloneChildrenWithModes(badge, modes);
106
+ return processed.length === 1 ? processed[0] : processed;
107
+ };
108
+ const renderHeader = () => {
109
+ if (headerSlot !== undefined) {
110
+ const processed = cloneChildrenWithModes(headerSlot, modes);
111
+ return processed.length === 1 ? processed[0] : processed;
112
+ }
113
+ return /*#__PURE__*/_jsxs(View, {
114
+ style: {
115
+ flexDirection: 'row',
116
+ alignItems: 'center',
117
+ gap: headerGap,
118
+ width: '100%'
119
+ },
120
+ children: [/*#__PURE__*/_jsx(View, {
121
+ style: {
122
+ flex: 1,
123
+ minWidth: 0
124
+ },
125
+ children: /*#__PURE__*/_jsx(InstitutionBadge, {
126
+ label: institutionName,
127
+ ...(institutionAvatar !== undefined ? {
128
+ source: institutionAvatar
129
+ } : {}),
130
+ modes: modes
131
+ })
132
+ }), renderBadge()]
133
+ });
134
+ };
135
+ const renderItems = () => {
136
+ if (children !== undefined && children !== null) {
137
+ const processed = cloneChildrenWithModes(children, modes);
138
+ if (processed.length === 0) return null;
139
+ return /*#__PURE__*/_jsx(View, {
140
+ style: {
141
+ width: '100%',
142
+ gap: listGroupGap
143
+ },
144
+ children: processed.length === 1 ? processed[0] : processed
145
+ });
146
+ }
147
+ if (!items || items.length === 0) return null;
148
+ return /*#__PURE__*/_jsx(View, {
149
+ style: {
150
+ width: '100%',
151
+ gap: listGroupGap
152
+ },
153
+ children: items.map((item, index) => /*#__PURE__*/_jsxs(View, {
154
+ style: {
155
+ flexDirection: 'row',
156
+ alignItems: 'center',
157
+ gap: rowGap,
158
+ width: '100%'
159
+ },
160
+ children: [/*#__PURE__*/_jsx(View, {
161
+ style: {
162
+ flex: 1,
163
+ minWidth: 0
164
+ },
165
+ children: /*#__PURE__*/_jsx(Text, {
166
+ style: labelStyle,
167
+ children: item.label
168
+ })
169
+ }), typeof item.value === 'string' || typeof item.value === 'number' ? /*#__PURE__*/_jsx(Text, {
170
+ style: valueTextStyle,
171
+ numberOfLines: 1,
172
+ children: item.value
173
+ }) : cloneChildrenWithModes(item.value, modes)]
174
+ }, `${item.label}-${index}`))
175
+ });
176
+ };
177
+ const renderFooter = () => {
178
+ if (footer === false || footer === null) return null;
179
+ if (footer === undefined) {
180
+ return /*#__PURE__*/_jsx(Button, {
181
+ label: buttonLabel,
182
+ ...(onButtonPress ? {
183
+ onPress: onButtonPress
184
+ } : {}),
185
+ modes: modes,
186
+ style: {
187
+ width: '100%'
188
+ }
189
+ });
190
+ }
191
+ const processed = cloneChildrenWithModes(footer, modes);
192
+ return processed.length === 1 ? processed[0] : processed;
193
+ };
194
+ return /*#__PURE__*/_jsxs(View, {
195
+ accessibilityLabel: accessibilityLabel ?? institutionName,
196
+ style: [{
197
+ backgroundColor: background,
198
+ borderRadius: radius,
199
+ paddingHorizontal,
200
+ paddingVertical,
201
+ gap,
202
+ alignItems: 'flex-start',
203
+ width: '100%'
204
+ }, style],
205
+ children: [renderHeader(), renderItems(), renderFooter()]
206
+ });
207
+ }
208
+ export default CardBankAccount;