jfs-components 0.0.84 → 0.0.86

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 (51) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/lib/commonjs/components/AllocationComparisonChart/AllocationComparisonChart.js +299 -0
  3. package/lib/commonjs/components/AppBar/AppBar.js +36 -22
  4. package/lib/commonjs/components/AreaLineChart/AreaLineChart.js +866 -0
  5. package/lib/commonjs/components/AreaLineChart/chartMath.js +252 -0
  6. package/lib/commonjs/components/Attached/Attached.js +34 -4
  7. package/lib/commonjs/components/BubbleChart/BubbleChart.js +191 -0
  8. package/lib/commonjs/components/BubbleChart/bubblePacking.js +378 -0
  9. package/lib/commonjs/components/ClusterBubble/ClusterBubble.js +272 -0
  10. package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +52 -89
  11. package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +7 -1
  12. package/lib/commonjs/components/index.js +34 -0
  13. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  14. package/lib/commonjs/icons/registry.js +1 -1
  15. package/lib/module/components/AllocationComparisonChart/AllocationComparisonChart.js +293 -0
  16. package/lib/module/components/AppBar/AppBar.js +36 -22
  17. package/lib/module/components/AreaLineChart/AreaLineChart.js +859 -0
  18. package/lib/module/components/AreaLineChart/chartMath.js +242 -0
  19. package/lib/module/components/Attached/Attached.js +34 -4
  20. package/lib/module/components/BubbleChart/BubbleChart.js +185 -0
  21. package/lib/module/components/BubbleChart/bubblePacking.js +370 -0
  22. package/lib/module/components/ClusterBubble/ClusterBubble.js +267 -0
  23. package/lib/module/components/FullscreenModal/FullscreenModal.js +53 -90
  24. package/lib/module/components/MetricLegendItem/MetricLegendItem.js +7 -1
  25. package/lib/module/components/index.js +4 -0
  26. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  27. package/lib/module/icons/registry.js +1 -1
  28. package/lib/typescript/src/components/AllocationComparisonChart/AllocationComparisonChart.d.ts +118 -0
  29. package/lib/typescript/src/components/AreaLineChart/AreaLineChart.d.ts +212 -0
  30. package/lib/typescript/src/components/AreaLineChart/chartMath.d.ts +90 -0
  31. package/lib/typescript/src/components/BubbleChart/BubbleChart.d.ts +81 -0
  32. package/lib/typescript/src/components/BubbleChart/bubblePacking.d.ts +83 -0
  33. package/lib/typescript/src/components/ClusterBubble/ClusterBubble.d.ts +76 -0
  34. package/lib/typescript/src/components/FullscreenModal/FullscreenModal.d.ts +21 -25
  35. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +7 -1
  36. package/lib/typescript/src/components/index.d.ts +4 -0
  37. package/lib/typescript/src/icons/registry.d.ts +1 -1
  38. package/package.json +1 -1
  39. package/src/components/AllocationComparisonChart/AllocationComparisonChart.tsx +450 -0
  40. package/src/components/AppBar/AppBar.tsx +37 -24
  41. package/src/components/AreaLineChart/AreaLineChart.tsx +1161 -0
  42. package/src/components/AreaLineChart/chartMath.ts +265 -0
  43. package/src/components/Attached/Attached.tsx +36 -5
  44. package/src/components/BubbleChart/BubbleChart.tsx +319 -0
  45. package/src/components/BubbleChart/bubblePacking.ts +397 -0
  46. package/src/components/ClusterBubble/ClusterBubble.tsx +359 -0
  47. package/src/components/FullscreenModal/FullscreenModal.tsx +61 -119
  48. package/src/components/MetricLegendItem/MetricLegendItem.tsx +20 -6
  49. package/src/components/index.ts +4 -0
  50. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  51. package/src/icons/registry.ts +1 -1
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
11
10
  var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
12
11
  var _reactUtils = require("../../utils/react-utils");
@@ -34,22 +33,11 @@ const FULLSCREEN_MODAL_FORCED_MODES = Object.freeze({
34
33
  context5: 'Fullscreen Modal'
35
34
  });
