@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
163 lines (162 loc) • 6.56 kB
JavaScript
"use client";
import React, { Fragment, useMemo } from 'react';
import clsx from 'clsx';
import Space from "../space/Space.js";
import { Hr } from "../../elements/index.js";
import useMedia from "../../shared/useMedia.js";
import { getSpaceValue, isHeadingElement, renderWithSpacing } from "./utils.js";
import withComponentMarkers from "../../shared/helpers/withComponentMarkers.js";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const propNames = ['direction', 'wrap', 'wrapChildrenInSpace', 'justify', 'align', 'divider', 'gap'];
export function pickFlexContainerProps(props, defaults = {}, skip = []) {
return {
...defaults,
...Object.fromEntries(Object.entries(props !== null && props !== void 0 ? props : {}).filter(([key]) => propNames.includes(key) && !skip.includes(key)))
};
}
function FlexContainer(props) {
const {
className,
style,
children,
element = 'div',
direction = 'horizontal',
wrap = true,
wrapChildrenInSpace = true,
sizeCount = 12,
rowGap,
justify = 'flex-start',
align = 'flex-start',
alignSelf,
divider = 'space',
gap = 'small',
breakpoints,
queries,
...rest
} = props;
const spacing = useMemo(() => {
var _ref;
return (_ref = direction === 'vertical' ? rowGap : undefined) !== null && _ref !== void 0 ? _ref : gap;
}, [direction, gap, rowGap]);
const childrenArray = replaceRootFragment(wrapChildren(props, children));
const hasHeading = childrenArray.some((child, i) => {
const previousChild = childrenArray === null || childrenArray === void 0 ? void 0 : childrenArray[i - 1];
return isHeadingElement(child) || i > 0 && isHeadingElement(previousChild);
});
const hasSizeProp = !hasHeading && direction === 'horizontal' && childrenArray.some(child => {
var _child$props;
return (_child$props = child['props']) === null || _child$props === void 0 ? void 0 : _child$props.span;
});
const {
key: mediaKey
} = useMedia({
disabled: !hasSizeProp,
breakpoints,
queries
});
const content = childrenArray.map((child, i) => {
var _previousChild$type;
const isFirst = i === 0;
const isLast = i >= childrenArray.length - 1;
const previousChild = childrenArray === null || childrenArray === void 0 ? void 0 : childrenArray[i - 1];
const isHeading = hasHeading && isHeadingElement(previousChild);
const start = direction === 'horizontal' ? 'left' : 'top';
const end = direction === 'horizontal' ? 'right' : 'bottom';
const endSpacing = 0;
let startSpacing = null;
if (!isHeading && (divider === 'line' && !isFirst || divider === 'line-framed')) {
var _getSpaceValue, _getSpaceValue2;
const spaceAboveLine = (_getSpaceValue = getSpaceValue(end, previousChild)) !== null && _getSpaceValue !== void 0 ? _getSpaceValue : spacing;
startSpacing = (_getSpaceValue2 = getSpaceValue(start, child)) !== null && _getSpaceValue2 !== void 0 ? _getSpaceValue2 : spacing;
return _jsxs(React.Fragment, {
children: [_jsx(Hr, {
top: !isFirst ? spaceAboveLine : 0,
space: 0,
className: "dnb-flex-container__hr"
}), renderWithSpacing(child, {
space: {
[start]: startSpacing,
[end]: endSpacing
},
wrapInSpace: wrapChildrenInSpace
}), divider === 'line-framed' && isLast && _jsx(Hr, {
top: spaceAboveLine,
space: 0,
className: "dnb-flex-container__hr"
})]
}, `element-${i}`);
}
if (isFirst && direction !== 'horizontal') {
startSpacing = 0;
} else {
var _ref2, _getSpaceValue3;
startSpacing = (_ref2 = (_getSpaceValue3 = getSpaceValue(start, child)) !== null && _getSpaceValue3 !== void 0 ? _getSpaceValue3 : getSpaceValue(end, previousChild)) !== null && _ref2 !== void 0 ? _ref2 : spacing;
}
if (React.isValidElement(previousChild) && (previousChild === null || previousChild === void 0 || (_previousChild$type = previousChild.type) === null || _previousChild$type === void 0 ? void 0 : _previousChild$type['_supportsSpacingProps']) === false) {
startSpacing = 0;
}
const space = direction === 'horizontal' ? {
[start]: endSpacing,
[end]: startSpacing
} : {
[start]: startSpacing,
[end]: endSpacing
};
return renderWithSpacing(child, {
key: (child === null || child === void 0 ? void 0 : child['key']) || `element-${i}`,
space,
wrapInSpace: wrapChildrenInSpace
});
});
const n = 'dnb-flex-container';
const rowGapClass = useMemo(() => {
if (rowGap !== false && direction === 'horizontal') {
return `${n}--row-gap-${rowGap !== null && rowGap !== void 0 ? rowGap : 'small'}`;
}
return undefined;
}, [direction, rowGap]);
const cn = clsx('dnb-flex-container', rowGapClass, className, direction && `${n}--direction-${direction}`, justify && `${n}--justify-${justify}`, align && `${n}--align-${align}`, alignSelf && `${n}--align-self-${alignSelf}`, spacing && `${n}--spacing-${spacing}`, wrap && `${n}--wrap`, hasSizeProp && `${n}--has-size`, divider && `${n}--divider-${divider}`);
return _jsx(Space, {
element: element,
className: cn,
"data-media-key": mediaKey,
style: hasSizeProp ? {
'--sizeCount': sizeCount,
...style
} : style,
...rest,
children: content
});
}
function wrapChildren(props, children) {
return React.Children.toArray(children).map(child => {
if (React.isValidElement(child) && child.type['_supportsSpacingProps'] === 'children') {
const childElement = child;
const {
key,
...childProps
} = childElement.props || {};
return React.createElement(childElement.type, {
key,
...childProps
}, _jsx(FlexContainer, {
...props,
children: childElement.props.children
}));
}
return child;
});
}
function replaceRootFragment(children) {
const firstChild = children[0];
if (React.Children.count(children) === 1 && (firstChild === null || firstChild === void 0 ? void 0 : firstChild.type) === Fragment) {
var _firstChild$props;
return React.Children.toArray(firstChild === null || firstChild === void 0 || (_firstChild$props = firstChild.props) === null || _firstChild$props === void 0 ? void 0 : _firstChild$props.children);
}
return children;
}
withComponentMarkers(FlexContainer, {
_supportsSpacingProps: true
});
export default FlexContainer;
//# sourceMappingURL=Container.js.map