@spaced-out/ui-design-system
Version:
Sense UI components library
111 lines (101 loc) • 2.59 kB
Flow
// @flow strict
import * as React from 'react';
import {classify} from '../../utils/classify';
import css from './Grid.module.css';
export type RowProps = {
className?: string,
children?: React.Node,
span?: number,
offset?: number,
gridType?: 'small' | 'medium' | 'large' | 'autoFill' | 'autoFit',
repeatTracks?: string,
};
const GRID_SYSTEM_MAP = {
small: 24,
medium: 12,
large: 6,
autoFill: 'auto-fill',
autoFit: 'auto-fit',
};
export const Row = ({
className,
children,
span = 1,
gridType = 'medium',
repeatTracks = '1fr',
}: RowProps): React.Node => {
const gridRepeatCount = GRID_SYSTEM_MAP[gridType];
let columnSpanCount = 0;
let lastChildColCount = 0;
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
const {span = 1, offset = 0} = child.props;
if (span < 1) {
console.error(`span can not be less than one`);
return;
}
if (offset < 0) {
console.error(`offset can not be negative`);
return;
}
lastChildColCount = columnSpanCount;
columnSpanCount = lastChildColCount + offset + span;
let gridColumnStart = 0,
gridColumnEnd = 0;
if (gridType === 'autoFill' || gridType === 'autoFit') {
gridColumnStart = 'auto';
return React.cloneElement(child, {
gridColumnStart,
gridColumnEnd: `span ${span}`,
});
} else if (
typeof gridRepeatCount === 'number' &&
columnSpanCount <= gridRepeatCount
) {
gridColumnStart = lastChildColCount + offset + 1;
return React.cloneElement(child, {
gridColumnStart,
gridColumnEnd: `span ${span}`,
});
} else {
console.error(`number of column exceed ${gridRepeatCount}`);
}
}
});
return (
<div
data-testid="Grid"
className={classify(css.gridRow, className)}
style={{
'--grid-repeat-count': gridRepeatCount,
'--repeat-tracks': repeatTracks,
}}
>
{childrenWithProps}
</div>
);
};
export type ColProps = {
className?: string,
children?: React.Node,
span?: number,
offset?: number,
gridColumnStart?: number,
gridColumnEnd?: number,
};
export const Col = ({
className,
children,
gridColumnStart,
gridColumnEnd,
}: ColProps): React.Node => (
<div
className={classify(css.gridColumn, className)}
style={{
'--grid-column-start': gridColumnStart,
'--grid-column-end': gridColumnEnd,
}}
>
{children}
</div>
);