@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
159 lines (158 loc) • 6.54 kB
JavaScript
"use client";
import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
import React, { Fragment, useMemo } from 'react';
import classnames from 'classnames';
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";
const propNames = ['direction', 'wrap', 'wrapChildrenInSpace', 'justify', 'align', 'divider', 'spacing', '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 handleDeprecatedProps({
spacing,
gap,
rowGap,
...rest
}) {
return {
...rest,
rowGap: rowGap === true ? undefined : rowGap,
gap: spacing !== null && spacing !== void 0 ? spacing : gap
};
}
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
} = handleDeprecatedProps(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.size;
});
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 React.createElement(React.Fragment, {
key: `element-${i}`
}, React.createElement(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 && React.createElement(Hr, {
top: spaceAboveLine,
space: 0,
className: "dnb-flex-container__hr"
}));
}
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 = classnames('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 React.createElement(Space, _extends({
element: element,
className: cn,
"data-media-key": mediaKey,
style: hasSizeProp ? {
'--sizeCount': sizeCount,
...style
} : style
}, rest), content);
}
function wrapChildren(props, children) {
return React.Children.toArray(children).map(child => {
if (React.isValidElement(child) && child.type['_supportsSpacingProps'] === 'children') {
return React.cloneElement(child, child.props, React.createElement(FlexContainer, props, child.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;
}
FlexContainer._supportsSpacingProps = true;
export default FlexContainer;
//# sourceMappingURL=Container.js.map