@thecb/components 6.0.0-beta.3 → 6.0.0-beta.30
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 +1475 -118
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1475 -118
- package/dist/index.esm.js.map +1 -1
- package/package.json +2 -1
- package/src/components/atoms/country-dropdown/CountryDropdown.js +1 -0
- package/src/components/atoms/dropdown/Dropdown.js +196 -124
- package/src/components/atoms/form-select/FormSelect.js +4 -2
- package/src/components/atoms/layouts/Box.js +79 -73
- package/src/components/atoms/state-province-dropdown/StateProvinceDropdown.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thecb/components",
|
|
3
|
-
"version": "6.0.0-beta.
|
|
3
|
+
"version": "6.0.0-beta.30",
|
|
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: ${({ themeValues }) =>
|
|
78
|
-
themeValues.hoverColor && themeValues.hoverColor};
|
|
79
|
-
font-size: 16px;
|
|
80
|
-
height: 24px;
|
|
81
|
-
`;
|
|
82
|
-
|
|
83
85
|
const Dropdown = ({
|
|
84
86
|
placeholder,
|
|
85
87
|
options,
|
|
@@ -94,13 +96,18 @@ const Dropdown = ({
|
|
|
94
96
|
widthFitOptions = false,
|
|
95
97
|
disabled,
|
|
96
98
|
hasTitles = false,
|
|
97
|
-
autoEraseTypeAhead = true
|
|
99
|
+
autoEraseTypeAhead = true,
|
|
100
|
+
ariaLabelledby,
|
|
101
|
+
autocompleteValue = "" // autofill item for browsers, like country-name or address-level1 for state
|
|
98
102
|
}) => {
|
|
99
103
|
const [inputValue, setInputValue] = useState("");
|
|
100
104
|
const [optionsState, setOptionsState] = useState([]);
|
|
101
105
|
const [filteredOptions, setFilteredOptions] = useState([]);
|
|
102
106
|
const [optionsChanged, setOptionsChanged] = useState(true);
|
|
103
107
|
const [selectedRef, setSelectedRef] = useState(undefined);
|
|
108
|
+
const [focusedRef, setFocusedRef] = useState(undefined);
|
|
109
|
+
const [inputChangedByAutofill, setInputChangedByAutofill] = useState(false);
|
|
110
|
+
const [focusedByClick, setFocusedByClick] = useState(false);
|
|
104
111
|
|
|
105
112
|
if (optionsState !== options) {
|
|
106
113
|
setOptionsState(options);
|
|
@@ -115,21 +122,23 @@ const Dropdown = ({
|
|
|
115
122
|
const [timer, setTimer] = useState(null);
|
|
116
123
|
const optionRefs = useRef([...Array(options.length)].map(() => createRef()));
|
|
117
124
|
const dropdownRef = useRef(null);
|
|
125
|
+
const inputRef = useRef(null);
|
|
118
126
|
|
|
119
127
|
const getSelection = () =>
|
|
120
128
|
value ? options.find(option => option.value === value)?.text : placeholder;
|
|
121
129
|
|
|
122
130
|
const onKeyDown = e => {
|
|
131
|
+
console.log("current input value top of keyDown", inputValue);
|
|
123
132
|
const { key, keyCode } = e;
|
|
124
133
|
const focus = document.activeElement;
|
|
125
134
|
console.log("dropdown value is", value);
|
|
126
|
-
console.log("focus is", focus);
|
|
127
|
-
console.log("option refs are", optionRefs.current);
|
|
128
135
|
const optionEl = optionRefs.current.find(ref => ref.current === focus);
|
|
129
|
-
console.log("option el is", optionEl);
|
|
130
136
|
switch (key) {
|
|
131
137
|
case "ArrowDown":
|
|
132
138
|
e.preventDefault();
|
|
139
|
+
if (!isOpen) {
|
|
140
|
+
onClick();
|
|
141
|
+
}
|
|
133
142
|
if (optionEl) {
|
|
134
143
|
if (optionEl.current.nextElementSibling) {
|
|
135
144
|
optionEl.current.nextElementSibling.focus();
|
|
@@ -161,27 +170,60 @@ const Dropdown = ({
|
|
|
161
170
|
break;
|
|
162
171
|
case "Backspace" || "Delete":
|
|
163
172
|
e.preventDefault();
|
|
164
|
-
console.log("input value is", inputValue);
|
|
165
|
-
console.log("new input value will be", inputValue.slice(0, -1));
|
|
166
173
|
setInputValue(inputValue.slice(0, -1));
|
|
167
174
|
break;
|
|
175
|
+
case "Home":
|
|
176
|
+
e.preventDefault();
|
|
177
|
+
optionRefs.current[0].current.focus();
|
|
178
|
+
break;
|
|
179
|
+
case "End":
|
|
180
|
+
e.preventDefault();
|
|
181
|
+
console.log("option refs current", optionRefs.current);
|
|
182
|
+
optionRefs.current.at(-1).current.focus();
|
|
183
|
+
break;
|
|
184
|
+
case "Escape":
|
|
185
|
+
if (isOpen) {
|
|
186
|
+
onClick();
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
168
189
|
}
|
|
169
190
|
if ((keyCode > 64 && keyCode < 91) || keyCode == 32 || keyCode == 189) {
|
|
170
191
|
e.preventDefault();
|
|
192
|
+
console.log("current input value inside keydown if", inputValue);
|
|
171
193
|
setInputValue(inputValue + key);
|
|
172
194
|
}
|
|
173
195
|
};
|
|
174
196
|
|
|
197
|
+
const handleItemSelection = (evt, choice, i) => {
|
|
198
|
+
if (disabledValues.includes(choice.value)) {
|
|
199
|
+
evt.preventDefault();
|
|
200
|
+
} else {
|
|
201
|
+
setSelectedRef(optionRefs.current[i]);
|
|
202
|
+
onSelect(choice.value);
|
|
203
|
+
if (isOpen) {
|
|
204
|
+
onClick();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
175
209
|
useEffect(() => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
210
|
+
const selectedRefExists =
|
|
211
|
+
selectedRef !== undefined && selectedRef.current !== null;
|
|
212
|
+
if (isOpen && selectedRefExists && !focusedByClick) {
|
|
213
|
+
// WAI-ARIA requires the selected option to receive focus
|
|
214
|
+
selectedRef.current.focus();
|
|
215
|
+
} else if (isOpen && optionRefs.current[0].current && !focusedByClick) {
|
|
216
|
+
// If no selected option, first option receives focus
|
|
183
217
|
optionRefs.current[0].current.focus();
|
|
184
218
|
}
|
|
219
|
+
if (isOpen && focusedByClick && selectedRefExists) {
|
|
220
|
+
selectedRef.current.scrollIntoView({
|
|
221
|
+
behavior: "smooth",
|
|
222
|
+
block: "nearest",
|
|
223
|
+
inline: "start"
|
|
224
|
+
});
|
|
225
|
+
setFocusedByClick(false);
|
|
226
|
+
}
|
|
185
227
|
clearTimeout(timer);
|
|
186
228
|
setInputValue("");
|
|
187
229
|
}, [isOpen]);
|
|
@@ -189,7 +231,7 @@ const Dropdown = ({
|
|
|
189
231
|
useEffect(() => {
|
|
190
232
|
if (autoEraseTypeAhead) {
|
|
191
233
|
clearTimeout(timer);
|
|
192
|
-
setTimer(setTimeout(() => setInputValue(""),
|
|
234
|
+
setTimer(setTimeout(() => setInputValue(""), 3000));
|
|
193
235
|
}
|
|
194
236
|
setFilteredOptions(
|
|
195
237
|
options.filter(
|
|
@@ -202,12 +244,21 @@ const Dropdown = ({
|
|
|
202
244
|
|
|
203
245
|
useEffect(() => {
|
|
204
246
|
if (
|
|
205
|
-
|
|
247
|
+
/*
|
|
248
|
+
Either user has typed a value into input that matches a non-disabled option
|
|
249
|
+
or
|
|
250
|
+
user has autofilled or pasted into input a string matching a valid option
|
|
251
|
+
*/
|
|
252
|
+
(!isOpen || inputChangedByAutofill) &&
|
|
206
253
|
filteredOptions[0] &&
|
|
207
254
|
!disabledValues.includes(filteredOptions[0].value) &&
|
|
208
255
|
filteredOptions[0].text != placeholder
|
|
209
256
|
) {
|
|
257
|
+
setInputChangedByAutofill(false);
|
|
210
258
|
onSelect(filteredOptions[0].value);
|
|
259
|
+
if (isOpen) {
|
|
260
|
+
setTimeout(() => onClick(), 2000);
|
|
261
|
+
}
|
|
211
262
|
}
|
|
212
263
|
if (optionRefs.current[0].current) {
|
|
213
264
|
optionRefs.current[0].current.focus();
|
|
@@ -218,26 +269,32 @@ const Dropdown = ({
|
|
|
218
269
|
|
|
219
270
|
return (
|
|
220
271
|
<Box
|
|
221
|
-
onKeyDown={onKeyDown}
|
|
222
|
-
onClick={onClick}
|
|
223
272
|
padding="0"
|
|
273
|
+
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
274
|
+
extraStyles={`position: relative;`}
|
|
275
|
+
minWidth="100%"
|
|
276
|
+
onClick={() => {
|
|
277
|
+
if (!isOpen) {
|
|
278
|
+
setFocusedByClick(true);
|
|
279
|
+
onClick();
|
|
280
|
+
}
|
|
281
|
+
}}
|
|
282
|
+
onKeyDown={onKeyDown}
|
|
224
283
|
width="100%"
|
|
225
|
-
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
226
|
-
aria-expanded={isOpen}
|
|
227
|
-
extraStyles={
|
|
228
|
-
disabled &&
|
|
229
|
-
`color: #6e727e;
|
|
230
|
-
background-color: #f7f7f7;
|
|
231
|
-
pointer-events: none;`
|
|
232
|
-
}
|
|
233
|
-
title={hasTitles ? getSelection() : null}
|
|
234
284
|
>
|
|
235
285
|
<Box
|
|
236
|
-
as="
|
|
286
|
+
as="input"
|
|
287
|
+
aria-multiline="false"
|
|
288
|
+
aria-autocomplete="list"
|
|
289
|
+
aria-controls={`${ariaLabelledby}_listbox`}
|
|
290
|
+
aria-activedescendant="focused_option"
|
|
291
|
+
aria-owns={`${ariaLabelledby}_listbox`}
|
|
292
|
+
aria-haspopup="listbox"
|
|
293
|
+
aria-labelledby={ariaLabelledby}
|
|
294
|
+
aria-expanded={isOpen}
|
|
295
|
+
autocomplete={autocompleteValue}
|
|
237
296
|
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
238
|
-
|
|
239
|
-
padding="12px"
|
|
240
|
-
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
297
|
+
borderRadius="2px"
|
|
241
298
|
borderSize="1px"
|
|
242
299
|
borderColor={
|
|
243
300
|
isError
|
|
@@ -246,82 +303,96 @@ const Dropdown = ({
|
|
|
246
303
|
? themeValues.selectedColor
|
|
247
304
|
: GREY_CHATEAU
|
|
248
305
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
extraStyles={`height: 48px;
|
|
253
|
-
${disabled &&
|
|
254
|
-
`color: #6e727e;
|
|
255
|
-
background-color: #f7f7f7;
|
|
256
|
-
pointer-events: none;`}
|
|
257
|
-
`}
|
|
258
|
-
>
|
|
259
|
-
<Stack direction="row" bottomItem={2}>
|
|
260
|
-
{isOpen ? (
|
|
261
|
-
<SearchInput
|
|
262
|
-
aria-label={inputValue || "Dropdown awaiting search value"}
|
|
263
|
-
value={inputValue}
|
|
264
|
-
onChange={noop}
|
|
265
|
-
themeValues={themeValues}
|
|
266
|
-
/>
|
|
267
|
-
) : (
|
|
268
|
-
<Text
|
|
269
|
-
variant="p"
|
|
270
|
-
extraStyles={
|
|
271
|
-
disabled &&
|
|
272
|
-
`color: #6e727e;
|
|
306
|
+
extraStyles={
|
|
307
|
+
disabled &&
|
|
308
|
+
`color: #6e727e;
|
|
273
309
|
background-color: #f7f7f7;
|
|
274
310
|
pointer-events: none;`
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
311
|
+
}
|
|
312
|
+
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
313
|
+
isOpen={isOpen}
|
|
314
|
+
minHeight="48px"
|
|
315
|
+
minWidth="100%"
|
|
316
|
+
name={autocompleteValue}
|
|
317
|
+
onChange={e => {
|
|
318
|
+
console.log("current input value onChange", inputValue);
|
|
319
|
+
console.log("input change event", e.target);
|
|
320
|
+
console.log("input change event value", e.target.value);
|
|
321
|
+
// support autofill and copy/paste
|
|
322
|
+
if (e.target.value !== inputValue) {
|
|
323
|
+
setInputValue(e.target.value);
|
|
324
|
+
setInputChangedByAutofill(true);
|
|
325
|
+
}
|
|
326
|
+
}}
|
|
327
|
+
padding="12px"
|
|
328
|
+
placeholder={getSelection()}
|
|
329
|
+
ref={inputRef}
|
|
330
|
+
role="combobox"
|
|
331
|
+
themeValues={themeValues}
|
|
332
|
+
title={hasTitles ? getSelection() : null}
|
|
333
|
+
type="text"
|
|
334
|
+
tabIndex={0}
|
|
335
|
+
value={inputValue}
|
|
336
|
+
width="100%"
|
|
337
|
+
dataQa={placeholder}
|
|
338
|
+
/>
|
|
339
|
+
<IconWrapper open={isOpen} onClick={onClick}>
|
|
340
|
+
<DropdownIcon />
|
|
341
|
+
</IconWrapper>
|
|
342
|
+
<Fragment>
|
|
343
|
+
{isOpen ? (
|
|
344
|
+
<DropdownContentWrapper
|
|
345
|
+
maxHeight={maxHeight}
|
|
346
|
+
open={isOpen}
|
|
347
|
+
ref={dropdownRef}
|
|
348
|
+
widthFitOptions={widthFitOptions}
|
|
349
|
+
tabIndex={0}
|
|
350
|
+
role="listbox"
|
|
351
|
+
id={`${ariaLabelledby}_listbox`}
|
|
352
|
+
>
|
|
353
|
+
<Stack childGap="0" as="ul">
|
|
354
|
+
{filteredOptions.map((choice, i) => {
|
|
355
|
+
if (
|
|
356
|
+
choice.value === value &&
|
|
357
|
+
selectedRef !== optionRefs.current[i]
|
|
358
|
+
) {
|
|
359
|
+
setSelectedRef(optionRefs.current[i]);
|
|
360
|
+
}
|
|
361
|
+
return (
|
|
362
|
+
<DropdownItemWrapper
|
|
363
|
+
id={
|
|
364
|
+
focusedRef === optionRefs.current[i]
|
|
365
|
+
? "focused_option"
|
|
366
|
+
: choice.value
|
|
323
367
|
}
|
|
324
|
-
|
|
368
|
+
key={choice.value}
|
|
369
|
+
ref={optionRefs.current[i]}
|
|
370
|
+
tabIndex={-1}
|
|
371
|
+
onClick={e => handleItemSelection(e, choice, i)}
|
|
372
|
+
onKeyDown={e => {
|
|
373
|
+
if (e.keyCode === 13) {
|
|
374
|
+
handleItemSelection(e, choice, i);
|
|
375
|
+
}
|
|
376
|
+
}}
|
|
377
|
+
selected={choice.value === value}
|
|
378
|
+
aria-selected={choice.value === value}
|
|
379
|
+
disabled={disabledValues.includes(choice.value)}
|
|
380
|
+
data-qa={choice.text}
|
|
381
|
+
themeValues={themeValues}
|
|
382
|
+
title={hasTitles ? choice.text : null}
|
|
383
|
+
role="option"
|
|
384
|
+
onFocus={() => setFocusedRef(optionRefs.current[i])}
|
|
385
|
+
>
|
|
386
|
+
<Text
|
|
387
|
+
variant="p"
|
|
388
|
+
color={
|
|
389
|
+
choice.value === value
|
|
390
|
+
? WHITE
|
|
391
|
+
: disabledValues.includes(choice.value)
|
|
392
|
+
? STORM_GREY
|
|
393
|
+
: MINESHAFT_GREY
|
|
394
|
+
}
|
|
395
|
+
extraStyles={`padding-left: 16px;
|
|
325
396
|
cursor: ${
|
|
326
397
|
disabledValues.includes(choice.value)
|
|
327
398
|
? "default"
|
|
@@ -330,17 +401,18 @@ const Dropdown = ({
|
|
|
330
401
|
white-space: nowrap;
|
|
331
402
|
overflow: hidden;
|
|
332
403
|
text-overflow: ellipsis;`}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
404
|
+
>
|
|
405
|
+
{choice.text}
|
|
406
|
+
</Text>
|
|
407
|
+
</DropdownItemWrapper>
|
|
408
|
+
);
|
|
409
|
+
})}
|
|
410
|
+
</Stack>
|
|
411
|
+
</DropdownContentWrapper>
|
|
412
|
+
) : (
|
|
413
|
+
<Fragment />
|
|
414
|
+
)}
|
|
415
|
+
</Fragment>
|
|
344
416
|
</Box>
|
|
345
417
|
);
|
|
346
418
|
};
|
|
@@ -19,7 +19,8 @@ const FormSelect = ({
|
|
|
19
19
|
disabledValues,
|
|
20
20
|
disabled,
|
|
21
21
|
themeValues,
|
|
22
|
-
hasTitles = false
|
|
22
|
+
hasTitles = false,
|
|
23
|
+
autocompleteValue // autofill item for browsers, like country-name or address-level1 for state
|
|
23
24
|
}) => {
|
|
24
25
|
const [open, setOpen] = useState(false);
|
|
25
26
|
const dropdownRef = useRef(null);
|
|
@@ -58,7 +59,7 @@ const FormSelect = ({
|
|
|
58
59
|
</Cluster>
|
|
59
60
|
</Box>
|
|
60
61
|
<Dropdown
|
|
61
|
-
|
|
62
|
+
ariaLabelledby={labelTextWhenNoError.replace(/\s+/g, "-")}
|
|
62
63
|
maxHeight={dropdownMaxHeight}
|
|
63
64
|
hasTitles={hasTitles}
|
|
64
65
|
placeholder={options[0] ? options[0].text : ""}
|
|
@@ -74,6 +75,7 @@ const FormSelect = ({
|
|
|
74
75
|
}
|
|
75
76
|
onClick={() => setOpen(!open)}
|
|
76
77
|
disabled={disabled}
|
|
78
|
+
autocompleteValue={autocompleteValue}
|
|
77
79
|
/>
|
|
78
80
|
<Stack direction="row" justify="space-between">
|
|
79
81
|
{(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;
|