@gitlab/ui 64.10.0 → 64.10.2

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
@@ -1,3 +1,17 @@
1
+ ## [64.10.2](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.10.1...v64.10.2) (2023-06-16)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **GlCollapsibleListbox:** reverse clear all logic ([270777b](https://gitlab.com/gitlab-org/gitlab-ui/commit/270777bd74cfa2e76eff594ec1612ea408b4372f))
7
+
8
+ ## [64.10.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.10.0...v64.10.1) (2023-06-14)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **GlCollapsibleListbox:** listbox stays open ([a83355d](https://gitlab.com/gitlab-org/gitlab-ui/commit/a83355d527c483ca6bd6587da64f565ef118b8da))
14
+
1
15
  # [64.10.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.9.0...v64.10.0) (2023-06-14)
2
16
 
3
17
 
@@ -329,7 +329,7 @@ var script = {
329
329
  },
330
330
  computed: {
331
331
  listboxTag() {
332
- if (this.items.length === 0 || isOption(this.items[0])) return 'ul';
332
+ if (!this.hasItems || isOption(this.items[0])) return 'ul';
333
333
  return 'div';
334
334
  },
335
335
  listboxClasses() {
@@ -345,6 +345,9 @@ var script = {
345
345
  flattenedOptions() {
346
346
  return flattenedOptions(this.items);
347
347
  },
348
+ hasItems() {
349
+ return this.items.length > 0;
350
+ },
348
351
  listboxToggleText() {
349
352
  if (!this.toggleText) {
350
353
  if (!this.multiple && this.selectedValues.length) {
@@ -384,8 +387,19 @@ var script = {
384
387
  if (!this.resetButtonLabel) {
385
388
  return false;
386
389
  }
390
+ if (!this.multiple) {
391
+ return false;
392
+ }
393
+
394
+ /**
395
+ * if dropdown has no items
396
+ * reset all should be hidden
397
+ */
398
+ if (!this.hasItems) {
399
+ return false;
400
+ }
387
401
  if (this.multiple) {
388
- return this.selected.length > 0;
402
+ return this.selected.length === this.items.length;
389
403
  }
390
404
  return Boolean(this.selected);
391
405
  },
@@ -396,7 +410,15 @@ var script = {
396
410
  if (!this.multiple) {
397
411
  return false;
398
412
  }
399
- return this.selected.length === 0;
413
+
414
+ /**
415
+ * if dropdown has no items
416
+ * select all should be hidden
417
+ */
418
+ if (!this.hasItems) {
419
+ return false;
420
+ }
421
+ return this.selected.length !== this.items.length;
400
422
  },
401
423
  showIntersectionObserver() {
402
424
  return this.infiniteScroll && !this.infiniteScrollLoading && !this.loading && !this.searching;
@@ -614,7 +636,6 @@ var script = {
614
636
  * @event reset
615
637
  */
616
638
  this.$emit('reset');
617
- this.closeAndFocus();
618
639
  },
619
640
  onSelectAllButtonClicked() {
620
641
  /**
@@ -35,6 +35,12 @@ const mockOptions = [{
35
35
  value: 'sup',
36
36
  text: 'Support'
37
37
  }];
38
+ const mockOptionsValues = mockOptions.map(_ref => {
39
+ let {
40
+ value
41
+ } = _ref;
42
+ return value;
43
+ });
38
44
  const mockGroups = [{
39
45
  text: 'Branches',
40
46
  options: [{
@@ -103,4 +109,4 @@ const mockUsers = [{
103
109
  icon: 'bin'
104
110
  }];
105
111
 
106
- export { mockGroups, mockGroupsWithTextSrOnly, mockOptions, mockUsers };
112
+ export { mockGroups, mockGroupsWithTextSrOnly, mockOptions, mockOptionsValues, mockUsers };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "64.10.0",
3
+ "version": "64.10.2",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -156,8 +156,8 @@
156
156
  "storybook": "7.0.20",
157
157
  "storybook-dark-mode": "3.0.0",
158
158
  "stylelint": "14.9.1",
159
- "stylelint-config-prettier": "9.0.4",
160
- "stylelint-prettier": "2.0.0",
159
+ "stylelint-config-prettier": "^9.0.5",
160
+ "stylelint-prettier": "3.0.0",
161
161
  "vue": "2.7.14",
162
162
  "vue-loader": "^15.8.3",
163
163
  "vue-loader-vue3": "npm:vue-loader@17",
@@ -18,7 +18,7 @@ import GlIntersectionObserver from '../../../utilities/intersection_observer/int
18
18
  import GlCollapsibleListbox, { ITEM_SELECTOR } from './listbox.vue';
19
19
  import GlListboxItem from './listbox_item.vue';
20
20
  import GlListboxGroup from './listbox_group.vue';
21
- import { mockOptions, mockGroups, mockGroupsWithTextSrOnly } from './mock_data';
21
+ import { mockOptions, mockOptionsValues, mockGroups, mockGroupsWithTextSrOnly } from './mock_data';
22
22
 
23
23
  jest.mock('@floating-ui/dom');
24
24
  autoUpdate.mockImplementation(() => {
@@ -179,6 +179,15 @@ describe('GlCollapsibleListbox', () => {
179
179
  await nextTick();
180
180
  expect(wrapper.emitted('select')[0][0]).toEqual(mockOptions[2].value);
181
181
  });
182
+
183
+ it('close dropdown for single selection', () => {
184
+ jest.spyOn(wrapper.vm, 'closeAndFocus');
185
+ expect(wrapper.vm.closeAndFocus).not.toHaveBeenCalled();
186
+
187
+ findListboxItems().at(2).vm.$emit('select', true);
188
+
189
+ expect(wrapper.vm.closeAndFocus).toHaveBeenCalled();
190
+ });
182
191
  });
183
192
 
184
193
  describe('with groups', () => {
@@ -475,17 +484,47 @@ describe('GlCollapsibleListbox', () => {
475
484
  expect(wrapper).toHaveLoggedVueErrors();
476
485
  });
477
486
 
478
- it('shows the reset button if the label is provided and the selection is not empty', () => {
487
+ it.each`
488
+ title | multiple | selected
489
+ ${'shows'} | ${true} | ${mockOptionsValues}
490
+ ${'hides'} | ${false} | ${mockOptions[1].value}
491
+ `(
492
+ '$title the reset button if the label is provided and the selection is complete and mode if multiple mode is $multiple',
493
+ ({ multiple, selected }) => {
494
+ buildWrapper({
495
+ headerText: 'Select assignee',
496
+ resetButtonLabel: 'Unassign',
497
+ selected,
498
+ items: mockOptions,
499
+ multiple,
500
+ });
501
+
502
+ expect(findResetButton().exists()).toBe(multiple);
503
+ }
504
+ );
505
+
506
+ it('hides reset button if the label is provided and the selection is not complete', () => {
479
507
  buildWrapper({
480
508
  headerText: 'Select assignee',
481
509
  resetButtonLabel: 'Unassign',
482
510
  selected: mockOptions[1].value,
483
511
  items: mockOptions,
512
+ multiple: true,
484
513
  });
485
- const button = findResetButton();
486
514
 
487
- expect(button.exists()).toBe(true);
488
- expect(button.text()).toBe('Unassign');
515
+ expect(findResetButton().exists()).toBe(false);
516
+ });
517
+
518
+ it('hides reset button if dropdown has no items', () => {
519
+ buildWrapper({
520
+ headerText: 'Select assignee',
521
+ resetButtonLabel: 'Unassign',
522
+ selected: mockOptions[1].value,
523
+ items: [],
524
+ multiple: true,
525
+ });
526
+
527
+ expect(findResetButton().exists()).toBe(false);
489
528
  });
490
529
 
491
530
  it.each`
@@ -503,12 +542,13 @@ describe('GlCollapsibleListbox', () => {
503
542
  expect(findResetButton().exists()).toBe(false);
504
543
  });
505
544
 
506
- it('on click, emits the reset event and calls closeAndFocus()', () => {
545
+ it('on click, emits the reset event does not and call closeAndFocus() for multiple mode', () => {
507
546
  buildWrapper({
508
547
  headerText: 'Select assignee',
509
548
  resetButtonLabel: 'Unassign',
510
- selected: mockOptions[1].value,
549
+ selected: mockOptionsValues,
511
550
  items: mockOptions,
551
+ multiple: true,
512
552
  });
513
553
  jest.spyOn(wrapper.vm, 'closeAndFocus');
514
554
 
@@ -518,7 +558,7 @@ describe('GlCollapsibleListbox', () => {
518
558
  findResetButton().trigger('click');
519
559
 
520
560
  expect(wrapper.emitted('reset')).toHaveLength(1);
521
- expect(wrapper.vm.closeAndFocus).toHaveBeenCalled();
561
+ expect(wrapper.vm.closeAndFocus).not.toHaveBeenCalled();
522
562
  });
523
563
  });
524
564
 
@@ -533,12 +573,12 @@ describe('GlCollapsibleListbox', () => {
533
573
  });
534
574
 
535
575
  it.each`
536
- multiple | expectedResult
537
- ${false} | ${false}
538
- ${true} | ${true}
576
+ multiple | resetVisible | selectAllVisible
577
+ ${false} | ${false} | ${false}
578
+ ${true} | ${false} | ${true}
539
579
  `(
540
580
  'shows the select all button if the label is provided and the selection is empty and multiple option is $multiple',
541
- ({ multiple, expectedResult }) => {
581
+ ({ multiple, resetVisible, selectAllVisible }) => {
542
582
  buildWrapper({
543
583
  headerText: 'Select assignee',
544
584
  resetButtonLabel: 'Unassign',
@@ -548,11 +588,49 @@ describe('GlCollapsibleListbox', () => {
548
588
  multiple,
549
589
  });
550
590
 
551
- expect(findResetButton().exists()).toBe(!expectedResult);
552
- expect(findSelectAllButton().exists()).toBe(expectedResult);
591
+ expect(findResetButton().exists()).toBe(resetVisible);
592
+ expect(findSelectAllButton().exists()).toBe(selectAllVisible);
553
593
  }
554
594
  );
555
595
 
596
+ it('hides select all button if dropdown has no items', () => {
597
+ buildWrapper({
598
+ headerText: 'Select assignee',
599
+ resetButtonLabel: 'Unassign',
600
+ showSelectAllButtonLabel: 'Select All',
601
+ items: [],
602
+ multiple: true,
603
+ });
604
+
605
+ expect(findSelectAllButton().exists()).toBe(false);
606
+ });
607
+
608
+ it('hides select all button if all items are selected', () => {
609
+ buildWrapper({
610
+ headerText: 'Select assignee',
611
+ resetButtonLabel: 'Unassign',
612
+ showSelectAllButtonLabel: 'Select All',
613
+ selected: mockOptionsValues,
614
+ items: mockOptions,
615
+ multiple: true,
616
+ });
617
+
618
+ expect(findSelectAllButton().exists()).toBe(false);
619
+ });
620
+
621
+ it('has the label text "Select All" if the label is provided and some items are selected', () => {
622
+ buildWrapper({
623
+ headerText: 'Select assignee',
624
+ resetButtonLabel: 'Unassign',
625
+ showSelectAllButtonLabel: 'Select All',
626
+ selected: [mockOptions[1].value],
627
+ items: mockOptions,
628
+ multiple: true,
629
+ });
630
+
631
+ expect(findSelectAllButton().text()).toBe('Select All');
632
+ });
633
+
556
634
  it('has the label text "Select All" if the label is provided and the selection is empty', () => {
557
635
  buildWrapper({
558
636
  headerText: 'Select assignee',
@@ -345,7 +345,7 @@ export default {
345
345
  },
346
346
  computed: {
347
347
  listboxTag() {
348
- if (this.items.length === 0 || isOption(this.items[0])) return 'ul';
348
+ if (!this.hasItems || isOption(this.items[0])) return 'ul';
349
349
  return 'div';
350
350
  },
351
351
  listboxClasses() {
@@ -361,6 +361,9 @@ export default {
361
361
  flattenedOptions() {
362
362
  return flattenedOptions(this.items);
363
363
  },
364
+ hasItems() {
365
+ return this.items.length > 0;
366
+ },
364
367
  listboxToggleText() {
365
368
  if (!this.toggleText) {
366
369
  if (!this.multiple && this.selectedValues.length) {
@@ -394,8 +397,21 @@ export default {
394
397
  if (!this.resetButtonLabel) {
395
398
  return false;
396
399
  }
400
+
401
+ if (!this.multiple) {
402
+ return false;
403
+ }
404
+
405
+ /**
406
+ * if dropdown has no items
407
+ * reset all should be hidden
408
+ */
409
+ if (!this.hasItems) {
410
+ return false;
411
+ }
412
+
397
413
  if (this.multiple) {
398
- return this.selected.length > 0;
414
+ return this.selected.length === this.items.length;
399
415
  }
400
416
  return Boolean(this.selected);
401
417
  },
@@ -408,7 +424,15 @@ export default {
408
424
  return false;
409
425
  }
410
426
 
411
- return this.selected.length === 0;
427
+ /**
428
+ * if dropdown has no items
429
+ * select all should be hidden
430
+ */
431
+ if (!this.hasItems) {
432
+ return false;
433
+ }
434
+
435
+ return this.selected.length !== this.items.length;
412
436
  },
413
437
  showIntersectionObserver() {
414
438
  return this.infiniteScroll && !this.infiniteScrollLoading && !this.loading && !this.searching;
@@ -636,7 +660,6 @@ export default {
636
660
  * @event reset
637
661
  */
638
662
  this.$emit('reset');
639
- this.closeAndFocus();
640
663
  },
641
664
  onSelectAllButtonClicked() {
642
665
  /**
@@ -49,6 +49,8 @@ export const mockOptions = [
49
49
  },
50
50
  ];
51
51
 
52
+ export const mockOptionsValues = mockOptions.map(({ value }) => value);
53
+
52
54
  export const mockGroups = [
53
55
  {
54
56
  text: 'Branches',