jfs-components 0.1.30 → 0.1.33
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/D2C.md +118 -0
- package/lib/commonjs/components/CategoryCard/CategoryCard.js +264 -0
- package/lib/commonjs/components/CompareTable/CompareTable.js +140 -84
- package/lib/commonjs/components/ContentSheet/ContentSheet.js +28 -5
- package/lib/commonjs/components/CounterBadge/CounterBadge.js +78 -0
- package/lib/commonjs/components/FavoriteToggle/FavoriteToggle.js +180 -0
- package/lib/commonjs/components/HelloJioInput/HelloJioInput.js +287 -0
- package/lib/commonjs/components/ValueBackMetric/ValueBackMetric.js +219 -0
- package/lib/commonjs/components/index.js +35 -0
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +40095 -1
- package/lib/commonjs/design-tokens/figma-modes.generated.js +3 -0
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/CategoryCard/CategoryCard.js +258 -0
- package/lib/module/components/CompareTable/CompareTable.js +140 -84
- package/lib/module/components/ContentSheet/ContentSheet.js +29 -6
- package/lib/module/components/CounterBadge/CounterBadge.js +73 -0
- package/lib/module/components/FavoriteToggle/FavoriteToggle.js +174 -0
- package/lib/module/components/HelloJioInput/HelloJioInput.js +281 -0
- package/lib/module/components/ValueBackMetric/ValueBackMetric.js +214 -0
- package/lib/module/components/index.js +6 -1
- package/lib/module/design-tokens/Coin Variables-variables-full.json +40095 -1
- package/lib/module/design-tokens/figma-modes.generated.js +3 -0
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/CategoryCard/CategoryCard.d.ts +72 -0
- package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +16 -1
- package/lib/typescript/src/components/ContentSheet/ContentSheet.d.ts +7 -1
- package/lib/typescript/src/components/CounterBadge/CounterBadge.d.ts +19 -0
- package/lib/typescript/src/components/FavoriteToggle/FavoriteToggle.d.ts +66 -0
- package/lib/typescript/src/components/HelloJioInput/HelloJioInput.d.ts +111 -0
- package/lib/typescript/src/components/ValueBackMetric/ValueBackMetric.d.ts +86 -0
- package/lib/typescript/src/components/index.d.ts +5 -0
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +7 -1
- package/scripts/extract-figma-modes.js +359 -0
- package/src/components/CategoryCard/CategoryCard.tsx +404 -0
- package/src/components/CompareTable/CompareTable.tsx +201 -101
- package/src/components/ContentSheet/ContentSheet.tsx +40 -11
- package/src/components/CounterBadge/CounterBadge.tsx +95 -0
- package/src/components/FavoriteToggle/FavoriteToggle.tsx +243 -0
- package/src/components/HelloJioInput/HelloJioInput.tsx +513 -0
- package/src/components/ValueBackMetric/ValueBackMetric.tsx +298 -0
- package/src/components/index.ts +5 -0
- package/src/design-tokens/Coin Variables-variables-full.json +40095 -1
- package/src/design-tokens/figma-modes.generated.ts +3 -0
- package/src/icons/registry.ts +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { View, Text, Pressable } from 'react-native';
|
|
5
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
|
|
7
|
+
import Icon from '../Icon/Icon';
|
|
8
|
+
import Link from '../Link/Link';
|
|
9
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
10
|
+
const TITLE_LINE_HEIGHT_RATIO = 1.2;
|
|
11
|
+
const VALUE_LINE_HEIGHT_RATIO = 1.2;
|
|
12
|
+
const CAPTION_LINE_HEIGHT_RATIO = 1.5;
|
|
13
|
+
|
|
14
|
+
// The Figma node binds the header-icon size and the per-part font sizes/weights
|
|
15
|
+
// to `valueBackMetric/*` variables, but those tokens are NOT in the committed
|
|
16
|
+
// variables snapshot (`npm run tokens -- find valueBackMetric` → no matches).
|
|
17
|
+
// They also intentionally differ from the `metricdata/*` typography defaults
|
|
18
|
+
// (e.g. `metricdata/value` resolves to 20px/700, whereas this component's value
|
|
19
|
+
// is 16px/500). So the sizes/weights below are encoded as literal constants
|
|
20
|
+
// matching the Figma design exactly. Colours, gaps and padding DO exist as real
|
|
21
|
+
// `metricdata/*` tokens (and match the design), so those resolve through
|
|
22
|
+
// `getVariableByName` and stay themeable.
|
|
23
|
+
const TITLE_FONT_SIZE = 12;
|
|
24
|
+
const TITLE_FONT_WEIGHT = '500';
|
|
25
|
+
const VALUE_FONT_SIZE = 16;
|
|
26
|
+
const VALUE_FONT_WEIGHT = '500';
|
|
27
|
+
const CAPTION_FONT_SIZE = 12;
|
|
28
|
+
const CAPTION_FONT_WEIGHT = '400';
|
|
29
|
+
const FONT_FAMILY = 'JioType Var';
|
|
30
|
+
const CARD_BACKGROUND = '#ffffff';
|
|
31
|
+
const CARD_MIN_HEIGHT = 82;
|
|
32
|
+
const ICON_SIZE = 18;
|
|
33
|
+
// Figma renders the header glyph flush (all `icon/padding/*` tokens are 0); the
|
|
34
|
+
// shared Icon pulls padding from those tokens, so mirror MetricData and zero it
|
|
35
|
+
// explicitly to keep the icon flush against the title.
|
|
36
|
+
const ICON_PADDING_RESET = {
|
|
37
|
+
paddingLeft: 0,
|
|
38
|
+
paddingRight: 0,
|
|
39
|
+
paddingTop: 0,
|
|
40
|
+
paddingBottom: 0
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* ValueBackMetric — a compact, left-aligned "value back" card.
|
|
44
|
+
*
|
|
45
|
+
* Stacks a branded header row (icon + `title`, e.g. "JioPoints"), a prominent
|
|
46
|
+
* `value`, a muted `caption`, and an optional bottom `linkLabel` (e.g. "Earn").
|
|
47
|
+
* `value`, `caption` and `linkLabel` each render only when provided; the header
|
|
48
|
+
* (icon + title) always shows.
|
|
49
|
+
*
|
|
50
|
+
* Colours, gaps and padding resolve from the `metricdata/*` tokens; the header
|
|
51
|
+
* glyph from the `icon/*` tokens (default 18px gold); the link entirely from
|
|
52
|
+
* the `link/*` + `text/foreground` tokens via the shared {@link Link}, with
|
|
53
|
+
* `Text Appearance: Secondary` and `Text Sizes: Small` seeded so it renders
|
|
54
|
+
* purple at 12px like the design (caller `modes` win). The per-part font
|
|
55
|
+
* sizes/weights come from the Figma `valueBackMetric/*` variables, which are
|
|
56
|
+
* not yet in the committed token snapshot, so they are encoded as constants
|
|
57
|
+
* matching the design.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <ValueBackMetric
|
|
62
|
+
* title="JioPoints"
|
|
63
|
+
* value="Value"
|
|
64
|
+
* caption="Earn 10 point with UPI"
|
|
65
|
+
* linkLabel="Earn"
|
|
66
|
+
* onPress={() => navigation.navigate('ValueBack')}
|
|
67
|
+
* onLinkPress={() => navigation.navigate('EarnPoints')}
|
|
68
|
+
* />
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
function ValueBackMetric({
|
|
72
|
+
icon = 'ic_rupee_coin',
|
|
73
|
+
title = 'JioPoints',
|
|
74
|
+
value,
|
|
75
|
+
caption,
|
|
76
|
+
linkLabel,
|
|
77
|
+
onLinkPress,
|
|
78
|
+
onPress,
|
|
79
|
+
disabled,
|
|
80
|
+
modes = EMPTY_MODES,
|
|
81
|
+
style,
|
|
82
|
+
titleStyle,
|
|
83
|
+
valueStyle,
|
|
84
|
+
captionStyle,
|
|
85
|
+
accessibilityLabel
|
|
86
|
+
}) {
|
|
87
|
+
const titleColor = getVariableByName('metricdata/title/color', modes) ?? '#000000';
|
|
88
|
+
const valueColor = getVariableByName('metricdata/value/color', modes) ?? '#000000';
|
|
89
|
+
const captionColor = getVariableByName('metricdata/caption/color', modes) ?? '#777777';
|
|
90
|
+
// The design's link is purple (`text/foreground` under `Text Appearance:
|
|
91
|
+
// Secondary`) at 12px (`link/fontSize` under `Text Sizes: Small`), while the
|
|
92
|
+
// header icon keeps the default gold `icon/color`. Seed only the link's
|
|
93
|
+
// modes; caller-supplied modes win.
|
|
94
|
+
const linkModes = React.useMemo(() => ({
|
|
95
|
+
'Text Appearance': 'Secondary',
|
|
96
|
+
'Text Sizes': 'Small',
|
|
97
|
+
...modes
|
|
98
|
+
}), [modes]);
|
|
99
|
+
|
|
100
|
+
// The header glyph is token-driven: `icon/color` (gold by default, retinted
|
|
101
|
+
// via `AppearanceBrand`) and `icon/size` (18px). Passing them explicitly — as
|
|
102
|
+
// MetricData does — makes the glyph deterministic instead of relying on the
|
|
103
|
+
// shared Icon's internal token lookups.
|
|
104
|
+
const iconColor = getVariableByName('icon/color', modes) ?? '#ad8444';
|
|
105
|
+
const iconSize = getVariableByName('icon/size', modes) ?? ICON_SIZE;
|
|
106
|
+
const gap = getVariableByName('metricdata/gap', modes) ?? 4;
|
|
107
|
+
const valueWrapGap = getVariableByName('metricdata/valueWrap/gap', modes) ?? 4;
|
|
108
|
+
const paddingHorizontal = getVariableByName('metricdata/padding/horizontal', modes) ?? 10;
|
|
109
|
+
const paddingVertical = getVariableByName('metricdata/padding/vertical', modes) ?? 10;
|
|
110
|
+
const containerStyle = {
|
|
111
|
+
flexDirection: 'column',
|
|
112
|
+
alignItems: 'flex-start',
|
|
113
|
+
justifyContent: 'center',
|
|
114
|
+
gap,
|
|
115
|
+
paddingHorizontal,
|
|
116
|
+
paddingVertical,
|
|
117
|
+
minHeight: CARD_MIN_HEIGHT,
|
|
118
|
+
backgroundColor: CARD_BACKGROUND
|
|
119
|
+
};
|
|
120
|
+
const titleTextStyle = {
|
|
121
|
+
color: titleColor,
|
|
122
|
+
fontFamily: FONT_FAMILY,
|
|
123
|
+
fontSize: TITLE_FONT_SIZE,
|
|
124
|
+
fontWeight: TITLE_FONT_WEIGHT,
|
|
125
|
+
lineHeight: TITLE_FONT_SIZE * TITLE_LINE_HEIGHT_RATIO
|
|
126
|
+
};
|
|
127
|
+
const valueTextStyle = {
|
|
128
|
+
color: valueColor,
|
|
129
|
+
fontFamily: FONT_FAMILY,
|
|
130
|
+
fontSize: VALUE_FONT_SIZE,
|
|
131
|
+
fontWeight: VALUE_FONT_WEIGHT,
|
|
132
|
+
lineHeight: VALUE_FONT_SIZE * VALUE_LINE_HEIGHT_RATIO
|
|
133
|
+
};
|
|
134
|
+
const captionTextStyle = {
|
|
135
|
+
color: captionColor,
|
|
136
|
+
fontFamily: FONT_FAMILY,
|
|
137
|
+
fontSize: CAPTION_FONT_SIZE,
|
|
138
|
+
fontWeight: CAPTION_FONT_WEIGHT,
|
|
139
|
+
lineHeight: CAPTION_FONT_SIZE * CAPTION_LINE_HEIGHT_RATIO
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Mirrors the Figma swap slot, whose preferred instances are `Icon` and
|
|
143
|
+
// `Image`. A registry name renders the token-driven `Icon` (18px, gold,
|
|
144
|
+
// flush — all from the `icon/*` tokens); a custom node (`<Icon/>`,
|
|
145
|
+
// `<Image/>`, anything) renders as-is with `modes` cascaded into it, so an
|
|
146
|
+
// Icon instance follows the icon tokens while an Image keeps its own sizing.
|
|
147
|
+
const iconNode = icon == null ? null : typeof icon === 'string' ? /*#__PURE__*/_jsx(Icon, {
|
|
148
|
+
iconName: icon,
|
|
149
|
+
size: iconSize,
|
|
150
|
+
color: iconColor,
|
|
151
|
+
modes: modes,
|
|
152
|
+
style: ICON_PADDING_RESET
|
|
153
|
+
}) : cloneChildrenWithModes(icon, modes);
|
|
154
|
+
const hasValue = value !== undefined && value !== null && value !== '';
|
|
155
|
+
const hasCaption = caption !== undefined && caption !== '';
|
|
156
|
+
const resolvedLabel = accessibilityLabel ?? ([title, typeof value === 'string' ? value : undefined, caption, linkLabel].filter(Boolean).join(', ') || undefined);
|
|
157
|
+
const content = /*#__PURE__*/_jsxs(_Fragment, {
|
|
158
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
159
|
+
style: {
|
|
160
|
+
flexDirection: 'row',
|
|
161
|
+
alignItems: 'center',
|
|
162
|
+
gap: valueWrapGap
|
|
163
|
+
},
|
|
164
|
+
children: [iconNode, title !== undefined && title !== '' ? /*#__PURE__*/_jsx(Text, {
|
|
165
|
+
style: [titleTextStyle, titleStyle],
|
|
166
|
+
children: title
|
|
167
|
+
}) : null]
|
|
168
|
+
}), hasValue || hasCaption ? /*#__PURE__*/_jsxs(View, {
|
|
169
|
+
style: {
|
|
170
|
+
flexDirection: 'column',
|
|
171
|
+
alignItems: 'flex-start',
|
|
172
|
+
gap: 4
|
|
173
|
+
},
|
|
174
|
+
children: [hasValue ? typeof value === 'string' ? /*#__PURE__*/_jsx(Text, {
|
|
175
|
+
style: [valueTextStyle, valueStyle],
|
|
176
|
+
children: value
|
|
177
|
+
}) : value : null, hasCaption ? /*#__PURE__*/_jsx(Text, {
|
|
178
|
+
style: [captionTextStyle, captionStyle],
|
|
179
|
+
children: caption
|
|
180
|
+
}) : null]
|
|
181
|
+
}) : null, linkLabel ? /*#__PURE__*/_jsx(Link, {
|
|
182
|
+
text: linkLabel,
|
|
183
|
+
autolayout: "Hug",
|
|
184
|
+
modes: linkModes,
|
|
185
|
+
...(onLinkPress ? {
|
|
186
|
+
onPress: onLinkPress
|
|
187
|
+
} : null)
|
|
188
|
+
}) : null]
|
|
189
|
+
});
|
|
190
|
+
if (onPress) {
|
|
191
|
+
return /*#__PURE__*/_jsx(Pressable, {
|
|
192
|
+
style: [containerStyle, style],
|
|
193
|
+
onPress: onPress,
|
|
194
|
+
disabled: disabled,
|
|
195
|
+
accessibilityRole: "button",
|
|
196
|
+
...(resolvedLabel !== undefined ? {
|
|
197
|
+
accessibilityLabel: resolvedLabel
|
|
198
|
+
} : null),
|
|
199
|
+
accessibilityState: {
|
|
200
|
+
disabled: !!disabled
|
|
201
|
+
},
|
|
202
|
+
children: content
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return /*#__PURE__*/_jsx(View, {
|
|
206
|
+
style: [containerStyle, style],
|
|
207
|
+
accessible: true,
|
|
208
|
+
...(resolvedLabel !== undefined ? {
|
|
209
|
+
accessibilityLabel: resolvedLabel
|
|
210
|
+
} : null),
|
|
211
|
+
children: content
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
export default /*#__PURE__*/React.memo(ValueBackMetric);
|
|
@@ -24,6 +24,7 @@ export { default as CardFeedback } from './CardFeedback/CardFeedback';
|
|
|
24
24
|
export { default as CardFinancialCondition } from './CardFinancialCondition/CardFinancialCondition';
|
|
25
25
|
export { default as CardInsight } from './CardInsight/CardInsight';
|
|
26
26
|
export { default as CcCard } from './CcCard/CcCard';
|
|
27
|
+
export { default as CategoryCard } from './CategoryCard/CategoryCard';
|
|
27
28
|
export { default as Disclaimer } from './Disclaimer/Disclaimer';
|
|
28
29
|
export { default as Divider } from './Divider/Divider';
|
|
29
30
|
export { default as Drawer } from './Drawer/Drawer';
|
|
@@ -51,6 +52,7 @@ export { default as AllocationComparisonChart } from './AllocationComparisonChar
|
|
|
51
52
|
export { default as MonthlyStatusGrid, CalendarGlyph } from './MonthlyStatusGrid/MonthlyStatusGrid';
|
|
52
53
|
export { default as Gauge } from './Gauge/Gauge';
|
|
53
54
|
export { default as HeroSection } from './HeroSection/HeroSection';
|
|
55
|
+
export { default as HelloJioInput } from './HelloJioInput/HelloJioInput';
|
|
54
56
|
export { default as HoldingsCard } from './HoldingsCard/HoldingsCard';
|
|
55
57
|
export { default as HStack } from './HStack/HStack';
|
|
56
58
|
export { default as Icon } from './Icon/Icon';
|
|
@@ -157,4 +159,7 @@ export { default as TextSegment } from './TextSegment/TextSegment';
|
|
|
157
159
|
export { default as SegmentedControl } from './SegmentedControl/SegmentedControl';
|
|
158
160
|
export { default as Toggle } from './Toggle/Toggle';
|
|
159
161
|
export { default as AutoplayControl } from './AutoplayControl/AutoplayControl';
|
|
160
|
-
export { default as NumberPagination } from './NumberPagination/NumberPagination';
|
|
162
|
+
export { default as NumberPagination } from './NumberPagination/NumberPagination';
|
|
163
|
+
export { default as CounterBadge } from './CounterBadge/CounterBadge';
|
|
164
|
+
export { default as FavoriteToggle } from './FavoriteToggle/FavoriteToggle';
|
|
165
|
+
export { default as ValueBackMetric } from './ValueBackMetric/ValueBackMetric';
|