@ultraviolet/ui 1.49.0 → 1.51.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.d.ts +7 -17
- package/dist/src/components/SelectInputV2/Dropdown.js +35 -34
- package/dist/src/components/SelectInputV2/SearchBarDropdown.js +14 -5
- package/dist/src/components/SelectInputV2/SelectBar.js +53 -50
- package/dist/src/components/SelectInputV2/SelectInputProvider.js +7 -4
- package/dist/src/components/SelectInputV2/index.js +1 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3534,7 +3534,7 @@ type OptionType = {
|
|
|
3534
3534
|
};
|
|
3535
3535
|
type DataType = Record<string, OptionType[]> | OptionType[];
|
|
3536
3536
|
|
|
3537
|
-
type SelectInputV2Props = {
|
|
3537
|
+
type SelectInputV2Props<IsMulti extends undefined | boolean = false> = {
|
|
3538
3538
|
/**
|
|
3539
3539
|
* Input name
|
|
3540
3540
|
*/
|
|
@@ -3631,31 +3631,21 @@ type SelectInputV2Props = {
|
|
|
3631
3631
|
*/
|
|
3632
3632
|
selectAllGroup?: boolean;
|
|
3633
3633
|
autofocus?: boolean;
|
|
3634
|
-
'data-testid'?: string;
|
|
3635
|
-
onChange?: (value: string[]) => void;
|
|
3636
|
-
} & Pick<HTMLAttributes<HTMLDivElement>, 'id' | 'onBlur' | 'onFocus' | 'aria-label' | 'className'> & ({
|
|
3637
|
-
/**
|
|
3638
|
-
* Whether it is possible to select multiple options
|
|
3639
|
-
*/
|
|
3640
|
-
multiselect: true;
|
|
3641
|
-
/**
|
|
3642
|
-
* Default value, must be one of the options
|
|
3643
|
-
*/
|
|
3644
|
-
value?: string[];
|
|
3645
|
-
} | {
|
|
3646
3634
|
/**
|
|
3647
3635
|
* Whether it is possible to select multiple options
|
|
3648
3636
|
*/
|
|
3649
|
-
multiselect?:
|
|
3637
|
+
multiselect?: IsMulti;
|
|
3650
3638
|
/**
|
|
3651
3639
|
* Default value, must be one of the options
|
|
3652
3640
|
*/
|
|
3653
|
-
value?: string;
|
|
3654
|
-
|
|
3641
|
+
value?: IsMulti extends true ? string[] : string;
|
|
3642
|
+
onChange?: IsMulti extends true ? (value: string[]) => void : (value: string) => void;
|
|
3643
|
+
'data-testid'?: string;
|
|
3644
|
+
} & Pick<HTMLAttributes<HTMLDivElement>, 'id' | 'onBlur' | 'onFocus' | 'aria-label' | 'className'>;
|
|
3655
3645
|
/**
|
|
3656
3646
|
* SelectInputV2 component is used to select one or many elements from a selection.
|
|
3657
3647
|
*/
|
|
3658
|
-
declare const SelectInputV2: ({ name, id, onBlur, onFocus, onChange, "aria-label": ariaLabel, value, label, helper, options, size, emptyState, descriptionDirection, success, error, "data-testid": dataTestId, className, footer, placeholderSearch, placeholder, searchable, disabled, readOnly, clearable, multiselect, required, labelDescription, autofocus, loadMore, optionalInfoPlacement, isLoading, selectAll, selectAllGroup, }: SelectInputV2Props) => _emotion_react_jsx_runtime.JSX.Element;
|
|
3648
|
+
declare const SelectInputV2: <IsMulti extends boolean | undefined>({ name, id, onBlur, onFocus, onChange, "aria-label": ariaLabel, value, label, helper, options, size, emptyState, descriptionDirection, success, error, "data-testid": dataTestId, className, footer, placeholderSearch, placeholder, searchable, disabled, readOnly, clearable, multiselect, required, labelDescription, autofocus, loadMore, optionalInfoPlacement, isLoading, selectAll, selectAllGroup, }: SelectInputV2Props<IsMulti>) => _emotion_react_jsx_runtime.JSX.Element;
|
|
3659
3649
|
|
|
3660
3650
|
declare const getUUID: (prefix?: string) => string;
|
|
3661
3651
|
|
|
@@ -207,7 +207,6 @@ const CreateDropdown = ({
|
|
|
207
207
|
isEmpty,
|
|
208
208
|
emptyState,
|
|
209
209
|
descriptionDirection,
|
|
210
|
-
onChange,
|
|
211
210
|
loadMore,
|
|
212
211
|
optionalInfoPlacement,
|
|
213
212
|
defaultSearchValue,
|
|
@@ -215,6 +214,7 @@ const CreateDropdown = ({
|
|
|
215
214
|
}) => {
|
|
216
215
|
const {
|
|
217
216
|
setIsDropdownVisible,
|
|
217
|
+
onChange,
|
|
218
218
|
options,
|
|
219
219
|
multiselect,
|
|
220
220
|
selectAll,
|
|
@@ -253,44 +253,48 @@ const CreateDropdown = ({
|
|
|
253
253
|
onChange?.([...selectedData.selectedValues, clickedOption.value]);
|
|
254
254
|
}
|
|
255
255
|
} else {
|
|
256
|
-
onChange?.(
|
|
256
|
+
onChange?.(clickedOption.value);
|
|
257
257
|
}
|
|
258
258
|
setIsDropdownVisible(multiselect); // hide the dropdown on click when single select only
|
|
259
259
|
};
|
|
260
260
|
const selectAllOptions = () => {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
onChange
|
|
266
|
-
|
|
267
|
-
const allValues = [];
|
|
268
|
-
if (!Array.isArray(options)) {
|
|
269
|
-
Object.keys(options).map(group => options[group].map(option => {
|
|
270
|
-
if (!option.disabled) {
|
|
271
|
-
allValues.push(option);
|
|
272
|
-
}
|
|
273
|
-
return null;
|
|
274
|
-
}));
|
|
261
|
+
if (multiselect) {
|
|
262
|
+
setSelectedData({
|
|
263
|
+
type: 'selectAll'
|
|
264
|
+
});
|
|
265
|
+
if (selectedData.allSelected && onChange) {
|
|
266
|
+
onChange([]);
|
|
275
267
|
} else {
|
|
276
|
-
|
|
268
|
+
const allValues = [];
|
|
269
|
+
if (!Array.isArray(options)) {
|
|
270
|
+
Object.keys(options).map(group => options[group].map(option => {
|
|
271
|
+
if (!option.disabled) {
|
|
272
|
+
allValues.push(option);
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}));
|
|
276
|
+
} else {
|
|
277
|
+
options.map(option => allValues.push(option));
|
|
278
|
+
}
|
|
279
|
+
onChange?.(allValues.map(value => value.value));
|
|
277
280
|
}
|
|
278
|
-
onChange?.(allValues.map(value => value.value));
|
|
279
281
|
}
|
|
280
282
|
};
|
|
281
283
|
const handleSelectGroup = group => {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
284
|
+
if (multiselect) {
|
|
285
|
+
setSelectedData({
|
|
286
|
+
type: 'selectGroup',
|
|
287
|
+
selectedGroup: group
|
|
288
|
+
});
|
|
289
|
+
if (!Array.isArray(options)) {
|
|
290
|
+
if (selectedData.selectedGroups.includes(group)) {
|
|
291
|
+
const newSelectedValues = [...selectedData.selectedValues].filter(selectedValue => !options[group].find(option => option.value === selectedValue));
|
|
292
|
+
onChange?.(newSelectedValues);
|
|
293
|
+
} else {
|
|
294
|
+
const newSelectedValues = [...selectedData.selectedValues];
|
|
295
|
+
options[group].map(option => newSelectedValues.includes(option.value) || option.disabled ? null : newSelectedValues.push(option.value));
|
|
296
|
+
onChange?.(newSelectedValues);
|
|
297
|
+
}
|
|
294
298
|
}
|
|
295
299
|
}
|
|
296
300
|
};
|
|
@@ -504,7 +508,6 @@ const Dropdown = ({
|
|
|
504
508
|
searchable,
|
|
505
509
|
placeholder,
|
|
506
510
|
footer,
|
|
507
|
-
onChange,
|
|
508
511
|
refSelect,
|
|
509
512
|
loadMore,
|
|
510
513
|
optionalInfoPlacement,
|
|
@@ -562,13 +565,11 @@ const Dropdown = ({
|
|
|
562
565
|
children: [searchable && !isLoading ? jsx(SearchBarDropdown, {
|
|
563
566
|
placeholder: placeholder,
|
|
564
567
|
displayedOptions: displayedOptions,
|
|
565
|
-
setSearchBarActive: setSearchBarActive
|
|
566
|
-
onChange: onChange
|
|
568
|
+
setSearchBarActive: setSearchBarActive
|
|
567
569
|
}) : null, jsx(CreateDropdown, {
|
|
568
570
|
isEmpty: isEmpty,
|
|
569
571
|
emptyState: emptyState,
|
|
570
572
|
descriptionDirection: descriptionDirection,
|
|
571
|
-
onChange: onChange,
|
|
572
573
|
loadMore: loadMore,
|
|
573
574
|
optionalInfoPlacement: optionalInfoPlacement,
|
|
574
575
|
defaultSearchValue: defaultSearchValue,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _styled from '@emotion/styled/base';
|
|
2
2
|
import { Icon } from '@ultraviolet/icons';
|
|
3
|
+
import { useRef, useEffect } from 'react';
|
|
3
4
|
import { TextInputV2 } from '../TextInputV2/index.js';
|
|
4
5
|
import { useSelectInput } from './SelectInputProvider.js';
|
|
5
6
|
import { jsx } from '@emotion/react/jsx-runtime';
|
|
@@ -41,10 +42,11 @@ const findClosestOption = (options, searchInput) => {
|
|
|
41
42
|
const SearchBarDropdown = ({
|
|
42
43
|
placeholder,
|
|
43
44
|
displayedOptions,
|
|
44
|
-
setSearchBarActive
|
|
45
|
-
onChange
|
|
45
|
+
setSearchBarActive
|
|
46
46
|
}) => {
|
|
47
|
+
const searchInputRef = useRef(null);
|
|
47
48
|
const {
|
|
49
|
+
onChange,
|
|
48
50
|
onSearch,
|
|
49
51
|
setSearchInput,
|
|
50
52
|
searchInput,
|
|
@@ -92,11 +94,18 @@ const SearchBarDropdown = ({
|
|
|
92
94
|
type: 'selectOption',
|
|
93
95
|
clickedOption: closestOption
|
|
94
96
|
});
|
|
95
|
-
onChange?.(selectedData.selectedValues);
|
|
97
|
+
onChange?.(selectedData.selectedValues[0] ?? '');
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
}
|
|
99
101
|
};
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
// TODO: Remove me and use autoFocus when popup is fixed
|
|
104
|
+
// Explanation : Actually the component render at -999px -999px then it will be placed according to child position and it broke the autoFocus (scroll -999px to top)
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
searchInputRef.current?.focus();
|
|
107
|
+
}, 50);
|
|
108
|
+
}, []);
|
|
100
109
|
return jsx(StyledInput, {
|
|
101
110
|
value: searchInput,
|
|
102
111
|
onChange: event => handleChange(event),
|
|
@@ -110,9 +119,9 @@ const SearchBarDropdown = ({
|
|
|
110
119
|
sentiment: "neutral"
|
|
111
120
|
}),
|
|
112
121
|
onKeyDown: event => handleKeyDown(event.key, searchInput),
|
|
113
|
-
autoFocus: true,
|
|
114
122
|
size: "medium",
|
|
115
|
-
"aria-label": "search-bar"
|
|
123
|
+
"aria-label": "search-bar",
|
|
124
|
+
ref: searchInputRef
|
|
116
125
|
});
|
|
117
126
|
};
|
|
118
127
|
|
|
@@ -72,52 +72,56 @@ const StyledPlaceholder = /*#__PURE__*/_styled(Text, {
|
|
|
72
72
|
}) => theme.colors.neutral.textWeakDisabled, ";}");
|
|
73
73
|
const isValidSelectedValue = (selectedValue, options) => !Array.isArray(options) ? Object.keys(options).some(group => options[group].some(option => option.value === selectedValue && !option.disabled)) : options.some(option => option.value === selectedValue && !option.disabled);
|
|
74
74
|
const DisplayValues = ({
|
|
75
|
-
multiselect,
|
|
76
75
|
refTag,
|
|
77
76
|
nonOverflowedValues,
|
|
78
77
|
disabled,
|
|
79
78
|
readOnly,
|
|
80
|
-
onChange,
|
|
81
79
|
overflowed,
|
|
82
80
|
overflowAmount,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
})
|
|
81
|
+
size
|
|
82
|
+
}) => {
|
|
83
|
+
const {
|
|
84
|
+
multiselect,
|
|
85
|
+
selectedData,
|
|
86
|
+
setSelectedData,
|
|
87
|
+
options,
|
|
88
|
+
onChange
|
|
89
|
+
} = useSelectInput();
|
|
90
|
+
return multiselect ? jsxs(Stack, {
|
|
91
|
+
direction: "row",
|
|
92
|
+
gap: "1",
|
|
93
|
+
wrap: "nowrap",
|
|
94
|
+
ref: refTag,
|
|
95
|
+
alignItems: "center",
|
|
96
|
+
children: [nonOverflowedValues.map(option => jsx(CustomTag, {
|
|
97
|
+
"data-testid": "selected-options-tags",
|
|
98
|
+
sentiment: "neutral",
|
|
99
|
+
disabled: disabled,
|
|
100
|
+
onClose: !readOnly ? event => {
|
|
101
|
+
event.stopPropagation();
|
|
102
|
+
setSelectedData({
|
|
103
|
+
type: 'selectOption',
|
|
104
|
+
clickedOption: option
|
|
105
|
+
});
|
|
106
|
+
const newSelectedValues = selectedData.selectedValues?.filter(val => val !== option.value);
|
|
107
|
+
onChange?.(newSelectedValues);
|
|
108
|
+
} : undefined,
|
|
109
|
+
children: option?.label
|
|
110
|
+
}, option?.value)), overflowed ? jsxs(Tag, {
|
|
111
|
+
sentiment: "neutral",
|
|
112
|
+
disabled: disabled,
|
|
113
|
+
"data-testid": "plus-tag",
|
|
114
|
+
"aria-label": "Plus tag",
|
|
115
|
+
children: [jsx(Icon, {
|
|
116
|
+
name: "plus"
|
|
117
|
+
}), overflowAmount]
|
|
118
|
+
}, "+") : null]
|
|
119
|
+
}) : jsx(Text, {
|
|
120
|
+
as: "p",
|
|
121
|
+
variant: size === 'large' ? 'body' : 'bodySmall',
|
|
122
|
+
children: selectedData.selectedValues[0] ? findOptionInOptions(options, selectedData.selectedValues[0])?.label : null
|
|
123
|
+
});
|
|
124
|
+
};
|
|
121
125
|
const SelectBar = ({
|
|
122
126
|
size,
|
|
123
127
|
clearable,
|
|
@@ -126,17 +130,17 @@ const SelectBar = ({
|
|
|
126
130
|
placeholder,
|
|
127
131
|
success,
|
|
128
132
|
error,
|
|
129
|
-
onChange,
|
|
130
133
|
autoFocus,
|
|
131
134
|
innerRef
|
|
132
135
|
}) => {
|
|
133
136
|
const {
|
|
134
137
|
isDropdownVisible,
|
|
138
|
+
onChange,
|
|
135
139
|
setIsDropdownVisible,
|
|
136
140
|
options,
|
|
137
|
-
multiselect,
|
|
138
141
|
selectedData,
|
|
139
|
-
setSelectedData
|
|
142
|
+
setSelectedData,
|
|
143
|
+
multiselect
|
|
140
144
|
} = useSelectInput();
|
|
141
145
|
const openable = !(readOnly || disabled);
|
|
142
146
|
const refTag = useRef(null);
|
|
@@ -223,18 +227,13 @@ const SelectBar = ({
|
|
|
223
227
|
"aria-controls": "select-dropdown",
|
|
224
228
|
tabIndex: 0,
|
|
225
229
|
children: [selectedData.selectedValues.length > 0 ? jsx(DisplayValues, {
|
|
226
|
-
multiselect: multiselect,
|
|
227
230
|
refTag: refTag,
|
|
228
231
|
nonOverflowedValues: nonOverflowedValues,
|
|
229
232
|
disabled: disabled,
|
|
230
233
|
readOnly: readOnly,
|
|
231
|
-
selectedData: selectedData,
|
|
232
|
-
setSelectedData: setSelectedData,
|
|
233
|
-
onChange: onChange,
|
|
234
234
|
overflowed: overflowed,
|
|
235
235
|
overflowAmount: overflowAmount,
|
|
236
|
-
size: size
|
|
237
|
-
options: options
|
|
236
|
+
size: size
|
|
238
237
|
}) : jsx(StyledPlaceholder, {
|
|
239
238
|
as: "p",
|
|
240
239
|
variant: size === 'large' ? 'body' : 'bodySmall',
|
|
@@ -261,7 +260,11 @@ const SelectBar = ({
|
|
|
261
260
|
setSelectedData({
|
|
262
261
|
type: 'clearAll'
|
|
263
262
|
});
|
|
264
|
-
|
|
263
|
+
if (multiselect) {
|
|
264
|
+
onChange?.([]);
|
|
265
|
+
} else {
|
|
266
|
+
onChange?.('');
|
|
267
|
+
}
|
|
265
268
|
},
|
|
266
269
|
sentiment: "neutral",
|
|
267
270
|
"data-testid": "clear-all"
|
|
@@ -20,7 +20,8 @@ const SelectInputContext = /*#__PURE__*/createContext({
|
|
|
20
20
|
selectedGroups: [],
|
|
21
21
|
selectedValues: []
|
|
22
22
|
},
|
|
23
|
-
setSelectedData: () => {}
|
|
23
|
+
setSelectedData: () => {},
|
|
24
|
+
onChange: () => {}
|
|
24
25
|
});
|
|
25
26
|
const useSelectInput = () => useContext(SelectInputContext);
|
|
26
27
|
const SelectInputProvider = ({
|
|
@@ -30,7 +31,8 @@ const SelectInputProvider = ({
|
|
|
30
31
|
value,
|
|
31
32
|
selectAllGroup,
|
|
32
33
|
numberOfOptions,
|
|
33
|
-
children
|
|
34
|
+
children,
|
|
35
|
+
onChange
|
|
34
36
|
}) => {
|
|
35
37
|
const currentValue = useMemo(() => {
|
|
36
38
|
if (value) {
|
|
@@ -155,8 +157,9 @@ const SelectInputProvider = ({
|
|
|
155
157
|
numberOfOptions,
|
|
156
158
|
displayedOptions,
|
|
157
159
|
selectedData,
|
|
158
|
-
setSelectedData
|
|
159
|
-
|
|
160
|
+
setSelectedData,
|
|
161
|
+
onChange
|
|
162
|
+
}), [displayedOptions, isDropdownVisible, multiselect, numberOfOptions, options, searchInput, selectAll, selectAllGroup, selectedData, onChange]);
|
|
160
163
|
return jsx(SelectInputContext.Provider, {
|
|
161
164
|
value: providerValue,
|
|
162
165
|
children: children
|
|
@@ -72,6 +72,7 @@ const SelectInputV2 = ({
|
|
|
72
72
|
value: value,
|
|
73
73
|
selectAllGroup: selectAllGroup,
|
|
74
74
|
numberOfOptions: numberOfOptions,
|
|
75
|
+
onChange: onChange,
|
|
75
76
|
children: jsxs(SelectInputContainer, {
|
|
76
77
|
id: id,
|
|
77
78
|
onBlur: onBlur,
|
|
@@ -85,7 +86,6 @@ const SelectInputV2 = ({
|
|
|
85
86
|
searchable: searchable,
|
|
86
87
|
placeholder: placeholderSearch,
|
|
87
88
|
footer: footer,
|
|
88
|
-
onChange: onChange,
|
|
89
89
|
refSelect: ref,
|
|
90
90
|
loadMore: loadMore,
|
|
91
91
|
optionalInfoPlacement: optionalInfoPlacement,
|
|
@@ -113,7 +113,6 @@ const SelectInputV2 = ({
|
|
|
113
113
|
placeholder: placeholder,
|
|
114
114
|
success: success,
|
|
115
115
|
error: error,
|
|
116
|
-
onChange: onChange,
|
|
117
116
|
autoFocus: autofocus,
|
|
118
117
|
innerRef: ref
|
|
119
118
|
})]
|