@pingux/astro 1.37.0 → 1.37.1

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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.37.1](https://gitlab.corp.pingidentity.com/ux/pingux/compare/@pingux/astro@1.37.0...@pingux/astro@1.37.1) (2022-12-06)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * [UIP-5903] Multivaluesfield improvements epic ([f82a7da](https://gitlab.corp.pingidentity.com/ux/pingux/commit/f82a7da926a9c9a9d9f61fd51b6ccbef75502826))
12
+
13
+
14
+
15
+
16
+
6
17
  # [1.37.0](https://gitlab.corp.pingidentity.com/ux/pingux/compare/@pingux/astro@1.36.2...@pingux/astro@1.37.0) (2022-12-01)
7
18
 
8
19
 
package/NOTICE.html CHANGED
@@ -146,7 +146,7 @@
146
146
 
147
147
  <main class="u-padding--xl">
148
148
  <h1>Snyk Licenses Attribution Report</h1>
149
- <h4>Report date: 12/1/2022</h4>
149
+ <h4>Report date: 12/6/2022</h4>
150
150
  <h2>Organization: <a href="https://app.snyk.io/org/ux-fbf">UX</a></h2>
151
151
  <div class="u-padding-top--sm">
152
152
  <h1>
@@ -263,11 +263,50 @@ var MultivaluesField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
263
263
  (0, _react.useEffect)(function () {
264
264
  if (onOpenChange) onOpenChange(isOpen);
265
265
  }, [isOpen]);
266
- (0, _react.useEffect)(function () {
267
- if (!state.collection.size) close();
268
- }, [state.collection]);
266
+
267
+ var addNewChipFromInput = function addNewChipFromInput(inputValue) {
268
+ var _context3, _context4;
269
+
270
+ var key = inputValue;
271
+
272
+ if (state.selectionManager.isSelected(key)) {
273
+ return;
274
+ }
275
+
276
+ selectionManager.setSelectedKeys((0, _concat["default"])(_context3 = []).call(_context3, (0, _from["default"])(selectionManager.state.selectedKeys), [key]));
277
+ setCustomItems((0, _concat["default"])(_context4 = []).call(_context4, customItems, [{
278
+ id: key,
279
+ key: key,
280
+ name: key
281
+ }]));
282
+ setFilterString('');
283
+ }; // there actually is a test for this, but coverage is not picking it up.
284
+
285
+ /* istanbul ignore next */
286
+
287
+
288
+ var selectTheOnlyFilteredItem = function selectTheOnlyFilteredItem() {
289
+ var key = filteredItems[0].key;
290
+
291
+ if (!(0, _includes["default"])(disabledKeys).call(disabledKeys, key)) {
292
+ selectionManager.toggleSelection(filteredItems[0].key);
293
+ setFilterString('');
294
+ }
295
+ }; // there actually is a test for this, but coverage is not picking it up.
296
+
297
+ /* istanbul ignore next */
298
+
299
+
300
+ var onBlurTextField = function onBlurTextField() {
301
+ if (!hasCustomValue && filteredItems.length === 1) {
302
+ selectTheOnlyFilteredItem();
303
+ } else if (hasCustomValue) {
304
+ addNewChipFromInput(filterString);
305
+ }
306
+ };
269
307
  /* istanbul ignore next */
270
308
 
309
+
271
310
  var keyDown = function keyDown(e) {
272
311
  switch (e.key) {
273
312
  case 'Enter':
@@ -282,28 +321,15 @@ var MultivaluesField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
282
321
  setFilterString('');
283
322
  }
284
323
  } else if (!hasCustomValue && filteredItems.length === 1) {
285
- var _key = filteredItems[0].key;
286
-
287
- if (!(0, _includes["default"])(disabledKeys).call(disabledKeys, _key)) {
288
- selectionManager.toggleSelection(filteredItems[0].key);
289
- setFilterString('');
290
- }
324
+ selectTheOnlyFilteredItem();
291
325
  } else if (hasCustomValue) {
292
- var _context3, _context4;
293
-
294
- var _key2 = e.target.value;
326
+ var _key = e.target.value;
295
327
 
296
- if (state.selectionManager.isSelected(_key2)) {
328
+ if (_key === '') {
297
329
  return;
298
330
  }
299
331
 
300
- selectionManager.setSelectedKeys((0, _concat["default"])(_context3 = []).call(_context3, (0, _from["default"])(selectionManager.state.selectedKeys), [_key2]));
301
- setCustomItems((0, _concat["default"])(_context4 = []).call(_context4, customItems, [{
302
- id: _key2,
303
- key: _key2,
304
- name: _key2
305
- }]));
306
- setFilterString('');
332
+ addNewChipFromInput(e.target.value);
307
333
  }
308
334
 
309
335
  break;
@@ -417,9 +443,7 @@ var MultivaluesField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
417
443
 
418
444
  return null;
419
445
  }));
