@indoqa/style-system
Version:
A style system for React with Typescript typed theme support and several base components.
113 lines • 4.66 kB
JavaScript
import * as React from 'react';
import { FelaComponent } from 'react-fela';
import { sortBreakpoints } from '../../theming/sortBreakpoints';
import { createPaddingCSSProps, createStylingCSSProps } from '../base';
import { addUnitIfNeeded, createResponsiveStyles, mergeThemedStyles } from '../utils';
import { GRID_SIZE } from './Col';
import { GridContext } from './GridContext';
import { testGridContext } from './testGridContext';
const calcWidthValue = (size, spacing) => {
const spacingWithUnit = addUnitIfNeeded(spacing);
const availableSpace = `(100% - ${spacingWithUnit} * ${GRID_SIZE - 1})`;
const coveredSpacing = `${spacingWithUnit} * ${size - 1}`;
return `calc(${availableSpace} / ${GRID_SIZE} * ${size} + ${coveredSpacing} - 0.01px)`;
};
const getEnhancedColStyles = (child, breakpointName, size, willBreakAfter, needsMarginTop, spacing) => {
const style = {
width: calcWidthValue(size, spacing),
marginTop: needsMarginTop ? spacing : 0,
marginRight: willBreakAfter ? '0px' : spacing,
};
return breakpointName === null ? style : { [breakpointName]: style };
};
const toSizeArray = (size) => {
if (Array.isArray(size)) {
return size;
}
return [size];
};
const initializeArray = (length) => {
const a = [];
for (let i = 0; i < length; i++) {
a.push(0);
}
return a;
};
const mergeStyles = (style1, style2) => {
if (style2 === null) {
return style1;
}
return [style1, style2];
};
const validateSizes = (sizes, breakpointCount, child) => {
if (sizes > breakpointCount + 1) {
if (process.env.NODE_ENV !== 'production') {
console.warn('There are more Col sizes than breakpoints.', child);
}
return false;
}
return true;
};
const rewriteCols = (breakpoints, children, spacing) => {
const currentRowSize = initializeArray(breakpoints.length + 1);
const rowsCount = initializeArray(breakpoints.length + 1);
return React.Children.map(children, (child) => {
const currentChild = child;
const sizes = toSizeArray(currentChild.props.size);
if (!validateSizes(sizes.length, breakpoints.length, child)) {
return;
}
const style = currentChild.props.style;
const enhancedColStyles = {};
for (let i = 0; i < sizes.length; i++) {
const currentBreakpoint = i === 0 ? null : breakpoints[i - 1].name;
currentRowSize[i] += sizes[i];
const willOverflow = currentRowSize[i] > GRID_SIZE;
if (willOverflow) {
currentRowSize[i] = sizes[i];
}
const completelyFillsRow = currentRowSize[i] === GRID_SIZE;
const needsMarginTop = willOverflow || rowsCount[i] > 0;
if (completelyFillsRow || willOverflow) {
rowsCount[i]++;
}
const enhancedColStyle = getEnhancedColStyles(currentChild, currentBreakpoint, sizes[i], completelyFillsRow, needsMarginTop, spacing);
Object.assign(enhancedColStyles, enhancedColStyle);
}
return React.cloneElement((currentChild), { style: mergeStyles(enhancedColStyles, style) });
});
};
function createBaseStyles(props, theme) {
return {
...createPaddingCSSProps(props, theme),
...createStylingCSSProps(props, theme),
};
}
class RowContainer extends React.Component {
render() {
const rowStyle = ({ style, spacing, ...otherProps }) => ({
...createResponsiveStyles(otherProps, createBaseStyles),
boxSizing: 'border-box',
display: 'flex',
flexWrap: 'wrap',
width: '100%',
marginTop: spacing,
'&:first-child': {
marginTop: 0,
},
});
const { style, testId, innerRef, ...otherProps } = this.props;
const styles = mergeThemedStyles(rowStyle, style);
const renderCols = ({ className, theme }) => (React.createElement("div", { className: className, ref: innerRef, "data-testid": testId }, rewriteCols(sortBreakpoints(theme.breakpoints), this.props.children, this.props.spacing)));
return (React.createElement(FelaComponent, { style: styles, ...otherProps }, renderCols));
}
}
export class ColRow extends React.Component {
render() {
return (React.createElement(GridContext.Consumer, null, ({ spacing }) => {
const child = (React.createElement(RowContainer, { spacing: spacing, ...this.props }, this.props.children));
return testGridContext(spacing, child);
}));
}
}
//# sourceMappingURL=ColRow.js.map