@thecb/components 6.0.0-beta.8 → 6.1.0-beta.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 +1425 -112
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1425 -112
- package/dist/index.esm.js.map +1 -1
- package/package.json +2 -1
- package/src/components/atoms/dropdown/Dropdown.js +178 -150
- package/src/components/atoms/form-select/FormSelect.js +3 -1
- package/src/components/atoms/layouts/Box.js +79 -73
- package/src/components/molecules/highlight-tab-row/HighlightTabRow.js +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thecb/components",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.0-beta.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);
|
|
@@ -122,17 +128,15 @@ const Dropdown = ({
|
|
|
122
128
|
value ? options.find(option => option.value === value)?.text : placeholder;
|
|
123
129
|
|
|
124
130
|
const onKeyDown = e => {
|
|
125
|
-
console.log("key down event is", e);
|
|
126
131
|
const { key, keyCode } = e;
|
|
127
132
|
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
133
|
const optionEl = optionRefs.current.find(ref => ref.current === focus);
|
|
132
|
-
console.log("option el is", optionEl);
|
|
133
134
|
switch (key) {
|
|
134
135
|
case "ArrowDown":
|
|
135
136
|
e.preventDefault();
|
|
137
|
+
if (!isOpen) {
|
|
138
|
+
onClick();
|
|
139
|
+
}
|
|
136
140
|
if (optionEl) {
|
|
137
141
|
if (optionEl.current.nextElementSibling) {
|
|
138
142
|
optionEl.current.nextElementSibling.focus();
|
|
@@ -172,9 +176,12 @@ const Dropdown = ({
|
|
|
172
176
|
break;
|
|
173
177
|
case "End":
|
|
174
178
|
e.preventDefault();
|
|
175
|
-
optionRefs.current
|
|
176
|
-
|
|
177
|
-
|
|
179
|
+
optionRefs.current.at(-1).current.focus();
|
|
180
|
+
break;
|
|
181
|
+
case "Escape":
|
|
182
|
+
if (isOpen) {
|
|
183
|
+
onClick();
|
|
184
|
+
}
|
|
178
185
|
break;
|
|
179
186
|
}
|
|
180
187
|
if ((keyCode > 64 && keyCode < 91) || keyCode == 32 || keyCode == 189) {
|
|
@@ -183,21 +190,37 @@ const Dropdown = ({
|
|
|
183
190
|
}
|
|
184
191
|
};
|
|
185
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
|
+
|
|
186
205
|
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
|
|
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
|
|
196
210
|
selectedRef.current.focus();
|
|
197
|
-
} else if (isOpen && optionRefs.current[0].current) {
|
|
211
|
+
} else if (isOpen && optionRefs.current[0].current && !focusedByClick) {
|
|
198
212
|
// If no selected option, first option receives focus
|
|
199
213
|
optionRefs.current[0].current.focus();
|
|
200
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
|
+
}
|
|
201
224
|
clearTimeout(timer);
|
|
202
225
|
setInputValue("");
|
|
203
226
|
}, [isOpen]);
|
|
@@ -218,14 +241,20 @@ const Dropdown = ({
|
|
|
218
241
|
|
|
219
242
|
useEffect(() => {
|
|
220
243
|
if (
|
|
221
|
-
|
|
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) &&
|
|
222
249
|
filteredOptions[0] &&
|
|
223
250
|
!disabledValues.includes(filteredOptions[0].value) &&
|
|
224
251
|
filteredOptions[0].text != placeholder
|
|
225
252
|
) {
|
|
226
|
-
|
|
227
|
-
console.log("option refs are", optionRefs);
|
|
253
|
+
setInputChangedByAutofill(false);
|
|
228
254
|
onSelect(filteredOptions[0].value);
|
|
255
|
+
if (isOpen) {
|
|
256
|
+
setTimeout(() => onClick(), 1000);
|
|
257
|
+
}
|
|
229
258
|
}
|
|
230
259
|
if (optionRefs.current[0].current) {
|
|
231
260
|
optionRefs.current[0].current.focus();
|
|
@@ -236,30 +265,32 @@ const Dropdown = ({
|
|
|
236
265
|
|
|
237
266
|
return (
|
|
238
267
|
<Box
|
|
239
|
-
onKeyDown={onKeyDown}
|
|
240
|
-
onClick={onClick}
|
|
241
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}
|
|
242
279
|
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
280
|
>
|
|
257
281
|
<Box
|
|
258
|
-
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}
|
|
259
292
|
background={isOpen ? themeValues.hoverColor : WHITE}
|
|
260
|
-
|
|
261
|
-
padding="12px"
|
|
262
|
-
hoverStyles={`background-color: ${themeValues.hoverColor};`}
|
|
293
|
+
borderRadius="2px"
|
|
263
294
|
borderSize="1px"
|
|
264
295
|
borderColor={
|
|
265
296
|
isError
|
|
@@ -268,96 +299,92 @@ const Dropdown = ({
|
|
|
268
299
|
? themeValues.selectedColor
|
|
269
300
|
: GREY_CHATEAU
|
|
270
301
|
}
|
|
271
|
-
|
|
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"
|
|
272
326
|
tabIndex={0}
|
|
327
|
+
value={inputValue}
|
|
328
|
+
width="100%"
|
|
273
329
|
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
|
|
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
|
|
359
359
|
}
|
|
360
|
-
|
|
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;
|
|
361
388
|
cursor: ${
|
|
362
389
|
disabledValues.includes(choice.value)
|
|
363
390
|
? "default"
|
|
@@ -366,17 +393,18 @@ const Dropdown = ({
|
|
|
366
393
|
white-space: nowrap;
|
|
367
394
|
overflow: hidden;
|
|
368
395
|
text-overflow: ellipsis;`}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
396
|
+
>
|
|
397
|
+
{choice.text}
|
|
398
|
+
</Text>
|
|
399
|
+
</DropdownItemWrapper>
|
|
400
|
+
);
|
|
401
|
+
})}
|
|
402
|
+
</Stack>
|
|
403
|
+
</DropdownContentWrapper>
|
|
404
|
+
) : (
|
|
405
|
+
<Fragment />
|
|
406
|
+
)}
|
|
407
|
+
</Fragment>
|
|
380
408
|
</Box>
|
|
381
409
|
);
|
|
382
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;
|