jfs-components 0.1.17 → 0.1.19

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 (48) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/lib/commonjs/components/AvatarGroup/AvatarGroup.js +41 -20
  3. package/lib/commonjs/components/Card/Card.js +29 -12
  4. package/lib/commonjs/components/CardFeedback/CardFeedback.js +16 -2
  5. package/lib/commonjs/components/CardInsight/CardInsight.js +34 -13
  6. package/lib/commonjs/components/CardProviderInfo/CardProviderInfo.js +23 -3
  7. package/lib/commonjs/components/DebitCard/DebitCard.js +23 -3
  8. package/lib/commonjs/components/MediaCard/MediaCard.js +24 -7
  9. package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +64 -60
  10. package/lib/commonjs/components/RechargeCard/RechargeCard.js +34 -13
  11. package/lib/commonjs/components/TestimonialsCard/TestimonialsCard.js +23 -5
  12. package/lib/commonjs/icons/registry.js +1 -1
  13. package/lib/commonjs/utils/GlassFill/GlassFill.js +69 -73
  14. package/lib/module/components/AvatarGroup/AvatarGroup.js +43 -21
  15. package/lib/module/components/Card/Card.js +31 -14
  16. package/lib/module/components/CardFeedback/CardFeedback.js +17 -3
  17. package/lib/module/components/CardInsight/CardInsight.js +36 -15
  18. package/lib/module/components/CardProviderInfo/CardProviderInfo.js +25 -5
  19. package/lib/module/components/DebitCard/DebitCard.js +25 -5
  20. package/lib/module/components/MediaCard/MediaCard.js +26 -9
  21. package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +66 -62
  22. package/lib/module/components/RechargeCard/RechargeCard.js +36 -15
  23. package/lib/module/components/TestimonialsCard/TestimonialsCard.js +25 -7
  24. package/lib/module/icons/registry.js +1 -1
  25. package/lib/module/utils/GlassFill/GlassFill.js +69 -72
  26. package/lib/typescript/src/components/Card/Card.d.ts +10 -1
  27. package/lib/typescript/src/components/CardFeedback/CardFeedback.d.ts +10 -1
  28. package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +10 -1
  29. package/lib/typescript/src/components/CardProviderInfo/CardProviderInfo.d.ts +10 -1
  30. package/lib/typescript/src/components/DebitCard/DebitCard.d.ts +10 -1
  31. package/lib/typescript/src/components/MediaCard/MediaCard.d.ts +10 -1
  32. package/lib/typescript/src/components/RechargeCard/RechargeCard.d.ts +10 -1
  33. package/lib/typescript/src/components/TestimonialsCard/TestimonialsCard.d.ts +8 -1
  34. package/lib/typescript/src/icons/registry.d.ts +1 -1
  35. package/lib/typescript/src/utils/GlassFill/GlassFill.d.ts +11 -4
  36. package/package.json +1 -2
  37. package/src/components/AvatarGroup/AvatarGroup.tsx +44 -18
  38. package/src/components/Card/Card.tsx +46 -15
  39. package/src/components/CardFeedback/CardFeedback.tsx +29 -4
  40. package/src/components/CardInsight/CardInsight.tsx +48 -17
  41. package/src/components/CardProviderInfo/CardProviderInfo.tsx +36 -3
  42. package/src/components/DebitCard/DebitCard.tsx +36 -3
  43. package/src/components/MediaCard/MediaCard.tsx +40 -9
  44. package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +76 -47
  45. package/src/components/RechargeCard/RechargeCard.tsx +48 -13
  46. package/src/components/TestimonialsCard/TestimonialsCard.tsx +37 -6
  47. package/src/icons/registry.ts +1 -1
  48. package/src/utils/GlassFill/GlassFill.tsx +59 -56
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
 
3
3
  import React, { createContext, useContext } from 'react';
4
- import { View, Text, StyleSheet } from 'react-native';
4
+ import { View, Text, Pressable, StyleSheet } from 'react-native';
5
5
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
6
  import Image from '../Image/Image';
