@kiwicom/orbit-components
Version:
Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.
186 lines (177 loc) • 6.02 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",
componentId: "sc-1t576ow-0"
})(["display:", ";flex-direction:", ";flex-wrap:", ";flex-grow:", ";flex-shrink:", ";flex-basis:", ";justify-content:", ";align-content:", ";align-items:", ";margin-bottom:", ";align-self:", ";& > *{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), ({
align,
direction,
flex
}) => flex && (direction === DIRECTIONS.COLUMN || align) && getAlign(align), ({
align,
direction,
flex
}) => flex && (direction === DIRECTIONS.COLUMN || align) && getAlign(align), getSpacingToken, ({
inline,
flex
}) => flex && !inline && "stretch", ({
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:", ";align-items:", ";margin-bottom:", ";"], ({
inline
}) => isDefined(desktop.inline) && inline !== desktop.inline && (desktop.inline ? "inline-flex" : "flex"), ({
direction
}) => isDefined(desktop.direction) && direction !== desktop.direction && (desktop.direction === DIRECTIONS.ROW ? "row" : "column"), ({
wrap
}) => isDefined(desktop.wrap) && wrap !== desktop.wrap && (desktop.wrap ? "wrap" : "nowrap"), ({
grow
}) => isDefined(desktop.grow) && grow !== desktop.grow && (desktop.grow ? "1" : "0"), ({
shrink
}) => isDefined(desktop.shrink) && shrink !== desktop.shrink && (desktop.shrink ? "1" : "0"), ({
basis
}) => isDefined(desktop.basis) && 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), ({
align,
direction,
flex
}) => flex && desktop && desktop.direction && (direction !== desktop.direction || align !== desktop.align) && desktop.direction === DIRECTIONS.COLUMN && getAlign(desktop.align || align), ({
theme,
spaceAfter
}) => isDefined(desktop.spaceAfter) && spaceAfter !== desktop.spaceAfter && getSpacingToken({
spaceAfter: desktop.spaceAfter,
theme
}))}
`);
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;