jfs-components 0.0.57 → 0.0.59
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.
- package/lib/commonjs/components/ActionFooter/ActionFooter.js +20 -14
- package/lib/commonjs/components/Button/Button.js +1 -1
- package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +11 -8
- package/lib/commonjs/components/Drawer/Drawer.js +1 -1
- package/lib/commonjs/components/ListGroup/ListGroup.js +1 -1
- package/lib/commonjs/components/Section/Section.js +71 -8
- package/lib/commonjs/components/Tabs/Tabs.js +6 -3
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/ActionFooter/ActionFooter.js +21 -15
- package/lib/module/components/Button/Button.js +1 -1
- package/lib/module/components/ButtonGroup/ButtonGroup.js +11 -8
- package/lib/module/components/Drawer/Drawer.js +1 -1
- package/lib/module/components/ListGroup/ListGroup.js +1 -1
- package/lib/module/components/Section/Section.js +73 -9
- package/lib/module/components/Tabs/Tabs.js +6 -3
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +4 -10
- package/lib/typescript/src/components/ButtonGroup/ButtonGroup.d.ts +3 -1
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/ActionFooter/ActionFooter.tsx +20 -14
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/ButtonGroup/ButtonGroup.tsx +17 -11
- package/src/components/Drawer/Drawer.tsx +1 -1
- package/src/components/ListGroup/ListGroup.tsx +1 -1
- package/src/components/Section/Section.tsx +90 -8
- package/src/components/Tabs/Tabs.tsx +2 -2
- 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"
|
|
35
|
-
* <Button label="Pay"
|
|
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
|
-
|
|
100
|
-
const
|
|
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:
|
|
113
|
+
children: enhancedChildren
|
|
108
114
|
})
|
|
109
115
|
});
|
|
110
116
|
}
|
|
@@ -63,7 +63,7 @@ function Button({
|
|
|
63
63
|
const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('button/lineHeight', modes) || 19;
|
|
64
64
|
const fontSize = (0, _figmaVariablesResolver.getVariableByName)('button/fontSize', modes) || 16;
|
|
65
65
|
const textColor = (0, _figmaVariablesResolver.getVariableByName)('button/foreground', modes) || '#0f0d0a';
|
|
66
|
-
const iconColor =
|
|
66
|
+
const iconColor = textColor;
|
|
67
67
|
const iconSize = (0, _figmaVariablesResolver.getVariableByName)('button/icon/size', modes) ?? 18;
|
|
68
68
|
const [isHovered, setIsHovered] = (0, _react.useState)(false);
|
|
69
69
|
const [isPressed, setIsPressed] = (0, _react.useState)(false);
|
|
@@ -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
|
-
* <
|
|
27
|
+
* <Button label="Pay" />
|
|
25
28
|
* </ButtonGroup>
|
|
26
29
|
* ```
|
|
27
30
|
*/
|
|
@@ -31,7 +34,7 @@ function ButtonGroup({
|
|
|
31
34
|
style
|
|
32
35
|
}) {
|
|
33
36
|
// Resolve design tokens
|
|
34
|
-
const gap = (0, _figmaVariablesResolver.getVariableByName)('buttonGroup/
|
|
37
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('buttonGroup/gap', modes) ?? 12;
|
|
35
38
|
const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('buttonGroup/padding/horizontal', modes) ?? 0;
|
|
36
39
|
const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('buttonGroup/padding/vertical', modes) ?? 0;
|
|
37
40
|
|
|
@@ -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;
|
|
@@ -229,7 +229,7 @@ function Drawer({
|
|
|
229
229
|
|
|
230
230
|
// Design Tokens
|
|
231
231
|
const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('drawer/background', modes) || '#f5f5f5';
|
|
232
|
-
const radius = (0, _figmaVariablesResolver.getVariableByName)('drawer/radius', modes) || 12;
|
|
232
|
+
const radius = (0, _figmaVariablesResolver.getVariableByName)('drawer/radius/top', modes) || 12;
|
|
233
233
|
|
|
234
234
|
// Handle
|
|
235
235
|
const handleColor = (0, _figmaVariablesResolver.getVariableByName)('drawer/handlebar/background', modes) || '#e0e0e3';
|
|
@@ -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)(
|
|
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:
|
|
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)(
|
|
269
|
-
|
|
270
|
-
|
|
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;
|