on d72cd54 help sign in
124 lines 2.9 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 disabled = false,
15 mono = false,
16 warning,
17 obscure,
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 // choose the base dom component
36 const BaseComponent = type === 'textarea' ? 'textarea' : 'input';
38 // notify parent of enter keypress iff not disabled and passing
39 // TODO: integrate this into react-final-form submission
40 // const onKeyPress = useCallback(
41 // e => !disabled && valid && e.key === 'Enter' && onEnter && onEnter(),
42 // [disabled, valid] // eslint-disable-line react-hooks/exhaustive-deps
43 // );
45 // console.log(input);
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="label"
59 className={cn('f6 lh-tall', {
60 black: !disabled,
61 gray4: disabled,
62 })}
63 htmlFor={name}>
64 {label}
65 </Flex.Item>
66 <Flex.Item as={Flex} row className="rel">
67 <Flex.Item
68 flex
69 as={BaseComponent}
70 {...rest}
71 // NOTE: 24px = 12px * 2 (from p3 styling)
72 style={type === 'textarea' ? { minHeight: 'calc(1rem + 24px)' } : {}}
73 className={cn(
74 'b b1 p3 outline-none',
75 { mono },
76 {
77 'bg-white': !disabled,
78 'bg-gray1': disabled,
79 },
80 {
81 gray4: !(active || touched),
82 black: active || touched,
83 },
84 {
85 'b-green3': valid,
86 'b-black': !valid && active,
87 'b-yellow3': !valid && !active && touched,
88 'b-gray2': !valid && !active && !touched,
89 }
90 )}
91 id={name}
92 name={name}
93 {...input}
94 type={type === 'textarea' ? undefined : type}
95 />
96 {accessory && (
97 <div
98 className="abs"
99 style={{
100 top: 0,
101 right: 0,
102 height: '100%',
103 width: '44px',
104 overflow: 'hidden',
105 }}>
106 {accessory}
107 </div>
108 )}
109 </Flex.Item>
111 {warning && (
112 <Flex.Item as={ErrorText} className="mv1">
113 {warning}
114 </Flex.Item>
115 )}
117 {touched && !active && error && (
118 <Flex.Item as={ErrorText} className="mv1">
119 {error}
120 </Flex.Item>
121 )}
122 </Flex>
123 );