@gitlab/ui 43.11.0 → 43.14.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 (27) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/components/base/new_dropdowns/listbox/listbox.js +43 -19
  3. package/dist/components/base/new_dropdowns/listbox/listbox_group.js +54 -0
  4. package/dist/components/base/new_dropdowns/listbox/listbox_item.js +19 -1
  5. package/dist/components/base/new_dropdowns/listbox/mock_data.js +61 -0
  6. package/dist/components/base/new_dropdowns/listbox/utils.js +34 -0
  7. package/dist/utility_classes.css +1 -1
  8. package/dist/utility_classes.css.map +1 -1
  9. package/package.json +5 -5
  10. package/scss_to_js/scss_variables.js +1 -0
  11. package/scss_to_js/scss_variables.json +5 -0
  12. package/src/components/base/new_dropdowns/listbox/listbox.md +56 -13
  13. package/src/components/base/new_dropdowns/listbox/listbox.spec.js +60 -33
  14. package/src/components/base/new_dropdowns/listbox/listbox.stories.js +94 -92
  15. package/src/components/base/new_dropdowns/listbox/listbox.vue +71 -19
  16. package/src/components/base/new_dropdowns/listbox/listbox_group.spec.js +47 -0
  17. package/src/components/base/new_dropdowns/listbox/listbox_group.vue +24 -0
  18. package/src/components/base/new_dropdowns/listbox/listbox_item.spec.js +25 -0
  19. package/src/components/base/new_dropdowns/listbox/listbox_item.vue +19 -2
  20. package/src/components/base/new_dropdowns/listbox/mock_data.js +68 -0
  21. package/src/components/base/new_dropdowns/listbox/utils.js +21 -0
  22. package/src/components/base/new_dropdowns/listbox/utils.spec.js +56 -0
  23. package/src/components/base/toggle/toggle.md +0 -2
  24. package/src/scss/utilities.scss +20 -0
  25. package/src/scss/utility-mixins/flex.scss +6 -0
  26. package/src/scss/utility-mixins/sizing.scss +4 -0
  27. package/src/scss/variables.scss +1 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ # [43.14.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v43.13.0...v43.14.0) (2022-09-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * **GlListbox:** Add support for grouping ([c6ec8f1](https://gitlab.com/gitlab-org/gitlab-ui/commit/c6ec8f1a53eb4fad9a3ec077a762b23e67ef0245))
