@rhc-shared-components/form-multi-select-component 1.0.3 → 1.0.4
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/FormMultiSelectInput.d.ts +19 -20
- package/dist/index.d.ts +2 -2
- package/dist/index.js +150 -81
- package/dist/index.modern.js +140 -69
- package/dist/index.test.d.ts +1 -1
- package/package.json +2 -2
- package/CHANGELOG.md +0 -65
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { SelectOptionProps } from '@patternfly/react-core';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export { FormMultiSelectInput, IMultiSelectInputOptionProps };
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SelectOptionProps } from '@patternfly/react-core';
|
|
3
|
+
export interface FormMultiSelectInputProps {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string;
|
|
6
|
+
isRequired?: boolean;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
selectMenuOptions: SelectOptionProps[];
|
|
9
|
+
ariaLabel?: string;
|
|
10
|
+
helperText?: string;
|
|
11
|
+
maxHeight?: string;
|
|
12
|
+
isDisabled?: boolean;
|
|
13
|
+
classNames?: string;
|
|
14
|
+
menuAppendTo?: HTMLElement | (() => HTMLElement) | 'inline' | 'parent';
|
|
15
|
+
extraProps?: any;
|
|
16
|
+
isScrollable?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare const FormMultiSelectInput: React.FunctionComponent<FormMultiSelectInputProps>;
|
|
19
|
+
export { FormMultiSelectInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { FormMultiSelectInput
|
|
2
|
-
export { FormMultiSelectInput
|
|
1
|
+
import { FormMultiSelectInput } from './FormMultiSelectInput';
|
|
2
|
+
export { FormMultiSelectInput };
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,24 @@ function _interopNamespace(e) {
|
|
|
26
26
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
27
27
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
28
28
|
|
|
29
|
+
function _extends() {
|
|
30
|
+
_extends = Object.assign || function (target) {
|
|
31
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
32
|
+
var source = arguments[i];
|
|
33
|
+
|
|
34
|
+
for (var key in source) {
|
|
35
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
36
|
+
target[key] = source[key];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return target;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return _extends.apply(this, arguments);
|
|
45
|
+
}
|
|
46
|
+
|
|
29
47
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
30
48
|
if (source == null) return {};
|
|
31
49
|
var target = {};
|
|
@@ -120,7 +138,8 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
120
138
|
placeholder = _ref.placeholder,
|
|
121
139
|
helperText = _ref.helperText,
|
|
122
140
|
maxHeight = _ref.maxHeight,
|
|
123
|
-
isDisabled = _ref.isDisabled,
|
|
141
|
+
_ref$isDisabled = _ref.isDisabled,
|
|
142
|
+
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
|
|
124
143
|
menuAppendTo = _ref.menuAppendTo,
|
|
125
144
|
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
126
145
|
|
|
@@ -155,10 +174,11 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
155
174
|
setFocusedItemIndex = _React$useState5[1];
|
|
156
175
|
|
|
157
176
|
var _React$useState6 = React__default["default"].useState(null),
|
|
158
|
-
|
|
159
|
-
|
|
177
|
+
activeItemId = _React$useState6[0],
|
|
178
|
+
setActiveItemId = _React$useState6[1];
|
|
160
179
|
|
|
161
180
|
var textInputRef = React__default["default"].useRef();
|
|
181
|
+
var NO_RESULTS = 'no results';
|
|
162
182
|
React__default["default"].useEffect(function () {
|
|
163
183
|
var newSelectOptions = selectMenuOptions; // Filter menu items based on the text input value when one exists
|
|
164
184
|
|
|
@@ -169,9 +189,9 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
169
189
|
|
|
170
190
|
if (!newSelectOptions.length) {
|
|
171
191
|
newSelectOptions = [{
|
|
172
|
-
|
|
192
|
+
isAriaDisabled: true,
|
|
173
193
|
children: "No results found for \"" + inputValue + "\"",
|
|
174
|
-
value:
|
|
194
|
+
value: NO_RESULTS
|
|
175
195
|
}];
|
|
176
196
|
} // Open the menu when the input value changes and the new value is not empty
|
|
177
197
|
|
|
@@ -182,8 +202,7 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
182
202
|
}
|
|
183
203
|
|
|
184
204
|
setSelectOptions(newSelectOptions);
|
|
185
|
-
|
|
186
|
-
}, [inputValue, selectMenuOptions]);
|
|
205
|
+
}, [inputValue]);
|
|
187
206
|
React__default["default"].useEffect(function () {
|
|
188
207
|
if ((value == null ? void 0 : value.length) > 0) {
|
|
189
208
|
setFieldValue(rest.name, value, true);
|
|
@@ -191,62 +210,120 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
191
210
|
}
|
|
192
211
|
}, []);
|
|
193
212
|
|
|
213
|
+
var createItemId = function createItemId(value) {
|
|
214
|
+
return "select-multi-typeahead-" + value.replace(' ', '-');
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
var setActiveAndFocusedItem = function setActiveAndFocusedItem(itemIndex) {
|
|
218
|
+
setFocusedItemIndex(itemIndex);
|
|
219
|
+
var focusedItem = selectOptions[itemIndex];
|
|
220
|
+
setActiveItemId(createItemId(focusedItem.value));
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
var resetActiveAndFocusedItem = function resetActiveAndFocusedItem() {
|
|
224
|
+
setFocusedItemIndex(null);
|
|
225
|
+
setActiveItemId(null);
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
var closeMenu = function closeMenu() {
|
|
229
|
+
setIsOpen(false);
|
|
230
|
+
resetActiveAndFocusedItem();
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
var onInputClick = function onInputClick() {
|
|
234
|
+
if (!isOpen) {
|
|
235
|
+
setIsOpen(true);
|
|
236
|
+
} else if (!inputValue) {
|
|
237
|
+
closeMenu();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
var _onSelect = function onSelect(value) {
|
|
242
|
+
var _textInputRef$current;
|
|
243
|
+
|
|
244
|
+
if (value && value !== NO_RESULTS) {
|
|
245
|
+
var selectedValues = selected.includes(value) ? selected.filter(function (selection) {
|
|
246
|
+
return selection !== value;
|
|
247
|
+
}) : [].concat(selected, [value]);
|
|
248
|
+
setSelected(selectedValues);
|
|
249
|
+
setFieldTouched(rest.name, true, false);
|
|
250
|
+
setFieldValue(rest.name, selectedValues, true);
|
|
251
|
+
} // eslint-disable-next-line no-unused-expressions
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
(_textInputRef$current = textInputRef.current) == null ? void 0 : _textInputRef$current.focus();
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
var onTextInputChange = function onTextInputChange(_event, value) {
|
|
258
|
+
setInputValue(value);
|
|
259
|
+
resetActiveAndFocusedItem();
|
|
260
|
+
};
|
|
261
|
+
|
|
194
262
|
var handleMenuArrowKeys = function handleMenuArrowKeys(key) {
|
|
195
263
|
var indexToFocus = 0;
|
|
196
264
|
|
|
197
|
-
if (isOpen) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
265
|
+
if (!isOpen) {
|
|
266
|
+
setIsOpen(true);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (selectOptions.every(function (option) {
|
|
270
|
+
return option.isDisabled;
|
|
271
|
+
})) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (key === 'ArrowUp') {
|
|
276
|
+
// When no index is set or at the first index, focus to the last, otherwise decrement focus index
|
|
277
|
+
if (focusedItemIndex === null || focusedItemIndex === 0) {
|
|
278
|
+
indexToFocus = selectOptions.length - 1;
|
|
279
|
+
} else {
|
|
280
|
+
indexToFocus = focusedItemIndex - 1;
|
|
281
|
+
} // Skip disabled options
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
285
|
+
indexToFocus--;
|
|
286
|
+
|
|
287
|
+
if (indexToFocus === -1) {
|
|
201
288
|
indexToFocus = selectOptions.length - 1;
|
|
202
|
-
} else {
|
|
203
|
-
indexToFocus = focusedItemIndex - 1;
|
|
204
289
|
}
|
|
205
290
|
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (key === 'ArrowDown') {
|
|
294
|
+
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
295
|
+
if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
|
|
296
|
+
indexToFocus = 0;
|
|
297
|
+
} else {
|
|
298
|
+
indexToFocus = focusedItemIndex + 1;
|
|
299
|
+
} // Skip disabled options
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
303
|
+
indexToFocus++;
|
|
206
304
|
|
|
207
|
-
|
|
208
|
-
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
209
|
-
if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
|
|
305
|
+
if (indexToFocus === selectOptions.length) {
|
|
210
306
|
indexToFocus = 0;
|
|
211
|
-
} else {
|
|
212
|
-
indexToFocus = focusedItemIndex + 1;
|
|
213
307
|
}
|
|
214
308
|
}
|
|
215
|
-
|
|
216
|
-
setFocusedItemIndex(indexToFocus);
|
|
217
|
-
var focusedItem = selectOptions.filter(function (option) {
|
|
218
|
-
return !option.isDisabled;
|
|
219
|
-
})[indexToFocus];
|
|
220
|
-
setActiveItem("select-multi-typeahead-" + focusedItem.value.replace(' ', '-'));
|
|
221
309
|
}
|
|
310
|
+
|
|
311
|
+
setActiveAndFocusedItem(indexToFocus);
|
|
222
312
|
};
|
|
223
313
|
|
|
224
314
|
var onInputKeyDown = function onInputKeyDown(event) {
|
|
225
|
-
var
|
|
226
|
-
return !menuItem.isDisabled;
|
|
227
|
-
});
|
|
228
|
-
var firstMenuItem = enabledMenuItems[0];
|
|
229
|
-
var focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
|
|
315
|
+
var focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
|
|
230
316
|
|
|
231
317
|
switch (event.key) {
|
|
232
|
-
// Select the first available option
|
|
233
318
|
case 'Enter':
|
|
234
|
-
if (!
|
|
235
|
-
setIsOpen(function (prevIsOpen) {
|
|
236
|
-
return !prevIsOpen;
|
|
237
|
-
});
|
|
238
|
-
} else if (isOpen && focusedItem.value !== 'no results') {
|
|
239
|
-
event.preventDefault();
|
|
240
|
-
|
|
319
|
+
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
|
|
241
320
|
_onSelect(focusedItem.value);
|
|
242
321
|
}
|
|
243
322
|
|
|
244
|
-
|
|
323
|
+
if (!isOpen) {
|
|
324
|
+
setIsOpen(true);
|
|
325
|
+
}
|
|
245
326
|
|
|
246
|
-
case 'Tab':
|
|
247
|
-
case 'Escape':
|
|
248
|
-
setIsOpen(false);
|
|
249
|
-
setActiveItem(null);
|
|
250
327
|
break;
|
|
251
328
|
|
|
252
329
|
case 'ArrowUp':
|
|
@@ -258,36 +335,35 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
258
335
|
};
|
|
259
336
|
|
|
260
337
|
var onToggleClick = function onToggleClick() {
|
|
261
|
-
|
|
262
|
-
};
|
|
338
|
+
var _textInputRef$current2;
|
|
263
339
|
|
|
264
|
-
|
|
265
|
-
setInputValue(value);
|
|
266
|
-
setFocusedItemIndex(null);
|
|
267
|
-
};
|
|
340
|
+
setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
|
|
268
341
|
|
|
269
|
-
|
|
270
|
-
|
|
342
|
+
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
343
|
+
};
|
|
271
344
|
|
|
272
|
-
|
|
273
|
-
|
|
345
|
+
var onClearButtonClick = function onClearButtonClick() {
|
|
346
|
+
var _textInputRef$current3;
|
|
274
347
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
setFieldValue(rest.name, selectedValues, true);
|
|
282
|
-
} // eslint-disable-next-line no-unused-expressions
|
|
348
|
+
setSelected([]);
|
|
349
|
+
setInputValue('');
|
|
350
|
+
resetActiveAndFocusedItem();
|
|
351
|
+
textInputRef == null ? void 0 : (_textInputRef$current3 = textInputRef.current) == null ? void 0 : _textInputRef$current3.focus();
|
|
352
|
+
setFieldValue(rest.name, [], true);
|
|
353
|
+
};
|
|
283
354
|
|
|
355
|
+
var getChildren = function getChildren(value) {
|
|
356
|
+
var _selectMenuOptions$fi;
|
|
284
357
|
|
|
285
|
-
|
|
358
|
+
return (_selectMenuOptions$fi = selectMenuOptions.find(function (option) {
|
|
359
|
+
return option.value === value;
|
|
360
|
+
})) == null ? void 0 : _selectMenuOptions$fi.children;
|
|
286
361
|
};
|
|
287
362
|
|
|
288
363
|
var toggle = function toggle(toggleRef) {
|
|
289
364
|
return React__default["default"].createElement(reactCore.MenuToggle, {
|
|
290
365
|
variant: 'typeahead',
|
|
366
|
+
"aria-label": 'menu toggle',
|
|
291
367
|
onClick: onToggleClick,
|
|
292
368
|
innerRef: toggleRef,
|
|
293
369
|
isExpanded: isOpen,
|
|
@@ -295,17 +371,17 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
295
371
|
isFullWidth: true
|
|
296
372
|
}, React__default["default"].createElement(reactCore.TextInputGroup, {
|
|
297
373
|
isPlain: true
|
|
298
|
-
}, React__default["default"].createElement(reactCore.TextInputGroupMain,
|
|
374
|
+
}, React__default["default"].createElement(reactCore.TextInputGroupMain, _extends({
|
|
299
375
|
value: inputValue,
|
|
300
|
-
onClick:
|
|
376
|
+
onClick: onInputClick,
|
|
301
377
|
onChange: onTextInputChange,
|
|
302
378
|
onKeyDown: onInputKeyDown,
|
|
303
379
|
id: 'multi-typeahead-select-input',
|
|
304
380
|
autoComplete: 'off',
|
|
305
381
|
innerRef: textInputRef,
|
|
306
382
|
placeholder: placeholder
|
|
307
|
-
},
|
|
308
|
-
'aria-activedescendant':
|
|
383
|
+
}, activeItemId && {
|
|
384
|
+
'aria-activedescendant': activeItemId
|
|
309
385
|
}, {
|
|
310
386
|
role: 'combobox',
|
|
311
387
|
isExpanded: isOpen,
|
|
@@ -320,18 +396,14 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
320
396
|
|
|
321
397
|
_onSelect(selection);
|
|
322
398
|
}
|
|
323
|
-
}, selection);
|
|
324
|
-
}))), React__default["default"].createElement(reactCore.TextInputGroupUtilities,
|
|
399
|
+
}, getChildren(selection));
|
|
400
|
+
}))), React__default["default"].createElement(reactCore.TextInputGroupUtilities, _extends({}, selected.length === 0 ? {
|
|
401
|
+
style: {
|
|
402
|
+
display: 'none'
|
|
403
|
+
}
|
|
404
|
+
} : {}), React__default["default"].createElement(reactCore.Button, {
|
|
325
405
|
variant: 'plain',
|
|
326
|
-
onClick:
|
|
327
|
-
var _textInputRef$current2;
|
|
328
|
-
|
|
329
|
-
setInputValue('');
|
|
330
|
-
setSelected([]); // eslint-disable-next-line no-unused-expressions
|
|
331
|
-
|
|
332
|
-
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
333
|
-
setFieldValue(rest.name, [], true);
|
|
334
|
-
},
|
|
406
|
+
onClick: onClearButtonClick,
|
|
335
407
|
"aria-label": 'Clear input value'
|
|
336
408
|
}, React__default["default"].createElement(TimesIcon$1, {
|
|
337
409
|
"aria-hidden": true
|
|
@@ -345,16 +417,13 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
345
417
|
fieldId: rest.name,
|
|
346
418
|
label: label,
|
|
347
419
|
helperText: helperText
|
|
348
|
-
}, React__default["default"].createElement(reactCore.Select,
|
|
420
|
+
}, React__default["default"].createElement(reactCore.Select, _extends({
|
|
349
421
|
id: 'multi-typeahead-select',
|
|
350
422
|
isOpen: isOpen,
|
|
351
423
|
selected: selected,
|
|
352
424
|
onSelect: function onSelect(_ev, selection) {
|
|
353
425
|
return _onSelect(selection);
|
|
354
426
|
},
|
|
355
|
-
onOpenChange: function onOpenChange() {
|
|
356
|
-
return setIsOpen(false);
|
|
357
|
-
},
|
|
358
427
|
toggle: toggle,
|
|
359
428
|
isScrollable: true,
|
|
360
429
|
maxMenuHeight: maxHeight
|
|
@@ -364,7 +433,7 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
364
433
|
isAriaMultiselectable: true,
|
|
365
434
|
id: 'select-multi-typeahead-listbox'
|
|
366
435
|
}, selectOptions == null ? void 0 : selectOptions.map(function (option, index) {
|
|
367
|
-
return React__default["default"].createElement(reactCore.SelectOption,
|
|
436
|
+
return React__default["default"].createElement(reactCore.SelectOption, _extends({
|
|
368
437
|
key: option.value || option.children,
|
|
369
438
|
isFocused: focusedItemIndex === index,
|
|
370
439
|
id: "select-multi-typeahead-" + option.value.replace(' ', '-'),
|
package/dist/index.modern.js
CHANGED
|
@@ -4,6 +4,24 @@ import { ValidatedOptions, Select, SelectList, SelectOption, MenuToggle, TextInp
|
|
|
4
4
|
import { FormGroupContainer } from '@rhc-shared-components/form-group-container';
|
|
5
5
|
import { useField, useFormikContext } from 'formik';
|
|
6
6
|
|
|
7
|
+
function _extends() {
|
|
8
|
+
_extends = Object.assign || function (target) {
|
|
9
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
10
|
+
var source = arguments[i];
|
|
11
|
+
|
|
12
|
+
for (var key in source) {
|
|
13
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
14
|
+
target[key] = source[key];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return target;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return _extends.apply(this, arguments);
|
|
23
|
+
}
|
|
24
|
+
|
|
7
25
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
8
26
|
if (source == null) return {};
|
|
9
27
|
var target = {};
|
|
@@ -96,11 +114,11 @@ const FormMultiSelectInput = _ref => {
|
|
|
96
114
|
label,
|
|
97
115
|
isRequired,
|
|
98
116
|
selectMenuOptions,
|
|
99
|
-
ariaLabel = 'Select
|
|
117
|
+
ariaLabel = 'Select a value',
|
|
100
118
|
placeholder,
|
|
101
119
|
helperText,
|
|
102
120
|
maxHeight,
|
|
103
|
-
isDisabled,
|
|
121
|
+
isDisabled = false,
|
|
104
122
|
menuAppendTo
|
|
105
123
|
} = _ref,
|
|
106
124
|
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
@@ -119,8 +137,9 @@ const FormMultiSelectInput = _ref => {
|
|
|
119
137
|
const [selected, setSelected] = React__default.useState([]);
|
|
120
138
|
const [selectOptions, setSelectOptions] = React__default.useState(selectMenuOptions);
|
|
121
139
|
const [focusedItemIndex, setFocusedItemIndex] = React__default.useState(null);
|
|
122
|
-
const [
|
|
140
|
+
const [activeItemId, setActiveItemId] = React__default.useState(null);
|
|
123
141
|
const textInputRef = React__default.useRef();
|
|
142
|
+
const NO_RESULTS = 'no results';
|
|
124
143
|
React__default.useEffect(() => {
|
|
125
144
|
let newSelectOptions = selectMenuOptions; // Filter menu items based on the text input value when one exists
|
|
126
145
|
|
|
@@ -129,9 +148,9 @@ const FormMultiSelectInput = _ref => {
|
|
|
129
148
|
|
|
130
149
|
if (!newSelectOptions.length) {
|
|
131
150
|
newSelectOptions = [{
|
|
132
|
-
|
|
151
|
+
isAriaDisabled: true,
|
|
133
152
|
children: `No results found for "${inputValue}"`,
|
|
134
|
-
value:
|
|
153
|
+
value: NO_RESULTS
|
|
135
154
|
}];
|
|
136
155
|
} // Open the menu when the input value changes and the new value is not empty
|
|
137
156
|
|
|
@@ -142,8 +161,7 @@ const FormMultiSelectInput = _ref => {
|
|
|
142
161
|
}
|
|
143
162
|
|
|
144
163
|
setSelectOptions(newSelectOptions);
|
|
145
|
-
|
|
146
|
-
}, [inputValue, selectMenuOptions]);
|
|
164
|
+
}, [inputValue]);
|
|
147
165
|
React__default.useEffect(() => {
|
|
148
166
|
if ((value == null ? void 0 : value.length) > 0) {
|
|
149
167
|
setFieldValue(rest.name, value, true);
|
|
@@ -151,55 +169,114 @@ const FormMultiSelectInput = _ref => {
|
|
|
151
169
|
}
|
|
152
170
|
}, []);
|
|
153
171
|
|
|
172
|
+
const createItemId = value => `select-multi-typeahead-${value.replace(' ', '-')}`;
|
|
173
|
+
|
|
174
|
+
const setActiveAndFocusedItem = itemIndex => {
|
|
175
|
+
setFocusedItemIndex(itemIndex);
|
|
176
|
+
const focusedItem = selectOptions[itemIndex];
|
|
177
|
+
setActiveItemId(createItemId(focusedItem.value));
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const resetActiveAndFocusedItem = () => {
|
|
181
|
+
setFocusedItemIndex(null);
|
|
182
|
+
setActiveItemId(null);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const closeMenu = () => {
|
|
186
|
+
setIsOpen(false);
|
|
187
|
+
resetActiveAndFocusedItem();
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const onInputClick = () => {
|
|
191
|
+
if (!isOpen) {
|
|
192
|
+
setIsOpen(true);
|
|
193
|
+
} else if (!inputValue) {
|
|
194
|
+
closeMenu();
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const onSelect = value => {
|
|
199
|
+
var _textInputRef$current;
|
|
200
|
+
|
|
201
|
+
if (value && value !== NO_RESULTS) {
|
|
202
|
+
const selectedValues = selected.includes(value) ? selected.filter(selection => selection !== value) : [...selected, value];
|
|
203
|
+
setSelected(selectedValues);
|
|
204
|
+
setFieldTouched(rest.name, true, false);
|
|
205
|
+
setFieldValue(rest.name, selectedValues, true);
|
|
206
|
+
} // eslint-disable-next-line no-unused-expressions
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
(_textInputRef$current = textInputRef.current) == null ? void 0 : _textInputRef$current.focus();
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const onTextInputChange = (_event, value) => {
|
|
213
|
+
setInputValue(value);
|
|
214
|
+
resetActiveAndFocusedItem();
|
|
215
|
+
};
|
|
216
|
+
|
|
154
217
|
const handleMenuArrowKeys = key => {
|
|
155
218
|
let indexToFocus = 0;
|
|
156
219
|
|
|
157
|
-
if (isOpen) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
220
|
+
if (!isOpen) {
|
|
221
|
+
setIsOpen(true);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (selectOptions.every(option => option.isDisabled)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (key === 'ArrowUp') {
|
|
229
|
+
// When no index is set or at the first index, focus to the last, otherwise decrement focus index
|
|
230
|
+
if (focusedItemIndex === null || focusedItemIndex === 0) {
|
|
231
|
+
indexToFocus = selectOptions.length - 1;
|
|
232
|
+
} else {
|
|
233
|
+
indexToFocus = focusedItemIndex - 1;
|
|
234
|
+
} // Skip disabled options
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
238
|
+
indexToFocus--;
|
|
239
|
+
|
|
240
|
+
if (indexToFocus === -1) {
|
|
161
241
|
indexToFocus = selectOptions.length - 1;
|
|
162
|
-
} else {
|
|
163
|
-
indexToFocus = focusedItemIndex - 1;
|
|
164
242
|
}
|
|
165
243
|
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (key === 'ArrowDown') {
|
|
247
|
+
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
248
|
+
if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
|
|
249
|
+
indexToFocus = 0;
|
|
250
|
+
} else {
|
|
251
|
+
indexToFocus = focusedItemIndex + 1;
|
|
252
|
+
} // Skip disabled options
|
|
166
253
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
254
|
+
|
|
255
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
256
|
+
indexToFocus++;
|
|
257
|
+
|
|
258
|
+
if (indexToFocus === selectOptions.length) {
|
|
170
259
|
indexToFocus = 0;
|
|
171
|
-
} else {
|
|
172
|
-
indexToFocus = focusedItemIndex + 1;
|
|
173
260
|
}
|
|
174
261
|
}
|
|
175
|
-
|
|
176
|
-
setFocusedItemIndex(indexToFocus);
|
|
177
|
-
const focusedItem = selectOptions.filter(option => !option.isDisabled)[indexToFocus];
|
|
178
|
-
setActiveItem(`select-multi-typeahead-${focusedItem.value.replace(' ', '-')}`);
|
|
179
262
|
}
|
|
263
|
+
|
|
264
|
+
setActiveAndFocusedItem(indexToFocus);
|
|
180
265
|
};
|
|
181
266
|
|
|
182
267
|
const onInputKeyDown = event => {
|
|
183
|
-
const
|
|
184
|
-
const [firstMenuItem] = enabledMenuItems;
|
|
185
|
-
const focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
|
|
268
|
+
const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
|
|
186
269
|
|
|
187
270
|
switch (event.key) {
|
|
188
|
-
// Select the first available option
|
|
189
271
|
case 'Enter':
|
|
190
|
-
if (!
|
|
191
|
-
setIsOpen(prevIsOpen => !prevIsOpen);
|
|
192
|
-
} else if (isOpen && focusedItem.value !== 'no results') {
|
|
193
|
-
event.preventDefault();
|
|
272
|
+
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
|
|
194
273
|
onSelect(focusedItem.value);
|
|
195
274
|
}
|
|
196
275
|
|
|
197
|
-
|
|
276
|
+
if (!isOpen) {
|
|
277
|
+
setIsOpen(true);
|
|
278
|
+
}
|
|
198
279
|
|
|
199
|
-
case 'Tab':
|
|
200
|
-
case 'Escape':
|
|
201
|
-
setIsOpen(false);
|
|
202
|
-
setActiveItem(null);
|
|
203
280
|
break;
|
|
204
281
|
|
|
205
282
|
case 'ArrowUp':
|
|
@@ -211,33 +288,32 @@ const FormMultiSelectInput = _ref => {
|
|
|
211
288
|
};
|
|
212
289
|
|
|
213
290
|
const onToggleClick = () => {
|
|
214
|
-
|
|
215
|
-
};
|
|
291
|
+
var _textInputRef$current2;
|
|
216
292
|
|
|
217
|
-
|
|
218
|
-
setInputValue(value);
|
|
219
|
-
setFocusedItemIndex(null);
|
|
220
|
-
};
|
|
293
|
+
setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
|
|
221
294
|
|
|
222
|
-
|
|
223
|
-
|
|
295
|
+
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
296
|
+
};
|
|
224
297
|
|
|
225
|
-
|
|
226
|
-
|
|
298
|
+
const onClearButtonClick = () => {
|
|
299
|
+
var _textInputRef$current3;
|
|
227
300
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
301
|
+
setSelected([]);
|
|
302
|
+
setInputValue('');
|
|
303
|
+
resetActiveAndFocusedItem();
|
|
304
|
+
textInputRef == null ? void 0 : (_textInputRef$current3 = textInputRef.current) == null ? void 0 : _textInputRef$current3.focus();
|
|
305
|
+
setFieldValue(rest.name, [], true);
|
|
306
|
+
};
|
|
234
307
|
|
|
308
|
+
const getChildren = value => {
|
|
309
|
+
var _selectMenuOptions$fi;
|
|
235
310
|
|
|
236
|
-
|
|
311
|
+
return (_selectMenuOptions$fi = selectMenuOptions.find(option => option.value === value)) == null ? void 0 : _selectMenuOptions$fi.children;
|
|
237
312
|
};
|
|
238
313
|
|
|
239
314
|
const toggle = toggleRef => React__default.createElement(MenuToggle, {
|
|
240
315
|
variant: 'typeahead',
|
|
316
|
+
"aria-label": 'menu toggle',
|
|
241
317
|
onClick: onToggleClick,
|
|
242
318
|
innerRef: toggleRef,
|
|
243
319
|
isExpanded: isOpen,
|
|
@@ -245,17 +321,17 @@ const FormMultiSelectInput = _ref => {
|
|
|
245
321
|
isFullWidth: true
|
|
246
322
|
}, React__default.createElement(TextInputGroup, {
|
|
247
323
|
isPlain: true
|
|
248
|
-
}, React__default.createElement(TextInputGroupMain,
|
|
324
|
+
}, React__default.createElement(TextInputGroupMain, _extends({
|
|
249
325
|
value: inputValue,
|
|
250
|
-
onClick:
|
|
326
|
+
onClick: onInputClick,
|
|
251
327
|
onChange: onTextInputChange,
|
|
252
328
|
onKeyDown: onInputKeyDown,
|
|
253
329
|
id: 'multi-typeahead-select-input',
|
|
254
330
|
autoComplete: 'off',
|
|
255
331
|
innerRef: textInputRef,
|
|
256
332
|
placeholder: placeholder
|
|
257
|
-
},
|
|
258
|
-
'aria-activedescendant':
|
|
333
|
+
}, activeItemId && {
|
|
334
|
+
'aria-activedescendant': activeItemId
|
|
259
335
|
}, {
|
|
260
336
|
role: 'combobox',
|
|
261
337
|
isExpanded: isOpen,
|
|
@@ -268,17 +344,13 @@ const FormMultiSelectInput = _ref => {
|
|
|
268
344
|
ev.stopPropagation();
|
|
269
345
|
onSelect(selection);
|
|
270
346
|
}
|
|
271
|
-
}, selection)))), React__default.createElement(TextInputGroupUtilities,
|
|
347
|
+
}, getChildren(selection))))), React__default.createElement(TextInputGroupUtilities, _extends({}, selected.length === 0 ? {
|
|
348
|
+
style: {
|
|
349
|
+
display: 'none'
|
|
350
|
+
}
|
|
351
|
+
} : {}), React__default.createElement(Button, {
|
|
272
352
|
variant: 'plain',
|
|
273
|
-
onClick:
|
|
274
|
-
var _textInputRef$current2;
|
|
275
|
-
|
|
276
|
-
setInputValue('');
|
|
277
|
-
setSelected([]); // eslint-disable-next-line no-unused-expressions
|
|
278
|
-
|
|
279
|
-
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
280
|
-
setFieldValue(rest.name, [], true);
|
|
281
|
-
},
|
|
353
|
+
onClick: onClearButtonClick,
|
|
282
354
|
"aria-label": 'Clear input value'
|
|
283
355
|
}, React__default.createElement(TimesIcon$1, {
|
|
284
356
|
"aria-hidden": true
|
|
@@ -291,12 +363,11 @@ const FormMultiSelectInput = _ref => {
|
|
|
291
363
|
fieldId: rest.name,
|
|
292
364
|
label: label,
|
|
293
365
|
helperText: helperText
|
|
294
|
-
}, React__default.createElement(Select,
|
|
366
|
+
}, React__default.createElement(Select, _extends({
|
|
295
367
|
id: 'multi-typeahead-select',
|
|
296
368
|
isOpen: isOpen,
|
|
297
369
|
selected: selected,
|
|
298
370
|
onSelect: (_ev, selection) => onSelect(selection),
|
|
299
|
-
onOpenChange: () => setIsOpen(false),
|
|
300
371
|
toggle: toggle,
|
|
301
372
|
isScrollable: true,
|
|
302
373
|
maxMenuHeight: maxHeight
|
|
@@ -305,7 +376,7 @@ const FormMultiSelectInput = _ref => {
|
|
|
305
376
|
}), React__default.createElement(SelectList, {
|
|
306
377
|
isAriaMultiselectable: true,
|
|
307
378
|
id: 'select-multi-typeahead-listbox'
|
|
308
|
-
}, selectOptions == null ? void 0 : selectOptions.map((option, index) => React__default.createElement(SelectOption,
|
|
379
|
+
}, selectOptions == null ? void 0 : selectOptions.map((option, index) => React__default.createElement(SelectOption, _extends({
|
|
309
380
|
key: option.value || option.children,
|
|
310
381
|
isFocused: focusedItemIndex === index,
|
|
311
382
|
id: `select-multi-typeahead-${option.value.replace(' ', '-')}`,
|
package/dist/index.test.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhc-shared-components/form-multi-select-component",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "project description",
|
|
5
5
|
"author": "shkale",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"react-scripts": "^3.4.1",
|
|
60
60
|
"rimraf": "^3.0.2",
|
|
61
61
|
"sass": "^1.57.1",
|
|
62
|
-
"typescript": "
|
|
62
|
+
"typescript": "~5.7.2"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
65
|
"@patternfly/react-core": "5.3.0",
|
package/CHANGELOG.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
-
|
|
6
|
-
## [0.0.8](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/compare/@rhc-shared-components/form-multi-select-component@0.0.7...@rhc-shared-components/form-multi-select-component@0.0.8) (2022-12-06)
|
|
7
|
-
|
|
8
|
-
**Note:** Version bump only for package @rhc-shared-components/form-multi-select-component
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## [0.0.7](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/compare/@rhc-shared-components/form-multi-select-component@0.0.6...@rhc-shared-components/form-multi-select-component@0.0.7) (2022-12-06)
|
|
15
|
-
|
|
16
|
-
**Note:** Version bump only for package @rhc-shared-components/form-multi-select-component
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## [0.0.6](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/compare/@rhc-shared-components/form-multi-select-component@0.0.4...@rhc-shared-components/form-multi-select-component@0.0.6) (2022-12-06)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### Bug Fixes
|
|
26
|
-
|
|
27
|
-
* added additional options ([a4e49e7](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/commit/a4e49e7a049b40583200f96cc2f7f9456e4ea99c))
|
|
28
|
-
* fixed bugs removed max filter, updated eg ([3fedea1](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/commit/3fedea120e3d93de365f2c9b19202ffe7f601612))
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
## [0.0.4](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/compare/@rhc-shared-components/form-multi-select-component@0.0.2...@rhc-shared-components/form-multi-select-component@0.0.4) (2022-10-27)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
### Bug Fixes
|
|
38
|
-
|
|
39
|
-
* added setTouched prop in multiselect component. ([3b0b6ff](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/commit/3b0b6ff0445995129bc2b2908861768a513339d8))
|
|
40
|
-
* added touched handler ([82e397e](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/commit/82e397e3c8ae90944d3110dd5d7b3d5ff98b0589))
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
## 0.0.3 (2022-10-27)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
### Bug Fixes
|
|
48
|
-
|
|
49
|
-
* added meta.touched prop to the form multi select component. ([590886f](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/commit/590886fd8eb49a2153f6d5b512c6bd61cbae205c))
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
## [0.0.2](https://gitlab.cee.redhat.com/customer-platform/rhc-shared-components/compare/@rhc-shared-components/form-multi-select-component@0.0.1...@rhc-shared-components/form-multi-select-component@0.0.2) (2022-01-05)
|
|
56
|
-
|
|
57
|
-
**Note:** Version bump only for package @rhc-shared-components/form-multi-select-component
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## 0.0.1 (2021-12-06)
|
|
64
|
-
|
|
65
|
-
**Note:** Version bump only for package @rhc-shared-components/form-multi-select-component
|