UNPKG

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

202 lines (183 loc) 6.29 kB
// @flow 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"; import type { Props } from "./index"; // 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 }) => ( <div className={className}>{children}</div> ))` display: ${({ inline, flex }) => flex && (inline ? "inline-flex" : "flex")}; flex-direction: ${({ direction, flex }) => flex && (direction === DIRECTIONS.ROW ? "row" : "column")}; flex-wrap: ${({ wrap, flex }) => flex && (wrap ? "wrap" : "nowrap")}; flex-grow: ${({ grow, flex }) => flex && (grow ? "1" : "0")}; flex-shrink: ${({ shrink, flex }) => flex && (shrink ? "1" : "0")}; flex-basis: ${({ basis, flex }) => flex && basis}; justify-content: ${({ flex, align, direction }) => flex && (direction === DIRECTIONS.ROW || align) && getAlign(align)}; align-items: ${({ flex }) => flex && "stretch"}; align-content: ${({ align, direction, flex }) => flex && (direction === DIRECTIONS.COLUMN || align) && getAlign(align)}; margin-bottom: ${getSpacingToken}; & > * { margin: ${({ align }) => align !== ALIGNS.EVEN && getSpacing()}; &:last-child { margin: 0; } } // TODO other block components & > ${StyledButton} { align-self: ${({ 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: ${({ inline }) => isDefined(desktop.inline) && inline !== desktop.inline && (desktop.inline ? "inline-flex" : "flex")}; flex-direction: ${({ direction, flex }) => flex && desktop && typeof desktop.direction !== "undefined" && direction !== desktop.direction && (desktop.direction === DIRECTIONS.ROW ? "row" : "column")}; flex-wrap: ${({ wrap, flex }) => flex && desktop && typeof desktop.wrap !== "undefined" && wrap !== desktop.wrap && (desktop.wrap ? "wrap" : "nowrap")}; flex-grow: ${({ grow, flex }) => flex && desktop && typeof desktop.grow !== "undefined" && grow !== desktop.grow && (desktop.grow ? "1" : "0")}; flex-shrink: ${({ shrink, flex }) => flex && desktop && typeof desktop.shrink !== "undefined" && shrink !== desktop.shrink && (desktop.shrink ? "1" : "0")}; flex-basis: ${({ basis, flex }) => flex && desktop && typeof desktop.basis !== "undefined" && basis !== desktop.basis && desktop.basis}; justify-content: ${({ flex, align, direction }) => flex && desktop && desktop.direction && (direction !== desktop.direction || align !== desktop.align) && desktop.direction === DIRECTIONS.ROW && getAlign(desktop.align || align)}; align-content: ${({ 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: 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 ( <StyledStack flex={flex} direction={direction} align={align} wrap={wrap} grow={grow} basis={basis} inline={inline} shrink={shrink} spacing={spacing} spaceAfter={spaceAfter} desktop={desktop} > {children} </StyledStack> ); }; export default Stack;