@rhc-shared-components/form-multi-select-component 1.0.2 → 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 -79
- package/dist/index.modern.js +140 -68
- 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,9 +202,7 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
182
202
|
}
|
|
183
203
|
|
|
184
204
|
setSelectOptions(newSelectOptions);
|
|
185
|
-
|
|
186
|
-
setActiveItem(null);
|
|
187
|
-
}, [inputValue, selectMenuOptions]);
|
|
205
|
+
}, [inputValue]);
|
|
188
206
|
React__default["default"].useEffect(function () {
|
|
189
207
|
if ((value == null ? void 0 : value.length) > 0) {
|
|
190
208
|
setFieldValue(rest.name, value, true);
|
|
@@ -192,60 +210,120 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
192
210
|
}
|
|
193
211
|
}, []);
|
|
194
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
|
+
|
|
195
262
|
var handleMenuArrowKeys = function handleMenuArrowKeys(key) {
|
|
196
263
|
var indexToFocus = 0;
|
|
197
264
|
|
|
198
|
-
if (isOpen) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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) {
|
|
202
288
|
indexToFocus = selectOptions.length - 1;
|
|
203
|
-
} else {
|
|
204
|
-
indexToFocus = focusedItemIndex - 1;
|
|
205
289
|
}
|
|
206
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
|
+
|
|
207
301
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
302
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
303
|
+
indexToFocus++;
|
|
304
|
+
|
|
305
|
+
if (indexToFocus === selectOptions.length) {
|
|
211
306
|
indexToFocus = 0;
|
|
212
|
-
} else {
|
|
213
|
-
indexToFocus = focusedItemIndex + 1;
|
|
214
307
|
}
|
|
215
308
|
}
|
|
216
|
-
|
|
217
|
-
setFocusedItemIndex(indexToFocus);
|
|
218
|
-
var focusedItem = selectOptions.filter(function (option) {
|
|
219
|
-
return !option.isDisabled;
|
|
220
|
-
})[indexToFocus];
|
|
221
|
-
setActiveItem("select-multi-typeahead-" + focusedItem.value.replace(' ', '-'));
|
|
222
309
|
}
|
|
310
|
+
|
|
311
|
+
setActiveAndFocusedItem(indexToFocus);
|
|
223
312
|
};
|
|
224
313
|
|
|
225
314
|
var onInputKeyDown = function onInputKeyDown(event) {
|
|
226
|
-
var
|
|
227
|
-
return !menuItem.isDisabled;
|
|
228
|
-
});
|
|
229
|
-
var firstMenuItem = enabledMenuItems[0];
|
|
230
|
-
var focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
|
|
315
|
+
var focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
|
|
231
316
|
|
|
232
317
|
switch (event.key) {
|
|
233
|
-
// Select the first available option
|
|
234
318
|
case 'Enter':
|
|
235
|
-
if (!
|
|
236
|
-
setIsOpen(function (prevIsOpen) {
|
|
237
|
-
return !prevIsOpen;
|
|
238
|
-
});
|
|
239
|
-
} else if (isOpen && focusedItem.value !== 'no results') {
|
|
319
|
+
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
|
|
240
320
|
_onSelect(focusedItem.value);
|
|
241
321
|
}
|
|
242
322
|
|
|
243
|
-
|
|
323
|
+
if (!isOpen) {
|
|
324
|
+
setIsOpen(true);
|
|
325
|
+
}
|
|
244
326
|
|
|
245
|
-
case 'Tab':
|
|
246
|
-
case 'Escape':
|
|
247
|
-
setIsOpen(false);
|
|
248
|
-
setActiveItem(null);
|
|
249
327
|
break;
|
|
250
328
|
|
|
251
329
|
case 'ArrowUp':
|
|
@@ -257,35 +335,35 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
257
335
|
};
|
|
258
336
|
|
|
259
337
|
var onToggleClick = function onToggleClick() {
|
|
260
|
-
|
|
261
|
-
};
|
|
338
|
+
var _textInputRef$current2;
|
|
262
339
|
|
|
263
|
-
|
|
264
|
-
setInputValue(value);
|
|
265
|
-
};
|
|
340
|
+
setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
|
|
266
341
|
|
|
267
|
-
|
|
268
|
-
|
|
342
|
+
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
343
|
+
};
|
|
269
344
|
|
|
270
|
-
|
|
271
|
-
|
|
345
|
+
var onClearButtonClick = function onClearButtonClick() {
|
|
346
|
+
var _textInputRef$current3;
|
|
272
347
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
setFieldValue(rest.name, selectedValues, true);
|
|
280
|
-
} // 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
|
+
};
|
|
281
354
|
|
|
355
|
+
var getChildren = function getChildren(value) {
|
|
356
|
+
var _selectMenuOptions$fi;
|
|
282
357
|
|
|
283
|
-
|
|
358
|
+
return (_selectMenuOptions$fi = selectMenuOptions.find(function (option) {
|
|
359
|
+
return option.value === value;
|
|
360
|
+
})) == null ? void 0 : _selectMenuOptions$fi.children;
|
|
284
361
|
};
|
|
285
362
|
|
|
286
363
|
var toggle = function toggle(toggleRef) {
|
|
287
364
|
return React__default["default"].createElement(reactCore.MenuToggle, {
|
|
288
365
|
variant: 'typeahead',
|
|
366
|
+
"aria-label": 'menu toggle',
|
|
289
367
|
onClick: onToggleClick,
|
|
290
368
|
innerRef: toggleRef,
|
|
291
369
|
isExpanded: isOpen,
|
|
@@ -293,17 +371,17 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
293
371
|
isFullWidth: true
|
|
294
372
|
}, React__default["default"].createElement(reactCore.TextInputGroup, {
|
|
295
373
|
isPlain: true
|
|
296
|
-
}, React__default["default"].createElement(reactCore.TextInputGroupMain,
|
|
374
|
+
}, React__default["default"].createElement(reactCore.TextInputGroupMain, _extends({
|
|
297
375
|
value: inputValue,
|
|
298
|
-
onClick:
|
|
376
|
+
onClick: onInputClick,
|
|
299
377
|
onChange: onTextInputChange,
|
|
300
378
|
onKeyDown: onInputKeyDown,
|
|
301
379
|
id: 'multi-typeahead-select-input',
|
|
302
380
|
autoComplete: 'off',
|
|
303
381
|
innerRef: textInputRef,
|
|
304
382
|
placeholder: placeholder
|
|
305
|
-
},
|
|
306
|
-
'aria-activedescendant':
|
|
383
|
+
}, activeItemId && {
|
|
384
|
+
'aria-activedescendant': activeItemId
|
|
307
385
|
}, {
|
|
308
386
|
role: 'combobox',
|
|
309
387
|
isExpanded: isOpen,
|
|
@@ -318,18 +396,14 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
318
396
|
|
|
319
397
|
_onSelect(selection);
|
|
320
398
|
}
|
|
321
|
-
}, selection);
|
|
322
|
-
}))), 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, {
|
|
323
405
|
variant: 'plain',
|
|
324
|
-
onClick:
|
|
325
|
-
var _textInputRef$current2;
|
|
326
|
-
|
|
327
|
-
setInputValue('');
|
|
328
|
-
setSelected([]); // eslint-disable-next-line no-unused-expressions
|
|
329
|
-
|
|
330
|
-
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
331
|
-
setFieldValue(rest.name, [], true);
|
|
332
|
-
},
|
|
406
|
+
onClick: onClearButtonClick,
|
|
333
407
|
"aria-label": 'Clear input value'
|
|
334
408
|
}, React__default["default"].createElement(TimesIcon$1, {
|
|
335
409
|
"aria-hidden": true
|
|
@@ -343,16 +417,13 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
343
417
|
fieldId: rest.name,
|
|
344
418
|
label: label,
|
|
345
419
|
helperText: helperText
|
|
346
|
-
}, React__default["default"].createElement(reactCore.Select,
|
|
420
|
+
}, React__default["default"].createElement(reactCore.Select, _extends({
|
|
347
421
|
id: 'multi-typeahead-select',
|
|
348
422
|
isOpen: isOpen,
|
|
349
423
|
selected: selected,
|
|
350
424
|
onSelect: function onSelect(_ev, selection) {
|
|
351
425
|
return _onSelect(selection);
|
|
352
426
|
},
|
|
353
|
-
onOpenChange: function onOpenChange() {
|
|
354
|
-
return setIsOpen(false);
|
|
355
|
-
},
|
|
356
427
|
toggle: toggle,
|
|
357
428
|
isScrollable: true,
|
|
358
429
|
maxMenuHeight: maxHeight
|
|
@@ -362,7 +433,7 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
362
433
|
isAriaMultiselectable: true,
|
|
363
434
|
id: 'select-multi-typeahead-listbox'
|
|
364
435
|
}, selectOptions == null ? void 0 : selectOptions.map(function (option, index) {
|
|
365
|
-
return React__default["default"].createElement(reactCore.SelectOption,
|
|
436
|
+
return React__default["default"].createElement(reactCore.SelectOption, _extends({
|
|
366
437
|
key: option.value || option.children,
|
|
367
438
|
isFocused: focusedItemIndex === index,
|
|
368
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,9 +161,7 @@ const FormMultiSelectInput = _ref => {
|
|
|
142
161
|
}
|
|
143
162
|
|
|
144
163
|
setSelectOptions(newSelectOptions);
|
|
145
|
-
|
|
146
|
-
setActiveItem(null);
|
|
147
|
-
}, [inputValue, selectMenuOptions]);
|
|
164
|
+
}, [inputValue]);
|
|
148
165
|
React__default.useEffect(() => {
|
|
149
166
|
if ((value == null ? void 0 : value.length) > 0) {
|
|
150
167
|
setFieldValue(rest.name, value, true);
|
|
@@ -152,54 +169,114 @@ const FormMultiSelectInput = _ref => {
|
|
|
152
169
|
}
|
|
153
170
|
}, []);
|
|
154
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
|
+
|
|
155
217
|
const handleMenuArrowKeys = key => {
|
|
156
218
|
let indexToFocus = 0;
|
|
157
219
|
|
|
158
|
-
if (isOpen) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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) {
|
|
162
241
|
indexToFocus = selectOptions.length - 1;
|
|
163
|
-
} else {
|
|
164
|
-
indexToFocus = focusedItemIndex - 1;
|
|
165
242
|
}
|
|
166
243
|
}
|
|
244
|
+
}
|
|
167
245
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
256
|
+
indexToFocus++;
|
|
257
|
+
|
|
258
|
+
if (indexToFocus === selectOptions.length) {
|
|
171
259
|
indexToFocus = 0;
|
|
172
|
-
} else {
|
|
173
|
-
indexToFocus = focusedItemIndex + 1;
|
|
174
260
|
}
|
|
175
261
|
}
|
|
176
|
-
|
|
177
|
-
setFocusedItemIndex(indexToFocus);
|
|
178
|
-
const focusedItem = selectOptions.filter(option => !option.isDisabled)[indexToFocus];
|
|
179
|
-
setActiveItem(`select-multi-typeahead-${focusedItem.value.replace(' ', '-')}`);
|
|
180
262
|
}
|
|
263
|
+
|
|
264
|
+
setActiveAndFocusedItem(indexToFocus);
|
|
181
265
|
};
|
|
182
266
|
|
|
183
267
|
const onInputKeyDown = event => {
|
|
184
|
-
const
|
|
185
|
-
const [firstMenuItem] = enabledMenuItems;
|
|
186
|
-
const focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
|
|
268
|
+
const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
|
|
187
269
|
|
|
188
270
|
switch (event.key) {
|
|
189
|
-
// Select the first available option
|
|
190
271
|
case 'Enter':
|
|
191
|
-
if (!
|
|
192
|
-
setIsOpen(prevIsOpen => !prevIsOpen);
|
|
193
|
-
} else if (isOpen && focusedItem.value !== 'no results') {
|
|
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,32 +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
|
-
};
|
|
293
|
+
setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
|
|
220
294
|
|
|
221
|
-
|
|
222
|
-
|
|
295
|
+
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
296
|
+
};
|
|
223
297
|
|
|
224
|
-
|
|
225
|
-
|
|
298
|
+
const onClearButtonClick = () => {
|
|
299
|
+
var _textInputRef$current3;
|
|
226
300
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
+
};
|
|
233
307
|
|
|
308
|
+
const getChildren = value => {
|
|
309
|
+
var _selectMenuOptions$fi;
|
|
234
310
|
|
|
235
|
-
|
|
311
|
+
return (_selectMenuOptions$fi = selectMenuOptions.find(option => option.value === value)) == null ? void 0 : _selectMenuOptions$fi.children;
|
|
236
312
|
};
|
|
237
313
|
|
|
238
314
|
const toggle = toggleRef => React__default.createElement(MenuToggle, {
|
|
239
315
|
variant: 'typeahead',
|
|
316
|
+
"aria-label": 'menu toggle',
|
|
240
317
|
onClick: onToggleClick,
|
|
241
318
|
innerRef: toggleRef,
|
|
242
319
|
isExpanded: isOpen,
|
|
@@ -244,17 +321,17 @@ const FormMultiSelectInput = _ref => {
|
|
|
244
321
|
isFullWidth: true
|
|
245
322
|
}, React__default.createElement(TextInputGroup, {
|
|
246
323
|
isPlain: true
|
|
247
|
-
}, React__default.createElement(TextInputGroupMain,
|
|
324
|
+
}, React__default.createElement(TextInputGroupMain, _extends({
|
|
248
325
|
value: inputValue,
|
|
249
|
-
onClick:
|
|
326
|
+
onClick: onInputClick,
|
|
250
327
|
onChange: onTextInputChange,
|
|
251
328
|
onKeyDown: onInputKeyDown,
|
|
252
329
|
id: 'multi-typeahead-select-input',
|
|
253
330
|
autoComplete: 'off',
|
|
254
331
|
innerRef: textInputRef,
|
|
255
332
|
placeholder: placeholder
|
|
256
|
-
},
|
|
257
|
-
'aria-activedescendant':
|
|
333
|
+
}, activeItemId && {
|
|
334
|
+
'aria-activedescendant': activeItemId
|
|
258
335
|
}, {
|
|
259
336
|
role: 'combobox',
|
|
260
337
|
isExpanded: isOpen,
|
|
@@ -267,17 +344,13 @@ const FormMultiSelectInput = _ref => {
|
|
|
267
344
|
ev.stopPropagation();
|
|
268
345
|
onSelect(selection);
|
|
269
346
|
}
|
|
270
|
-
}, 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, {
|
|
271
352
|
variant: 'plain',
|
|
272
|
-
onClick:
|
|
273
|
-
var _textInputRef$current2;
|
|
274
|
-
|
|
275
|
-
setInputValue('');
|
|
276
|
-
setSelected([]); // eslint-disable-next-line no-unused-expressions
|
|
277
|
-
|
|
278
|
-
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
279
|
-
setFieldValue(rest.name, [], true);
|
|
280
|
-
},
|
|
353
|
+
onClick: onClearButtonClick,
|
|
281
354
|
"aria-label": 'Clear input value'
|
|
282
355
|
}, React__default.createElement(TimesIcon$1, {
|
|
283
356
|
"aria-hidden": true
|
|
@@ -290,12 +363,11 @@ const FormMultiSelectInput = _ref => {
|
|
|
290
363
|
fieldId: rest.name,
|
|
291
364
|
label: label,
|
|
292
365
|
helperText: helperText
|
|
293
|
-
}, React__default.createElement(Select,
|
|
366
|
+
}, React__default.createElement(Select, _extends({
|
|
294
367
|
id: 'multi-typeahead-select',
|
|
295
368
|
isOpen: isOpen,
|
|
296
369
|
selected: selected,
|
|
297
370
|
onSelect: (_ev, selection) => onSelect(selection),
|
|
298
|
-
onOpenChange: () => setIsOpen(false),
|
|
299
371
|
toggle: toggle,
|
|
300
372
|
isScrollable: true,
|
|
301
373
|
maxMenuHeight: maxHeight
|
|
@@ -304,7 +376,7 @@ const FormMultiSelectInput = _ref => {
|
|
|
304
376
|
}), React__default.createElement(SelectList, {
|
|
305
377
|
isAriaMultiselectable: true,
|
|
306
378
|
id: 'select-multi-typeahead-listbox'
|
|
307
|
-
}, 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({
|
|
308
380
|
key: option.value || option.children,
|
|
309
381
|
isFocused: focusedItemIndex === index,
|
|
310
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
|