From 741bf1e39e2c6dead93acb68cdc8c56ebdc856f5 Mon Sep 17 00:00:00 2001 From: Tatiana Cherednichenko Date: Wed, 19 May 2021 18:30:11 +0300 Subject: [PATCH] feat: generate map of states --- package.json | 1 + src/lib/map-generation.tsx | 184 +++++++++++++++++++++++ src/ui/atoms/button-icon/state-props.tsx | 48 ++++++ src/ui/atoms/button-icon/state.mdx | 9 ++ src/ui/atoms/button-icon/usage.mdx | 4 + src/ui/atoms/button/state-props.tsx | 56 +++++++ src/ui/atoms/button/state.mdx | 9 ++ src/ui/atoms/button/usage.mdx | 4 + src/ui/atoms/chip/state-props.tsx | 61 ++++++++ src/ui/atoms/chip/state.mdx | 9 ++ src/ui/atoms/chip/usage.mdx | 4 + src/ui/atoms/input/state-props.tsx | 52 +++++++ src/ui/atoms/input/state.mdx | 9 ++ src/ui/atoms/input/usage.mdx | 4 + yarn.lock | 45 +++++- 15 files changed, 495 insertions(+), 4 deletions(-) create mode 100644 src/lib/map-generation.tsx create mode 100644 src/ui/atoms/button-icon/state-props.tsx create mode 100644 src/ui/atoms/button-icon/state.mdx create mode 100644 src/ui/atoms/button/state-props.tsx create mode 100644 src/ui/atoms/button/state.mdx create mode 100644 src/ui/atoms/chip/state-props.tsx create mode 100644 src/ui/atoms/chip/state.mdx create mode 100644 src/ui/atoms/input/state-props.tsx create mode 100644 src/ui/atoms/input/state.mdx diff --git a/package.json b/package.json index 0b8415a9..ff9203a8 100755 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@typescript-eslint/parser": "4.15.0", "@wessberg/rollup-plugin-ts": "^1.3.8", "babel-loader": "^8.2.2", + "babel-plugin-extract-react-types": "^0.1.14", "babel-plugin-module-resolver": "^4.1.0", "babel-plugin-styled-components": "^1.12.0", "commitizen": "^4.2.3", diff --git a/src/lib/map-generation.tsx b/src/lib/map-generation.tsx new file mode 100644 index 00000000..a1d59e10 --- /dev/null +++ b/src/lib/map-generation.tsx @@ -0,0 +1,184 @@ +/* eslint-disable no-loop-func */ +/* eslint-disable react/no-array-index-key */ +import * as React from 'react'; +import styled, { StyledComponent } from 'styled-components'; +import { Global } from 'lib/global'; +import { Grid, Heading } from 'ui'; + +type SizeProps = 'N' | 'XS' | 'S' | 'M' | 'L' | 'XL' | 'H'; + +type ComponentValuesType = string | boolean | SizeProps; + +interface ComponentProps { + name: string; + values: Array; +} + +interface GenerateMapProps { + otherProps: Record>; + x: ComponentProps; + y: ComponentProps; +} + +interface SizesProps { + size: SizeProps; +} + +const map = ({ size }: SizesProps) => ({ + 'data-size': size, +}); + +export const GenerateMap: React.FC< + GenerateMapProps & { component: React.FC<{ prop: Record }> } +> = ({ x, y, otherProps, component }) => { + const Component = component; + const variants = generateMap({ x, y, otherProps }); + + if (!variants) return null; + + return ( +
+ {variants.map((variant, i) => ( + +
{variant.name}
+ + +
+ {variant.values[0].values.map(({ variants, sizes, ...prop }, headKey) => ( +
{showHead(prop)}
+ ))} + {variant.values.map((props, j) => ( + <> + + {props.name} + + {props.values.map((prop, propKey) => ( + + ))} + + ))} + + + + ))} +
+ ); +}; + +export const generateMap = ({ x, y, otherProps }: GenerateMapProps) => { + const result = []; + + if (x.values.length === 0 || y.values.length === 0) return; + + for (const valueX of x.values) { + const yArr = []; + let columns = 0; + for (const valueY of y.values) { + const map = generatePropsMap([{ [x.name]: valueX, [y.name]: valueY }], otherProps); + yArr.push({ name: valueY, values: map }); + columns = map.length; + } + result.push({ name: valueX, values: yArr, columns }); + } + return result; +}; + +const generatePropsMap = ( + main: Array>, + otherProps: Record>, +) => { + let tree = main; + + Object.keys(otherProps).forEach((key: string) => { + const values: Array = otherProps[key]; + const buffer: Array> = []; + + values.forEach((value: unknown) => { + const cloned = deepCopy(tree); + cloned.forEach((item: Record) => (item[key] = value)); + buffer.push(...cloned); + }); + tree = buffer; + }); + + return tree; +}; + +const deepCopy = (obj: Array>) => JSON.parse(JSON.stringify(obj)); + +export const showHead = (props: Record) => + Object.keys(props).reduce((acc, key) => acc + (props[key] ? key + '\n' : ''), ''); + +const VariantBlock = styled.div` + display: flex; + flex-direction: column; + padding: 20px; +`; + +const Header = styled(Heading)` + padding-left: 5px; + padding-bottom: 15px; +`; + +const GridTemplate = styled(Grid)` + gap: 10px; +`; + +const AreaVariants = styled(Grid)` + color: #c4c4c4; + white-space: pre-line; + gap: 10px; +`; + +export const Column = styled.div` + display: flex; + flex-direction: column; + & > * { + margin: 5px; + } +`; + +export const Row = styled.div` + display: flex; + & > * { + margin: 5px; + } +`; + +export const Main = styled(Global)` + display: flex; + white-space: nowrap; + overflow: scroll; +`; + +export const SizeBlock = styled.div.attrs(map)` + display: flex; + margin: 5px; + align-items: center; + --woly-font-size: 15px; + + &[data-size='N'] { + --woly-component-level: 0; + } + &[data-size='XS'] { + --woly-component-level: 1; + } + &[data-size='S'] { + --woly-component-level: 2; + } + &[data-size='M'] { + --woly-component-level: 3; + } + &[data-size='L'] { + --woly-component-level: 4; + --woly-font-size: 18px; + } + &[data-size='XL'] { + --woly-component-level: 5; + --woly-font-size: 21px; + } + &[data-size='H'] { + --woly-component-level: 6; + --woly-font-size: 21px; + } +` as StyledComponent<'div', Record, SizesProps>; diff --git a/src/ui/atoms/button-icon/state-props.tsx b/src/ui/atoms/button-icon/state-props.tsx new file mode 100644 index 00000000..288188ff --- /dev/null +++ b/src/ui/atoms/button-icon/state-props.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { ButtonIcon } from 'ui'; +import { IconSearch } from 'static/icons'; + +import { GenerateMap, SizeBlock } from '../../../lib/map-generation'; + +interface ComponentProps { + name: string; + values: Array; +} + +interface ButtonIconProps { + disabled: boolean; + filled: boolean; + sizes: 'N' | 'XS' | 'S' | 'M' | 'L' | 'XL' | 'H'; + variants: string; +} + +export const variants: ComponentProps = { + name: 'variants', + values: ['primary', 'secondary'], +}; + +export const sizes: ComponentProps = { + name: 'sizes', + values: ['N', 'XS', 'S', 'M', 'L', 'XL', 'H'], +}; + +export const props = { disabled: [false, true], filled: [false, true] }; + +export const ComponentButtonIcon = ({ prop }: { prop: ButtonIconProps }) => { + const { variants, disabled, filled, sizes } = prop; + return ( + + } + onClick={() => console.info('ButtonIcon clicked')} + variant={variants} + disabled={disabled} + filled={filled} + /> + + ); +}; + +export const GenerateButtonIconMap = () => ( + +); diff --git a/src/ui/atoms/button-icon/state.mdx b/src/ui/atoms/button-icon/state.mdx new file mode 100644 index 00000000..e1013c07 --- /dev/null +++ b/src/ui/atoms/button-icon/state.mdx @@ -0,0 +1,9 @@ +--- +name: button-icon-map +category: map +package: woly +--- + +import {GenerateButtonIconMap } from './state-props' + + diff --git a/src/ui/atoms/button-icon/usage.mdx b/src/ui/atoms/button-icon/usage.mdx index 0b1bd503..0a773a4c 100644 --- a/src/ui/atoms/button-icon/usage.mdx +++ b/src/ui/atoms/button-icon/usage.mdx @@ -140,6 +140,10 @@ Secondary and error variant should be used to focus user attention. /> +### Map of ButtonIcon + +See map + ### Props | Name | Type | Default | Description | diff --git a/src/ui/atoms/button/state-props.tsx b/src/ui/atoms/button/state-props.tsx new file mode 100644 index 00000000..9b65c94d --- /dev/null +++ b/src/ui/atoms/button/state-props.tsx @@ -0,0 +1,56 @@ +import * as React from 'react'; +import { IconSearch } from 'static/icons'; + +import { Button } from '.'; +import { GenerateMap, SizeBlock } from '../../../lib/map-generation'; + +interface ComponentProps { + name: string; + values: Array; +} + +interface ComponentButtonProps { + disabled: boolean; + icon: boolean; + outlined: boolean; + sizes: 'N' | 'XS' | 'S' | 'M' | 'L' | 'XL' | 'H'; + variants: string; +} + +export const variants: ComponentProps = { + name: 'variants', + values: ['primary', 'secondary'], +}; + +export const sizes: ComponentProps = { + name: 'sizes', + values: ['N', 'XS', 'S', 'M', 'L', 'XL', 'H'], +}; + +export const otherProps: Record> = { + disabled: [false, true], + outlined: [false, true], + icon: [false, true], +}; + +export const ComponentButton = ({ prop }: { prop: ComponentButtonProps }) => { + const { disabled, icon, outlined, sizes, variants } = prop; + return ( + +