jfs-components 0.1.25 → 0.1.28

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 (81) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/lib/commonjs/components/AutoplayControl/AutoplayControl.js +66 -0
  3. package/lib/commonjs/components/Carousel/Carousel.js +112 -19
  4. package/lib/commonjs/components/ContentSheet/ContentSheet.js +39 -5
  5. package/lib/commonjs/components/FormUpload/Additem.js +168 -0
  6. package/lib/commonjs/components/FormUpload/FormUpload.js +198 -0
  7. package/lib/commonjs/components/Grid/Grid.js +206 -0
  8. package/lib/commonjs/components/NumberPagination/NumberPagination.js +144 -0
  9. package/lib/commonjs/components/ProfileCard/ProfileCard.js +208 -0
  10. package/lib/commonjs/components/UpiHandle/UpiHandle.js +23 -11
  11. package/lib/commonjs/components/index.js +42 -0
  12. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  13. package/lib/commonjs/design-tokens/figma-modes.generated.js +21 -10
  14. package/lib/commonjs/icons/components/IconBrokenimage.js +19 -0
  15. package/lib/commonjs/icons/components/IconImage.js +19 -0
  16. package/lib/commonjs/icons/components/IconMic.js +19 -0
  17. package/lib/commonjs/icons/components/IconMicoff.js +19 -0
  18. package/lib/commonjs/icons/components/IconPause.js +19 -0
  19. package/lib/commonjs/icons/components/IconPlay.js +19 -0
  20. package/lib/commonjs/icons/components/index.js +66 -0
  21. package/lib/commonjs/icons/registry.js +2 -2
  22. package/lib/module/components/AutoplayControl/AutoplayControl.js +60 -0
  23. package/lib/module/components/Carousel/Carousel.js +111 -19
  24. package/lib/module/components/ContentSheet/ContentSheet.js +41 -7
  25. package/lib/module/components/FormUpload/Additem.js +162 -0
  26. package/lib/module/components/FormUpload/FormUpload.js +192 -0
  27. package/lib/module/components/Grid/Grid.js +201 -0
  28. package/lib/module/components/NumberPagination/NumberPagination.js +138 -0
  29. package/lib/module/components/ProfileCard/ProfileCard.js +202 -0
  30. package/lib/module/components/UpiHandle/UpiHandle.js +23 -11
  31. package/lib/module/components/index.js +7 -1
  32. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  33. package/lib/module/design-tokens/figma-modes.generated.js +21 -10
  34. package/lib/module/icons/components/IconBrokenimage.js +12 -0
  35. package/lib/module/icons/components/IconImage.js +12 -0
  36. package/lib/module/icons/components/IconMic.js +12 -0
  37. package/lib/module/icons/components/IconMicoff.js +12 -0
  38. package/lib/module/icons/components/IconPause.js +12 -0
  39. package/lib/module/icons/components/IconPlay.js +12 -0
  40. package/lib/module/icons/components/index.js +6 -0
  41. package/lib/module/icons/registry.js +2 -2
  42. package/lib/typescript/src/components/AutoplayControl/AutoplayControl.d.ts +15 -0
  43. package/lib/typescript/src/components/Carousel/Carousel.d.ts +8 -1
  44. package/lib/typescript/src/components/ContentSheet/ContentSheet.d.ts +7 -1
  45. package/lib/typescript/src/components/FormUpload/Additem.d.ts +96 -0
  46. package/lib/typescript/src/components/FormUpload/FormUpload.d.ts +85 -0
  47. package/lib/typescript/src/components/Grid/Grid.d.ts +87 -0
  48. package/lib/typescript/src/components/NumberPagination/NumberPagination.d.ts +21 -0
  49. package/lib/typescript/src/components/ProfileCard/ProfileCard.d.ts +89 -0
  50. package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +7 -1
  51. package/lib/typescript/src/components/index.d.ts +34 -28
  52. package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +10 -4
  53. package/lib/typescript/src/icons/components/IconBrokenimage.d.ts +3 -0
  54. package/lib/typescript/src/icons/components/IconImage.d.ts +3 -0
  55. package/lib/typescript/src/icons/components/IconMic.d.ts +3 -0
  56. package/lib/typescript/src/icons/components/IconMicoff.d.ts +3 -0
  57. package/lib/typescript/src/icons/components/IconPause.d.ts +3 -0
  58. package/lib/typescript/src/icons/components/IconPlay.d.ts +3 -0
  59. package/lib/typescript/src/icons/components/index.d.ts +6 -0
  60. package/lib/typescript/src/icons/registry.d.ts +1 -1
  61. package/package.json +1 -1
  62. package/src/components/AutoplayControl/AutoplayControl.tsx +77 -0
  63. package/src/components/Carousel/Carousel.tsx +133 -23
  64. package/src/components/ContentSheet/ContentSheet.tsx +50 -0
  65. package/src/components/FormUpload/Additem.tsx +262 -0
  66. package/src/components/FormUpload/FormUpload.tsx +313 -0
  67. package/src/components/Grid/Grid.tsx +368 -0
  68. package/src/components/NumberPagination/NumberPagination.tsx +170 -0
  69. package/src/components/ProfileCard/ProfileCard.tsx +268 -0
  70. package/src/components/UpiHandle/UpiHandle.tsx +35 -24
  71. package/src/components/index.ts +329 -182
  72. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  73. package/src/design-tokens/figma-modes.generated.ts +21 -10
  74. package/src/icons/components/IconBrokenimage.tsx +11 -0
  75. package/src/icons/components/IconImage.tsx +11 -0
  76. package/src/icons/components/IconMic.tsx +11 -0
  77. package/src/icons/components/IconMicoff.tsx +11 -0
  78. package/src/icons/components/IconPause.tsx +11 -0
  79. package/src/icons/components/IconPlay.tsx +11 -0
  80. package/src/icons/components/index.ts +6 -0
  81. package/src/icons/registry.ts +25 -1
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+
3
+ import React, { useMemo } from 'react';
4
+ import { View } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
7
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils';
8
+ import Avatar from '../Avatar/Avatar';
9
+ import Attached from '../Attached/Attached';
10
+ import IconCapsule from '../IconCapsule/IconCapsule';
11
+ import ListItem from '../ListItem/ListItem';
12
+ import UpiHandle from '../UpiHandle/UpiHandle';
13
+ import Divider from '../Divider/Divider';
14
+
15
+ /**
16
+ * A single UPI handle pill rendered under the profile name.
17
+ */
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ // Forced modes for everything rendered inside the card — the profile card is
20
+ // an on-dark (jioPlus) surface, so child components (Avatar, UpiHandle,
21
+ // ListItem, Divider, Text, Button, …) must resolve their tokens through the
22
+ // `context 10: jioPlus` mode. Consumer modes are spread first so appearance
23
+ // modes (e.g. `Profile Card Appearance: Premium`) still cascade through.
24
+ const CARD_CONTEXT = Object.freeze({
25
+ 'context 10': 'jioPlus'
26
+ });
27
+ const DEFAULT_UPI_HANDLES = [{
28
+ label: 'username@jio',
29
+ iconName: 'ic_copy'
30
+ }, {
31
+ label: '9999999999',
32
+ iconName: 'ic_confirm'
33
+ }];
34
+ function resolveProfileCardTokens(modes) {
35
+ const backgroundColor = getVariableByName('profileCard/bg', modes) ?? '#00065a';
36
+ const gap = getVariableByName('profileCard/gap', modes) ?? 12;
37
+ const borderRadius = getVariableByName('profileCard/radius', modes) ?? 12;
38
+ const paddingHorizontal = getVariableByName('profileCard/padding/horizontal', modes) ?? 20;
39
+ const paddingVertical = getVariableByName('profileCard/padding/vertical', modes) ?? 20;
40
+ const childModes = {
41
+ ...modes,
42
+ ...CARD_CONTEXT
43
+ };
44
+
45
+ // The UPI handle pills sit in the header ListItem's support slot, whose row
46
+ // gap is the `slot/gap` token in the ListItem context.
47
+ const handlesGap = getVariableByName('slot/gap', {
48
+ ...childModes,
49
+ Context: 'ListItem'
50
+ }) ?? 2;
51
+
52
+ // The avatar badge is a white circle: the fill comes from the Attached
53
+ // slot's background token (the IconCapsule itself resolves transparent).
54
+ const badgeBackground = getVariableByName('attached/slot/background', childModes) ?? '#ffffff';
55
+ return {
56
+ containerStyle: {
57
+ backgroundColor,
58
+ borderRadius,
59
+ paddingHorizontal,
60
+ paddingVertical,
61
+ gap,
62
+ flexDirection: 'column',
63
+ alignItems: 'stretch'
64
+ },
65
+ handlesRowStyle: {
66
+ flexDirection: 'row',
67
+ flexWrap: 'wrap',
68
+ alignItems: 'center',
69
+ alignSelf: 'flex-start',
70
+ gap: handlesGap
71
+ },
72
+ badgeBackground,
73
+ childModes,
74
+ // XS capsule per the Figma spec; consumers can still override the size
75
+ // through their own modes.
76
+ badgeModes: {
77
+ 'Icon Capsule Size': 'XS',
78
+ ...modes,
79
+ ...CARD_CONTEXT
80
+ }
81
+ };
82
+ }
83
+
84
+ /**
85
+ * ProfileCard — Figma node 6914:38498 ("Profile Card").
86
+ *
87
+ * A dark, rounded profile summary card composed from the shared primitives:
88
+ *
89
+ * - **Header** — a {@link ListItem} whose leading slot is an {@link Attached}
90
+ * monogram {@link Avatar} with a small {@link IconCapsule} badge at its
91
+ * bottom-right, the user's name as the title, and a row of
92
+ * {@link UpiHandle} pills in the support slot.
93
+ * - **Divider** — separates the header from the body.
94
+ * - **Body slot** — arbitrary children (typically `ListItem`s separated by
95
+ * `Divider`s). All profile-card context modes cascade into the slot, so
96
+ * nested components automatically resolve their on-dark token values.
97
+ *
98
+ * The card supports the `Profile Card Appearance` collection
99
+ * (`Default` | `Premium`) via the `modes` prop, which recolors the container,
100
+ * avatar, pills and divider in one go.
101
+ *
102
+ * @example
103
+ * ```tsx
104
+ * <ProfileCard
105
+ * name="Shruti Chandarshekhar Rai"
106
+ * monogram="SR"
107
+ * upiHandles={[
108
+ * { label: 'shrutirai-1@jio', iconName: 'ic_copy', onPress: copyHandle },
109
+ * { label: '9184844184', iconName: 'ic_confirm' },
110
+ * ]}
111
+ * >
112
+ * <ListItem layout="Horizontal" title="JioFinance+" navArrow={false} />
113
+ * </ProfileCard>
114
+ * ```
115
+ */
116
+ function ProfileCard({
117
+ name = 'Name',
118
+ monogram = 'MS',
119
+ avatarSource,
120
+ badgeIcon = 'ic_qr_code',
121
+ upiHandles = DEFAULT_UPI_HANDLES,
122
+ header,
123
+ children,
124
+ showDivider = true,
125
+ width = 344,
126
+ modes: propModes = EMPTY_MODES,
127
+ style,
128
+ accessibilityLabel
129
+ }) {
130
+ const {
131
+ modes: globalModes
132
+ } = useTokens();
133
+ const modes = useMemo(() => globalModes === EMPTY_MODES && propModes === EMPTY_MODES ? EMPTY_MODES : {
134
+ ...globalModes,
135
+ ...propModes
136
+ }, [globalModes, propModes]);
137
+ const tokens = useMemo(() => resolveProfileCardTokens(modes), [modes]);
138
+
139
+ // ---- Header -------------------------------------------------------------
140
+ const headerNode = useMemo(() => {
141
+ if (header) return cloneChildrenWithModes(header, tokens.childModes);
142
+ const avatar = /*#__PURE__*/_jsx(Attached, {
143
+ position: "bottom-right",
144
+ modes: tokens.childModes,
145
+ badge: badgeIcon != null ? /*#__PURE__*/_jsx(IconCapsule, {
146
+ iconName: badgeIcon,
147
+ modes: tokens.badgeModes,
148
+ style: {
149
+ backgroundColor: tokens.badgeBackground
150
+ }
151
+ }) : null,
152
+ children: /*#__PURE__*/_jsx(Avatar, {
153
+ monogram: monogram,
154
+ style: avatarSource ? 'Image' : 'Monogram',
155
+ ...(avatarSource != null ? {
156
+ imageSource: avatarSource
157
+ } : {}),
158
+ modes: tokens.childModes
159
+ })
160
+ });
161
+ const handles = upiHandles.length > 0 ? /*#__PURE__*/_jsx(View, {
162
+ style: tokens.handlesRowStyle,
163
+ children: upiHandles.map((handle, index) => /*#__PURE__*/_jsx(UpiHandle, {
164
+ label: handle.label,
165
+ ...(handle.iconName != null ? {
166
+ iconName: handle.iconName
167
+ } : {}),
168
+ showIcon: handle.showIcon ?? true,
169
+ ...(handle.onPress != null ? {
170
+ onPress: handle.onPress
171
+ } : {}),
172
+ modes: tokens.childModes
173
+ }, `${handle.label}-${index}`))
174
+ }) : null;
175
+ return /*#__PURE__*/_jsx(ListItem, {
176
+ layout: "Horizontal",
177
+ title: name,
178
+ navArrow: false,
179
+ showSupportText: handles != null,
180
+ supportSlot: handles,
181
+ leading: avatar,
182
+ modes: tokens.childModes
183
+ });
184
+ }, [header, name, monogram, avatarSource, badgeIcon, upiHandles, tokens]);
185
+
186
+ // ---- Body slot ----------------------------------------------------------
187
+ const bodyChildren = useMemo(() => children != null ? cloneChildrenWithModes(children, tokens.childModes) : null, [children, tokens.childModes]);
188
+ const hasBody = bodyChildren != null && bodyChildren.length > 0;
189
+ const containerStyle = useMemo(() => ({
190
+ ...tokens.containerStyle,
191
+ width
192
+ }), [tokens.containerStyle, width]);
193
+ return /*#__PURE__*/_jsxs(View, {
194
+ style: [containerStyle, style],
195
+ accessibilityLabel: accessibilityLabel,
196
+ children: [headerNode, hasBody && showDivider ? /*#__PURE__*/_jsx(Divider, {
197
+ direction: "horizontal",
198
+ modes: tokens.childModes
199
+ }) : null, bodyChildren]
200
+ });
201
+ }
202
+ export default /*#__PURE__*/React.memo(ProfileCard);
@@ -8,9 +8,6 @@ import { EMPTY_MODES, resolveTruncation } from '../../utils/react-utils';
8
8
  import MediaSource from '../../utils/MediaSource';
