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