Skip to content

Instantly share code, notes, and snippets.

@kylealwyn
Created March 14, 2018 23:45
Show Gist options
  • Save kylealwyn/9d01de2e0380eb85825c64b9c997fb72 to your computer and use it in GitHub Desktop.
Save kylealwyn/9d01de2e0380eb85825c64b9c997fb72 to your computer and use it in GitHub Desktop.

Revisions

  1. kylealwyn created this gist Mar 14, 2018.
    136 changes: 136 additions & 0 deletions with-spacing.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,136 @@
    /* eslint-disable no-param-reassign */

    import React from 'react';

    const Gutter = 12;
    const SIZES = ['', 'xs', 'sm', 'md', 'lg', 'xl'];
    const SIZE_MAP = {
    xs: 4,
    sm: 8,
    '': 12,
    md: 12,
    lg: 16,
    xl: 24,
    };

    const DIRECTIONS = ['t', 'r', 'b', 'l', 'v', 'h'];
    const DIRECTION_SUFFIXES = {
    t: 'Top',
    r: 'Right',
    b: 'Bottom',
    l: 'Left',
    v: 'Vertical',
    // h: 'Horizontal',
    };

    const getFlex = flex => {
    if (typeof flex === 'boolean') {
    return 1;
    }

    if (typeof flex === 'number') {
    return flex;
    }

    return 0;
    };

    const buildSpacingStyles = ({ props, propPrefix, stylePrefix }) => {
    const style = SIZES.reduce((styles, size) => {
    const pixels = SIZE_MAP[size];
    if (props[propPrefix + size]) {
    styles[stylePrefix] = pixels;
    }

    const directionalStyles = DIRECTIONS.reduce((dirStyles, direction) => {
    const validDirectionProp = props[propPrefix + direction + size];
    if (validDirectionProp) {
    const styleKey = stylePrefix + DIRECTION_SUFFIXES[direction];

    return {
    ...dirStyles,
    [styleKey]: pixels,
    };
    }
    return dirStyles;
    }, {});

    return {
    ...styles,
    ...directionalStyles,
    };
    }, {});

    return style;
    };

    const margin = props => buildSpacingStyles({ props, propPrefix: 'm', stylePrefix: 'margin' });

    const padding = props => buildSpacingStyles({ props, propPrefix: 'p', stylePrefix: 'padding' });

    const alignment = ({ row, col, v, h, justify, align, flex, collapsed }) => {
    const vprop = row ? 'alignItems' : 'justifyContent';
    const hprop = row ? 'justifyContent' : 'alignItems';
    const styles = {
    flex: getFlex(flex),
    flexDirection: row ? 'row' : 'column',
    [vprop]: v,
    [hprop]: h,
    justifyContent: justify,
    alignItems: align,
    };

    if (row) {
    // styles.marginHorizontal = collapsed ? 0 : -Gutter;
    }

    if (col) {
    // styles.paddingHorizontal = collapsed ? 0 : Gutter;
    styles.flex = typeof col === 'number' ? col : 1;
    }

    return styles;
    };

    const dimensions = ({ width, height, w, h }) => {
    const style = {};

    if (width || w) {
    style.width = width || w;
    }
    if (height || h) {
    style.height = height || h;
    }

    return style;
    };

    const border = ({ border }) => {
    if (border) {
    const borderColor = border.color || '#000';
    return {
    borderColor,
    borderWidth: border.width,
    borderTopWidth: border.top || border.width,
    borderBottomWidth: border.bottom || border.width,
    borderLeftWidth: border.left || border.width,
    borderRightWidth: border.right || border.width,
    };
    }
    return '';
    };

    export default BaseComponent => props => (
    <BaseComponent
    {...props}
    style={{
    ...border(props),
    ...margin(props),
    ...padding(props),
    ...alignment(props),
    ...dimensions(props),
    ...(props.style || {}),
    }}>
    {props.children}
    </BaseComponent>
    );