jfs-components 0.1.2 → 0.1.8

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 (107) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/lib/commonjs/components/AmountInput/AmountInput.js +8 -5
  3. package/lib/commonjs/components/BenefitCard/BenefitCard.js +231 -0
  4. package/lib/commonjs/components/CcCard/CcCard.js +470 -0
  5. package/lib/commonjs/components/Checkbox/Checkbox.js +4 -3
  6. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +4 -3
  7. package/lib/commonjs/components/CompareTable/CompareTable.js +372 -0
  8. package/lib/commonjs/components/ComparisonBar/ComparisonBar.js +266 -0
  9. package/lib/commonjs/components/DropdownInput/DropdownInput.js +35 -3
  10. package/lib/commonjs/components/FormField/FormField.js +4 -3
  11. package/lib/commonjs/components/InputSearch/InputSearch.js +6 -4
  12. package/lib/commonjs/components/NoteInput/NoteInput.js +6 -5
  13. package/lib/commonjs/components/PdpCcCard/PdpCcCard.js +273 -0
  14. package/lib/commonjs/components/ProductMerchandisingCard/GlassFill.js +263 -0
  15. package/lib/commonjs/components/ProductMerchandisingCard/GlassFill.web.js +116 -0
  16. package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +353 -0
  17. package/lib/commonjs/components/ProjectionMarker/ProjectionMarker.js +161 -0
  18. package/lib/commonjs/components/Radio/Radio.js +5 -5
  19. package/lib/commonjs/components/Slider/Slider.js +473 -0
  20. package/lib/commonjs/components/TextInput/TextInput.js +13 -8
  21. package/lib/commonjs/components/TextSegment/TextSegment.js +118 -0
  22. package/lib/commonjs/components/index.js +63 -0
  23. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  24. package/lib/commonjs/design-tokens/figma-modes.generated.js +38 -9
  25. package/lib/commonjs/icons/registry.js +1 -1
  26. package/lib/commonjs/utils/react-utils.js +22 -0
  27. package/lib/module/components/AmountInput/AmountInput.js +6 -4
  28. package/lib/module/components/BenefitCard/BenefitCard.js +225 -0
  29. package/lib/module/components/CcCard/CcCard.js +464 -0
  30. package/lib/module/components/Checkbox/Checkbox.js +5 -4
  31. package/lib/module/components/CheckboxItem/CheckboxItem.js +5 -4
  32. package/lib/module/components/CompareTable/CompareTable.js +367 -0
  33. package/lib/module/components/ComparisonBar/ComparisonBar.js +260 -0
  34. package/lib/module/components/DropdownInput/DropdownInput.js +36 -4
  35. package/lib/module/components/FormField/FormField.js +5 -4
  36. package/lib/module/components/InputSearch/InputSearch.js +6 -4
  37. package/lib/module/components/NoteInput/NoteInput.js +7 -6
  38. package/lib/module/components/PdpCcCard/PdpCcCard.js +267 -0
  39. package/lib/module/components/ProductMerchandisingCard/GlassFill.js +257 -0
  40. package/lib/module/components/ProductMerchandisingCard/GlassFill.web.js +111 -0
  41. package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +347 -0
  42. package/lib/module/components/ProjectionMarker/ProjectionMarker.js +156 -0
  43. package/lib/module/components/Radio/Radio.js +5 -4
  44. package/lib/module/components/Slider/Slider.js +468 -0
  45. package/lib/module/components/TextInput/TextInput.js +15 -10
  46. package/lib/module/components/TextSegment/TextSegment.js +113 -0
  47. package/lib/module/components/index.js +9 -0
  48. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  49. package/lib/module/design-tokens/figma-modes.generated.js +38 -9
  50. package/lib/module/icons/registry.js +1 -1
  51. package/lib/module/utils/react-utils.js +21 -0
  52. package/lib/typescript/src/components/AmountInput/AmountInput.d.ts +3 -2
  53. package/lib/typescript/src/components/BenefitCard/BenefitCard.d.ts +93 -0
  54. package/lib/typescript/src/components/CcCard/CcCard.d.ts +137 -0
  55. package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +3 -2
  56. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +2 -2
  57. package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +88 -0
  58. package/lib/typescript/src/components/ComparisonBar/ComparisonBar.d.ts +118 -0
  59. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +20 -1
  60. package/lib/typescript/src/components/FormField/FormField.d.ts +2 -2
  61. package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +23 -2
  62. package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +19 -2
  63. package/lib/typescript/src/components/PdpCcCard/PdpCcCard.d.ts +84 -0
  64. package/lib/typescript/src/components/ProductMerchandisingCard/GlassFill.d.ts +56 -0
  65. package/lib/typescript/src/components/ProductMerchandisingCard/GlassFill.web.d.ts +27 -0
  66. package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +81 -0
  67. package/lib/typescript/src/components/ProjectionMarker/ProjectionMarker.d.ts +82 -0
  68. package/lib/typescript/src/components/Radio/Radio.d.ts +3 -2
  69. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +2 -2
  70. package/lib/typescript/src/components/Slider/Slider.d.ts +99 -0
  71. package/lib/typescript/src/components/TextInput/TextInput.d.ts +9 -29
  72. package/lib/typescript/src/components/TextSegment/TextSegment.d.ts +100 -0
  73. package/lib/typescript/src/components/index.d.ts +10 -1
  74. package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +22 -2
  75. package/lib/typescript/src/icons/registry.d.ts +1 -1
  76. package/lib/typescript/src/utils/react-utils.d.ts +10 -0
  77. package/package.json +2 -1
  78. package/src/components/AmountInput/AmountInput.tsx +7 -5
  79. package/src/components/BenefitCard/BenefitCard.tsx +309 -0
  80. package/src/components/CcCard/CcCard.tsx +598 -0
  81. package/src/components/Checkbox/Checkbox.tsx +5 -4
  82. package/src/components/CheckboxItem/CheckboxItem.tsx +5 -4
  83. package/src/components/CompareTable/CompareTable.tsx +477 -0
  84. package/src/components/ComparisonBar/ComparisonBar.tsx +356 -0
  85. package/src/components/DropdownInput/DropdownInput.tsx +55 -3
  86. package/src/components/FormField/FormField.tsx +5 -4
  87. package/src/components/InputSearch/InputSearch.tsx +8 -5
  88. package/src/components/NoteInput/NoteInput.tsx +8 -6
  89. package/src/components/PdpCcCard/PdpCcCard.tsx +356 -0
  90. package/src/components/ProductMerchandisingCard/GlassFill.tsx +276 -0
  91. package/src/components/ProductMerchandisingCard/GlassFill.web.tsx +127 -0
  92. package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +423 -0
  93. package/src/components/ProjectionMarker/ProjectionMarker.tsx +277 -0
  94. package/src/components/Radio/Radio.tsx +5 -4
  95. package/src/components/Slider/Slider.tsx +628 -0
  96. package/src/components/TextInput/TextInput.tsx +15 -11
  97. package/src/components/TextSegment/TextSegment.tsx +166 -0
  98. package/src/components/index.ts +10 -1
  99. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  100. package/src/design-tokens/figma-modes.generated.ts +38 -9
  101. package/src/icons/registry.ts +1 -1
  102. package/src/utils/react-utils.ts +23 -0
  103. package/lib/typescript/scripts/extract-component-tokens.d.ts +0 -9
  104. package/lib/typescript/scripts/generate-component-docs.d.ts +0 -9
  105. package/lib/typescript/scripts/generate-icon-registry.d.ts +0 -3
  106. package/lib/typescript/scripts/generate-mode-types.d.ts +0 -2
  107. package/lib/typescript/scripts/retype-modes.d.cts +0 -2
