@kiwicom/orbit-components
Version:
<div align="center"> <a href="https://orbit.kiwi" target="_blank"> <img alt="orbit-components" src="https://orbit.kiwi/wp-content/uploads/2018/08/orbit-components.png" srcset="https://orbit.kiwi/wp-content/uploads/2018/08/orbit-components@2x.png 2x"
115 lines (101 loc) • 5.59 kB
JavaScript
import * as React from "react";
import styled, { css } from "styled-components";
import media from "../utils/media";
import defaultTokens from "../defaultTokens";
import { ALIGNS, DIRECTIONS, SPACINGS, TOKENS } from "./consts";
import { StyledButton } from "../Button";
import getSpacingToken from "../common/getSpacingToken";
// TODO: use tokens for spacings
const getSpacing = (isDesktop = false) => ({ spacing, direction, desktop }) => () => {
const finalSpacing = isDesktop && desktop && desktop.spacing || spacing;
const finalDirection = isDesktop && desktop && desktop.direction || direction;
const finalType = isDesktop ? TOKENS.SPACING : TOKENS.MOBILESPACING;
const tokens = {
[TOKENS.SPACING]: {
[SPACINGS.EXTRATIGHT]: "2px",
[SPACINGS.TIGHT]: "4px",
[SPACINGS.CONDENSED]: "8px",
[SPACINGS.COMPACT]: "12px",
[SPACINGS.NATURAL]: "16px",
[SPACINGS.COMFY]: "24px",
[SPACINGS.LOOSE]: "32px",
[SPACINGS.EXTRALOOSE]: "40px"
},
[TOKENS.MOBILESPACING]: {
[SPACINGS.EXTRATIGHT]: "2px",
[SPACINGS.TIGHT]: "4px",
[SPACINGS.CONDENSED]: "8px",
[SPACINGS.COMPACT]: "12px",
[SPACINGS.NATURAL]: "16px",
[SPACINGS.COMFY]: "20px",
[SPACINGS.LOOSE]: "28px",
[SPACINGS.EXTRALOOSE]: "36px"
}
};
// TODO: rtl here
return finalDirection === DIRECTIONS.COLUMN ? `0 0 ${tokens[finalType][finalSpacing]} 0` : `0 ${tokens[finalType][finalSpacing]} 0 0`;
};
const getAlign = (name = ALIGNS.START, self = false) => {
const align = self && name === ALIGNS.EVEN ? ALIGNS.START : name;
const tokens = {
[ALIGNS.START]: "flex-start",
[ALIGNS.END]: "flex-end",
[ALIGNS.CENTER]: "center",
[ALIGNS.EVEN]: "space-between"
};
return tokens[align];
};
const isDefined = property => ({ flex, desktop }) => flex && desktop && typeof property !== "undefined";
const StyledStack = styled(({ className, children }) => React.createElement(
"div",
{ className: className },
children
)).withConfig({
displayName: "Stack__StyledStack"
})(["display:", ";flex-direction:", ";flex-wrap:", ";flex-grow:", ";flex-shrink:", ";flex-basis:", ";justify-content:", ";align-items:", ";align-content:", ";margin-bottom:", ";& > *{margin:", ";&:last-child{margin:0;}}& > ", "{align-self:", ";}", ";"], ({ inline, flex }) => flex && (inline ? "inline-flex" : "flex"), ({ direction, flex }) => flex && (direction === DIRECTIONS.ROW ? "row" : "column"), ({ wrap, flex }) => flex && (wrap ? "wrap" : "nowrap"), ({ grow, flex }) => flex && (grow ? "1" : "0"), ({ shrink, flex }) => flex && (shrink ? "1" : "0"), ({ basis, flex }) => flex && basis, ({ flex, align, direction }) => flex && (direction === DIRECTIONS.ROW || align) && getAlign(align), ({ flex }) => flex && "stretch", ({ align, direction, flex }) => flex && (direction === DIRECTIONS.COLUMN || align) && getAlign(align), getSpacingToken, ({ align }) => align !== ALIGNS.EVEN && getSpacing(), StyledButton, ({ align }) => getAlign(align, true), media.desktop`
& > * {
margin: ${getSpacing(true)};
}
// TODO other block components
& > ${StyledButton} {
align-self: ${({ desktop, align }) => desktop && desktop.align !== align && getAlign(desktop.align === ALIGNS.EVEN ? ALIGNS.START : desktop.align)};
}
${({ desktop }) => desktop && css(["display:", ";flex-direction:", ";flex-wrap:", ";flex-grow:", ";flex-shrink:", ";flex-basis:", ";justify-content:", ";align-content:", ";"], ({ inline }) => isDefined(desktop.inline) && inline !== desktop.inline && (desktop.inline ? "inline-flex" : "flex"), ({ direction, flex }) => flex && desktop && typeof desktop.direction !== "undefined" && direction !== desktop.direction && (desktop.direction === DIRECTIONS.ROW ? "row" : "column"), ({ wrap, flex }) => flex && desktop && typeof desktop.wrap !== "undefined" && wrap !== desktop.wrap && (desktop.wrap ? "wrap" : "nowrap"), ({ grow, flex }) => flex && desktop && typeof desktop.grow !== "undefined" && grow !== desktop.grow && (desktop.grow ? "1" : "0"), ({ shrink, flex }) => flex && desktop && typeof desktop.shrink !== "undefined" && shrink !== desktop.shrink && (desktop.shrink ? "1" : "0"), ({ basis, flex }) => flex && desktop && typeof desktop.basis !== "undefined" && basis !== desktop.basis && desktop.basis, ({ flex, align, direction }) => flex && desktop && desktop.direction && (direction !== desktop.direction || align !== desktop.align) && desktop.direction === DIRECTIONS.ROW && getAlign(desktop.align || align), ({ align, direction, flex }) => flex && desktop && desktop.direction && (direction !== desktop.direction || align !== desktop.align) && desktop.direction === DIRECTIONS.COLUMN && getAlign(desktop.align || align))}
`);
StyledStack.defaultProps = {
theme: defaultTokens
};
const Stack = props => {
const {
inline = false,
direction = DIRECTIONS.COLUMN,
spacing = SPACINGS.NATURAL,
align = ALIGNS.START,
grow = true,
wrap = false,
shrink = false,
basis,
desktop,
spaceAfter,
children
} = props;
const flex = Object.keys(props).map(item => !(item === "children" || item === "spaceAfter" || item === "spacing")).includes(true);
return React.createElement(
StyledStack,
{
flex: flex,
direction: direction,
align: align,
wrap: wrap,
grow: grow,
basis: basis,
inline: inline,
shrink: shrink,
spacing: spacing,
spaceAfter: spaceAfter,
desktop: desktop
},
children
);
};
export default Stack;