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