joyent-portal/packages/ui-toolkit/src/form/base/input.js

265 lines
5.7 KiB
JavaScript

import React from 'react';
import { Subscriber } from 'joy-react-broadcast';
import styled, { css } from 'styled-components';
import remcalc from 'remcalc';
import is, { isNot } from 'styled-is';
import PropTypes from 'prop-types';
const colorWithDisabled = props =>
props.disabled ? props.theme.disabled : props.theme.text;
const colorWithDefaultValue = props =>
props.value === props.defaultValue
? props.theme.disabled
: colorWithDisabled(props);
const color = props =>
props.defaultValue ? colorWithDefaultValue(props) : colorWithDisabled(props);
const height = props =>
props.multiple ? 'auto' : props.textarea ? remcalc(192) : remcalc(48);
const paddingTop = props => (props.multiple ? remcalc(20) : remcalc(13));
const style = css`
box-sizing: border-box;
width: ${remcalc(300)};
height: ${height};
min-height: ${height};
padding: ${paddingTop} ${remcalc(12)};
border-radius: ${props => props.theme.borderRadius};
background-color: ${props => props.theme.white};
border: ${remcalc(1)} solid ${props => props.theme.grey};
color: ${color};
font-size: ${remcalc(15)};
line-height: normal !important;
font-style: normal;
font-stretch: normal;
appearance: none;
outline: 0;
&:focus {
border-color: ${props => props.theme.primary};
outline: 0;
}
&::-webkit-input-placeholder {
color: ${props => props.theme.textDisabled};
}
&::-moz-placeholder {
color: ${props => props.theme.textDisabled};
}
&:-ms-input-placeholder {
color: ${props => props.theme.textDisabled};
}
&:invalid {
box-shadow: none;
}
${is('disabled')`
background-color: ${props => props.theme.disabled};
color: ${props => props.theme.grey};
cursor: not-allowed;
::-webkit-input-placeholder { /* WebKit, Blink, Edge */
color: ${props => props.theme.grey};
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: ${props => props.theme.grey};
}
:-ms-input-placeholder { /* Internet Explorer 10-11 */
color: ${props => props.theme.grey};
}
`};
&:disabled {
background-color: ${props => props.theme.disabled};
color: ${props => props.theme.grey};
cursor: not-allowed;
::-webkit-input-placeholder {
/* WebKit, Blink, Edge */
color: ${props => props.theme.textDisabled};
}
::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: ${props => props.theme.textDisabled};
}
:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: ${props => props.theme.textDisabled};
}
}
${is('small')`
width: ${remcalc(120)};
`};
${is('monospace')`
white-space: pre-wrap;
font-family: ${props => props.theme.monoFont.families};
&:disabled {
color: ${props => props.theme.text};
::-webkit-input-placeholder {
color: ${props => props.theme.text};
}
::-moz-placeholder {
color: ${props => props.theme.text};
}
:-ms-input-placeholder {
color: ${props => props.theme.text};
}
}
`};
${is('fluid')`
width: 100%;
min-width: 100%;
`};
${is('xSmall')`
width: ${remcalc(80)}
`};
${is('error')`
border-color: ${props => props.theme.red};
&:focus {
border-color: ${props => props.theme.red};
}
`};
${is('embedded')`
border: none;
border-bottom: ${remcalc(1)} solid ${props => props.theme.text};
border-radius: 0;
background: transparent;
padding: 0;
padding-right: ${remcalc(12)};
display: inline;
height: ${remcalc(24)};
appearance: none;
min-height: 0;
`};
${is('warning')`
border-color: ${props => props.theme.orangeDark}
`};
${is('wrapped')`
border: none;
width: ${remcalc(120)};
`};
${is('borderless')`
border: none;
`};
${is('success')`
border-color: ${props => props.theme.greenDark}
`};
${isNot('fluid')`
max-width: ${remcalc(355)};
`};
${is('width')`
width: ${props => props.width};
max-width: ${props => props.width};
`};
${is('mono')`
font-family: ${props => props.theme.monoFont.families};
`};
${isNot('value')`
text-overflow: ellipsis;
`};
${is('resize')`
resize: ${props => props.resize};
`};
${is('big')`
width: ${remcalc(355)};
max-width: 100%;
`};
${is('number')`
font-weight: ${props => props.theme.font.weight.semibold};
text-align: center;
border-radius: 0;
`};
${is('white')`
color: ${props => props.theme.white};
`};
${is('dark')`
background: ${props => props.theme.greyDarker};
`};
`;
const BaseInput = Component => ({ resize, onBlur, type, ...props }) => {
const render = value => {
const _value = value || {};
const { input = {}, meta = {}, id = '' } = _value;
const hasError = Boolean(props.error || _value.error || meta.error);
const hasWarning = Boolean(props.warning || _value.warning || meta.warning);
const hasSuccess = Boolean(props.success || _value.success || meta.success);
const textarea = type === 'textarea';
const fluid = Boolean(props.fluid);
const mono = Boolean(props.mono);
return (
<Component
{...props}
{...input}
onBlur={onBlur}
id={id}
error={hasError}
warning={hasWarning}
success={hasSuccess}
fluid={fluid}
mono={mono}
resize={textarea ? resize : null}
textarea={textarea}
/>
);
};
return <Subscriber channel="input-group">{render}</Subscriber>;
};
BaseInput.propTypes = {
error: PropTypes.bool,
warning: PropTypes.bool
};
export default BaseInput;
export const Stylable = Component => {
const stylable =
typeof Component === 'string' ? styled[Component] : styled(Component);
return stylable`
${style}
`;
};