7
7
  import GlassFill from '../../utils/GlassFill/GlassFill';
8
8
  import { EMPTY_MODES } from '../../utils/react-utils';
9
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const MediaCardContext = /*#__PURE__*/createContext({});
11
11
  /**
12
12
  * MediaCard component implementation from Figma node 1241:4140.
@@ -32,7 +32,10 @@ export function MediaCard({
32
32
  media,
33
33
  children,
34
34
  modes = EMPTY_MODES,
35
- style
35
+ style,
36
+ onPress,
37
+ disabled,
38
+ accessibilityLabel
36
39
  }) {
37
40
  const radius = parseFloat(getVariableByName('cardMedia/radius', modes));
38
41
  const containerStyle = {
@@ -47,17 +50,31 @@ export function MediaCard({
47
50
  accessibilityElementsHidden: true,
48
51
  importantForAccessibility: "no"
49
52
  }) : null);
53
+ const content = /*#__PURE__*/_jsxs(_Fragment, {
54
+ children: [background, children != null ? /*#__PURE__*/_jsx(View, {
55
+ style: StyleSheet.absoluteFill,
56
+ pointerEvents: "box-none",
57
+ children: children
58
+ }) : null]
59
+ });
50
60
  return /*#__PURE__*/_jsx(MediaCardContext.Provider, {
51
61
  value: {
52
62
  modes
53
63
  },
54
- children: /*#__PURE__*/_jsxs(View, {
64
+ children: onPress ? /*#__PURE__*/_jsx(Pressable, {
65
+ style: [containerStyle, style],
66
+ onPress: onPress,
67
+ disabled: disabled,
68
+ accessibilityRole: "button",
69
+ accessibilityLabel: accessibilityLabel,
70
+ accessibilityState: {
71
+ disabled: !!disabled
72
+ },
73
+ children: content
74
+ }) : /*#__PURE__*/_jsx(View, {
55
75
  style: [containerStyle, style],
56
- children: [background, children != null ? /*#__PURE__*/_jsx(View, {
57
- style: StyleSheet.absoluteFill,
58
- pointerEvents: "box-none",
59
- children: children
60
- }) : null]
76
+ accessibilityLabel: accessibilityLabel,
77
+ children: content
61
78
  })
62
79
  });
63
80
  }
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
 
3
3
  import React, { useId, useMemo } from 'react';
4
- import { View, Text, Pressable, StyleSheet, Platform, Image as RNImage } from 'react-native';
5
- import MaskedView from '@react-native-masked-view/masked-view';
6
- import Svg, { Defs, LinearGradient, Stop, Rect } from 'react-native-svg';
4
+ import { View, Text, Pressable, StyleSheet } from 'react-native';
5
+ import Svg, { Defs, LinearGradient, Stop, Rect, Mask, Filter, FeGaussianBlur, Image as SvgImage } from 'react-native-svg';
7
6
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
8
7
  import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils';
9
8
  import Avatar from '../Avatar/Avatar';
@@ -65,7 +64,9 @@ function ProductMerchandisingCard({
65
64
  const rawId = useId();
66
65
  const safeId = rawId.replace(/[^a-zA-Z0-9_-]/g, '');
67
66
  const scrimId = `pmc-footer-scrim-${safeId}`;
67
+ const blurGradientId = `pmc-footer-blurgrad-${safeId}`;
68
68
  const blurMaskId = `pmc-footer-blurmask-${safeId}`;
69
+ const blurFilterId = `pmc-footer-blurfilter-${safeId}`;
69
70
  const normalizedImageSource = useMemo(() => normalizeImageSource(imageSource), [imageSource]);
70
71
  const tokens = useMemo(() => resolveTokens(modes), [modes]);
71
72
  const containerStyle = {
@@ -159,57 +160,63 @@ function ProductMerchandisingCard({
159
160
  children: [normalizedImageSource != null ? /*#__PURE__*/_jsx(View, {
160
161
  style: StyleSheet.absoluteFill,
161
162
  pointerEvents: "none",
162
- children: /*#__PURE__*/_jsx(MaskedView, {
163
- style: StyleSheet.absoluteFill,
164
- maskElement: /*#__PURE__*/_jsxs(Svg, {
165
- width: "100%",
166
- height: "100%",
167
- children: [/*#__PURE__*/_jsx(Defs, {
168
- children: /*#__PURE__*/_jsxs(LinearGradient, {
169
- id: blurMaskId,
170
- x1: "0",
171
- y1: "0",
172
- x2: "0",
173
- y2: "1",
174
- children: [/*#__PURE__*/_jsx(Stop, {
175
- offset: "0",
176
- stopColor: "#000000",
177
- stopOpacity: 0
178
- }), /*#__PURE__*/_jsx(Stop, {
179
- offset: "0.35",
180
- stopColor: "#000000",
181
- stopOpacity: 0.5
182
- }), /*#__PURE__*/_jsx(Stop, {
183
- offset: "0.7",
184
- stopColor: "#000000",
185
- stopOpacity: 0.92
186
- }), /*#__PURE__*/_jsx(Stop, {
187
- offset: "1",
188
- stopColor: "#000000",
189
- stopOpacity: 1
190
- })]
163
+ children: /*#__PURE__*/_jsxs(Svg, {
164
+ width: "100%",
165
+ height: "100%",
166
+ children: [/*#__PURE__*/_jsxs(Defs, {
167
+ children: [/*#__PURE__*/_jsx(Filter, {
168
+ id: blurFilterId,
169
+ x: "-15%",
170
+ y: "-15%",
171
+ width: "130%",
172
+ height: "130%",
173
+ children: /*#__PURE__*/_jsx(FeGaussianBlur, {
174
+ stdDeviation: tokens.imageBlurStdDeviation,
175
+ edgeMode: "duplicate"
176
+ })
177
+ }), /*#__PURE__*/_jsxs(LinearGradient, {
178
+ id: blurGradientId,
179
+ x1: "0",
180
+ y1: "0",
181
+ x2: "0",
182
+ y2: "1",
183
+ children: [/*#__PURE__*/_jsx(Stop, {
184
+ offset: "0",
185
+ stopColor: "#ffffff",
186
+ stopOpacity: 0
187
+ }), /*#__PURE__*/_jsx(Stop, {
188
+ offset: "0.35",
189
+ stopColor: "#ffffff",
190
+ stopOpacity: 0.5
191
+ }), /*#__PURE__*/_jsx(Stop, {
192
+ offset: "0.7",
193
+ stopColor: "#ffffff",
194
+ stopOpacity: 0.92
195
+ }), /*#__PURE__*/_jsx(Stop, {
196
+ offset: "1",
197
+ stopColor: "#ffffff",
198
+ stopOpacity: 1
199
+ })]
200
+ }), /*#__PURE__*/_jsx(Mask, {
201
+ id: blurMaskId,
202
+ children: /*#__PURE__*/_jsx(Rect, {
203
+ x: "0",
204
+ y: "0",
205
+ width: "100%",
206
+ height: "100%",
207
+ fill: `url(#${blurGradientId})`
191
208
  })
192
- }), /*#__PURE__*/_jsx(Rect, {
193
- x: "0",
194
- y: "0",
195
- width: "100%",
196
- height: "100%",
197
- fill: `url(#${blurMaskId})`
198
209
  })]
199
- }),
200
- children: /*#__PURE__*/_jsx(RNImage, {
201
- source: normalizedImageSource,
202
- blurRadius: tokens.imageBlurRadius,
203
- resizeMode: "cover",
204
- style: {
205
- position: 'absolute',
206
- left: 0,
207
- right: 0,
208
- bottom: 0,
209
- width: '100%',
210
- height
211
- }
212
- })
210
+ }), /*#__PURE__*/_jsx(SvgImage, {
211
+ href: normalizedImageSource,
212
+ x: "0",
213
+ y: "0",
214
+ width: "100%",
215
+ height: "100%",
216
+ preserveAspectRatio: "xMidYMid slice",
217
+ filter: `url(#${blurFilterId})`,
218
+ mask: `url(#${blurMaskId})`
219
+ })]
213
220
  })
214
221
  }) : /*#__PURE__*/_jsx(GlassFill, {
215
222
  tint: "dark",
@@ -328,19 +335,16 @@ function resolveTokens(modes) {
328
335
  const sbFamily = asStr(getVariableByName('productMerchandisingcard/specialbadge/text/fontfamily', modes), 'JioType Var');
329
336
  const sbWeight = asStr(getVariableByName('productMerchandisingcard/specialbadge/text/fontweight', modes), '500');
330
337
 
331
- // `Image.blurRadius` is interpreted differently per platform — iOS applies a
332
- // strong Gaussian while Android's IterativeBoxBlur is gentler at the same
333
- // numeric radius so we tune each platform to land on the same perceived
334
- // "minimal" frosted strength as the Figma design.
335
- const imageBlurRadius = Platform.select({
336
- ios: Math.max(6, Math.round(blurRadius * 0.5)),
337
- android: Math.max(12, Math.round(blurRadius * 0.95)),
338
- default: Math.max(8, Math.round(blurRadius * 0.6))
339
- });
338
+ // SVG `<FeGaussianBlur stdDeviation>` is resolution-independent and renders
339
+ // an identical Gaussian on iOS, Android and web so unlike the old
340
+ // `Image.blurRadius` path it needs no per-platform tuning. `stdDeviation` is
341
+ // roughly half a perceptual "blur radius", so we scale the `blur/minimal`
342
+ // token down to land on the same subtle frosted strength as the design.
343
+ const imageBlurStdDeviation = Math.max(4, Math.round(blurRadius * 0.35));
340
344
  return {
341
345
  radius,
342
346
  blurIntensity: Math.max(0, Math.min(100, Math.round(blurRadius * BLUR_INTENSITY_FACTOR))),
343
- imageBlurRadius,
347
+ imageBlurStdDeviation,
344
348
  header: {
345
349
  flexDirection: 'row',
346
350
  alignItems: 'flex-start',
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  import React from 'react';
4
- import { View, Text } from 'react-native';
4
+ import { View, Text, Pressable } from 'react-native';
5
5
  import ButtonGroup from '../ButtonGroup/ButtonGroup';
6
6
  import AvatarGroup from '../AvatarGroup/AvatarGroup';
7
7
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
8
8
  import { EMPTY_MODES } from '../../utils/react-utils';
9
9
  import MoneyValue from '../MoneyValue/MoneyValue';
10
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
11
  // Defaults applied to the inner ButtonGroup so the card matches Figma out of
12
12
  // the box. They are spread *before* the caller's `modes` so any consumer can
13
13
  // override an individual key (e.g. swap the size to "M").
@@ -36,7 +36,10 @@ export default function RechargeCard({
36
36
  subscriptionContent,
37
37
  actions,
38
38
  modes = EMPTY_MODES,
39
- style
39
+ style,
40
+ onPress,
41
+ disabled,
42
+ accessibilityLabel
40
43
  }) {
41
44
  // Container Tokens (defaults mirror Figma node 2235:937).
42
45
  const backgroundColor = getVariableByName('rechargeCard/background', modes);
@@ -85,18 +88,18 @@ export default function RechargeCard({
85
88
  // Pass modes to subscription children (e.g. AvatarGroup)
86
89
  // Now encapsulated, so we just pass children to AvatarGroup
87
90
  const hasSubscriptions = React.Children.count(subscriptionContent) > 0;
88
- return /*#__PURE__*/_jsxs(View, {
89
- style: [{
90
- backgroundColor,
91
- paddingHorizontal,
92
- paddingVertical,
93
- gap,
94
- borderRadius: radius,
95
- borderWidth: strokeWidth,
96
- borderColor: strokeColor,
97
- minWidth,
98
- alignItems: 'flex-start'
99
- }, style],
91
+ const containerStyle = {
92
+ backgroundColor,
93
+ paddingHorizontal,
94
+ paddingVertical,
95
+ gap,
96
+ borderRadius: radius,
97
+ borderWidth: strokeWidth,
98
+ borderColor: strokeColor,
99
+ minWidth,
100
+ alignItems: 'flex-start'
101
+ };
102
+ const content = /*#__PURE__*/_jsxs(_Fragment, {
100
103
  children: [/*#__PURE__*/_jsxs(View, {
101
104
  style: {
102
105
  gap: headerGap,
@@ -212,4 +215,22 @@ export default function RechargeCard({
212
215
  children: actions
213
216
  })]
214
217
  });
218
+ if (onPress) {
219
+ return /*#__PURE__*/_jsx(Pressable, {
220
+ style: [containerStyle, style],
221
+ onPress: onPress,
222
+ disabled: disabled,
223
+ accessibilityRole: "button",
224
+ accessibilityLabel: accessibilityLabel ?? title,
225
+ accessibilityState: {
226
+ disabled: !!disabled
227
+ },
228
+ children: content
229
+ });
230
+ }
231
+ return /*#__PURE__*/_jsx(View, {
232
+ style: [containerStyle, style],
233
+ accessibilityLabel: accessibilityLabel,
234
+ children: content
235
+ });
215
236
  }
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
 
3
3
  import React from 'react';
4
- import { View, Text } from 'react-native';
4
+ import { View, Text, Pressable } from 'react-native';
5
5
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
6
  import { EMPTY_MODES } from '../../utils/react-utils';
7
7
  import Avatar from '../Avatar/Avatar';
8
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
9
9
  /**
10
10
  * TestimonialsCard renders a compact, fixed-width card with a circular avatar,
11
11
  * a bold title, and a body paragraph. It is typically used inside a horizontal
@@ -28,7 +28,9 @@ function TestimonialsCard({
28
28
  modes = EMPTY_MODES,
29
29
  style,
30
30
  avatarProps,
31
- accessibilityLabel
31
+ accessibilityLabel,
32
+ onPress,
33
+ disabled
32
34
  }) {
33
35
  // Container tokens
34
36
  const background = getVariableByName('testimonialsCard/background', modes) ?? '#ffffff';
@@ -84,10 +86,7 @@ function TestimonialsCard({
84
86
  ...(avatarProps?.modes || {})
85
87
  };
86
88
  const resolvedAccessibilityLabel = accessibilityLabel ?? `Testimonial${title ? ` from ${title}` : ''}${body ? `: ${body}` : ''}`;
87
- return /*#__PURE__*/_jsxs(View, {
88
- style: [containerStyle, style],
89
- accessibilityRole: "text",
90
- accessibilityLabel: resolvedAccessibilityLabel,
89
+ const content = /*#__PURE__*/_jsxs(_Fragment, {
91
90
  children: [/*#__PURE__*/_jsx(Avatar, {
92
91
  style: "Image",
93
92
  modes: avatarModes,
@@ -107,6 +106,25 @@ function TestimonialsCard({
107
106
  })]
108
107
  })]
109
108
  });
109
+ if (onPress) {
110
+ return /*#__PURE__*/_jsx(Pressable, {
111
+ style: [containerStyle, style],
112
+ onPress: onPress,
113
+ disabled: disabled,
114
+ accessibilityRole: "button",
115
+ accessibilityLabel: resolvedAccessibilityLabel,
116
+ accessibilityState: {
117
+ disabled: !!disabled
118
+ },
119
+ children: content
120
+ });
121
+ }
122
+ return /*#__PURE__*/_jsx(View, {
123
+ style: [containerStyle, style],
124
+ accessibilityRole: "text",
125
+ accessibilityLabel: resolvedAccessibilityLabel,
126
+ children: content
127
+ });
110
128
  }
111
129
  const textContainerStyle = {
112
130
  width: '100%',