9
9
  import Icon from '../../icons/Icon';
10
10
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
11
- // Default static asset from the component folder.
12
- // Consumers can override the image via the `source` prop if needed.
13
- const DEFAULT_AVATAR_IMAGE = require('./Image.png');
14
11
  const IS_WEB = Platform.OS === 'web';
15
12
  const IS_IOS = Platform.OS === 'ios';
16
13
  const PRESS_DELAY = IS_IOS ? 130 : 0;
@@ -83,7 +80,7 @@ function resolveUpiHandleTokens(modes) {
83
80
  * @param {Object} [props.modes={}] - Modes object passed directly to `getVariableByName`.
84
81
  * @param {boolean} [props.showIcon=true] - Toggles the trailing icon visibility.
85
82
  * @param {string} [props.iconName='ic_scan_qr_code'] - Icon name from the actions set.
86
- * @param {UnifiedSource} [props.source] - Unified avatar source (URI, inline SVG XML, `require()` asset, SVG React component, or React element). Smart-detects raster vs SVG so the same prop works on iOS, Android and web.
83
+ * @param {UnifiedSource} [props.source] - Unified avatar source (URI, inline SVG XML, `require()` asset, SVG React component, or React element). Smart-detects raster vs SVG so the same prop works on iOS, Android and web. Providing a source force-sets `UPI Handle Image: True` (avatar shown); omitting it force-sets `False` (avatar hidden), overriding any `UPI Handle Image` value passed via `modes`.
87
84
  * @param {ImageSourcePropType|UnifiedSource} [props.avatarSource] - Deprecated alias for `source`; kept for back-compat.
88
85
  * @param {Function} [props.onClick] - Click/tap handler. Works as an alias for `onPress`.
89
86
  * @param {string} [props.accessibilityLabel] - Accessibility label for screen readers
@@ -118,10 +115,24 @@ function UpiHandle({
118
115
  const {
119
116
  modes: globalModes
120
117
  } = useTokens();
121
- const modes = useMemo(() => globalModes === EMPTY_MODES && propModes === EMPTY_MODES ? EMPTY_MODES : {
122
- ...globalModes,
123
- ...propModes
124
- }, [globalModes, propModes]);
118
+
119
+ // The avatar is fully driven by the presence of a `source`. It force-sets the
120
+ // Figma "UPI Handle Image" collection to `True` when a source is provided and
121
+ // `False` otherwise. This is applied last so it overrides any consumer-passed
122
+ // `UPI Handle Image` mode, keeping the avatar visibility and the token layout
123
+ // (symmetric padding in the hidden-image state) in lockstep with the source.
124
+ const hasSource = source != null || avatarSource != null;
125
+ const modes = useMemo(() => {
126
+ const base = globalModes === EMPTY_MODES && propModes === EMPTY_MODES ? EMPTY_MODES : {
127
+ ...globalModes,
128
+ ...propModes
129
+ };
130
+ return {
131
+ ...base,
132
+ 'UPI Handle Image': hasSource ? 'True' : 'False'
133
+ };
134
+ }, [globalModes, propModes, hasSource]);
135
+ const showImageResolved = hasSource;
125
136
  const tokens = useMemo(() => resolveUpiHandleTokens(modes), [modes]);
126
137
 
127
138
  // Focus is a sustained visible state (web-only). Setter is gated so it
@@ -155,11 +166,12 @@ function UpiHandle({
155
166
 
156
167
  // `source` wins; `avatarSource` is the legacy fallback. Both are accepted
157
168
  // as a UnifiedSource (string / number / {uri} / component / element), and
158
- // the legacy `ImageSourcePropType` shapes naturally fit that union too.
159
- const resolvedAvatarSource = source ?? avatarSource ?? DEFAULT_AVATAR_IMAGE;
169
+ // the legacy `ImageSourcePropType` shapes naturally fit that union too. This
170
+ // is only read when `showImageResolved` is true, which requires a source.
171
+ const resolvedAvatarSource = source ?? avatarSource;
160
172
  const avatarSize = tokens.avatarStyle.width ?? 23;
161
173
  const innerContent = /*#__PURE__*/_jsxs(_Fragment, {
162
- children: [/*#__PURE__*/_jsx(View, {
174
+ children: [showImageResolved && /*#__PURE__*/_jsx(View, {
163
175
  style: tokens.avatarStyle,
164
176
  children: /*#__PURE__*/_jsx(MediaSource, {
165
177
  source: resolvedAvatarSource,
@@ -37,6 +37,9 @@ export { default as FullscreenModal } from './FullscreenModal/FullscreenModal';
37
37
  export { default as Form } from './Form/Form';
38
38
  export { useFormContext } from './Form/Form';
39
39
  export { default as FormField } from './FormField/FormField';
40
+ export { default as Grid } from './Grid/Grid';
41
+ export { default as FormUpload } from './FormUpload/FormUpload';
42
+ export { default as Additem } from './FormUpload/Additem';
40
43
  export { default as ContentSheet } from './ContentSheet/ContentSheet';
41
44
  export { default as CircularProgressBar } from './CircularProgressBar/CircularProgressBar';
42
45
  export { default as CircularProgressBarDoted } from './CircularProgressBarDoted/CircularProgressBarDoted';
@@ -136,6 +139,7 @@ export { default as CompareTable } from './CompareTable/CompareTable';
136
139
  export { default as Table, TableHeader, TableHeaderCell, TableBody, TableRow, TableCell } from './Table/Table';
137
140
  export { default as PoweredByLabel } from './PoweredByLabel/PoweredByLabel';
138
141
  export { default as ProductLabel } from './ProductLabel/ProductLabel';
142
+ export { default as ProfileCard } from './ProfileCard/ProfileCard';
139
143
  export { default as ProductMerchandisingCard } from './ProductMerchandisingCard/ProductMerchandisingCard';
140
144
  export { default as ProductOverview } from './ProductOverview/ProductOverview';
141
145
  export { default as ProjectionMarker } from './ProjectionMarker/ProjectionMarker';
@@ -151,4 +155,6 @@ export { default as TestimonialsCard } from './TestimonialsCard/TestimonialsCard
151
155
  export { default as Text } from './Text/Text';
152
156
  export { default as TextSegment } from './TextSegment/TextSegment';
153
157
  export { default as SegmentedControl } from './SegmentedControl/SegmentedControl';
154
- export { default as Toggle } from './Toggle/Toggle';
158
+ export { default as Toggle } from './Toggle/Toggle';
159
+ export { default as AutoplayControl } from './AutoplayControl/AutoplayControl';
160
+ export { default as NumberPagination } from './NumberPagination/NumberPagination';