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