on 91176c2 help sign in
125 lines 2.9 kB history raw
1import React from 'react';
2import cn from 'classnames';
3import { useField } from 'react-final-form';
5import Flex from './Flex';
6import { ErrorText } from './Typography';
8export default function Input({
9 // visuals
10 type,
11 name,
12 label,
13 className,
14 accessory,
15 disabled = false,
16 mono = false,
18 // callbacks
19 onEnter,
21 // state
22 config,
24 // extra
25 ...rest
26}) {
27 const {
28 input,
29 meta: {
30 active,
31 error,
32 submitting,
33 touched,
34 valid,
35 data: { warning },
36 },
37 } = useField(name, config);
39 disabled = disabled || submitting;
41 // notify parent of enter keypress iff not disabled and passing
42 // TODO: integrate this into react-final-form submission
43 // const onKeyPress = useCallback(
44 // e => !disabled && valid && e.key === 'Enter' && onEnter && onEnter(),
45 // [disabled, valid] // eslint-disable-line react-hooks/exhaustive-deps
46 // );
48 return (
49 <Flex
50 col
51 className={cn(className, 'mb1')}
52 style={{
53 ...(disabled && {
54 pointerEvents: 'none',
55 cursor: 'not-allowed',
56 }),
57 }}>
58 <Flex.Item
59 as="label"
60 className={cn('f6 lh-tall', {
61 black: !disabled,
62 gray4: disabled,
63 })}
64 htmlFor={name}>
65 {label}
66 </Flex.Item>
67 <Flex.Item as={Flex} row className="rel">
68 <Flex.Item
69 flex
70 as={type === 'textarea' ? 'textarea' : 'input'}
71 {...rest}
72 // NOTE: 24px = 12px * 2 (from p3 styling)
73 style={type === 'textarea' ? { minHeight: 'calc(1rem + 24px)' } : {}}
74 className={cn(
75 'b b1 p3 outline-none',
76 { mono },
77 {
78 'bg-white': !disabled,
79 'bg-gray1': disabled,
80 },
81 {
82 gray4: !(active || touched),
83 black: active || touched,
84 },
85 {
86 'b-green3': valid,
87 'b-black': !valid && active,
88 'b-yellow3': !valid && !active && touched,
89 'b-gray2': !valid && !active && !touched,
90 }
91 )}
92 id={name}
93 name={name}
94 {...input}
95 type={type === 'textarea' ? undefined : type}
96 />
97 {accessory && (
98 <div
99 className="abs"
100 style={{
101 top: 0,
102 right: 0,
103 height: '100%',
104 width: '44px',
105 overflow: 'hidden',
106 }}>
107 {accessory}
108 </div>
109 )}
110 </Flex.Item>
112 {warning && (
113 <Flex.Item as={ErrorText} className="mv1">
114 {warning}
115 </Flex.Item>
116 )}
118 {touched && !active && error && (
119 <Flex.Item as={ErrorText} className="mv1">
120 {error}
121 </Flex.Item>
122 )}
123 </Flex>
124 );