@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.
Files changed (46) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/components/base/alert/alert.js +1 -1
  3. package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +240 -0
  4. package/dist/components/base/new_dropdowns/constants.js +20 -0
  5. package/dist/components/base/new_dropdowns/listbox/listbox.js +381 -0
  6. package/dist/components/base/new_dropdowns/listbox/listbox_item.js +77 -0
  7. package/dist/index.css +1 -1
  8. package/dist/index.css.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/utility_classes.css +1 -1
  11. package/dist/utility_classes.css.map +1 -1
  12. package/dist/utils/utils.js +24 -1
  13. package/package.json +6 -5
  14. package/scss_to_js/scss_variables.js +1 -0
  15. package/scss_to_js/scss_variables.json +5 -0
  16. package/src/components/base/alert/alert.spec.js +3 -1
  17. package/src/components/base/alert/alert.vue +1 -1
  18. package/src/components/base/avatar_labeled/avatar_labeled.stories.js +2 -1
  19. package/src/components/base/avatar_link/avatar_link.stories.js +2 -3
  20. package/src/components/base/breadcrumb/breadcrumb.md +1 -1
  21. package/src/components/base/breadcrumb/breadcrumb.stories.js +2 -1
  22. package/src/components/base/broadcast_message/broadcast_message.scss +1 -1
  23. package/src/components/base/button/button.scss +1 -1
  24. package/src/components/base/dropdown/dropdown.scss +10 -3
  25. package/src/components/base/dropdown/dropdown_item.scss +1 -0
  26. package/src/components/base/link/link.stories.js +9 -7
  27. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +171 -0
  28. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +221 -0
  29. package/src/components/base/new_dropdowns/constants.js +22 -0
  30. package/src/components/base/new_dropdowns/listbox/listbox.md +71 -0
  31. package/src/components/base/new_dropdowns/listbox/listbox.spec.js +236 -0
  32. package/src/components/base/new_dropdowns/listbox/listbox.stories.js +276 -0
  33. package/src/components/base/new_dropdowns/listbox/listbox.vue +348 -0
  34. package/src/components/base/new_dropdowns/listbox/listbox_item.spec.js +104 -0
  35. package/src/components/base/new_dropdowns/listbox/listbox_item.vue +59 -0
  36. package/src/components/utilities/friendly_wrap/friendly_wrap.stories.js +10 -11
  37. package/src/components/utilities/sprintf/sprintf.stories.js +11 -9
  38. package/src/index.js +4 -0
  39. package/src/scss/utilities.scss +18 -0
  40. package/src/scss/utility-mixins/color.scss +4 -0
  41. package/src/scss/utility-mixins/composite.scss +20 -0
  42. package/src/scss/utility-mixins/index.scss +1 -0
  43. package/src/scss/variables.scss +1 -0
  44. package/src/utils/data_utils.js +2 -21
  45. package/src/utils/utils.js +18 -0
  46. 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('h4',{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)};
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 };