UNPKG

@axeptio/design-system

Version:
400 lines (364 loc) 9.88 kB
import React from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; import Icon from '../../Icon'; const Header = styled.div` max-width: ${props => (props?.specialWidth ? props.specialWidth : 400)}px; min-width: 100px; width: ${props => (props.specialWidth ? props.specialWidth + 'px' : '100%')}; display: flex; flex-direction: row; justify-content: space-between; margin-bottom: 5px; `; const Left = styled.span` color: ${props => props.theme.colors.secondary}; font-family: ${props => props.theme.fonts.text}; font-weight: 600; font-size: 15px; `; const Right = styled.span` color: ${props => props.theme.colors.secondary}; font-family: ${props => props.theme.fonts.text}; font-size: 14px; font-weight: 400; `; const Label = styled.span` position: absolute; user-select: none; top: -6px; left: 0px; display: flex; border-color: ${props => props.theme.colors.grey.v200}; width: 100%; max-height: 100%; color: ${props => props.theme.colors.secondary}; cursor: ${props => (props.disabled ? 'not-allowed' : 'text')}; transition: color 0.2s ease 0s, font-size 0.2s ease 0s, line-height 0.2s ease 0s, left 0.2s ease 0s, width 0.2s ease 0s; font-family: ${props => props.theme.fonts.text}; font-size: 12px; line-height: 16px; font-weight: 400; z-index: 1; &:before { margin-right: 4px; border-left: 2px solid transparent; border-radius: 6px 0px; } &:after { -webkit-box-flex: 1; flex-grow: 1; margin-left: 4px; border-right: 2px solid transparent; border-radius: 0px 6px; } &:before, :after { content: ''; display: block; box-sizing: border-box; margin-top: 6px; top: -6px; border-top: 2px solid ${props => (props.error ? props.theme.colors.red : props.theme.colors.grey.v200)}; min-width: 10px; height: 8px; pointer-events: none; box-shadow: transparent 0px 1px inset; transition: border-color 0.2s ease 0s, box-shadow 0.2s ease 0s; } `; const Container = styled.label` font-family: ${props => props.theme.fonts.text}; max-width: ${props => (props.specialWidth ? props.specialWidth : 400)}px; width: ${props => (props.specialWidth ? props.specialWidth + 'px' : '100%')}; font-style: normal; font-size: 14px; line-height: 20px; font-weight: 400; position: relative; display: inline-block; min-width: 100px; min-height: 44px; outline: none; display: ${props => (props.unit ? 'flex' : 'block')}; & :first-child:not(:focus):placeholder-shown + ${Label} { font-size: inherit; line-height: 56px; width: calc(100% - ${props => (props.prefix ? props.prefix.length * 6 + 20 : props.icon ? 41 : 0)}px); left: ${props => (props.prefix ? props.prefix.length * 6 + 20 : props.icon ? 41 : 0)}px; } & :not(:focus):placeholder-shown + ${Label} { border-top-color: ${props => props.theme.colors.grey.v200}; } & :first-child:not(:focus):placeholder-shown + ${Label}:after { border-top-color: transparent; } & :first-child:not(:focus):placeholder-shown + ${Label}:before { border-top-color: transparent; } `; const InputUnit = styled.span.attrs({ className: 'InputUnit' })` z-index: 10; position: relative; display: flex; align-items: center; padding: 8px; font-size: 14px; font-family: ${props => props.theme.fonts.text}; color: ${props => (props.error ? props.theme.colors.red : props.theme.colors.grey.v200)}; background: ${props => props.theme.colors.white}; border: 2px solid ${props => (props.error ? props.theme.colors.red : props.theme.colors.grey.v200)}; border-left: none; transition: border 0.2s ease 0s, box-shadow 0.2s ease 0s; border-radius: 0 6px 6px 0; `; const Logo = styled.div` position: absolute; display: flex; -webkit-box-align: center; align-items: center; cursor: ${props => (props.disabled ? 'not-allowed' : 'text')}; ${props => !props.right ? ` left: ${props.prefix ? '4px' : '16px'}; width: 20px; height: 20px; top: 14px; ` : ` right: ${props.suffix ? '4px' : '16px'}; width: 24px; height: 24px; top: 12px; `} ${props => props.onClick && ` cursor: pointer; `} `; const Root = styled.div` font-family: ${props => props.theme.fonts.text}; box-sizing: border-box; margin: 0px; border-width: 2px; border-style: solid; cursor: ${props => (props.disabled ? 'not-allowed' : 'text')}; border-image: initial; border-color: ${props => props.headerExist ? (props.error ? props.theme.colors.red : props.theme.colors.grey.v200) : 'transparent'} ${props => (props.error ? props.theme.colors.red : props.theme.colors.grey.v200)} ${props => (props.error ? props.theme.colors.red : props.theme.colors.grey.v200)}; border-radius: ${props => (props.unit ? '6px 0px 0px 6px' : '6px')}; width: 100%; height: inherit; color: ${props => props.theme.colors.secondary}; background-color: ${props => props.theme.colors.white}; font-family: inherit; font-size: inherit; line-height: inherit; caret-color: ${props => props.theme.colors.secondary}; transition: border 0.2s ease 0s, box-shadow 0.2s ease 0s; overflow: visible; padding-top: 12px; padding-right: 12px; padding-bottom: 12px; padding-left: ${props => (props.prefix ? `${props.prefix.length * 6 + 15}px` : props.icon ? '51px' : '13px')}; ${props => props.disabled && ` background-color: ${props.theme.colors.grey['grey-50']}; opacity: 0.3; `} &:not(:focus):placeholder-shown { border-top-color: ${props => (props.error ? props.theme.colors.red : props.theme.colors.grey.v200)}; } &:focus { border-color: ${props => (props.headerExist ? props.theme.colors.secondary : 'transparent')} ${props => props.theme.colors.secondary} ${props => props.theme.colors.secondary}; outline: none; } &:focus ~ ${InputUnit} { border: 2px solid ${props => props.theme.colors.secondary}; border-left: transparent; color: ${props => props.theme.colors.secondary}; } &:focus + ${Label} { color: ${props => props.theme.colors.secondary}; top: -6px; } &:focus + ${Label}:before { border-top-color: ${props => props.theme.colors.secondary}; } &:focus + ${Label}:after { border-top-color: ${props => props.theme.colors.secondary}; } `; const Footer = styled.div.attrs({ className: 'footer' })` margin-top: 5px; font-family: ${props => props.theme.fonts.text}; font-style: normal; font-size: 14px; line-height: 20px; font-weight: 400; color: ${props => props.theme.colors.red}; `; const Prefix = styled.span` font-family: ${props => props.theme.fonts.text}; font-style: normal; font-size: 14px; line-height: 20px; font-weight: 400; color: ${props => props.theme.colors.grey.v500}; background: ${props => props.theme.colors.grey.v200}; border-radius: 3px; padding: 10px; `; const Encapsuled = styled.div` display: flex; flex-direction: column; `; const Input = ({ autoFocus, label, icon, type, disabled, width, value, prefix, unit, error, multiline, header, optionalText, ...props }) => { const headerExist = header.length !== 0 || optionalText.length !== 0; const [passwordShow, setPasswordShow] = React.useState(false); return ( <Encapsuled> <Header specialWidth={width}> <Left>{header}</Left> <Right>{optionalText}</Right> </Header> <Container unit={unit} specialWidth={width} prefix={prefix} icon={icon}> <Root value={value} error={error} prefix={prefix} unit={unit} icon={icon} name={label} autoFocus={autoFocus} headerExist={headerExist} disabled={disabled} placeholder={headerExist ? label : ' '} type={type === 'password' && passwordShow ? 'text' : type} labe={label} as={multiline ? 'textarea' : 'input'} onChange={e => { props.onChange(e.target.value); }} /> {headerExist ? null : ( <Label error={error} disabled={disabled}> {label} </Label> )} <Logo prefix={prefix} disabled={disabled}> {prefix ? <Prefix>{prefix}</Prefix> : <Icon iconSize={20} name={icon} />} </Logo> {unit ? <InputUnit error={error}>{unit}</InputUnit> : null} {type === 'password' && ( <Logo suffix={unit} right={true} disabled={disabled} onClick={() => setPasswordShow(v => !v)}> <Icon iconSize={24} name={passwordShow ? 'View' : 'ViewOff'} /> </Logo> )} </Container> <div>{error ? <Footer>{error}</Footer> : null}</div> </Encapsuled> ); }; Input.propTypes = { /** * disabled */ autoFocus: PropTypes.bool, /** * disabled */ disabled: PropTypes.bool, /** * Multiline textearea */ multiline: PropTypes.bool, /** * full Width */ width: PropTypes.number, /** * Type */ type: PropTypes.oneOf(['text', 'email', 'password', 'number', 'number', 'url']), /** * icon on the left */ icon: PropTypes.string, /** * header on the left */ header: PropTypes.string, /** * optionalText on the left */ optionalText: PropTypes.string, /** * Input contents */ label: PropTypes.string.isRequired, /** * Change event */ onChange: PropTypes.func, /** * value */ value: PropTypes.any, /** * prefix */ prefix: PropTypes.string, /** * unit */ unit: PropTypes.string, /** * error */ error: PropTypes.string }; Input.defaultProps = { type: 'text', disabled: false, label: '', header: '', optionalText: '' }; export default Input;