7
+
8
+ # [43.13.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v43.12.0...v43.13.0) (2022-09-06)
9
+
10
+
11
+ ### Features
12
+
13
+ * **css:** Adds align items center from sm up ([2f59188](https://gitlab.com/gitlab-org/gitlab-ui/commit/2f5918849f390ad4ee8a6a0a1040923fe4a82e00))
14
+
15
+ # [43.12.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v43.11.0...v43.12.0) (2022-09-02)
16
+
17
+
18
+ ### Features
19
+
20
+ * **css:** Add xl container util ([95755b9](https://gitlab.com/gitlab-org/gitlab-ui/commit/95755b9f3ff23dfd184a6c2c74ab23ea7d9865f6))
21
+
1
22
  # [43.11.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v43.10.0...v43.11.0) (2022-09-01)
2
23
 
3
24
 
@@ -5,9 +5,12 @@ import { GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, HOME, END, ARROW_UP, ARROW_DOWN
5
5
  import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions } from '../../../../utils/constants';
6
6
  import GlBaseDropdown from '../base_dropdown/base_dropdown';
7
7
  import GlListboxItem from './listbox_item';
8
+ import GlListboxGroup from './listbox_group';
9
+ import { itemsValidator, isOption, flattenedOptions } from './utils';
8
10
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
9
11
 
10
12
  const ITEM_SELECTOR = '[role="option"]';
13
+ const GROUP_TOP_BORDER_CLASSES = ['gl-border-t', 'gl-pt-3', 'gl-mt-3'];
11
14
  var script = {
12
15
  events: {
13
16
  GL_DROPDOWN_SHOWN,
@@ -15,7 +18,8 @@ var script = {
15
18
  },
16
19
  components: {
17
20
  GlBaseDropdown,
18
- GlListboxItem
21
+ GlListboxItem,
22
+ GlListboxGroup
19
23
  },
20
24
  model: {
21
25
  prop: 'selected',
@@ -29,14 +33,7 @@ var script = {
29
33
  type: Array,
30
34
  required: false,
31
35
  default: () => [],
32
- validator: items => {
33
- return items.every(_ref => {
34
- let {
35
- value
36
- } = _ref;
37
- return typeof value === 'string';
38
- });
39
- }
36
+ validator: itemsValidator
40
37
  },
41
38
 
42
39
  /**
@@ -159,6 +156,15 @@ var script = {
159
156
  default: false
160
157
  },
161
158
 
159
+ /**
160
+ * Center selected item checkmark
161
+ */
162
+ isCheckCentered: {
163
+ type: Boolean,
164
+ required: false,
165
+ default: false
166
+ },
167
+
162
168
  /**
163
169
  * The `aria-labelledby` attribute value for the toggle button
164
170
  */
@@ -178,17 +184,26 @@ var script = {
178
184
  },
179
185
 
180
186
  computed: {
187
+ listboxTag() {
188
+ if (this.items.length === 0 || isOption(this.items[0])) return 'ul';
189
+ return 'div';
190
+ },
191
+
192
+ flattenedOptions() {
193
+ return flattenedOptions(this.items);
194
+ },
195
+
181
196
  listboxToggleText() {
182
197
  if (!this.toggleText) {
183
198
  if (!this.multiple && this.selectedValues.length) {
184
- var _this$items$find;
199
+ var _this$flattenedOption;
185
200
 
186
- return (_this$items$find = this.items.find(_ref2 => {
201
+ return (_this$flattenedOption = this.flattenedOptions.find(_ref => {
187
202
  let {
188
203
  value
189
- } = _ref2;
204
+ } = _ref;
190
205
  return value === this.selectedValues[0];
191
- })) === null || _this$items$find === void 0 ? void 0 : _this$items$find.text;
206
+ })) === null || _this$flattenedOption === void 0 ? void 0 : _this$flattenedOption.text;
192
207
  }
193
208
 
194
209
  return '';
@@ -198,10 +213,10 @@ var script = {
198
213
  },
199
214
 
200
215
  selectedIndices() {
201
- return this.selectedValues.map(selected => this.items.findIndex(_ref3 => {
216
+ return this.selectedValues.map(selected => this.flattenedOptions.findIndex(_ref2 => {
202
217
  let {
203
218
  value
204
- } = _ref3;
219
+ } = _ref2;
205
220
  return value === selected;
206
221
  })).sort();
207
222
  }
@@ -226,6 +241,10 @@ var script = {
226
241
  }
227
242
  },
228
243
  methods: {
244
+ groupClasses(index) {
245
+ return index === 0 ? null : GROUP_TOP_BORDER_CLASSES;
246
+ },
247
+
229
248
  onShow() {
230
249
  this.$nextTick(() => {
231
250
  var _this$selectedIndices;
@@ -301,10 +320,10 @@ var script = {
301
320
  });
302
321
  },
303
322
 
304
- onSelect(_ref4, isSelected) {
323
+ onSelect(_ref3, isSelected) {
305
324
  let {
306
325
  value
307
- } = _ref4;
326
+ } = _ref3;
308
327
 
309
328
  if (this.multiple) {
310
329
  this.onMultiSelect(value, isSelected);
@@ -317,6 +336,10 @@ var script = {
317
336
  return this.selectedValues.some(value => value === item.value);
318
337
  },
319
338
 
339
+ isFocused(item) {
340
+ return this.nextFocusedItemIndex === this.flattenedOptions.indexOf(item);
341
+ },
342
+
320
343
  onSingleSelect(value, isSelected) {
321
344
  if (isSelected) {
322
345
  /**
@@ -336,8 +359,9 @@ var script = {
336
359
  } else {
337
360
  this.$emit('select', this.selectedValues.filter(selectedValue => selectedValue !== value));
338
361
  }
339
- }
362
+ },
340
363
 
364
+ isOption
341
365
  }
342
366
  };
343
367
 
@@ -345,7 +369,7 @@ var script = {
345
369
  const __vue_script__ = script;
346
370
 
347
371
  /* 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",function(){return [_vm._v("\n "+_vm._s(item.text)+"\n ")]},{"item":item})],2)}),1),_vm._v(" "),_vm._t("footer")],2)};
372
+ 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(_vm.listboxTag,{ref:"list",tag:"component",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 [(_vm.isOption(item))?[_c('gl-listbox-item',{key:item.value,attrs:{"is-selected":_vm.isSelected(item),"is-focused":_vm.isFocused(item),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(item, $event)}}},[_vm._t("list-item",function(){return [_vm._v("\n "+_vm._s(item.text)+"\n ")]},{"item":item})],2)]:[_c('gl-listbox-group',{key:item.text,class:_vm.groupClasses(index),attrs:{"name":item.text},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._l((item.options),function(option){return _c('gl-listbox-item',{key:option.value,attrs:{"is-selected":_vm.isSelected(option),"is-focused":_vm.isFocused(option),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(option, $event)}}},[_vm._t("list-item",function(){return [_vm._v("\n "+_vm._s(option.text)+"\n ")]},{"item":option})],2)})],2)]]})],2),_vm._v(" "),_vm._t("footer")],2)};
349
373
  var __vue_staticRenderFns__ = [];
350
374
 
351
375
  /* style */
@@ -0,0 +1,54 @@
1
+ import _uniqueId from 'lodash/uniqueId';
2
+ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
3
+
4
+ var script = {
5
+ props: {
6
+ name: {
7
+ type: String,
8
+ required: true
9
+ }
10
+ },
11
+
12
+ created() {
13
+ this.nameId = _uniqueId('gl-listbox-group-');
14
+ }
15
+
16
+ };
17
+
18
+ /* script */
19
+ const __vue_script__ = script;
20
+
21
+ /* template */
22
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',{staticClass:"gl-mb-0 gl-pl-0 gl-list-style-none",attrs:{"role":"group","aria-labelledby":_vm.nameId}},[_c('li',{staticClass:"gl-pl-5! gl-py-2! gl-font-base gl-font-weight-bold",attrs:{"id":_vm.nameId,"role":"presentation"}},[_vm._t("group-label",function(){return [_vm._v(_vm._s(_vm.name))]})],2),_vm._v(" "),_vm._t("default")],2)};
23
+ var __vue_staticRenderFns__ = [];
24
+
25
+ /* style */
26
+ const __vue_inject_styles__ = undefined;
27
+ /* scoped */
28
+ const __vue_scope_id__ = undefined;
29
+ /* module identifier */
30
+ const __vue_module_identifier__ = undefined;
31
+ /* functional template */
32
+ const __vue_is_functional_template__ = false;
33
+ /* style inject */
34
+
35
+ /* style inject SSR */
36
+
37
+ /* style inject shadow dom */
38
+
39
+
40
+
41
+ const __vue_component__ = __vue_normalize__(
42
+ { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
43
+ __vue_inject_styles__,
44
+ __vue_script__,
45
+ __vue_scope_id__,
46
+ __vue_is_functional_template__,
47
+ __vue_module_identifier__,
48
+ false,
49
+ undefined,
50
+ undefined,
51
+ undefined
52
+ );
53
+
54
+ export default __vue_component__;
@@ -17,8 +17,23 @@ var script = {
17
17
  type: Boolean,
18
18
  default: false,
19
19
  required: false
20
+ },
21
+ isCheckCentered: {
22
+ type: Boolean,
23
+ required: false,
24
+ default: false
20
25
  }
21
26
  },
27
+ computed: {
28
+ checkedClasses() {
29
+ if (this.isCheckCentered) {
30
+ return '';
31
+ }
32
+
33
+ return 'gl-mt-3 gl-align-self-start';
34
+ }
35
+
36
+ },
22
37
  methods: {
23
38
  toggleSelection() {
24
39
  this.$emit('select', !this.isSelected);
@@ -42,7 +57,10 @@ var script = {
42
57
  const __vue_script__ = script;
43
58
 
44
59
  /* template */
45
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{staticClass:"gl-new-dropdown-item",attrs:{"role":"option","tabindex":_vm.isFocused ? 0 : -1,"aria-selected":_vm.isSelected},on:{"click":_vm.toggleSelection,"keydown":_vm.onKeydown}},[_c('span',{staticClass:"dropdown-item"},[_c('gl-icon',{staticClass:"gl-mt-3 gl-align-self-start",class:['gl-new-dropdown-item-check-icon', { 'gl-visibility-hidden': !_vm.isSelected }],attrs:{"name":"mobile-issue-close","data-testid":"dropdown-item-checkbox"}}),_vm._v(" "),_c('span',{staticClass:"gl-new-dropdown-item-text-wrapper"},[_vm._t("default")],2)],1)])};
60
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{staticClass:"gl-new-dropdown-item",attrs:{"role":"option","tabindex":_vm.isFocused ? 0 : -1,"aria-selected":_vm.isSelected},on:{"click":_vm.toggleSelection,"keydown":_vm.onKeydown}},[_c('span',{staticClass:"dropdown-item"},[_c('gl-icon',{class:[
61
+ 'gl-new-dropdown-item-check-icon',
62
+ { 'gl-visibility-hidden': !_vm.isSelected },
63
+ _vm.checkedClasses ],attrs:{"name":"mobile-issue-close","data-testid":"dropdown-item-checkbox"}}),_vm._v(" "),_c('span',{staticClass:"gl-new-dropdown-item-text-wrapper"},[_vm._t("default")],2)],1)])};
46
64
  var __vue_staticRenderFns__ = [];
47
65
 
48
66
  /* style */
@@ -0,0 +1,61 @@
1
+ const mockOptions = [{
2
+ value: 'prod',
3
+ text: 'Product'
4
+ }, {
5
+ value: 'ppl',
6
+ text: 'People'
7
+ }, {
8
+ value: 'fin',
9
+ text: 'Finance'
10
+ }, {
11
+ value: 'leg',
12
+ text: 'Legal'
13
+ }, {
14
+ value: 'eng',
15
+ text: 'Engineering'
16
+ }, {
17
+ value: 'sales',
18
+ text: 'Sales'
19
+ }, {
20
+ value: 'marketing',
21
+ text: 'Marketing'
22
+ }, {
23
+ value: 'acc',
24
+ text: 'Accounting'
25
+ }, {
26
+ value: 'hr',
27
+ text: 'Human Resource Management'
28
+ }, {
29
+ value: 'rnd',
30
+ text: 'Research and Development'
31
+ }, {
32
+ value: 'cust',
33
+ text: 'Customer Service'
34
+ }, {
35
+ value: 'sup',
36
+ text: 'Support'
37
+ }];
38
+ const mockGroups = [{
39
+ text: 'Branches',
40
+ options: [{
41
+ text: 'main',
42
+ value: 'main'
43
+ }, {
44
+ text: 'feature-123',
45
+ value: 'feature-123'
46
+ }]
47
+ }, {
48
+ text: 'Tags',
49
+ options: [{
50
+ text: 'v1.0',
51
+ value: 'v1.0'
52
+ }, {
53
+ text: 'v2.0',
54
+ value: 'v2.0'
55
+ }, {
56
+ text: 'v2.1',
57
+ value: 'v2.1'
58
+ }]
59
+ }];
60
+
61
+ export { mockGroups, mockOptions };
@@ -0,0 +1,34 @@
1
+ import _isString from 'lodash/isString';
2
+
3
+ const isOption = item => Boolean(item) && _isString(item.value);
4
+
5
+ const isGroup = function () {
6
+ let {
7
+ options
8
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
9
+ return Array.isArray(options) && options.every(isOption);
10
+ };
11
+
12
+ const hasNoDuplicates = array => array.length === new Set(array).size;
13
+
14
+ const flattenedOptions = items => items.flatMap(item => isOption(item) ? item : item.options);
15
+
16
+ const isAllOptionsOrAllGroups = items => items.every(isOption) || items.every(isGroup);
17
+
18
+ const hasUniqueValues = items => hasNoDuplicates(flattenedOptions(items).map(_ref => {
19
+ let {
20
+ value
21
+ } = _ref;
22
+ return value;
23
+ }));
24
+
25
+ const hasUniqueGroups = items => hasNoDuplicates(items.filter(isGroup).map(_ref2 => {
26
+ let {
27
+ text
28
+ } = _ref2;
29
+ return text;
30
+ }));
31
+
32
+ const itemsValidator = items => isAllOptionsOrAllGroups(items) && hasUniqueValues(items) && hasUniqueGroups(items);
33
+
34
+ export { flattenedOptions, isOption, itemsValidator };