@vitus-labs/coolgrid
Version:
Ultra flexible and extensible grid system inspired by Bootstrap grid, based on styled-components
292 lines (272 loc) • 8.81 kB
JavaScript
import { context, makeItResponsive, value, extendCss, ALIGN_CONTENT_MAP_X } from '@vitus-labs/unistyle';
export { Provider } from '@vitus-labs/unistyle';
import React, { createContext, useContext, useMemo } from 'react';
import { omit, pick, get, config } from '@vitus-labs/core';
const PKG_NAME = '@vitus-labs/coolgrid';
/* eslint-disable import/prefer-default-export */
const CONTEXT_KEYS = [
// 'breakpoints',
// 'rootSize',
'columns',
'size',
'gap',
'padding',
'gutter',
'colCss',
'colComponent',
'rowCss',
'rowComponent',
'contentAlignX',
];
const isNumber = (value) => Number.isFinite(value);
const hasValue = (value) => isNumber(value) && value > 0;
const isVisible = (value) => (isNumber(value) && value !== 0) || value === undefined;
const omitCtxKeys = (props) => omit(props, CONTEXT_KEYS);
var ContainerContext = createContext({});
const pickThemeProps = (props, keywords) => pick(props, keywords);
const getGridContext = (props = {}, theme = {}) => ({
columns: (get(props, 'columns') ||
get(theme, 'grid.columns') ||
get(theme, 'coolgrid.columns')),
containerWidth: (get(props, 'width') ||
get(theme, 'grid.container') ||
get(theme, 'coolgrid.container')),
});
const useGridContext = (props) => {
const { theme } = useContext(context);
const ctxProps = pickThemeProps(props, CONTEXT_KEYS);
const gridContext = getGridContext(ctxProps, theme);
return { ...gridContext, ...ctxProps };
};
const { styled: styled$2, css: css$2, component: component$2 } = config;
const styles$2 = ({ theme: t, css, rootSize }) => css `
max-width: ${value(t.width, rootSize)};
${extendCss(t.extraStyles)};
`;
var Styled$2 = styled$2(component$2) `
${false};
display: flex;
width: 100%;
flex-direction: column;
margin-right: auto;
margin-left: auto;
${makeItResponsive({
key: '$coolgrid',
styles: styles$2,
css: css$2,
normalize: true,
})};
`;
const Component$2 = ({ children, component, css, width, ...props }) => {
const { containerWidth = {}, ...ctx } = useGridContext(props);
const context = useMemo(() => ctx, [ctx]);
let finalWidth = containerWidth;
if (width) {
// @ts-ignore
finalWidth = typeof width === 'function' ? width(containerWidth) : width;
}
const finalProps = useMemo(() => ({
$coolgrid: {
width: finalWidth,
extraStyles: css,
},
}), [finalWidth, css]);
const getDevProps = () => {
const result = {};
if (process.env.NODE_ENV !== 'production') {
result['data-coolgrid'] = 'container';
}
return result;
};
return (React.createElement(Styled$2, { ...omitCtxKeys(props), as: component, ...finalProps, ...getDevProps() },
React.createElement(ContainerContext.Provider, { value: context }, children)));
};
const name$2 = `${PKG_NAME}/Container`;
Component$2.displayName = name$2;
Component$2.pkgName = PKG_NAME;
Component$2.VITUS_LABS__COMPONENT = name$2;
var RowContext = createContext({});
/* eslint-disable @typescript-eslint/no-non-null-assertion */
const { styled: styled$1, css: css$1, component: component$1 } = config;
const spacingStyles$1 = ({ gap, gutter }, { rootSize }) => {
if (!isNumber(gap))
return '';
const getValue = (param) => value(param, rootSize);
const spacingX = (gap / 2) * -1;
const spacingY = isNumber(gutter) ? gutter - gap / 2 : gap / 2;
return css$1 `
margin: ${getValue(spacingY)} ${getValue(spacingX)};
`;
};
const contentAlign = (align) => {
if (!align)
return '';
return css$1 `
justify-content: ${ALIGN_CONTENT_MAP_X[align]};
`;
};
const styles$1 = ({ theme, css, rootSize }) => {
const { gap, gutter, contentAlignX, extraStyles } = theme;
return css `
${spacingStyles$1({ gap, gutter }, { rootSize })};
${contentAlign(contentAlignX)};
${extendCss(extraStyles)};
`;
};
var Styled$1 = styled$1(component$1) `
${false};
display: flex;
flex-wrap: wrap;
align-self: stretch;
flex-direction: row;
${makeItResponsive({
key: '$coolgrid',
styles: styles$1,
css: css$1,
normalize: true,
})};
`;
const Component$1 = ({ children, component, css, contentAlignX: rowAlignX, ...props }) => {
const parentCtx = useContext(ContainerContext);
const { columns, gap, gutter, rowComponent, rowCss, contentAlignX, ...ctx } = useGridContext({ ...parentCtx, ...props });
const context = useMemo(() => ({ ...ctx, columns, gap, gutter }), [ctx, columns, gap, gutter]);
const finalComponent = useMemo(() => component || rowComponent, [component, rowComponent]);
const finalProps = useMemo(() => ({
$coolgrid: {
contentAlignX: rowAlignX || contentAlignX,
columns,
gap,
gutter,
extraStyles: css || rowCss,
},
}), [rowAlignX, contentAlignX, columns, gap, gutter, css, rowCss]);
const getDevProps = () => {
const result = {};
if (process.env.NODE_ENV !== 'production') {
result['data-coolgrid'] = 'row';
}
return result;
};
return (React.createElement(Styled$1, { ...omitCtxKeys(props), as: finalComponent, ...finalProps, ...getDevProps() },
React.createElement(RowContext.Provider, { value: context }, children)));
};
const name$1 = `${PKG_NAME}/Row`;
Component$1.displayName = name$1;
Component$1.pkgName = PKG_NAME;
Component$1.VITUS_LABS__COMPONENT = name$1;
/* eslint-disable @typescript-eslint/no-non-null-assertion */
const { styled, css, component } = config;
const hasWidth = (size, columns) => hasValue(size) && hasValue(columns);
const widthStyles = ({ size, columns, gap, RNparentWidth }, { rootSize }) => {
if (!hasWidth(size, columns)) {
return '';
}
// calculate % of width
const width = (RNparentWidth / columns) * size;
const hasGap = hasValue(gap);
// eslint-disable-next-line no-nested-ternary
const val = hasGap
? width - gap
: width;
return css `
flex-grow: 0;
flex-shrink: 0;
max-width: ${value(val, rootSize)};
flex-basis: ${value(val, rootSize)};
`;
};
const spacingStyles = (type, param, rootSize) => {
if (!isNumber(param)) {
return '';
}
const finalStyle = `${type}: ${value(param / 2, rootSize)}`;
return css `
${finalStyle};
`;
};
const styles = ({ theme, css, rootSize, }) => {
const { size, columns, gap, padding, extraStyles, RNparentWidth } = theme;
const renderStyles = isVisible(size);
if (renderStyles) {
return css `
left: initial;
position: relative;
${widthStyles({ size, columns, gap, RNparentWidth }, { rootSize })};
${spacingStyles('padding', padding, rootSize)};
${spacingStyles('margin', gap, rootSize)};
${extendCss(extraStyles)};
`;
}
return css `
left: -9999px;
position: fixed;
margin: 0;
padding: 0;
`;
};
var Styled = styled(component) `
${false};
position: relative;
display: flex;
flex-basis: 0;
flex-grow: 1;
flex-direction: column;
justify-content: stretch;
${makeItResponsive({
key: '$coolgrid',
styles,
css,
normalize: true,
})};
`;
const Component = ({ children, component, css, ...props }) => {
const parentCtx = useContext(RowContext);
const { colCss, colComponent, columns, gap, size, padding } = useGridContext({
...parentCtx,
...props,
});
const finalComponent = useMemo(() => component ?? colComponent, [component, colComponent]);
const finalProps = useMemo(() => ({
$coolgrid: {
columns,
gap,
size,
padding,
extraStyles: css ?? colCss,
},
}), [columns, gap, size, padding, css, colCss]);
const getDevProps = () => {
const result = {};
if (process.env.NODE_ENV !== 'production') {
result['data-coolgrid'] = 'col';
}
return result;
};
return (React.createElement(Styled, { ...omitCtxKeys(props), as: finalComponent, ...finalProps, ...getDevProps() }, children));
};
const name = `${PKG_NAME}/Col`;
Component.displayName = name;
Component.pkgName = PKG_NAME;
Component.VITUS_LABS__COMPONENT = name;
var theme = {
rootSize: 16,
breakpoints: {
xs: 0,
sm: 576,
md: 768,
lg: 992,
xl: 1200,
},
grid: {
columns: 12,
container: {
xs: '100%',
sm: 540,
md: 720,
lg: 960,
xl: 1140,
},
},
};
export { Component as Col, Component$2 as Container, Component$1 as Row, theme };
//# sourceMappingURL=vitus-labs-coolgrid.native.js.map