on 703ff86 help sign in
122 lines 3.0 kB history raw
1import React from 'react';
2import cn from 'classnames';
3import { useField } from 'react-final-form';
4import Flex from './Flex';
5import { ErrorText } from './Typography';
7export default function Input({
8 // visuals
9 type,
10 name,
11 label,
12 className,
13 accessory,
14 labelAccessory,
15 disabled = false,
16 mono = false,
17 obscure,
19 // state
20 config,
22 // extra
23 ...rest
24}) {
25 const {
26 input,
27 meta: {
28 active,
29 error,
30 submitError,
31 dirtySinceLastSubmit,
32 submitting,
33 submitSucceeded,
34 touched,
35 valid,
36 },
37 } = useField(name, config);
39 disabled = disabled || submitting || submitSucceeded;
41 // choose the base dom component
42 const BaseComponent = type === 'textarea' ? 'textarea' : 'input';
43 const showError = !!error;
44 const showSubmitError = !!submitError && !dirtySinceLastSubmit;
45 const indicateError = touched && !active && (showError || showSubmitError);
47 return (
48 <Flex
49 col
50 className={cn(className, 'mb1')}
51 style={{
52 ...(disabled && {
53 pointerEvents: 'none',
54 cursor: 'not-allowed',
55 }),
56 }}>
57 <Flex.Item
58 as={Flex}
59 justify="between"
60 align="center"
61 className={cn('f6 lh-tall', {
62 black: !disabled,
63 gray4: disabled,
64 })}>
65 <Flex.Item as="label" justify="center" htmlFor={name}>
66 {label}
67 </Flex.Item>
68 {labelAccessory && <Flex.Item>{labelAccessory}</Flex.Item>}
69 </Flex.Item>
70 <Flex.Item as={Flex} row className="rel">
71 <Flex.Item
72 flex
73 as={BaseComponent}
74 {...rest}
75 // NOTE: 1.15 from input line-height, 24px = 12px * 2 (from p3 styling)
76 style={type === 'textarea' ? { minHeight: 'calc(1.5rem * 3)' } : {}}
77 className={cn(
78 'b b1 p3 outline-none bs-none r4',
79 { mono },
80 {
81 'bg-white': !disabled,
82 'bg-gray1': disabled,
83 },
84 {
85 gray4: !(active || touched),
86 black: active || touched,
87 },
88 {
89 'b-green3': valid,
90 'b-black': !valid && active,
91 'b-yellow3': !valid && !active && touched,
92 'b-gray2': !valid && !active && !touched,
93 }
94 )}
95 id={name}
96 name={name}
97 {...input}
98 type={type === 'textarea' ? undefined : type}
99 />
100 {accessory && (
101 <div
102 className="abs"
103 style={{
104 top: 0,
105 right: 0,
106 height: '100%',
107 width: 'calc(1.5em + 24px)',
108 overflow: 'hidden',
109 }}>
110 {accessory}
111 </div>
112 )}
113 </Flex.Item>
115 {indicateError && (
116 <Flex.Item as={ErrorText} className="mv1">
117 {error ? error : submitError}
118 </Flex.Item>
119 )}
120 </Flex>
121 );