@gitlab/ui 46.0.0 → 47.0.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 +25 -0
- package/dist/components/base/breadcrumb/breadcrumb.js +1 -1
- package/dist/components/base/datepicker/datepicker.js +17 -11
- package/dist/components/base/dropdown/dropdown.js +3 -3
- package/dist/components/base/filtered_search/filtered_search.js +1 -1
- package/dist/components/base/form/form_checkbox_tree/form_checkbox_tree.js +1 -1
- package/dist/components/base/form/form_checkbox_tree/models/tree.js +0 -1
- package/dist/components/base/infinite_scroll/infinite_scroll.js +17 -26
- package/dist/components/base/pagination/pagination.js +3 -1
- package/dist/components/base/search_box_by_click/search_box_by_click.js +1 -1
- package/dist/components/base/token_selector/token_container.js +1 -1
- package/dist/components/base/token_selector/token_selector.js +1 -1
- package/dist/components/charts/column/column.js +0 -1
- package/dist/components/utilities/intersperse/intersperse.js +1 -1
- package/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/package.json +7 -7
- package/src/components/base/alert/alert.spec.js +3 -3
- package/src/components/base/breadcrumb/breadcrumb.spec.js +0 -2
- package/src/components/base/breadcrumb/breadcrumb.vue +1 -1
- package/src/components/base/datepicker/datepicker.vue +18 -11
- package/src/components/base/daterange_picker/daterange_picker.spec.js +1 -3
- package/src/components/base/dropdown/dropdown.vue +4 -4
- package/src/components/base/filtered_search/filtered_search.vue +29 -30
- package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.vue +1 -1
- package/src/components/base/form/form_checkbox_tree/models/tree.js +0 -1
- package/src/components/base/form/form_group/form_group.spec.js +1 -0
- package/src/components/base/infinite_scroll/infinite_scroll.vue +15 -24
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +1 -0
- package/src/components/base/new_dropdowns/listbox/listbox.spec.js +1 -0
- package/src/components/base/new_dropdowns/listbox/listbox.stories.js +64 -99
- package/src/components/base/pagination/pagination.spec.js +1 -1
- package/src/components/base/pagination/pagination.vue +6 -4
- package/src/components/base/search_box_by_click/search_box_by_click.spec.js +6 -5
- package/src/components/base/search_box_by_click/search_box_by_click.vue +1 -1
- package/src/components/base/sorting/sorting.spec.js +0 -17
- package/src/components/base/tabs/tab/tab.spec.js +2 -3
- package/src/components/base/tabs/tabs/scrollable_tabs.spec.js +3 -1
- package/src/components/base/token_selector/token_container.vue +48 -45
- package/src/components/base/token_selector/token_selector.vue +1 -1
- package/src/components/charts/column/column.vue +1 -1
- package/src/components/utilities/intersection_observer/intersection_observer.spec.js +1 -1
- package/src/components/utilities/intersperse/intersperse.vue +1 -1
- package/src/components/utilities/sprintf/sprintf.spec.js +1 -5
- package/src/components/utilities/truncate/truncate.spec.js +4 -5
- package/src/directives/hover_load/hover_load.spec.js +1 -1
- package/src/directives/safe_link/safe_link.spec.js +11 -13
- package/src/scss/utilities.scss +2 -12
- package/src/scss/utility-mixins/spacing.scss +1 -8
|
@@ -125,17 +125,19 @@ describe('search box by click component', () => {
|
|
|
125
125
|
|
|
126
126
|
it('displays disabled history dropdown', () => {
|
|
127
127
|
expect(wrapper.findComponent({ ref: 'historyDropdown' }).exists()).toBe(true);
|
|
128
|
-
expect(
|
|
128
|
+
expect(
|
|
129
|
+
wrapper.findComponent({ ref: 'historyDropdown' }).attributes('disabled')
|
|
130
|
+
).toBeDefined();
|
|
129
131
|
});
|
|
130
132
|
|
|
131
133
|
it('displays disabled input', () => {
|
|
132
134
|
expect(wrapper.findComponent({ ref: 'input' }).exists()).toBe(true);
|
|
133
|
-
expect(wrapper.findComponent({ ref: 'input' }).attributes('disabled')).
|
|
135
|
+
expect(wrapper.findComponent({ ref: 'input' }).attributes('disabled')).toBeDefined();
|
|
134
136
|
});
|
|
135
137
|
|
|
136
138
|
it('displays disabled search button', () => {
|
|
137
139
|
expect(findSearchButton().exists()).toBe(true);
|
|
138
|
-
expect(findSearchButton().attributes('disabled')).
|
|
140
|
+
expect(findSearchButton().attributes('disabled')).toBeDefined();
|
|
139
141
|
});
|
|
140
142
|
|
|
141
143
|
it('does not render clear icon even with value', () => {
|
|
@@ -146,9 +148,8 @@ describe('search box by click component', () => {
|
|
|
146
148
|
it('emits submit event when Enter key is pressed', async () => {
|
|
147
149
|
createComponent({ value: 'some-input' });
|
|
148
150
|
|
|
149
|
-
wrapper.findComponent(GlFormInput).
|
|
151
|
+
await wrapper.findComponent(GlFormInput).trigger('keydown.enter');
|
|
150
152
|
|
|
151
|
-
await wrapper.vm.$nextTick();
|
|
152
153
|
expect(wrapper.emitted('submit')[0]).toEqual(['some-input']);
|
|
153
154
|
});
|
|
154
155
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { mount } from '@vue/test-utils';
|
|
2
2
|
import GlDropdown from '../dropdown/dropdown.vue';
|
|
3
|
-
import GlDropdownItem from '../dropdown/dropdown_item.vue';
|
|
4
3
|
import GlIcon from '../icon/icon.vue';
|
|
5
4
|
import GlSorting from './sorting.vue';
|
|
6
|
-
import GlSortingItem from './sorting_item.vue';
|
|
7
5
|
|
|
8
6
|
describe('sorting component', () => {
|
|
9
7
|
let wrapper;
|
|
@@ -22,25 +20,10 @@ describe('sorting component', () => {
|
|
|
22
20
|
|
|
23
21
|
const createComponent = (propsData) => {
|
|
24
22
|
wrapper = mount(GlSorting, {
|
|
25
|
-
attachTo: document.body,
|
|
26
|
-
components: {
|
|
27
|
-
GlSortingItem,
|
|
28
|
-
},
|
|
29
|
-
slots: {
|
|
30
|
-
default: [
|
|
31
|
-
'<gl-sorting-item :active="true">First item</gl-sorting-item>',
|
|
32
|
-
'<gl-sorting-item>Second item</gl-sorting-item>',
|
|
33
|
-
'<gl-sorting-item>Third item</gl-sorting-item>',
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
23
|
propsData: {
|
|
37
24
|
...defaultProps,
|
|
38
25
|
...propsData,
|
|
39
26
|
},
|
|
40
|
-
stubs: {
|
|
41
|
-
GlSortingItem,
|
|
42
|
-
GlDropdownItem,
|
|
43
|
-
},
|
|
44
27
|
});
|
|
45
28
|
};
|
|
46
29
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import { BTab } from 'bootstrap-vue';
|
|
2
3
|
import { DEFAULT_TAB_TITLE_LINK_CLASS } from '../constants';
|
|
3
4
|
import GlTab from './tab.vue';
|
|
4
5
|
|
|
@@ -27,9 +28,7 @@ describe('Tab component', () => {
|
|
|
27
28
|
},
|
|
28
29
|
});
|
|
29
30
|
|
|
30
|
-
expect(wrapper.
|
|
31
|
-
`<b-tab-stub tag="div" title="" titlelinkclass="${expectedProp}"></b-tab-stub>`
|
|
32
|
-
);
|
|
31
|
+
expect(wrapper.findComponent(BTab).props('titleLinkClass')).toStrictEqual(expectedProp);
|
|
33
32
|
}
|
|
34
33
|
);
|
|
35
34
|
});
|
|
@@ -58,7 +58,9 @@ describe('GlScrollableTabs', () => {
|
|
|
58
58
|
...props,
|
|
59
59
|
},
|
|
60
60
|
slots: {
|
|
61
|
-
default:
|
|
61
|
+
default: {
|
|
62
|
+
template: `<div><gl-tab v-for="tab in tabs" :key="tab.key" :title="tab.title">{{ tab.content }}</gl-tab></div>`,
|
|
63
|
+
},
|
|
62
64
|
},
|
|
63
65
|
stubs: {
|
|
64
66
|
'gl-tab': GlTab,
|
|
@@ -128,54 +128,57 @@ export default {
|
|
|
128
128
|
</script>
|
|
129
129
|
|
|
130
130
|
<template>
|
|
131
|
-
<div
|
|
132
|
-
ref="tokenContainer"
|
|
133
|
-
class="gl-display-flex gl-flex-wrap gl-align-items-center gl-my-n1 gl-mx-n1 gl-w-full"
|
|
134
|
-
role="listbox"
|
|
135
|
-
aria-multiselectable="false"
|
|
136
|
-
aria-orientation="horizontal"
|
|
137
|
-
:aria-invalid="state === false && 'true'"
|
|
138
|
-
@keydown.left="handleLeftArrow"
|
|
139
|
-
@keydown.right="handleRightArrow"
|
|
140
|
-
@keydown.home="handleHome"
|
|
141
|
-
@keydown.end="handleEnd"
|
|
142
|
-
@keydown.delete="handleDelete"
|
|
143
|
-
@keydown.esc="handleEscape"
|
|
144
|
-
@keydown.tab.exact.prevent="handleTab"
|
|
145
|
-
>
|
|
131
|
+
<div class="gl-display-flex gl-flex-wrap-nowrap gl-align-items-flex-start gl-w-full">
|
|
146
132
|
<div
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
@
|
|
133
|
+
ref="tokenContainer"
|
|
134
|
+
class="gl-display-flex gl-flex-wrap gl-align-items-center gl-my-n1 gl-mx-n1 gl-w-full"
|
|
135
|
+
role="listbox"
|
|
136
|
+
aria-multiselectable="false"
|
|
137
|
+
aria-orientation="horizontal"
|
|
138
|
+
:aria-invalid="state === false && 'true'"
|
|
139
|
+
@keydown.left="handleLeftArrow"
|
|
140
|
+
@keydown.right="handleRightArrow"
|
|
141
|
+
@keydown.home="handleHome"
|
|
142
|
+
@keydown.end="handleEnd"
|
|
143
|
+
@keydown.delete="handleDelete"
|
|
144
|
+
@keydown.esc="handleEscape"
|
|
145
|
+
@keydown.tab.exact.prevent="handleTab"
|
|
155
146
|
>
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
:
|
|
160
|
-
:
|
|
161
|
-
|
|
147
|
+
<div
|
|
148
|
+
v-for="(token, index) in tokens"
|
|
149
|
+
ref="tokens"
|
|
150
|
+
:key="token.id"
|
|
151
|
+
:data-token-id="token.id"
|
|
152
|
+
class="gl-token-selector-token-container gl-px-1 gl-py-2 gl-outline-none"
|
|
153
|
+
role="option"
|
|
154
|
+
tabindex="-1"
|
|
155
|
+
@focus="bindFocusEvent ? handleTokenFocus(index) : null"
|
|
162
156
|
>
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
157
|
+
<gl-token
|
|
158
|
+
class="gl-cursor-default"
|
|
159
|
+
:class="token.class"
|
|
160
|
+
:style="token.style"
|
|
161
|
+
:view-only="viewOnly"
|
|
162
|
+
@close="handleClose(token)"
|
|
163
|
+
>
|
|
164
|
+
<slot name="token-content" :token="token">
|
|
165
|
+
<span>
|
|
166
|
+
{{ token.name }}
|
|
167
|
+
</span>
|
|
168
|
+
</slot>
|
|
169
|
+
</gl-token>
|
|
170
|
+
</div>
|
|
171
|
+
<slot name="text-input"></slot>
|
|
172
|
+
</div>
|
|
173
|
+
<div v-if="showClearAllButton" class="gl-ml-3 gl-p-1">
|
|
174
|
+
<gl-button
|
|
175
|
+
size="small"
|
|
176
|
+
aria-label="Clear all"
|
|
177
|
+
icon="clear"
|
|
178
|
+
category="tertiary"
|
|
179
|
+
data-testid="clear-all-button"
|
|
180
|
+
@click.stop="$emit('clear-all')"
|
|
181
|
+
/>
|
|
169
182
|
</div>
|
|
170
|
-
<slot name="text-input"></slot>
|
|
171
|
-
<gl-button
|
|
172
|
-
v-if="showClearAllButton"
|
|
173
|
-
size="small"
|
|
174
|
-
aria-label="Clear all"
|
|
175
|
-
icon="clear"
|
|
176
|
-
category="tertiary"
|
|
177
|
-
data-testid="clear-all-button"
|
|
178
|
-
@click.stop="$emit('clear-all')"
|
|
179
|
-
/>
|
|
180
183
|
</div>
|
|
181
184
|
</template>
|
|
@@ -415,7 +415,7 @@ export default {
|
|
|
415
415
|
<input
|
|
416
416
|
ref="textInput"
|
|
417
417
|
type="text"
|
|
418
|
-
class="gl-token-selector-input gl-bg-none gl-font-regular gl-font-base gl-line-height-normal gl-px-1 gl-h-auto gl-text-gray-900 gl-border-none gl-outline-none gl-flex-grow-1"
|
|
418
|
+
class="gl-token-selector-input gl-bg-none gl-font-regular gl-font-base gl-line-height-normal gl-px-1 gl-h-auto gl-text-gray-900 gl-border-none gl-outline-none gl-flex-grow-1 gl-w-40p"
|
|
419
419
|
:value="inputText"
|
|
420
420
|
:autocomplete="autocomplete"
|
|
421
421
|
:aria-labelledby="ariaLabelledby"
|
|
@@ -96,7 +96,7 @@ export default {
|
|
|
96
96
|
barSeries() {
|
|
97
97
|
return this.bars.map(({ name, data }, index) => {
|
|
98
98
|
const color = colorFromDefaultPalette(index);
|
|
99
|
-
return generateBarSeries({
|
|
99
|
+
return generateBarSeries({ name, data, color });
|
|
100
100
|
});
|
|
101
101
|
},
|
|
102
102
|
lineSeries() {
|
|
@@ -7,7 +7,7 @@ import filter from 'lodash/fp/filter';
|
|
|
7
7
|
import { intersperse, insert } from '../../../utils/data_utils';
|
|
8
8
|
|
|
9
9
|
const containsWhitespaceOnly = (vNode) => vNode.text.trim() === '';
|
|
10
|
-
const isTag = (vNode) => vNode.tag
|
|
10
|
+
const isTag = (vNode) => typeof vNode.tag === 'string';
|
|
11
11
|
const filterWhitespaceNodes = filter((vNode) => isTag(vNode) || !containsWhitespaceOnly(vNode));
|
|
12
12
|
|
|
13
13
|
const insertAfterSecondLastItem = insert(-1);
|
|
@@ -89,11 +89,7 @@ describe('sprintf component', () => {
|
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
it('should work with a default slot', () => {
|
|
92
|
-
createComponent(
|
|
93
|
-
`<sprintf message="Written by %{default}">
|
|
94
|
-
<template>Author</template>
|
|
95
|
-
</sprintf>`
|
|
96
|
-
);
|
|
92
|
+
createComponent(`<sprintf message="Written by %{default}">Author</sprintf>`);
|
|
97
93
|
|
|
98
94
|
expect(wrapper.element.innerHTML).toBe('Written by Author');
|
|
99
95
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import {
|
|
2
|
+
import { getBinding } from '~helpers/vue_mock_directive';
|
|
3
3
|
import { POSITION } from './constants';
|
|
4
4
|
import Truncate from './truncate.vue';
|
|
5
5
|
|
|
@@ -17,10 +17,9 @@ describe('Truncate component', () => {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const createComponent = (props) => {
|
|
20
|
-
wrapper = shallowMount(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
20
|
+
wrapper = shallowMount(Truncate, {
|
|
21
|
+
propsData: { ...defaultProps, ...props },
|
|
22
|
+
});
|
|
24
23
|
};
|
|
25
24
|
|
|
26
25
|
describe('All', () => {
|
|
@@ -17,20 +17,18 @@ describe('safe link directive', () => {
|
|
|
17
17
|
mountFn = shallowMount,
|
|
18
18
|
} = {}) => {
|
|
19
19
|
const component = {
|
|
20
|
+
props: {
|
|
21
|
+
href: { type: String },
|
|
22
|
+
safeLinkConfig: { type: Object },
|
|
23
|
+
},
|
|
20
24
|
directives: {
|
|
21
25
|
SafeLink: SafeLinkDirective,
|
|
22
26
|
},
|
|
23
27
|
components,
|
|
24
|
-
data() {
|
|
25
|
-
return {
|
|
26
|
-
href,
|
|
27
|
-
safeLinkConfig,
|
|
28
|
-
};
|
|
29
|
-
},
|
|
30
28
|
template,
|
|
31
29
|
};
|
|
32
30
|
|
|
33
|
-
wrapper = mountFn(component);
|
|
31
|
+
wrapper = mountFn(component, { propsData: { href, safeLinkConfig } });
|
|
34
32
|
};
|
|
35
33
|
|
|
36
34
|
describe('default', () => {
|
|
@@ -64,7 +62,7 @@ describe('safe link directive', () => {
|
|
|
64
62
|
describe('valid urls', () => {
|
|
65
63
|
const validUrls = [...absoluteUrls, ...relativeUrls, ...encodedJavaScriptUrls];
|
|
66
64
|
/* Note:
|
|
67
|
-
/* Encoded JavaScript URLs are safe urls in Vue context, since
|
|
65
|
+
/* Encoded JavaScript URLs are safe urls in Vue context, since
|
|
68
66
|
/* Vue attribute bindings are also automatically escaped
|
|
69
67
|
/* https://vuejs.org/v2/guide/security.html#Injecting-URLs
|
|
70
68
|
*/
|
|
@@ -99,13 +97,13 @@ describe('safe link directive', () => {
|
|
|
99
97
|
expect(wrapper.attributes('href')).toBe('about:blank');
|
|
100
98
|
|
|
101
99
|
// set href to a valid url
|
|
102
|
-
wrapper.
|
|
103
|
-
await Vue.nextTick();
|
|
100
|
+
await wrapper.setProps({ href: 'https://gitlab.com' });
|
|
104
101
|
expect(wrapper.attributes('href')).toBe('https://gitlab.com');
|
|
105
102
|
|
|
106
103
|
// set href to back to an invalid url
|
|
107
|
-
wrapper.
|
|
104
|
+
await wrapper.setProps({ href: javascriptUrls[1] });
|
|
108
105
|
await Vue.nextTick();
|
|
106
|
+
|
|
109
107
|
expect(wrapper.attributes('href')).toBe('about:blank');
|
|
110
108
|
});
|
|
111
109
|
|
|
@@ -123,12 +121,12 @@ describe('safe link directive', () => {
|
|
|
123
121
|
expect(wrapper.attributes('href')).toBe(url);
|
|
124
122
|
|
|
125
123
|
// set href to a valid url
|
|
126
|
-
wrapper.
|
|
124
|
+
await wrapper.setProps({ href: 'https://gitlab.com' });
|
|
127
125
|
await Vue.nextTick();
|
|
128
126
|
expect(wrapper.attributes('href')).toBe('https://gitlab.com');
|
|
129
127
|
|
|
130
128
|
// set href to back to an invalid url
|
|
131
|
-
wrapper.
|
|
129
|
+
await wrapper.setProps({ href: url });
|
|
132
130
|
await Vue.nextTick();
|
|
133
131
|
expect(wrapper.attributes('href')).toBe(url);
|
|
134
132
|
});
|
package/src/scss/utilities.scss
CHANGED
|
@@ -6633,12 +6633,12 @@
|
|
|
6633
6633
|
}
|
|
6634
6634
|
}
|
|
6635
6635
|
.gl-sm-pr-2 {
|
|
6636
|
-
@include gl-media-breakpoint-
|
|
6636
|
+
@include gl-media-breakpoint-up(sm) {
|
|
6637
6637
|
padding-right: $gl-spacing-scale-2;
|
|
6638
6638
|
}
|
|
6639
6639
|
}
|
|
6640
6640
|
.gl-sm-pr-2\! {
|
|
6641
|
-
@include gl-media-breakpoint-
|
|
6641
|
+
@include gl-media-breakpoint-up(sm) {
|
|
6642
6642
|
padding-right: $gl-spacing-scale-2 !important;
|
|
6643
6643
|
}
|
|
6644
6644
|
}
|
|
@@ -6762,16 +6762,6 @@
|
|
|
6762
6762
|
padding-right: $gl-spacing-scale-1 !important;
|
|
6763
6763
|
}
|
|
6764
6764
|
}
|
|
6765
|
-
.gl-md-pr-2 {
|
|
6766
|
-
@include gl-media-breakpoint-up(md) {
|
|
6767
|
-
padding-right: $gl-spacing-scale-2;
|
|
6768
|
-
}
|
|
6769
|
-
}
|
|
6770
|
-
.gl-md-pr-2\! {
|
|
6771
|
-
@include gl-media-breakpoint-up(md) {
|
|
6772
|
-
padding-right: $gl-spacing-scale-2 !important;
|
|
6773
|
-
}
|
|
6774
|
-
}
|
|
6775
6765
|
.gl-md-pr-3 {
|
|
6776
6766
|
@include gl-media-breakpoint-up(md) {
|
|
6777
6767
|
padding-right: $gl-spacing-scale-3;
|
|
@@ -1061,8 +1061,7 @@
|
|
|
1061
1061
|
*/
|
|
1062
1062
|
|
|
1063
1063
|
@mixin gl-sm-pr-2 {
|
|
1064
|
-
|
|
1065
|
-
@include gl-media-breakpoint-down(sm) {
|
|
1064
|
+
@include gl-media-breakpoint-up(sm) {
|
|
1066
1065
|
@include gl-pr-2;
|
|
1067
1066
|
}
|
|
1068
1067
|
}
|
|
@@ -1143,12 +1142,6 @@
|
|
|
1143
1142
|
}
|
|
1144
1143
|
}
|
|
1145
1144
|
|
|
1146
|
-
@mixin gl-md-pr-2 {
|
|
1147
|
-
@include gl-media-breakpoint-up(md) {
|
|
1148
|
-
@include gl-pr-2;
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
1145
|
@mixin gl-md-pr-3 {
|
|
1153
1146
|
@include gl-media-breakpoint-up(md) {
|
|
1154
1147
|
@include gl-pr-3;
|