36
35
 
37
- // Reanimated-driven ScrollView so the parallax handler runs on the UI thread.
38
- // Module scope so the wrapped component identity is stable across renders.
39
- const AnimatedScrollView = _reactNativeReanimated.default.createAnimatedComponent(_reactNative.ScrollView);
40
-
41
- // Parallax tuning. The hero collapses by HEIGHT only as the user scrolls up —
42
- // its full width is preserved and the media keeps a fixed aspect ratio (it is
43
- // cropped, never scaled or squished, like a `cover` background). When no
44
- // explicit `heroMinHeight` is given, the hero collapses to this fraction of
45
- // its resting height.
46
- const HERO_MIN_HEIGHT_RATIO = 0.45;
47
-
48
36
  // ---------------------------------------------------------------------------
49
37
  // Hero text — the eyebrow / headline / supporting / price block. Built inline
50
38
  // (rather than reusing <PageHero>) so we can render BOTH a supporting
51
39
  // paragraph AND a price line with the exact PageHero token gaps, and overlay
52
- // it on the parallax media without PageHero's media/button scaffolding.
40
+ // it on the hero media without PageHero's media/button scaffolding.
53
41
  // ---------------------------------------------------------------------------
54
42
 
55
43
  function HeroText({
@@ -134,8 +122,9 @@ function HeroText({
134
122
  }
135
123
 
136
124
  /**
137
- * FullscreenModal — a full-screen takeover surface with a parallax media hero,
138
- * a scrollable body, a floating close button, and a sticky `ActionFooter`.
125
+ * FullscreenModal — a full-screen takeover surface with a full-bleed media
126
+ * hero, a scrollable body, a floating close button, and a sticky
127
+ * `ActionFooter`.
139
128
  *
140
129
  * The component always themes itself with `context5: 'Fullscreen Modal'`
141
130
  * (non-overridable) so every nested component (Section, ListItem, Button,
@@ -143,14 +132,12 @@ function HeroText({
143
132
  * That mode is cascaded into `children`, the footer, and the hero text via
144
133
  * `cloneChildrenWithModes` / the merged `modes` object.
145
134
  *
146
- * ### Parallax
147
- * As the user scrolls up, the hero collapses by **height only** (from
148
- * `heroHeight` to `heroMinHeight`) its **full width is always preserved**.
149
- * The `heroMedia` is pinned to the top at a fixed size and `cover`-cropped by
150
- * the collapsing clip, so it keeps a perfect aspect ratio the whole time
151
- * (never scaled or squished). Because it collapses slower than the content
152
- * scrolls, the media lags behind for the parallax depth cue. Disable with
153
- * `parallax={false}`.
135
+ * ### Hero
136
+ * The `heroMedia` is rendered full modal width inside the scroll body and
137
+ * takes its height from its own aspect ratio. The hero text (eyebrow /
138
+ * headline / supporting / price) is overlaid on top, anchored to the bottom.
139
+ * The whole hero scrolls together with the rest of the content — there is no
140
+ * parallax effect.
154
141
  *
155
142
  * @component
156
143
  * @example
@@ -160,7 +147,7 @@ function HeroText({
160
147
  * headline="Get more from your money."
161
148
  * supportingText="JioFinance+ is your upgraded financial experience…"
162
149
  * priceText="₹999/year · ₹0 until 2027"
163
- * heroMedia={<LottiePlayer source={hero} size={{ width: 360, height: 420 }} />}
150
+ * heroMedia={<Image imageSource={hero} ratio={3 / 4} />}
164
151
  * primaryActionLabel="Upgrade for free"
165
152
  * disclaimer="By upgrading, we'll check your eligibility with Experian."
166
153
  * onPrimaryAction={() => upgrade()}
@@ -178,8 +165,6 @@ function FullscreenModal({
178
165
  priceText = '₹999/year · ₹0 until 2027',
179
166
  heroMedia,
180
167
  heroHeight = 420,
181
- heroMinHeight,
182
- parallax = true,
183
168
  showClose = true,
184
169
  onClose,
185
170
  closeAccessibilityLabel = 'Close',
@@ -206,49 +191,13 @@ function FullscreenModal({
206
191
  ...FULLSCREEN_MODAL_FORCED_MODES
207
192
  }), [globalModes, propModes]);
208
193
  const rootGap = Number((0, _figmaVariablesResolver.getVariableByName)('fullScreenModal/gap', modes)) || 16;
209
- const minHeight = heroMinHeight ?? Math.round(heroHeight * HERO_MIN_HEIGHT_RATIO);
210
- const scrollY = (0, _reactNativeReanimated.useSharedValue)(0);
211
- const onScroll = (0, _reactNativeReanimated.useAnimatedScrollHandler)(event => {
212
- scrollY.value = event.contentOffset.y;
213
- });
214
-
215
- // Collapse the hero by HEIGHT only as the user scrolls up. The clip's width
216
- // never changes and the media inside is pinned full-size at the top, so the
217
- // art is cropped (cover) rather than scaled or narrowed — it keeps a perfect
218
- // aspect ratio the whole time. Pull-down (negative offset) is clamped, so the
219
- // hero never grows past its resting height.
220
- const heroAnimatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
221
- const height = (0, _reactNativeReanimated.interpolate)(scrollY.value, [0, heroHeight], [heroHeight, minHeight], _reactNativeReanimated.Extrapolation.CLAMP);
222
- return {
223
- height
224
- };
225
- });
226
194
  const processedHeroMedia = (0, _react.useMemo)(() => heroMedia ? (0, _reactUtils.cloneChildrenWithModes)(heroMedia, modes, FULLSCREEN_MODAL_FORCED_MODES) : null, [heroMedia, modes]);
227
195
  const processedChildren = (0, _react.useMemo)(() => children ? (0, _reactUtils.cloneChildrenWithModes)(children, modes, FULLSCREEN_MODAL_FORCED_MODES) : null, [children, modes]);
228
196
 
229
- // The clip is full-width and top-pinned; its height is what animates. Width
230
- // is intentionally never animated.
231
- const heroClipBaseStyle = (0, _react.useMemo)(() => ({
232
- position: 'absolute',
233
- top: 0,
234
- left: 0,
235
- right: 0,
236
- overflow: 'hidden'
237
- }), []);
238
-
239
- // The media sits at a fixed full-size box pinned to the top of the clip, so
240
- // the collapsing clip crops it from the bottom (cover) instead of resizing
241
- // it. Full width, fixed height — a perfect, constant aspect ratio.
242
- const heroMediaWrapStyle = (0, _react.useMemo)(() => ({
243
- position: 'absolute',
244
- top: 0,
245
- left: 0,
246
- right: 0,
247
- height: heroHeight,
248
- alignItems: 'stretch'
249
- }), [heroHeight]);
250
- const heroTextRegionStyle = (0, _react.useMemo)(() => ({
251
- height: heroHeight,
197
+ // No-media fallback: without hero media the text region needs an explicit
198
+ // resting height (driven by `heroHeight`) so the hero still has presence.
199
+ const heroTextFallbackStyle = (0, _react.useMemo)(() => ({
200
+ minHeight: heroHeight,
252
201
  justifyContent: 'flex-end',
253
202
  paddingHorizontal: 16,
254
203
  paddingBottom: 16
@@ -259,15 +208,28 @@ function FullscreenModal({
259
208
  paddingTop: rootGap,
260
209
  paddingBottom: 24
261
210
  }, contentContainerStyle], [backgroundColor, rootGap, contentContainerStyle]);
262
- const heroClip = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
263
- style: [heroClipBaseStyle, parallax ? heroAnimatedStyle : {
264
- height: heroHeight
265
- }],
266
- pointerEvents: "none",
267
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
268
- style: heroMediaWrapStyle,
269
- children: processedHeroMedia
270
- })
211
+ const heroTextNode = /*#__PURE__*/(0, _jsxRuntime.jsx)(HeroText, {
212
+ eyebrow: eyebrow,
213
+ headline: headline,
214
+ supportingText: supportingText,
215
+ priceText: priceText,
216
+ modes: modes
217
+ });
218
+
219
+ // The hero scrolls inline with the body (no parallax). When media is present
220
+ // it is laid out full modal width and takes its height from its own aspect
221
+ // ratio; the hero text is overlaid on top, anchored to the bottom. Without
222
+ // media the text simply renders in flow at the fallback height.
223
+ const hero = processedHeroMedia ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
224
+ style: heroMediaContainerStyle,
225
+ children: [processedHeroMedia, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
226
+ style: heroTextOverlayStyle,
227
+ pointerEvents: "box-none",
228
+ children: heroTextNode
229
+ })]
230
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
231
+ style: heroTextFallbackStyle,
232
+ children: heroTextNode
271
233
  });
