@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.
@@ -1,20 +1,19 @@
1
- import React from 'react';
2
- import { SelectOptionProps } from '@patternfly/react-core';
3
- declare type IMultiSelectInputOptionProps = SelectOptionProps;
4
- export interface FormMultiSelectInputProps {
5
- name: string;
6
- label: string;
7
- isRequired?: boolean;
8
- placeholder?: string;
9
- selectMenuOptions: IMultiSelectInputOptionProps[];
10
- ariaLabel?: string;
11
- helperText?: string;
12
- maxHeight?: string;
13
- isDisabled?: boolean;
14
- classNames?: string;
15
- menuAppendTo?: HTMLElement | (() => HTMLElement) | 'inline' | 'parent';
16
- extraProps?: any;
17
- isScrollable?: boolean;
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
+ 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, IMultiSelectInputOptionProps } from './FormMultiSelectInput';
2
- export { FormMultiSelectInput, IMultiSelectInputOptionProps };
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
- activeItem = _React$useState6[0],
159
- setActiveItem = _React$useState6[1];
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
- isDisabled: false,
192
+ isAriaDisabled: true,
173
193
  children: "No results found for \"" + inputValue + "\"",
174
- value: 'no results'
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
- setFocusedItemIndex(null);
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
- if (key === 'ArrowUp') {
200
- // When no index is set or at the first index, focus to the last, otherwise decrement focus index
201
- if (focusedItemIndex === null || focusedItemIndex === 0) {
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
- if (key === 'ArrowDown') {
209
- // When no index is set or at the last index, focus to the first, otherwise increment focus index
210
- if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
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 enabledMenuItems = selectOptions.filter(function (menuItem) {
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 (!isOpen) {
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
- break;
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
- setIsOpen(!isOpen);
261
- };
338
+ var _textInputRef$current2;
262
339
 
263
- var onTextInputChange = function onTextInputChange(_event, value) {
264
- setInputValue(value);
265
- };
340
+ setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
266
341
 
267
- var _onSelect = function onSelect(value) {
268
- var _textInputRef$current;
342
+ textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
343
+ };
269
344
 
270
- // eslint-disable-next-line no-console
271
- console.log('selected', value);
345
+ var onClearButtonClick = function onClearButtonClick() {
346
+ var _textInputRef$current3;
272
347
 
273
- if (value && value !== 'no results') {
274
- var selectedValues = selected.includes(value) ? selected.filter(function (selection) {
275
- return selection !== value;
276
- }) : [].concat(selected, [value]);
277
- setSelected(selectedValues);
278
- setFieldTouched(rest.name, true, false);
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
- textInputRef == null ? void 0 : (_textInputRef$current = textInputRef.current) == null ? void 0 : _textInputRef$current.focus();
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, Object.assign({
374
+ }, React__default["default"].createElement(reactCore.TextInputGroupMain, _extends({
297
375
  value: inputValue,
298
- onClick: onToggleClick,
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
- }, activeItem && {
306
- 'aria-activedescendant': activeItem
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, null, selected.length > 0 && React__default["default"].createElement(reactCore.Button, {
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: function 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, Object.assign({
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, Object.assign({
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(' ', '-'),
@@ -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 Input',
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 [activeItem, setActiveItem] = React__default.useState(null);
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
- isDisabled: false,
151
+ isAriaDisabled: true,
133
152
  children: `No results found for "${inputValue}"`,
134
- value: 'no results'
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
- setFocusedItemIndex(null);
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
- if (key === 'ArrowUp') {
160
- // When no index is set or at the first index, focus to the last, otherwise decrement focus index
161
- if (focusedItemIndex === null || focusedItemIndex === 0) {
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
- if (key === 'ArrowDown') {
169
- // When no index is set or at the last index, focus to the first, otherwise increment focus index
170
- if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
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 enabledMenuItems = selectOptions.filter(menuItem => !menuItem.isDisabled);
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 (!isOpen) {
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
- break;
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
- setIsOpen(!isOpen);
215
- };
291
+ var _textInputRef$current2;
216
292
 
217
- const onTextInputChange = (_event, value) => {
218
- setInputValue(value);
219
- };
293
+ setIsOpen(!isOpen); // eslint-disable-next-line no-unused-expressions
220
294
 
221
- const onSelect = value => {
222
- var _textInputRef$current;
295
+ textInputRef == null ? void 0 : (_textInputRef$current2 = textInputRef.current) == null ? void 0 : _textInputRef$current2.focus();
296
+ };
223
297
 
224
- // eslint-disable-next-line no-console
225
- console.log('selected', value);
298
+ const onClearButtonClick = () => {
299
+ var _textInputRef$current3;
226
300
 
227
- if (value && value !== 'no results') {
228
- const selectedValues = selected.includes(value) ? selected.filter(selection => selection !== value) : [...selected, value];
229
- setSelected(selectedValues);
230
- setFieldTouched(rest.name, true, false);
231
- setFieldValue(rest.name, selectedValues, true);
232
- } // eslint-disable-next-line no-unused-expressions
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
- textInputRef == null ? void 0 : (_textInputRef$current = textInputRef.current) == null ? void 0 : _textInputRef$current.focus();
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, Object.assign({
324
+ }, React__default.createElement(TextInputGroupMain, _extends({
248
325
  value: inputValue,
249
- onClick: onToggleClick,
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
- }, activeItem && {
257
- 'aria-activedescendant': activeItem
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, null, selected.length > 0 && React__default.createElement(Button, {
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, Object.assign({
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, Object.assign({
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(' ', '-')}`,
@@ -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.2",
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": "^3.7.5"
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