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