@gitlab/ui 77.5.0 → 77.6.0

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,10 @@
1
+ # [77.6.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v77.5.0...v77.6.0) (2024-03-01)
2
+
3
+
4
+ ### Features
5
+
6
+ * **GlDisclosureDropdownItem:** Support Vue router links ([2bff76d](https://gitlab.com/gitlab-org/gitlab-ui/commit/2bff76de9f1c675eea407d92b646018395be0b2e))
7
+
1
8
  # [77.5.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v77.4.0...v77.5.0) (2024-03-01)
2
9
 
3
10
 
@@ -1,3 +1,4 @@
1
+ import { BLink } from 'bootstrap-vue/esm/index.js';
1
2
  import { ENTER, SPACE } from '../constants';
2
3
  import { stopEvent } from '../../../../utils/utils';
3
4
  import { isItem } from './utils';
@@ -8,6 +9,9 @@ const ITEM_CLASS = 'gl-new-dropdown-item';
8
9
  var script = {
9
10
  name: DISCLOSURE_DROPDOWN_ITEM_NAME,
10
11
  ITEM_CLASS,
12
+ components: {
13
+ BLink
14
+ },
11
15
  props: {
12
16
  item: {
13
17
  type: Object,
@@ -18,8 +22,8 @@ var script = {
18
22
  },
19
23
  computed: {
20
24
  isLink() {
21
- var _this$item;
22
- return typeof ((_this$item = this.item) === null || _this$item === void 0 ? void 0 : _this$item.href) === 'string';
25
+ var _this$item, _this$item2;
26
+ return typeof ((_this$item = this.item) === null || _this$item === void 0 ? void 0 : _this$item.href) === 'string' || typeof ((_this$item2 = this.item) === null || _this$item2 === void 0 ? void 0 : _this$item2.to) === 'string';
23
27
  },
24
28
  isCustomContent() {
25
29
  return Boolean(this.$scopedSlots.default);
@@ -29,9 +33,10 @@ var script = {
29
33
  item
30
34
  } = this;
31
35
  if (this.isLink) return {
32
- is: 'a',
36
+ is: BLink,
33
37
  attrs: {
34
38
  href: item.href,
39
+ to: item.to,
35
40
  ...item.extraAttrs
36
41
  },
37
42
  listeners: {
@@ -54,16 +59,16 @@ var script = {
54
59
  };
55
60
  },
56
61
  listIndex() {
57
- var _this$item2, _this$item2$extraAttr;
58
- return (_this$item2 = this.item) !== null && _this$item2 !== void 0 && (_this$item2$extraAttr = _this$item2.extraAttrs) !== null && _this$item2$extraAttr !== void 0 && _this$item2$extraAttr.disabled ? null : 0;
62
+ var _this$item3, _this$item3$extraAttr;
63
+ return (_this$item3 = this.item) !== null && _this$item3 !== void 0 && (_this$item3$extraAttr = _this$item3.extraAttrs) !== null && _this$item3$extraAttr !== void 0 && _this$item3$extraAttr.disabled ? null : 0;
59
64
  },
60
65
  componentIndex() {
61
- var _this$item3, _this$item3$extraAttr;
62
- return (_this$item3 = this.item) !== null && _this$item3 !== void 0 && (_this$item3$extraAttr = _this$item3.extraAttrs) !== null && _this$item3$extraAttr !== void 0 && _this$item3$extraAttr.disabled ? null : -1;
66
+ var _this$item4, _this$item4$extraAttr;
67
+ return (_this$item4 = this.item) !== null && _this$item4 !== void 0 && (_this$item4$extraAttr = _this$item4.extraAttrs) !== null && _this$item4$extraAttr !== void 0 && _this$item4$extraAttr.disabled ? null : -1;
63
68
  },
64
69
  wrapperClass() {
65
- var _this$item$wrapperCla, _this$item4;
66
- return (_this$item$wrapperCla = (_this$item4 = this.item) === null || _this$item4 === void 0 ? void 0 : _this$item4.wrapperClass) !== null && _this$item$wrapperCla !== void 0 ? _this$item$wrapperCla : '';
70
+ var _this$item$wrapperCla, _this$item5;
71
+ return (_this$item$wrapperCla = (_this$item5 = this.item) === null || _this$item5 === void 0 ? void 0 : _this$item5.wrapperClass) !== null && _this$item$wrapperCla !== void 0 ? _this$item$wrapperCla : '';
67
72
  },
68
73
  wrapperListeners() {
69
74
  const listeners = {
@@ -84,16 +89,21 @@ var script = {
84
89
  if (this.isCustomContent) {
85
90
  this.action();
86
91
  } else {
87
- var _this$$refs$item;
88
92
  stopEvent(event);
89
93
  /** Instead of simply navigating or calling the action, we want
90
94
  * the `a/button` to be the target of the event as it might have additional attributes.
91
95
  * E.g. `a` might have `target` attribute.
92
96
  */
93
- (_this$$refs$item = this.$refs.item) === null || _this$$refs$item === void 0 ? void 0 : _this$$refs$item.dispatchEvent(new MouseEvent('click', {
97
+ const e = new MouseEvent('click', {
94
98
  bubbles: true,
95
99
  cancelable: true
96
- }));
100
+ });
101
+ if (this.isLink) {
102
+ this.$refs.item.$el.dispatchEvent(e);
103
+ } else {
104
+ var _this$$refs$item;
105
+ (_this$$refs$item = this.$refs.item) === null || _this$$refs$item === void 0 ? void 0 : _this$$refs$item.dispatchEvent(e);
106
+ }
97
107
  }
98
108
  }
99
109
  },
@@ -24,6 +24,12 @@ const mockItems = [{
24
24
  rel: 'nofollow',
25
25
  target: '_blank'
26
26
  }
27
+ }, {
28
+ text: 'Edit merge request',
29
+ to: '/edit',
30
+ extraAttrs: {
31
+ 'data-uuid': '1234'
32
+ }
27
33
  }];
28
34
  const mockItemsCustomItem = [{
29
35
  text: 'Assigned to you',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 01 Mar 2024 12:16:54 GMT
3
+ * Generated on Fri, 01 Mar 2024 18:36:36 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 01 Mar 2024 12:16:54 GMT
3
+ * Generated on Fri, 01 Mar 2024 18:36:36 GMT
4
4
  */
5
5
 
6
6
  :root.gl-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 01 Mar 2024 12:16:54 GMT
3
+ * Generated on Fri, 01 Mar 2024 18:36:36 GMT
4
4
  */
5
5
 
6
6
  export const DATA_VIZ_GREEN_50 = "#133a03";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 01 Mar 2024 12:16:54 GMT
3
+ * Generated on Fri, 01 Mar 2024 18:36:36 GMT
4
4
  */
5
5
 
6
6
  export const DATA_VIZ_GREEN_50 = "#ddfab7";
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Fri, 01 Mar 2024 12:16:54 GMT
3
+ // Generated on Fri, 01 Mar 2024 18:36:36 GMT
4
4
 
5
5
  $gl-text-tertiary: #737278 !default;
6
6
  $gl-text-secondary: #89888d !default;
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Fri, 01 Mar 2024 12:16:54 GMT
3
+ // Generated on Fri, 01 Mar 2024 18:36:36 GMT
4
4
 
5
5
  $gl-text-tertiary: #89888d !default;
6
6
  $gl-text-secondary: #737278 !default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "77.5.0",
3
+ "version": "77.6.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -64,7 +64,7 @@ After closing, `GlDisclosureDropdown` emits a `hidden` event.
64
64
  ## Setting disclosure dropdown items
65
65
 
66
66
  Use the `items` prop to provide actions/links to the disclosure dropdown. Each
67
- item can be either an item or a group. For `Item`s, provide an `href` string to
67
+ item can be either an item or a group. For `Item`s, provide an `href` or `to` string to
68
68
  make them render as links. Otherwise, they will be buttons. Provide an `action`
69
69
  function to items to be called when they are pressed, or, listen for the
70
70
  `action` event on the top-level component. Both will receive the given item as
@@ -81,6 +81,8 @@ type Item = {
81
81
  text: string;
82
82
  // href link
83
83
  href?: string;
84
+ // or, a Vue router link with `to`
85
+ to?: string;
84
86
  // Item action
85
87
  action?: (item: Item) => void;
86
88
  // Set of extra attributes applied directly to the element
@@ -140,6 +140,7 @@ describe('GlDisclosureDropdown', () => {
140
140
  let firstItem;
141
141
  let secondItem;
142
142
  let thirdItem;
143
+ let fourthItem;
143
144
 
144
145
  beforeEach(() => {
145
146
  buildWrapper({ items: mockItems });
@@ -147,6 +148,7 @@ describe('GlDisclosureDropdown', () => {
147
148
  firstItem = findListItem(0);
148
149
  secondItem = findListItem(1);
149
150
  thirdItem = findListItem(2);
151
+ fourthItem = findListItem(3);
150
152
  });
151
153
 
152
154
  it('should move the focus from toggle and down the list of items on `ARROW_DOWN` and stop on the last item', async () => {
@@ -160,7 +162,9 @@ describe('GlDisclosureDropdown', () => {
160
162
  await secondItem.trigger('keydown', { code: ARROW_DOWN });
161
163
  expect(thirdItem.element).toHaveFocus();
162
164
  await thirdItem.trigger('keydown', { code: ARROW_DOWN });
163
- expect(thirdItem.element).toHaveFocus();
165
+ expect(fourthItem.element).toHaveFocus();
166
+ await fourthItem.trigger('keydown', { code: ARROW_DOWN });
167
+ expect(fourthItem.element).toHaveFocus();
164
168
  });
165
169
 
166
170
  it('should move the focus up the list of items on `ARROW_UP` and stop on the first item', async () => {
@@ -182,9 +186,9 @@ describe('GlDisclosureDropdown', () => {
182
186
  );
183
187
  expect(firstItem.element).toHaveFocus();
184
188
  await firstItem.trigger('keydown', { code: END });
185
- expect(thirdItem.element).toHaveFocus();
186
- await thirdItem.trigger('keydown', { code: END });
187
- expect(thirdItem.element).toHaveFocus();
189
+ expect(fourthItem.element).toHaveFocus();
190
+ await fourthItem.trigger('keydown', { code: END });
191
+ expect(fourthItem.element).toHaveFocus();
188
192
  });
189
193
 
190
194
  it('should move focus to the first item on `HOME` keydown', async () => {
@@ -1,4 +1,5 @@
1
1
  import { mount } from '@vue/test-utils';
2
+ import { BLink } from 'bootstrap-vue';
2
3
  import { ENTER, SPACE } from '../constants';
3
4
  import { mockItems } from './mock_data';
4
5
 
@@ -47,21 +48,29 @@ describe('GlDisclosureDropdownItem', () => {
47
48
  });
48
49
  });
49
50
 
50
- describe('when item has a `href`', () => {
51
- const item = mockItems[0];
51
+ describe.each`
52
+ prop | mockItem
53
+ ${'href'} | ${0}
54
+ ${'to'} | ${3}
55
+ `('when item has a `$prop`', ({ prop, mockItem }) => {
56
+ const item = mockItems[mockItem];
52
57
 
53
58
  beforeEach(() => {
54
59
  buildWrapper({ item });
55
60
  });
56
61
 
57
- const findLink = () => wrapper.find('a.gl-new-dropdown-item-content');
62
+ const findLink = () => wrapper.findComponent(BLink);
58
63
 
59
64
  it('should render a link', () => {
60
65
  expect(findLink().exists()).toBe(true);
61
66
  });
62
67
 
63
- it('should set correct attributes', () => {
64
- expect(findLink().attributes('href')).toBe(item.href);
68
+ it('should set correct class', () => {
69
+ expect(findLink().classes()).toContain('gl-new-dropdown-item-content');
70
+ });
71
+
72
+ it('should set correct props and attributes', () => {
73
+ expect(findLink().props(prop)).toBe(item[prop]);
65
74
  expect(findLink().attributes()).toEqual(expect.objectContaining(item.extraAttrs));
66
75
  });
67
76
 
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import { BLink } from 'bootstrap-vue';
2
3
  import { ENTER, SPACE } from '../constants';
3
4
  import { stopEvent } from '../../../../utils/utils';
4
5
  import { isItem } from './utils';
@@ -9,6 +10,7 @@ export const ITEM_CLASS = 'gl-new-dropdown-item';
9
10
  export default {
10
11
  name: DISCLOSURE_DROPDOWN_ITEM_NAME,
11
12
  ITEM_CLASS,
13
+ components: { BLink },
12
14
  props: {
13
15
  item: {
14
16
  type: Object,
@@ -19,7 +21,7 @@ export default {
19
21
  },
20
22
  computed: {
21
23
  isLink() {
22
- return typeof this.item?.href === 'string';
24
+ return typeof this.item?.href === 'string' || typeof this.item?.to === 'string';
23
25
  },
24
26
  isCustomContent() {
25
27
  return Boolean(this.$scopedSlots.default);
@@ -29,9 +31,10 @@ export default {
29
31
 
30
32
  if (this.isLink)
31
33
  return {
32
- is: 'a',
34
+ is: BLink,
33
35
  attrs: {
34
36
  href: item.href,
37
+ to: item.to,
35
38
  ...item.extraAttrs,
36
39
  },
37
40
  listeners: {
@@ -85,9 +88,12 @@ export default {
85
88
  * the `a/button` to be the target of the event as it might have additional attributes.
86
89
  * E.g. `a` might have `target` attribute.
87
90
  */
88
- this.$refs.item?.dispatchEvent(
89
- new MouseEvent('click', { bubbles: true, cancelable: true })
90
- );
91
+ const e = new MouseEvent('click', { bubbles: true, cancelable: true });
92
+ if (this.isLink) {
93
+ this.$refs.item.$el.dispatchEvent(e);
94
+ } else {
95
+ this.$refs.item?.dispatchEvent(e);
96
+ }
91
97
  }
92
98
  }
93
99
  },
@@ -28,6 +28,13 @@ export const mockItems = [
28
28
  target: '_blank',
29
29
  },
30
30
  },
31
+ {
32
+ text: 'Edit merge request',
33
+ to: '/edit',
34
+ extraAttrs: {
35
+ 'data-uuid': '1234',
36
+ },
37
+ },
31
38
  ];
32
39
 
33
40
  export const mockItemsCustomItem = [