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