@thecb/components 6.0.0-beta.8 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +1426 -112
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1426 -112
- package/dist/index.esm.js.map +1 -1
- package/package.json +2 -1
- package/src/components/atoms/dropdown/Dropdown.js +184 -152
- package/src/components/atoms/form-select/FormSelect.js +3 -1
- package/src/components/atoms/layouts/Box.js +79 -73
- package/src/util/general.js +21 -0
- package/src/.DS_Store +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thecb/components",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.1",
|
|
4
4
|
"description": "Common lib for CityBase react components",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@babel/runtime": "^7.15.4",
|
|
81
|
+
"core-js": "^3.22.5",
|
|
81
82
|
"formatted-input": "^1.0.0",
|
|
82
83
|
"framer-motion": "^1.11.0",
|
|
83
84
|
"numeral": "^2.0.6",
|
|
@@ -1,26 +1,36 @@
|
|
|
1
1
|
import React, { useEffect, Fragment, useState, useRef, createRef } from "react";
|
|
2
2
|
import { Box, Stack } from "../layouts";
|
|
3
3
|
import Text from "../text";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
noop,
|
|
6
|
+
inputDisabledStyle,
|
|
7
|
+
inputPlaceholderTextStyle
|
|
8
|
+
} from "../../../util/general";
|
|
5
9
|
import DropdownIcon from "./DropdownIcon";
|
|
6
10
|
import styled from "styled-components";
|
|
11
|
+
// support for Array.prototype.at() in older browsers
|
|
12
|
+
import "core-js/proposals/relative-indexing-method";
|
|
7
13
|
|
|
8
14
|
import {
|
|
9
15
|
WHITE,
|
|
10
16
|
GREY_CHATEAU,
|
|
11
17
|
STORM_GREY,
|
|
12
18
|
MINESHAFT_GREY,
|
|
13
|
-
ERROR_COLOR
|
|
19
|
+
ERROR_COLOR,
|
|
20
|
+
CHARADE_GREY
|
|
14
21
|
} from "../../../constants/colors";
|
|
15
22
|
import { fallbackValues } from "./Dropdown.theme";
|
|
16
23
|
import { themeComponent } from "../../../util/themeUtils";
|
|
17
24
|
|
|
18
25
|
const IconWrapper = styled.div`
|
|
26
|
+
position: absolute;
|
|
19
27
|
display: flex;
|
|
20
28
|
flex-direction: column;
|
|
21
29
|
justify-content: center;
|
|
22
30
|
transition: transform 0.3s ease;
|
|
23
|
-
${({ open }) => (open ? "transform: rotate(-180deg)" : "")}
|
|
31
|
+
${({ open }) => (open ? "transform: rotate(-180deg)" : "")};
|
|
32
|
+
top: 20px;
|
|
33
|
+
right: 12px;
|
|
24
34
|
`;
|
|
25
35
|
|
|
26
36
|
const DropdownContentWrapper = styled.div`
|
|
@@ -39,9 +49,13 @@ const DropdownContentWrapper = styled.div`
|
|
|
39
49
|
&:focus {
|
|
40
50
|
outline: none;
|
|
41
51
|
}
|
|
52
|
+
|
|
53
|
+
ul {
|
|
54
|
+
padding-left: 0;
|
|
55
|
+
}
|
|
42
56
|
`;
|
|
43
57
|
|
|
44
|
-
const DropdownItemWrapper = styled.
|
|
58
|
+
const DropdownItemWrapper = styled.li`
|
|
45
59
|
background-color: ${({ selected, themeValues }) =>
|
|
46
60
|
selected ? themeValues.selectedColor : WHITE};
|
|
47
61
|
text-align: start;
|
|
@@ -51,6 +65,7 @@ const DropdownItemWrapper = styled.div`
|
|
|
51
65
|
padding: 1rem;
|
|
52
66
|
box-sizing: border-box;
|
|
53
67
|
width: 100%;
|
|
68
|
+
list-style: none;
|
|
54
69
|
cursor: ${({ disabled }) => (disabled ? "default" : "pointer")};
|
|
55
70
|
|
|
56
71
|
&:hover {
|
|
@@ -72,14 +87,6 @@ const DropdownItemWrapper = styled.div`
|
|
|
72
87
|
}
|
|
73
88
|
`;
|
|
74
89
|
|
|
75
|
-
const SearchInput = styled.input`
|
|
76
|
-
border: none;
|
|
77
|
-
background-color: transparent;
|
|
78
|
-
font-size: 16px;
|
|
79
|
-
height: 24px;
|
|
80
|
-
min-width: 80%;
|
|
81
|
-
`;
|
|
82
|
-
|
|
83
90
|
const Dropdown = ({
|
|
84
91
|
placeholder,
|
|
85
92
|
options,
|
|
@@ -94,15 +101,19 @@ const Dropdown = ({
|
|
|
94
101
|
widthFitOptions = false,
|
|
95
102
|
disabled,
|
|
96
103
|
hasTitles = false,
|
|
97
|
-
autoEraseTypeAhead = true,
|
|
104
|
+
autoEraseTypeAhead = true,
|
|
98
105
|
ariaLabelledby,
|
|
99
|
-
autocompleteValue = "" // autofill
|
|
106
|
+
autocompleteValue = "", // browser autofill value, like country-name or address-level1 for state
|
|
107
|
+
smoothScroll = true
|
|
100
108
|
}) => {
|
|
101
109
|
const [inputValue, setInputValue] = useState("");
|
|
102
110
|
const [optionsState, setOptionsState] = useState([]);
|
|
103
111
|
const [filteredOptions, setFilteredOptions] = useState([]);
|
|
104
112
|
const [optionsChanged, setOptionsChanged] = useState(true);
|
|
105
113
|
const [selectedRef, setSelectedRef] = useState(undefined);
|
|
114
|
+
const [focusedRef, setFocusedRef] = useState(undefined);
|
|
115
|
+
const [inputChangedByAutofill, setInputChangedByAutofill] = useState(false);
|
|
116
|
+
const [focusedByClick, setFocusedByClick] = useState(false);
|
|
106
117
|
|
|
107
118
|
if (optionsState !== options) {
|
|
108
119
|
setOptionsState(options);
|
|
@@ -122,17 +133,15 @@ const Dropdown = ({
|
|
|
122
133
|
value ? options.find(option => option.value === value)?.text : placeholder;
|
|
123
134
|
|
|
124
135
|
const onKeyDown = e => {
|
|
125
|
-
console.log("key down event is", e);
|
|
126
136
|
const { key, keyCode } = e;
|
|
127
137
|
const focus = document.activeElement;
|
|
128
|
-
console.log("dropdown value is", value);
|
|
129
|
-
console.log("focus is", focus);
|
|
130
|
-
console.log("option refs are", optionRefs.current);
|
|
131
138
|
const optionEl = optionRefs.current.find(ref => ref.current === focus);
|
|
132
|
-
console.log("option el is", optionEl);
|
|
133
139
|
switch (key) {
|
|
134
140
|
case "ArrowDown":
|
|
135
141
|
e.preventDefault();
|
|
142
|
+
if (!isOpen) {
|
|
143
|
+
onClick();
|
|
144
|
+
}
|
|
136
145
|
if (optionEl) {
|
|
137
146
|
if (optionEl.current.nextElementSibling) {
|
|
138
147
|
optionEl.current.nextElementSibling.focus();
|
|
@@ -172,9 +181,12 @@ const Dropdown = ({
|
|
|
172
181
|
break;
|
|
173
182
|
case "End":
|
|
174
183
|
e.preventDefault();
|
|
175
|
-
optionRefs.current
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
optionRefs.current.at(-1).current.focus();
|
|
185
|
+
break;
|
|
186
|
+
case "Escape":
|
|
187
|
+
if (isOpen) {
|
|
188
|
+
onClick();
|
|
189
|
+
}
|
|
178
190
|
break;
|
|
179
191
|
}
|
|
180
192
|
if ((keyCode > 64 && keyCode < 91) || keyCode == 32 || keyCode == 189) {
|
|
@@ -183,21 +195,37 @@ const Dropdown = ({
|
|
|
183
195
|
}
|
|
184
196
|
};
|
|
185
197
|
|
|
198
|
+
const handleItemSelection = (evt, choice, i) => {
|
|
199
|
+
if (disabledValues.includes(choice.value)) {
|
|
200
|
+
evt.preventDefault();
|
|
201
|
+
} else {
|
|
202
|
+
setSelectedRef(optionRefs.current[i]);
|
|
203
|
+
onSelect(choice.value);
|
|
204
|
+
if (isOpen) {
|
|
205
|
+
onClick();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
186
210
|
useEffect(() => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
);
|
|
192
|
-
console.log("selected refs in isopen useffect", selectedRef);
|
|
193
|
-
console.log("value in isopen useffect", value);
|
|
194
|
-
if (isOpen && selectedRef !== undefined && selectedRef.current !== null) {
|
|
195
|
-
// WAI-ARIA requires the selected option to receive focus
|
|
211
|
+
const selectedRefExists =
|
|
212
|
+
selectedRef !== undefined && selectedRef.current !== null;
|
|
213
|
+
if (isOpen && selectedRefExists && !focusedByClick) {
|
|
214
|
+
// For keyboard users, WAI-ARIA requires the selected option to receive focus
|
|
196
215
|
selectedRef.current.focus();
|
|
197
|
-
} else if (isOpen && optionRefs.current[0].current) {
|
|
216
|
+
} else if (isOpen && optionRefs.current[0].current && !focusedByClick) {
|
|
198
217
|
// If no selected option, first option receives focus
|
|
199
218
|
optionRefs.current[0].current.focus();
|
|
200
219
|
}
|
|
220
|
+
if (isOpen && focusedByClick && selectedRefExists) {
|
|
221
|
+
// To support autofill for mouse users, we maintain focus on input just scroll item into view
|
|
222
|
+
selectedRef.current.scrollIntoView({
|
|
223
|
+
behavior: smoothScroll ? "smooth" : "auto",
|
|
224
|
+
block: "nearest",
|
|
225
|
+
inline: "start"
|
|
226
|
+
});
|
|
227
|
+
setFocusedByClick(false);
|
|
228
|
+
}
|
|
201
229
|
clearTimeout(timer);
|
|
202
230
|
setInputValue("");
|
|
203
231
|
}, [isOpen]);
|
|
@@ -218,14 +246,20 @@ const Dropdown = ({
|
|
|
218
246
|
|
|
219
247
|
useEffect(() => {
|
|
220
248
|
if (
|
|
221
|
-
|
|
249
|
+
/*
|
|
250
|
+
Either user has typed a value into input that matches a non-disabled option or
|
|
251
|
+
user has autofilled or pasted into input a string matching a valid option
|
|
252
|
+
*/
|
|
253
|
+
(!isOpen || inputChangedByAutofill) &&
|
|
222
254
|
filteredOptions[0] &&
|
|
223
255
|
!disabledValues.includes(filteredOptions[0].value) &&
|
|
224
256
|
filteredOptions[0].text != placeholder
|
|
225
257
|
) {
|
|
226
|
-
|
|
227
|
-
console.log("option refs are", optionRefs);
|
|
258
|
+
setInputChangedByAutofill(false);
|
|
228
259
|
onSelect(filteredOptions[0].value);
|
|
260
|
+
if (isOpen) {
|
|
261
|
+
setTimeout(() => onClick(), 1000);
|
|
262
|
+
}
|
|
229
263
|
}
|
|
230
264
|
if (optionRefs.current[0].current) {
|
|
231
265
|
optionRefs.current[0].current.focus();
|
|
@@ -236,30 +270,32 @@ const Dropdown = ({
|
|
|
236
270
|
|
|
237
271
|
return (
|
|
238
272
|
<Box
|
|
239
|
-
onKeyDown={onKeyDown}
|
|
240
|
-
onClick={onClick}
|
|
241
273
|
padding="0"
|
|
274
|
+
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
275
|
+
extraStyles={`position: relative;`}
|
|
276
|
+
minWidth="100%"
|
|
277
|
+
onClick={() => {
|
|
278
|
+
if (!isOpen) {
|
|
279
|
+
setFocusedByClick(true);
|
|
280
|
+
onClick();
|
|
281
|
+
}
|
|
282
|
+
}}
|
|
283
|
+
onKeyDown={onKeyDown}
|
|
242
284
|
width="100%"
|
|
243
|
-
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
244
|
-
aria-expanded={isOpen}
|
|
245
|
-
role="combobox"
|
|
246
|
-
aria-owns={`${ariaLabelledby}_listbox`}
|
|
247
|
-
aria-haspopup="listbox"
|
|
248
|
-
aria-labelledby={ariaLabelledby}
|
|
249
|
-
extraStyles={
|
|
250
|
-
disabled &&
|
|
251
|
-
`color: #6e727e;
|
|
252
|
-
background-color: #f7f7f7;
|
|
253
|
-
pointer-events: none;`
|
|
254
|
-
}
|
|
255
|
-
title={hasTitles ? getSelection() : null}
|
|
256
285
|
>
|
|
257
286
|
<Box
|
|
258
|
-
as="
|
|
287
|
+
as="input"
|
|
288
|
+
aria-multiline="false"
|
|
289
|
+
aria-autocomplete="list"
|
|
290
|
+
aria-controls={`${ariaLabelledby}_listbox`}
|
|
291
|
+
aria-activedescendant="focused_option"
|
|
292
|
+
aria-owns={`${ariaLabelledby}_listbox`}
|
|
293
|
+
aria-haspopup="listbox"
|
|
294
|
+
aria-labelledby={ariaLabelledby}
|
|
295
|
+
aria-expanded={isOpen}
|
|
296
|
+
autocomplete={autocompleteValue}
|
|
259
297
|
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
260
|
-
|
|
261
|
-
padding="12px"
|
|
262
|
-
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
298
|
+
borderRadius="2px"
|
|
263
299
|
borderSize="1px"
|
|
264
300
|
borderColor={
|
|
265
301
|
isError
|
|
@@ -268,96 +304,91 @@ const Dropdown = ({
|
|
|
268
304
|
? themeValues.selectedColor
|
|
269
305
|
: GREY_CHATEAU
|
|
270
306
|
}
|
|
271
|
-
|
|
307
|
+
extraStyles={
|
|
308
|
+
disabled
|
|
309
|
+
? `${inputPlaceholderTextStyle}${inputDisabledStyle}`
|
|
310
|
+
: inputPlaceholderTextStyle
|
|
311
|
+
}
|
|
312
|
+
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
313
|
+
isOpen={isOpen}
|
|
314
|
+
minHeight="48px"
|
|
315
|
+
minWidth="100%"
|
|
316
|
+
name={autocompleteValue}
|
|
317
|
+
onChange={e => {
|
|
318
|
+
// support autofill and copy/paste
|
|
319
|
+
if (e.target.value !== inputValue) {
|
|
320
|
+
setInputValue(e.target.value);
|
|
321
|
+
setInputChangedByAutofill(true);
|
|
322
|
+
}
|
|
323
|
+
}}
|
|
324
|
+
padding="12px"
|
|
325
|
+
placeholder={getSelection()}
|
|
326
|
+
role="combobox"
|
|
327
|
+
themeValues={themeValues}
|
|
328
|
+
title={hasTitles ? getSelection() : null}
|
|
329
|
+
type="text"
|
|
272
330
|
tabIndex={0}
|
|
331
|
+
value={inputValue}
|
|
332
|
+
width="100%"
|
|
273
333
|
dataQa={placeholder}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
autocomplete={autocompleteValue}
|
|
304
|
-
/>
|
|
305
|
-
<IconWrapper open={isOpen}>
|
|
306
|
-
<DropdownIcon />
|
|
307
|
-
</IconWrapper>
|
|
308
|
-
</Stack>
|
|
309
|
-
</Box>
|
|
310
|
-
{isOpen ? (
|
|
311
|
-
<DropdownContentWrapper
|
|
312
|
-
maxHeight={maxHeight}
|
|
313
|
-
open={isOpen}
|
|
314
|
-
ref={dropdownRef}
|
|
315
|
-
widthFitOptions={widthFitOptions}
|
|
316
|
-
tabIndex={0}
|
|
317
|
-
role="listbox"
|
|
318
|
-
id={`${ariaLabelledby}_listbox`}
|
|
319
|
-
>
|
|
320
|
-
<Stack childGap="0">
|
|
321
|
-
{filteredOptions.map((choice, i) => {
|
|
322
|
-
if (
|
|
323
|
-
choice.value === value &&
|
|
324
|
-
selectedRef !== optionRefs.current[i]
|
|
325
|
-
) {
|
|
326
|
-
setSelectedRef(optionRefs.current[i]);
|
|
327
|
-
}
|
|
328
|
-
return (
|
|
329
|
-
<DropdownItemWrapper
|
|
330
|
-
id={choice.value === value ? "selected_option" : choice.value}
|
|
331
|
-
key={choice.value}
|
|
332
|
-
ref={optionRefs.current[i]}
|
|
333
|
-
as="button"
|
|
334
|
-
tabIndex={-1}
|
|
335
|
-
onClick={
|
|
336
|
-
disabledValues.includes(choice.value)
|
|
337
|
-
? evt => evt.preventDefault()
|
|
338
|
-
: () => {
|
|
339
|
-
setSelectedRef(optionRefs.current[i]);
|
|
340
|
-
onSelect(choice.value);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
selected={choice.value === value}
|
|
344
|
-
aria-selected={choice.value === value}
|
|
345
|
-
disabled={disabledValues.includes(choice.value)}
|
|
346
|
-
data-qa={choice.text}
|
|
347
|
-
themeValues={themeValues}
|
|
348
|
-
title={hasTitles ? choice.text : null}
|
|
349
|
-
role="option"
|
|
350
|
-
>
|
|
351
|
-
<Text
|
|
352
|
-
variant="p"
|
|
353
|
-
color={
|
|
354
|
-
choice.value === value
|
|
355
|
-
? WHITE
|
|
356
|
-
: disabledValues.includes(choice.value)
|
|
357
|
-
? STORM_GREY
|
|
358
|
-
: MINESHAFT_GREY
|
|
334
|
+
/>
|
|
335
|
+
<IconWrapper open={isOpen} onClick={onClick}>
|
|
336
|
+
<DropdownIcon />
|
|
337
|
+
</IconWrapper>
|
|
338
|
+
<Fragment>
|
|
339
|
+
{isOpen ? (
|
|
340
|
+
<DropdownContentWrapper
|
|
341
|
+
maxHeight={maxHeight}
|
|
342
|
+
open={isOpen}
|
|
343
|
+
ref={dropdownRef}
|
|
344
|
+
widthFitOptions={widthFitOptions}
|
|
345
|
+
tabIndex={0}
|
|
346
|
+
role="listbox"
|
|
347
|
+
id={`${ariaLabelledby}_listbox`}
|
|
348
|
+
>
|
|
349
|
+
<Stack childGap="0" as="ul">
|
|
350
|
+
{filteredOptions.map((choice, i) => {
|
|
351
|
+
if (
|
|
352
|
+
choice.value === value &&
|
|
353
|
+
selectedRef !== optionRefs.current[i]
|
|
354
|
+
) {
|
|
355
|
+
setSelectedRef(optionRefs.current[i]);
|
|
356
|
+
}
|
|
357
|
+
return (
|
|
358
|
+
<DropdownItemWrapper
|
|
359
|
+
id={
|
|
360
|
+
focusedRef === optionRefs.current[i]
|
|
361
|
+
? "focused_option"
|
|
362
|
+
: choice.value
|
|
359
363
|
}
|
|
360
|
-
|
|
364
|
+
key={choice.value}
|
|
365
|
+
ref={optionRefs.current[i]}
|
|
366
|
+
tabIndex={-1}
|
|
367
|
+
onClick={e => handleItemSelection(e, choice, i)}
|
|
368
|
+
onKeyDown={e => {
|
|
369
|
+
if (e.keyCode === 13) {
|
|
370
|
+
handleItemSelection(e, choice, i);
|
|
371
|
+
}
|
|
372
|
+
}}
|
|
373
|
+
selected={choice.value === value}
|
|
374
|
+
aria-selected={choice.value === value}
|
|
375
|
+
disabled={disabledValues.includes(choice.value)}
|
|
376
|
+
data-qa={choice.text}
|
|
377
|
+
themeValues={themeValues}
|
|
378
|
+
title={hasTitles ? choice.text : null}
|
|
379
|
+
role="option"
|
|
380
|
+
onFocus={() => setFocusedRef(optionRefs.current[i])}
|
|
381
|
+
>
|
|
382
|
+
<Text
|
|
383
|
+
variant="p"
|
|
384
|
+
color={
|
|
385
|
+
choice.value === value
|
|
386
|
+
? WHITE
|
|
387
|
+
: disabledValues.includes(choice.value)
|
|
388
|
+
? STORM_GREY
|
|
389
|
+
: MINESHAFT_GREY
|
|
390
|
+
}
|
|
391
|
+
extraStyles={`padding-left: 16px;
|
|
361
392
|
cursor: ${
|
|
362
393
|
disabledValues.includes(choice.value)
|
|
363
394
|
? "default"
|
|
@@ -366,17 +397,18 @@ const Dropdown = ({
|
|
|
366
397
|
white-space: nowrap;
|
|
367
398
|
overflow: hidden;
|
|
368
399
|
text-overflow: ellipsis;`}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
400
|
+
>
|
|
401
|
+
{choice.text}
|
|
402
|
+
</Text>
|
|
403
|
+
</DropdownItemWrapper>
|
|
404
|
+
);
|
|
405
|
+
})}
|
|
406
|
+
</Stack>
|
|
407
|
+
</DropdownContentWrapper>
|
|
408
|
+
) : (
|
|
409
|
+
<Fragment />
|
|
410
|
+
)}
|
|
411
|
+
</Fragment>
|
|
380
412
|
</Box>
|
|
381
413
|
);
|
|
382
414
|
};
|
|
@@ -20,7 +20,8 @@ const FormSelect = ({
|
|
|
20
20
|
disabled,
|
|
21
21
|
themeValues,
|
|
22
22
|
hasTitles = false,
|
|
23
|
-
autocompleteValue // autofill
|
|
23
|
+
autocompleteValue, // browser autofill value, like country-name or address-level1 for state
|
|
24
|
+
smoothScroll = true // whether the browser should animate scroll to selected item on first open
|
|
24
25
|
}) => {
|
|
25
26
|
const [open, setOpen] = useState(false);
|
|
26
27
|
const dropdownRef = useRef(null);
|
|
@@ -76,6 +77,7 @@ const FormSelect = ({
|
|
|
76
77
|
onClick={() => setOpen(!open)}
|
|
77
78
|
disabled={disabled}
|
|
78
79
|
autocompleteValue={autocompleteValue}
|
|
80
|
+
smoothScroll={smoothScroll}
|
|
79
81
|
/>
|
|
80
82
|
<Stack direction="row" justify="space-between">
|
|
81
83
|
{(field.hasErrors && field.dirty) || (field.hasErrors && showErrors) ? (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Fragment } from "react";
|
|
1
|
+
import React, { Fragment, forwardRef } from "react";
|
|
2
2
|
import { BoxWrapper } from "./Box.styled";
|
|
3
3
|
import { safeChildren, screenReaderOnlyStyle } from "../../../util/general";
|
|
4
4
|
|
|
@@ -10,78 +10,84 @@ import { safeChildren, screenReaderOnlyStyle } from "../../../util/general";
|
|
|
10
10
|
completely off screen (only for users of screen readers)
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
const Box = (
|
|
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
|
-
|
|
13
|
+
const Box = forwardRef(
|
|
14
|
+
(
|
|
15
|
+
{
|
|
16
|
+
padding = "16px",
|
|
17
|
+
borderSize = "0px",
|
|
18
|
+
borderColor = "transparent",
|
|
19
|
+
borderRadius,
|
|
20
|
+
boxShadow = "none",
|
|
21
|
+
background,
|
|
22
|
+
color,
|
|
23
|
+
minHeight,
|
|
24
|
+
width,
|
|
25
|
+
minWidth,
|
|
26
|
+
maxWidth,
|
|
27
|
+
borderWidthOverride,
|
|
28
|
+
border,
|
|
29
|
+
textAlign,
|
|
30
|
+
hoverStyles,
|
|
31
|
+
activeStyles,
|
|
32
|
+
disabledStyles,
|
|
33
|
+
variant,
|
|
34
|
+
as,
|
|
35
|
+
onClick,
|
|
36
|
+
onKeyDown,
|
|
37
|
+
onMouseEnter,
|
|
38
|
+
onMouseLeave,
|
|
39
|
+
onFocus,
|
|
40
|
+
onBlur,
|
|
41
|
+
onTouchEnd,
|
|
42
|
+
theme,
|
|
43
|
+
hiddenStyles,
|
|
44
|
+
extraStyles,
|
|
45
|
+
srOnly = false,
|
|
46
|
+
dataQa,
|
|
47
|
+
children,
|
|
48
|
+
...rest
|
|
49
|
+
},
|
|
50
|
+
ref
|
|
51
|
+
) => (
|
|
52
|
+
<BoxWrapper
|
|
53
|
+
padding={padding}
|
|
54
|
+
borderSize={borderSize}
|
|
55
|
+
borderColor={borderColor}
|
|
56
|
+
boxShadow={boxShadow}
|
|
57
|
+
color={color}
|
|
58
|
+
minHeight={minHeight}
|
|
59
|
+
width={width}
|
|
60
|
+
minWidth={minWidth}
|
|
61
|
+
maxWidth={maxWidth}
|
|
62
|
+
background={background}
|
|
63
|
+
borderRadius={borderRadius}
|
|
64
|
+
borderWidthOverride={borderWidthOverride}
|
|
65
|
+
border={border}
|
|
66
|
+
hoverStyles={hoverStyles}
|
|
67
|
+
activeStyles={activeStyles}
|
|
68
|
+
disabledStyles={disabledStyles}
|
|
69
|
+
variant={variant}
|
|
70
|
+
as={as}
|
|
71
|
+
onClick={onClick}
|
|
72
|
+
hiddenStyles={hiddenStyles}
|
|
73
|
+
onKeyDown={onKeyDown}
|
|
74
|
+
extraStyles={
|
|
75
|
+
srOnly ? `${screenReaderOnlyStyle}${extraStyles}` : extraStyles
|
|
76
|
+
}
|
|
77
|
+
theme={theme}
|
|
78
|
+
textAlign={textAlign}
|
|
79
|
+
data-qa={dataQa}
|
|
80
|
+
onMouseEnter={onMouseEnter}
|
|
81
|
+
onMouseLeave={onMouseLeave}
|
|
82
|
+
onFocus={onFocus}
|
|
83
|
+
onBlur={onBlur}
|
|
84
|
+
onTouchEnd={onTouchEnd}
|
|
85
|
+
ref={ref}
|
|
86
|
+
{...rest}
|
|
87
|
+
>
|
|
88
|
+
{children && safeChildren(children, <Fragment />)}
|
|
89
|
+
</BoxWrapper>
|
|
90
|
+
)
|
|
85
91
|
);
|
|
86
92
|
|
|
87
93
|
export default Box;
|