jfs-components 0.1.35 → 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.
Files changed (49) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/D2C.md +82 -87
  3. package/lib/commonjs/components/Accordion/Accordion.js +16 -3
  4. package/lib/commonjs/components/AppBar/AppBar.js +118 -93
  5. package/lib/commonjs/components/CompareTable/CompareTable.js +98 -33
  6. package/lib/commonjs/components/FormField/FormField.js +9 -1
  7. package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +4 -14
  8. package/lib/commonjs/components/HelloJioInput/HelloJioInput.js +20 -4
  9. package/lib/commonjs/components/PageHero/PageHero.js +3 -0
  10. package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +50 -30
  11. package/lib/commonjs/components/ValueBackMetric/ValueBackMetric.js +117 -89
  12. package/lib/commonjs/components/index.js +7 -1
  13. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -42204
  14. package/lib/commonjs/icons/registry.js +1 -1
  15. package/lib/module/components/Accordion/Accordion.js +16 -3
  16. package/lib/module/components/AppBar/AppBar.js +116 -93
  17. package/lib/module/components/CompareTable/CompareTable.js +99 -34
  18. package/lib/module/components/FormField/FormField.js +9 -1
  19. package/lib/module/components/FullscreenModal/FullscreenModal.js +4 -14
  20. package/lib/module/components/HelloJioInput/HelloJioInput.js +20 -4
  21. package/lib/module/components/PageHero/PageHero.js +3 -0
  22. package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +50 -30
  23. package/lib/module/components/ValueBackMetric/ValueBackMetric.js +120 -93
  24. package/lib/module/components/index.js +1 -1
  25. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -42204
  26. package/lib/module/icons/registry.js +1 -1
  27. package/lib/typescript/src/components/Accordion/Accordion.d.ts +14 -1
  28. package/lib/typescript/src/components/AppBar/AppBar.d.ts +46 -14
  29. package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +29 -12
  30. package/lib/typescript/src/components/HelloJioInput/HelloJioInput.d.ts +6 -4
  31. package/lib/typescript/src/components/PageHero/PageHero.d.ts +1 -0
  32. package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +8 -1
  33. package/lib/typescript/src/components/ValueBackMetric/ValueBackMetric.d.ts +27 -16
  34. package/lib/typescript/src/components/index.d.ts +1 -1
  35. package/lib/typescript/src/icons/registry.d.ts +1 -1
  36. package/package.json +3 -1
  37. package/scripts/extract-figma-modes.js +150 -121
  38. package/src/components/Accordion/Accordion.tsx +61 -33
  39. package/src/components/AppBar/AppBar.tsx +154 -124
  40. package/src/components/CompareTable/CompareTable.tsx +138 -52
  41. package/src/components/FormField/FormField.tsx +7 -0
  42. package/src/components/FullscreenModal/FullscreenModal.tsx +5 -14
  43. package/src/components/HelloJioInput/HelloJioInput.tsx +31 -12
  44. package/src/components/PageHero/PageHero.tsx +5 -0
  45. package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +63 -30
  46. package/src/components/ValueBackMetric/ValueBackMetric.tsx +178 -104
  47. package/src/components/index.ts +6 -1
  48. package/src/design-tokens/Coin Variables-variables-full.json +1 -42204
  49. package/src/icons/registry.ts +1 -1
@@ -4,62 +4,97 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("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 _Link = _interopRequireDefault(require("../Link/Link"));
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 mirror MetricData and zero it
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` (e.g. "Earn").
52
- * `value`, `caption` and `linkLabel` each render only when provided; the header
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, gaps and padding resolve from the `metricdata/*` tokens; the header
56
- * glyph from the `icon/*` tokens (default 18px gold); the link entirely from
57
- * the `link/*` + `text/foreground` tokens via the shared {@link Link}, with
58
- * `Text Appearance: Secondary` and `Text Sizes: Small` seeded so it renders
59
- * purple at 12px like the design (caller `modes` win). The per-part font
60
- * sizes/weights come from the Figma `valueBackMetric/*` variables, which are
61
- * not yet in the committed token snapshot, so they are encoded as constants
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 titleColor = (0, _figmaVariablesResolver.getVariableByName)('metricdata/title/color', modes) ?? '#000000';
93
- const valueColor = (0, _figmaVariablesResolver.getVariableByName)('metricdata/value/color', modes) ?? '#000000';
94
- const captionColor = (0, _figmaVariablesResolver.getVariableByName)('metricdata/caption/color', modes) ?? '#777777';
95
- // The design's link is purple (`text/foreground` under `Text Appearance:
96
- // Secondary`) at 12px (`link/fontSize` under `Text Sizes: Small`), while the
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: CARD_BACKGROUND
145
+ backgroundColor: tokens.backgroundColor
124
146
  };
125
147
  const titleTextStyle = {
126
- color: titleColor,
127
- fontFamily: FONT_FAMILY,
128
- fontSize: TITLE_FONT_SIZE,
129
- fontWeight: TITLE_FONT_WEIGHT,
130
- lineHeight: TITLE_FONT_SIZE * TITLE_LINE_HEIGHT_RATIO
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: FONT_FAMILY,
135
- fontSize: VALUE_FONT_SIZE,
136
- fontWeight: VALUE_FONT_WEIGHT,
137
- lineHeight: VALUE_FONT_SIZE * VALUE_LINE_HEIGHT_RATIO
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: FONT_FAMILY,
142
- fontSize: CAPTION_FONT_SIZE,
143
- fontWeight: CAPTION_FONT_WEIGHT,
144
- lineHeight: CAPTION_FONT_SIZE * CAPTION_LINE_HEIGHT_RATIO
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: 4
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, linkLabel ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Link.default, {
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 = _interopRequireDefault(require("./AppBar/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"));