@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,7 +1,5 @@
|
|
|
1
|
-
import { withKnobs, boolean } from '@storybook/addon-knobs';
|
|
2
1
|
import PortalVue from 'portal-vue';
|
|
3
2
|
import Vue from 'vue';
|
|
4
|
-
import { documentedStoriesOf } from '../../../../documentation/documented_stories';
|
|
5
3
|
import { GlIcon } from '../../../index';
|
|
6
4
|
import { provide } from './common_story_options';
|
|
7
5
|
import GlFilteredSearchSuggestion from './filtered_search_suggestion.vue';
|
|
@@ -10,152 +8,159 @@ import GlFilteredSearchToken from './filtered_search_token.vue';
|
|
|
10
8
|
|
|
11
9
|
Vue.use(PortalVue);
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
const generateProps = ({ active = true } = {}) => ({
|
|
12
|
+
active,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line no-unused-vars
|
|
16
|
+
export const Default = (args, { argTypes }) => ({
|
|
17
|
+
components: {
|
|
18
|
+
GlFilteredSearchToken,
|
|
19
|
+
GlFilteredSearchSuggestion,
|
|
20
|
+
GlIcon,
|
|
21
|
+
},
|
|
22
|
+
provide,
|
|
23
|
+
props: ['active'],
|
|
24
|
+
data() {
|
|
25
|
+
return {
|
|
26
|
+
value: { operator: '=', data: 'Yes' },
|
|
27
|
+
config: {
|
|
28
|
+
title: 'Confidential',
|
|
26
29
|
},
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
mounted() {
|
|
33
|
+
this.$nextTick(() => {
|
|
34
|
+
document.activeElement.blur();
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
template: `
|
|
38
|
+
<div>
|
|
39
|
+
<div> {{ value }} </div>
|
|
40
|
+
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
41
|
+
<gl-filtered-search-token
|
|
42
|
+
v-model="value"
|
|
43
|
+
class="gl-h-full"
|
|
44
|
+
:config="config"
|
|
45
|
+
:active="active"
|
|
46
|
+
>
|
|
47
|
+
<template #suggestions>
|
|
48
|
+
<gl-filtered-search-suggestion value="Yes"><gl-icon name="eye-slash" :size="16"/> Yes</gl-filtered-search-suggestion>
|
|
49
|
+
<gl-filtered-search-suggestion value="No"><gl-icon name="eye" :size="16"/> No</gl-filtered-search-suggestion>
|
|
50
|
+
</template>
|
|
51
|
+
</gl-filtered-search-token>
|
|
52
|
+
</div>
|
|
42
53
|
<div>
|
|
43
|
-
<
|
|
44
|
-
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
45
|
-
<gl-filtered-search-token
|
|
46
|
-
v-model="value"
|
|
47
|
-
class="gl-h-full"
|
|
48
|
-
:config="config"
|
|
49
|
-
:active="active"
|
|
50
|
-
>
|
|
51
|
-
<template #suggestions>
|
|
52
|
-
<gl-filtered-search-suggestion value="Yes"><gl-icon name="eye-slash" :size="16"/> Yes</gl-filtered-search-suggestion>
|
|
53
|
-
<gl-filtered-search-suggestion value="No"><gl-icon name="eye" :size="16"/> No</gl-filtered-search-suggestion>
|
|
54
|
-
</template>
|
|
55
|
-
</gl-filtered-search-token>
|
|
56
|
-
</div>
|
|
57
|
-
<div>
|
|
58
|
-
<portal-target name="portal" class="gl-relative" />
|
|
59
|
-
</div>
|
|
54
|
+
<portal-target name="portal" class="gl-relative" />
|
|
60
55
|
</div>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
},
|
|
56
|
+
</div>
|
|
57
|
+
`,
|
|
58
|
+
});
|
|
59
|
+
Default.args = generateProps();
|
|
60
|
+
|
|
61
|
+
// eslint-disable-next-line no-unused-vars
|
|
62
|
+
export const WithCustomOperatorsOptions = (args, { argTypes }) => ({
|
|
63
|
+
components: {
|
|
64
|
+
GlFilteredSearchToken,
|
|
65
|
+
GlFilteredSearchSuggestion,
|
|
66
|
+
GlIcon,
|
|
67
|
+
},
|
|
68
|
+
provide,
|
|
69
|
+
props: ['active'],
|
|
70
|
+
data() {
|
|
71
|
+
return {
|
|
72
|
+
value: { operator: '!', data: 'Yes' },
|
|
73
|
+
config: {
|
|
74
|
+
title: 'Confidential',
|
|
81
75
|
operators: [
|
|
82
76
|
{ value: '^', description: 'or' },
|
|
83
77
|
{ value: '!', description: 'is not', default: 'true' },
|
|
84
78
|
],
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
mounted() {
|
|
83
|
+
this.$nextTick(() => {
|
|
84
|
+
document.activeElement.blur();
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
template: `
|
|
88
|
+
<div>
|
|
89
|
+
<div> {{ value }} </div>
|
|
90
|
+
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
91
|
+
<gl-filtered-search-token
|
|
92
|
+
v-model="value"
|
|
93
|
+
class="gl-h-full"
|
|
94
|
+
:config="config"
|
|
95
|
+
:active="active"
|
|
96
|
+
>
|
|
103
97
|
<template #suggestions>
|
|
104
98
|
<gl-filtered-search-suggestion value="Yes"><gl-icon name="eye-slash" :size="16"/> Yes</gl-filtered-search-suggestion>
|
|
105
99
|
<gl-filtered-search-suggestion value="No"><gl-icon name="eye" :size="16"/> No</gl-filtered-search-suggestion>
|
|
106
100
|
</template>
|
|
107
|
-
</
|
|
108
|
-
<div>
|
|
109
|
-
<portal-target name="portal" class="gl-relative" />
|
|
110
|
-
</div>
|
|
101
|
+
</gl-filtered-search-token>
|
|
111
102
|
</div>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
103
|
+
<div>
|
|
104
|
+
<portal-target name="portal" class="gl-relative" />
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
`,
|
|
108
|
+
});
|
|
109
|
+
WithCustomOperatorsOptions.args = generateProps();
|
|
110
|
+
|
|
111
|
+
// eslint-disable-next-line no-unused-vars
|
|
112
|
+
export const WithStaticOptions = (args, { argTypes }) => ({
|
|
113
|
+
components: {
|
|
114
|
+
GlFilteredSearchToken,
|
|
115
|
+
GlFilteredSearchSuggestion,
|
|
116
|
+
},
|
|
117
|
+
provide,
|
|
118
|
+
props: ['active'],
|
|
119
|
+
data() {
|
|
120
|
+
return {
|
|
121
|
+
value: { operator: '=', data: 'first' },
|
|
122
|
+
config: {
|
|
123
|
+
title: 'Confidential',
|
|
132
124
|
options: [
|
|
133
125
|
{ icon: 'hourglass', title: 'first', value: 'one' },
|
|
134
126
|
{ title: 'second-without-icon', value: 'two' },
|
|
135
127
|
{ icon: 'issues', title: 'third', value: 'three' },
|
|
136
128
|
],
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
mounted() {
|
|
133
|
+
this.$nextTick(() => {
|
|
134
|
+
document.activeElement.blur();
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
template: `
|
|
138
|
+
<div>
|
|
139
|
+
<div> {{ value }} </div>
|
|
140
|
+
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
141
|
+
<gl-filtered-search-token
|
|
142
|
+
v-model="value"
|
|
143
|
+
class="gl-h-full"
|
|
144
|
+
:config="config"
|
|
145
|
+
:active="active"
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
145
148
|
<div>
|
|
146
|
-
<
|
|
147
|
-
<div class="gl-border-1 gl-border-solid gl-border-gray-200">
|
|
148
|
-
<gl-filtered-search-token
|
|
149
|
-
v-model="value"
|
|
150
|
-
class="gl-h-full"
|
|
151
|
-
:config="config"
|
|
152
|
-
:active="active"
|
|
153
|
-
:options="options"
|
|
154
|
-
/>
|
|
155
|
-
</div>
|
|
156
|
-
<div>
|
|
157
|
-
<portal-target name="portal" class="gl-relative" />
|
|
158
|
-
</div>
|
|
149
|
+
<portal-target name="portal" class="gl-relative" />
|
|
159
150
|
</div>
|
|
160
|
-
|
|
161
|
-
|
|
151
|
+
</div>
|
|
152
|
+
`,
|
|
153
|
+
});
|
|
154
|
+
WithStaticOptions.args = generateProps();
|
|
155
|
+
|
|
156
|
+
export default {
|
|
157
|
+
title: 'base/filtered-search/token',
|
|
158
|
+
component: GlFilteredSearchToken,
|
|
159
|
+
parameters: {
|
|
160
|
+
docs: {
|
|
161
|
+
description: {
|
|
162
|
+
component: readme,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { cloneDeep } from 'lodash';
|
|
2
3
|
import { COMMA } from '../../../utils/constants';
|
|
3
4
|
import GlToken from '../token/token.vue';
|
|
4
5
|
import GlFilteredSearchTokenSegment from './filtered_search_token_segment.vue';
|
|
5
|
-
import {
|
|
6
|
+
import { createTerm } from './filtered_search_utils';
|
|
6
7
|
|
|
7
8
|
const SEGMENT_TITLE = 'TYPE';
|
|
8
9
|
const SEGMENT_OPERATOR = 'OPERATOR';
|
|
@@ -15,6 +16,7 @@ const DEFAULT_OPERATORS = [
|
|
|
15
16
|
];
|
|
16
17
|
|
|
17
18
|
export default {
|
|
19
|
+
name: 'GlFilteredSearchToken',
|
|
18
20
|
components: {
|
|
19
21
|
GlToken,
|
|
20
22
|
GlFilteredSearchTokenSegment,
|
|
@@ -26,11 +28,17 @@ export default {
|
|
|
26
28
|
required: false,
|
|
27
29
|
default: () => [],
|
|
28
30
|
},
|
|
31
|
+
/**
|
|
32
|
+
* Token configuration with available operators and options.
|
|
33
|
+
*/
|
|
29
34
|
config: {
|
|
30
35
|
type: Object,
|
|
31
36
|
required: false,
|
|
32
37
|
default: () => ({}),
|
|
33
38
|
},
|
|
39
|
+
/**
|
|
40
|
+
* Determines if the token is being edited or not.
|
|
41
|
+
*/
|
|
34
42
|
active: {
|
|
35
43
|
type: Boolean,
|
|
36
44
|
required: false,
|
|
@@ -41,11 +49,17 @@ export default {
|
|
|
41
49
|
required: false,
|
|
42
50
|
default: () => [],
|
|
43
51
|
},
|
|
52
|
+
/**
|
|
53
|
+
* Current token value.
|
|
54
|
+
*/
|
|
44
55
|
value: {
|
|
45
56
|
type: Object,
|
|
46
57
|
required: false,
|
|
47
58
|
default: () => ({ operator: '', data: '' }),
|
|
48
59
|
},
|
|
60
|
+
/**
|
|
61
|
+
* Display operators' descriptions instead of their values (e.g., "is" instead of "=").
|
|
62
|
+
*/
|
|
49
63
|
showFriendlyText: {
|
|
50
64
|
type: Boolean,
|
|
51
65
|
required: false,
|
|
@@ -55,6 +69,7 @@ export default {
|
|
|
55
69
|
data() {
|
|
56
70
|
return {
|
|
57
71
|
activeSegment: null,
|
|
72
|
+
tokenValue: cloneDeep(this.value),
|
|
58
73
|
};
|
|
59
74
|
},
|
|
60
75
|
|
|
@@ -64,7 +79,7 @@ export default {
|
|
|
64
79
|
},
|
|
65
80
|
|
|
66
81
|
hasDataOrDataSegmentIsCurrentlyActive() {
|
|
67
|
-
return this.
|
|
82
|
+
return this.tokenValue.data !== '' || this.isSegmentActive(SEGMENT_DATA);
|
|
68
83
|
},
|
|
69
84
|
|
|
70
85
|
availableTokensWithSelf() {
|
|
@@ -75,7 +90,7 @@ export default {
|
|
|
75
90
|
},
|
|
76
91
|
|
|
77
92
|
operatorDescription() {
|
|
78
|
-
const operator = this.operators.find((op) => op.value === this.
|
|
93
|
+
const operator = this.operators.find((op) => op.value === this.tokenValue.operator);
|
|
79
94
|
return this.showFriendlyText ? operator?.description : operator?.value;
|
|
80
95
|
},
|
|
81
96
|
},
|
|
@@ -85,22 +100,43 @@ export default {
|
|
|
85
100
|
SEGMENT_OPERATOR,
|
|
86
101
|
},
|
|
87
102
|
watch: {
|
|
88
|
-
|
|
103
|
+
tokenValue: {
|
|
89
104
|
deep: true,
|
|
90
105
|
handler(newValue) {
|
|
106
|
+
/**
|
|
107
|
+
* Emitted when the token changes its value.
|
|
108
|
+
*
|
|
109
|
+
* @event input
|
|
110
|
+
* @type {object} dataObj Object containing the update value.
|
|
111
|
+
*/
|
|
91
112
|
this.$emit('input', newValue);
|
|
92
113
|
},
|
|
93
114
|
},
|
|
94
115
|
|
|
116
|
+
value: {
|
|
117
|
+
handler(newValue, oldValue) {
|
|
118
|
+
if (newValue?.data === oldValue?.data && newValue?.operator === oldValue?.operator) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.tokenValue = cloneDeep(newValue);
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
|
|
95
126
|
active: {
|
|
96
127
|
immediate: true,
|
|
97
128
|
handler(newValue) {
|
|
98
129
|
if (newValue) {
|
|
99
130
|
if (!this.activeSegment) {
|
|
100
|
-
this.activateSegment(this.
|
|
131
|
+
this.activateSegment(this.tokenValue.data !== '' ? SEGMENT_DATA : SEGMENT_OPERATOR);
|
|
101
132
|
}
|
|
102
|
-
} else if (this.
|
|
133
|
+
} else if (this.tokenValue.data === '') {
|
|
103
134
|
this.activeSegment = null;
|
|
135
|
+
/**
|
|
136
|
+
* Emitted when token is about to be destroyed.
|
|
137
|
+
*
|
|
138
|
+
* @event destroy
|
|
139
|
+
*/
|
|
104
140
|
this.$emit('destroy');
|
|
105
141
|
}
|
|
106
142
|
},
|
|
@@ -108,13 +144,13 @@ export default {
|
|
|
108
144
|
},
|
|
109
145
|
|
|
110
146
|
created() {
|
|
111
|
-
if (!('operator' in this.
|
|
147
|
+
if (!('operator' in this.tokenValue)) {
|
|
112
148
|
if (this.operators.length === 1) {
|
|
113
149
|
const operator = this.operators[0].value;
|
|
114
|
-
this.$emit('input', { ...this.
|
|
150
|
+
this.$emit('input', { ...this.tokenValue, operator });
|
|
115
151
|
this.activeSegment = SEGMENT_DATA;
|
|
116
152
|
} else {
|
|
117
|
-
this.$emit('input', { ...this.
|
|
153
|
+
this.$emit('input', { ...this.tokenValue, operator: '' });
|
|
118
154
|
}
|
|
119
155
|
}
|
|
120
156
|
},
|
|
@@ -124,6 +160,11 @@ export default {
|
|
|
124
160
|
this.activeSegment = segment;
|
|
125
161
|
|
|
126
162
|
if (!this.active) {
|
|
163
|
+
/**
|
|
164
|
+
* Emitted when this term token is clicked.
|
|
165
|
+
*
|
|
166
|
+
* @event activate
|
|
167
|
+
*/
|
|
127
168
|
this.$emit('activate');
|
|
128
169
|
}
|
|
129
170
|
},
|
|
@@ -137,8 +178,12 @@ export default {
|
|
|
137
178
|
},
|
|
138
179
|
|
|
139
180
|
replaceWithTermIfEmpty() {
|
|
140
|
-
if (this.
|
|
141
|
-
|
|
181
|
+
if (this.tokenValue.operator === '' && this.tokenValue.data === '') {
|
|
182
|
+
/**
|
|
183
|
+
* Emitted when this token is converted to another type
|
|
184
|
+
* @property {object} token Replacement token configuration
|
|
185
|
+
*/
|
|
186
|
+
this.$emit('replace', createTerm(this.config.title));
|
|
142
187
|
}
|
|
143
188
|
},
|
|
144
189
|
|
|
@@ -147,6 +192,11 @@ export default {
|
|
|
147
192
|
|
|
148
193
|
if (newTokenConfig === this.config) {
|
|
149
194
|
this.$nextTick(() => {
|
|
195
|
+
/**
|
|
196
|
+
* Emitted when this term token will lose its focus.
|
|
197
|
+
*
|
|
198
|
+
* @event deactivate
|
|
199
|
+
*/
|
|
150
200
|
this.$emit('deactivate');
|
|
151
201
|
});
|
|
152
202
|
return;
|
|
@@ -157,7 +207,7 @@ export default {
|
|
|
157
207
|
this.config.dataType && this.config.dataType === newTokenConfig.dataType;
|
|
158
208
|
this.$emit('replace', {
|
|
159
209
|
type: newTokenConfig.type,
|
|
160
|
-
value: isCompatible ? this.
|
|
210
|
+
value: isCompatible ? this.tokenValue : { data: '' },
|
|
161
211
|
});
|
|
162
212
|
}
|
|
163
213
|
},
|
|
@@ -174,7 +224,7 @@ export default {
|
|
|
174
224
|
key.length === 1 &&
|
|
175
225
|
!this.operators.find(({ value }) => value.startsWith(potentialValue))
|
|
176
226
|
) {
|
|
177
|
-
if (this.
|
|
227
|
+
if (this.tokenValue.data === '') {
|
|
178
228
|
applySuggestion(suggestedValue);
|
|
179
229
|
} else {
|
|
180
230
|
evt.preventDefault();
|
|
@@ -184,21 +234,27 @@ export default {
|
|
|
184
234
|
|
|
185
235
|
activateDataSegment() {
|
|
186
236
|
if (this.config.multiSelect) {
|
|
187
|
-
this.$emit('input', { ...this.
|
|
237
|
+
this.$emit('input', { ...this.tokenValue, data: '' });
|
|
188
238
|
}
|
|
189
239
|
this.activateSegment(this.$options.segments.SEGMENT_DATA);
|
|
190
240
|
},
|
|
191
241
|
|
|
192
242
|
handleComplete() {
|
|
193
243
|
if (this.config.multiSelect) {
|
|
194
|
-
this.$emit('input', { ...this.
|
|
244
|
+
this.$emit('input', { ...this.tokenValue, data: this.multiSelectValues.join(COMMA) });
|
|
195
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Emitted when the token entry has been completed.
|
|
248
|
+
*
|
|
249
|
+
* @event complete
|
|
250
|
+
*/
|
|
196
251
|
this.$emit('complete');
|
|
197
252
|
},
|
|
198
253
|
|
|
199
254
|
destroyByClose(event) {
|
|
200
255
|
if (event.target.closest(TOKEN_CLOSE_SELECTOR)) {
|
|
201
256
|
event.preventDefault();
|
|
257
|
+
event.stopPropagation();
|
|
202
258
|
this.$emit('destroy');
|
|
203
259
|
}
|
|
204
260
|
},
|
|
@@ -208,6 +264,10 @@ export default {
|
|
|
208
264
|
|
|
209
265
|
<template>
|
|
210
266
|
<div class="gl-filtered-search-token" :class="{ 'gl-filtered-search-token-active': active }">
|
|
267
|
+
<!--
|
|
268
|
+
Emitted when the token is submitted.
|
|
269
|
+
@event submit
|
|
270
|
+
-->
|
|
211
271
|
<gl-filtered-search-token-segment
|
|
212
272
|
key="title-segment"
|
|
213
273
|
:value="config.title"
|
|
@@ -228,10 +288,9 @@ export default {
|
|
|
228
288
|
>
|
|
229
289
|
</template>
|
|
230
290
|
</gl-filtered-search-token-segment>
|
|
231
|
-
<!-- eslint-disable vue/no-mutating-props -->
|
|
232
291
|
<gl-filtered-search-token-segment
|
|
233
292
|
key="operator-segment"
|
|
234
|
-
v-model="
|
|
293
|
+
v-model="tokenValue.operator"
|
|
235
294
|
:active="isSegmentActive($options.segments.SEGMENT_OPERATOR)"
|
|
236
295
|
:options="operators"
|
|
237
296
|
:custom-input-keydown-handler="handleOperatorKeydown"
|
|
@@ -241,7 +300,6 @@ export default {
|
|
|
241
300
|
@complete="activateSegment($options.segments.SEGMENT_DATA)"
|
|
242
301
|
@deactivate="$emit('deactivate')"
|
|
243
302
|
>
|
|
244
|
-
<!-- eslint-enable vue/no-mutating-props -->
|
|
245
303
|
<template #view>
|
|
246
304
|
<gl-token
|
|
247
305
|
class="gl-filtered-search-token-operator"
|
|
@@ -260,11 +318,20 @@ export default {
|
|
|
260
318
|
</div>
|
|
261
319
|
</template>
|
|
262
320
|
</gl-filtered-search-token-segment>
|
|
263
|
-
<!--
|
|
321
|
+
<!--
|
|
322
|
+
Emitted when a suggestion has been selected.
|
|
323
|
+
@event select
|
|
324
|
+
@type {string} value The value of the selected suggestion.
|
|
325
|
+
-->
|
|
326
|
+
<!--
|
|
327
|
+
Emitted when Space is pressed in-between term text.
|
|
328
|
+
@event split
|
|
329
|
+
@property {array} newTokens Token configurations
|
|
330
|
+
-->
|
|
264
331
|
<gl-filtered-search-token-segment
|
|
265
332
|
v-if="hasDataOrDataSegmentIsCurrentlyActive"
|
|
266
333
|
key="data-segment"
|
|
267
|
-
v-model="
|
|
334
|
+
v-model="tokenValue.data"
|
|
268
335
|
:active="isSegmentActive($options.segments.SEGMENT_DATA)"
|
|
269
336
|
:multi-select="config.multiSelect"
|
|
270
337
|
:options="config.options"
|
|
@@ -277,11 +344,12 @@ export default {
|
|
|
277
344
|
@deactivate="$emit('deactivate')"
|
|
278
345
|
@split="$emit('split', $event)"
|
|
279
346
|
>
|
|
280
|
-
<!-- eslint-enable vue/no-mutating-props -->
|
|
281
347
|
<template #suggestions>
|
|
348
|
+
<!-- @slot The suggestions (implemented with GlFilteredSearchSuggestion). -->
|
|
282
349
|
<slot name="suggestions"></slot>
|
|
283
350
|
</template>
|
|
284
351
|
<template #view="{ inputValue }">
|
|
352
|
+
<!-- @slot Used to customize how the token is rendered. -->
|
|
285
353
|
<slot
|
|
286
354
|
name="view-token"
|
|
287
355
|
v-bind="{
|
|
@@ -300,6 +368,10 @@ export default {
|
|
|
300
368
|
@mousedown="destroyByClose"
|
|
301
369
|
>
|
|
302
370
|
<span class="gl-filtered-search-token-data-content">
|
|
371
|
+
<!--
|
|
372
|
+
@slot Template for token value in inactive state
|
|
373
|
+
@binding {array} suggestions Slot for rendering autocomplete suggestions when no options are provided.
|
|
374
|
+
-->
|
|
303
375
|
<slot name="view" v-bind="{ inputValue }">{{ inputValue }}</slot>
|
|
304
376
|
</span>
|
|
305
377
|
</gl-token>
|
|
@@ -2,47 +2,4 @@ import * as description from './filtered_search_token_segment.md';
|
|
|
2
2
|
|
|
3
3
|
export default {
|
|
4
4
|
description,
|
|
5
|
-
bootstrapComponent: null,
|
|
6
|
-
propsInfo: {
|
|
7
|
-
active: {
|
|
8
|
-
additionalInfo: 'If this term token is currently active',
|
|
9
|
-
},
|
|
10
|
-
options: {
|
|
11
|
-
additionalInfo: '',
|
|
12
|
-
},
|
|
13
|
-
optionTextField: {
|
|
14
|
-
additionalInfo: '',
|
|
15
|
-
},
|
|
16
|
-
customInputKeydownHandler: {
|
|
17
|
-
additionalInfo: '',
|
|
18
|
-
},
|
|
19
|
-
value: {
|
|
20
|
-
additionalInfo: 'Current term value',
|
|
21
|
-
},
|
|
22
|
-
searchInputAttributes: {
|
|
23
|
-
additionalInfo: 'HTML attributes to add to the search input',
|
|
24
|
-
},
|
|
25
|
-
isLastToken: {
|
|
26
|
-
additionalInfo: 'If this is the last token',
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
events: [
|
|
30
|
-
{ event: 'activate', description: 'Emitted on mousedown event on the main component' },
|
|
31
|
-
{ event: 'backspace', description: 'Emitted when Backspace is pressed and the value is empty' },
|
|
32
|
-
{
|
|
33
|
-
event: 'complete',
|
|
34
|
-
description: 'Emitted when suggestion is selected from the suggestion list',
|
|
35
|
-
},
|
|
36
|
-
{ event: 'submit', description: 'Emitted when Enter is pressed and no suggestion is selected' },
|
|
37
|
-
{
|
|
38
|
-
event: 'split',
|
|
39
|
-
args: [
|
|
40
|
-
{
|
|
41
|
-
arg: 'newStrings',
|
|
42
|
-
description: '(Array of strings) New strings to be converted into term tokens',
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
description: 'Emitted when Space appears in token segment value',
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
5
|
};
|