@rhc-shared-components/form-multi-select-component 1.0.3 → 1.0.5
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 +18 -20
- package/dist/index.d.ts +2 -2
- package/dist/index.js +162 -90
- package/dist/index.modern.js +153 -79
- package/dist/index.test.d.ts +1 -1
- package/package.json +2 -2
- package/CHANGELOG.md +0 -65
|
@@ -1,20 +1,18 @@
|
|
|
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
|
-
declare const FormMultiSelectInput: React.FunctionComponent<FormMultiSelectInputProps>;
|
|
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
|
+
extraProps?: any;
|
|
15
|
+
isScrollable?: boolean;
|
|
16
|
+
}
|
|
17
|
+
declare const FormMultiSelectInput: React.FunctionComponent<FormMultiSelectInputProps>;
|
|
18
|
+
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 = {};
|
|
@@ -111,7 +129,7 @@ const TimesIcon = createIcon(TimesIconConfig);
|
|
|
111
129
|
|
|
112
130
|
var TimesIcon$1 = TimesIcon;
|
|
113
131
|
|
|
114
|
-
var _excluded = ["label", "isRequired", "children", "selectMenuOptions", "ariaLabel", "placeholder", "helperText", "maxHeight", "isDisabled", "classNames", "
|
|
132
|
+
var _excluded = ["label", "isRequired", "children", "selectMenuOptions", "ariaLabel", "placeholder", "helperText", "maxHeight", "isDisabled", "classNames", "extraProps", "isScrollable"];
|
|
115
133
|
|
|
116
134
|
var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
117
135
|
var label = _ref.label,
|
|
@@ -120,8 +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,
|
|
124
|
-
|
|
141
|
+
_ref$isDisabled = _ref.isDisabled,
|
|
142
|
+
isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
|
|
125
143
|
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
126
144
|
|
|
127
145
|
var _useField = formik.useField(rest),
|
|
@@ -155,10 +173,11 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
155
173
|
setFocusedItemIndex = _React$useState5[1];
|
|
156
174
|
|
|
157
175
|
var _React$useState6 = React__default["default"].useState(null),
|
|
158
|
-
|
|
159
|
-
|
|
176
|
+
activeItemId = _React$useState6[0],
|
|
177
|
+
setActiveItemId = _React$useState6[1];
|
|
160
178
|
|
|
161
179
|
var textInputRef = React__default["default"].useRef();
|
|
180
|
+
var NO_RESULTS = 'no results';
|
|
162
181
|
React__default["default"].useEffect(function () {
|
|
163
182
|
var newSelectOptions = selectMenuOptions; // Filter menu items based on the text input value when one exists
|
|
164
183
|
|
|
@@ -169,9 +188,9 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
169
188
|
|
|
170
189
|
if (!newSelectOptions.length) {
|
|
171
190
|
newSelectOptions = [{
|
|
172
|
-
|
|
191
|
+
isAriaDisabled: true,
|
|
173
192
|
children: "No results found for \"" + inputValue + "\"",
|
|
174
|
-
value:
|
|
193
|
+
value: NO_RESULTS
|
|
175
194
|
}];
|
|
176
195
|
} // Open the menu when the input value changes and the new value is not empty
|
|
177
196
|
|
|
@@ -182,8 +201,7 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
182
201
|
}
|
|
183
202
|
|
|
184
203
|
setSelectOptions(newSelectOptions);
|
|
185
|
-
|
|
186
|
-
}, [inputValue, selectMenuOptions]);
|
|
204
|
+
}, [inputValue]);
|
|
187
205
|
React__default["default"].useEffect(function () {
|
|
188
206
|
if ((value == null ? void 0 : value.length) > 0) {
|
|
189
207
|
setFieldValue(rest.name, value, true);
|
|
@@ -191,62 +209,122 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
191
209
|
}
|
|
192
210
|
}, []);
|
|
193
211
|
|
|
212
|
+
var createItemId = function createItemId(value) {
|
|
213
|
+
return "select-multi-typeahead-" + value.replace(' ', '-');
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
var setActiveAndFocusedItem = function setActiveAndFocusedItem(itemIndex) {
|
|
217
|
+
setFocusedItemIndex(itemIndex);
|
|
218
|
+
var focusedItem = selectOptions[itemIndex];
|
|
219
|
+
setActiveItemId(createItemId(focusedItem.value));
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
var resetActiveAndFocusedItem = function resetActiveAndFocusedItem() {
|
|
223
|
+
setFocusedItemIndex(null);
|
|
224
|
+
setActiveItemId(null);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
var closeMenu = function closeMenu() {
|
|
228
|
+
setIsOpen(false);
|
|
229
|
+
resetActiveAndFocusedItem();
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
var onInputClick = function onInputClick() {
|
|
233
|
+
if (!isOpen) {
|
|
234
|
+
setIsOpen(true);
|
|
235
|
+
} else if (!inputValue) {
|
|
236
|
+
closeMenu();
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
var _onSelect = function onSelect(value) {
|
|
241
|
+
var _textInputRef$current;
|
|
242
|
+
|
|
243
|
+
if (value && value !== NO_RESULTS) {
|
|
244
|
+
var selectedValues = selected.includes(value) ? selected.filter(function (selection) {
|
|
245
|
+
return selection !== value;
|
|
246
|
+
}) : [].concat(selected, [value]);
|
|
247
|
+
setSelected(selectedValues);
|
|
248
|
+
setFieldTouched(rest.name, true, false);
|
|
249
|
+
setFieldValue(rest.name, selectedValues, true);
|
|
250
|
+
} // eslint-disable-next-line no-unused-expressions
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
(_textInputRef$current = textInputRef.current) == null ? void 0 : _textInputRef$current.focus();
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
var onTextInputChange = function onTextInputChange(_event, value) {
|
|
257
|
+
setInputValue(value);
|
|
258
|
+
resetActiveAndFocusedItem();
|
|
259
|
+
};
|
|
260
|
+
|
|
194
261
|
var handleMenuArrowKeys = function handleMenuArrowKeys(key) {
|
|
195
262
|
var indexToFocus = 0;
|
|
196
263
|
|
|
197
|
-
if (isOpen) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
264
|
+
if (!isOpen) {
|
|
265
|
+
setIsOpen(true);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (selectOptions.every(function (option) {
|
|
269
|
+
return option.isDisabled;
|
|
270
|
+
})) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (key === 'ArrowUp') {
|
|
275
|
+
// When no index is set or at the first index, focus to the last, otherwise decrement focus index
|
|
276
|
+
if (focusedItemIndex === null || focusedItemIndex === 0) {
|
|
277
|
+
indexToFocus = selectOptions.length - 1;
|
|
278
|
+
} else {
|
|
279
|
+
indexToFocus = focusedItemIndex - 1;
|
|
280
|
+
} // Skip disabled options
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
284
|
+
indexToFocus--;
|
|
285
|
+
|
|
286
|
+
if (indexToFocus === -1) {
|
|
201
287
|
indexToFocus = selectOptions.length - 1;
|
|
202
|
-
} else {
|
|
203
|
-
indexToFocus = focusedItemIndex - 1;
|
|
204
288
|
}
|
|
205
289
|
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (key === 'ArrowDown') {
|
|
293
|
+
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
294
|
+
if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
|
|
295
|
+
indexToFocus = 0;
|
|
296
|
+
} else {
|
|
297
|
+
indexToFocus = focusedItemIndex + 1;
|
|
298
|
+
} // Skip disabled options
|
|
299
|
+
|
|
206
300
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
301
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
302
|
+
indexToFocus++;
|
|
303
|
+
|
|
304
|
+
if (indexToFocus === selectOptions.length) {
|
|
210
305
|
indexToFocus = 0;
|
|
211
|
-
} else {
|
|
212
|
-
indexToFocus = focusedItemIndex + 1;
|
|
213
306
|
}
|
|
214
307
|
}
|
|
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
308
|
}
|
|
309
|
+
|
|
310
|
+
setActiveAndFocusedItem(indexToFocus);
|
|
222
311
|
};
|
|
223
312
|
|
|
224
313
|
var onInputKeyDown = function onInputKeyDown(event) {
|
|
225
|
-
var
|
|
226
|
-
return !menuItem.isDisabled;
|
|
227
|
-
});
|
|
228
|
-
var firstMenuItem = enabledMenuItems[0];
|
|
229
|
-
var focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
|
|
314
|
+
var focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
|
|
230
315
|
|
|
231
316
|
switch (event.key) {
|
|
232
|
-
// Select the first available option
|
|
233
317
|
case 'Enter':
|
|
234
|
-
|
|
235
|
-
setIsOpen(function (prevIsOpen) {
|
|
236
|
-
return !prevIsOpen;
|
|
237
|
-
});
|
|
238
|
-
} else if (isOpen && focusedItem.value !== 'no results') {
|
|
239
|
-
event.preventDefault();
|
|
318
|
+
event.preventDefault();
|
|
240
319
|
|
|
320
|
+
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
|
|
241
321
|
_onSelect(focusedItem.value);
|
|
242
322
|
}
|
|
243
323
|
|
|
244
|
-
|
|
324
|
+
if (!isOpen) {
|
|
325
|
+
setIsOpen(true);
|
|
326
|
+
}
|
|
245
327
|
|
|
246
|
-
case 'Tab':
|
|
247
|
-
case 'Escape':
|
|
248
|
-
setIsOpen(false);
|
|
249
|
-
setActiveItem(null);
|
|
250
328
|
break;
|
|
251
329
|
|
|
252
330
|
case 'ArrowUp':
|
|
@@ -258,36 +336,35 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
258
336
|
};
|
|
259
337
|
|
|
260
338
|
var onToggleClick = function onToggleClick() {
|
|
261
|
-
|
|
262
|
-
};
|
|
339
|
+
var _textInputRef$current2;
|
|
263
340
|
|
|
264
|
-
|
|
265
|
-
setInputValue(value);
|
|
266
|
-
setFocusedItemIndex(null);
|
|
267
|
-
};
|
|
341
|
+
setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
|
|
268
342
|
|
|
269
|
-
|
|
270
|
-
|
|
343
|
+
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
344
|
+
};
|
|
271
345
|
|
|
272
|
-
|
|
273
|
-
|
|
346
|
+
var onClearButtonClick = function onClearButtonClick() {
|
|
347
|
+
var _textInputRef$current3;
|
|
274
348
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
setFieldValue(rest.name, selectedValues, true);
|
|
282
|
-
} // eslint-disable-next-line no-unused-expressions
|
|
349
|
+
setSelected([]);
|
|
350
|
+
setInputValue('');
|
|
351
|
+
resetActiveAndFocusedItem();
|
|
352
|
+
textInputRef == null ? void 0 : (_textInputRef$current3 = textInputRef.current) == null ? void 0 : _textInputRef$current3.focus();
|
|
353
|
+
setFieldValue(rest.name, [], true);
|
|
354
|
+
};
|
|
283
355
|
|
|
356
|
+
var getChildren = function getChildren(value) {
|
|
357
|
+
var _selectMenuOptions$fi;
|
|
284
358
|
|
|
285
|
-
|
|
359
|
+
return (_selectMenuOptions$fi = selectMenuOptions.find(function (option) {
|
|
360
|
+
return option.value === value;
|
|
361
|
+
})) == null ? void 0 : _selectMenuOptions$fi.children;
|
|
286
362
|
};
|
|
287
363
|
|
|
288
364
|
var toggle = function toggle(toggleRef) {
|
|
289
365
|
return React__default["default"].createElement(reactCore.MenuToggle, {
|
|
290
366
|
variant: 'typeahead',
|
|
367
|
+
"aria-label": 'menu toggle',
|
|
291
368
|
onClick: onToggleClick,
|
|
292
369
|
innerRef: toggleRef,
|
|
293
370
|
isExpanded: isOpen,
|
|
@@ -295,17 +372,17 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
295
372
|
isFullWidth: true
|
|
296
373
|
}, React__default["default"].createElement(reactCore.TextInputGroup, {
|
|
297
374
|
isPlain: true
|
|
298
|
-
}, React__default["default"].createElement(reactCore.TextInputGroupMain,
|
|
375
|
+
}, React__default["default"].createElement(reactCore.TextInputGroupMain, _extends({
|
|
299
376
|
value: inputValue,
|
|
300
|
-
onClick:
|
|
377
|
+
onClick: onInputClick,
|
|
301
378
|
onChange: onTextInputChange,
|
|
302
379
|
onKeyDown: onInputKeyDown,
|
|
303
380
|
id: 'multi-typeahead-select-input',
|
|
304
381
|
autoComplete: 'off',
|
|
305
382
|
innerRef: textInputRef,
|
|
306
383
|
placeholder: placeholder
|
|
307
|
-
},
|
|
308
|
-
'aria-activedescendant':
|
|
384
|
+
}, activeItemId && {
|
|
385
|
+
'aria-activedescendant': activeItemId
|
|
309
386
|
}, {
|
|
310
387
|
role: 'combobox',
|
|
311
388
|
isExpanded: isOpen,
|
|
@@ -320,57 +397,52 @@ var FormMultiSelectInput = function FormMultiSelectInput(_ref) {
|
|
|
320
397
|
|
|
321
398
|
_onSelect(selection);
|
|
322
399
|
}
|
|
323
|
-
}, selection);
|
|
324
|
-
}))), React__default["default"].createElement(reactCore.TextInputGroupUtilities,
|
|
400
|
+
}, getChildren(selection));
|
|
401
|
+
}))), React__default["default"].createElement(reactCore.TextInputGroupUtilities, _extends({}, selected.length === 0 ? {
|
|
402
|
+
style: {
|
|
403
|
+
display: 'none'
|
|
404
|
+
}
|
|
405
|
+
} : {}), React__default["default"].createElement(reactCore.Button, {
|
|
325
406
|
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
|
-
},
|
|
407
|
+
onClick: onClearButtonClick,
|
|
335
408
|
"aria-label": 'Clear input value'
|
|
336
409
|
}, React__default["default"].createElement(TimesIcon$1, {
|
|
337
410
|
"aria-hidden": true
|
|
338
411
|
})))));
|
|
339
412
|
};
|
|
340
413
|
|
|
341
|
-
return React__default["default"].createElement(
|
|
414
|
+
return React__default["default"].createElement(formGroupContainer.FormGroupContainer, {
|
|
342
415
|
validated: meta.touched && meta.error ? reactCore.ValidatedOptions.error : reactCore.ValidatedOptions["default"],
|
|
343
416
|
helperTextInvalid: meta.error,
|
|
344
417
|
isRequired: isRequired,
|
|
345
418
|
fieldId: rest.name,
|
|
346
419
|
label: label,
|
|
347
420
|
helperText: helperText
|
|
348
|
-
}, React__default["default"].createElement(reactCore.Select,
|
|
421
|
+
}, React__default["default"].createElement(reactCore.Select, {
|
|
349
422
|
id: 'multi-typeahead-select',
|
|
350
423
|
isOpen: isOpen,
|
|
351
424
|
selected: selected,
|
|
352
425
|
onSelect: function onSelect(_ev, selection) {
|
|
353
426
|
return _onSelect(selection);
|
|
354
427
|
},
|
|
355
|
-
onOpenChange: function onOpenChange() {
|
|
356
|
-
return setIsOpen(false);
|
|
357
|
-
},
|
|
358
428
|
toggle: toggle,
|
|
359
429
|
isScrollable: true,
|
|
360
|
-
maxMenuHeight: maxHeight
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
430
|
+
maxMenuHeight: maxHeight,
|
|
431
|
+
onOpenChange: function onOpenChange(isOpen) {
|
|
432
|
+
!isOpen && closeMenu();
|
|
433
|
+
}
|
|
434
|
+
}, React__default["default"].createElement(reactCore.SelectList, {
|
|
364
435
|
isAriaMultiselectable: true,
|
|
365
|
-
id:
|
|
436
|
+
id: "select-multi-typeahead-listbox"
|
|
366
437
|
}, selectOptions == null ? void 0 : selectOptions.map(function (option, index) {
|
|
367
|
-
return React__default["default"].createElement(reactCore.SelectOption,
|
|
438
|
+
return React__default["default"].createElement(reactCore.SelectOption, _extends({
|
|
368
439
|
key: option.value || option.children,
|
|
369
440
|
isFocused: focusedItemIndex === index,
|
|
370
|
-
|
|
441
|
+
className: option.className,
|
|
442
|
+
id: createItemId(option.value),
|
|
371
443
|
isDisabled: option.isDisabled || isSubmitting
|
|
372
444
|
}, option));
|
|
373
|
-
}))))
|
|
445
|
+
}))));
|
|
374
446
|
};
|
|
375
447
|
|
|
376
448
|
exports.FormMultiSelectInput = FormMultiSelectInput;
|
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 = {};
|
|
@@ -89,19 +107,18 @@ const TimesIcon = createIcon(TimesIconConfig);
|
|
|
89
107
|
|
|
90
108
|
var TimesIcon$1 = TimesIcon;
|
|
91
109
|
|
|
92
|
-
const _excluded = ["label", "isRequired", "children", "selectMenuOptions", "ariaLabel", "placeholder", "helperText", "maxHeight", "isDisabled", "classNames", "
|
|
110
|
+
const _excluded = ["label", "isRequired", "children", "selectMenuOptions", "ariaLabel", "placeholder", "helperText", "maxHeight", "isDisabled", "classNames", "extraProps", "isScrollable"];
|
|
93
111
|
|
|
94
112
|
const FormMultiSelectInput = _ref => {
|
|
95
113
|
let {
|
|
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
|
|
104
|
-
menuAppendTo
|
|
121
|
+
isDisabled = false
|
|
105
122
|
} = _ref,
|
|
106
123
|
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
107
124
|
|
|
@@ -119,8 +136,9 @@ const FormMultiSelectInput = _ref => {
|
|
|
119
136
|
const [selected, setSelected] = React__default.useState([]);
|
|
120
137
|
const [selectOptions, setSelectOptions] = React__default.useState(selectMenuOptions);
|
|
121
138
|
const [focusedItemIndex, setFocusedItemIndex] = React__default.useState(null);
|
|
122
|
-
const [
|
|
139
|
+
const [activeItemId, setActiveItemId] = React__default.useState(null);
|
|
123
140
|
const textInputRef = React__default.useRef();
|
|
141
|
+
const NO_RESULTS = 'no results';
|
|
124
142
|
React__default.useEffect(() => {
|
|
125
143
|
let newSelectOptions = selectMenuOptions; // Filter menu items based on the text input value when one exists
|
|
126
144
|
|
|
@@ -129,9 +147,9 @@ const FormMultiSelectInput = _ref => {
|
|
|
129
147
|
|
|
130
148
|
if (!newSelectOptions.length) {
|
|
131
149
|
newSelectOptions = [{
|
|
132
|
-
|
|
150
|
+
isAriaDisabled: true,
|
|
133
151
|
children: `No results found for "${inputValue}"`,
|
|
134
|
-
value:
|
|
152
|
+
value: NO_RESULTS
|
|
135
153
|
}];
|
|
136
154
|
} // Open the menu when the input value changes and the new value is not empty
|
|
137
155
|
|
|
@@ -142,8 +160,7 @@ const FormMultiSelectInput = _ref => {
|
|
|
142
160
|
}
|
|
143
161
|
|
|
144
162
|
setSelectOptions(newSelectOptions);
|
|
145
|
-
|
|
146
|
-
}, [inputValue, selectMenuOptions]);
|
|
163
|
+
}, [inputValue]);
|
|
147
164
|
React__default.useEffect(() => {
|
|
148
165
|
if ((value == null ? void 0 : value.length) > 0) {
|
|
149
166
|
setFieldValue(rest.name, value, true);
|
|
@@ -151,55 +168,116 @@ const FormMultiSelectInput = _ref => {
|
|
|
151
168
|
}
|
|
152
169
|
}, []);
|
|
153
170
|
|
|
171
|
+
const createItemId = value => `select-multi-typeahead-${value.replace(' ', '-')}`;
|
|
172
|
+
|
|
173
|
+
const setActiveAndFocusedItem = itemIndex => {
|
|
174
|
+
setFocusedItemIndex(itemIndex);
|
|
175
|
+
const focusedItem = selectOptions[itemIndex];
|
|
176
|
+
setActiveItemId(createItemId(focusedItem.value));
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const resetActiveAndFocusedItem = () => {
|
|
180
|
+
setFocusedItemIndex(null);
|
|
181
|
+
setActiveItemId(null);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const closeMenu = () => {
|
|
185
|
+
setIsOpen(false);
|
|
186
|
+
resetActiveAndFocusedItem();
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const onInputClick = () => {
|
|
190
|
+
if (!isOpen) {
|
|
191
|
+
setIsOpen(true);
|
|
192
|
+
} else if (!inputValue) {
|
|
193
|
+
closeMenu();
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const onSelect = value => {
|
|
198
|
+
var _textInputRef$current;
|
|
199
|
+
|
|
200
|
+
if (value && value !== NO_RESULTS) {
|
|
201
|
+
const selectedValues = selected.includes(value) ? selected.filter(selection => selection !== value) : [...selected, value];
|
|
202
|
+
setSelected(selectedValues);
|
|
203
|
+
setFieldTouched(rest.name, true, false);
|
|
204
|
+
setFieldValue(rest.name, selectedValues, true);
|
|
205
|
+
} // eslint-disable-next-line no-unused-expressions
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
(_textInputRef$current = textInputRef.current) == null ? void 0 : _textInputRef$current.focus();
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const onTextInputChange = (_event, value) => {
|
|
212
|
+
setInputValue(value);
|
|
213
|
+
resetActiveAndFocusedItem();
|
|
214
|
+
};
|
|
215
|
+
|
|
154
216
|
const handleMenuArrowKeys = key => {
|
|
155
217
|
let indexToFocus = 0;
|
|
156
218
|
|
|
157
|
-
if (isOpen) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
219
|
+
if (!isOpen) {
|
|
220
|
+
setIsOpen(true);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (selectOptions.every(option => option.isDisabled)) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (key === 'ArrowUp') {
|
|
228
|
+
// When no index is set or at the first index, focus to the last, otherwise decrement focus index
|
|
229
|
+
if (focusedItemIndex === null || focusedItemIndex === 0) {
|
|
230
|
+
indexToFocus = selectOptions.length - 1;
|
|
231
|
+
} else {
|
|
232
|
+
indexToFocus = focusedItemIndex - 1;
|
|
233
|
+
} // Skip disabled options
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
237
|
+
indexToFocus--;
|
|
238
|
+
|
|
239
|
+
if (indexToFocus === -1) {
|
|
161
240
|
indexToFocus = selectOptions.length - 1;
|
|
162
|
-
} else {
|
|
163
|
-
indexToFocus = focusedItemIndex - 1;
|
|
164
241
|
}
|
|
165
242
|
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (key === 'ArrowDown') {
|
|
246
|
+
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
247
|
+
if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
|
|
248
|
+
indexToFocus = 0;
|
|
249
|
+
} else {
|
|
250
|
+
indexToFocus = focusedItemIndex + 1;
|
|
251
|
+
} // Skip disabled options
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
while (selectOptions[indexToFocus].isDisabled) {
|
|
255
|
+
indexToFocus++;
|
|
166
256
|
|
|
167
|
-
|
|
168
|
-
// When no index is set or at the last index, focus to the first, otherwise increment focus index
|
|
169
|
-
if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
|
|
257
|
+
if (indexToFocus === selectOptions.length) {
|
|
170
258
|
indexToFocus = 0;
|
|
171
|
-
} else {
|
|
172
|
-
indexToFocus = focusedItemIndex + 1;
|
|
173
259
|
}
|
|
174
260
|
}
|
|
175
|
-
|
|
176
|
-
setFocusedItemIndex(indexToFocus);
|
|
177
|
-
const focusedItem = selectOptions.filter(option => !option.isDisabled)[indexToFocus];
|
|
178
|
-
setActiveItem(`select-multi-typeahead-${focusedItem.value.replace(' ', '-')}`);
|
|
179
261
|
}
|
|
262
|
+
|
|
263
|
+
setActiveAndFocusedItem(indexToFocus);
|
|
180
264
|
};
|
|
181
265
|
|
|
182
266
|
const onInputKeyDown = event => {
|
|
183
|
-
const
|
|
184
|
-
const [firstMenuItem] = enabledMenuItems;
|
|
185
|
-
const focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
|
|
267
|
+
const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
|
|
186
268
|
|
|
187
269
|
switch (event.key) {
|
|
188
|
-
// Select the first available option
|
|
189
270
|
case 'Enter':
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
event.preventDefault();
|
|
271
|
+
event.preventDefault();
|
|
272
|
+
|
|
273
|
+
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
|
|
194
274
|
onSelect(focusedItem.value);
|
|
195
275
|
}
|
|
196
276
|
|
|
197
|
-
|
|
277
|
+
if (!isOpen) {
|
|
278
|
+
setIsOpen(true);
|
|
279
|
+
}
|
|
198
280
|
|
|
199
|
-
case 'Tab':
|
|
200
|
-
case 'Escape':
|
|
201
|
-
setIsOpen(false);
|
|
202
|
-
setActiveItem(null);
|
|
203
281
|
break;
|
|
204
282
|
|
|
205
283
|
case 'ArrowUp':
|
|
@@ -211,33 +289,32 @@ const FormMultiSelectInput = _ref => {
|
|
|
211
289
|
};
|
|
212
290
|
|
|
213
291
|
const onToggleClick = () => {
|
|
214
|
-
|
|
215
|
-
};
|
|
292
|
+
var _textInputRef$current2;
|
|
216
293
|
|
|
217
|
-
|
|
218
|
-
setInputValue(value);
|
|
219
|
-
setFocusedItemIndex(null);
|
|
220
|
-
};
|
|
294
|
+
setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
|
|
221
295
|
|
|
222
|
-
|
|
223
|
-
|
|
296
|
+
textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
|
|
297
|
+
};
|
|
224
298
|
|
|
225
|
-
|
|
226
|
-
|
|
299
|
+
const onClearButtonClick = () => {
|
|
300
|
+
var _textInputRef$current3;
|
|
227
301
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
302
|
+
setSelected([]);
|
|
303
|
+
setInputValue('');
|
|
304
|
+
resetActiveAndFocusedItem();
|
|
305
|
+
textInputRef == null ? void 0 : (_textInputRef$current3 = textInputRef.current) == null ? void 0 : _textInputRef$current3.focus();
|
|
306
|
+
setFieldValue(rest.name, [], true);
|
|
307
|
+
};
|
|
234
308
|
|
|
309
|
+
const getChildren = value => {
|
|
310
|
+
var _selectMenuOptions$fi;
|
|
235
311
|
|
|
236
|
-
|
|
312
|
+
return (_selectMenuOptions$fi = selectMenuOptions.find(option => option.value === value)) == null ? void 0 : _selectMenuOptions$fi.children;
|
|
237
313
|
};
|
|
238
314
|
|
|
239
315
|
const toggle = toggleRef => React__default.createElement(MenuToggle, {
|
|
240
316
|
variant: 'typeahead',
|
|
317
|
+
"aria-label": 'menu toggle',
|
|
241
318
|
onClick: onToggleClick,
|
|
242
319
|
innerRef: toggleRef,
|
|
243
320
|
isExpanded: isOpen,
|
|
@@ -245,17 +322,17 @@ const FormMultiSelectInput = _ref => {
|
|
|
245
322
|
isFullWidth: true
|
|
246
323
|
}, React__default.createElement(TextInputGroup, {
|
|
247
324
|
isPlain: true
|
|
248
|
-
}, React__default.createElement(TextInputGroupMain,
|
|
325
|
+
}, React__default.createElement(TextInputGroupMain, _extends({
|
|
249
326
|
value: inputValue,
|
|
250
|
-
onClick:
|
|
327
|
+
onClick: onInputClick,
|
|
251
328
|
onChange: onTextInputChange,
|
|
252
329
|
onKeyDown: onInputKeyDown,
|
|
253
330
|
id: 'multi-typeahead-select-input',
|
|
254
331
|
autoComplete: 'off',
|
|
255
332
|
innerRef: textInputRef,
|
|
256
333
|
placeholder: placeholder
|
|
257
|
-
},
|
|
258
|
-
'aria-activedescendant':
|
|
334
|
+
}, activeItemId && {
|
|
335
|
+
'aria-activedescendant': activeItemId
|
|
259
336
|
}, {
|
|
260
337
|
role: 'combobox',
|
|
261
338
|
isExpanded: isOpen,
|
|
@@ -268,49 +345,46 @@ const FormMultiSelectInput = _ref => {
|
|
|
268
345
|
ev.stopPropagation();
|
|
269
346
|
onSelect(selection);
|
|
270
347
|
}
|
|
271
|
-
}, selection)))), React__default.createElement(TextInputGroupUtilities,
|
|
348
|
+
}, getChildren(selection))))), React__default.createElement(TextInputGroupUtilities, _extends({}, selected.length === 0 ? {
|
|
349
|
+
style: {
|
|
350
|
+
display: 'none'
|
|
351
|
+
}
|
|
352
|
+
} : {}), React__default.createElement(Button, {
|
|
272
353
|
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
|
-
},
|
|
354
|
+
onClick: onClearButtonClick,
|
|
282
355
|
"aria-label": 'Clear input value'
|
|
283
356
|
}, React__default.createElement(TimesIcon$1, {
|
|
284
357
|
"aria-hidden": true
|
|
285
358
|
})))));
|
|
286
359
|
|
|
287
|
-
return React__default.createElement(
|
|
360
|
+
return React__default.createElement(FormGroupContainer, {
|
|
288
361
|
validated: meta.touched && meta.error ? ValidatedOptions.error : ValidatedOptions.default,
|
|
289
362
|
helperTextInvalid: meta.error,
|
|
290
363
|
isRequired: isRequired,
|
|
291
364
|
fieldId: rest.name,
|
|
292
365
|
label: label,
|
|
293
366
|
helperText: helperText
|
|
294
|
-
}, React__default.createElement(Select,
|
|
367
|
+
}, React__default.createElement(Select, {
|
|
295
368
|
id: 'multi-typeahead-select',
|
|
296
369
|
isOpen: isOpen,
|
|
297
370
|
selected: selected,
|
|
298
371
|
onSelect: (_ev, selection) => onSelect(selection),
|
|
299
|
-
onOpenChange: () => setIsOpen(false),
|
|
300
372
|
toggle: toggle,
|
|
301
373
|
isScrollable: true,
|
|
302
|
-
maxMenuHeight: maxHeight
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
374
|
+
maxMenuHeight: maxHeight,
|
|
375
|
+
onOpenChange: isOpen => {
|
|
376
|
+
!isOpen && closeMenu();
|
|
377
|
+
}
|
|
378
|
+
}, React__default.createElement(SelectList, {
|
|
306
379
|
isAriaMultiselectable: true,
|
|
307
|
-
id:
|
|
308
|
-
}, selectOptions == null ? void 0 : selectOptions.map((option, index) => React__default.createElement(SelectOption,
|
|
380
|
+
id: "select-multi-typeahead-listbox"
|
|
381
|
+
}, selectOptions == null ? void 0 : selectOptions.map((option, index) => React__default.createElement(SelectOption, _extends({
|
|
309
382
|
key: option.value || option.children,
|
|
310
383
|
isFocused: focusedItemIndex === index,
|
|
311
|
-
|
|
384
|
+
className: option.className,
|
|
385
|
+
id: createItemId(option.value),
|
|
312
386
|
isDisabled: option.isDisabled || isSubmitting
|
|
313
|
-
}, option))))))
|
|
387
|
+
}, option))))));
|
|
314
388
|
};
|
|
315
389
|
|
|
316
390
|
export { FormMultiSelectInput };
|
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.5",
|
|
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
|