@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 +11 -0
- package/NOTICE.html +1 -1
- package/lib/cjs/components/MultivaluesField/MultivaluesField.js +51 -26
- package/lib/cjs/components/MultivaluesField/MultivaluesField.test.js +173 -11
- package/lib/cjs/hooks/useField/useField.js +3 -2
- package/lib/components/MultivaluesField/MultivaluesField.js +51 -26
- package/lib/components/MultivaluesField/MultivaluesField.test.js +144 -11
- package/lib/hooks/useField/useField.js +3 -2
- package/package.json +1 -1
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/
|
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
|
-
|
267
|
-
|
268
|
-
|
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
|
-
|
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
|
293
|
-
|
294
|
-
var _key2 = e.target.value;
|
326
|
+
var _key = e.target.value;
|
295
327
|
|
296
|
-
if (
|
328
|
+
if (_key === '') {
|
297
329
|
return;
|
298
330
|
}
|
299
331
|
|
300
|
-
|
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(
|
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
|
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
|
647
|
+
return _regenerator["default"].wrap(function _callee3$(_context3) {
|
486
648
|
while (1) {
|
487
|
-
switch (
|
649
|
+
switch (_context3.prev = _context3.next) {
|
488
650
|
case 0:
|
489
651
|
jest.useRealTimers();
|
490
652
|
_getComponent = getComponent(), container = _getComponent.container;
|
491
|
-
|
653
|
+
_context3.next = 4;
|
492
654
|
return (0, _jestAxe.axe)(container);
|
493
655
|
|
494
656
|
case 4:
|
495
|
-
results =
|
657
|
+
results = _context3.sent;
|
496
658
|
expect(results).toHaveNoViolations();
|
497
659
|
|
498
660
|
case 6:
|
499
661
|
case "end":
|
500
|
-
return
|
662
|
+
return _context3.stop();
|
501
663
|
}
|
502
664
|
}
|
503
|
-
},
|
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(
|
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
|
-
|
215
|
-
|
216
|
-
|
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
|
-
|
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
|
241
|
-
|
242
|
-
var _key2 = e.target.value;
|
274
|
+
var _key = e.target.value;
|
243
275
|
|
244
|
-
if (
|
276
|
+
if (_key === '') {
|
245
277
|
return;
|
246
278
|
}
|
247
279
|
|
248
|
-
|
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(
|
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
|
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
|
489
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
357
490
|
while (1) {
|
358
|
-
switch (
|
491
|
+
switch (_context3.prev = _context3.next) {
|
359
492
|
case 0:
|
360
493
|
jest.useRealTimers();
|
361
494
|
_getComponent = getComponent(), container = _getComponent.container;
|
362
|
-
|
495
|
+
_context3.next = 4;
|
363
496
|
return axe(container);
|
364
497
|
|
365
498
|
case 4:
|
366
|
-
results =
|
499
|
+
results = _context3.sent;
|
367
500
|
expect(results).toHaveNoViolations();
|
368
501
|
|
369
502
|
case 6:
|
370
503
|
case "end":
|
371
|
-
return
|
504
|
+
return _context3.stop();
|
372
505
|
}
|
373
506
|
}
|
374
|
-
},
|
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(
|
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,
|