@rhc-shared-components/form-multi-select-component 1.0.3 → 1.0.4

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