jfs-components 0.1.34 → 0.1.35
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/lib/commonjs/components/LottiePlayer/LottiePlayer.js +5 -5
- package/lib/commonjs/components/LottiePlayer/LottiePlayer.web.js +2 -2
- package/lib/commonjs/components/PageHero/PageHero.js +73 -76
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +42204 -1
- package/lib/commonjs/design-tokens/figma-modes.generated.js +52 -37
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/LottiePlayer/LottiePlayer.js +5 -5
- package/lib/module/components/LottiePlayer/LottiePlayer.web.js +2 -2
- package/lib/module/components/PageHero/PageHero.js +73 -76
- package/lib/module/design-tokens/Coin Variables-variables-full.json +42204 -1
- package/lib/module/design-tokens/figma-modes.generated.js +52 -37
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/LottiePlayer/LottiePlayer.d.ts +6 -6
- package/lib/typescript/src/components/PageHero/PageHero.d.ts +33 -25
- package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +14 -1
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/LottiePlayer/LottiePlayer.tsx +8 -8
- package/src/components/LottiePlayer/LottiePlayer.web.tsx +2 -2
- package/src/components/PageHero/PageHero.tsx +142 -106
- package/src/design-tokens/Coin Variables-variables-full.json +42204 -1
- package/src/design-tokens/figma-modes.generated.ts +52 -37
- package/src/icons/registry.ts +1 -1
|
@@ -22,8 +22,8 @@ function resolveSize(size, modes) {
|
|
|
22
22
|
height: size
|
|
23
23
|
};
|
|
24
24
|
if (size && typeof size === 'object') return size;
|
|
25
|
-
const width = Number(getVariableByName('
|
|
26
|
-
const height = Number(getVariableByName('
|
|
25
|
+
const width = Number(getVariableByName('video/width', modes)) || DEFAULT_SIZE;
|
|
26
|
+
const height = Number(getVariableByName('video/height', modes)) || DEFAULT_SIZE;
|
|
27
27
|
return {
|
|
28
28
|
width,
|
|
29
29
|
height
|
|
@@ -50,8 +50,8 @@ function resolveSize(size, modes) {
|
|
|
50
50
|
* webpack via platform extensions — same pattern as `MediaCard/GlassFill`.
|
|
51
51
|
*
|
|
52
52
|
* Token-driven sizing: when `size` is omitted, `LottiePlayer` reads
|
|
53
|
-
* `
|
|
54
|
-
* animation matches the surrounding component's `
|
|
53
|
+
* `video/width` and `video/height` from the Figma variables resolver, so the
|
|
54
|
+
* animation matches the surrounding component's `Video / Output` mode
|
|
55
55
|
* automatically. This is the same sizing contract `PageHero` and
|
|
56
56
|
* `LottieIntroBlock` use for their `media` slots.
|
|
57
57
|
*
|
|
@@ -62,7 +62,7 @@ function resolveSize(size, modes) {
|
|
|
62
62
|
*
|
|
63
63
|
* <LottiePlayer source={animation} /> // 117 × 117 (default)
|
|
64
64
|
* <LottiePlayer source={animation} size={70} /> // 70 × 70
|
|
65
|
-
* <LottiePlayer source={animation} modes={{ '
|
|
65
|
+
* <LottiePlayer source={animation} modes={{ 'Video / Output': 'S' }} /> // 20 × 20
|
|
66
66
|
* <PageHero media={<LottiePlayer source={animation} />} />
|
|
67
67
|
* ```
|
|
68
68
|
*/
|
|
@@ -13,8 +13,8 @@ function resolveSize(size, modes) {
|
|
|
13
13
|
height: size
|
|
14
14
|
};
|
|
15
15
|
if (size && typeof size === 'object') return size;
|
|
16
|
-
const width = Number(getVariableByName('
|
|
17
|
-
const height = Number(getVariableByName('
|
|
16
|
+
const width = Number(getVariableByName('video/width', modes)) || DEFAULT_SIZE;
|
|
17
|
+
const height = Number(getVariableByName('video/height', modes)) || DEFAULT_SIZE;
|
|
18
18
|
return {
|
|
19
19
|
width,
|
|
20
20
|
height
|
|
@@ -7,16 +7,24 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider';
|
|
|
7
7
|
import Button from '../Button/Button';
|
|
8
8
|
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
|
|
9
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
// Figma media frame is 117×117 ("Video / Output" L). Used when the token
|
|
11
|
+
// collection is missing from a consumer's variables JSON so the media slot
|
|
12
|
+
// never collapses to 0.
|
|
13
|
+
const MEDIA_FALLBACK = 117;
|
|
10
14
|
/**
|
|
11
15
|
* PageHero displays a centered hero block typically used at the top of a page
|
|
12
16
|
* or feature screen. It contains an optional media slot (illustration / image
|
|
13
17
|
* / Lottie / SVG / video — consumer's choice), an eyebrow line, a large
|
|
14
|
-
* headline, an optional supporting line (e.g. price
|
|
15
|
-
* optional action button.
|
|
18
|
+
* headline, an optional supporting line (e.g. price), an optional body line
|
|
19
|
+
* (e.g. timeline), and an optional action button.
|
|
16
20
|
*
|
|
17
21
|
* All visual values are resolved from Figma design tokens via
|
|
18
|
-
* `getVariableByName
|
|
19
|
-
*
|
|
22
|
+
* `getVariableByName` (Figma node 4453:2348 — "Page Hero"). Text colors react
|
|
23
|
+
* to the `Page type` (`MainPage | SubPage | JioPlus`) and `Color Mode`
|
|
24
|
+
* (`Light | Dark`) collections; type scale reacts to `PageHero Size`
|
|
25
|
+
* (`M | S`); the media box reacts to `Video / Output` (`L | M | S`). Slots
|
|
26
|
+
* cascade the active `modes` to their children through
|
|
27
|
+
* `cloneChildrenWithModes`.
|
|
20
28
|
*
|
|
21
29
|
* @component
|
|
22
30
|
* @example
|
|
@@ -27,21 +35,19 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
27
35
|
* supportingText="₹999/year · ₹0 until 2027"
|
|
28
36
|
* buttonLabel="Renew for free"
|
|
29
37
|
* onButtonPress={() => navigate('Upgrade')}
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* imageSource={require('./assets/upgrade.png')}
|
|
33
|
-
* width={117}
|
|
34
|
-
* height={117}
|
|
35
|
-
* />
|
|
36
|
-
* }
|
|
38
|
+
* modes={{ 'Page type': 'JioPlus' }}
|
|
39
|
+
* media={<LottiePlayer source={animation} />}
|
|
37
40
|
* />
|
|
38
41
|
* ```
|
|
39
42
|
*/
|
|
40
43
|
function PageHero({
|
|
41
44
|
eyebrow = 'Upgrade to JioFinance+',
|
|
45
|
+
showEyebrow = true,
|
|
42
46
|
headline = 'Resume earning cashback, extra points, and 1% gold',
|
|
43
47
|
supportingText = '₹999/year · ₹0 until 2027',
|
|
44
48
|
showSupportingText = true,
|
|
49
|
+
body,
|
|
50
|
+
showBody = true,
|
|
45
51
|
buttonLabel = 'Renew for free',
|
|
46
52
|
onButtonPress,
|
|
47
53
|
showButton = true,
|
|
@@ -59,34 +65,49 @@ function PageHero({
|
|
|
59
65
|
...propModes
|
|
60
66
|
}), [globalModes, propModes]);
|
|
61
67
|
const gap = Number(getVariableByName('PageHero/gap', modes));
|
|
62
|
-
const paddingHorizontal = Number(getVariableByName('PageHero/padding/horizontal', modes));
|
|
63
68
|
const textWrapGap = Number(getVariableByName('PageHero/textWrap/gap', modes));
|
|
64
69
|
|
|
65
|
-
// Media slot box —
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
const mediaWidth = Number(getVariableByName('
|
|
69
|
-
const mediaHeight = Number(getVariableByName('
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
// Media slot box — Figma frame 4540:7845 ("Video"), sized by the
|
|
71
|
+
// `Video / Output` collection (L=117, M=70, S=20). Falls back to 117 when
|
|
72
|
+
// the collection is absent so the slot never collapses to 0×0.
|
|
73
|
+
const mediaWidth = Number(getVariableByName('video/width', modes)) || MEDIA_FALLBACK;
|
|
74
|
+
const mediaHeight = Number(getVariableByName('video/height', modes)) || MEDIA_FALLBACK;
|
|
75
|
+
const eyebrowStyle = useMemo(() => ({
|
|
76
|
+
color: getVariableByName('PageHero/eyebrow/color', modes),
|
|
77
|
+
fontFamily: getVariableByName('PageHero/eyebrow/fontFamily', modes),
|
|
78
|
+
fontSize: Number(getVariableByName('PageHero/eyebrow/fontSize', modes)),
|
|
79
|
+
fontWeight: String(getVariableByName('PageHero/eyebrow/fontWeight', modes)),
|
|
80
|
+
lineHeight: Number(getVariableByName('PageHero/eyebrow/lineHeight', modes)),
|
|
81
|
+
textAlign: 'center'
|
|
82
|
+
}), [modes]);
|
|
83
|
+
const headlineStyle = useMemo(() => ({
|
|
84
|
+
color: getVariableByName('PageHero/headline/color', modes),
|
|
85
|
+
fontFamily: getVariableByName('PageHero/headline/fontFamily', modes),
|
|
86
|
+
fontSize: Number(getVariableByName('PageHero/headline/fontSize', modes)),
|
|
87
|
+
fontWeight: String(getVariableByName('PageHero/headline/fontWeight', modes)),
|
|
88
|
+
lineHeight: Number(getVariableByName('PageHero/headline/lineHeight', modes)),
|
|
89
|
+
textAlign: 'center',
|
|
90
|
+
width: '100%'
|
|
91
|
+
}), [modes]);
|
|
92
|
+
const supportingTextStyle = useMemo(() => ({
|
|
93
|
+
color: getVariableByName('PageHero/supportingText/color', modes),
|
|
94
|
+
fontFamily: getVariableByName('PageHero/supportingText/fontFamily', modes),
|
|
95
|
+
fontSize: Number(getVariableByName('PageHero/supportingText/fontSize', modes)),
|
|
96
|
+
fontWeight: String(getVariableByName('PageHero/supportingText/fontWeight', modes)),
|
|
97
|
+
lineHeight: Number(getVariableByName('PageHero/supportingText/lineHeight', modes)),
|
|
98
|
+
textAlign: 'center'
|
|
99
|
+
}), [modes]);
|
|
100
|
+
const bodyStyle = useMemo(() => ({
|
|
101
|
+
color: getVariableByName('PageHero/body/color', modes),
|
|
102
|
+
fontFamily: getVariableByName('PageHero/body/fontFamily', modes),
|
|
103
|
+
fontSize: Number(getVariableByName('PageHero/body/fontSize', modes)),
|
|
104
|
+
fontWeight: String(getVariableByName('PageHero/body/fontWeight', modes)),
|
|
105
|
+
lineHeight: Number(getVariableByName('PageHero/body/lineHeight', modes)),
|
|
106
|
+
textAlign: 'center'
|
|
107
|
+
}), [modes]);
|
|
86
108
|
const containerStyle = {
|
|
87
109
|
flexDirection: 'column',
|
|
88
110
|
alignItems: 'center',
|
|
89
|
-
paddingHorizontal,
|
|
90
111
|
gap,
|
|
91
112
|
width: '100%'
|
|
92
113
|
};
|
|
@@ -96,34 +117,6 @@ function PageHero({
|
|
|
96
117
|
gap: textWrapGap,
|
|
97
118
|
width: '100%'
|
|
98
119
|
};
|
|
99
|
-
const eyebrowStyle = {
|
|
100
|
-
color: eyebrowColor,
|
|
101
|
-
fontFamily: eyebrowFontFamily,
|
|
102
|
-
fontSize: eyebrowFontSize,
|
|
103
|
-
fontWeight: String(eyebrowFontWeight),
|
|
104
|
-
lineHeight: eyebrowLineHeight,
|
|
105
|
-
textAlign: 'center'
|
|
106
|
-
};
|
|
107
|
-
const headlineStyle = {
|
|
108
|
-
color: headlineColor,
|
|
109
|
-
fontFamily: headlineFontFamily,
|
|
110
|
-
fontSize: headlineFontSize,
|
|
111
|
-
fontWeight: String(headlineFontWeight),
|
|
112
|
-
lineHeight: headlineLineHeight,
|
|
113
|
-
textAlign: 'center',
|
|
114
|
-
width: '100%'
|
|
115
|
-
};
|
|
116
|
-
const supportingTextStyle = {
|
|
117
|
-
color: '#ffffff',
|
|
118
|
-
fontFamily: 'System',
|
|
119
|
-
fontSize: 12,
|
|
120
|
-
fontWeight: '500',
|
|
121
|
-
lineHeight: supportingTextLineHeight,
|
|
122
|
-
textAlign: 'center'
|
|
123
|
-
};
|
|
124
|
-
const buttonWrapStyle = {
|
|
125
|
-
width: '100%'
|
|
126
|
-
};
|
|
127
120
|
const buttonContent = useMemo(() => {
|
|
128
121
|
if (buttonSlot !== undefined && buttonSlot !== null) {
|
|
129
122
|
return cloneChildrenWithModes(buttonSlot, modes);
|
|
@@ -135,20 +128,16 @@ function PageHero({
|
|
|
135
128
|
label: buttonLabel,
|
|
136
129
|
onPress: onButtonPress,
|
|
137
130
|
modes: modes,
|
|
138
|
-
style:
|
|
131
|
+
style: FULL_WIDTH
|
|
139
132
|
});
|
|
140
|
-
// buttonWrapStyle is a literal object created above; it is intentionally
|
|
141
|
-
// omitted from deps because its identity changes on every render but its
|
|
142
|
-
// shape never does.
|
|
143
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
144
133
|
}, [buttonSlot, showButton, buttonLabel, onButtonPress, modes]);
|
|
145
134
|
|
|
146
135
|
// Sized container for the media slot. Always rendered when `media` is
|
|
147
|
-
// provided, so the slot has a predictable box (
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
// `clipsContent` so a slightly oversized illustration doesn't break
|
|
151
|
-
//
|
|
136
|
+
// provided, so the slot has a predictable box (Figma frame 4540:7845 —
|
|
137
|
+
// 117×117 at `Video / Output = L`) even if the inner element omits its own
|
|
138
|
+
// width/height. `overflow: 'hidden'` mirrors the Figma frame's
|
|
139
|
+
// `clipsContent` so a slightly oversized illustration doesn't break the
|
|
140
|
+
// centered layout.
|
|
152
141
|
const mediaContent = useMemo(() => {
|
|
153
142
|
if (media === undefined || media === null) return null;
|
|
154
143
|
return /*#__PURE__*/_jsx(View, {
|
|
@@ -162,22 +151,30 @@ function PageHero({
|
|
|
162
151
|
children: cloneChildrenWithModes(media, modes)
|
|
163
152
|
});
|
|
164
153
|
}, [media, mediaWidth, mediaHeight, modes]);
|
|
154
|
+
const hasEyebrow = showEyebrow && !!eyebrow;
|
|
155
|
+
const hasHeadline = !!headline;
|
|
165
156
|
return /*#__PURE__*/_jsxs(View, {
|
|
166
157
|
style: [containerStyle, style],
|
|
167
158
|
testID: testID,
|
|
168
|
-
children: [mediaContent, /*#__PURE__*/_jsxs(View, {
|
|
159
|
+
children: [mediaContent, hasEyebrow || hasHeadline ? /*#__PURE__*/_jsxs(View, {
|
|
169
160
|
style: textWrapStyle,
|
|
170
|
-
children: [
|
|
161
|
+
children: [hasEyebrow ? /*#__PURE__*/_jsx(Text, {
|
|
171
162
|
style: eyebrowStyle,
|
|
172
163
|
children: eyebrow
|
|
173
|
-
}) : null,
|
|
164
|
+
}) : null, hasHeadline ? /*#__PURE__*/_jsx(Text, {
|
|
174
165
|
style: headlineStyle,
|
|
175
166
|
children: headline
|
|
176
167
|
}) : null]
|
|
177
|
-
}), showSupportingText && supportingText ? /*#__PURE__*/_jsx(Text, {
|
|
168
|
+
}) : null, showSupportingText && supportingText ? /*#__PURE__*/_jsx(Text, {
|
|
178
169
|
style: supportingTextStyle,
|
|
179
170
|
children: supportingText
|
|
171
|
+
}) : null, showBody && body ? /*#__PURE__*/_jsx(Text, {
|
|
172
|
+
style: bodyStyle,
|
|
173
|
+
children: body
|
|
180
174
|
}) : null, buttonContent]
|
|
181
175
|
});
|
|
182
176
|
}
|
|
177
|
+
const FULL_WIDTH = {
|
|
178
|
+
width: '100%'
|
|
179
|
+
};
|
|
183
180
|
export default PageHero;
|