@thecb/components 10.12.0 → 10.12.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 +554 -350
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.esm.js +554 -350
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/molecules/multiple-select-filter/MultipleSelectFilter.js +61 -295
- package/src/components/molecules/multiple-select-filter/MultipleSelectFilter.stories.js +1 -1
- package/src/components/molecules/multiple-select-filter/MultipleSelectFilter.styled.js +4 -4
- package/src/components/molecules/multiple-select-filter/__private__/ActionLinkButton.js +24 -0
- package/src/components/molecules/multiple-select-filter/__private__/FilterButton.js +85 -0
- package/src/components/molecules/multiple-select-filter/__private__/FilterDropdown.js +23 -0
- package/src/components/molecules/multiple-select-filter/__private__/FilterableList.js +144 -0
- package/src/components/molecules/multiple-select-filter/__private__/FilterableListItem.js +67 -0
- package/src/components/molecules/multiple-select-filter/__private__/SearchBox.js +38 -0
- package/src/components/molecules/multiple-select-filter/__private__/useKeyboardNavigation.js +84 -0
- package/src/components/molecules/multiple-select-filter/__private__/util.js +31 -0
- package/src/hooks/use-outside-click/index.js +4 -5
- package/src/components/atoms/.DS_Store +0 -0
package/package.json
CHANGED
|
@@ -1,146 +1,16 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef
|
|
1
|
+
import React, { useState, useEffect, useRef } from "react";
|
|
2
2
|
import { fallbackValues } from "./MultipleSelectFilter.theme";
|
|
3
3
|
import { themeComponent } from "../../../util/themeUtils";
|
|
4
|
-
import { Box
|
|
5
|
-
import {
|
|
6
|
-
import ButtonWithAction from "../../atoms/button-with-action";
|
|
7
|
-
import Checkbox from "../../atoms/checkbox";
|
|
8
|
-
import { GHOST_GREY, WHITE } from "../../../constants/colors";
|
|
9
|
-
import { Text } from "../../atoms";
|
|
10
|
-
import DropdownIconV2 from "../../atoms/dropdown/DropdownIconV2";
|
|
11
|
-
import { FONT_WEIGHT_REGULAR } from "../../../constants/style_constants";
|
|
4
|
+
import { Box } from "../../atoms/layouts";
|
|
5
|
+
import { GHOST_GREY, WHITE, CHARADE_GREY } from "../../../constants/colors";
|
|
12
6
|
import { noop } from "../../../util/general";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
id,
|
|
21
|
-
optionsList,
|
|
22
|
-
selectedOptions,
|
|
23
|
-
themeValues,
|
|
24
|
-
selectOption,
|
|
25
|
-
maxSelections,
|
|
26
|
-
name
|
|
27
|
-
}) => {
|
|
28
|
-
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
29
|
-
const checkboxRefs = useRef([]);
|
|
30
|
-
const isMaxSelectionReached =
|
|
31
|
-
maxSelections && maxSelections === selectedOptions?.length;
|
|
32
|
-
const isChecked = option =>
|
|
33
|
-
selectedOptions?.some(
|
|
34
|
-
selectedOption => selectedOption?.name === option?.name
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (
|
|
39
|
-
focusedIndex !== -1 &&
|
|
40
|
-
checkboxRefs.current &&
|
|
41
|
-
checkboxRefs.current[focusedIndex]
|
|
42
|
-
) {
|
|
43
|
-
checkboxRefs.current[focusedIndex].focus(); // move focus to the active option
|
|
44
|
-
}
|
|
45
|
-
}, [focusedIndex]);
|
|
46
|
-
|
|
47
|
-
const handleKeyDown = event => {
|
|
48
|
-
if (event.key === "ArrowDown") {
|
|
49
|
-
event.preventDefault();
|
|
50
|
-
setFocusedIndex(prevIndex =>
|
|
51
|
-
prevIndex < optionsList.length - 1 ? prevIndex + 1 : 0
|
|
52
|
-
);
|
|
53
|
-
} else if (event.key === "ArrowUp") {
|
|
54
|
-
event.preventDefault();
|
|
55
|
-
setFocusedIndex(prevIndex =>
|
|
56
|
-
prevIndex > 0 ? prevIndex - 1 : optionsList.length - 1
|
|
57
|
-
);
|
|
58
|
-
} else if (event.key === " ") {
|
|
59
|
-
event.preventDefault();
|
|
60
|
-
// Select option on spacebar press if the maximum selection hasn't been reached.
|
|
61
|
-
const validFocusedIndex = focusedIndex < 0 ? 0 : focusedIndex;
|
|
62
|
-
if (
|
|
63
|
-
!isMaxSelectionReached ||
|
|
64
|
-
(focusedIndex !== -1 && isChecked(optionsList[validFocusedIndex]))
|
|
65
|
-
) {
|
|
66
|
-
selectOption(optionsList[validFocusedIndex]);
|
|
67
|
-
}
|
|
68
|
-
} else if (event.key === "Tab") {
|
|
69
|
-
// Reset focus when tabbing out of the list.
|
|
70
|
-
setTimeout(() => {
|
|
71
|
-
setFocusedIndex(-1);
|
|
72
|
-
}, 500);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<Box
|
|
78
|
-
id={id}
|
|
79
|
-
role="listbox"
|
|
80
|
-
padding="0"
|
|
81
|
-
extraStyles={`
|
|
82
|
-
overflow-y: auto;
|
|
83
|
-
max-height: 250px;
|
|
84
|
-
display: flex;
|
|
85
|
-
flex-flow: column;
|
|
86
|
-
`}
|
|
87
|
-
onKeyDown={handleKeyDown}
|
|
88
|
-
>
|
|
89
|
-
{optionsList.map((option, index) => {
|
|
90
|
-
const checked = isChecked(option);
|
|
91
|
-
const isDisabled = isMaxSelectionReached && !checked;
|
|
92
|
-
const tabIndex =
|
|
93
|
-
index === focusedIndex || (index === 0 && focusedIndex === -1)
|
|
94
|
-
? "0"
|
|
95
|
-
: "-1";
|
|
96
|
-
return (
|
|
97
|
-
<Box
|
|
98
|
-
padding="0"
|
|
99
|
-
key={index}
|
|
100
|
-
extraStyles={`
|
|
101
|
-
:hover,
|
|
102
|
-
:active,
|
|
103
|
-
:focus {
|
|
104
|
-
background-color: ${themeValues.primaryColor};
|
|
105
|
-
}
|
|
106
|
-
`}
|
|
107
|
-
>
|
|
108
|
-
<Checkbox
|
|
109
|
-
ref={el => (checkboxRefs.current[index] = el)}
|
|
110
|
-
title={option.name}
|
|
111
|
-
name={option.name}
|
|
112
|
-
checked={checked}
|
|
113
|
-
onChange={() => (isDisabled ? noop : selectOption(option))}
|
|
114
|
-
textExtraStyles={`font-size: 0.875rem; margin: 0;`}
|
|
115
|
-
disabled={isDisabled}
|
|
116
|
-
extraStyles={`
|
|
117
|
-
padding: 0.075rem 0.325rem;
|
|
118
|
-
margin: 0;
|
|
119
|
-
:hover,
|
|
120
|
-
:active,
|
|
121
|
-
:focus {
|
|
122
|
-
background-color: ${themeValues.primaryColor};
|
|
123
|
-
}
|
|
124
|
-
`}
|
|
125
|
-
checkboxMargin="0.3rem"
|
|
126
|
-
role="option"
|
|
127
|
-
checkboxExtraStyles={`
|
|
128
|
-
width: 1.375rem;
|
|
129
|
-
height: 1.375rem;
|
|
130
|
-
${
|
|
131
|
-
checked && !isDisabled
|
|
132
|
-
? `background: ` + themeValues.secondaryColor + `;`
|
|
133
|
-
: ""
|
|
134
|
-
}`}
|
|
135
|
-
tabIndex={tabIndex}
|
|
136
|
-
dataQa={`${name}-option-${index}`}
|
|
137
|
-
/>
|
|
138
|
-
</Box>
|
|
139
|
-
);
|
|
140
|
-
})}
|
|
141
|
-
</Box>
|
|
142
|
-
);
|
|
143
|
-
};
|
|
7
|
+
import { FilterContainer } from "./MultipleSelectFilter.styled";
|
|
8
|
+
import ActionLinkButton from "./__private__/ActionLinkButton";
|
|
9
|
+
import FilterButton from "./__private__/FilterButton";
|
|
10
|
+
import FilterDropdown from "./__private__/FilterDropdown";
|
|
11
|
+
import SearchBox from "./__private__/SearchBox";
|
|
12
|
+
import FilterableList from "./__private__/FilterableList";
|
|
13
|
+
import useOutsideClickHook from "../../../hooks/use-outside-click";
|
|
144
14
|
|
|
145
15
|
const MultipleSelectFilter = ({
|
|
146
16
|
actions,
|
|
@@ -164,53 +34,27 @@ const MultipleSelectFilter = ({
|
|
|
164
34
|
themeValues,
|
|
165
35
|
truncateBtnTextWidth = "15rem"
|
|
166
36
|
}) => {
|
|
167
|
-
const [itemList, setItemList] = useState([]);
|
|
168
37
|
const [opened, setOpened] = useState(false);
|
|
169
|
-
const
|
|
38
|
+
const [appliedOptions, setAppliedOptions] = useState([]);
|
|
39
|
+
|
|
40
|
+
const handleClickOutsideContainer = () => {
|
|
41
|
+
setOpened(false);
|
|
42
|
+
actions.fields.searchTerm.set("");
|
|
43
|
+
onApply(selectedOptions);
|
|
44
|
+
};
|
|
45
|
+
const containerRef = useOutsideClickHook(() => handleClickOutsideContainer());
|
|
170
46
|
const dropdownRef = useRef(null);
|
|
171
47
|
const filterButtonRef = useRef(null);
|
|
172
48
|
const applyFilterButtonRef = useRef(null);
|
|
173
49
|
const filterDropdownID = `${name}-filter-dropdown`;
|
|
174
50
|
const checkboxListID = `${name}-checkbox-list`;
|
|
175
51
|
|
|
176
|
-
const backgroundColor = opened
|
|
177
|
-
? themeValues.primaryColor
|
|
178
|
-
: selectedOptions?.length
|
|
179
|
-
? themeValues.secondaryColor
|
|
180
|
-
: WHITE;
|
|
181
|
-
const contentColor = !opened && selectedOptions?.length ? WHITE : "#292A33";
|
|
182
|
-
|
|
183
|
-
const completeOptionsList = itemList
|
|
184
|
-
.slice()
|
|
185
|
-
.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
|
|
186
|
-
const selectValues = items => items.map(item => item.value);
|
|
187
|
-
const selectOption = selectedOption => {
|
|
188
|
-
if (selectValues(selectedOptions).includes(selectedOption.value)) {
|
|
189
|
-
const fewerOptions = selectedOptions.filter(
|
|
190
|
-
option => option.value !== selectedOption.value
|
|
191
|
-
);
|
|
192
|
-
setSelectedOptions(fewerOptions);
|
|
193
|
-
} else {
|
|
194
|
-
const moreOptions = selectedOptions.concat(selectedOption);
|
|
195
|
-
setSelectedOptions(moreOptions);
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
useEffect(() => setItemList(options), [options]);
|
|
200
|
-
|
|
201
52
|
useEffect(() => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
.includes(fields?.searchTerm?.rawValue?.toLowerCase())
|
|
206
|
-
);
|
|
207
|
-
// If no items are filtered, display the entire list of options.
|
|
208
|
-
if (filteredItems?.length) {
|
|
209
|
-
setItemList(filteredItems);
|
|
210
|
-
} else {
|
|
211
|
-
setItemList(options);
|
|
53
|
+
if (!opened) {
|
|
54
|
+
onApply(selectedOptions);
|
|
55
|
+
setAppliedOptions(selectedOptions);
|
|
212
56
|
}
|
|
213
|
-
}, [
|
|
57
|
+
}, [opened]);
|
|
214
58
|
|
|
215
59
|
useEffect(() => {
|
|
216
60
|
const handleKeyDown = event => {
|
|
@@ -238,22 +82,8 @@ const MultipleSelectFilter = ({
|
|
|
238
82
|
onApply(selectedOptions);
|
|
239
83
|
}
|
|
240
84
|
};
|
|
241
|
-
const handleClickOutside = event => {
|
|
242
|
-
if (
|
|
243
|
-
containerRef.current &&
|
|
244
|
-
!containerRef.current.contains(event.target) &&
|
|
245
|
-
dropdownRef.current &&
|
|
246
|
-
!dropdownRef.current.contains(event.target)
|
|
247
|
-
) {
|
|
248
|
-
setOpened(false);
|
|
249
|
-
actions.fields.searchTerm.set("");
|
|
250
|
-
onApply(selectedOptions);
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
254
85
|
document.addEventListener("keydown", handleKeyDown);
|
|
255
86
|
return () => {
|
|
256
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
257
87
|
document.removeEventListener("keydown", handleKeyDown);
|
|
258
88
|
};
|
|
259
89
|
}, []);
|
|
@@ -262,101 +92,53 @@ const MultipleSelectFilter = ({
|
|
|
262
92
|
<FilterContainer ref={containerRef} extraStyles={`${extraStyles}`}>
|
|
263
93
|
<FilterButton
|
|
264
94
|
ref={filterButtonRef}
|
|
265
|
-
|
|
95
|
+
btnContentOverride={btnContentOverride}
|
|
266
96
|
action={() => {
|
|
267
97
|
actions.fields.searchTerm.set("");
|
|
268
98
|
setOpened(!opened);
|
|
269
99
|
}}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
as="span"
|
|
288
|
-
style={{
|
|
289
|
-
display: "flex",
|
|
290
|
-
flexDirection: "row",
|
|
291
|
-
padding: "0 0.5rem 0 0.25rem"
|
|
292
|
-
}}
|
|
293
|
-
intrinsic
|
|
294
|
-
>
|
|
295
|
-
<Text
|
|
296
|
-
variant="pS"
|
|
297
|
-
color={contentColor}
|
|
298
|
-
extraStyles={`
|
|
299
|
-
white-space: nowrap;
|
|
300
|
-
overflow: hidden;
|
|
301
|
-
text-overflow: ellipsis;
|
|
302
|
-
${truncateBtnTextWidth && `max-width:` + truncateBtnTextWidth}
|
|
303
|
-
`}
|
|
304
|
-
>
|
|
305
|
-
{selectedOptions?.length
|
|
306
|
-
? `${filterLabel ? filterLabel + ": " : ""}${
|
|
307
|
-
selectedOptions[0].name
|
|
308
|
-
}`
|
|
309
|
-
: `${filterLabel ? filterLabel : ""}`}
|
|
310
|
-
</Text>
|
|
311
|
-
<Text color={contentColor} variant="pS">
|
|
312
|
-
{selectedOptions?.length && selectedOptions?.length > 1
|
|
313
|
-
? `, +${selectedOptions?.length - 1} More`
|
|
314
|
-
: ""}
|
|
315
|
-
</Text>
|
|
316
|
-
</Center>
|
|
317
|
-
<DropdownIconV2 color={contentColor} />
|
|
318
|
-
</Center>
|
|
319
|
-
)}
|
|
320
|
-
</FilterButton>
|
|
100
|
+
opened={opened}
|
|
101
|
+
backgroundColor={
|
|
102
|
+
opened
|
|
103
|
+
? themeValues.primaryColor
|
|
104
|
+
: selectedOptions?.length
|
|
105
|
+
? themeValues.secondaryColor
|
|
106
|
+
: WHITE
|
|
107
|
+
}
|
|
108
|
+
contentColor={!opened && selectedOptions?.length ? WHITE : CHARADE_GREY}
|
|
109
|
+
name={name}
|
|
110
|
+
filterDropdownID={filterDropdownID}
|
|
111
|
+
hasIcon={hasIcon}
|
|
112
|
+
icon={Icon}
|
|
113
|
+
truncateBtnTextWidth={truncateBtnTextWidth}
|
|
114
|
+
filterLabel={filterLabel}
|
|
115
|
+
selectedOptions={selectedOptions}
|
|
116
|
+
></FilterButton>
|
|
321
117
|
<FilterDropdown
|
|
322
118
|
id={filterDropdownID}
|
|
323
119
|
ref={dropdownRef}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
aria-expanded={opened}
|
|
327
|
-
aria-haspopup="listbox"
|
|
328
|
-
aria-owns={checkboxListID}
|
|
120
|
+
ariaOwns={checkboxListID}
|
|
121
|
+
opened={opened}
|
|
329
122
|
>
|
|
330
|
-
<
|
|
331
|
-
{searchable && options?.length > 8
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
disabled={disabled}
|
|
340
|
-
extraStyles={`
|
|
341
|
-
height: 2.875rem;
|
|
342
|
-
border: 0;
|
|
343
|
-
border-radius: 0;
|
|
344
|
-
padding: 0.45rem;
|
|
345
|
-
font-size: 0.875rem;
|
|
346
|
-
border-bottom: 1px solid ${GHOST_GREY};
|
|
347
|
-
`}
|
|
348
|
-
/>
|
|
349
|
-
)}
|
|
350
|
-
</Box>
|
|
351
|
-
<ScrollableOptionsList
|
|
123
|
+
<SearchBox
|
|
124
|
+
showSearchBox={searchable && options?.length > 8}
|
|
125
|
+
autocompleteValue={autocompleteValue}
|
|
126
|
+
fields={fields}
|
|
127
|
+
actions={actions}
|
|
128
|
+
placeholder={placeholder}
|
|
129
|
+
disabled={disabled}
|
|
130
|
+
></SearchBox>
|
|
131
|
+
<FilterableList
|
|
352
132
|
id={checkboxListID}
|
|
353
|
-
|
|
354
|
-
|
|
133
|
+
options={options}
|
|
134
|
+
appliedOptions={appliedOptions}
|
|
355
135
|
themeValues={themeValues}
|
|
356
|
-
|
|
136
|
+
selectedOptions={selectedOptions}
|
|
357
137
|
maxSelections={maxSelections}
|
|
358
138
|
name={name}
|
|
359
|
-
|
|
139
|
+
setSelectedOptions={setSelectedOptions}
|
|
140
|
+
searchTerm={fields?.searchTerm}
|
|
141
|
+
></FilterableList>
|
|
360
142
|
<Box
|
|
361
143
|
padding="0 0.5rem 0.0625rem 0.5rem"
|
|
362
144
|
extraStyles={`
|
|
@@ -367,42 +149,26 @@ const MultipleSelectFilter = ({
|
|
|
367
149
|
border-top: 1px solid ${GHOST_GREY};
|
|
368
150
|
`}
|
|
369
151
|
>
|
|
370
|
-
<
|
|
152
|
+
<ActionLinkButton
|
|
371
153
|
action={() => {
|
|
372
154
|
setOpened(false);
|
|
373
155
|
setSelectedOptions([]);
|
|
374
156
|
actions.fields.searchTerm.set("");
|
|
375
157
|
onClear();
|
|
376
158
|
}}
|
|
377
|
-
variant="tertiary"
|
|
378
|
-
extraStyles={`
|
|
379
|
-
padding: 0.2rem;
|
|
380
|
-
margin: 0.5rem;
|
|
381
|
-
min-height: auto;
|
|
382
|
-
min-width: auto;
|
|
383
|
-
`}
|
|
384
|
-
textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR};`}
|
|
385
159
|
text="Clear"
|
|
386
160
|
dataQa={`${name}-clear-filters`}
|
|
387
|
-
></
|
|
388
|
-
<
|
|
161
|
+
></ActionLinkButton>
|
|
162
|
+
<ActionLinkButton
|
|
389
163
|
ref={applyFilterButtonRef}
|
|
390
164
|
action={() => {
|
|
391
165
|
setOpened(false);
|
|
392
166
|
actions.fields.searchTerm.set("");
|
|
393
167
|
onApply(selectedOptions);
|
|
394
168
|
}}
|
|
395
|
-
variant="tertiary"
|
|
396
|
-
extraStyles={`
|
|
397
|
-
padding: 0.2rem;
|
|
398
|
-
margin: 0.5rem;
|
|
399
|
-
min-height: auto;
|
|
400
|
-
min-width: auto;
|
|
401
|
-
`}
|
|
402
|
-
textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR};`}
|
|
403
169
|
text="Apply"
|
|
404
170
|
dataQa={`${name}-apply-filters`}
|
|
405
|
-
></
|
|
171
|
+
></ActionLinkButton>
|
|
406
172
|
</Box>
|
|
407
173
|
</FilterDropdown>
|
|
408
174
|
</FilterContainer>
|
|
@@ -28,11 +28,11 @@ const StyledFilterDropdown = styled(Box)`
|
|
|
28
28
|
max-width: 18.625rem;
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
|
-
export const
|
|
31
|
+
export const FilterDropdownContainer = forwardRef((props, ref) => (
|
|
32
32
|
<StyledFilterDropdown ref={ref} {...props} />
|
|
33
33
|
));
|
|
34
34
|
|
|
35
|
-
const
|
|
35
|
+
const FilterButton = styled(ButtonWithAction)`
|
|
36
36
|
min-width: auto;
|
|
37
37
|
min-height: 2.3125rem;
|
|
38
38
|
margin: 0;
|
|
@@ -52,6 +52,6 @@ const StyledFilterButton = styled(ButtonWithAction)`
|
|
|
52
52
|
`}
|
|
53
53
|
`;
|
|
54
54
|
|
|
55
|
-
export const
|
|
56
|
-
<
|
|
55
|
+
export const StyledFilterButton = forwardRef((props, ref) => (
|
|
56
|
+
<FilterButton ref={ref} {...props} />
|
|
57
57
|
));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { ButtonWithAction } from "../../../atoms";
|
|
3
|
+
import { FONT_WEIGHT_REGULAR } from "../../../../constants/style_constants";
|
|
4
|
+
|
|
5
|
+
const ActionLinkButton = forwardRef(({ action, text, dataQa }, ref) => {
|
|
6
|
+
return (
|
|
7
|
+
<ButtonWithAction
|
|
8
|
+
ref={ref}
|
|
9
|
+
action={action}
|
|
10
|
+
variant="tertiary"
|
|
11
|
+
extraStyles={`
|
|
12
|
+
padding: 0.2rem;
|
|
13
|
+
margin: 0.5rem;
|
|
14
|
+
min-height: auto;
|
|
15
|
+
min-width: auto;
|
|
16
|
+
`}
|
|
17
|
+
textExtraStyles={`font-weight: ${FONT_WEIGHT_REGULAR};`}
|
|
18
|
+
text={text}
|
|
19
|
+
dataQa={dataQa}
|
|
20
|
+
></ButtonWithAction>
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export default ActionLinkButton;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { Text, Center } from "../../../atoms";
|
|
3
|
+
import DropdownIconV2 from "../../../atoms/dropdown/DropdownIconV2";
|
|
4
|
+
import { StyledFilterButton } from "../MultipleSelectFilter.styled";
|
|
5
|
+
import { noop } from "../../../../util/general";
|
|
6
|
+
|
|
7
|
+
const FilterButton = forwardRef(
|
|
8
|
+
(
|
|
9
|
+
{
|
|
10
|
+
btnContentOverride,
|
|
11
|
+
action = noop,
|
|
12
|
+
opened,
|
|
13
|
+
backgroundColor,
|
|
14
|
+
contentColor,
|
|
15
|
+
name,
|
|
16
|
+
filterDropdownID,
|
|
17
|
+
hasIcon = false,
|
|
18
|
+
icon: Icon,
|
|
19
|
+
truncateBtnTextWidth,
|
|
20
|
+
filterLabel,
|
|
21
|
+
selectedOptions
|
|
22
|
+
},
|
|
23
|
+
ref
|
|
24
|
+
) => {
|
|
25
|
+
return (
|
|
26
|
+
<StyledFilterButton
|
|
27
|
+
ref={ref}
|
|
28
|
+
variant="tertiary"
|
|
29
|
+
action={action}
|
|
30
|
+
aria-haspopup="listbox"
|
|
31
|
+
aria-expanded={opened}
|
|
32
|
+
aria-controls={filterDropdownID}
|
|
33
|
+
backgroundColor={backgroundColor}
|
|
34
|
+
dataQa={`${name}-filter-button`}
|
|
35
|
+
contentOverride
|
|
36
|
+
>
|
|
37
|
+
{btnContentOverride ? (
|
|
38
|
+
btnContentOverride
|
|
39
|
+
) : (
|
|
40
|
+
<Center
|
|
41
|
+
as="span"
|
|
42
|
+
style={{ display: "flex", flexDirection: "row" }}
|
|
43
|
+
intrinsic
|
|
44
|
+
>
|
|
45
|
+
{hasIcon && <Icon color={contentColor} />}
|
|
46
|
+
<Center
|
|
47
|
+
as="span"
|
|
48
|
+
style={{
|
|
49
|
+
display: "flex",
|
|
50
|
+
flexDirection: "row",
|
|
51
|
+
padding: "0 0.5rem 0 0.25rem"
|
|
52
|
+
}}
|
|
53
|
+
intrinsic
|
|
54
|
+
>
|
|
55
|
+
<Text
|
|
56
|
+
variant="pS"
|
|
57
|
+
color={contentColor}
|
|
58
|
+
extraStyles={`
|
|
59
|
+
white-space: nowrap;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
text-overflow: ellipsis;
|
|
62
|
+
${truncateBtnTextWidth && `max-width:` + truncateBtnTextWidth}
|
|
63
|
+
`}
|
|
64
|
+
>
|
|
65
|
+
{selectedOptions?.length
|
|
66
|
+
? `${filterLabel ? filterLabel + ": " : ""}${
|
|
67
|
+
selectedOptions[0].name
|
|
68
|
+
}`
|
|
69
|
+
: `${filterLabel ? filterLabel : ""}`}
|
|
70
|
+
</Text>
|
|
71
|
+
<Text color={contentColor} variant="pS">
|
|
72
|
+
{selectedOptions?.length && selectedOptions?.length > 1
|
|
73
|
+
? `, +${selectedOptions?.length - 1} More`
|
|
74
|
+
: ""}
|
|
75
|
+
</Text>
|
|
76
|
+
</Center>
|
|
77
|
+
<DropdownIconV2 color={contentColor} />
|
|
78
|
+
</Center>
|
|
79
|
+
)}
|
|
80
|
+
</StyledFilterButton>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
export default FilterButton;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { FilterDropdownContainer } from "../MultipleSelectFilter.styled";
|
|
3
|
+
|
|
4
|
+
const FilterDropdown = forwardRef(({ id, ariaOwns, opened, children }, ref) => {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
{opened && (
|
|
8
|
+
<FilterDropdownContainer
|
|
9
|
+
ref={ref}
|
|
10
|
+
id={id}
|
|
11
|
+
role="combobox"
|
|
12
|
+
aria-expanded={opened}
|
|
13
|
+
aria-haspopup="listbox"
|
|
14
|
+
aria-owns={ariaOwns}
|
|
15
|
+
>
|
|
16
|
+
{children}
|
|
17
|
+
</FilterDropdownContainer>
|
|
18
|
+
)}
|
|
19
|
+
</>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default FilterDropdown;
|