diff --git a/.storybook/next.js b/.storybook/next.js index 9fe10c6..e98b651 100644 --- a/.storybook/next.js +++ b/.storybook/next.js @@ -18,6 +18,19 @@ module.exports = { }); newConfig.resolve.extensions.push('.ts', '.tsx'); + // JavaScript + newConfig.module.rules.push({ + test: /\.(js|jsx)$/, + // include: [path.resolve(__dirname, '../src/client/components')], + use: [{ + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'] + } + }] + }); + newConfig.resolve.extensions.push('.js', '.jsx'); + // Stylus newConfig.module.rules.push({ test: /\.styl$/, diff --git a/package-lock.json b/package-lock.json index f49d87d..3457829 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { + "@dzeio/object-util": "^1.3.0", "lucide-react": "^0.16.0", "rollup": "^2.44.0", "rollup-plugin-styles": "^3.14.1", @@ -1871,6 +1872,11 @@ "node": ">=0.1.95" } }, + "node_modules/@dzeio/object-util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.3.0.tgz", + "integrity": "sha512-9pI7BdaS88NIM1RVP3pQ+oJoAPBtYJyInnIzFw3wE+j8W5eyTfudSQvkNoQW6SYrjxND7+IQRCMFwTor+lN5lA==" + }, "node_modules/@emotion/cache": { "version": "10.0.29", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", @@ -24161,6 +24167,11 @@ "minimist": "^1.2.0" } }, + "@dzeio/object-util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@dzeio/object-util/-/object-util-1.3.0.tgz", + "integrity": "sha512-9pI7BdaS88NIM1RVP3pQ+oJoAPBtYJyInnIzFw3wE+j8W5eyTfudSQvkNoQW6SYrjxND7+IQRCMFwTor+lN5lA==" + }, "@emotion/cache": { "version": "10.0.29", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", diff --git a/package.json b/package.json index cf9d495..742d335 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "postinstall": "rollup --config" }, "dependencies": { + "@dzeio/object-util": "^1.3.0", "lucide-react": "^0.16.0", "rollup": "^2.44.0", "rollup-plugin-styles": "^3.14.1", diff --git a/src/dzeio/Container/Container.module.styl b/src/dzeio/Container/Container.module.styl index 8f4d70f..455f861 100644 --- a/src/dzeio/Container/Container.module.styl +++ b/src/dzeio/Container/Container.module.styl @@ -1,5 +1,7 @@ .container - margin 48px auto - padding 0 16px + padding 0 32px width 100% - max-width 1312px + max-width 1280px + @padding[1] * 2 + margin auto auto + &.main + margin 48px auto diff --git a/src/dzeio/Container/index.tsx b/src/dzeio/Container/index.tsx index 647b9d3..d27e652 100644 --- a/src/dzeio/Container/index.tsx +++ b/src/dzeio/Container/index.tsx @@ -6,14 +6,11 @@ import css from './Container.module.styl' interface Props { children: React.ReactNode className?: string + mainContainer?: boolean } export default class Container extends React.Component { - public render = () => ( -
- {this.props.children} -
- ) + public render = () => React.createElement(this.props.mainContainer ? 'main' : 'div', {className: buildClassName(css.container, this.props.className, [css.main, this.props.mainContainer]), children: this.props.children}) } diff --git a/src/dzeio/Footer/Footer.module.styl b/src/dzeio/Footer/Footer.module.styl index 753fbbc..1e37d23 100644 --- a/src/dzeio/Footer/Footer.module.styl +++ b/src/dzeio/Footer/Footer.module.styl @@ -1,7 +1,7 @@ @import '../config.styl' .footer - padding 16px + padding 24px 0 background $foregroundLight @media (prefers-color-scheme dark) background $foregroundDark @@ -9,14 +9,16 @@ ul padding 0 margin 0 - margin-top 12px display flex - justify-content center + justify-content right li display inline-block + padding-left 24px + + .icon + padding-left 16px + &:not(.icon) + .icon + padding-left 48px - &.socials a - padding 0 8px .animation animation grow 1s linear infinite diff --git a/src/dzeio/Footer/index.tsx b/src/dzeio/Footer/index.tsx index a3ac13a..fab640b 100644 --- a/src/dzeio/Footer/index.tsx +++ b/src/dzeio/Footer/index.tsx @@ -5,6 +5,9 @@ import Text from '../Text' import css from './Footer.module.styl' import Image from 'next/image' import { Icon } from '../interfaces' +import Container from '../Container' +import Row from '../Row' +import Col from '../Col' interface Props { text?: string @@ -22,27 +25,34 @@ interface Props { export default class Footer extends React.Component { public render = () => (
- {this.props.text ? ( - {this.props.text} - ) : ( - Made with by {this.props.company || 'Dzeio'} - )} - {this.props.links && ( -
    {this.props.links.map((l, index) => ( -
  • {index !== 0 && (<> - )}{l.name}
  • - ))}
- )} - {this.props.socials && ( -
    {this.props.socials.map((l, index) => ( -
  • - {typeof l.icon === 'string' ? ( - + + + + {this.props.text ? ( + {this.props.text} ) : ( - - )} -
  • - ))}
- )} + Made with by {this.props.company || 'Dzeio'} + )} + + +
    + {this.props.links && this.props.links.map((l, index) => ( +
  • {l.name}
  • + ))} + {this.props.socials && this.props.socials.map((l, index) => ( +
  • + {typeof l.icon === 'string' ? ( + + ) : ( + + )} +
  • + ))} +
+ + + +
) } diff --git a/src/dzeio/Input/Input.module.styl b/src/dzeio/Input/Input.module.styl index a85a99c..8540789 100644 --- a/src/dzeio/Input/Input.module.styl +++ b/src/dzeio/Input/Input.module.styl @@ -15,6 +15,9 @@ color $darkGrayDark transition color $transition pointer-events none + &.iconClickable + pointer-events all + cursor pointer top 14px &.left left 16px // input padding-left @@ -51,52 +54,25 @@ /* End */ .autocomplete - display flex opacity 0 transition all $transition overflow-x hidden pointer-events none - // display flex - flex-direction column - list-style none position absolute - top calc(100% - 4px) + top calc(100% + 16px) left 0 width 100% z-index 100 - box-shadow 0 2px 4px rgba(black, .3) - margin 0 - padding 0 - background $foregroundLight - @media (prefers-color-scheme dark) - background $foregroundDark - - border-radius 8px max-height 25vh overflow-y auto @media (max-width $mobile) max-height 50vh &.reverse - flex-direction column-reverse top initial - bottom 100% - box-shadow 0 -4px 8px rgba(black, .3) - border-radius 0 - border-top-left-radius 4px - border-top-right-radius 4px - li - transition all $transition - padding 8px - @media (max-width $mobile) - padding 24px - cursor pointer - &:hover - background darken(@background, 20%) - @media (prefers-color-scheme dark) - background lighten(lighten($foregroundDark, 5%), 20%) + bottom calc(100% + 16px) div + .autocomplete - top calc(100% - 4px - .9em) + top 100% input:focus ~ .autocomplete select:focus ~ .autocomplete @@ -127,9 +103,13 @@ font-size rem(16) transition color $transition opacity 1 - color $darkGrayLight + // color $darkGrayLight + // @media (prefers-color-scheme dark) + // color $darkGrayDark + + color black @media (prefers-color-scheme dark) - color $darkGrayDark + color white &:disabled @@ -162,14 +142,14 @@ ~ svg color @border-color - &::placeholder - color black + // &::placeholder + // color black - @media (prefers-color-scheme dark) - color white + // @media (prefers-color-scheme dark) + // color white &:invalid - border-color $errorDark + border-color $errorLight ~ label color @border-color @@ -177,7 +157,7 @@ ~ svg color @border-color @media (prefers-color-scheme dark) - border-color $errorLight + border-color $errorDark ~ label color @border-color @@ -190,53 +170,7 @@ padding-left 16px + 24px + 10px &.iconRight padding-right 16 + 24 + 10px - &.filled - border none - background rgba(gray, .1) - border-radius @border-radius @border-radius 0 0 - border-bottom 2px solid rgba(black,.4) - @media (prefers-color-scheme dark) - background rgba(white, .1) - border-bottom 2px solid rgba(white,.4) - - &.opaque - background white - - @media (prefers-color-scheme dark) - background #202020 - - &:hover:not(:disabled) - background rgba(gray, .2) - - @media (prefers-color-scheme dark) - background rgba(white, .2) - - &.opaque - background darken(white, 5%) - @media (prefers-color-scheme dark) - background #1c1c1c - &:focus - background rgba(gray, .3) - border-bottom 2px solid $main - - &.opaque - background white - - @media (prefers-color-scheme dark) - background #202020 - - &:not(:placeholder-shown) - &:focus - &:not([placeholder=" "]) - ~ label - top 3px - left 16px - 4px // .input/padding-left label/padding-left - background transparent - padding 0 - font-size .75rem - ~ svg.left ~ label - left 16px + 24px + 10px // .input/padding-left label/padding-left ~ svg.rotate transform rotateX(0) transition $transition @@ -249,6 +183,9 @@ padding 0 8px font-size rem(14) - &.block, &.block input, &.block select, &.block textarea + &.block + &.block input + &.block select + &.block textarea width 100% display block diff --git a/src/dzeio/Input/Input.stories.tsx b/src/dzeio/Input/Input.stories.tsx index ad5baf0..879757e 100644 --- a/src/dzeio/Input/Input.stories.tsx +++ b/src/dzeio/Input/Input.stories.tsx @@ -1,29 +1,37 @@ -import { Meta } from '@storybook/react/types-6-0' -import { Story } from "@storybook/react" -import React from 'react' -import Component from '.' -import { X } from 'lucide-react' - -export default { - title: 'DZEIO/Input', - component: Component -} as Meta - -export const Basic: Story = (args: any) => - -let tmp = Basic.bind({}) -tmp.args = {label: 'Label', helper: 'Helper', maxLength: 6, characterCount: true, icon: X} - -export const Normal = tmp - -tmp = Basic.bind({}) -tmp.args = {label: 'Label', filled:true, helper: 'Helper', autocomplete: ['a', 'b', 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'], characterCount: true, icon: X} - -export const AutoComplete = tmp - -export const Select: Story = (args: any) => - - - - - \ No newline at end of file +import { Meta } from '@storybook/react/types-6-0' +import { Story } from "@storybook/react" +import React from 'react' +import Component from '.' +import { X } from 'lucide-react' + +export default { + title: 'DZEIO/Input', + component: Component +} as Meta + +export const Basic: Story = (args: any) => + +let tmp = Basic.bind({}) +tmp.args = {label: 'Label', helper: 'Helper', maxLength: 6, iconLeft: { + icon: X, + transformer: (v: string) => v + 1 +}} + +export const Normal = tmp + +tmp = Basic.bind({}) +tmp.args = {label: 'Label', filled:true, helper: 'Helper', choices: [ + 'a', + 'a', + 'a', + 'a', + 'a', + 'a', + 'a', + 'a', + 'b', + {value: 'd', display: 'D'}, + 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' +], characterCount: true, iconLeft: X} + +export const AutoComplete = tmp diff --git a/src/dzeio/Input/index.tsx b/src/dzeio/Input/index.tsx index 534b8c5..452fd14 100644 --- a/src/dzeio/Input/index.tsx +++ b/src/dzeio/Input/index.tsx @@ -5,22 +5,28 @@ import Text from '../Text' import { Icon } from '../interfaces' import { buildClassName } from '../Util' import css from './Input.module.styl' +import Menu from '../Menu' +import { objectClone } from '@dzeio/object-util' interface Props extends React.DetailedHTMLProps, HTMLInputElement> { id?: string label?: string - icon?: Icon - iconRight?: Icon + iconLeft?: Icon | { + icon: Icon + transformer: (value: string) => string + } + iconRight?: Icon | { + icon: Icon + transformer: (value: string) => string + } helper?: string inputRef?: React.RefObject - selectRef?: React.RefObject type?: 'color' | 'text' | 'date' | 'datetime-local' | 'email' | 'file' | 'month' | 'number' | 'password' | 'range' | 'search' | 'tel' | 'time' | 'url' | 'week' | // Custom Types - 'select' | 'textarea' - autocomplete?: Array - children?: React.ReactNode + 'textarea' + choices?: Array } interface States { @@ -29,100 +35,78 @@ interface States { isInFirstPartOfScreen?: boolean } -export default class Input extends React.Component { +export default class Input extends React.PureComponent { public state: States = {} // any because f*ck types - private inputRef: React.RefObject = React.createRef() + private inputRef: React.RefObject = React.createRef() private parentRef: React.RefObject = React.createRef() public componentDidMount() { if (this.props.type === 'textarea') { this.textareaHandler() } - if (this.props.autocomplete) { + if (this.props.choices) { window.addEventListener('scroll', this.parentScroll) this.parentScroll() } } + public componentDidUpdate() { + console.log(this.state) + } + public componentWillUnmount() { - if (this.props.autocomplete) { + if (this.props.choices) { window.removeEventListener('scroll', this.parentScroll) } } public render() { - const props: Props = Object.assign({}, this.props) + const props: Props = objectClone(this.props) delete props.label - delete props.children - delete props.icon - delete props.helper - delete props.autocomplete + delete props.iconLeft delete props.iconRight delete props.inputRef - delete props.selectRef - delete props.color + delete props.helper + delete props.choices const baseProps: React.DetailedHTMLProps, HTMLInputElement> = { placeholder: this.props.label || this.props.placeholder || ' ', ref: this.props.inputRef || this.inputRef, className: buildClassName( - [css.iconLeft, this.props.icon], - [css.iconRight, this.props.iconRight || this.props.autocomplete] + [css.iconLeft, this.props.iconLeft], + [css.iconRight, this.props.iconRight || this.props.choices] ), onInvalid: (ev: React.FormEvent) => ev.preventDefault(), } let input: React.DetailedHTMLProps, HTMLInputElement> - if (this.props.type === 'number') { - baseProps.onWheel = (ev: React.WheelEvent) => ev.currentTarget.blur() - } - - if (this.props.type === 'select' && !this.props.readOnly) { - input = ( - - ) - // select is readonly - } else if (this.props.type === 'select') { - input = ( - - ) - } else if (this.props.type === 'textarea') { - delete baseProps.ref - input = ( -