@gitlab/ui 39.3.1 → 39.5.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 +26 -0
- package/dist/components/base/alert/alert.js +1 -1
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +240 -0
- package/dist/components/base/new_dropdowns/constants.js +20 -0
- package/dist/components/base/new_dropdowns/listbox/listbox.js +381 -0
- package/dist/components/base/new_dropdowns/listbox/listbox_item.js +77 -0
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.js +2 -0
- package/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/dist/utils/utils.js +24 -1
- package/package.json +6 -5
- package/scss_to_js/scss_variables.js +1 -0
- package/scss_to_js/scss_variables.json +5 -0
- package/src/components/base/alert/alert.spec.js +3 -1
- package/src/components/base/alert/alert.vue +1 -1
- package/src/components/base/avatar_labeled/avatar_labeled.stories.js +2 -1
- package/src/components/base/avatar_link/avatar_link.stories.js +2 -3
- package/src/components/base/breadcrumb/breadcrumb.md +1 -1
- package/src/components/base/breadcrumb/breadcrumb.stories.js +2 -1
- package/src/components/base/broadcast_message/broadcast_message.scss +1 -1
- package/src/components/base/button/button.scss +1 -1
- package/src/components/base/dropdown/dropdown.scss +10 -3
- package/src/components/base/dropdown/dropdown_item.scss +1 -0
- package/src/components/base/link/link.stories.js +9 -7
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +171 -0
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +221 -0
- package/src/components/base/new_dropdowns/constants.js +22 -0
- package/src/components/base/new_dropdowns/listbox/listbox.md +71 -0
- package/src/components/base/new_dropdowns/listbox/listbox.spec.js +236 -0
- package/src/components/base/new_dropdowns/listbox/listbox.stories.js +276 -0
- package/src/components/base/new_dropdowns/listbox/listbox.vue +348 -0
- package/src/components/base/new_dropdowns/listbox/listbox_item.spec.js +104 -0
- package/src/components/base/new_dropdowns/listbox/listbox_item.vue +59 -0
- package/src/components/utilities/friendly_wrap/friendly_wrap.stories.js +10 -11
- package/src/components/utilities/sprintf/sprintf.stories.js +11 -9
- package/src/index.js +4 -0
- package/src/scss/utilities.scss +18 -0
- package/src/scss/utility-mixins/color.scss +4 -0
- package/src/scss/utility-mixins/composite.scss +20 -0
- package/src/scss/utility-mixins/index.scss +1 -0
- package/src/scss/variables.scss +1 -0
- package/src/utils/data_utils.js +2 -21
- package/src/utils/utils.js +18 -0
- package/src/utils/utils.spec.js +41 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
# [39.5.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v39.4.0...v39.5.0) (2022-05-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **Alert:** Change title heading level from 4 to 2 ([0d69125](https://gitlab.com/gitlab-org/gitlab-ui/commit/0d69125fd7ef23ef6fe8eeb2d5395b6dc5dbde09))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add gl--flex-center composite class ([d1b3153](https://gitlab.com/gitlab-org/gitlab-ui/commit/d1b315356dfb07e718d67df0c16d0e43c48c1f55))
|
|
12
|
+
|
|
13
|
+
# [39.4.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v39.3.2...v39.4.0) (2022-04-28)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* **GlListbox:** create listbox component ([dcc7eae](https://gitlab.com/gitlab-org/gitlab-ui/commit/dcc7eae54db81de1c922857c990f89ceb0e1c694))
|
|
19
|
+
|
|
20
|
+
## [39.3.2](https://gitlab.com/gitlab-org/gitlab-ui/compare/v39.3.1...v39.3.2) (2022-04-27)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* **GlButton:** Fix button text color in dark mode ([61267e3](https://gitlab.com/gitlab-org/gitlab-ui/commit/61267e3ce3c80d0592e5fe7e6458c86ab6ff3979))
|
|
26
|
+
|
|
1
27
|
## [39.3.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v39.3.0...v39.3.1) (2022-04-26)
|
|
2
28
|
|
|
3
29
|
|
|
@@ -185,7 +185,7 @@ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=
|
|
|
185
185
|
{ 'gl-alert-sticky': _vm.sticky },
|
|
186
186
|
{ 'gl-alert-not-dismissible': !_vm.dismissible },
|
|
187
187
|
{ 'gl-alert-no-icon': !_vm.showIcon },
|
|
188
|
-
_vm.variantClass ]},[(_vm.showIcon)?_c('gl-icon',{class:{ 'gl-alert-icon': true, 'gl-alert-icon-no-title': !_vm.title },attrs:{"name":_vm.iconName}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-alert-content",attrs:{"role":"alert"}},[(_vm.title)?_c('
|
|
188
|
+
_vm.variantClass ]},[(_vm.showIcon)?_c('gl-icon',{class:{ 'gl-alert-icon': true, 'gl-alert-icon-no-title': !_vm.title },attrs:{"name":_vm.iconName}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-alert-content",attrs:{"role":"alert"}},[(_vm.title)?_c('h2',{staticClass:"gl-alert-title"},[_vm._v(_vm._s(_vm.title))]):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-alert-body"},[_vm._t("default")],2),_vm._v(" "),(_vm.shouldRenderActions)?_c('div',{staticClass:"gl-alert-actions"},[_vm._t("actions",_vm._l((_vm.actionButtons),function(actionButton,index){return _c('gl-button',_vm._g(_vm._b({key:index,staticClass:"gl-alert-action"},'gl-button',actionButton.attrs,false),actionButton.listeners),[_vm._v("\n "+_vm._s(actionButton.text)+"\n ")])}))],2):_vm._e()]),_vm._v(" "),(_vm.dismissible)?_c('close-button',{ref:"dismiss",staticClass:"gl-dismiss-btn",attrs:{"label":_vm.dismissLabel},on:{"click":_vm.onDismiss}}):_vm._e()],1)};
|
|
189
189
|
var __vue_staticRenderFns__ = [];
|
|
190
190
|
|
|
191
191
|
/* style */
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { createPopper } from '@popperjs/core';
|
|
2
|
+
import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions } from '../../../../utils/constants';
|
|
3
|
+
import { POPPER_CONFIG, GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN } from '../constants';
|
|
4
|
+
import GlButton from '../../button/button';
|
|
5
|
+
import GlIcon from '../../icon/icon';
|
|
6
|
+
import { OutsideDirective } from '../../../../directives/outside/outside';
|
|
7
|
+
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
8
|
+
|
|
9
|
+
var script = {
|
|
10
|
+
components: {
|
|
11
|
+
GlButton,
|
|
12
|
+
GlIcon
|
|
13
|
+
},
|
|
14
|
+
directives: {
|
|
15
|
+
Outside: OutsideDirective
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
toggleText: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: false,
|
|
21
|
+
default: ''
|
|
22
|
+
},
|
|
23
|
+
textSrOnly: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
required: false,
|
|
26
|
+
default: false
|
|
27
|
+
},
|
|
28
|
+
category: {
|
|
29
|
+
type: String,
|
|
30
|
+
required: false,
|
|
31
|
+
default: buttonCategoryOptions.primary,
|
|
32
|
+
validator: value => Object.keys(buttonCategoryOptions).includes(value)
|
|
33
|
+
},
|
|
34
|
+
variant: {
|
|
35
|
+
type: String,
|
|
36
|
+
required: false,
|
|
37
|
+
default: dropdownVariantOptions.default,
|
|
38
|
+
validator: value => Object.keys(dropdownVariantOptions).includes(value)
|
|
39
|
+
},
|
|
40
|
+
size: {
|
|
41
|
+
type: String,
|
|
42
|
+
required: false,
|
|
43
|
+
default: buttonSizeOptions.medium,
|
|
44
|
+
validator: value => Object.keys(buttonSizeOptions).includes(value)
|
|
45
|
+
},
|
|
46
|
+
icon: {
|
|
47
|
+
type: String,
|
|
48
|
+
required: false,
|
|
49
|
+
default: ''
|
|
50
|
+
},
|
|
51
|
+
disabled: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
required: false,
|
|
54
|
+
default: false
|
|
55
|
+
},
|
|
56
|
+
loading: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
required: false,
|
|
59
|
+
default: false
|
|
60
|
+
},
|
|
61
|
+
toggleClass: {
|
|
62
|
+
type: [String, Array, Object],
|
|
63
|
+
required: false,
|
|
64
|
+
default: null
|
|
65
|
+
},
|
|
66
|
+
noCaret: {
|
|
67
|
+
type: Boolean,
|
|
68
|
+
required: false,
|
|
69
|
+
default: false
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Right align dropdown menu with respect to the toggle button
|
|
74
|
+
*/
|
|
75
|
+
right: {
|
|
76
|
+
type: Boolean,
|
|
77
|
+
required: false,
|
|
78
|
+
default: false
|
|
79
|
+
},
|
|
80
|
+
// ARIA props
|
|
81
|
+
ariaHaspopup: {
|
|
82
|
+
type: [String, Boolean],
|
|
83
|
+
required: false,
|
|
84
|
+
default: false,
|
|
85
|
+
validator: value => {
|
|
86
|
+
return ['menu', 'listbox', 'tree', 'grid', 'dialog', true, false].includes(value);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Id that will be referenced by `aria-labelledby` attribute of the dropdown content`
|
|
92
|
+
*/
|
|
93
|
+
toggleId: {
|
|
94
|
+
type: String,
|
|
95
|
+
required: true
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The `aria-labelledby` attribute value for the toggle `button`
|
|
100
|
+
*/
|
|
101
|
+
ariaLabelledby: {
|
|
102
|
+
type: String,
|
|
103
|
+
required: false,
|
|
104
|
+
default: null
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
data() {
|
|
109
|
+
return {
|
|
110
|
+
visible: false
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
computed: {
|
|
115
|
+
isIconOnly() {
|
|
116
|
+
var _this$toggleText;
|
|
117
|
+
|
|
118
|
+
return Boolean(this.icon && (!((_this$toggleText = this.toggleText) !== null && _this$toggleText !== void 0 && _this$toggleText.length) || this.textSrOnly));
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
isIconWithText() {
|
|
122
|
+
var _this$toggleText2;
|
|
123
|
+
|
|
124
|
+
return Boolean(this.icon && ((_this$toggleText2 = this.toggleText) === null || _this$toggleText2 === void 0 ? void 0 : _this$toggleText2.length) && !this.textSrOnly);
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
toggleButtonClasses() {
|
|
128
|
+
return [this.toggleClass, {
|
|
129
|
+
'gl-dropdown-toggle': true,
|
|
130
|
+
'dropdown-toggle': true,
|
|
131
|
+
'dropdown-icon-only': this.isIconOnly,
|
|
132
|
+
'dropdown-icon-text': this.isIconWithText,
|
|
133
|
+
'dropdown-toggle-no-caret': this.noCaret
|
|
134
|
+
}];
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
toggleLabelledBy() {
|
|
138
|
+
return this.ariaLabelledby ? `${this.ariaLabelledby} ${this.toggleId}` : this.toggleId;
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
popperConfig() {
|
|
142
|
+
return {
|
|
143
|
+
placement: this.right ? 'bottom-end' : 'bottom-start',
|
|
144
|
+
...POPPER_CONFIG
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
updated() {
|
|
151
|
+
if (this.visible) {
|
|
152
|
+
var _this$popper;
|
|
153
|
+
|
|
154
|
+
(_this$popper = this.popper) === null || _this$popper === void 0 ? void 0 : _this$popper.update();
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
mounted() {
|
|
159
|
+
this.$nextTick(() => {
|
|
160
|
+
this.popper = createPopper(this.$refs.toggle.$el, this.$refs.content, this.popperConfig);
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
beforeDestroy() {
|
|
165
|
+
this.popper.destroy();
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
methods: {
|
|
169
|
+
toggle() {
|
|
170
|
+
this.visible = !this.visible;
|
|
171
|
+
|
|
172
|
+
if (this.visible) {
|
|
173
|
+
this.popper.update();
|
|
174
|
+
this.$emit(GL_DROPDOWN_SHOWN);
|
|
175
|
+
} else {
|
|
176
|
+
this.$emit(GL_DROPDOWN_HIDDEN);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
close() {
|
|
181
|
+
if (!this.visible) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.toggle();
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
closeAndFocus() {
|
|
189
|
+
if (!this.visible) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.toggle();
|
|
194
|
+
this.focusToggle();
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
focusToggle() {
|
|
198
|
+
this.$refs.toggle.$el.focus();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/* script */
|
|
205
|
+
const __vue_script__ = script;
|
|
206
|
+
|
|
207
|
+
/* template */
|
|
208
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{directives:[{name:"outside",rawName:"v-outside",value:(_vm.close),expression:"close"}],staticClass:"gl-new-dropdown dropdown btn-group"},[_c('gl-button',{ref:"toggle",class:_vm.toggleButtonClasses,attrs:{"id":_vm.toggleId,"data-testid":"base-dropdown-toggle","icon":_vm.icon,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"disabled":_vm.disabled,"loading":_vm.loading,"aria-haspopup":_vm.ariaHaspopup,"aria-expanded":_vm.visible,"aria-labelledby":_vm.toggleLabelledBy},on:{"click":_vm.toggle}},[_c('span',{staticClass:"gl-new-dropdown-button-text",class:{ 'gl-sr-only': _vm.textSrOnly }},[_vm._v("\n "+_vm._s(_vm.toggleText)+"\n ")]),_vm._v(" "),(!_vm.noCaret)?_c('gl-icon',{staticClass:"gl-button-icon dropdown-chevron",attrs:{"name":"chevron-down"}}):_vm._e()],1),_vm._v(" "),_c('div',{ref:"content",staticClass:"dropdown-menu",class:{ show: _vm.visible },attrs:{"data-testid":"base-dropdown-menu"},on:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }$event.stopPropagation();$event.preventDefault();return _vm.closeAndFocus($event)}}},[_c('div',{staticClass:"gl-new-dropdown-inner"},[_vm._t("default")],2)])],1)};
|
|
209
|
+
var __vue_staticRenderFns__ = [];
|
|
210
|
+
|
|
211
|
+
/* style */
|
|
212
|
+
const __vue_inject_styles__ = undefined;
|
|
213
|
+
/* scoped */
|
|
214
|
+
const __vue_scope_id__ = undefined;
|
|
215
|
+
/* module identifier */
|
|
216
|
+
const __vue_module_identifier__ = undefined;
|
|
217
|
+
/* functional template */
|
|
218
|
+
const __vue_is_functional_template__ = false;
|
|
219
|
+
/* style inject */
|
|
220
|
+
|
|
221
|
+
/* style inject SSR */
|
|
222
|
+
|
|
223
|
+
/* style inject shadow dom */
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
const __vue_component__ = __vue_normalize__(
|
|
228
|
+
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
|
|
229
|
+
__vue_inject_styles__,
|
|
230
|
+
__vue_script__,
|
|
231
|
+
__vue_scope_id__,
|
|
232
|
+
__vue_is_functional_template__,
|
|
233
|
+
__vue_module_identifier__,
|
|
234
|
+
false,
|
|
235
|
+
undefined,
|
|
236
|
+
undefined,
|
|
237
|
+
undefined
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
export default __vue_component__;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const POPPER_CONFIG = {
|
|
2
|
+
modifiers: [{
|
|
3
|
+
name: 'offset',
|
|
4
|
+
options: {
|
|
5
|
+
offset: [0, 4]
|
|
6
|
+
}
|
|
7
|
+
}]
|
|
8
|
+
}; // base dropdown events
|
|
9
|
+
|
|
10
|
+
const GL_DROPDOWN_SHOWN = 'shown';
|
|
11
|
+
const GL_DROPDOWN_HIDDEN = 'hidden'; // KEY Codes
|
|
12
|
+
|
|
13
|
+
const HOME = 'Home';
|
|
14
|
+
const END = 'End';
|
|
15
|
+
const ARROW_UP = 'ArrowUp';
|
|
16
|
+
const ARROW_DOWN = 'ArrowDown';
|
|
17
|
+
const ENTER = 'Enter';
|
|
18
|
+
const SPACE = 'Space';
|
|
19
|
+
|
|
20
|
+
export { ARROW_DOWN, ARROW_UP, END, ENTER, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_SHOWN, HOME, POPPER_CONFIG, SPACE };
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import _uniqueId from 'lodash/uniqueId';
|
|
2
|
+
import _clamp from 'lodash/clamp';
|
|
3
|
+
import { stopEvent } from '../../../../utils/utils';
|
|
4
|
+
import { GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, HOME, END, ARROW_UP, ARROW_DOWN } from '../constants';
|
|
5
|
+
import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions } from '../../../../utils/constants';
|
|
6
|
+
import GlBaseDropdown from '../base_dropdown/base_dropdown';
|
|
7
|
+
import GlListboxItem from './listbox_item';
|
|
8
|
+
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
9
|
+
|
|
10
|
+
const ITEM_SELECTOR = '[role="option"]';
|
|
11
|
+
var script = {
|
|
12
|
+
events: {
|
|
13
|
+
GL_DROPDOWN_SHOWN,
|
|
14
|
+
GL_DROPDOWN_HIDDEN
|
|
15
|
+
},
|
|
16
|
+
components: {
|
|
17
|
+
GlBaseDropdown,
|
|
18
|
+
GlListboxItem
|
|
19
|
+
},
|
|
20
|
+
model: {
|
|
21
|
+
prop: 'selected',
|
|
22
|
+
event: 'select'
|
|
23
|
+
},
|
|
24
|
+
props: {
|
|
25
|
+
/**
|
|
26
|
+
* Items to display in the dropdown
|
|
27
|
+
*/
|
|
28
|
+
items: {
|
|
29
|
+
type: Array,
|
|
30
|
+
required: false,
|
|
31
|
+
default: () => [],
|
|
32
|
+
validator: items => {
|
|
33
|
+
return items.every(_ref => {
|
|
34
|
+
let {
|
|
35
|
+
value
|
|
36
|
+
} = _ref;
|
|
37
|
+
return typeof value === 'string';
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* array of selected items values for multi-select and selected item value for single-select
|
|
44
|
+
*/
|
|
45
|
+
selected: {
|
|
46
|
+
type: [Array, String, Number],
|
|
47
|
+
required: false,
|
|
48
|
+
default: () => []
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Allow multi-selection
|
|
53
|
+
*/
|
|
54
|
+
multiple: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
required: false,
|
|
57
|
+
default: false
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Toggle button text
|
|
62
|
+
*/
|
|
63
|
+
toggleText: {
|
|
64
|
+
type: String,
|
|
65
|
+
required: false,
|
|
66
|
+
default: ''
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Toggle text to be read by screen readers only
|
|
71
|
+
*/
|
|
72
|
+
textSrOnly: {
|
|
73
|
+
type: Boolean,
|
|
74
|
+
required: false,
|
|
75
|
+
default: false
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Styling option - dropdown's toggle category
|
|
80
|
+
*/
|
|
81
|
+
category: {
|
|
82
|
+
type: String,
|
|
83
|
+
required: false,
|
|
84
|
+
default: buttonCategoryOptions.primary,
|
|
85
|
+
validator: value => Object.keys(buttonCategoryOptions).includes(value)
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Styling option - dropdown's toggle variant
|
|
90
|
+
*/
|
|
91
|
+
variant: {
|
|
92
|
+
type: String,
|
|
93
|
+
required: false,
|
|
94
|
+
default: dropdownVariantOptions.default,
|
|
95
|
+
validator: value => Object.keys(dropdownVariantOptions).includes(value)
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The size of the dropdown toggle
|
|
100
|
+
*/
|
|
101
|
+
size: {
|
|
102
|
+
type: String,
|
|
103
|
+
required: false,
|
|
104
|
+
default: buttonSizeOptions.medium,
|
|
105
|
+
validator: value => Object.keys(buttonSizeOptions).includes(value)
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Icon name that will be rendered in the toggle button
|
|
110
|
+
*/
|
|
111
|
+
icon: {
|
|
112
|
+
type: String,
|
|
113
|
+
required: false,
|
|
114
|
+
default: ''
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Set to "true" to disable the dropdown
|
|
119
|
+
*/
|
|
120
|
+
disabled: {
|
|
121
|
+
type: Boolean,
|
|
122
|
+
required: false,
|
|
123
|
+
default: false
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Set to "true" when dropdown content (items) is loading
|
|
128
|
+
*/
|
|
129
|
+
loading: {
|
|
130
|
+
type: Boolean,
|
|
131
|
+
required: false,
|
|
132
|
+
default: false
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Additional CSS classes to customize toggle appearance
|
|
137
|
+
*/
|
|
138
|
+
toggleClass: {
|
|
139
|
+
type: [String, Array, Object],
|
|
140
|
+
required: false,
|
|
141
|
+
default: null
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Set to "true" to hide the caret
|
|
146
|
+
*/
|
|
147
|
+
noCaret: {
|
|
148
|
+
type: Boolean,
|
|
149
|
+
required: false,
|
|
150
|
+
default: false
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Right align listbox menu with respect to the toggle button
|
|
155
|
+
*/
|
|
156
|
+
right: {
|
|
157
|
+
type: Boolean,
|
|
158
|
+
required: false,
|
|
159
|
+
default: false
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The `aria-labelledby` attribute value for the toggle button
|
|
164
|
+
*/
|
|
165
|
+
ariaLabelledby: {
|
|
166
|
+
type: String,
|
|
167
|
+
required: false,
|
|
168
|
+
default: null
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
data() {
|
|
173
|
+
return {
|
|
174
|
+
selectedValues: [],
|
|
175
|
+
toggleId: _uniqueId('dropdown-toggle-btn-'),
|
|
176
|
+
nextFocusedItemIndex: null
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
computed: {
|
|
181
|
+
listboxToggleText() {
|
|
182
|
+
if (!this.toggleText) {
|
|
183
|
+
if (!this.multiple && this.selectedValues.length) {
|
|
184
|
+
var _this$items$find;
|
|
185
|
+
|
|
186
|
+
return (_this$items$find = this.items.find(_ref2 => {
|
|
187
|
+
let {
|
|
188
|
+
value
|
|
189
|
+
} = _ref2;
|
|
190
|
+
return value === this.selectedValues[0];
|
|
191
|
+
})) === null || _this$items$find === void 0 ? void 0 : _this$items$find.text;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return '';
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return this.toggleText;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
selectedIndices() {
|
|
201
|
+
return this.selectedValues.map(selected => this.items.findIndex(_ref3 => {
|
|
202
|
+
let {
|
|
203
|
+
value
|
|
204
|
+
} = _ref3;
|
|
205
|
+
return value === selected;
|
|
206
|
+
})).sort();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
},
|
|
210
|
+
watch: {
|
|
211
|
+
selected: {
|
|
212
|
+
immediate: true,
|
|
213
|
+
|
|
214
|
+
handler(newSelected) {
|
|
215
|
+
if (Array.isArray(newSelected)) {
|
|
216
|
+
if (!this.multiple && newSelected.length) {
|
|
217
|
+
throw new Error('To allow multi-selection, please, set "multiple" property to "true"');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
this.selectedValues = [...newSelected];
|
|
221
|
+
} else {
|
|
222
|
+
this.selectedValues = [newSelected];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
methods: {
|
|
229
|
+
onShow() {
|
|
230
|
+
this.$nextTick(() => {
|
|
231
|
+
var _this$selectedIndices;
|
|
232
|
+
|
|
233
|
+
this.focusItem((_this$selectedIndices = this.selectedIndices[0]) !== null && _this$selectedIndices !== void 0 ? _this$selectedIndices : 0, this.getFocusableListItemElements());
|
|
234
|
+
/**
|
|
235
|
+
* Emitted when dropdown is shown
|
|
236
|
+
*
|
|
237
|
+
* @event shown
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
this.$emit(GL_DROPDOWN_SHOWN);
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
onHide() {
|
|
245
|
+
/**
|
|
246
|
+
* Emitted when dropdown is hidden
|
|
247
|
+
*
|
|
248
|
+
* @event hidden
|
|
249
|
+
*/
|
|
250
|
+
this.$emit(GL_DROPDOWN_HIDDEN);
|
|
251
|
+
this.nextFocusedItemIndex = null;
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
onKeydown(event) {
|
|
255
|
+
const {
|
|
256
|
+
code
|
|
257
|
+
} = event;
|
|
258
|
+
const elements = this.getFocusableListItemElements();
|
|
259
|
+
if (elements.length < 1) return;
|
|
260
|
+
let stop = true;
|
|
261
|
+
|
|
262
|
+
if (code === HOME) {
|
|
263
|
+
this.focusItem(0, elements);
|
|
264
|
+
} else if (code === END) {
|
|
265
|
+
this.focusItem(elements.length - 1, elements);
|
|
266
|
+
} else if (code === ARROW_UP) {
|
|
267
|
+
this.focusNextItem(event, elements, -1);
|
|
268
|
+
} else if (code === ARROW_DOWN) {
|
|
269
|
+
this.focusNextItem(event, elements, 1);
|
|
270
|
+
} else {
|
|
271
|
+
stop = false;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (stop) {
|
|
275
|
+
stopEvent(event);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
getFocusableListItemElements() {
|
|
280
|
+
const items = this.$refs.list.querySelectorAll(ITEM_SELECTOR);
|
|
281
|
+
return Array.from(items);
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
focusNextItem(event, elements, offset) {
|
|
285
|
+
const {
|
|
286
|
+
target
|
|
287
|
+
} = event;
|
|
288
|
+
const currentIndex = elements.indexOf(target);
|
|
289
|
+
|
|
290
|
+
const nextIndex = _clamp(currentIndex + offset, 0, elements.length - 1);
|
|
291
|
+
|
|
292
|
+
this.focusItem(nextIndex, elements);
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
focusItem(index, elements) {
|
|
296
|
+
this.nextFocusedItemIndex = index;
|
|
297
|
+
this.$nextTick(() => {
|
|
298
|
+
var _elements$index;
|
|
299
|
+
|
|
300
|
+
(_elements$index = elements[index]) === null || _elements$index === void 0 ? void 0 : _elements$index.focus();
|
|
301
|
+
});
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
onSelect(_ref4, isSelected) {
|
|
305
|
+
let {
|
|
306
|
+
value
|
|
307
|
+
} = _ref4;
|
|
308
|
+
|
|
309
|
+
if (this.multiple) {
|
|
310
|
+
this.onMultiSelect(value, isSelected);
|
|
311
|
+
} else {
|
|
312
|
+
this.onSingleSelect(value, isSelected);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
isSelected(item) {
|
|
317
|
+
return this.selectedValues.some(value => value === item.value);
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
onSingleSelect(value, isSelected) {
|
|
321
|
+
if (isSelected) {
|
|
322
|
+
/**
|
|
323
|
+
* Emitted when selection is changed
|
|
324
|
+
*
|
|
325
|
+
* @event select
|
|
326
|
+
*/
|
|
327
|
+
this.$emit('select', value);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
this.$refs.baseDropdown.closeAndFocus();
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
onMultiSelect(value, isSelected) {
|
|
334
|
+
if (isSelected) {
|
|
335
|
+
this.$emit('select', [...this.selectedValues, value]);
|
|
336
|
+
} else {
|
|
337
|
+
this.$emit('select', this.selectedValues.filter(selectedValue => selectedValue !== value));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
/* script */
|
|
345
|
+
const __vue_script__ = script;
|
|
346
|
+
|
|
347
|
+
/* template */
|
|
348
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",attrs:{"aria-haspopup":"listbox","aria-labelledby":_vm.ariaLabelledby,"toggle-id":_vm.toggleId,"toggle-text":_vm.listboxToggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"right":_vm.right},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide])},[_vm._t("header"),_vm._v(" "),_c('ul',{ref:"list",staticClass:"gl-new-dropdown-contents gl-list-style-none gl-pl-0 gl-mb-0",attrs:{"aria-labelledby":_vm.toggleId,"role":"listbox","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},_vm._l((_vm.items),function(item,index){return _c('gl-listbox-item',{key:item.value,attrs:{"is-selected":_vm.isSelected(item),"is-focused":_vm.nextFocusedItemIndex === index},on:{"select":function($event){return _vm.onSelect(item, $event)}}},[_vm._t("list-item",[_vm._v("\n "+_vm._s(item.text)+"\n ")],{"item":item})],2)}),1),_vm._v(" "),_vm._t("footer")],2)};
|
|
349
|
+
var __vue_staticRenderFns__ = [];
|
|
350
|
+
|
|
351
|
+
/* style */
|
|
352
|
+
const __vue_inject_styles__ = undefined;
|
|
353
|
+
/* scoped */
|
|
354
|
+
const __vue_scope_id__ = undefined;
|
|
355
|
+
/* module identifier */
|
|
356
|
+
const __vue_module_identifier__ = undefined;
|
|
357
|
+
/* functional template */
|
|
358
|
+
const __vue_is_functional_template__ = false;
|
|
359
|
+
/* style inject */
|
|
360
|
+
|
|
361
|
+
/* style inject SSR */
|
|
362
|
+
|
|
363
|
+
/* style inject shadow dom */
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
const __vue_component__ = __vue_normalize__(
|
|
368
|
+
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
|
|
369
|
+
__vue_inject_styles__,
|
|
370
|
+
__vue_script__,
|
|
371
|
+
__vue_scope_id__,
|
|
372
|
+
__vue_is_functional_template__,
|
|
373
|
+
__vue_module_identifier__,
|
|
374
|
+
false,
|
|
375
|
+
undefined,
|
|
376
|
+
undefined,
|
|
377
|
+
undefined
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
export default __vue_component__;
|
|
381
|
+
export { ITEM_SELECTOR };
|