-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathinput.js
124 lines (116 loc) · 3.13 KB
/
input.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import React, { useMemo, useRef, useCallback } from "react"
import Flex from "@/components/templates/flex"
import { TextMicro } from "@/components/typography"
import { Input, LabelText } from "./styled"
import Autocomplete from "./autocomplete"
import { mergeRefs } from "@/utils"
const Error = ({ error }) => {
const errorMessage = error === true ? "invalid" : error
return typeof errorMessage === "string" ? (
<TextMicro color="errorText">{errorMessage}</TextMicro>
) : (
!!errorMessage && errorMessage
)
}
export const TextInput = ({
error,
disabled,
iconLeft,
iconRight,
name,
onFocus,
onBlur,
className,
hint,
fieldIndicator,
placeholder = "",
label,
value,
inputRef,
size = "large",
containerStyles,
inputContainerStyles,
hideErrorMessage,
autocompleteProps,
...props
}) => {
const ref = useRef()
const autocompleteMenuRef = useRef()
const onKeyDown = useCallback(
e => {
if (autocompleteMenuRef.current && ["ArrowDown", "ArrowUp"].includes(e.key)) {
autocompleteMenuRef.current.focus()
}
},
[autocompleteMenuRef?.current]
)
const onAutocompleteEscape = useCallback(() => {
if (ref?.current) {
ref.current.focus()
}
}, [ref])
const autocompleteInputProps = useMemo(
() =>
autocompleteProps
? {
"aria-autocomplete": "list",
"aria-controls": "autocomplete-list",
onKeyDown,
}
: {},
[autocompleteProps, onKeyDown]
)
return (
<Flex
gap={0.5}
column
className={className}
position="relative"
{...containerStyles}
as="label"
>
{typeof label === "string" ? <LabelText size={size}>{label}</LabelText> : label}
<Flex position="relative" {...inputContainerStyles}>
{iconLeft && (
<Flex position="absolute" left={1} top={0} bottom={0} alignItems="center">
{iconLeft}
</Flex>
)}
<Input
disabled={disabled}
placeholder={placeholder}
onBlur={onBlur}
onFocus={onFocus}
name={name}
aria-label={name}
hasIconLeft={!!iconLeft}
hasIconRight={!!iconRight}
hasIndicator={!!fieldIndicator}
type="text"
value={value}
size={size}
ref={mergeRefs(inputRef, ref)}
error={error}
hasValue={!!value}
{...autocompleteInputProps}
{...props}
/>
{(!!iconRight || !!fieldIndicator) && (
<Flex position="absolute" right={1} top={0} bottom={0} alignItems="center" gap={1}>
{!!fieldIndicator && <TextMicro color="textLite">{fieldIndicator}</TextMicro>}
{!!iconRight && iconRight}
</Flex>
)}
</Flex>
{typeof hint === "string" ? <TextMicro color="textLite">{hint}</TextMicro> : !!hint && hint}
{!hideErrorMessage ? <Error error={error} /> : null}
<Autocomplete
ref={autocompleteMenuRef}
value={value}
onEsc={onAutocompleteEscape}
autocompleteProps={autocompleteProps}
onInputChange={props.onChange}
/>
</Flex>
)
}