420
- var listbox = (0, _react2.jsx)(_focus.FocusScope, {
421
- restoreFocus: true
422
- }, (0, _react2.jsx)(_overlays.DismissButton, {
446
+ var listbox = (0, _react2.jsx)(_focus.FocusScope, null, (0, _react2.jsx)(_overlays.DismissButton, {
423
447
  onDismiss: close
424
448
  }), (0, _react2.jsx)(_.ScrollBox, scrollBoxProps, (0, _react2.jsx)(_ListBox["default"], {
425
449
  ref: listBoxRef,
@@ -452,12 +476,14 @@ var MultivaluesField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
452
476
  border: 'none'
453
477
  }
454
478
  },
455
- status: status
479
+ status: status,
480
+ isRestrictiveMultivalues: !hasCustomValue
456
481
  });
457
482
 
458
483
  return (0, _react2.jsx)(_.Box, containerProps, (0, _react2.jsx)(_.TextField, (0, _extends2["default"])({
459
484
  onBlur: function onBlur(e) {
460
485
  setIsOpen(false);
486
+ if (mode === 'non-restrictive' && filterString !== '') onBlurTextField();
461
487
  if (_onBlur) _onBlur(e.nativeEvent);
462
488
  },
463
489
  onChange: function onChange(e) {
@@ -483,9 +509,8 @@ var MultivaluesField = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref)
483
509
  "aria-invalid": status === 'error' && true
484
510
  }, ariaProps, inputProps)), (0, _react2.jsx)(_.PopoverContainer, {
485
511
  hasNoArrow: true,
486
- isDismissable: true,
487
512
  isNonModal: true,
488
- isOpen: isOpen,
513
+ isOpen: !state.collection.size ? false : isOpen,
489
514
  onClose: close,
490
515
  placement: placement,
491
516
  ref: popoverRef,
@@ -198,6 +198,71 @@ test('clicking an option renders chip with option name', function () {
198
198
  var chipContainer = chip.parentElement;
199
199
  expect(chipContainer).toHaveAttribute('role', 'presentation');
200
200
  });
201
+ test('after clicking an option, and then clicking the text input, the listbox remains open', function () {
202
+ getComponent();
203
+
204
+ var input = _testWrapper.screen.getByRole('combobox');
205
+
206
+ _userEvent["default"].tab();
207
+
208
+ expect(input).toHaveFocus();
209
+
210
+ var options = _testWrapper.screen.getAllByRole('option');
211
+
212
+ var firstOption = options[0];
213
+ firstOption.click();
214
+ expect(firstOption).not.toBeInTheDocument();
215
+ expect(_testWrapper.screen.queryByRole('listbox')).toBeInTheDocument();
216
+
217
+ _userEvent["default"].click(input);
218
+
219
+ expect(_testWrapper.screen.queryByRole('listbox')).toBeInTheDocument();
220
+ });
221
+ test('no chips are rendered, if nothing is selected', function () {
222
+ getComponent({
223
+ isReadOnly: false
224
+ });
225
+ expect(_testWrapper.screen.queryByRole('presentation')).not.toBeInTheDocument(0);
226
+ });
227
+ test('after clicking an option, and then typing a custom input, the listbox remains open and filters the options', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
228
+ var input, options, firstOption, value, listbox, filteredOptions;
229
+ return _regenerator["default"].wrap(function _callee$(_context) {
230
+ while (1) {
231
+ switch (_context.prev = _context.next) {
232
+ case 0:
233
+ getComponent({
234
+ mode: 'non-restrictive'
235
+ });
236
+ input = _testWrapper.screen.getByRole('combobox');
237
+
238
+ _userEvent["default"].tab();
239
+
240
+ expect(input).toHaveFocus();
241
+ options = _testWrapper.screen.getAllByRole('option');
242
+ firstOption = options[0];
243
+ firstOption.click();
244
+ expect(firstOption).not.toBeInTheDocument();
245
+ _context.next = 10;
246
+ return _userEvent["default"].clear(input);
247
+
248
+ case 10:
249
+ value = 'ka';
250
+ _context.next = 13;
251
+ return _userEvent["default"].type(input, value);
252
+
253
+ case 13:
254
+ listbox = _testWrapper.screen.queryByRole('listbox');
255
+ expect(listbox).toBeInTheDocument();
256
+ filteredOptions = (0, _testWrapper.within)(listbox).getAllByRole('option');
257
+ expect(filteredOptions.length).toBe(1);
258
+
259
+ case 17:
260
+ case "end":
261
+ return _context.stop();
262
+ }
263
+ }
264
+ }, _callee);
265
+ })));
201
266
  test('clicking on delete button deletes selection, and re-adds option to list', function () {
202
267
  getComponent();
203
268
 
@@ -257,7 +322,8 @@ test('clicking an option fires "onSelectionChange"', function () {
257
322
  test('changing the input value opens listbox, filters options, and fires "onInputChange"', function () {
258
323
  var onInputChange = jest.fn();
259
324
  getComponent({
260
- onInputChange: onInputChange
325
+ onInputChange: onInputChange,
326
+ mode: 'non-restrictive'
261
327
  });
262
328
 
263
329
  var input = _testWrapper.screen.getByRole('combobox');
@@ -274,6 +340,87 @@ test('changing the input value opens listbox, filters options, and fires "onInpu
274
340
  expect(onInputChange).toBeCalledTimes(value.length);
275
341
  expect(onInputChange).toHaveBeenCalledWith(value);
276
342
  });
343
+ test('in non-restrictive mode, a chip gets added if there is input, onBlur', function () {
344
+ getComponent({
345
+ mode: 'non-restrictive'
346
+ });
347
+
348
+ var input = _testWrapper.screen.getByRole('combobox');
349
+
350
+ var value = 'custom';
351
+
352
+ _userEvent["default"].type(input, value);
353
+
354
+ _userEvent["default"].tab();
355
+
356
+ var chip = _testWrapper.screen.queryByText(value);
357
+
358
+ expect(chip).toBeInTheDocument();
359
+ var chipContainer = chip.parentElement;
360
+ expect(chipContainer).toHaveAttribute('role', 'presentation');
361
+ expect(input.value).toBe('');
362
+ });
363
+ test('in non-restrictive mode, a chip gets added if there is only one matching filtered option, onBlur', function () {
364
+ getComponent({
365
+ mode: 'non-restrictive'
366
+ });
367
+
368
+ var input = _testWrapper.screen.getByRole('combobox');
369
+
370
+ _userEvent["default"].tab();
371
+
372
+ var listbox = _testWrapper.screen.getByRole('listbox');
373
+
374
+ var options = (0, _testWrapper.within)(listbox).getAllByRole('option');
375
+ var firstOption = options[0];
376
+ var value = 'Aardvark';
377
+
378
+ _userEvent["default"].type(input, value);
379
+
380
+ _userEvent["default"].tab();
381
+
382
+ var chip = _testWrapper.screen.queryByText(value);
383
+
384
+ expect(chip).toBeInTheDocument();
385
+ var chipContainer = chip.parentElement;
386
+ expect(chipContainer).toHaveAttribute('role', 'presentation');
387
+ expect(firstOption).not.toBeInTheDocument();
388
+ });
389
+ test('dropdown with options reappears after entering a custom input', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
390
+ var input, value1, value2, listbox, options2;
391
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
392
+ while (1) {
393
+ switch (_context2.prev = _context2.next) {
394
+ case 0:
395
+ getComponent({
396
+ mode: 'non-restrictive'
397
+ });
398
+ input = _testWrapper.screen.getByRole('combobox');
399
+ value1 = 'longstring';
400
+
401
+ _userEvent["default"].type(input, value1);
402
+
403
+ expect(_testWrapper.screen.queryByRole('listbox')).not.toBeInTheDocument();
404
+ value2 = '';
405
+ _context2.next = 8;
406
+ return _userEvent["default"].clear(input);
407
+
408
+ case 8:
409
+ _context2.next = 10;
410
+ return _userEvent["default"].type(input, value2);
411
+
412
+ case 10:
413
+ listbox = _testWrapper.screen.getByRole('listbox');
414
+ options2 = (0, _testWrapper.within)(listbox).getAllByRole('option');
415
+ expect(options2.length).toBe(items.length);
416
+
417
+ case 13:
418
+ case "end":
419
+ return _context2.stop();
420
+ }
421
+ }
422
+ }, _callee2);
423
+ })));
277
424
  test('changing the input value and hitting enter by default do nothing', function () {
278
425
  getComponent();
279
426
 
@@ -286,8 +433,7 @@ test('changing the input value and hitting enter by default do nothing', functio
286
433
 
287
434
  _userEvent["default"].type(input, '{enter}');
288
435
 
289
- expect(input).toHaveValue(value);
290
- expect(_testWrapper.screen.queryByRole('listbox')).not.toBeInTheDocument();
436
+ expect(input).toHaveValue('');
291
437
  });
292
438
  test('changing the input value and hitting enter creates new value in non-restrictive mode', function () {
293
439
  getComponent({
@@ -313,6 +459,22 @@ test('changing the input value and hitting enter creates new value in non-restri
313
459
  var chipContainer = chip.parentElement;
314
460
  expect(chipContainer).toHaveAttribute('role', 'presentation');
315
461
  });
462
+ test('pressing enter, when the input values is an empty string does not add an option, in non-restrictive mode', function () {
463
+ var onSelectionChange = jest.fn();
464
+ getComponent({
465
+ mode: 'non-restrictive',
466
+ onSelectionChange: onSelectionChange
467
+ });
468
+
469
+ var input = _testWrapper.screen.getByRole('combobox');
470
+
471
+ expect(input).toHaveValue('');
472
+
473
+ _userEvent["default"].type(input, '{enter}');
474
+
475
+ expect(input).toHaveValue('');
476
+ expect(onSelectionChange).toBeCalledTimes(0);
477
+ });
316
478
  test('in non-restrictive mode "onSelectionChange" returns entered keys', function () {
317
479
  var onSelectionChange = jest.fn();
318
480
  getComponent({
@@ -479,28 +641,28 @@ test('selected keys', function () {
479
641
 
480
642
  expect(secondChip).toBeInTheDocument();
481
643
  });
482
- test('should have no accessibility violations', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
644
+ test('should have no accessibility violations', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3() {
483
645
  var _getComponent, container, results;
484
646
 
485
- return _regenerator["default"].wrap(function _callee$(_context) {
647
+ return _regenerator["default"].wrap(function _callee3$(_context3) {
486
648
  while (1) {
487
- switch (_context.prev = _context.next) {
649
+ switch (_context3.prev = _context3.next) {
488
650
  case 0:
489
651
  jest.useRealTimers();
490
652
  _getComponent = getComponent(), container = _getComponent.container;
491
- _context.next = 4;
653
+ _context3.next = 4;
492
654
  return (0, _jestAxe.axe)(container);
493
655
 
494
656
  case 4:
495
- results = _context.sent;
657
+ results = _context3.sent;
496
658
  expect(results).toHaveNoViolations();
497
659
 
498
660
  case 6:
499
661
  case "end":
500
- return _context.stop();
662
+ return _context3.stop();
501
663
  }
502
664
  }
503
- }, _callee);
665
+ }, _callee3);
504
666
  })));
505
667
  test('read only keys', function () {
506
668
  getComponent({
@@ -606,7 +768,7 @@ test('form does not submit when adding custom value', function () {
606
768
 
607
769
  _userEvent["default"].type(input, value);
608
770
 
609
- expect(input).toHaveValue(value);
771
+ expect(input).toHaveValue('');
610
772
 
611
773
  _userEvent["default"].type(input, '{enter}');
612
774
 
@@ -52,7 +52,7 @@ var _hooks = require("../../hooks");
52
52
 
53
53
  var _constants = require("../../components/Label/constants");
54
54
 
55
- var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isIndeterminate", "isReadOnly", "isRequired", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
55
+ var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isIndeterminate", "isReadOnly", "isRequired", "isRestrictiveMultivalues", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
56
56
 
57
57
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
58
58
 
@@ -88,6 +88,7 @@ var useField = function useField() {
88
88
  isIndeterminate = props.isIndeterminate,
89
89
  isReadOnly = props.isReadOnly,
90
90
  isRequired = props.isRequired,
91
+ isRestrictiveMultivalues = props.isRestrictiveMultivalues,
91
92
  isSelected = props.isSelected,
92
93
  label = props.label,
93
94
  labelMode = props.labelMode,
@@ -216,7 +217,7 @@ var useField = function useField() {
216
217
  name: name,
217
218
  onChange: fieldOnChange,
218
219
  placeholder: placeholder,
219
- readOnly: isReadOnly,
220
+ readOnly: isRestrictiveMultivalues ? true : isReadOnly,
220
221
  required: isRequired,
221
222
  role: role,
222
223
  spellCheck: spellCheck,
@@ -211,11 +211,50 @@ var MultivaluesField = /*#__PURE__*/forwardRef(function (props, ref) {
211
211
  useEffect(function () {
212
212
  if (onOpenChange) onOpenChange(isOpen);
213
213
  }, [isOpen]);
214
- useEffect(function () {
215
- if (!state.collection.size) close();
216
- }, [state.collection]);
214
+
215
+ var addNewChipFromInput = function addNewChipFromInput(inputValue) {
216
+ var _context3, _context4;
217
+
218
+ var key = inputValue;
219
+
220
+ if (state.selectionManager.isSelected(key)) {
221
+ return;
222
+ }
223
+
224
+ selectionManager.setSelectedKeys(_concatInstanceProperty(_context3 = []).call(_context3, _Array$from(selectionManager.state.selectedKeys), [key]));
225
+ setCustomItems(_concatInstanceProperty(_context4 = []).call(_context4, customItems, [{
226
+ id: key,
227
+ key: key,
228
+ name: key
229
+ }]));
230
+ setFilterString('');
231
+ }; // there actually is a test for this, but coverage is not picking it up.
232
+
233
+ /* istanbul ignore next */
234
+
235
+
236
+ var selectTheOnlyFilteredItem = function selectTheOnlyFilteredItem() {
237
+ var key = filteredItems[0].key;
238
+
239
+ if (!_includesInstanceProperty(disabledKeys).call(disabledKeys, key)) {
240
+ selectionManager.toggleSelection(filteredItems[0].key);
241
+ setFilterString('');
242
+ }
243
+ }; // there actually is a test for this, but coverage is not picking it up.
244
+
245
+ /* istanbul ignore next */
246
+
247
+
248
+ var onBlurTextField = function onBlurTextField() {
249
+ if (!hasCustomValue && filteredItems.length === 1) {
250
+ selectTheOnlyFilteredItem();
251
+ } else if (hasCustomValue) {
252
+ addNewChipFromInput(filterString);
253
+ }
254
+ };
217
255
  /* istanbul ignore next */
218
256
 
257
+
219
258
  var keyDown = function keyDown(e) {
220
259
  switch (e.key) {
221
260
  case 'Enter':
@@ -230,28 +269,15 @@ var MultivaluesField = /*#__PURE__*/forwardRef(function (props, ref) {
230
269
  setFilterString('');
231
270
  }
232
271
  } else if (!hasCustomValue && filteredItems.length === 1) {
233
- var _key = filteredItems[0].key;
234
-
235
- if (!_includesInstanceProperty(disabledKeys).call(disabledKeys, _key)) {
236
- selectionManager.toggleSelection(filteredItems[0].key);
237
- setFilterString('');
238
- }
272
+ selectTheOnlyFilteredItem();
239
273
  } else if (hasCustomValue) {
240
- var _context3, _context4;
241
-
242
- var _key2 = e.target.value;
274
+ var _key = e.target.value;
243
275
 
244
- if (state.selectionManager.isSelected(_key2)) {
276
+ if (_key === '') {
245
277
  return;
246
278
  }
247
279
 
248
- selectionManager.setSelectedKeys(_concatInstanceProperty(_context3 = []).call(_context3, _Array$from(selectionManager.state.selectedKeys), [_key2]));
249
- setCustomItems(_concatInstanceProperty(_context4 = []).call(_context4, customItems, [{
250
- id: _key2,
251
- key: _key2,
252
- name: _key2
253
- }]));
254
- setFilterString('');
280
+ addNewChipFromInput(e.target.value);
255
281
  }
256
282
 
257
283
  break;
@@ -368,9 +394,7 @@ var MultivaluesField = /*#__PURE__*/forwardRef(function (props, ref) {
368
394
  return null;
369
395
  }));
370
396
 
371
- var listbox = ___EmotionJSX(FocusScope, {
372
- restoreFocus: true
373
- }, ___EmotionJSX(DismissButton, {
397
+ var listbox = ___EmotionJSX(FocusScope, null, ___EmotionJSX(DismissButton, {
374
398
  onDismiss: close
375
399
  }), ___EmotionJSX(ScrollBox, scrollBoxProps, ___EmotionJSX(ListBox, {
376
400
  ref: listBoxRef,
@@ -403,12 +427,14 @@ var MultivaluesField = /*#__PURE__*/forwardRef(function (props, ref) {
403
427
  border: 'none'
404
428
  }
405
429
  },
406
- status: status
430
+ status: status,
431
+ isRestrictiveMultivalues: !hasCustomValue
407
432
  });
408
433
 
409
434
  return ___EmotionJSX(Box, containerProps, ___EmotionJSX(TextField, _extends({
410
435
  onBlur: function onBlur(e) {
411
436
  setIsOpen(false);
437
+ if (mode === 'non-restrictive' && filterString !== '') onBlurTextField();
412
438
  if (_onBlur) _onBlur(e.nativeEvent);
413
439
  },
414
440
  onChange: function onChange(e) {
@@ -434,9 +460,8 @@ var MultivaluesField = /*#__PURE__*/forwardRef(function (props, ref) {
434
460
  "aria-invalid": status === 'error' && true
435
461
  }, ariaProps, inputProps)), ___EmotionJSX(PopoverContainer, {
436
462
  hasNoArrow: true,
437
- isDismissable: true,
438
463
  isNonModal: true,
439
- isOpen: isOpen,
464
+ isOpen: !state.collection.size ? false : isOpen,
440
465
  onClose: close,
441
466
  placement: placement,
442
467
  ref: popoverRef,
@@ -158,6 +158,62 @@ test('clicking an option renders chip with option name', function () {
158
158
  var chipContainer = chip.parentElement;
159
159
  expect(chipContainer).toHaveAttribute('role', 'presentation');
160
160
  });
161
+ test('after clicking an option, and then clicking the text input, the listbox remains open', function () {
162
+ getComponent();
163
+ var input = screen.getByRole('combobox');
164
+ userEvent.tab();
165
+ expect(input).toHaveFocus();
166
+ var options = screen.getAllByRole('option');
167
+ var firstOption = options[0];
168
+ firstOption.click();
169
+ expect(firstOption).not.toBeInTheDocument();
170
+ expect(screen.queryByRole('listbox')).toBeInTheDocument();
171
+ userEvent.click(input);
172
+ expect(screen.queryByRole('listbox')).toBeInTheDocument();
173
+ });
174
+ test('no chips are rendered, if nothing is selected', function () {
175
+ getComponent({
176
+ isReadOnly: false
177
+ });
178
+ expect(screen.queryByRole('presentation')).not.toBeInTheDocument(0);
179
+ });
180
+ test('after clicking an option, and then typing a custom input, the listbox remains open and filters the options', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
181
+ var input, options, firstOption, value, listbox, filteredOptions;
182
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
183
+ while (1) {
184
+ switch (_context.prev = _context.next) {
185
+ case 0:
186
+ getComponent({
187
+ mode: 'non-restrictive'
188
+ });
189
+ input = screen.getByRole('combobox');
190
+ userEvent.tab();
191
+ expect(input).toHaveFocus();
192
+ options = screen.getAllByRole('option');
193
+ firstOption = options[0];
194
+ firstOption.click();
195
+ expect(firstOption).not.toBeInTheDocument();
196
+ _context.next = 10;
197
+ return userEvent.clear(input);
198
+
199
+ case 10:
200
+ value = 'ka';
201
+ _context.next = 13;
202
+ return userEvent.type(input, value);
203
+
204
+ case 13:
205
+ listbox = screen.queryByRole('listbox');
206
+ expect(listbox).toBeInTheDocument();
207
+ filteredOptions = within(listbox).getAllByRole('option');
208
+ expect(filteredOptions.length).toBe(1);
209
+
210
+ case 17:
211
+ case "end":
212
+ return _context.stop();
213
+ }
214
+ }
215
+ }, _callee);
216
+ })));
161
217
  test('clicking on delete button deletes selection, and re-adds option to list', function () {
162
218
  getComponent();
163
219
  var input = screen.getByRole('combobox');
@@ -201,7 +257,8 @@ test('clicking an option fires "onSelectionChange"', function () {
201
257
  test('changing the input value opens listbox, filters options, and fires "onInputChange"', function () {
202
258
  var onInputChange = jest.fn();
203
259
  getComponent({
204
- onInputChange: onInputChange
260
+ onInputChange: onInputChange,
261
+ mode: 'non-restrictive'
205
262
  });
206
263
  var input = screen.getByRole('combobox');
207
264
  var value = 'aa';
@@ -213,6 +270,71 @@ test('changing the input value opens listbox, filters options, and fires "onInpu
213
270
  expect(onInputChange).toBeCalledTimes(value.length);
214
271
  expect(onInputChange).toHaveBeenCalledWith(value);
215
272
  });
273
+ test('in non-restrictive mode, a chip gets added if there is input, onBlur', function () {
274
+ getComponent({
275
+ mode: 'non-restrictive'
276
+ });
277
+ var input = screen.getByRole('combobox');
278
+ var value = 'custom';
279
+ userEvent.type(input, value);
280
+ userEvent.tab();
281
+ var chip = screen.queryByText(value);
282
+ expect(chip).toBeInTheDocument();
283
+ var chipContainer = chip.parentElement;
284
+ expect(chipContainer).toHaveAttribute('role', 'presentation');
285
+ expect(input.value).toBe('');
286
+ });
287
+ test('in non-restrictive mode, a chip gets added if there is only one matching filtered option, onBlur', function () {
288
+ getComponent({
289
+ mode: 'non-restrictive'
290
+ });
291
+ var input = screen.getByRole('combobox');
292
+ userEvent.tab();
293
+ var listbox = screen.getByRole('listbox');
294
+ var options = within(listbox).getAllByRole('option');
295
+ var firstOption = options[0];
296
+ var value = 'Aardvark';
297
+ userEvent.type(input, value);
298
+ userEvent.tab();
299
+ var chip = screen.queryByText(value);
300
+ expect(chip).toBeInTheDocument();
301
+ var chipContainer = chip.parentElement;
302
+ expect(chipContainer).toHaveAttribute('role', 'presentation');
303
+ expect(firstOption).not.toBeInTheDocument();
304
+ });
305
+ test('dropdown with options reappears after entering a custom input', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
306
+ var input, value1, value2, listbox, options2;
307
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
308
+ while (1) {
309
+ switch (_context2.prev = _context2.next) {
310
+ case 0:
311
+ getComponent({
312
+ mode: 'non-restrictive'
313
+ });
314
+ input = screen.getByRole('combobox');
315
+ value1 = 'longstring';
316
+ userEvent.type(input, value1);
317
+ expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
318
+ value2 = '';
319
+ _context2.next = 8;
320
+ return userEvent.clear(input);
321
+
322
+ case 8:
323
+ _context2.next = 10;
324
+ return userEvent.type(input, value2);
325
+
326
+ case 10:
327
+ listbox = screen.getByRole('listbox');
328
+ options2 = within(listbox).getAllByRole('option');
329
+ expect(options2.length).toBe(items.length);
330
+
331
+ case 13:
332
+ case "end":
333
+ return _context2.stop();
334
+ }
335
+ }
336
+ }, _callee2);
337
+ })));
216
338
  test('changing the input value and hitting enter by default do nothing', function () {
217
339
  getComponent();
218
340
  var input = screen.getByRole('combobox');
@@ -220,8 +342,7 @@ test('changing the input value and hitting enter by default do nothing', functio
220
342
  var value = 'custom';
221
343
  userEvent.type(input, value);
222
344
  userEvent.type(input, '{enter}');
223
- expect(input).toHaveValue(value);
224
- expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
345
+ expect(input).toHaveValue('');
225
346
  });
226
347
  test('changing the input value and hitting enter creates new value in non-restrictive mode', function () {
227
348
  getComponent({
@@ -239,6 +360,18 @@ test('changing the input value and hitting enter creates new value in non-restri
239
360
  var chipContainer = chip.parentElement;
240
361
  expect(chipContainer).toHaveAttribute('role', 'presentation');
241
362
  });
363
+ test('pressing enter, when the input values is an empty string does not add an option, in non-restrictive mode', function () {
364
+ var onSelectionChange = jest.fn();
365
+ getComponent({
366
+ mode: 'non-restrictive',
367
+ onSelectionChange: onSelectionChange
368
+ });
369
+ var input = screen.getByRole('combobox');
370
+ expect(input).toHaveValue('');
371
+ userEvent.type(input, '{enter}');
372
+ expect(input).toHaveValue('');
373
+ expect(onSelectionChange).toBeCalledTimes(0);
374
+ });
242
375
  test('in non-restrictive mode "onSelectionChange" returns entered keys', function () {
243
376
  var onSelectionChange = jest.fn();
244
377
  getComponent({
@@ -350,28 +483,28 @@ test('selected keys', function () {
350
483
  var secondChip = screen.getByText(items[2].name);
351
484
  expect(secondChip).toBeInTheDocument();
352
485
  });
353
- test('should have no accessibility violations', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
486
+ test('should have no accessibility violations', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
354
487
  var _getComponent, container, results;
355
488
 
356
- return _regeneratorRuntime.wrap(function _callee$(_context) {
489
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
357
490
  while (1) {
358
- switch (_context.prev = _context.next) {
491
+ switch (_context3.prev = _context3.next) {
359
492
  case 0:
360
493
  jest.useRealTimers();
361
494
  _getComponent = getComponent(), container = _getComponent.container;
362
- _context.next = 4;
495
+ _context3.next = 4;
363
496
  return axe(container);
364
497
 
365
498
  case 4:
366
- results = _context.sent;
499
+ results = _context3.sent;
367
500
  expect(results).toHaveNoViolations();
368
501
 
369
502
  case 6:
370
503
  case "end":
371
- return _context.stop();
504
+ return _context3.stop();
372
505
  }
373
506
  }
374
- }, _callee);
507
+ }, _callee3);
375
508
  })));
376
509
  test('read only keys', function () {
377
510
  getComponent({
@@ -450,7 +583,7 @@ test('form does not submit when adding custom value', function () {
450
583
  expect(input).toHaveValue('');
451
584
  var value = 'custom';
452
585
  userEvent.type(input, value);
453
- expect(input).toHaveValue(value);
586
+ expect(input).toHaveValue('');
454
587
  userEvent.type(input, '{enter}');
455
588
  expect(onFormSubmit).not.toHaveBeenCalled();
456
589
  });
@@ -9,7 +9,7 @@ import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
9
9
  import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
10
10
  import _slicedToArray from "@babel/runtime-corejs3/helpers/esm/slicedToArray";
11
11
  import _objectWithoutProperties from "@babel/runtime-corejs3/helpers/esm/objectWithoutProperties";
12
- var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isIndeterminate", "isReadOnly", "isRequired", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
12
+ var _excluded = ["autocomplete", "autoComplete", "autoCorrect", "children", "className", "containerProps", "controlProps", "defaultText", "defaultValue", "direction", "disabledKeys", "hasAutoFocus", "hasNoStatusIndicator", "helperText", "hintText", "id", "isDefaultSelected", "isDisabled", "isIndeterminate", "isReadOnly", "isRequired", "isRestrictiveMultivalues", "isSelected", "label", "labelMode", "labelProps", "maxLength", "name", "onBlur", "onChange", "onClear", "onFocus", "onFocusChange", "onLoadMore", "onOpenChange", "onSelectionChange", "placeholder", "role", "selectedKey", "spellCheck", "status", "statusClasses", "type", "value"];
13
13
 
14
14
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
15
15
 
@@ -58,6 +58,7 @@ var useField = function useField() {
58
58
  isIndeterminate = props.isIndeterminate,
59
59
  isReadOnly = props.isReadOnly,
60
60
  isRequired = props.isRequired,
61
+ isRestrictiveMultivalues = props.isRestrictiveMultivalues,
61
62
  isSelected = props.isSelected,
62
63
  label = props.label,
63
64
  labelMode = props.labelMode,
@@ -187,7 +188,7 @@ var useField = function useField() {
187
188
  name: name,
188
189
  onChange: fieldOnChange,
189
190
  placeholder: placeholder,
190
- readOnly: isReadOnly,
191
+ readOnly: isRestrictiveMultivalues ? true : isReadOnly,
191
192
  required: isRequired,
192
193
  role: role,
193
194
  spellCheck: spellCheck,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingux/astro",
3
- "version": "1.37.0",
3
+ "version": "1.37.1",
4
4
  "description": "PingUX themeable React component library",
5
5
  "repository": {
6
6
  "type": "git",