on b72f345 help sign in
117 lines 2.6 kB history raw
1import React, { useCallback } from 'react';
2import cn from 'classnames';
4import Flex from './Flex';
5import { ErrorText } from './Typography';
7export default function Input({
8 // visuals
9 name,
10 label,
11 className,
12 accessory,
13 mono = false,
15 // callbacks
16 onEnter,
18 // state from hook
19 focused,
20 pass,
21 visiblyPassed,
22 error,
23 hintError,
24 data,
25 bind,
26 autoFocus,
27 disabled,
29 // ignored
30 initialValue,
31 validators,
32 transformers,
34 // extra
35 ...rest
36}) {
37 // NB(shrugs): we disable exhaustive deps because we don't want the callbacks
38 // (whose identity might change between renders) to trigger a re-notify of
39 // state that we already know
40 // this also happens to prevent render loops when rendering a map of inputs
42 // notify parent of enter keypress iff not disabled and passing
43 const onKeyPress = useCallback(
44 e => !disabled && pass && e.key === 'Enter' && onEnter && onEnter(),
45 [disabled, pass] // eslint-disable-line react-hooks/exhaustive-deps
46 );
48 return (
49 <Flex
50 className={cn(className, 'mb1')}
51 col
52 style={{
53 ...(disabled && {
54 pointerEvents: 'none',
55 cursor: 'not-allowed',
56 }),
57 }}>
58 <Flex.Item
59 as="label"
60 className={cn('f6 lh-tall', {
61 black: !disabled,
62 gray4: disabled,
63 })}
64 htmlFor={name}>
65 {label}
66 </Flex.Item>
67 <Flex.Item as={Flex} className="rel" row>
68 <Flex.Item
69 as="input"
70 {...rest}
71 className={cn(
72 'b b1 p3 outline-none',
73 { mono },
74 {
75 'bg-white': !disabled,
76 'bg-gray1': disabled,
77 },
78 {
79 gray4: !focused,
80 black: focused,
81 },
82 {
83 'b-green3': visiblyPassed,
84 'b-black': focused && !visiblyPassed,
85 'b-yellow3': !focused && hintError,
86 'b-gray2': !focused && !hintError && !visiblyPassed,
87 }
88 // TODO: inputClassName ?
89 )}
90 id={name}
91 name={name}
92 onKeyPress={onKeyPress}
93 {...bind}
94 flex
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>
110 {error && (
111 <Flex.Item as={ErrorText} className="mv1">
112 {error}
113 </Flex.Item>
114 )}
115 </Flex>
116 );