272
234
 
273
235
  // Footer: a fully custom node, or the default Button + Disclaimer column.
@@ -296,26 +258,15 @@ function FullscreenModal({
296
258
  backgroundColor
297
259
  }, style],
298
260
  testID: testID,
299
- children: [processedHeroMedia ? heroClip : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(AnimatedScrollView, {
261
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
300
262
  style: scrollViewStyle,
301
263
  contentContainerStyle: scrollContentStyle,
302
- showsVerticalScrollIndicator: false,
303
- onScroll: onScroll,
304
- scrollEventThrottle: 16
264
+ showsVerticalScrollIndicator: false
305
265
  // Tap an input in the body and it focuses on the FIRST tap, even when
306
266
  // the keyboard is already open (default 'never' eats that tap).
307
267
  ,
308
268
  keyboardShouldPersistTaps: "handled",
309
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
310
- style: heroTextRegionStyle,
311
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(HeroText, {
312
- eyebrow: eyebrow,
313
- headline: headline,
314
- supportingText: supportingText,
315
- priceText: priceText,
316
- modes: modes
317
- })
318
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
269
+ children: [hero, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
319
270
  style: bodyStyle,
320
271
  children: processedChildren
321
272
  })]
@@ -354,4 +305,16 @@ const closeButtonStyle = {
354
305
  top: 12,
355
306
  right: 12
356
307
  };
308
+ // Full-width hero wrapper; height comes from the media's own aspect ratio.
309
+ const heroMediaContainerStyle = {
310
+ width: '100%',
311
+ position: 'relative'
312
+ };
313
+ // Hero text overlaid on the media, anchored to the bottom edge.
314
+ const heroTextOverlayStyle = {
315
+ ..._reactNative.StyleSheet.absoluteFillObject,
316
+ justifyContent: 'flex-end',
317
+ paddingHorizontal: 16,
318
+ paddingBottom: 16
319
+ };
357
320
  var _default = exports.default = FullscreenModal;
@@ -22,6 +22,7 @@ function MetricLegendItem({
22
22
  label = 'Current (4 months)',
23
23
  value,
24
24
  indicatorColor,
25
+ indicatorShape = 'dot',
25
26
  modes = _reactUtils.EMPTY_MODES,
26
27
  style,
27
28
  indicatorStyle,
@@ -54,7 +55,12 @@ function MetricLegendItem({
54
55
  }, style],
55
56
  accessibilityRole: "text",
56
57
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
57
- style: [{
58
+ style: [indicatorShape === 'line' ? {
59
+ width: indicatorSize * 2,
60
+ height: Math.max(2, Math.round(indicatorSize / 4)),
61
+ borderRadius: indicatorRadius,
62
+ backgroundColor: indicatorBg
63
+ } : {
58
64
  width: indicatorSize,
59
65
  height: indicatorSize,
60
66
  borderRadius: indicatorRadius,
@@ -33,6 +33,12 @@ Object.defineProperty(exports, "ActionTile", {
33
33
  return _ActionTile.default;
34
34
  }
35
35
  });
36
+ Object.defineProperty(exports, "AllocationComparisonChart", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _AllocationComparisonChart.default;
40
+ }
41
+ });
36
42
  Object.defineProperty(exports, "AmountInput", {
37
43
  enumerable: true,
38
44
  get: function () {
@@ -45,6 +51,12 @@ Object.defineProperty(exports, "AppBar", {
45
51
  return _AppBar.default;
46
52
  }
47
53
  });
54
+ Object.defineProperty(exports, "AreaLineChart", {
55
+ enumerable: true,
56
+ get: function () {
57
+ return _AreaLineChart.default;
58
+ }
59
+ });
48
60
  Object.defineProperty(exports, "Attached", {
49
61
  enumerable: true,
50
62
  get: function () {
@@ -93,6 +105,12 @@ Object.defineProperty(exports, "BrandChip", {
93
105
  return _BrandChip.default;
94
106
  }
95
107
  });
108
+ Object.defineProperty(exports, "BubbleChart", {
109
+ enumerable: true,
110
+ get: function () {
111
+ return _BubbleChart.default;
112
+ }
113
+ });
96
114
  Object.defineProperty(exports, "Button", {
97
115
  enumerable: true,
98
116
  get: function () {
@@ -213,6 +231,12 @@ Object.defineProperty(exports, "CircularRating", {
213
231
  return _CircularRating.default;
214
232
  }
215
233
  });
234
+ Object.defineProperty(exports, "ClusterBubble", {
235
+ enumerable: true,
236
+ get: function () {
237
+ return _ClusterBubble.default;
238
+ }
239
+ });
216
240
  Object.defineProperty(exports, "CoverageBarComparison", {
217
241
  enumerable: true,
218
242
  get: function () {
@@ -801,6 +825,12 @@ Object.defineProperty(exports, "closeToast", {
801
825
  return _useToast.closeToast;
802
826
  }
803
827
  });
828
+ Object.defineProperty(exports, "useChart", {
829
+ enumerable: true,
830
+ get: function () {
831
+ return _AreaLineChart.useChart;
832
+ }
833
+ });
804
834
  Object.defineProperty(exports, "useFormContext", {
805
835
  enumerable: true,
806
836
  get: function () {
@@ -857,6 +887,7 @@ var _CircularProgressBarDoted = _interopRequireDefault(require("./CircularProgre
857
887
  var _CircularRating = _interopRequireDefault(require("./CircularRating/CircularRating"));
858
888
  var _CoverageRing = _interopRequireDefault(require("./CoverageRing/CoverageRing"));
859
889
  var _CoverageBarComparison = _interopRequireDefault(require("./CoverageBarComparison/CoverageBarComparison"));
890
+ var _AllocationComparisonChart = _interopRequireDefault(require("./AllocationComparisonChart/AllocationComparisonChart"));
860
891
  var _MonthlyStatusGrid = _interopRequireWildcard(require("./MonthlyStatusGrid/MonthlyStatusGrid"));
861
892
  var _Gauge = _interopRequireDefault(require("./Gauge/Gauge"));
862
893
  var _HoldingsCard = _interopRequireDefault(require("./HoldingsCard/HoldingsCard"));
@@ -916,6 +947,9 @@ var _RadioButton = _interopRequireDefault(require("./RadioButton/RadioButton"));
916
947
  var _RechargeCard = _interopRequireDefault(require("./RechargeCard/RechargeCard"));
917
948
  var _SavingsGoalSummary = _interopRequireDefault(require("./SavingsGoalSummary/SavingsGoalSummary"));
918
949
  var _DonutChart = _interopRequireWildcard(require("./DonutChart/DonutChart"));
950
+ var _AreaLineChart = _interopRequireWildcard(require("./AreaLineChart/AreaLineChart"));
951
+ var _ClusterBubble = _interopRequireDefault(require("./ClusterBubble/ClusterBubble"));
952
+ var _BubbleChart = _interopRequireDefault(require("./BubbleChart/BubbleChart"));
919
953
  var _DonutChartSummary = _interopRequireDefault(require("./DonutChartSummary/DonutChartSummary"));
920
954
  var _RangeTrack = _interopRequireDefault(require("./RangeTrack/RangeTrack"));
921
955
  var _SegmentedTrack = _interopRequireWildcard(require("./SegmentedTrack/SegmentedTrack"));