jfs-components 0.0.56 → 0.0.58

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 (26) hide show
  1. package/lib/commonjs/components/ActionFooter/ActionFooter.js +20 -14
  2. package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +10 -7
  3. package/lib/commonjs/components/ListGroup/ListGroup.js +1 -1
  4. package/lib/commonjs/components/Section/Section.js +71 -8
  5. package/lib/commonjs/components/Tabs/Tabs.js +6 -3
  6. package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +24 -20
  7. package/lib/commonjs/icons/registry.js +1 -1
  8. package/lib/module/components/ActionFooter/ActionFooter.js +21 -15
  9. package/lib/module/components/ButtonGroup/ButtonGroup.js +10 -7
  10. package/lib/module/components/ListGroup/ListGroup.js +1 -1
  11. package/lib/module/components/Section/Section.js +73 -9
  12. package/lib/module/components/Tabs/Tabs.js +6 -3
  13. package/lib/module/components/TransactionBubble/TransactionBubble.js +24 -20
  14. package/lib/module/icons/registry.js +1 -1
  15. package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +4 -10
  16. package/lib/typescript/src/components/ButtonGroup/ButtonGroup.d.ts +3 -1
  17. package/lib/typescript/src/components/TransactionBubble/TransactionBubble.d.ts +9 -6
  18. package/lib/typescript/src/icons/registry.d.ts +1 -1
  19. package/package.json +1 -1
  20. package/src/components/ActionFooter/ActionFooter.tsx +20 -14
  21. package/src/components/ButtonGroup/ButtonGroup.tsx +16 -10
  22. package/src/components/ListGroup/ListGroup.tsx +1 -1
  23. package/src/components/Section/Section.tsx +90 -8
  24. package/src/components/Tabs/Tabs.tsx +2 -2
  25. package/src/components/TransactionBubble/TransactionBubble.tsx +17 -14
  26. package/src/icons/registry.ts +1 -1
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(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
+ var _IconButton = _interopRequireDefault(require("../IconButton/IconButton"));
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
14
  /**
@@ -28,18 +29,12 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
28
29
  *
29
30
  * @example
30
31
  * ```tsx
31
- * // Basic usage - modes are automatically passed to all children
32
+ * // Basic usage - modes are automatically passed to all children.
33
+ * // Non-IconButton children (e.g., Button) are auto-stretched to fill.
32
34
  * <ActionFooter modes={modes}>
33
35
  * <IconButton iconName="ic_split" />
34
- * <Button label="Request" style={{ flex: 1 }} />
35
- * <Button label="Pay" style={{ flex: 1 }} />
36
- * </ActionFooter>
37
- *
38
- * // Children can override with their own modes (merged with parent)
39
- * <ActionFooter modes={modes}>
40
- * <IconButton iconName="ic_split" />
41
- * <Button label="Request" modes={{ Appearance: 'secondary' }} style={{ flex: 1 }} />
42
- * <Button label="Pay" modes={{ Appearance: 'primary' }} style={{ flex: 1 }} />
36
+ * <Button label="Request" />
37
+ * <Button label="Pay" />
43
38
  * </ActionFooter>
44
39
  * ```
45
40
  */
@@ -95,16 +90,27 @@ function ActionFooter({
95
90
  const webShadow = _reactNative.Platform.OS === 'web' ? {
96
91
  boxShadow: '0px -12px 24px 0px rgba(12, 13, 16, 0.12), 0px -16px 48px 0px rgba(12, 13, 16, 0.16)'
97
92
  } : {};
98
-
99
- // Pass modes prop to all slot children
100
- const childrenWithModes = (0, _reactUtils.cloneChildrenWithModes)(children, modes);
93
+ const flatChildren = (0, _reactUtils.flattenChildren)(children);
94
+ const processedChildren = (0, _reactUtils.cloneChildrenWithModes)(flatChildren, modes);
95
+ const enhancedChildren = processedChildren.map((child, index) => {
96
+ if (! /*#__PURE__*/_react.default.isValidElement(child)) return child;
97
+ const element = child;
98
+ const isIconButton = element.type === _IconButton.default;
99
+ const stretchStyle = isIconButton ? undefined : {
100
+ flex: 1
101
+ };
102
+ return /*#__PURE__*/_react.default.cloneElement(element, {
103
+ key: element.key ?? index,
104
+ style: [stretchStyle, element.props.style]
105
+ });
106
+ });
101
107
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
102
108
  style: [containerStyle, webShadow, style],
103
109
  accessibilityRole: "toolbar",
104
110
  accessibilityLabel: undefined,
105
111
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
106
112
  style: slotStyle,
107
- children: childrenWithModes
113
+ children: enhancedChildren
108
114
  })
109
115
  });
