jfs-components 0.1.36 → 0.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/lib/commonjs/components/Accordion/Accordion.js +16 -3
- package/lib/commonjs/components/AppBar/AppBar.js +118 -93
- package/lib/commonjs/components/CompareTable/CompareTable.js +98 -33
- package/lib/commonjs/components/FormField/FormField.js +9 -1
- package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +4 -14
- package/lib/commonjs/components/HelloJioInput/HelloJioInput.js +20 -4
- package/lib/commonjs/components/PageHero/PageHero.js +3 -0
- package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +50 -30
- package/lib/commonjs/components/ValueBackMetric/ValueBackMetric.js +117 -89
- package/lib/commonjs/components/index.js +7 -1
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -42204
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/Accordion/Accordion.js +16 -3
- package/lib/module/components/AppBar/AppBar.js +116 -93
- package/lib/module/components/CompareTable/CompareTable.js +99 -34
- package/lib/module/components/FormField/FormField.js +9 -1
- package/lib/module/components/FullscreenModal/FullscreenModal.js +4 -14
- package/lib/module/components/HelloJioInput/HelloJioInput.js +20 -4
- package/lib/module/components/PageHero/PageHero.js +3 -0
- package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +50 -30
- package/lib/module/components/ValueBackMetric/ValueBackMetric.js +120 -93
- package/lib/module/components/index.js +1 -1
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -42204
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/Accordion/Accordion.d.ts +14 -1
- package/lib/typescript/src/components/AppBar/AppBar.d.ts +46 -14
- package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +29 -12
- package/lib/typescript/src/components/HelloJioInput/HelloJioInput.d.ts +6 -4
- package/lib/typescript/src/components/PageHero/PageHero.d.ts +1 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +8 -1
- package/lib/typescript/src/components/ValueBackMetric/ValueBackMetric.d.ts +27 -16
- package/lib/typescript/src/components/index.d.ts +1 -1
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +61 -33
- package/src/components/AppBar/AppBar.tsx +154 -124
- package/src/components/CompareTable/CompareTable.tsx +138 -52
- package/src/components/FormField/FormField.tsx +7 -0
- package/src/components/FullscreenModal/FullscreenModal.tsx +5 -14
- package/src/components/HelloJioInput/HelloJioInput.tsx +31 -12
- package/src/components/PageHero/PageHero.tsx +5 -0
- package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +63 -30
- package/src/components/ValueBackMetric/ValueBackMetric.tsx +178 -104
- package/src/components/index.ts +6 -1
- package/src/design-tokens/Coin Variables-variables-full.json +1 -42204
- package/src/icons/registry.ts +1 -1
|
@@ -57,7 +57,15 @@ const STATE_FALLBACKS = {
|
|
|
57
57
|
iconColor: '#24262b'
|
|
58
58
|
},
|
|
59
59
|
IdleJioPlus: {
|
|
60
|
-
|
|
60
|
+
// Glass fill. In Figma the IdleJioPlus surface resolves
|
|
61
|
+
// `helloJioInput/background` under the `Page type = JioPlus` variable mode,
|
|
62
|
+
// which yields a TRANSLUCENT light fill (not the opaque `#f5f5f5` the
|
|
63
|
+
// MainPage mode gives). Painted over the backdrop blur, an opaque value
|
|
64
|
+
// would read as a solid bar and hide the blur entirely — so, matching the
|
|
65
|
+
// translucent glass fallbacks the sibling GlassFill consumers use
|
|
66
|
+
// (FavoriteToggle `#ffffff33`, NumberPagination `rgba(141,141,141,0.4)`),
|
|
67
|
+
// this fallback carries alpha so the frost tints the blurred content.
|
|
68
|
+
background: '#f5f5f566',
|
|
61
69
|
borderColor: '#f5f5f5',
|
|
62
70
|
labelColor: '#545961',
|
|
63
71
|
iconColor: '#545961'
|
|
@@ -94,7 +102,11 @@ function resolveHelloJioInputTokens(modes, visualState) {
|
|
|
94
102
|
// Glass keeps the container transparent so GlassFill shows through.
|
|
95
103
|
backgroundColor: useGlass ? 'transparent' : background,
|
|
96
104
|
borderColor,
|
|
97
|
-
|
|
105
|
+
// The Figma IdleJioPlus variant is a borderless frosted pill — it has no
|
|
106
|
+
// `border/color`/`strokeWidth` tokens. Drawing the Idle border color here
|
|
107
|
+
// would leave a faint light ring the design doesn't have, so drop the
|
|
108
|
+
// border entirely in the glass state.
|
|
109
|
+
borderWidth: useGlass ? 0 : strokeWidth,
|
|
98
110
|
borderStyle: 'solid',
|
|
99
111
|
borderRadius,
|
|
100
112
|
paddingLeft,
|
|
@@ -201,11 +213,15 @@ const HelloJioInput = /*#__PURE__*/(0, _react.forwardRef)(function HelloJioInput
|
|
|
201
213
|
setIsFocused(false);
|
|
202
214
|
onBlur?.(e);
|
|
203
215
|
}, [onBlur]);
|
|
204
|
-
|
|
216
|
+
|
|
217
|
+
// Symmetric with `trailing`: an explicit `null` hides the leading icon
|
|
218
|
+
// (the design's `startSlot={false}`); `undefined` falls back to the
|
|
219
|
+
// default brand icon.
|
|
220
|
+
const leadingElement = leading === undefined ? leadingIconName ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
205
221
|
name: leadingIconName,
|
|
206
222
|
size: tokens.iconSize,
|
|
207
223
|
color: tokens.iconColor
|
|
208
|
-
}) : null
|
|
224
|
+
}) : null : leading;
|
|
209
225
|
const processedLeading = leadingElement ? (0, _reactUtils.cloneChildrenWithModes)(_react.default.Children.toArray(leadingElement), modes) : null;
|
|
210
226
|
const defaultTrailing = /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
|
|
211
227
|
iconName: sendIconName,
|
|
@@ -39,6 +39,7 @@ const MEDIA_FALLBACK = 117;
|
|
|
39
39
|
* eyebrow="Upgrade to JioFinance+"
|
|
40
40
|
* headline="Resume earning cashback, extra points, and 1% gold"
|
|
41
41
|
* supportingText="₹999/year · ₹0 until 2027"
|
|
42
|
+
* body="₹999/year · ₹0 until 2027"
|
|
42
43
|
* buttonLabel="Renew for free"
|
|
43
44
|
* onButtonPress={() => navigate('Upgrade')}
|
|
44
45
|
* modes={{ 'Page type': 'JioPlus' }}
|
|
@@ -71,6 +72,7 @@ function PageHero({
|
|
|
71
72
|
...propModes
|
|
72
73
|
}), [globalModes, propModes]);
|
|
73
74
|
const gap = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/gap', modes));
|
|
75
|
+
const paddingHorizontal = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/padding/horizontal', modes));
|
|
74
76
|
const textWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/textWrap/gap', modes));
|
|
75
77
|
|
|
76
78
|
// Media slot box — Figma frame 4540:7845 ("Video"), sized by the
|
|
@@ -115,6 +117,7 @@ function PageHero({
|
|
|
115
117
|
flexDirection: 'column',
|
|
116
118
|
alignItems: 'center',
|
|
117
119
|
gap,
|
|
120
|
+
paddingHorizontal,
|
|
118
121
|
width: '100%'
|
|
119
122
|
};
|
|
120
123
|
const textWrapStyle = {
|
|
@@ -48,6 +48,7 @@ function ProductMerchandisingCard({
|
|
|
48
48
|
title = 'Title',
|
|
49
49
|
subtitle = 'Subtitle',
|
|
50
50
|
badgeLabel,
|
|
51
|
+
badgeIcon,
|
|
51
52
|
badge,
|
|
52
53
|
showAvatar = true,
|
|
53
54
|
avatarSource,
|
|
@@ -102,29 +103,33 @@ function ProductMerchandisingCard({
|
|
|
102
103
|
}), [modes]);
|
|
103
104
|
const headerBadge = badge ?? (badgeLabel != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Badge.default, {
|
|
104
105
|
label: badgeLabel,
|
|
106
|
+
leading: badgeIcon,
|
|
105
107
|
modes: badgeModes
|
|
106
108
|
}) : null);
|
|
107
109
|
const headerAvatar = showAvatar ? avatar ?? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Avatar.default, {
|
|
108
110
|
style: avatarSource ? 'Image' : avatarMonogram ? 'Monogram' : 'Image',
|
|
109
|
-
|
|
110
|
-
|
|
111
|
+
...(avatarSource != null ? {
|
|
112
|
+
imageSource: avatarSource
|
|
113
|
+
} : {}),
|
|
114
|
+
...(avatarMonogram != null ? {
|
|
115
|
+
monogram: avatarMonogram
|
|
116
|
+
} : {}),
|
|
111
117
|
modes: avatarModes
|
|
112
118
|
}) : null;
|
|
113
119
|
|
|
114
|
-
// The footer "special badge" is
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
// instantiation renders byte-for-byte the same as before.
|
|
120
|
+
// The footer "special badge" is the shared <Badge type="glass">. Overlay +
|
|
121
|
+
// blur come from `badge/glass/*` + `blur/minimal`; box/gap from
|
|
122
|
+
// `productMerchandisingcard/specialbadge/*`; label color/weight from the
|
|
123
|
+
// glass badge tokens (Figma: white / 600). Optional `specialBadgeIcon`
|
|
124
|
+
// maps to Badge's `leading` slot.
|
|
120
125
|
const footerSpecialBadge = specialBadge ?? (specialBadgeLabel != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Badge.default, {
|
|
121
126
|
type: "glass",
|
|
122
127
|
label: specialBadgeLabel,
|
|
123
128
|
leading: specialBadgeIcon,
|
|
124
|
-
glassOverlayColor:
|
|
125
|
-
glassIntensity:
|
|
129
|
+
glassOverlayColor: tokens.specialBadgeBg,
|
|
130
|
+
glassIntensity: tokens.specialBadgeIntensity,
|
|
126
131
|
modes: modes,
|
|
127
|
-
style:
|
|
132
|
+
style: tokens.specialBadge,
|
|
128
133
|
labelStyle: tokens.specialBadgeText,
|
|
129
134
|
...(disableTruncation != null ? {
|
|
130
135
|
disableTruncation
|
|
@@ -142,7 +147,9 @@ function ProductMerchandisingCard({
|
|
|
142
147
|
const footerCta = cta ?? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
|
|
143
148
|
label: ctaLabel,
|
|
144
149
|
modes: ctaModes,
|
|
145
|
-
|
|
150
|
+
...(onCtaPress != null ? {
|
|
151
|
+
onPress: onCtaPress
|
|
152
|
+
} : {})
|
|
146
153
|
});
|
|
147
154
|
const content = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
148
155
|
children: [imageSource != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Image.default, {
|
|
@@ -303,12 +310,6 @@ function ProductMerchandisingCard({
|
|
|
303
310
|
// the ramp (the strongest point); the upper part fades to fully clear. Kept
|
|
304
311
|
// intentionally small to match the design's subtle "minimal" blur.
|
|
305
312
|
const BLUR_INTENSITY_FACTOR = 1.0;
|
|
306
|
-
|
|
307
|
-
// Special badge ("frosted" pill) — values are literals in the Figma node
|
|
308
|
-
// (no dedicated tokens): bg rgba(255,245,229,0.15), 5px backdrop blur.
|
|
309
|
-
const SPECIAL_BADGE_BG = 'rgba(255,245,229,0.15)';
|
|
310
|
-
const SPECIAL_BADGE_INTENSITY = 17; // ~5px CSS blur / ~2 native blurAmount
|
|
311
|
-
|
|
312
313
|
function asNum(raw, fallback) {
|
|
313
314
|
const n = typeof raw === 'number' ? raw : parseFloat(raw);
|
|
314
315
|
return Number.isFinite(n) ? n : fallback;
|
|
@@ -328,6 +329,7 @@ function resolveTokens(modes) {
|
|
|
328
329
|
const footerPadH = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/padding/horizontal', modes), 16);
|
|
329
330
|
const footerPadV = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/padding/vertical', modes), 16);
|
|
330
331
|
const textGap = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/text/gap', modes), 2);
|
|
332
|
+
const textWrapMinWidth = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/textWrap/minWidth', modes), 100);
|
|
331
333
|
const blurRadius = asNum((0, _figmaVariablesResolver.getVariableByName)('blur/minimal', modes), 29);
|
|
332
334
|
const titleColor = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/title/font/color', modes), '#ffffff');
|
|
333
335
|
const titleSize = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/title/fontsize', modes), 14);
|
|
@@ -339,7 +341,20 @@ function resolveTokens(modes) {
|
|
|
339
341
|
const subtitleWeight = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/footer/subtitle/fontweight', modes), '400');
|
|
340
342
|
const sbSize = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/text/fontsize', modes), 12);
|
|
341
343
|
const sbFamily = asStr((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/text/fontfamily', modes), 'JioType Var');
|
|
342
|
-
|
|
344
|
+
// No dedicated `specialbadge/text/fontweight` in the collection — Figma
|
|
345
|
+
// binds the glass badge label to `badge/label/fontWeight` (600).
|
|
346
|
+
const sbWeight = asStr((0, _figmaVariablesResolver.getVariableByName)('badge/label/fontWeight', modes), '600');
|
|
347
|
+
const sbPadH = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/padding/horizontal', modes), 6);
|
|
348
|
+
const sbGap = asNum((0, _figmaVariablesResolver.getVariableByName)('productMerchandisingcard/specialbadge/gap', modes), 4);
|
|
349
|
+
const sbPadV = asNum((0, _figmaVariablesResolver.getVariableByName)('badge/padding/vertical', modes), 4);
|
|
350
|
+
const sbRadius = asNum((0, _figmaVariablesResolver.getVariableByName)('badge/radius', modes), 4);
|
|
351
|
+
const sbLabelColor = asStr((0, _figmaVariablesResolver.getVariableByName)('badge/glass/color/label', modes), '#ffffff');
|
|
352
|
+
|
|
353
|
+
// The special badge is a `type="glass"` Badge: its overlay + blur come
|
|
354
|
+
// straight from the shared badge-glass tokens the design references
|
|
355
|
+
// (`badge/glass/color/background` and the `glass/minimal` → `blur/minimal`
|
|
356
|
+
// effect), so it frosts at the same strength as the footer.
|
|
357
|
+
const specialBadgeBg = asStr((0, _figmaVariablesResolver.getVariableByName)('badge/glass/color/background', modes), 'rgba(255,255,255,0.15)');
|
|
343
358
|
|
|
344
359
|
// SVG `<FeGaussianBlur stdDeviation>` is resolution-independent and renders
|
|
345
360
|
// an identical Gaussian on iOS, Android and web — so unlike the old
|
|
@@ -351,6 +366,10 @@ function resolveTokens(modes) {
|
|
|
351
366
|
radius,
|
|
352
367
|
blurIntensity: Math.max(0, Math.min(100, Math.round(blurRadius * BLUR_INTENSITY_FACTOR))),
|
|
353
368
|
imageBlurStdDeviation,
|
|
369
|
+
specialBadgeBg,
|
|
370
|
+
// Same `blur/minimal`-derived intensity the footer glass uses, so the
|
|
371
|
+
// special badge frosts consistently with the surface behind it.
|
|
372
|
+
specialBadgeIntensity: Math.max(0, Math.min(100, Math.round(blurRadius * BLUR_INTENSITY_FACTOR))),
|
|
354
373
|
header: {
|
|
355
374
|
flexDirection: 'row',
|
|
356
375
|
alignItems: 'flex-start',
|
|
@@ -368,6 +387,9 @@ function resolveTokens(modes) {
|
|
|
368
387
|
},
|
|
369
388
|
textWrap: {
|
|
370
389
|
flex: 1,
|
|
390
|
+
// The Figma footer pins the text column to a minimum width so a long
|
|
391
|
+
// CTA can never squeeze the title/subtitle away (`footer/textWrap/minWidth`).
|
|
392
|
+
minWidth: textWrapMinWidth,
|
|
371
393
|
gap: textGap,
|
|
372
394
|
justifyContent: 'center'
|
|
373
395
|
},
|
|
@@ -387,8 +409,16 @@ function resolveTokens(modes) {
|
|
|
387
409
|
lineHeight: Math.round(subtitleSize * 1.2),
|
|
388
410
|
includeFontPadding: false
|
|
389
411
|
},
|
|
412
|
+
// Pin the special-badge box to the card collection tokens so a parent
|
|
413
|
+
// `Badge Size` mode cannot inflate/deflate this pill away from Figma.
|
|
414
|
+
specialBadge: {
|
|
415
|
+
paddingHorizontal: sbPadH,
|
|
416
|
+
paddingVertical: sbPadV,
|
|
417
|
+
borderRadius: sbRadius,
|
|
418
|
+
gap: sbGap
|
|
419
|
+
},
|
|
390
420
|
specialBadgeText: {
|
|
391
|
-
color:
|
|
421
|
+
color: sbLabelColor,
|
|
392
422
|
fontSize: sbSize,
|
|
393
423
|
fontFamily: sbFamily,
|
|
394
424
|
fontWeight: sbWeight,
|
|
@@ -414,16 +444,6 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
414
444
|
// the intended fade strength.
|
|
415
445
|
opacity: 0.9
|
|
416
446
|
},
|
|
417
|
-
// Overrides layered on top of <Badge type="glass">. Badge already supplies
|
|
418
|
-
// the row layout + 4px gap (when a leading icon is present), `overflow:
|
|
419
|
-
// 'hidden'`, `alignSelf: 'flex-start'` and `alignItems: 'center'`; these
|
|
420
|
-
// pin the special badge's literal Figma box (6/2 padding, 4px radius)
|
|
421
|
-
// regardless of the badge size tokens resolved by the active modes.
|
|
422
|
-
specialBadge: {
|
|
423
|
-
paddingHorizontal: 6,
|
|
424
|
-
paddingVertical: 2,
|
|
425
|
-
borderRadius: 4
|
|
426
|
-
},
|
|
427
447
|
pressed: {
|
|
428
448
|
opacity: 0.92
|
|
429
449
|
}
|
|
@@ -4,62 +4,97 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var _react =
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
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 _Icon = _interopRequireDefault(require("../Icon/Icon"));
|
|
12
|
-
var
|
|
12
|
+
var _Text = _interopRequireDefault(require("../Text/Text"));
|
|
13
13
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
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); }
|
|
15
16
|
const TITLE_LINE_HEIGHT_RATIO = 1.2;
|
|
16
17
|
const VALUE_LINE_HEIGHT_RATIO = 1.2;
|
|
17
18
|
const CAPTION_LINE_HEIGHT_RATIO = 1.5;
|
|
18
|
-
|
|
19
|
-
// The Figma node binds the header-icon size and the per-part font sizes/weights
|
|
20
|
-
// to `valueBackMetric/*` variables, but those tokens are NOT in the committed
|
|
21
|
-
// variables snapshot (`npm run tokens -- find valueBackMetric` → no matches).
|
|
22
|
-
// They also intentionally differ from the `metricdata/*` typography defaults
|
|
23
|
-
// (e.g. `metricdata/value` resolves to 20px/700, whereas this component's value
|
|
24
|
-
// is 16px/500). So the sizes/weights below are encoded as literal constants
|
|
25
|
-
// matching the Figma design exactly. Colours, gaps and padding DO exist as real
|
|
26
|
-
// `metricdata/*` tokens (and match the design), so those resolve through
|
|
27
|
-
// `getVariableByName` and stay themeable.
|
|
28
|
-
const TITLE_FONT_SIZE = 12;
|
|
29
|
-
const TITLE_FONT_WEIGHT = '500';
|
|
30
|
-
const VALUE_FONT_SIZE = 16;
|
|
31
|
-
const VALUE_FONT_WEIGHT = '500';
|
|
32
|
-
const CAPTION_FONT_SIZE = 12;
|
|
33
|
-
const CAPTION_FONT_WEIGHT = '400';
|
|
34
|
-
const FONT_FAMILY = 'JioType Var';
|
|
35
|
-
const CARD_BACKGROUND = '#ffffff';
|
|
36
19
|
const CARD_MIN_HEIGHT = 82;
|
|
37
20
|
const ICON_SIZE = 18;
|
|
21
|
+
const TEXT_WRAP_GAP = 4;
|
|
22
|
+
|
|
38
23
|
// Figma renders the header glyph flush (all `icon/padding/*` tokens are 0); the
|
|
39
|
-
// shared Icon pulls padding from those tokens, so
|
|
40
|
-
// explicitly to keep the icon flush against the title.
|
|
24
|
+
// shared Icon pulls padding from those tokens, so zero it explicitly.
|
|
41
25
|
const ICON_PADDING_RESET = {
|
|
42
26
|
paddingLeft: 0,
|
|
43
27
|
paddingRight: 0,
|
|
44
28
|
paddingTop: 0,
|
|
45
29
|
paddingBottom: 0
|
|
46
30
|
};
|
|
31
|
+
// The `valueBackMetric/*` layout + typography tokens are bound on the Figma
|
|
32
|
+
// node but are NOT yet in the committed variables snapshot
|
|
33
|
+
// (`npm run tokens -- find valueBackMetric` → no matches). Colours and the
|
|
34
|
+
// header-row gap do exist as `metricdata/*` / `icon/*` tokens. Until the
|
|
35
|
+
// export is re-synced, `getVariableByName` returns undefined for the
|
|
36
|
+
// valueBackMetric names and the Figma-node fallbacks below take over.
|
|
37
|
+
function resolveTokens(modes) {
|
|
38
|
+
const titleColor = (0, _figmaVariablesResolver.getVariableByName)('metricdata/title/color', modes) ?? '#000000';
|
|
39
|
+
const valueColor = (0, _figmaVariablesResolver.getVariableByName)('metricdata/value/color', modes) ?? '#000000';
|
|
40
|
+
const captionColor = (0, _figmaVariablesResolver.getVariableByName)('metricdata/caption/color', modes) ?? '#777777';
|
|
41
|
+
const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/title/fontfamily', modes) ?? 'JioType Var';
|
|
42
|
+
const titleFontSize = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/title/fontsize', modes) ?? 12;
|
|
43
|
+
const titleFontWeight = String((0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/title/fontweight', modes) ?? 500);
|
|
44
|
+
const valueFontFamily = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/value/fontfamily', modes) ?? 'JioType Var';
|
|
45
|
+
const valueFontSize = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/value/fontsize', modes) ?? 16;
|
|
46
|
+
// Figma binds the value face to JioType Medium; there is no dedicated
|
|
47
|
+
// valueBackMetric/value/fontweight token yet, so fall back to 500.
|
|
48
|
+
const valueFontWeight = '500';
|
|
49
|
+
const captionFontFamily = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/caption/fontfamily', modes) ?? 'JioType Var';
|
|
50
|
+
const captionFontSize = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/caption/fontsize', modes) ?? 12;
|
|
51
|
+
const captionFontWeight = String((0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/caption/fontweight', modes) ?? 400);
|
|
52
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/gap', modes) ?? 4;
|
|
53
|
+
const valueWrapGap = (0, _figmaVariablesResolver.getVariableByName)('metricdata/valueWrap/gap', modes) ?? 4;
|
|
54
|
+
// Design padding is 0 — do NOT fall back to metricdata/padding (10).
|
|
55
|
+
const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/padding/horizontal', modes) ?? 0;
|
|
56
|
+
const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/padding/vertical', modes) ?? 0;
|
|
57
|
+
const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('valueBackMetric/background/color', modes) ?? '#ffffff';
|
|
58
|
+
const iconColor = (0, _figmaVariablesResolver.getVariableByName)('icon/color', modes) ?? '#ad8444';
|
|
59
|
+
const iconSize = (0, _figmaVariablesResolver.getVariableByName)('icon/size', modes) ?? ICON_SIZE;
|
|
60
|
+
return {
|
|
61
|
+
titleColor,
|
|
62
|
+
titleFontFamily,
|
|
63
|
+
titleFontSize,
|
|
64
|
+
titleFontWeight,
|
|
65
|
+
valueColor,
|
|
66
|
+
valueFontFamily,
|
|
67
|
+
valueFontSize,
|
|
68
|
+
valueFontWeight,
|
|
69
|
+
captionColor,
|
|
70
|
+
captionFontFamily,
|
|
71
|
+
captionFontSize,
|
|
72
|
+
captionFontWeight,
|
|
73
|
+
gap,
|
|
74
|
+
valueWrapGap,
|
|
75
|
+
paddingHorizontal,
|
|
76
|
+
paddingVertical,
|
|
77
|
+
backgroundColor,
|
|
78
|
+
iconColor,
|
|
79
|
+
iconSize
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
47
83
|
/**
|
|
48
84
|
* ValueBackMetric — a compact, left-aligned "value back" card.
|
|
49
85
|
*
|
|
50
86
|
* Stacks a branded header row (icon + `title`, e.g. "JioPoints"), a prominent
|
|
51
|
-
* `value`, a muted `caption`, and an optional bottom `linkLabel`
|
|
52
|
-
* `value`, `caption` and
|
|
53
|
-
* (icon + title) always shows.
|
|
87
|
+
* `value`, a muted `caption`, and an optional bottom CTA (`linkLabel` / `link`
|
|
88
|
+
* slot, e.g. "Earn"). `value`, `caption` and the CTA each render only when
|
|
89
|
+
* provided; the header (icon + title) always shows.
|
|
54
90
|
*
|
|
55
|
-
* Colours
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* matching the design.
|
|
91
|
+
* Colours resolve from the `metricdata/*` tokens; the header glyph from the
|
|
92
|
+
* `icon/*` tokens (default 18px gold); the CTA from the shared {@link Text}
|
|
93
|
+
* with `Text Appearance: Secondary` + `Text Sizes: Small` seeded so it renders
|
|
94
|
+
* purple at 12px like the design (caller `modes` win). Layout/typography
|
|
95
|
+
* follow the Figma `valueBackMetric/*` variables — not yet in the committed
|
|
96
|
+
* token snapshot, so they resolve through `getVariableByName` with Figma-node
|
|
97
|
+
* fallbacks.
|
|
63
98
|
*
|
|
64
99
|
* @example
|
|
65
100
|
* ```tsx
|
|
@@ -79,6 +114,7 @@ function ValueBackMetric({
|
|
|
79
114
|
value,
|
|
80
115
|
caption,
|
|
81
116
|
linkLabel,
|
|
117
|
+
link,
|
|
82
118
|
onLinkPress,
|
|
83
119
|
onPress,
|
|
84
120
|
disabled,
|
|
@@ -89,82 +125,81 @@ function ValueBackMetric({
|
|
|
89
125
|
captionStyle,
|
|
90
126
|
accessibilityLabel
|
|
91
127
|
}) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
//
|
|
96
|
-
|
|
97
|
-
// header icon keeps the default gold `icon/color`. Seed only the link's
|
|
98
|
-
// modes; caller-supplied modes win.
|
|
99
|
-
const linkModes = _react.default.useMemo(() => ({
|
|
128
|
+
const tokens = (0, _react.useMemo)(() => resolveTokens(modes), [modes]);
|
|
129
|
+
|
|
130
|
+
// Figma Code-Connects the CTA to Text (not Link): purple, no underline.
|
|
131
|
+
// Seed Secondary + Small so it matches the design; caller modes win.
|
|
132
|
+
const linkModes = (0, _react.useMemo)(() => ({
|
|
100
133
|
'Text Appearance': 'Secondary',
|
|
101
134
|
'Text Sizes': 'Small',
|
|
102
135
|
...modes
|
|
103
136
|
}), [modes]);
|
|
104
|
-
|
|
105
|
-
// The header glyph is token-driven: `icon/color` (gold by default, retinted
|
|
106
|
-
// via `AppearanceBrand`) and `icon/size` (18px). Passing them explicitly — as
|
|
107
|
-
// MetricData does — makes the glyph deterministic instead of relying on the
|
|
108
|
-
// shared Icon's internal token lookups.
|
|
109
|
-
const iconColor = (0, _figmaVariablesResolver.getVariableByName)('icon/color', modes) ?? '#ad8444';
|
|
110
|
-
const iconSize = (0, _figmaVariablesResolver.getVariableByName)('icon/size', modes) ?? ICON_SIZE;
|
|
111
|
-
const gap = (0, _figmaVariablesResolver.getVariableByName)('metricdata/gap', modes) ?? 4;
|
|
112
|
-
const valueWrapGap = (0, _figmaVariablesResolver.getVariableByName)('metricdata/valueWrap/gap', modes) ?? 4;
|
|
113
|
-
const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('metricdata/padding/horizontal', modes) ?? 10;
|
|
114
|
-
const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('metricdata/padding/vertical', modes) ?? 10;
|
|
115
137
|
const containerStyle = {
|
|
116
138
|
flexDirection: 'column',
|
|
117
139
|
alignItems: 'flex-start',
|
|
118
140
|
justifyContent: 'center',
|
|
119
|
-
gap,
|
|
120
|
-
paddingHorizontal,
|
|
121
|
-
paddingVertical,
|
|
141
|
+
gap: tokens.gap,
|
|
142
|
+
paddingHorizontal: tokens.paddingHorizontal,
|
|
143
|
+
paddingVertical: tokens.paddingVertical,
|
|
122
144
|
minHeight: CARD_MIN_HEIGHT,
|
|
123
|
-
backgroundColor:
|
|
145
|
+
backgroundColor: tokens.backgroundColor
|
|
124
146
|
};
|
|
125
147
|
const titleTextStyle = {
|
|
126
|
-
color: titleColor,
|
|
127
|
-
fontFamily:
|
|
128
|
-
fontSize:
|
|
129
|
-
fontWeight:
|
|
130
|
-
lineHeight:
|
|
148
|
+
color: tokens.titleColor,
|
|
149
|
+
fontFamily: tokens.titleFontFamily,
|
|
150
|
+
fontSize: tokens.titleFontSize,
|
|
151
|
+
fontWeight: tokens.titleFontWeight,
|
|
152
|
+
lineHeight: tokens.titleFontSize * TITLE_LINE_HEIGHT_RATIO
|
|
131
153
|
};
|
|
132
154
|
const valueTextStyle = {
|
|
133
|
-
color: valueColor,
|
|
134
|
-
fontFamily:
|
|
135
|
-
fontSize:
|
|
136
|
-
fontWeight:
|
|
137
|
-
lineHeight:
|
|
155
|
+
color: tokens.valueColor,
|
|
156
|
+
fontFamily: tokens.valueFontFamily,
|
|
157
|
+
fontSize: tokens.valueFontSize,
|
|
158
|
+
fontWeight: tokens.valueFontWeight,
|
|
159
|
+
lineHeight: tokens.valueFontSize * VALUE_LINE_HEIGHT_RATIO
|
|
138
160
|
};
|
|
139
161
|
const captionTextStyle = {
|
|
140
|
-
color: captionColor,
|
|
141
|
-
fontFamily:
|
|
142
|
-
fontSize:
|
|
143
|
-
fontWeight:
|
|
144
|
-
lineHeight:
|
|
162
|
+
color: tokens.captionColor,
|
|
163
|
+
fontFamily: tokens.captionFontFamily,
|
|
164
|
+
fontSize: tokens.captionFontSize,
|
|
165
|
+
fontWeight: tokens.captionFontWeight,
|
|
166
|
+
lineHeight: tokens.captionFontSize * CAPTION_LINE_HEIGHT_RATIO
|
|
145
167
|
};
|
|
146
|
-
|
|
147
|
-
// Mirrors the Figma swap slot, whose preferred instances are `Icon` and
|
|
148
|
-
// `Image`. A registry name renders the token-driven `Icon` (18px, gold,
|
|
149
|
-
// flush — all from the `icon/*` tokens); a custom node (`<Icon/>`,
|
|
150
|
-
// `<Image/>`, anything) renders as-is with `modes` cascaded into it, so an
|
|
151
|
-
// Icon instance follows the icon tokens while an Image keeps its own sizing.
|
|
152
168
|
const iconNode = icon == null ? null : typeof icon === 'string' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
153
169
|
iconName: icon,
|
|
154
|
-
size: iconSize,
|
|
155
|
-
color: iconColor,
|
|
170
|
+
size: tokens.iconSize,
|
|
171
|
+
color: tokens.iconColor,
|
|
156
172
|
modes: modes,
|
|
157
173
|
style: ICON_PADDING_RESET
|
|
158
174
|
}) : (0, _reactUtils.cloneChildrenWithModes)(icon, modes);
|
|
159
175
|
const hasValue = value !== undefined && value !== null && value !== '';
|
|
160
176
|
const hasCaption = caption !== undefined && caption !== '';
|
|
177
|
+
const hasLinkSlot = link !== undefined && link !== null && link !== false;
|
|
178
|
+
const hasLinkLabel = linkLabel !== undefined && linkLabel !== '';
|
|
161
179
|
const resolvedLabel = accessibilityLabel ?? ([title, typeof value === 'string' ? value : undefined, caption, linkLabel].filter(Boolean).join(', ') || undefined);
|
|
180
|
+
|
|
181
|
+
// Seed Secondary + Small into the CTA slot too, so a bare `<Text text="Earn" />`
|
|
182
|
+
// matches the design without the consumer re-seeding. Child-level modes still win.
|
|
183
|
+
const ctaNode = hasLinkSlot ? (0, _reactUtils.cloneChildrenWithModes)(link, linkModes) : hasLinkLabel ? onLinkPress ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
184
|
+
onPress: onLinkPress,
|
|
185
|
+
accessibilityRole: "link",
|
|
186
|
+
accessibilityLabel: linkLabel,
|
|
187
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
|
|
188
|
+
text: linkLabel,
|
|
189
|
+
textAlign: "Left",
|
|
190
|
+
modes: linkModes
|
|
191
|
+
})
|
|
192
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
|
|
193
|
+
text: linkLabel,
|
|
194
|
+
textAlign: "Left",
|
|
195
|
+
modes: linkModes
|
|
196
|
+
}) : null;
|
|
162
197
|
const content = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
163
198
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
164
199
|
style: {
|
|
165
200
|
flexDirection: 'row',
|
|
166
201
|
alignItems: 'center',
|
|
167
|
-
gap: valueWrapGap
|
|
202
|
+
gap: tokens.valueWrapGap
|
|
168
203
|
},
|
|
169
204
|
children: [iconNode, title !== undefined && title !== '' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
170
205
|
style: [titleTextStyle, titleStyle],
|
|
@@ -174,7 +209,7 @@ function ValueBackMetric({
|
|
|
174
209
|
style: {
|
|
175
210
|
flexDirection: 'column',
|
|
176
211
|
alignItems: 'flex-start',
|
|
177
|
-
gap:
|
|
212
|
+
gap: TEXT_WRAP_GAP
|
|
178
213
|
},
|
|
179
214
|
children: [hasValue ? typeof value === 'string' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
180
215
|
style: [valueTextStyle, valueStyle],
|
|
@@ -183,14 +218,7 @@ function ValueBackMetric({
|
|
|
183
218
|
style: [captionTextStyle, captionStyle],
|
|
184
219
|
children: caption
|
|
185
220
|
}) : null]
|
|
186
|
-
}) : null,
|
|
187
|
-
text: linkLabel,
|
|
188
|
-
autolayout: "Hug",
|
|
189
|
-
modes: linkModes,
|
|
190
|
-
...(onLinkPress ? {
|
|
191
|
-
onPress: onLinkPress
|
|
192
|
-
} : null)
|
|
193
|
-
}) : null]
|
|
221
|
+
}) : null, ctaNode]
|
|
194
222
|
});
|
|
195
223
|
if (onPress) {
|
|
196
224
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
@@ -489,6 +489,12 @@ Object.defineProperty(exports, "InstitutionBadge", {
|
|
|
489
489
|
return _InstitutionBadge.default;
|
|
490
490
|
}
|
|
491
491
|
});
|
|
492
|
+
Object.defineProperty(exports, "JioDot", {
|
|
493
|
+
enumerable: true,
|
|
494
|
+
get: function () {
|
|
495
|
+
return _AppBar.JioDot;
|
|
496
|
+
}
|
|
497
|
+
});
|
|
492
498
|
Object.defineProperty(exports, "LazyList", {
|
|
493
499
|
enumerable: true,
|
|
494
500
|
get: function () {
|
|
@@ -1062,7 +1068,7 @@ Object.defineProperty(exports, "useToast", {
|
|
|
1062
1068
|
var _AccountCard = _interopRequireDefault(require("./AccountCard/AccountCard"));
|
|
1063
1069
|
var _ActionFooter = _interopRequireDefault(require("./ActionFooter/ActionFooter"));
|
|
1064
1070
|
var _Attached = _interopRequireDefault(require("./Attached/Attached"));
|
|
1065
|
-
var _AppBar =
|
|
1071
|
+
var _AppBar = _interopRequireWildcard(require("./AppBar/AppBar"));
|
|
1066
1072
|
var _Avatar = _interopRequireDefault(require("./Avatar/Avatar"));
|
|
1067
1073
|
var _AvatarGroup = _interopRequireDefault(require("./AvatarGroup/AvatarGroup"));
|
|
1068
1074
|
var _Badge = _interopRequireDefault(require("./Badge/Badge"));
|