@@ -0,0 +1,353 @@
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 _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
10
+ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
+ var _reactUtils = require("../../utils/react-utils");
12
+ var _Avatar = _interopRequireDefault(require("../Avatar/Avatar"));
13
+ var _Badge = _interopRequireDefault(require("../Badge/Badge"));
14
+ var _Button = _interopRequireDefault(require("../Button/Button"));
15
+ var _Image = _interopRequireDefault(require("../Image/Image"));
16
+ var _GlassFill = _interopRequireDefault(require("./GlassFill"));
17
+ var _jsxRuntime = require("react/jsx-runtime");
18
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
+ 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); }
20
+ /**
21
+ * ProductMerchandisingCard — a full-bleed image card (Figma node 5277:317)
22
+ * with a top header (avatar + badge) and a bottom **glass footer** that
23
+ * combines a real native background blur with a transparent→black gradient
24
+ * scrim for legible text over any image.
25
+ *
26
+ * Glass footer implementation (works on iOS, Android and Web):
27
+ * - **iOS / Android:** `<GlassFill>` wraps `@react-native-community/blur`'s
28
+ * `BlurView` — iOS gets a real `UIVisualEffectView` (live OS blur),
29
+ * Android gets the community `RealtimeBlurView` with a tinted scrim
30
+ * fallback. The native-only module is isolated in `GlassFill.tsx`.
31
+ * - **Web:** the platform-extension `GlassFill.web.tsx` renders a translucent
32
+ * `View` with `backdrop-filter: blur()` — Metro picks the right file so the
33
+ * web bundle never imports the native blur module.
34
+ * - The gradient scrim is drawn with `react-native-svg` (one renderer for all
35
+ * platforms) so the fade is identical everywhere.
36
+ *
37
+ * The blur strength is driven by the Figma `blur/minimal` token, mapped to the
38
+ * `GlassFill` 0–100 intensity scale the same way `MediaCard` does.
39
+ */
40
+ function ProductMerchandisingCard({
41
+ imageSource,
42
+ title = 'Title',
43
+ subtitle = 'Subtitle',
44
+ badgeLabel,
45
+ badge,
46
+ showAvatar = true,
47
+ avatarSource,
48
+ avatarMonogram,
49
+ avatar,
50
+ specialBadgeLabel,
51
+ specialBadgeIcon,
52
+ specialBadge,
53
+ ctaLabel = 'CTA',
54
+ onCtaPress,
55
+ cta,
56
+ onPress,
57
+ height = 223,
58
+ modes = _reactUtils.EMPTY_MODES,
59
+ style,
60
+ accessibilityLabel
61
+ }) {
62
+ // Unique gradient id so multiple cards on one (web) document never collide.
63
+ const rawId = (0, _react.useId)();
64
+ const scrimId = `pmc-footer-scrim-${rawId.replace(/[^a-zA-Z0-9_-]/g, '')}`;
65
+ const tokens = (0, _react.useMemo)(() => resolveTokens(modes), [modes]);
66
+ const containerStyle = {
67
+ height,
68
+ borderRadius: tokens.radius,
69
+ overflow: 'hidden',
70
+ position: 'relative',
71
+ flexDirection: 'column',
72
+ justifyContent: 'space-between'
73
+ };
74
+
75
+ // Header avatar defaults to the design's 36px (Avatar Size = M). A
76
+ // consumer-supplied `modes['Avatar Size']` still wins via spread order.
77
+ const avatarModes = (0, _react.useMemo)(() => ({
78
+ 'Avatar Size': 'M',
79
+ ...modes
80
+ }), [modes]);
81
+
82
+ // The Figma node renders the header badge with the brand "Secondary"
83
+ // appearance at "Medium" emphasis (lilac fill + dark label). These are set
84
+ // as defaults so the card matches the design out of the box; a
85
+ // consumer-supplied `modes` value still wins via spread order.
86
+ const badgeModes = (0, _react.useMemo)(() => ({
87
+ AppearanceBrand: 'Secondary',
88
+ Emphasis: 'Medium',
89
+ ...modes
90
+ }), [modes]);
91
+ const headerBadge = badge ?? (badgeLabel != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Badge.default, {
92
+ label: badgeLabel,
93
+ modes: badgeModes
94
+ }) : null);
95
+ const headerAvatar = showAvatar ? avatar ?? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Avatar.default, {
96
+ style: avatarSource ? 'Image' : avatarMonogram ? 'Monogram' : 'Image',
97
+ imageSource: avatarSource,
98
+ monogram: avatarMonogram,
99
+ modes: avatarModes
100
+ }) : null;
101
+ const footerSpecialBadge = specialBadge ?? (specialBadgeLabel != null ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
102
+ style: styles.specialBadge,
103
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_GlassFill.default, {
104
+ tint: "light",
105
+ intensity: SPECIAL_BADGE_INTENSITY,
106
+ overlayColor: SPECIAL_BADGE_BG,
107
+ style: styles.specialBadgeFill
108
+ }), specialBadgeIcon != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
109
+ style: styles.specialBadgeIcon,
110
+ children: specialBadgeIcon
111
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
112
+ style: tokens.specialBadgeText,
113
+ numberOfLines: 1,
114
+ children: specialBadgeLabel
115
+ })]
116
+ }) : null);
117
+
118
+ // The Figma CTA uses the brand "Secondary" appearance (purple fill, white
119
+ // label) at the small size. Defaults match the design; consumer `modes`
120
+ // win via spread order.
121
+ const ctaModes = (0, _react.useMemo)(() => ({
122
+ 'Button / Size': 'S',
123
+ AppearanceBrand: 'Secondary',
124
+ ...modes
125
+ }), [modes]);
126
+ const footerCta = cta ?? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
127
+ label: ctaLabel,
128
+ modes: ctaModes,
129
+ onPress: onCtaPress
130
+ });
131
+ const content = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
132
+ children: [imageSource != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Image.default, {
133
+ imageSource: imageSource,
134
+ style: _reactNative.StyleSheet.absoluteFillObject,
135
+ width: "100%",
136
+ height: height,
137
+ resizeMode: "cover",
138
+ accessibilityElementsHidden: true,
139
+ importantForAccessibility: "no"
140
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
141
+ style: tokens.header,
142
+ pointerEvents: "box-none",
143
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
144
+ style: styles.avatarContainer,
145
+ children: headerAvatar
146
+ }), headerBadge]
147
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
148
+ style: tokens.footer,
149
+ pointerEvents: "box-none",
150
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_GlassFill.default, {
151
+ tint: "dark",
152
+ intensity: tokens.blurIntensity,
153
+ progressive: true
154
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
155
+ style: [_reactNative.StyleSheet.absoluteFill, styles.scrim],
156
+ pointerEvents: "none",
157
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSvg.default, {
158
+ width: "100%",
159
+ height: "100%",
160
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Defs, {
161
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSvg.LinearGradient, {
162
+ id: scrimId,
163
+ x1: "0",
164
+ y1: "0",
165
+ x2: "0",
166
+ y2: "1",
167
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Stop, {
168
+ offset: "0.018",
169
+ stopColor: "#000000",
170
+ stopOpacity: 0
171
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Stop, {
172
+ offset: "0.974",
173
+ stopColor: "#000000",
174
+ stopOpacity: 1
175
+ })]
176
+ })
177
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSvg.Rect, {
178
+ x: "0",
179
+ y: "0",
180
+ width: "100%",
181
+ height: "100%",
182
+ fill: `url(#${scrimId})`
183
+ })]
184
+ })
185
+ }), footerSpecialBadge, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
186
+ style: styles.footerRow,
187
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
188
+ style: tokens.textWrap,
189
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
190
+ style: tokens.title,
191
+ numberOfLines: 1,
192
+ children: title
193
+ }), subtitle != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
194
+ style: tokens.subtitle,
195
+ numberOfLines: 1,
196
+ children: subtitle
197
+ }) : null]
198
+ }), footerCta]
199
+ })]
200
+ })]
201
+ });
202
+ if (onPress) {
203
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
204
+ style: ({
205
+ pressed
206
+ }) => [containerStyle, pressed ? styles.pressed : null, style],
207
+ accessibilityRole: "button",
208
+ accessibilityLabel: accessibilityLabel ?? title,
209
+ onPress: onPress,
210
+ children: content
211
+ });
212
+ }
213
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
214
+ style: [containerStyle, style],
215
+ accessibilityLabel: accessibilityLabel,
216
+ children: content
217
+ });
218
+ }
219
+
220
+ // ---------------------------------------------------------------------------
221
+ // Tokens / static styles
222
+ // ---------------------------------------------------------------------------
223
+
224
+ // Figma footer backdrop-blur token (`blur/minimal`). The footer uses a
225
+ // *progressive* blur, so this maps the token to the intensity at the BOTTOM of
226
+ // the ramp (the strongest point); the upper part fades to fully clear. Kept
227
+ // intentionally small to match the design's subtle "minimal" blur.
228
+ const BLUR_INTENSITY_FACTOR = 1.0;
229
+
230
+ // Special badge ("frosted" pill) — values are literals in the Figma node
231
+ // (no dedicated tokens): bg rgba(255,245,229,0.15), 5px backdrop blur.
232
+ const SPECIAL_BADGE_BG = 'rgba(255,245,229,0.15)';
233
+ const SPECIAL_BADGE_INTENSITY = 17; // ~5px CSS blur / ~2 native blurAmount
234
+
235
+ function asNum(raw, fallback) {
236
+ const n = typeof raw === 'number' ? raw : parseFloat(raw);
237
+ return Number.isFinite(n) ? n : fallback;
238
+ }
239
+ function asStr(raw, fallback) {
240
+ return raw != null ? String(raw) : fallback;
241
+ }
242
+ function resolveTokens(modes) {
243
+ // NOTE: token names are passed as string literals DIRECTLY to
244
+ // getVariableByName so the `extract-component-tokens` script can statically
245
+ // collect them for the generated docs. Do not refactor these into a helper
246
+ // that receives the name as a variable.
247
+ const radius = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/radius', modes), 12);
248
+ const headerPadH = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/header/padding/horizontal', modes), 12);
249
+ const headerPadV = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/header/padding/vertical', modes), 12);
250
+ const footerGap = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/gap', modes), 8);
251
+ const footerPadH = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/padding/horizontal', modes), 16);
252
+ const footerPadV = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/padding/vertical', modes), 16);
253
+ const textGap = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/text/gap', modes), 2);
254
+ const blurRadius = asNum((0, _figmaVariablesResolver.getVariableByName)('blur/minimal', modes), 29);
255
+ const titleColor = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/title/font/color', modes), '#ffffff');
256
+ const titleSize = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/title/fontsize', modes), 14);
257
+ const titleFamily = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/title/fontfamily', modes), 'JioType Var');
258
+ const titleWeight = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/title/fontweight', modes), '700');
259
+ const subtitleColor = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/subtitle/font/color', modes), '#c5bcb5');
260
+ const subtitleSize = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/subtitle/fontsize', modes), 12);
261
+ const subtitleFamily = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/subtitle/fontfamily', modes), 'JioType Var');
262
+ const subtitleWeight = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/subtitle/fontweight', modes), '400');
263
+ const sbSize = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/text/fontsize', modes), 12);
264
+ const sbFamily = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/text/fontfamily', modes), 'JioType Var');
265
+ const sbWeight = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/text/fontweight', modes), '500');
266
+ return {
267
+ radius,
268
+ blurIntensity: Math.max(0, Math.min(100, Math.round(blurRadius * BLUR_INTENSITY_FACTOR))),
269
+ header: {
270
+ flexDirection: 'row',
271
+ alignItems: 'flex-start',
272
+ justifyContent: 'space-between',
273
+ paddingHorizontal: headerPadH,
274
+ paddingVertical: headerPadV,
275
+ zIndex: 1
276
+ },
277
+ footer: {
278
+ paddingHorizontal: footerPadH,
279
+ paddingVertical: footerPadV,
280
+ gap: footerGap,
281
+ overflow: 'hidden',
282
+ zIndex: 2
283
+ },
284
+ textWrap: {
285
+ flex: 1,
286
+ gap: textGap,
287
+ justifyContent: 'center'
288
+ },
289
+ title: {
290
+ color: titleColor,
291
+ fontSize: titleSize,
292
+ fontFamily: titleFamily,
293
+ fontWeight: titleWeight,
294
+ lineHeight: Math.round(titleSize * 1.2),
295
+ includeFontPadding: false
296
+ },
297
+ subtitle: {
298
+ color: subtitleColor,
299
+ fontSize: subtitleSize,
300
+ fontFamily: subtitleFamily,
301
+ fontWeight: subtitleWeight,
302
+ lineHeight: Math.round(subtitleSize * 1.2),
303
+ includeFontPadding: false
304
+ },
305
+ specialBadgeText: {
306
+ color: '#ffffff',
307
+ fontSize: sbSize,
308
+ fontFamily: sbFamily,
309
+ fontWeight: sbWeight,
310
+ lineHeight: Math.round(sbSize * 1.2),
311
+ includeFontPadding: false
312
+ }
313
+ };
314
+ }
315
+ const styles = _reactNative.StyleSheet.create({
316
+ avatarContainer: {
317
+ flexShrink: 1,
318
+ justifyContent: 'center'
319
+ },
320
+ footerRow: {
321
+ flexDirection: 'row',
322
+ alignItems: 'center',
323
+ justifyContent: 'space-between',
324
+ gap: 8
325
+ },
326
+ scrim: {
327
+ // The footer node sits at 90% opacity in Figma; applying it to the
328
+ // scrim (not the content) keeps the title/CTA crisp while preserving
329
+ // the intended fade strength.
330
+ opacity: 0.9
331
+ },
332
+ specialBadge: {
333
+ flexDirection: 'row',
334
+ alignItems: 'center',
335
+ gap: 4,
336
+ paddingHorizontal: 6,
337
+ paddingVertical: 2,
338
+ borderRadius: 4,
339
+ overflow: 'hidden',
340
+ alignSelf: 'flex-start'
341
+ },
342
+ specialBadgeFill: {
343
+ borderRadius: 4
344
+ },
345
+ specialBadgeIcon: {
346
+ justifyContent: 'center',
347
+ alignItems: 'center'
348
+ },
349
+ pressed: {
350
+ opacity: 0.92
351
+ }
352
+ });
353
+ var _default = exports.default = ProductMerchandisingCard;
@@ -0,0 +1,161 @@
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 _Divider = _interopRequireDefault(require("../Divider/Divider"));
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ /**
15
+ * A value rendered at either end of the marker. A `string`/`number` is rendered
16
+ * with the built-in title typography; any other `ReactNode` (e.g. a
17
+ * `MoneyValue`) is rendered as-is so consumers can fully control presentation.
18
+ */
19
+
20
+ const isTextValue = value => typeof value === 'string' || typeof value === 'number';
21
+
22
+ /**
23
+ * ProjectionMarker renders a start value and an end value connected to a
24
+ * centered badge that summarizes the projection (e.g. a tenure and interest
25
+ * rate). It mirrors the Figma `projectionMarker` component and is commonly used
26
+ * inside "Potential returns" style cards.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * <ProjectionMarker
31
+ * startValue="₹1,00,000"
32
+ * endValue="₹1,25,101"
33
+ * duration="1Y 10M"
34
+ * rate="@ 8.25 %"
35
+ * />
36
+ * ```
37
+ *
38
+ * @example Custom end values via MoneyValue
39
+ * ```tsx
40
+ * <ProjectionMarker
41
+ * startValue={<MoneyValue value="1,00,000" />}
42
+ * endValue={<MoneyValue value="1,25,101" />}
43
+ * duration="1Y 10M"
44
+ * rate="@ 8.25 %"
45
+ * />
46
+ * ```
47
+ */
48
+ function ProjectionMarker({
49
+ startValue = '₹1,00,000',
50
+ endValue = '₹1,25,101',
51
+ duration = '1Y 10M',
52
+ rate = '@ 8.25 %',
53
+ showConnectors = true,
54
+ modes = _reactUtils.EMPTY_MODES,
55
+ style,
56
+ startValueStyle,
57
+ endValueStyle,
58
+ badgeStyle,
59
+ durationStyle,
60
+ rateStyle,
61
+ accessibilityLabel
62
+ }) {
63
+ const titleColor = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/title/color', modes) ?? '#000000';
64
+ const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/title/fontfamily', modes) ?? 'JioType Var';
65
+ const titleFontSize = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/title/fontsize', modes) ?? 14;
66
+ const titleFontWeight = String((0, _figmaVariablesResolver.getVariableByName)('projectionMarker/title/fontweight', modes) ?? 600);
67
+ const durationColor = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/duration/color', modes) ?? '#000000';
68
+ const durationFontFamily = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/duration/fontfamily', modes) ?? 'JioType Var';
69
+ const durationFontSize = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/duration/fontsize', modes) ?? 12;
70
+ const durationFontWeight = String((0, _figmaVariablesResolver.getVariableByName)('projectionMarker/duration/fontweight', modes) ?? 500);
71
+ const rateColor = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/rate/color', modes) ?? '#6b6b6b';
72
+ const rateFontFamily = (0, _figmaVariablesResolver.getVariableByName)('metricdata/rate/fontfamily', modes) ?? 'JioType Var';
73
+ const rateFontSize = (0, _figmaVariablesResolver.getVariableByName)('metricdata/rate/fontsize', modes) ?? 11;
74
+ const rateFontWeight = String((0, _figmaVariablesResolver.getVariableByName)('metricdata/rate/fontweight', modes) ?? 400);
75
+ const badgeBg = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/durationWrap/bg/color', modes) ?? '#f5f5f5';
76
+ const badgeBorderColor = (0, _figmaVariablesResolver.getVariableByName)('projectionMarker/durationWrap/border/color', modes) ?? '#ebebed';
77
+ const badgeBorderWidth = (0, _figmaVariablesResolver.getVariableByName)('metricdata/durationWrap/stroke', modes) ?? 1;
78
+ const badgeRadius = (0, _figmaVariablesResolver.getVariableByName)('metricdata/durationWrap/radius', modes) ?? 8;
79
+ const badgePaddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('metricdata/durationWrap/padding/horizontal', modes) ?? 16;
80
+ const badgePaddingVertical = (0, _figmaVariablesResolver.getVariableByName)('metricdata/durationWrap/padding/vertical', modes) ?? 8;
81
+ const titleTextStyle = {
82
+ color: titleColor,
83
+ fontFamily: titleFontFamily,
84
+ fontSize: titleFontSize,
85
+ fontWeight: titleFontWeight,
86
+ lineHeight: titleFontSize * 1.3
87
+ };
88
+ const renderEndValue = (value, overrideStyle) => {
89
+ if (value === null || value === undefined) return null;
90
+ if (isTextValue(value)) {
91
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
92
+ style: [titleTextStyle, overrideStyle],
93
+ numberOfLines: 1,
94
+ children: value
95
+ });
96
+ }
97
+ return (0, _reactUtils.cloneChildrenWithModes)(value, modes);
98
+ };
99
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
100
+ style: [styles.container, style],
101
+ accessibilityRole: "summary",
102
+ accessibilityLabel: accessibilityLabel,
103
+ children: [renderEndValue(startValue, startValueStyle), showConnectors && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
104
+ direction: "horizontal",
105
+ modes: modes,
106
+ style: styles.connector
107
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
108
+ style: [styles.badge, {
109
+ backgroundColor: badgeBg,
110
+ borderColor: badgeBorderColor,
111
+ borderWidth: badgeBorderWidth,
112
+ borderRadius: badgeRadius,
113
+ paddingHorizontal: badgePaddingHorizontal,
114
+ paddingVertical: badgePaddingVertical
115
+ }, badgeStyle],
116
+ children: [duration !== null && duration !== undefined ? isTextValue(duration) ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
117
+ style: [{
118
+ color: durationColor,
119
+ fontFamily: durationFontFamily,
120
+ fontSize: durationFontSize,
121
+ fontWeight: durationFontWeight,
122
+ lineHeight: durationFontSize * 1.2,
123
+ textAlign: 'center'
124
+ }, durationStyle],
125
+ children: duration
126
+ }) : (0, _reactUtils.cloneChildrenWithModes)(duration, modes) : null, rate !== null && rate !== undefined ? isTextValue(rate) ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
127
+ style: [{
128
+ color: rateColor,
129
+ fontFamily: rateFontFamily,
130
+ fontSize: rateFontSize,
131
+ fontWeight: rateFontWeight,
132
+ lineHeight: rateFontSize * 1.3,
133
+ textAlign: 'center'
134
+ }, rateStyle],
135
+ children: rate
136
+ }) : (0, _reactUtils.cloneChildrenWithModes)(rate, modes) : null]
137
+ }), showConnectors && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
138
+ direction: "horizontal",
139
+ modes: modes,
140
+ style: styles.connector
141
+ }), renderEndValue(endValue, endValueStyle)]
142
+ });
143
+ }
144
+ const styles = {
145
+ container: {
146
+ flexDirection: 'row',
147
+ alignItems: 'center',
148
+ width: '100%'
149
+ },
150
+ connector: {
151
+ flex: 1,
152
+ alignSelf: 'center',
153
+ marginHorizontal: 16
154
+ },
155
+ badge: {
156
+ flexDirection: 'column',
157
+ alignItems: 'center',
158
+ justifyContent: 'center'
159
+ }
160
+ };
161
+ var _default = exports.default = ProjectionMarker;
@@ -3,8 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.Radio = Radio;
7
- exports.default = void 0;
6
+ exports.default = exports.Radio = void 0;
8
7
  var _react = _interopRequireWildcard(require("react"));
9
8
  var _reactNative = require("react-native");
10
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
@@ -19,14 +18,14 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
19
18
  // Radio
20
19
  // ---------------------------------------------------------------------------
21
20
 
22
- function Radio({
21
+ const Radio = exports.Radio = /*#__PURE__*/(0, _react.forwardRef)(function Radio({
23
22
  selected = false,
24
23
  disabled = false,
25
24
  onPress,
26
25
  modes = _reactUtils.EMPTY_MODES,
27
26
  style,
28
27
  testID
29
- }) {
28
+ }, ref) {
30
29
  // ---- Refs & State ----
31
30
  const [hovered, setHovered] = (0, _react.useState)(false);
32
31
  const [focused, setFocused] = (0, _react.useState)(false);
@@ -174,6 +173,7 @@ function Radio({
174
173
  (0, _figmaVariablesResolver.getVariableByName)('radio/disabledSelected/border/color');
175
174
  }
176
175
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
176
+ ref: ref,
177
177
  testID: testID,
178
178
  disabled: disabled,
179
179
  onPress: onPress,
@@ -190,5 +190,5 @@ function Radio({
190
190
  style: selectorStyle
191
191
  })
192
192
  });
193
- }
193
+ });
194
194
  var _default = exports.default = Radio;