@gitlab/ui 53.3.0 → 54.1.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 +34 -0
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.js +19 -13
- package/dist/components/base/new_dropdowns/disclosure/utils.js +3 -7
- package/dist/index.js +0 -1
- package/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/package.json +1 -1
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.md +18 -12
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.spec.js +19 -9
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.vue +16 -13
- package/src/components/base/new_dropdowns/disclosure/utils.js +1 -2
- package/src/components/base/new_dropdowns/disclosure/utils.spec.js +1 -0
- package/src/index.js +0 -1
- package/src/scss/utilities.scss +6 -0
- package/src/scss/utility-mixins/spacing.scss +4 -0
- package/dist/components/editors/rich_text_editor/rich_text_editor.js +0 -41
- package/src/components/editors/rich_text_editor/rich_text_editor.md +0 -38
- package/src/components/editors/rich_text_editor/rich_text_editor.spec.js +0 -9
- package/src/components/editors/rich_text_editor/rich_text_editor.stories.js +0 -25
- package/src/components/editors/rich_text_editor/rich_text_editor.vue +0 -7
package/package.json
CHANGED
|
@@ -44,8 +44,12 @@ After closing, `GlDisclosureDropdown` emits a `hidden` event.
|
|
|
44
44
|
|
|
45
45
|
### Setting disclosure dropdown items
|
|
46
46
|
|
|
47
|
-
Use the `items` prop to provide actions/links to the disclosure dropdown. Each
|
|
48
|
-
either an item or a group. For `Item`s,
|
|
47
|
+
Use the `items` prop to provide actions/links to the disclosure dropdown. Each
|
|
48
|
+
item can be either an item or a group. For `Item`s, provide an `href` string to
|
|
49
|
+
make them render as links. Otherwise, they will be buttons. Provide an `action`
|
|
50
|
+
function to items to be called when they are pressed, or, listen for the
|
|
51
|
+
`action` event on the top-level component. Both will receive the given item as
|
|
52
|
+
an argument.
|
|
49
53
|
A <!-- markdownlint-disable-next-line line-length -->
|
|
50
54
|
[validation error](https://gitlab.com/gitlab-org/gitlab-ui/-/blob/6cbff4f908b429cc01f17a4cc2868e881db1aa31/src/components/base/new_dropdowns/disclosure/utils.js#L1)
|
|
51
55
|
will be triggered if neither field is set.
|
|
@@ -56,7 +60,7 @@ Below are the expected shapes of these objects:
|
|
|
56
60
|
type Item = {
|
|
57
61
|
text: string
|
|
58
62
|
href?: string,
|
|
59
|
-
action?:
|
|
63
|
+
action?: (item: Item) => void,
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
type Group = {
|
|
@@ -75,15 +79,17 @@ template. If you want to render a custom template for items, use the
|
|
|
75
79
|
|
|
76
80
|
```html
|
|
77
81
|
<gl-disclosure-dropdown :items="items">
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
<template #list-item="{ item }">
|
|
83
|
+
<a
|
|
84
|
+
class="gl-hover-text-decoration-none gl-text-gray-900"
|
|
85
|
+
tabindex="-1"
|
|
86
|
+
:href="item.href"
|
|
87
|
+
v-bind="item.extraAttrs"
|
|
88
|
+
>
|
|
89
|
+
{{ item.text }}
|
|
90
|
+
<gl-badge v-if="item.count" pill variant="info">{{ item.count }}</gl-badge>
|
|
91
|
+
</a>
|
|
92
|
+
</template>
|
|
87
93
|
</gl-disclosure-dropdown>
|
|
88
94
|
```
|
|
89
95
|
|
|
@@ -18,8 +18,10 @@ describe('GlDisclosureDropdownItem', () => {
|
|
|
18
18
|
describe('when default slot content provided', () => {
|
|
19
19
|
const content = 'This is an item';
|
|
20
20
|
const slots = { default: content };
|
|
21
|
+
const item = mockItems[1];
|
|
22
|
+
|
|
21
23
|
beforeEach(() => {
|
|
22
|
-
buildWrapper({}, slots);
|
|
24
|
+
buildWrapper({ item }, slots);
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
it('renders it', () => {
|
|
@@ -33,7 +35,7 @@ describe('GlDisclosureDropdownItem', () => {
|
|
|
33
35
|
${() => findItem().trigger('keydown', { code: SPACE })} | ${'SPACE'}
|
|
34
36
|
`(`$event should emit 'action' event`, ({ trigger }) => {
|
|
35
37
|
trigger();
|
|
36
|
-
expect(wrapper.emitted('action')).
|
|
38
|
+
expect(wrapper.emitted('action')).toEqual([[item]]);
|
|
37
39
|
});
|
|
38
40
|
});
|
|
39
41
|
|
|
@@ -55,10 +57,11 @@ describe('GlDisclosureDropdownItem', () => {
|
|
|
55
57
|
});
|
|
56
58
|
|
|
57
59
|
describe('when item has an `action`', () => {
|
|
58
|
-
const
|
|
60
|
+
const item = mockItems[1];
|
|
61
|
+
const action = jest.spyOn(item, 'action');
|
|
59
62
|
|
|
60
63
|
beforeEach(() => {
|
|
61
|
-
buildWrapper({ item
|
|
64
|
+
buildWrapper({ item });
|
|
62
65
|
action.mockClear();
|
|
63
66
|
});
|
|
64
67
|
|
|
@@ -69,16 +72,23 @@ describe('GlDisclosureDropdownItem', () => {
|
|
|
69
72
|
});
|
|
70
73
|
|
|
71
74
|
it('should set correct attributes', () => {
|
|
72
|
-
const attrs = { ...
|
|
75
|
+
const attrs = { ...item.extraAttrs };
|
|
73
76
|
delete attrs.class;
|
|
74
|
-
expect(findButton().classes()).toContain(
|
|
77
|
+
expect(findButton().classes()).toContain(item.extraAttrs.class);
|
|
75
78
|
expect(findButton().attributes()).toMatchObject(attrs);
|
|
76
79
|
});
|
|
77
80
|
|
|
78
81
|
it('should call `action` on `click`', () => {
|
|
79
82
|
findButton().trigger('click');
|
|
80
|
-
expect(action).
|
|
81
|
-
|
|
83
|
+
expect(action).toHaveBeenCalledTimes(1);
|
|
84
|
+
|
|
85
|
+
const actionThisArg = action.mock.contexts[0];
|
|
86
|
+
expect(actionThisArg).toBe(undefined);
|
|
87
|
+
|
|
88
|
+
const actionArgs = action.mock.calls[0];
|
|
89
|
+
expect(actionArgs).toEqual([item]);
|
|
90
|
+
|
|
91
|
+
expect(wrapper.emitted('action')).toEqual([[item]]);
|
|
82
92
|
});
|
|
83
93
|
|
|
84
94
|
it.each`
|
|
@@ -88,7 +98,7 @@ describe('GlDisclosureDropdownItem', () => {
|
|
|
88
98
|
${() => findItem().trigger('keydown', { code: SPACE })} | ${'SPACE'}
|
|
89
99
|
`(`$event will execute action and emit 'action' event`, ({ trigger }) => {
|
|
90
100
|
trigger();
|
|
91
|
-
expect(wrapper.emitted('action')).
|
|
101
|
+
expect(wrapper.emitted('action')).toEqual([[item]]);
|
|
92
102
|
});
|
|
93
103
|
});
|
|
94
104
|
});
|
|
@@ -16,31 +16,34 @@ export default {
|
|
|
16
16
|
},
|
|
17
17
|
},
|
|
18
18
|
computed: {
|
|
19
|
-
|
|
20
|
-
return this.item?.
|
|
19
|
+
isLink() {
|
|
20
|
+
return typeof this.item?.href === 'string';
|
|
21
21
|
},
|
|
22
22
|
isCustomContent() {
|
|
23
23
|
return Boolean(this.$scopedSlots.default);
|
|
24
24
|
},
|
|
25
25
|
itemComponent() {
|
|
26
|
-
|
|
26
|
+
const { item } = this;
|
|
27
|
+
|
|
28
|
+
if (this.isLink)
|
|
27
29
|
return {
|
|
28
|
-
is: '
|
|
30
|
+
is: 'a',
|
|
29
31
|
attrs: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
listeners: {
|
|
34
|
-
click: () => this.item.action(),
|
|
32
|
+
href: item.href,
|
|
33
|
+
...item.extraAttrs,
|
|
35
34
|
},
|
|
35
|
+
listeners: {},
|
|
36
36
|
};
|
|
37
|
+
|
|
37
38
|
return {
|
|
38
|
-
is: '
|
|
39
|
+
is: 'button',
|
|
39
40
|
attrs: {
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
...item.extraAttrs,
|
|
42
|
+
type: 'button',
|
|
43
|
+
},
|
|
44
|
+
listeners: {
|
|
45
|
+
click: () => item.action?.call(undefined, item),
|
|
42
46
|
},
|
|
43
|
-
listeners: {},
|
|
44
47
|
};
|
|
45
48
|
},
|
|
46
49
|
},
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const itemValidator = (
|
|
2
|
-
Boolean(text?.length && (href?.length || typeof action === 'function'));
|
|
1
|
+
const itemValidator = (item) => item?.text?.length > 0 && !Array.isArray(item?.items);
|
|
3
2
|
|
|
4
3
|
const isItem = (item) => Boolean(item) && itemValidator(item);
|
|
5
4
|
|
package/src/index.js
CHANGED
|
@@ -98,7 +98,6 @@ export { default as GlAccordion } from './components/base/accordion/accordion.vu
|
|
|
98
98
|
export { default as GlAccordionItem } from './components/base/accordion/accordion_item.vue';
|
|
99
99
|
export { default as GlCarousel } from './components/base/carousel/carousel.vue';
|
|
100
100
|
export { default as GlCarouselSlide } from './components/base/carousel/carousel_slide.vue';
|
|
101
|
-
export { default as RichTextEditor } from './components/editors/rich_text_editor/rich_text_editor.vue';
|
|
102
101
|
|
|
103
102
|
// Utilities
|
|
104
103
|
export { default as GlAnimatedNumber } from './components/utilities/animated_number/animated_number.vue';
|
package/src/scss/utilities.scss
CHANGED
|
@@ -6374,6 +6374,12 @@
|
|
|
6374
6374
|
margin-top: #{$gl-spacing-scale-3} !important;
|
|
6375
6375
|
}
|
|
6376
6376
|
}
|
|
6377
|
+
.gl-gap-2 {
|
|
6378
|
+
gap: $gl-spacing-scale-2;
|
|
6379
|
+
}
|
|
6380
|
+
.gl-gap-2\! {
|
|
6381
|
+
gap: $gl-spacing-scale-2 !important;
|
|
6382
|
+
}
|
|
6377
6383
|
.gl-gap-3 {
|
|
6378
6384
|
gap: $gl-spacing-scale-3;
|
|
6379
6385
|
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
2
|
-
|
|
3
|
-
var script = {};
|
|
4
|
-
|
|
5
|
-
/* script */
|
|
6
|
-
const __vue_script__ = script;
|
|
7
|
-
|
|
8
|
-
/* template */
|
|
9
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_vm._v("This is a rich-text-editor")])};
|
|
10
|
-
var __vue_staticRenderFns__ = [];
|
|
11
|
-
|
|
12
|
-
/* style */
|
|
13
|
-
const __vue_inject_styles__ = undefined;
|
|
14
|
-
/* scoped */
|
|
15
|
-
const __vue_scope_id__ = undefined;
|
|
16
|
-
/* module identifier */
|
|
17
|
-
const __vue_module_identifier__ = undefined;
|
|
18
|
-
/* functional template */
|
|
19
|
-
const __vue_is_functional_template__ = false;
|
|
20
|
-
/* style inject */
|
|
21
|
-
|
|
22
|
-
/* style inject SSR */
|
|
23
|
-
|
|
24
|
-
/* style inject shadow dom */
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const __vue_component__ = __vue_normalize__(
|
|
29
|
-
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
|
|
30
|
-
__vue_inject_styles__,
|
|
31
|
-
__vue_script__,
|
|
32
|
-
__vue_scope_id__,
|
|
33
|
-
__vue_is_functional_template__,
|
|
34
|
-
__vue_module_identifier__,
|
|
35
|
-
false,
|
|
36
|
-
undefined,
|
|
37
|
-
undefined,
|
|
38
|
-
undefined
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
export default __vue_component__;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
Briefly describe the component's purpose here.
|
|
3
|
-
This should correspond to the short description in Pajamas' website: https://design.gitlab.com/components/status/
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
The Rich Text Editor is a UI component that provides a WYSIWYG editing
|
|
7
|
-
experience for[GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.md#gitlab-flavored-markdown-gfm)
|
|
8
|
-
(GFM) in the GitLab application.
|
|
9
|
-
It also serves as the foundation for implementing Markdown-focused editors that target other engines,
|
|
10
|
-
like static site generators.
|
|
11
|
-
|
|
12
|
-
<!-- Provide technical information on how to use the component, add code examples if relevant. -->
|
|
13
|
-
|
|
14
|
-
<!--
|
|
15
|
-
## Dos and don'ts
|
|
16
|
-
|
|
17
|
-
If relevant, describe how the component is expected to be used, and how it's not.
|
|
18
|
-
-->
|
|
19
|
-
|
|
20
|
-
<!--
|
|
21
|
-
## Browser compatibility
|
|
22
|
-
|
|
23
|
-
If the component requires any polyfill or fallback on certain browsers, describe those requirements
|
|
24
|
-
here.
|
|
25
|
-
-->
|
|
26
|
-
|
|
27
|
-
<!--
|
|
28
|
-
## Edge cases
|
|
29
|
-
|
|
30
|
-
If the component has some known limitations, describe them here.
|
|
31
|
-
-->
|
|
32
|
-
|
|
33
|
-
<!--
|
|
34
|
-
## Deprecation warning
|
|
35
|
-
|
|
36
|
-
If and when this component introduced API changes that would require deprecating old APIs, describe
|
|
37
|
-
the changes here, and provide a migration paths to the new API.
|
|
38
|
-
-->
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import GlRichTextEditor from './rich_text_editor.vue';
|
|
3
|
-
|
|
4
|
-
describe('GlRichTextEditor', () => {
|
|
5
|
-
it('renders main components', () => {
|
|
6
|
-
const wrapper = shallowMount(GlRichTextEditor);
|
|
7
|
-
expect(wrapper).toBeInstanceOf(Object);
|
|
8
|
-
});
|
|
9
|
-
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import readme from './rich_text_editor.md';
|
|
2
|
-
import GlRichTextEditor from './rich_text_editor.vue';
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
title: 'editor/Rich Text Editor',
|
|
6
|
-
component: GlRichTextEditor,
|
|
7
|
-
parameters: {
|
|
8
|
-
docs: {
|
|
9
|
-
description: {
|
|
10
|
-
component: readme,
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
argTypes: {},
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const Template = (_, { argTypes }) => ({
|
|
18
|
-
components: { GlRichTextEditor },
|
|
19
|
-
props: Object.keys(argTypes),
|
|
20
|
-
template: `
|
|
21
|
-
<gl-rich-text-editor />
|
|
22
|
-
`,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const Default = Template.bind({});
|