110
116
  }
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(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
+ var _IconButton = _interopRequireDefault(require("../IconButton/IconButton"));
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
14
  /**
@@ -15,13 +16,15 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
15
16
  * and handles their layout and styling/theming via design tokens.
16
17
  *
17
18
  * It passes the provided `modes` to all its immediate React Element children.
19
+ * Non-IconButton children (e.g., Button) are automatically stretched to fill
20
+ * available space. IconButton children keep their natural width.
18
21
  *
19
22
  * @component
20
23
  * @example
21
24
  * ```jsx
22
25
  * <ButtonGroup modes={{"Appearance": "light"}}>
23
26
  * <IconButton iconName="ic_qr_code" />
24
- * <IconButton iconName="ic_photo" />
27
+ * <Button label="Pay" />
25
28
  * </ButtonGroup>
26
29
  * ```
27
30
  */
@@ -46,21 +49,21 @@ function ButtonGroup({
46
49
 
47
50
  // Flatten children to handle Fragments properly
48
51
  const flatChildren = (0, _reactUtils.flattenChildren)(children);
49
-
50
- // Clone children to pass `modes` prop
51
52
  const childrenWithModes = _react.default.Children.map(flatChildren, child => {
52
53
  if (/*#__PURE__*/_react.default.isValidElement(child)) {
53
- // We safely try to pass `modes` to the child.
54
- // We merge the group modes with any modes defined on the child explicitly.
55
- // Child modes take precedence.
56
54
  const element = child;
57
55
  const childModes = element.props.modes || {};
58
56
  const mergedModes = {
59
57
  ...modes,
60
58
  ...childModes
61
59
  };
60
+ const isIconButton = element.type === _IconButton.default;
61
+ const stretchStyle = isIconButton ? undefined : {
62
+ flex: 1
63
+ };
62
64
  return /*#__PURE__*/_react.default.cloneElement(element, {
63
- modes: mergedModes
65
+ modes: mergedModes,
66
+ style: [stretchStyle, element.props.style]
64
67
  });
65
68
  }
66
69
  return child;
@@ -69,7 +69,7 @@ function ListGroup({
69
69
  borderWidth,
70
70
  borderStyle: 'solid',
71
71
  flexDirection: 'column',
72
- alignItems: 'flex-start',
72
+ alignItems: 'stretch',
73
73
  width: '100%'
74
74
  };
75
75
  const labelStyle = {
@@ -13,6 +13,69 @@ var _reactUtils = require("../../utils/react-utils");
13
13
  var _jsxRuntime = require("react/jsx-runtime");
14
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
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); }
16
+ // ---------------------------------------------------------------------------
17
+ // Shared grid layout: measures widest child, enforces uniform width,
18
+ // chunks into fixed rows of up to maxColumns, space-between per row.
19
+ // ---------------------------------------------------------------------------
20
+ const SLOT_GRID_MAX_COLUMNS = 4;
21
+ function SlotGrid({
22
+ items,
23
+ gap,
24
+ maxColumns = SLOT_GRID_MAX_COLUMNS
25
+ }) {
26
+ const [maxItemWidth, setMaxItemWidth] = (0, _react.useState)(null);
27
+ const itemWidthsRef = (0, _react.useRef)(new Map());
28
+ const totalItems = items.length;
29
+ (0, _react.useEffect)(() => {
30
+ itemWidthsRef.current.clear();
31
+ setMaxItemWidth(null);
32
+ }, [totalItems]);
33
+ const handleItemLayout = (0, _react.useCallback)((index, width) => {
34
+ itemWidthsRef.current.set(index, width);
35
+ if (itemWidthsRef.current.size >= totalItems && totalItems > 0) {
36
+ setMaxItemWidth(Math.max(...itemWidthsRef.current.values()));
37
+ }
38
+ }, [totalItems]);
39
+ const isMeasured = maxItemWidth !== null;
40
+ const columns = Math.min(maxColumns, totalItems || 1);
41
+ const rows = [];
42
+ for (let i = 0; i < items.length; i += columns) {
43
+ rows.push(items.slice(i, i + columns));
44
+ }
45
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
46
+ style: {
47
+ gap,
48
+ ...(isMeasured ? {} : {
49
+ opacity: 0
50
+ })
51
+ },
52
+ children: rows.map((row, rowIndex) => {
53
+ const spacersNeeded = row.length < columns ? columns - row.length : 0;
54
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
55
+ style: {
56
+ flexDirection: 'row',
57
+ justifyContent: 'space-between'
58
+ },
59
+ children: [row.map((child, colIndex) => {
60
+ const itemIndex = rowIndex * columns + colIndex;
61
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
62
+ onLayout: !isMeasured ? e => handleItemLayout(itemIndex, e.nativeEvent.layout.width) : undefined,
63
+ style: isMeasured ? {
64
+ width: maxItemWidth
65
+ } : undefined,
66
+ children: child
67
+ }, itemIndex);
68
+ }), isMeasured && spacersNeeded > 0 && Array.from({
69
+ length: spacersNeeded
70
+ }, (_, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
71
+ style: {
72
+ width: maxItemWidth
73
+ }
74
+ }, `spacer-${i}`))]
75
+ }, rowIndex);
76
+ })
77
+ });
78
+ }
16
79
  /**
17
80
  * Section component that mirrors the Figma "Section" component.
18
81
  *
@@ -202,9 +265,12 @@ function Section({
202
265
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
203
266
  style: headerStyle,
204
267
  children: headerContent
205
- }), slot && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
268
+ }), slot && slotDirection === 'row' && /*#__PURE__*/(0, _jsxRuntime.jsx)(SlotGrid, {
269
+ items: (0, _reactUtils.cloneChildrenWithModes)((0, _reactUtils.flattenChildren)(slot), modes),
270
+ gap: sectionGap
271
+ }), slot && slotDirection === 'column' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
206
272
  style: {
207
- flexDirection: slotDirection,
273
+ flexDirection: 'column',
208
274
  gap: slotGap
209
275
  },
