@gitlab/ui 55.3.0 → 55.3.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 +7 -0
- package/dist/components/base/new_dropdowns/disclosure/constants.js +4 -0
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +7 -16
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown_group.js +3 -1
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.js +2 -0
- package/dist/components/base/new_dropdowns/disclosure/utils.js +23 -3
- package/package.json +1 -1
- package/src/components/base/new_dropdowns/disclosure/constants.js +2 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.spec.js +51 -8
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.stories.js +18 -13
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +6 -18
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown_group.vue +4 -2
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.vue +2 -0
- package/src/components/base/new_dropdowns/disclosure/utils.js +28 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [55.3.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v55.3.0...v55.3.1) (2023-02-16)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **GlDisclosureDropdown:** Improve markup semantics of dropdown wrapper ([79b1922](https://gitlab.com/gitlab-org/gitlab-ui/commit/79b19229c617904cc300a58d54c6ff04b742bb53))
|
|
7
|
+
|
|
1
8
|
# [55.3.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v55.2.1...v55.3.0) (2023-02-16)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -6,7 +6,7 @@ import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions, dropd
|
|
|
6
6
|
import GlBaseDropdown from '../base_dropdown/base_dropdown';
|
|
7
7
|
import GlDisclosureDropdownItem, { ITEM_CLASS } from './disclosure_dropdown_item';
|
|
8
8
|
import GlDisclosureDropdownGroup from './disclosure_dropdown_group';
|
|
9
|
-
import { itemsValidator,
|
|
9
|
+
import { itemsValidator, hasOnlyListItems, isItem } from './utils';
|
|
10
10
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
11
11
|
|
|
12
12
|
var script = {
|
|
@@ -157,21 +157,12 @@ var script = {
|
|
|
157
157
|
};
|
|
158
158
|
},
|
|
159
159
|
computed: {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
tag: 'ul'
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
if (isAllGroups(this.items)) return {
|
|
168
|
-
tag: 'div',
|
|
169
|
-
role: 'group'
|
|
170
|
-
};
|
|
160
|
+
disclosureTag() {
|
|
161
|
+
var _this$items;
|
|
162
|
+
if ((_this$items = this.items) !== null && _this$items !== void 0 && _this$items.length || hasOnlyListItems(this.$scopedSlots)) {
|
|
163
|
+
return 'ul';
|
|
171
164
|
}
|
|
172
|
-
return
|
|
173
|
-
tag: 'div'
|
|
174
|
-
};
|
|
165
|
+
return 'div';
|
|
175
166
|
},
|
|
176
167
|
hasCustomToggle() {
|
|
177
168
|
return Boolean(this.$scopedSlots.toggle);
|
|
@@ -265,7 +256,7 @@ var script = {
|
|
|
265
256
|
const __vue_script__ = script;
|
|
266
257
|
|
|
267
258
|
/* template */
|
|
268
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",staticClass:"gl-disclosure-dropdown",attrs:{"aria-labelledby":_vm.toggleAriaLabelledBy,"toggle-id":_vm.toggleId,"toggle-text":_vm.toggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"placement":_vm.placement},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.
|
|
259
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",staticClass:"gl-disclosure-dropdown",attrs:{"aria-labelledby":_vm.toggleAriaLabelledBy,"toggle-id":_vm.toggleId,"toggle-text":_vm.toggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"placement":_vm.placement},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureTag,{ref:"content",tag:"component",staticClass:"gl-new-dropdown-contents",attrs:{"id":_vm.disclosureId,"aria-labelledby":_vm.listAriaLabelledBy || _vm.toggleId,"data-testid":"disclosure-content","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},[_vm._t("default",function(){return [_vm._l((_vm.items),function(item,index){return [(_vm.isItem(item))?[_c('gl-disclosure-dropdown-item',{key:item.text,attrs:{"item":item},on:{"action":_vm.handleAction}},[_vm._t("list-item",null,{"item":item})],2)]:[_c('gl-disclosure-dropdown-group',{key:item.name,attrs:{"bordered":index !== 0,"group":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null],null,true)},[_vm._v(" "),(_vm.$scopedSlots['list-item'])?_vm._l((item.items),function(groupItem){return _c('gl-disclosure-dropdown-item',{key:groupItem.text,attrs:{"item":groupItem},on:{"action":_vm.handleAction}},[_vm._t("list-item",null,{"item":groupItem})],2)}):_vm._e()],2)]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
|
|
269
260
|
var __vue_staticRenderFns__ = [];
|
|
270
261
|
|
|
271
262
|
/* style */
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import _uniqueId from 'lodash/uniqueId';
|
|
2
2
|
import GlDisclosureDropdownItem from './disclosure_dropdown_item';
|
|
3
3
|
import { isGroup } from './utils';
|
|
4
|
+
import { DISCLOSURE_DROPDOWN_GROUP_NAME } from './constants';
|
|
4
5
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
5
6
|
|
|
6
7
|
const GROUP_TOP_BORDER_CLASSES = 'gl-border-t gl-pt-2 gl-mt-2';
|
|
7
8
|
var script = {
|
|
9
|
+
name: DISCLOSURE_DROPDOWN_GROUP_NAME,
|
|
8
10
|
components: {
|
|
9
11
|
GlDisclosureDropdownItem
|
|
10
12
|
},
|
|
@@ -54,7 +56,7 @@ var script = {
|
|
|
54
56
|
const __vue_script__ = script;
|
|
55
57
|
|
|
56
58
|
/* template */
|
|
57
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('
|
|
59
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{class:_vm.borderClass},[(_vm.showHeader)?_c('div',{staticClass:"gl-pl-4 gl-py-2 gl-font-sm gl-font-weight-bold",attrs:{"id":_vm.nameId,"aria-hidden":"true"}},[_vm._t("group-label",function(){return [_vm._v(_vm._s(_vm.group.name))]})],2):_vm._e(),_vm._v(" "),_c('ul',{staticClass:"gl-mb-0 gl-pl-0 gl-list-style-none",attrs:{"role":"group","aria-labelledby":_vm.groupLabeledBy}},[_vm._t("default",function(){return _vm._l((_vm.group.items),function(item){return _c('gl-disclosure-dropdown-item',{key:item.text,attrs:{"item":item},on:{"action":_vm.handleAction}},[_vm._t("list-item",null,{"item":item})],2)})})],2)])};
|
|
58
60
|
var __vue_staticRenderFns__ = [];
|
|
59
61
|
|
|
60
62
|
/* style */
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { ENTER, SPACE } from '../constants';
|
|
2
2
|
import { stopEvent } from '../../../../utils/utils';
|
|
3
3
|
import { isItem } from './utils';
|
|
4
|
+
import { DISCLOSURE_DROPDOWN_ITEM_NAME } from './constants';
|
|
4
5
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
5
6
|
|
|
6
7
|
const ITEM_CLASS = 'gl-new-dropdown-item';
|
|
7
8
|
var script = {
|
|
9
|
+
name: DISCLOSURE_DROPDOWN_ITEM_NAME,
|
|
8
10
|
ITEM_CLASS,
|
|
9
11
|
props: {
|
|
10
12
|
item: {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import _isFunction from 'lodash/isFunction';
|
|
2
|
+
import { DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME } from './constants';
|
|
3
|
+
|
|
1
4
|
const itemValidator = item => {
|
|
2
5
|
var _item$text;
|
|
3
6
|
return (item === null || item === void 0 ? void 0 : (_item$text = item.text) === null || _item$text === void 0 ? void 0 : _item$text.length) > 0 && !Array.isArray(item === null || item === void 0 ? void 0 : item.items);
|
|
@@ -5,7 +8,24 @@ const itemValidator = item => {
|
|
|
5
8
|
const isItem = item => Boolean(item) && itemValidator(item);
|
|
6
9
|
const isGroup = group => Boolean(group) && Array.isArray(group.items) && Boolean(group.items.length) && group.items.every(isItem);
|
|
7
10
|
const itemsValidator = items => items.every(isItem) || items.every(isGroup);
|
|
8
|
-
const
|
|
9
|
-
const
|
|
11
|
+
const isListItem = tag => ['gl-disclosure-dropdown-group', 'gl-disclosure-dropdown-item', 'li'].includes(tag);
|
|
12
|
+
const isValidSlotTagVue2 = vNode => {
|
|
13
|
+
var _vNode$componentOptio;
|
|
14
|
+
return Boolean(vNode) && isListItem(((_vNode$componentOptio = vNode.componentOptions) === null || _vNode$componentOptio === void 0 ? void 0 : _vNode$componentOptio.tag) || vNode.tag);
|
|
15
|
+
};
|
|
16
|
+
const isValidSlotTag = vNode => {
|
|
17
|
+
var _vNode$type;
|
|
18
|
+
return [DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME].includes((_vNode$type = vNode.type) === null || _vNode$type === void 0 ? void 0 : _vNode$type.name) || vNode.type === 'li';
|
|
19
|
+
};
|
|
20
|
+
const hasOnlyListItems = _ref => {
|
|
21
|
+
let {
|
|
22
|
+
default: defaultSlot
|
|
23
|
+
} = _ref;
|
|
24
|
+
if (!_isFunction(defaultSlot)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const nodes = defaultSlot();
|
|
28
|
+
return Array.isArray(nodes) && nodes.filter(vNode => vNode.tag).length && (nodes.filter(vNode => vNode.tag).every(isValidSlotTagVue2) || nodes.filter(vNode => vNode.tag).every(isValidSlotTag));
|
|
29
|
+
};
|
|
10
30
|
|
|
11
|
-
export {
|
|
31
|
+
export { hasOnlyListItems, isGroup, isItem, itemsValidator };
|
package/package.json
CHANGED
|
@@ -22,6 +22,7 @@ describe('GlDisclosureDropdown', () => {
|
|
|
22
22
|
const buildWrapper = (propsData, slots = {}) => {
|
|
23
23
|
wrapper = mount(GlDisclosureDropdown, {
|
|
24
24
|
propsData,
|
|
25
|
+
components: { GlDisclosureDropdownItem, GlDisclosureDropdownGroup },
|
|
25
26
|
slots,
|
|
26
27
|
attachTo: document.body,
|
|
27
28
|
});
|
|
@@ -216,23 +217,65 @@ describe('GlDisclosureDropdown', () => {
|
|
|
216
217
|
});
|
|
217
218
|
});
|
|
218
219
|
|
|
219
|
-
describe('disclosure
|
|
220
|
-
it('should render
|
|
220
|
+
describe('disclosure tag', () => {
|
|
221
|
+
it('should render `ul` as content tag when items is a list of items', () => {
|
|
221
222
|
buildWrapper({ items: mockItems });
|
|
222
223
|
expect(findDisclosureContent().element.tagName).toBe('UL');
|
|
223
|
-
expect(findDisclosureContent().attributes('role')).toBeUndefined();
|
|
224
224
|
});
|
|
225
225
|
|
|
226
|
-
it('should render
|
|
226
|
+
it('should render `ul` as content tag when items is a list of groups', () => {
|
|
227
227
|
buildWrapper({ items: mockGroups });
|
|
228
|
+
expect(findDisclosureContent().element.tagName).toBe('UL');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should render `ul` as content tag when default slot contains only groups', () => {
|
|
232
|
+
const slots = {
|
|
233
|
+
default: `
|
|
234
|
+
<gl-disclosure-dropdown-group>
|
|
235
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
236
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
237
|
+
</gl-disclosure-dropdown-group>
|
|
238
|
+
<gl-disclosure-dropdown-group>
|
|
239
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
240
|
+
</gl-disclosure-dropdown-group>
|
|
241
|
+
`,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
buildWrapper({}, slots);
|
|
245
|
+
expect(findDisclosureContent().element.tagName).toBe('UL');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('should render `ul` as content tag when default slot contains only items', () => {
|
|
249
|
+
const slots = {
|
|
250
|
+
default: `
|
|
251
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
252
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
253
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
254
|
+
`,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
buildWrapper({}, slots);
|
|
258
|
+
expect(findDisclosureContent().element.tagName).toBe('UL');
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('should render `div` as content tag when default slot does not contain valid list item', () => {
|
|
262
|
+
const slots = {
|
|
263
|
+
default: `
|
|
264
|
+
<div>Item</div>
|
|
265
|
+
<gl-disclosure-dropdown-group>
|
|
266
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
267
|
+
<gl-disclosure-dropdown-item>Item</gl-disclosure-dropdown-item>
|
|
268
|
+
</gl-disclosure-dropdown-group>
|
|
269
|
+
`,
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
buildWrapper({}, slots);
|
|
228
273
|
expect(findDisclosureContent().element.tagName).toBe('DIV');
|
|
229
|
-
expect(findDisclosureContent().attributes('role')).toBe('group');
|
|
230
274
|
});
|
|
231
275
|
|
|
232
|
-
it('should render
|
|
233
|
-
buildWrapper({
|
|
276
|
+
it('should render `div` as content tag when slot is not a list item', () => {
|
|
277
|
+
buildWrapper({}, { default: 'Some other content' });
|
|
234
278
|
expect(findDisclosureContent().element.tagName).toBe('DIV');
|
|
235
|
-
expect(findDisclosureContent().attributes('role')).toBeUndefined();
|
|
236
279
|
});
|
|
237
280
|
});
|
|
238
281
|
});
|
|
@@ -52,13 +52,16 @@ function openDisclosure(component) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const template = (content, { bindingOverrides = {} } = {}) => `
|
|
55
|
+
const template = (content, { bindingOverrides = {} } = {}, after) => `
|
|
56
|
+
<div>
|
|
56
57
|
<gl-disclosure-dropdown
|
|
57
58
|
ref="disclosure"
|
|
58
59
|
${makeBindings(bindingOverrides)}
|
|
59
60
|
>
|
|
60
61
|
${content || ''}
|
|
61
62
|
</gl-disclosure-dropdown>
|
|
63
|
+
${after || ''}
|
|
64
|
+
</div>
|
|
62
65
|
`;
|
|
63
66
|
|
|
64
67
|
const TOGGLE_ID = 'custom-toggle-id';
|
|
@@ -217,15 +220,14 @@ CustomGroupsAndItems.args = {
|
|
|
217
220
|
CustomGroupsAndItems.decorators = [makeContainer({ height: '200px' })];
|
|
218
221
|
|
|
219
222
|
export const CustomGroupsItemsAndToggle = makeGroupedExample({
|
|
220
|
-
template: template(
|
|
221
|
-
|
|
222
|
-
<
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
<div role="group">
|
|
223
|
+
template: template(
|
|
224
|
+
`
|
|
225
|
+
<template #toggle>
|
|
226
|
+
<span class="gl-sr-only">
|
|
227
|
+
Orange Fox user's menu
|
|
228
|
+
</span>
|
|
229
|
+
<gl-avatar :size="32" entity-name="Orange Fox" aria-hidden="true"></gl-avatar>
|
|
230
|
+
</template>
|
|
229
231
|
<gl-disclosure-dropdown-group>
|
|
230
232
|
<gl-disclosure-dropdown-item>
|
|
231
233
|
<span class="gl-display-flex gl-flex-direction-column">
|
|
@@ -256,15 +258,18 @@ export const CustomGroupsItemsAndToggle = makeGroupedExample({
|
|
|
256
258
|
<gl-toggle label="New navigation" label-position="left" v-model="newNavigation"/>
|
|
257
259
|
</gl-disclosure-dropdown-item>
|
|
258
260
|
<gl-disclosure-dropdown-item @action="toggleModalVisibility(true)">
|
|
259
|
-
|
|
261
|
+
Provide feedback
|
|
260
262
|
</gl-disclosure-dropdown-item>
|
|
261
263
|
</gl-disclosure-dropdown-group>
|
|
262
264
|
<gl-disclosure-dropdown-group bordered :group="$options.groups[1]"> </gl-disclosure-dropdown-group>
|
|
265
|
+
`,
|
|
266
|
+
{},
|
|
267
|
+
`
|
|
263
268
|
<gl-modal :visible="feedBackModalVisible" @change="toggleModalVisibility" modal-id="feedbackModal" size="sm">
|
|
264
269
|
<textarea class="gl-w-full">Tell us what you think!</textarea>
|
|
265
270
|
</gl-modal>
|
|
266
|
-
|
|
267
|
-
|
|
271
|
+
`
|
|
272
|
+
),
|
|
268
273
|
data() {
|
|
269
274
|
return {
|
|
270
275
|
newNavigation: true,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import GlBaseDropdown from '../base_dropdown/base_dropdown.vue';
|
|
20
20
|
import GlDisclosureDropdownItem, { ITEM_CLASS } from './disclosure_dropdown_item.vue';
|
|
21
21
|
import GlDisclosureDropdownGroup from './disclosure_dropdown_group.vue';
|
|
22
|
-
import { itemsValidator, isItem,
|
|
22
|
+
import { itemsValidator, isItem, hasOnlyListItems } from './utils';
|
|
23
23
|
|
|
24
24
|
export default {
|
|
25
25
|
events: {
|
|
@@ -169,22 +169,11 @@ export default {
|
|
|
169
169
|
};
|
|
170
170
|
},
|
|
171
171
|
computed: {
|
|
172
|
-
|
|
173
|
-
if (this.items) {
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
tag: 'ul',
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (isAllGroups(this.items))
|
|
181
|
-
return {
|
|
182
|
-
tag: 'div',
|
|
183
|
-
role: 'group',
|
|
184
|
-
};
|
|
172
|
+
disclosureTag() {
|
|
173
|
+
if (this.items?.length || hasOnlyListItems(this.$scopedSlots)) {
|
|
174
|
+
return 'ul';
|
|
185
175
|
}
|
|
186
|
-
|
|
187
|
-
return { tag: 'div' };
|
|
176
|
+
return 'div';
|
|
188
177
|
},
|
|
189
178
|
hasCustomToggle() {
|
|
190
179
|
return Boolean(this.$scopedSlots.toggle);
|
|
@@ -305,10 +294,9 @@ export default {
|
|
|
305
294
|
<slot name="header"></slot>
|
|
306
295
|
|
|
307
296
|
<component
|
|
308
|
-
:is="
|
|
297
|
+
:is="disclosureTag"
|
|
309
298
|
:id="disclosureId"
|
|
310
299
|
ref="content"
|
|
311
|
-
:role="disclosureOptions.role"
|
|
312
300
|
:aria-labelledby="listAriaLabelledBy || toggleId"
|
|
313
301
|
data-testid="disclosure-content"
|
|
314
302
|
class="gl-new-dropdown-contents"
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { uniqueId } from 'lodash';
|
|
3
3
|
import GlDisclosureDropdownItem from './disclosure_dropdown_item.vue';
|
|
4
4
|
import { isGroup } from './utils';
|
|
5
|
+
import { DISCLOSURE_DROPDOWN_GROUP_NAME } from './constants';
|
|
5
6
|
|
|
6
7
|
export const GROUP_TOP_BORDER_CLASSES = 'gl-border-t gl-pt-2 gl-mt-2';
|
|
7
8
|
|
|
8
9
|
export default {
|
|
10
|
+
name: DISCLOSURE_DROPDOWN_GROUP_NAME,
|
|
9
11
|
components: {
|
|
10
12
|
GlDisclosureDropdownItem,
|
|
11
13
|
},
|
|
@@ -52,7 +54,7 @@ export default {
|
|
|
52
54
|
</script>
|
|
53
55
|
|
|
54
56
|
<template>
|
|
55
|
-
<
|
|
57
|
+
<li :class="borderClass">
|
|
56
58
|
<div
|
|
57
59
|
v-if="showHeader"
|
|
58
60
|
:id="nameId"
|
|
@@ -73,5 +75,5 @@ export default {
|
|
|
73
75
|
</gl-disclosure-dropdown-item>
|
|
74
76
|
</slot>
|
|
75
77
|
</ul>
|
|
76
|
-
</
|
|
78
|
+
</li>
|
|
77
79
|
</template>
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { ENTER, SPACE } from '../constants';
|
|
3
3
|
import { stopEvent } from '../../../../utils/utils';
|
|
4
4
|
import { isItem } from './utils';
|
|
5
|
+
import { DISCLOSURE_DROPDOWN_ITEM_NAME } from './constants';
|
|
5
6
|
|
|
6
7
|
export const ITEM_CLASS = 'gl-new-dropdown-item';
|
|
7
8
|
|
|
8
9
|
export default {
|
|
10
|
+
name: DISCLOSURE_DROPDOWN_ITEM_NAME,
|
|
9
11
|
ITEM_CLASS,
|
|
10
12
|
props: {
|
|
11
13
|
item: {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { isFunction } from 'lodash';
|
|
2
|
+
import { DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME } from './constants';
|
|
3
|
+
|
|
1
4
|
const itemValidator = (item) => item?.text?.length > 0 && !Array.isArray(item?.items);
|
|
2
5
|
|
|
3
6
|
const isItem = (item) => Boolean(item) && itemValidator(item);
|
|
@@ -10,8 +13,30 @@ const isGroup = (group) =>
|
|
|
10
13
|
|
|
11
14
|
const itemsValidator = (items) => items.every(isItem) || items.every(isGroup);
|
|
12
15
|
|
|
13
|
-
const
|
|
16
|
+
const isListItem = (tag) =>
|
|
17
|
+
['gl-disclosure-dropdown-group', 'gl-disclosure-dropdown-item', 'li'].includes(tag);
|
|
18
|
+
|
|
19
|
+
const isValidSlotTagVue2 = (vNode) =>
|
|
20
|
+
Boolean(vNode) && isListItem(vNode.componentOptions?.tag || vNode.tag);
|
|
21
|
+
|
|
22
|
+
const isValidSlotTag = (vNode) => {
|
|
23
|
+
return (
|
|
24
|
+
[DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME].includes(vNode.type?.name) ||
|
|
25
|
+
vNode.type === 'li'
|
|
26
|
+
);
|
|
27
|
+
};
|
|
14
28
|
|
|
15
|
-
const
|
|
29
|
+
const hasOnlyListItems = ({ default: defaultSlot }) => {
|
|
30
|
+
if (!isFunction(defaultSlot)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const nodes = defaultSlot();
|
|
34
|
+
return (
|
|
35
|
+
Array.isArray(nodes) &&
|
|
36
|
+
nodes.filter((vNode) => vNode.tag).length &&
|
|
37
|
+
(nodes.filter((vNode) => vNode.tag).every(isValidSlotTagVue2) ||
|
|
38
|
+
nodes.filter((vNode) => vNode.tag).every(isValidSlotTag))
|
|
39
|
+
);
|
|
40
|
+
};
|
|
16
41
|
|
|
17
|
-
export { itemsValidator, isItem, isGroup,
|
|
42
|
+
export { itemsValidator, isItem, isGroup, hasOnlyListItems };
|