@gitlab/ui 38.0.1 → 38.2.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 +27 -0
- package/README.md +1 -1
- package/dist/components/base/breadcrumb/breadcrumb.js +10 -5
- package/dist/components/base/{filtered_search/examples/filtered_search.single_unique.example.js → breadcrumb/breadcrumb_item.js} +32 -28
- package/dist/components/base/dropdown/dropdown.documentation.js +1 -5
- package/dist/components/base/dropdown/dropdown_item.documentation.js +2 -3
- package/dist/components/base/filtered_search/filtered_search.documentation.js +2 -66
- package/dist/components/base/filtered_search/filtered_search.js +51 -20
- package/dist/components/base/filtered_search/filtered_search_suggestion.documentation.js +2 -8
- package/dist/components/base/filtered_search/filtered_search_suggestion.js +5 -1
- package/dist/components/base/filtered_search/filtered_search_suggestion_list.documentation.js +2 -7
- package/dist/components/base/filtered_search/filtered_search_suggestion_list.js +4 -0
- package/dist/components/base/filtered_search/filtered_search_term.documentation.js +2 -44
- package/dist/components/base/filtered_search/filtered_search_term.js +37 -0
- package/dist/components/base/filtered_search/filtered_search_token.documentation.js +2 -31
- package/dist/components/base/filtered_search/filtered_search_token.js +80 -23
- package/dist/components/base/filtered_search/filtered_search_token_segment.documentation.js +2 -46
- package/dist/components/base/filtered_search/filtered_search_token_segment.js +48 -0
- package/dist/components/base/filtered_search/filtered_search_utils.js +42 -9
- package/dist/components/base/form/form_checkbox_tree/form_checkbox_tree.documentation.js +2 -27
- package/dist/components/base/form/form_checkbox_tree/form_checkbox_tree.js +16 -1
- package/dist/components/charts/series_label/series_label.js +6 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/utils/use_mock_intersection_observer.js +2 -2
- package/documentation/components_documentation.js +0 -4
- package/documentation/documented_stories.js +10 -1
- package/package.json +11 -9
- package/src/components/base/avatar_link/avatar_link.stories.js +2 -2
- package/src/components/base/breadcrumb/breadcrumb.spec.js +24 -10
- package/src/components/base/breadcrumb/breadcrumb.vue +11 -6
- package/src/components/base/breadcrumb/breadcrumb_item.spec.js +45 -0
- package/src/components/base/breadcrumb/breadcrumb_item.vue +43 -0
- package/src/components/base/dropdown/dropdown.documentation.js +0 -3
- package/src/components/base/dropdown/dropdown.md +7 -2
- package/src/components/base/dropdown/dropdown.stories.js +487 -439
- package/src/components/base/dropdown/dropdown_item.documentation.js +0 -1
- package/src/components/base/dropdown/dropdown_item.md +0 -6
- package/src/components/base/dropdown/dropdown_item.stories.js +107 -35
- package/src/components/base/filtered_search/filtered_search.documentation.js +0 -76
- package/src/components/base/filtered_search/filtered_search.md +3 -4
- package/src/components/base/filtered_search/filtered_search.spec.js +37 -12
- package/src/components/base/filtered_search/filtered_search.stories.js +260 -17
- package/src/components/base/filtered_search/filtered_search.vue +57 -14
- package/src/components/base/filtered_search/filtered_search_suggestion.documentation.js +0 -6
- package/src/components/base/filtered_search/filtered_search_suggestion.md +1 -7
- package/src/components/base/filtered_search/filtered_search_suggestion.stories.js +26 -18
- package/src/components/base/filtered_search/filtered_search_suggestion.vue +6 -0
- package/src/components/base/filtered_search/filtered_search_suggestion_list.documentation.js +0 -5
- package/src/components/base/filtered_search/filtered_search_suggestion_list.md +1 -7
- package/src/components/base/filtered_search/filtered_search_suggestion_list.stories.js +33 -25
- package/src/components/base/filtered_search/filtered_search_suggestion_list.vue +5 -0
- package/src/components/base/filtered_search/filtered_search_term.documentation.js +0 -41
- package/src/components/base/filtered_search/filtered_search_term.md +0 -2
- package/src/components/base/filtered_search/filtered_search_term.stories.js +33 -26
- package/src/components/base/filtered_search/filtered_search_term.vue +54 -0
- package/src/components/base/filtered_search/filtered_search_token.documentation.js +0 -26
- package/src/components/base/filtered_search/filtered_search_token.md +1 -3
- package/src/components/base/filtered_search/filtered_search_token.spec.js +31 -1
- package/src/components/base/filtered_search/filtered_search_token.stories.js +137 -132
- package/src/components/base/filtered_search/filtered_search_token.vue +93 -21
- package/src/components/base/filtered_search/filtered_search_token_segment.documentation.js +0 -43
- package/src/components/base/filtered_search/filtered_search_token_segment.md +0 -2
- package/src/components/base/filtered_search/filtered_search_token_segment.stories.js +86 -79
- package/src/components/base/filtered_search/filtered_search_token_segment.vue +42 -0
- package/src/components/base/filtered_search/filtered_search_utils.js +38 -5
- package/src/components/base/form/form.stories.js +2 -0
- package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.documentation.js +0 -26
- package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.md +0 -4
- package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.stories.js +123 -92
- package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.vue +13 -1
- package/src/components/base/form/form_radio/form_radio.spec.js +21 -8
- package/src/components/base/form/form_radio_group/form_radio_group.stories.js +2 -1
- package/src/components/base/markdown/markdown.scss +21 -0
- package/src/components/base/markdown/markdown_typescale_demo.html +17 -6
- package/src/components/base/navbar/navbar.stories.js +2 -1
- package/src/components/base/skeleton_loader/skeleton_loader.stories.js +67 -21
- package/src/components/base/tabs/tabs/tabs.stories.js +2 -2
- package/src/components/charts/series_label/series_label.stories.js +6 -3
- package/src/components/charts/series_label/series_label.vue +3 -0
- package/src/scss/typescale/typescale.md +0 -2
- package/src/scss/typescale/typescale.stories.js +17 -4
- package/src/utils/use_mock_intersection_observer.js +3 -3
- package/dist/components/base/dropdown/dropdown_divider.documentation.js +0 -8
- package/dist/components/base/dropdown/dropdown_form.documentation.js +0 -17
- package/dist/components/base/dropdown/dropdown_section_header.documentation.js +0 -8
- package/dist/components/base/dropdown/dropdown_text.documentation.js +0 -8
- package/dist/components/base/dropdown/examples/dropdown.default.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.links.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_avatar_and_secondary_text.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_checked_items.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_clear_all.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_divider.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_form.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_header.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_highlighted_items.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_icons.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_right_align.example.js +0 -38
- package/dist/components/base/dropdown/examples/dropdown.with_search.example.js +0 -67
- package/dist/components/base/dropdown/examples/dropdown.with_section_headers.example.js +0 -38
- package/dist/components/base/dropdown/examples/index.js +0 -85
- package/dist/components/base/filtered_search/examples/filtered_search.default.example.js +0 -422
- package/dist/components/base/filtered_search/examples/filtered_search.friendly.example.js +0 -423
- package/dist/components/base/filtered_search/examples/filtered_search.history.example.js +0 -91
- package/dist/components/base/filtered_search/examples/filtered_search.multi_select.example.js +0 -196
- package/dist/components/base/filtered_search/examples/index.js +0 -32
- package/dist/components/base/form/form_checkbox_tree/examples/form_checkbox_tree.basic.example.js +0 -103
- package/dist/components/base/form/form_checkbox_tree/examples/index.js +0 -13
- package/src/components/base/dropdown/dropdown_divider.documentation.js +0 -6
- package/src/components/base/dropdown/dropdown_divider.md +0 -7
- package/src/components/base/dropdown/dropdown_divider.stories.js +0 -16
- package/src/components/base/dropdown/dropdown_form.documentation.js +0 -9
- package/src/components/base/dropdown/dropdown_form.md +0 -4
- package/src/components/base/dropdown/dropdown_form.stories.js +0 -17
- package/src/components/base/dropdown/dropdown_section_header.documentation.js +0 -6
- package/src/components/base/dropdown/dropdown_section_header.stories.js +0 -17
- package/src/components/base/dropdown/dropdown_text.documentation.js +0 -6
- package/src/components/base/dropdown/dropdown_text.stories.js +0 -16
- package/src/components/base/dropdown/examples/dropdown.default.example.vue +0 -7
- package/src/components/base/dropdown/examples/dropdown.links.example.vue +0 -7
- package/src/components/base/dropdown/examples/dropdown.with_avatar_and_secondary_text.example.vue +0 -7
- package/src/components/base/dropdown/examples/dropdown.with_checked_items.example.vue +0 -6
- package/src/components/base/dropdown/examples/dropdown.with_clear_all.example.vue +0 -7
- package/src/components/base/dropdown/examples/dropdown.with_divider.example.vue +0 -9
- package/src/components/base/dropdown/examples/dropdown.with_form.example.vue +0 -10
- package/src/components/base/dropdown/examples/dropdown.with_header.example.vue +0 -7
- package/src/components/base/dropdown/examples/dropdown.with_highlighted_items.example.vue +0 -9
- package/src/components/base/dropdown/examples/dropdown.with_icons.example.vue +0 -43
- package/src/components/base/dropdown/examples/dropdown.with_right_align.example.vue +0 -7
- package/src/components/base/dropdown/examples/dropdown.with_search.example.vue +0 -38
- package/src/components/base/dropdown/examples/dropdown.with_section_headers.example.vue +0 -10
- package/src/components/base/dropdown/examples/index.js +0 -99
- package/src/components/base/filtered_search/examples/filtered_search.default.example.vue +0 -298
- package/src/components/base/filtered_search/examples/filtered_search.friendly.example.vue +0 -300
- package/src/components/base/filtered_search/examples/filtered_search.history.example.vue +0 -50
- package/src/components/base/filtered_search/examples/filtered_search.multi_select.example.vue +0 -132
- package/src/components/base/filtered_search/examples/filtered_search.single_unique.example.vue +0 -31
- package/src/components/base/filtered_search/examples/index.js +0 -38
- package/src/components/base/form/form_checkbox_tree/examples/form_checkbox_tree.basic.example.vue +0 -77
- package/src/components/base/form/form_checkbox_tree/examples/index.js +0 -15
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { withKnobs, boolean } from '@storybook/addon-knobs';
|
|
2
1
|
import PortalVue from 'portal-vue';
|
|
3
2
|
import Vue from 'vue';
|
|
4
3
|
import { GlFilteredSearchSuggestion } from '../../../index';
|
|
5
|
-
import { documentedStoriesOf } from '../../../../documentation/documented_stories';
|
|
6
4
|
import { provide } from './common_story_options';
|
|
7
5
|
import readme from './filtered_search_term.md';
|
|
8
6
|
import GlFilteredSearchTokenSegment from './filtered_search_token_segment.vue';
|
|
@@ -14,84 +12,93 @@ const staticOptions = [
|
|
|
14
12
|
{ icon: 'eye', value: false, title: 'No' },
|
|
15
13
|
];
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
15
|
+
const generateProps = ({ active = true } = {}) => ({
|
|
16
|
+
active,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line no-unused-vars
|
|
20
|
+
export const Default = (args, { argTypes }) => ({
|
|
21
|
+
components: {
|
|
22
|
+
GlFilteredSearchTokenSegment,
|
|
23
|
+
GlFilteredSearchSuggestion,
|
|
24
|
+
},
|
|
25
|
+
provide,
|
|
26
|
+
props: ['active'],
|
|
27
|
+
data() {
|
|
28
|
+
return {
|
|
29
|
+
value: 'demo1',
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
mounted() {
|
|
33
|
+
this.$nextTick(() => document.activeElement.blur());
|
|
34
|
+
},
|
|
35
|
+
template: `
|
|
36
|
+
<div>
|
|
37
|
+
<div>v-model value: {{ value }} </div>
|
|
38
|
+
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
39
|
+
<gl-filtered-search-token-segment
|
|
40
|
+
v-model="value"
|
|
41
|
+
class="gl-h-full"
|
|
42
|
+
:active="active"
|
|
43
|
+
>
|
|
44
|
+
<template #suggestions>
|
|
45
|
+
<gl-filtered-search-suggestion value="demo1">Static suggestion 1</gl-filtered-search-suggestion>
|
|
46
|
+
<gl-filtered-search-suggestion value="demo2">Static suggestion 2</gl-filtered-search-suggestion>
|
|
47
|
+
</template>
|
|
48
|
+
</gl-filtered-search-token-segment>
|
|
49
|
+
</div>
|
|
40
50
|
<div>
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
<portal-target name="portal" class="gl-relative" />
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
`,
|
|
55
|
+
});
|
|
56
|
+
Default.args = generateProps();
|
|
57
|
+
|
|
58
|
+
// eslint-disable-next-line no-unused-vars
|
|
59
|
+
export const WithStaticOptions = (args, { argTypes }) => ({
|
|
60
|
+
components: {
|
|
61
|
+
GlFilteredSearchTokenSegment,
|
|
62
|
+
},
|
|
63
|
+
provide,
|
|
64
|
+
props: ['active'],
|
|
65
|
+
data() {
|
|
66
|
+
return {
|
|
67
|
+
value: true,
|
|
68
|
+
staticOptions,
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
mounted() {
|
|
72
|
+
this.$nextTick(() => document.activeElement.blur());
|
|
73
|
+
},
|
|
74
|
+
template: `
|
|
75
|
+
<div>
|
|
76
|
+
<div>v-model value: {{ value }} </div>
|
|
77
|
+
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
78
|
+
<gl-filtered-search-token-segment
|
|
79
|
+
v-model="value"
|
|
80
|
+
class="gl-h-full"
|
|
81
|
+
:active="active"
|
|
82
|
+
:options="staticOptions"
|
|
83
|
+
option-text-field="title"
|
|
84
|
+
/>
|
|
57
85
|
</div>
|
|
58
|
-
`,
|
|
59
|
-
}))
|
|
60
|
-
.add('with static options', () => ({
|
|
61
|
-
components: {
|
|
62
|
-
GlFilteredSearchTokenSegment,
|
|
63
|
-
},
|
|
64
|
-
provide,
|
|
65
|
-
props: {
|
|
66
|
-
active: {
|
|
67
|
-
type: Boolean,
|
|
68
|
-
default: boolean('active', true),
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
data() {
|
|
72
|
-
return {
|
|
73
|
-
value: true,
|
|
74
|
-
staticOptions,
|
|
75
|
-
};
|
|
76
|
-
},
|
|
77
|
-
mounted() {
|
|
78
|
-
this.$nextTick(() => document.activeElement.blur());
|
|
79
|
-
},
|
|
80
|
-
template: `
|
|
81
86
|
<div>
|
|
82
|
-
<
|
|
83
|
-
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
84
|
-
<gl-filtered-search-token-segment
|
|
85
|
-
v-model="value"
|
|
86
|
-
class="gl-h-full"
|
|
87
|
-
:active="active"
|
|
88
|
-
:options="staticOptions"
|
|
89
|
-
option-text-field="title"
|
|
90
|
-
/>
|
|
91
|
-
</div>
|
|
92
|
-
<div>
|
|
93
|
-
<portal-target name="portal" class="gl-relative" />
|
|
94
|
-
</div>
|
|
87
|
+
<portal-target name="portal" class="gl-relative" />
|
|
95
88
|
</div>
|
|
96
|
-
|
|
97
|
-
|
|
89
|
+
</div>
|
|
90
|
+
`,
|
|
91
|
+
});
|
|
92
|
+
WithStaticOptions.args = generateProps();
|
|
93
|
+
|
|
94
|
+
export default {
|
|
95
|
+
title: 'base/filtered-search/token-segment',
|
|
96
|
+
component: GlFilteredSearchTokenSegment,
|
|
97
|
+
parameters: {
|
|
98
|
+
docs: {
|
|
99
|
+
description: {
|
|
100
|
+
component: readme,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
};
|
|
@@ -7,6 +7,7 @@ import GlFilteredSearchSuggestionList from './filtered_search_suggestion_list.vu
|
|
|
7
7
|
import { splitOnQuotes, wrapTokenInQuotes } from './filtered_search_utils';
|
|
8
8
|
|
|
9
9
|
export default {
|
|
10
|
+
name: 'GlFilteredSearchTokenSegment',
|
|
10
11
|
components: {
|
|
11
12
|
Portal,
|
|
12
13
|
GlFilteredSearchSuggestionList,
|
|
@@ -15,6 +16,9 @@ export default {
|
|
|
15
16
|
inject: ['portalName', 'alignSuggestions'],
|
|
16
17
|
inheritAttrs: false,
|
|
17
18
|
props: {
|
|
19
|
+
/**
|
|
20
|
+
* If this token segment is currently being edited.
|
|
21
|
+
*/
|
|
18
22
|
active: {
|
|
19
23
|
type: Boolean,
|
|
20
24
|
required: false,
|
|
@@ -45,15 +49,24 @@ export default {
|
|
|
45
49
|
required: false,
|
|
46
50
|
default: () => () => false,
|
|
47
51
|
},
|
|
52
|
+
/**
|
|
53
|
+
* Current term value
|
|
54
|
+
*/
|
|
48
55
|
value: {
|
|
49
56
|
required: true,
|
|
50
57
|
validator: () => true,
|
|
51
58
|
},
|
|
59
|
+
/**
|
|
60
|
+
* HTML attributes to add to the search input
|
|
61
|
+
*/
|
|
52
62
|
searchInputAttributes: {
|
|
53
63
|
type: Object,
|
|
54
64
|
required: false,
|
|
55
65
|
default: () => ({}),
|
|
56
66
|
},
|
|
67
|
+
/**
|
|
68
|
+
* If this is the last token
|
|
69
|
+
*/
|
|
57
70
|
isLastToken: {
|
|
58
71
|
type: Boolean,
|
|
59
72
|
required: false,
|
|
@@ -89,6 +102,11 @@ export default {
|
|
|
89
102
|
},
|
|
90
103
|
|
|
91
104
|
set(v) {
|
|
105
|
+
/**
|
|
106
|
+
* Emitted when this token segment's value changes.
|
|
107
|
+
*
|
|
108
|
+
* @type {object} option The current option.
|
|
109
|
+
*/
|
|
92
110
|
this.$emit('input', this.getMatchingOptionForInputValue(v)?.value ?? v);
|
|
93
111
|
},
|
|
94
112
|
},
|
|
@@ -145,6 +163,10 @@ export default {
|
|
|
145
163
|
this.$emit('input', this.getMatchingOptionForInputValue(firstWord)?.value ?? firstWord);
|
|
146
164
|
|
|
147
165
|
if (otherWords.length) {
|
|
166
|
+
/**
|
|
167
|
+
* Emitted when Space appears in token segment value
|
|
168
|
+
* @property {array|string} newStrings New strings to be converted into term tokens
|
|
169
|
+
*/
|
|
148
170
|
this.$emit('split', otherWords);
|
|
149
171
|
}
|
|
150
172
|
},
|
|
@@ -153,6 +175,9 @@ export default {
|
|
|
153
175
|
methods: {
|
|
154
176
|
emitIfInactive(e) {
|
|
155
177
|
if (!this.active) {
|
|
178
|
+
/**
|
|
179
|
+
* Emitted on mousedown event on the main component.
|
|
180
|
+
*/
|
|
156
181
|
this.$emit('activate');
|
|
157
182
|
e.preventDefault();
|
|
158
183
|
}
|
|
@@ -190,6 +215,11 @@ export default {
|
|
|
190
215
|
applySuggestion(suggestedValue) {
|
|
191
216
|
const formattedSuggestedValue = wrapTokenInQuotes(suggestedValue);
|
|
192
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Emitted when autocomplete entry is selected.
|
|
220
|
+
*
|
|
221
|
+
* @type {string} value The selected value.
|
|
222
|
+
*/
|
|
193
223
|
this.$emit('select', formattedSuggestedValue);
|
|
194
224
|
|
|
195
225
|
if (!this.multiSelect) {
|
|
@@ -205,6 +235,9 @@ export default {
|
|
|
205
235
|
if (key === 'Backspace') {
|
|
206
236
|
if (this.inputValue === '') {
|
|
207
237
|
e.preventDefault();
|
|
238
|
+
/**
|
|
239
|
+
* Emitted when Backspace is pressed and the value is empty
|
|
240
|
+
*/
|
|
208
241
|
this.$emit('backspace');
|
|
209
242
|
}
|
|
210
243
|
return;
|
|
@@ -216,6 +249,9 @@ export default {
|
|
|
216
249
|
if (suggestedValue != null) {
|
|
217
250
|
this.applySuggestion(suggestedValue);
|
|
218
251
|
} else {
|
|
252
|
+
/**
|
|
253
|
+
* Emitted when Enter is pressed and no suggestion is selected
|
|
254
|
+
*/
|
|
219
255
|
this.$emit('submit');
|
|
220
256
|
}
|
|
221
257
|
},
|
|
@@ -227,6 +263,9 @@ export default {
|
|
|
227
263
|
},
|
|
228
264
|
Escape: () => {
|
|
229
265
|
e.preventDefault();
|
|
266
|
+
/**
|
|
267
|
+
* Emitted when suggestion is selected from the suggestion list
|
|
268
|
+
*/
|
|
230
269
|
this.$emit('complete');
|
|
231
270
|
},
|
|
232
271
|
};
|
|
@@ -258,6 +297,9 @@ export default {
|
|
|
258
297
|
if (this.multiSelect) {
|
|
259
298
|
this.$emit('complete');
|
|
260
299
|
} else if (this.active) {
|
|
300
|
+
/**
|
|
301
|
+
* Emitted when this term token will lose its focus.
|
|
302
|
+
*/
|
|
261
303
|
this.$emit('deactivate');
|
|
262
304
|
}
|
|
263
305
|
},
|
|
@@ -39,7 +39,42 @@ export function needDenormalization(tokens) {
|
|
|
39
39
|
|
|
40
40
|
assertValidTokens(tokens);
|
|
41
41
|
|
|
42
|
-
return tokens.some((t) => typeof t === 'string');
|
|
42
|
+
return tokens.some((t) => typeof t === 'string' || !t.id);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let tokenIdCounter = 0;
|
|
46
|
+
const getTokenId = () => {
|
|
47
|
+
const tokenId = `token-${tokenIdCounter}`;
|
|
48
|
+
tokenIdCounter += 1;
|
|
49
|
+
return tokenId;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Ensure the given token has an `id` property, which `GlFilteredSearch` relies
|
|
53
|
+
* on as a unique key for the token.
|
|
54
|
+
*
|
|
55
|
+
* If the given token does not have an `id`, it returns a shallow copy of the
|
|
56
|
+
* token with an `id`. Otherwise, it returns the given token.
|
|
57
|
+
*
|
|
58
|
+
* @param {object} token The token to check.
|
|
59
|
+
* @returns {object} A token with an `id`.
|
|
60
|
+
*/
|
|
61
|
+
export function ensureTokenId(token) {
|
|
62
|
+
if (!token.id) {
|
|
63
|
+
return {
|
|
64
|
+
...token,
|
|
65
|
+
id: getTokenId(),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return token;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function createTerm(data = '') {
|
|
73
|
+
return {
|
|
74
|
+
id: getTokenId(),
|
|
75
|
+
type: TERM_TOKEN_TYPE,
|
|
76
|
+
value: { data },
|
|
77
|
+
};
|
|
43
78
|
}
|
|
44
79
|
|
|
45
80
|
export function denormalizeTokens(inputTokens) {
|
|
@@ -51,11 +86,9 @@ export function denormalizeTokens(inputTokens) {
|
|
|
51
86
|
tokens.forEach((t) => {
|
|
52
87
|
if (typeof t === 'string') {
|
|
53
88
|
const stringTokens = t.split(' ').filter(Boolean);
|
|
54
|
-
stringTokens.forEach((strToken) =>
|
|
55
|
-
result.push({ type: TERM_TOKEN_TYPE, value: { data: strToken } })
|
|
56
|
-
);
|
|
89
|
+
stringTokens.forEach((strToken) => result.push(createTerm(strToken)));
|
|
57
90
|
} else {
|
|
58
|
-
result.push(t);
|
|
91
|
+
result.push(ensureTokenId(t));
|
|
59
92
|
}
|
|
60
93
|
});
|
|
61
94
|
return result;
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
GlFormInput,
|
|
5
5
|
GlFormSelect,
|
|
6
6
|
GlFormCheckbox,
|
|
7
|
+
GlFormCheckboxGroup,
|
|
7
8
|
GlButton,
|
|
8
9
|
} from '../../../index';
|
|
9
10
|
import { setStoryTimeout } from '../../../utils/test_utils';
|
|
@@ -16,6 +17,7 @@ export const Default = (args) => ({
|
|
|
16
17
|
GlFormInput,
|
|
17
18
|
GlFormSelect,
|
|
18
19
|
GlFormCheckbox,
|
|
20
|
+
GlFormCheckboxGroup,
|
|
19
21
|
GlButton,
|
|
20
22
|
},
|
|
21
23
|
props: Object.keys(args),
|
|
@@ -1,31 +1,5 @@
|
|
|
1
|
-
import examples from './examples';
|
|
2
1
|
import * as description from './form_checkbox_tree.md';
|
|
3
|
-
import { V_MODEL } from './models/constants';
|
|
4
2
|
|
|
5
3
|
export default {
|
|
6
4
|
description,
|
|
7
|
-
examples,
|
|
8
|
-
propsInfo: {
|
|
9
|
-
options: {
|
|
10
|
-
additionalInfo: 'The options tree.',
|
|
11
|
-
},
|
|
12
|
-
[V_MODEL.PROP]: {
|
|
13
|
-
additionalInfo: 'The selected options as an array of values.',
|
|
14
|
-
},
|
|
15
|
-
hideToggleAll: {
|
|
16
|
-
additionalInfo: 'Set to true to hide the "Select/unselect all" checkbox',
|
|
17
|
-
},
|
|
18
|
-
selectAllLabel: {
|
|
19
|
-
additionalInfo: 'Label for the toggle all checkbox when some or all options are unchecked',
|
|
20
|
-
},
|
|
21
|
-
unselectAllLabel: {
|
|
22
|
-
additionalInfo: 'Label for the toggle all checkbox when all options are checked',
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
events: [
|
|
26
|
-
{
|
|
27
|
-
event: V_MODEL.EVENT,
|
|
28
|
-
description: 'Emitted the selection changes.',
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
5
|
};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { withKnobs, boolean } from '@storybook/addon-knobs';
|
|
2
|
-
import { documentedStoriesOf } from '../../../../../documentation/documented_stories';
|
|
3
1
|
import GlToken from '../../token/token.vue';
|
|
4
2
|
import readme from './form_checkbox_tree.md';
|
|
5
3
|
import GlFormCheckboxTree from './form_checkbox_tree.vue';
|
|
@@ -9,95 +7,128 @@ const components = {
|
|
|
9
7
|
GlToken,
|
|
10
8
|
};
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
const defaultOptions = [
|
|
11
|
+
{
|
|
12
|
+
value: 1,
|
|
13
|
+
label: 'Felidae',
|
|
14
|
+
children: [
|
|
15
|
+
{
|
|
16
|
+
value: 11,
|
|
17
|
+
label: 'Lion',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: 12,
|
|
21
|
+
label: 'Felinae',
|
|
22
|
+
children: [
|
|
23
|
+
{
|
|
24
|
+
value: 121,
|
|
25
|
+
label: 'Cheetah',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: 122,
|
|
29
|
+
label: 'Ocelot',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
value: 2,
|
|
37
|
+
label: 'Canidae',
|
|
38
|
+
children: [
|
|
39
|
+
{
|
|
40
|
+
value: 21,
|
|
41
|
+
label: 'Caninae',
|
|
42
|
+
children: [
|
|
43
|
+
{
|
|
44
|
+
value: 211,
|
|
45
|
+
label: 'Canis lupus',
|
|
46
|
+
children: [
|
|
47
|
+
{
|
|
48
|
+
value: 2112,
|
|
49
|
+
label: 'Wolf',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
value: 2113,
|
|
53
|
+
label: 'Himalayan wolf',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
value: 2114,
|
|
57
|
+
label: 'Dingo',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
value: 212,
|
|
63
|
+
label: 'Black-backed jackal',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
value: 22,
|
|
69
|
+
label: 'Fennec fox',
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
value: 3,
|
|
75
|
+
label: 'Karabair',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
value: 4,
|
|
79
|
+
label: 'Okapi',
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
const defaultValue = (prop) => GlFormCheckboxTree.props[prop].default;
|
|
84
|
+
|
|
85
|
+
const generateProps = ({
|
|
86
|
+
options = defaultOptions,
|
|
87
|
+
hideToggleAll = defaultValue('hideToggleAll'),
|
|
88
|
+
selectAllLabel = defaultValue('selectAllLabel'),
|
|
89
|
+
unselectAllLabel = defaultValue('unselectAllLabel'),
|
|
90
|
+
label = defaultValue('label'),
|
|
91
|
+
labelSrOnly = defaultValue('labelSrOnly'),
|
|
92
|
+
} = {}) => ({
|
|
93
|
+
options,
|
|
94
|
+
hideToggleAll,
|
|
95
|
+
selectAllLabel,
|
|
96
|
+
unselectAllLabel,
|
|
97
|
+
label,
|
|
98
|
+
labelSrOnly,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const Default = (args, { argTypes }) => ({
|
|
102
|
+
props: Object.keys(argTypes),
|
|
103
|
+
data: () => ({
|
|
104
|
+
checked: [1, 11, 12, 121, 122, 2113, 3],
|
|
105
|
+
}),
|
|
106
|
+
components,
|
|
107
|
+
template: `
|
|
108
|
+
<div>
|
|
109
|
+
<gl-form-checkbox-tree
|
|
110
|
+
v-model="checked"
|
|
111
|
+
:options="options"
|
|
112
|
+
:hide-toggle-all="hideToggleAll"
|
|
113
|
+
:select-all-label="selectAllLabel"
|
|
114
|
+
:unselect-all-label="unselectAllLabel"
|
|
115
|
+
:label="label"
|
|
116
|
+
:label-sr-only="labelSrOnly" />
|
|
117
|
+
Selected options:
|
|
118
|
+
<gl-token v-for="value in checked" :key="value" class="gl-mr-1" view-only>{{ value }}</gl-token>
|
|
119
|
+
</div>
|
|
120
|
+
`,
|
|
121
|
+
});
|
|
122
|
+
Default.args = generateProps();
|
|
123
|
+
|
|
124
|
+
export default {
|
|
125
|
+
title: 'base/form/form-checkbox-tree',
|
|
126
|
+
component: GlFormCheckboxTree,
|
|
127
|
+
parameters: {
|
|
128
|
+
docs: {
|
|
129
|
+
description: {
|
|
130
|
+
component: readme,
|
|
18
131
|
},
|
|
19
132
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
options: [
|
|
23
|
-
{
|
|
24
|
-
value: 1,
|
|
25
|
-
label: 'Felidae',
|
|
26
|
-
children: [
|
|
27
|
-
{
|
|
28
|
-
value: 11,
|
|
29
|
-
label: 'Lion',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
value: 12,
|
|
33
|
-
label: 'Felinae',
|
|
34
|
-
children: [
|
|
35
|
-
{
|
|
36
|
-
value: 121,
|
|
37
|
-
label: 'Cheetah',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
value: 122,
|
|
41
|
-
label: 'Ocelot',
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
value: 2,
|
|
49
|
-
label: 'Canidae',
|
|
50
|
-
children: [
|
|
51
|
-
{
|
|
52
|
-
value: 21,
|
|
53
|
-
label: 'Caninae',
|
|
54
|
-
children: [
|
|
55
|
-
{
|
|
56
|
-
value: 211,
|
|
57
|
-
label: 'Canis lupus',
|
|
58
|
-
children: [
|
|
59
|
-
{
|
|
60
|
-
value: 2112,
|
|
61
|
-
label: 'Wolf',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
value: 2113,
|
|
65
|
-
label: 'Himalayan wolf',
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
value: 2114,
|
|
69
|
-
label: 'Dingo',
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
value: 212,
|
|
75
|
-
label: 'Black-backed jackal',
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
value: 22,
|
|
81
|
-
label: 'Fennec fox',
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
value: 3,
|
|
87
|
-
label: 'Karabair',
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
value: 4,
|
|
91
|
-
label: 'Okapi',
|
|
92
|
-
},
|
|
93
|
-
],
|
|
94
|
-
}),
|
|
95
|
-
components,
|
|
96
|
-
template: `
|
|
97
|
-
<div>
|
|
98
|
-
<gl-form-checkbox-tree :hide-toggle-all="hideToggleAll" :options="options" v-model="checked" />
|
|
99
|
-
Selected options:
|
|
100
|
-
<gl-token v-for="value in checked" :key="value" class="gl-mr-1" view-only>{{ value }}</gl-token>
|
|
101
|
-
</div>
|
|
102
|
-
`,
|
|
103
|
-
}));
|
|
133
|
+
},
|
|
134
|
+
};
|
|
@@ -34,23 +34,32 @@ export default {
|
|
|
34
34
|
required: true,
|
|
35
35
|
},
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* The selected options as an array of values
|
|
38
38
|
*/
|
|
39
39
|
value: {
|
|
40
40
|
type: Array,
|
|
41
41
|
required: false,
|
|
42
42
|
default: () => [],
|
|
43
43
|
},
|
|
44
|
+
/**
|
|
45
|
+
* Set to true to hide the "Select/unselect all" checkbox
|
|
46
|
+
*/
|
|
44
47
|
hideToggleAll: {
|
|
45
48
|
type: Boolean,
|
|
46
49
|
required: false,
|
|
47
50
|
default: false,
|
|
48
51
|
},
|
|
52
|
+
/**
|
|
53
|
+
* Label for the toggle all checkbox when some or all options are unchecked
|
|
54
|
+
*/
|
|
49
55
|
selectAllLabel: {
|
|
50
56
|
type: String,
|
|
51
57
|
required: false,
|
|
52
58
|
default: 'Select all',
|
|
53
59
|
},
|
|
60
|
+
/**
|
|
61
|
+
* Label for the toggle all checkbox when all options are checked
|
|
62
|
+
*/
|
|
54
63
|
unselectAllLabel: {
|
|
55
64
|
type: String,
|
|
56
65
|
required: false,
|
|
@@ -80,6 +89,9 @@ export default {
|
|
|
80
89
|
watch: {
|
|
81
90
|
'tree.selected': {
|
|
82
91
|
handler(selected) {
|
|
92
|
+
/**
|
|
93
|
+
* Emitted when the selection changes.
|
|
94
|
+
*/
|
|
83
95
|
this.$emit(V_MODEL.EVENT, selected);
|
|
84
96
|
},
|
|
85
97
|
},
|