210
276
  children: (0, _reactUtils.cloneChildrenWithModes)((0, _reactUtils.flattenChildren)(slot), modes)
@@ -265,12 +331,9 @@ function SectionBento({
265
331
  accessibilityLabel: undefined,
266
332
  accessibilityHint: accessibilityHint,
267
333
  ...rest,
268
- children: [processedNavSlot && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
269
- style: {
270
- flexDirection: 'row',
271
- gap
272
- },
273
- children: processedNavSlot
334
+ children: [processedNavSlot && /*#__PURE__*/(0, _jsxRuntime.jsx)(SlotGrid, {
335
+ items: processedNavSlot,
336
+ gap: gap
274
337
  }), processedUpiSlot && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
275
338
  style: {
276
339
  flexDirection: 'row',
@@ -48,8 +48,6 @@ function Tabs({
48
48
  const paddingBottom = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/bottom', modes) ?? 0;
49
49
  const paddingLeft = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/left', modes) ?? 0;
50
50
  const paddingRight = (0, _figmaVariablesResolver.getVariableByName)('tabs/padding/right', modes) ?? 0;
51
-
52
- // Forward modes to all TabItem children
53
51
  const enhancedChildren = _react.default.Children.map(children, child => {
54
52
  if (/*#__PURE__*/_react.default.isValidElement(child) && child.type === _TabItem.default) {
55
53
  const childElement = child;
@@ -57,7 +55,12 @@ function Tabs({
57
55
  modes: {
58
56
  ...modes,
59
57
  ...(childElement.props.modes ?? {})
60
- }
58
+ },
59
+ ...(scrollable ? {} : {
60
+ style: [{
61
+ flex: 1
62
+ }, childElement.props.style]
63
+ })
61
64
  });
62
65
  }
63
66
  return child;
@@ -17,16 +17,19 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
17
17
  /**
18
18
  * TransactionBubble — Figma node 1517:1155.
19
19
  *
20
- * Layout (single horizontal row inside a rounded bordered pill):
20
+ * Layout (vertical stack inside a rounded bordered pill):
21
21
  *
22
22
  * ┌──────────────────────────────────────────────┐
23
- * │ Description Status · Date
24
- * │ ₹56
23
+ * │ Description
24
+ * │ ₹56
25
+ * │ [slot / children content] │
26
+ * │ ⚠ Expired · 20 Mar 2025 › │
25
27
  * └──────────────────────────────────────────────┘
26
28
  *
27
- * Left column: description text + MoneyValue, stacked vertically with `transactionBubble/gap`.
28
- * Right column: TransactionStatus + NavArrow, stacked vertically with `transactionBubble/statusWrap/gap`,
29
- * right-aligned.
29
+ * moneyValueWrap: description + MoneyValue, vertical with `transactionBubble/wrap/gap`.
30
+ * slotWrap: children (optional), rendered between moneyValueWrap and statusWrap.
31
+ * statusWrap: TransactionStatus + NavArrow, horizontal row with `transactionBubble/statusWrap/gap`.
32
+ * Container gap between sections: `transactionBubble/gap`.
30
33
  */
31
34
  function TransactionBubble({
32
35
  description = 'Payment to Uber India',
@@ -54,12 +57,13 @@ function TransactionBubble({
54
57
  const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('transactionBubble/background', resolvedModes) || '#ffffff';
55
58
  const borderColor = (0, _figmaVariablesResolver.getVariableByName)('transactionBubble/border/color', resolvedModes) || '#e5e5e5';
56
59
  const bubbleGap = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/gap', resolvedModes)) || 8;
57
- const wrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/wrap/gap', resolvedModes)) || 8;
60
+ const moneyValueWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/wrap/gap', resolvedModes)) || 8;
58
61
  const descriptionColor = (0, _figmaVariablesResolver.getVariableByName)('transactionBubble/description/color', resolvedModes) || '#24262b';
59
62
  const descriptionFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/description/fontSize', resolvedModes)) || 14;
60
63
  const descriptionLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/description/lineHeight', resolvedModes)) || 17;
61
64
  const descriptionFontFamily = (0, _figmaVariablesResolver.getVariableByName)('transactionBubble/description/fontFamily', resolvedModes) || 'JioType Var';
62
65
  const statusWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/statusWrap/gap', resolvedModes)) || 4;
66
+ const statusWrapHeight = Number((0, _figmaVariablesResolver.getVariableByName)('transactionBubble/statusWrap/height', resolvedModes)) || 18;
63
67
  const containerStyle = {
64
68
  padding,
65
69
  borderRadius: radius,
@@ -83,11 +87,13 @@ function TransactionBubble({
83
87
  accessibilityLabel: defaultAccessibilityLabel,
84
88
  webAccessibilityProps
85
89
  });
86
- const rightColumn = processedStatusSlot || /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
90
+ const statusRow = processedStatusSlot || /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
87
91
  style: {
88
- alignItems: 'flex-end',
89
- justifyContent: 'flex-end',
90
- gap: statusWrapGap
92
+ flexDirection: 'row',
93
+ alignItems: 'center',
94
+ justifyContent: 'space-between',
95
+ gap: statusWrapGap,
96
+ height: statusWrapHeight
91
97
  },
92
98
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_TransactionStatus.default, {
93
99
  status: status,
@@ -100,13 +106,11 @@ function TransactionBubble({
100
106
  });
101
107
  const mainContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
102
108
  style: {
103
- flexDirection: 'row',
104
- gap: wrapGap
109
+ gap: bubbleGap
105
110
  },
106
111
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
107
112
  style: {
108
- flex: 1,
109
- gap: bubbleGap
113
+ gap: moneyValueWrapGap
110
114
  },
111
115
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
112
116
  style: descriptionStyle,
@@ -117,10 +121,10 @@ function TransactionBubble({
117
121
  currency: currency,
118
122
  modes: resolvedModes
119
123
  })]
120
- }), rightColumn]
124
+ }), processedChildren, statusRow]
121
125
  });
122
126
  if (onPress) {
123
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
127
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
124
128
  onPress: onPress,
125
129
  style: ({
126
130
  pressed
@@ -132,14 +136,14 @@ function TransactionBubble({
132
136
  accessibilityHint: accessibilityHint,
133
137
  ...webProps,
134
138
  ...rest,
135
- children: [mainContent, processedChildren]
139
+ children: mainContent
136
140
  });
137
141
  }
138
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
142
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
139
143
  style: [containerStyle, style],
140
144
  accessibilityLabel: defaultAccessibilityLabel,
141
145
  accessibilityHint: accessibilityHint,
142
- children: [mainContent, processedChildren]
146
+ children: mainContent
143
147
  });
144
148
  }
145
149
  var _default = exports.default = TransactionBubble;