@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
87 lines (85 loc) • 3.7 kB
JavaScript
'use client';
import { useStylesheet, useViewportRange } from '@ui5/webcomponents-react-base';
import { clsx } from 'clsx';
import { forwardRef, isValidElement } from 'react';
import { GridPosition } from '../../enums/GridPosition.js';
import { flattenFragments } from '../../internal/utils.js';
import { classNames, styleData } from './Grid.module.css.js';
import { jsx as _jsx } from "react/jsx-runtime";
const INDENT_PATTERN = /^([X][L](?<LargeDesktop>[0-9]|1[0-2]))? ?([L](?<Desktop>[0-9]|1[0-2]))? ?([M](?<Tablet>[0-9]|1[0-2]))? ?([S](?<Phone>[0-9]|1[0-2]))?$/i;
const SPAN_PATTERN = /^([X][L](?<LargeDesktop>[1-9]|1[0-2]))? ?([L](?<Desktop>[1-9]|1[0-2]))? ?([M](?<Tablet>[1-9]|1[0-2]))? ?([S](?<Phone>[1-9]|1[0-2]))?$/i;
const DefaultSpanMap = new Map();
DefaultSpanMap.set('Phone', 1);
DefaultSpanMap.set('Tablet', 2);
DefaultSpanMap.set('Desktop', 4);
DefaultSpanMap.set('LargeDesktop', 4);
const DefaultIndentMap = new Map();
DefaultIndentMap.set('Phone', 0);
DefaultIndentMap.set('Tablet', 0);
DefaultIndentMap.set('Desktop', 0);
DefaultIndentMap.set('LargeDesktop', 0);
const getSpanFromString = (span, currentRange) => {
const spanConfig = SPAN_PATTERN.exec(span);
return Number(spanConfig?.groups[currentRange] ?? DefaultSpanMap.get(currentRange));
};
const getIndentFromString = (indent, currentRange) => {
const indentConfig = INDENT_PATTERN.exec(indent);
return Number(indentConfig?.groups[currentRange] ?? DefaultIndentMap.get(currentRange));
};
/**
* A layout container component used for aligning items with various sizes in a simple grid.
*
* __Note:__ The `Grid` component is only applying grid styles only on the first level of its children. If you want to define a more complex grid, we recommend implementing a standard [CSS grid layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout).
*
* __Note:__ The `Grid` currently doesn't implement the same wrapping behavior as the `sap.ui.layout.Grid`. To follow UXC guidelines use a different component.
*/
const Grid = /*#__PURE__*/forwardRef((props, ref) => {
const {
position,
children,
hSpacing = '1rem',
vSpacing = '1rem',
style,
className,
slot,
defaultIndent = 'XL0 L0 M0 S0',
defaultSpan = 'XL3 L3 M6 S12',
...rest
} = props;
useStylesheet(styleData, Grid.displayName);
const currentRange = useViewportRange();
const gridClasses = clsx(classNames.grid, GridPosition.Center === position && classNames.positionCenter, GridPosition.Right === position && classNames.positionRight, className);
return /*#__PURE__*/_jsx("div", {
ref: ref,
className: gridClasses,
style: {
rowGap: vSpacing,
columnGap: hSpacing,
...style
},
slot: slot,
...rest,
children: flattenFragments(children, Infinity).map(child => {
if (! /*#__PURE__*/isValidElement(child)) {
return null;
}
const childSpan = getSpanFromString(child.props['data-layout-span'] ?? defaultSpan, currentRange);
const childClass = classNames[`gridSpan${childSpan}`];
const childrenWithGridLayout = [/*#__PURE__*/_jsx("div", {
className: childClass,
children: child
}, child.key)];
const indentSpan = getIndentFromString(child.props['data-layout-indent'] ?? defaultIndent, currentRange);
if (indentSpan && indentSpan > 0) {
childrenWithGridLayout.unshift(/*#__PURE__*/_jsx("span", {
className: classNames[`gridSpan${indentSpan}`],
"data-component-name": "GridIndentSpacer",
"aria-hidden": "true"
}, `${child.key}-indent`));
}
return childrenWithGridLayout;
})
});
});
Grid.displayName = 'Grid';
export { Grid };