UNPKG

@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
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