@gitlab/ui 128.11.0 → 128.13.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.
@@ -35,7 +35,7 @@ var script = {
35
35
  default: ''
36
36
  },
37
37
  /**
38
- * Layout of label and text: 'horizontal' for inline/flex or 'vertical' for block.
38
+ * Layout of label and text: 'horizontal' for line or 'vertical' for stacked
39
39
  */
40
40
  layout: {
41
41
  type: String,
@@ -1,5 +1,6 @@
1
1
  import isString from 'lodash/isString';
2
2
  import isPlainObject from 'lodash/isPlainObject';
3
+ import { uniqueId } from 'lodash';
3
4
  import { BFormGroup } from '../../../../vendor/bootstrap-vue/src/components/form-group/form-group';
4
5
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
5
6
 
@@ -8,8 +9,11 @@ var script = {
8
9
  components: {
9
10
  BFormGroup
10
11
  },
11
- provide: {
12
- isInFormGroup: true
12
+ provide() {
13
+ return {
14
+ // Only for internal use by @gitlab/ui components
15
+ getFormGroupInstance: () => this
16
+ };
13
17
  },
14
18
  inheritAttrs: false,
15
19
  props: {
@@ -46,6 +50,11 @@ var script = {
46
50
  default: '(optional)'
47
51
  }
48
52
  },
53
+ data() {
54
+ return {
55
+ labelId: uniqueId('gl-form-group-label-')
56
+ };
57
+ },
49
58
  computed: {
50
59
  actualLabelClass() {
51
60
  const {
@@ -77,7 +86,7 @@ var script = {
77
86
  const __vue_script__ = script;
78
87
 
79
88
  /* template */
80
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-form-group',_vm._b({staticClass:"gl-form-group",attrs:{"label-class":_vm.actualLabelClass},scopedSlots:_vm._u([(_vm.$attrs.label || _vm.$scopedSlots.label)?{key:"label",fn:function(){return [_vm._t("label",function(){return [_vm._v("\n "+_vm._s(_vm.$attrs.label)+"\n "),(_vm.optional)?_c('span',{staticClass:"optional-label",attrs:{"data-testid":"optional-label"}},[_vm._v(_vm._s(_vm.optionalText))]):_vm._e()]}),_vm._v(" "),(_vm.hasLabelDescription)?_c('div',{staticClass:"label-description",attrs:{"data-testid":"label-description"}},[_vm._t("label-description",function(){return [_vm._v(_vm._s(_vm.labelDescription))]})],2):_vm._e()]},proxy:true}:null,_vm._l((Object.keys(_vm.$slots)),function(slot){return {key:slot,fn:function(){return [_vm._t(slot)]},proxy:true}})],null,true)},'b-form-group',_vm.$attrs,false))};
89
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-form-group',_vm._b({staticClass:"gl-form-group",attrs:{"label-class":_vm.actualLabelClass,"label-id":_vm.labelId},scopedSlots:_vm._u([(_vm.$attrs.label || _vm.$scopedSlots.label)?{key:"label",fn:function(){return [_vm._t("label",function(){return [_vm._v("\n "+_vm._s(_vm.$attrs.label)+"\n "),(_vm.optional)?_c('span',{staticClass:"optional-label",attrs:{"data-testid":"optional-label"}},[_vm._v(_vm._s(_vm.optionalText))]):_vm._e()]}),_vm._v(" "),(_vm.hasLabelDescription)?_c('div',{staticClass:"label-description",attrs:{"data-testid":"label-description"}},[_vm._t("label-description",function(){return [_vm._v(_vm._s(_vm.labelDescription))]})],2):_vm._e()]},proxy:true}:null,_vm._l((Object.keys(_vm.$slots)),function(slot){return {key:slot,fn:function(){return [_vm._t(slot)]},proxy:true}})],null,true)},'b-form-group',_vm.$attrs,false))};
81
90
  var __vue_staticRenderFns__ = [];
82
91
 
83
92
  /* style */
@@ -1,4 +1,5 @@
1
1
  import uniqueId from 'lodash/uniqueId';
2
+ import isBoolean from 'lodash/isBoolean';
2
3
  import { offset, autoPlacement, shift, arrow, size, autoUpdate, computePosition } from '@floating-ui/dom';
3
4
  import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions, dropdownPlacements, dropdownAllowedAutoPlacements } from '../../../../utils/constants';
4
5
  import { POSITION_ABSOLUTE, POSITION_FIXED, GL_DROPDOWN_CONTENTS_CLASS, GL_DROPDOWN_BEFORE_CLOSE, GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, KEY_CODE_ESCAPE, ENTER, SPACE, ARROW_DOWN, GL_DROPDOWN_FOCUS_CONTENT } from '../constants';
@@ -25,6 +26,11 @@ var script = {
25
26
  directives: {
26
27
  Outside: OutsideDirective
27
28
  },
29
+ inject: {
30
+ getFormGroupInstance: {
31
+ default: () => () => {}
32
+ }
33
+ },
28
34
  props: {
29
35
  toggleText: {
30
36
  type: String,
@@ -84,6 +90,14 @@ var script = {
84
90
  required: false,
85
91
  default: false
86
92
  },
93
+ /**
94
+ * Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state
95
+ */
96
+ state: {
97
+ type: Boolean,
98
+ required: false,
99
+ default: null
100
+ },
87
101
  placement: {
88
102
  type: String,
89
103
  required: false,
@@ -211,6 +225,15 @@ var script = {
211
225
  isCaretOnly() {
212
226
  return !this.noCaret && !this.icon && this.hasNoVisibleToggleText;
213
227
  },
228
+ computedState() {
229
+ // If not a boolean, ensure that value is null
230
+ return isBoolean(this.state) ? this.state : null;
231
+ },
232
+ stateClass() {
233
+ if (this.computedState === true) return 'is-valid';
234
+ if (this.computedState === false) return 'is-invalid';
235
+ return null;
236
+ },
214
237
  isDefaultToggle() {
215
238
  return !this.$scopedSlots.toggle;
216
239
  },
@@ -261,21 +284,46 @@ var script = {
261
284
  'gl-new-dropdown-icon-only btn-icon': this.isIconOnly && !this.isEllipsisButton,
262
285
  'gl-new-dropdown-toggle-no-caret': this.noCaret,
263
286
  'gl-new-dropdown-caret-only btn-icon': this.isCaretOnly
264
- }];
287
+ }, this.stateClass];
265
288
  },
266
289
  toggleButtonTextClasses() {
267
290
  return this.block ? 'gl-w-full' : '';
268
291
  },
292
+ // Set the aria-labelledby property with one or more ID strings
269
293
  toggleLabelledBy() {
294
+ var _this$getFormGroupIns;
295
+ const formGroupLabelId = (_this$getFormGroupIns = this.getFormGroupInstance()) === null || _this$getFormGroupIns === void 0 ? void 0 : _this$getFormGroupIns.labelId;
270
296
  if (this.isToggleCombobox) {
297
+ // Comboboxes announce label and self value when aria-labelledby is label ID.
298
+ // Tested with VoiceOver, NVDA, JAWS, Narrator and preferred browsers.
271
299
  if (this.ariaLabelledby) {
272
- return `${this.ariaLabelledby} ${this.toggleId}`;
300
+ return `${this.ariaLabelledby}`;
273
301
  }
302
+
303
+ // Combobox inside GlFormGroup
304
+ if (formGroupLabelId) {
305
+ return `${formGroupLabelId} ${this.toggleId}`;
306
+ }
307
+
308
+ // Fallback calculated toggleId value
274
309
  return this.toggleId;
275
310
  }
311
+ if (!this.isToggleCombobox) {
312
+ // Disclosures or buttons with listbox require both IDs to announce correctly.
313
+ // Tested with VoiceOver, NVDA, JAWS, Narrator and preferred browsers.
314
+ if (this.ariaLabelledby) {
315
+ return `${this.ariaLabelledby} ${this.toggleId}`;
316
+ }
276
317
 
277
- // For non-combobox toggles, combine IDs or use the button's own text
278
- return this.ariaLabelledby ? `${this.ariaLabelledby} ${this.toggleId}` : undefined;
318
+ // Disclosure or button with listbox inside GlFormGroup
319
+ if (formGroupLabelId) {
320
+ return `${formGroupLabelId} ${this.toggleId}`;
321
+ }
322
+
323
+ // Fallback calculated toggleId value
324
+ return this.toggleId;
325
+ }
326
+ return undefined;
279
327
  },
280
328
  toggleRole() {
281
329
  if (this.isToggleCombobox) {
@@ -515,7 +563,7 @@ var script = {
515
563
  this.$emit(GL_DROPDOWN_SHOWN);
516
564
  } else {
517
565
  this.stopFloating();
518
- this.$emit(GL_DROPDOWN_HIDDEN);
566
+ this.$emit(GL_DROPDOWN_HIDDEN, event);
519
567
  }
520
568
 
521
569
  // this is to check whether `toggle` was prevented or not
@@ -39,8 +39,8 @@ var script = {
39
39
  GlIntersectionObserver
40
40
  },
41
41
  inject: {
42
- isInFormGroup: {
43
- default: false
42
+ getFormGroupInstance: {
43
+ default: () => () => {}
44
44
  }
45
45
  },
46
46
  model: {
@@ -138,6 +138,14 @@ var script = {
138
138
  required: false,
139
139
  default: false
140
140
  },
141
+ /**
142
+ * Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state
143
+ */
144
+ state: {
145
+ type: Boolean,
146
+ required: false,
147
+ default: null
148
+ },
141
149
  /**
142
150
  * Set to "true" when dropdown content (items) is loading
143
151
  * It will render a small loader in the dropdown toggle and make it disabled
@@ -385,6 +393,9 @@ var script = {
385
393
  // Fallback. Return a header ID or the toggle button ID.
386
394
  return this.listAriaLabelledBy || this.headerId || this.toggleIdComputed;
387
395
  },
396
+ isInFormGroup() {
397
+ return Boolean(this.getFormGroupInstance());
398
+ },
388
399
  toggleIdComputed() {
389
400
  return this.toggleId || uniqueId('dropdown-toggle-btn-');
390
401
  },
@@ -645,7 +656,7 @@ var script = {
645
656
  */
646
657
  this.$emit(GL_DROPDOWN_SHOWN);
647
658
  },
648
- onHide() {
659
+ onHide(event) {
649
660
  /**
650
661
  * Emitted when dropdown is hidden
651
662
  *
@@ -653,6 +664,8 @@ var script = {
653
664
  */
654
665
  this.$emit(GL_DROPDOWN_HIDDEN);
655
666
  this.nextFocusedItemIndex = null;
667
+ // Emit native blur event for form validation in FormGroup
668
+ this.$emit('blur', event);
656
669
  },
657
670
  getNextIndex(currentIndex, keyCode, totalLength) {
658
671
  // For UP: move up or wrap to end
@@ -919,7 +932,7 @@ var script = {
919
932
  const __vue_script__ = script;
920
933
 
921
934
  /* template */
922
- 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","active-item-id":_vm.activeItemId,"aria-labelledby":_vm.toggleAriaLabelledBy,"block":_vm.block,"has-searchable-listbox":_vm.searchable,"has-external-label":_vm.isInFormGroup,"listbox-id":_vm.listboxIdComputed,"toggle-id":_vm.toggleIdComputed,"toggle-text":_vm.listboxToggleText,"toggle-class":_vm.toggleButtonClasses,"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,"placement":_vm.placement,"offset":_vm.dropdownOffset,"fluid-width":_vm.fluidWidth,"panel-match-trigger-width":_vm.panelMatchTriggerWidth,"positioning-strategy":_vm.positioningStrategy},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_FOCUS_CONTENT,_vm.onFocusContent,_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(slotProps){return [_vm._t("toggle",null,null,slotProps)]}}:null,{key:"default",fn:function(ref){
935
+ 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","active-item-id":_vm.activeItemId,"aria-labelledby":_vm.toggleAriaLabelledBy,"block":_vm.block,"has-searchable-listbox":_vm.searchable,"has-external-label":_vm.isInFormGroup,"listbox-id":_vm.listboxIdComputed,"state":_vm.state,"toggle-id":_vm.toggleIdComputed,"toggle-text":_vm.listboxToggleText,"toggle-class":_vm.toggleButtonClasses,"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,"placement":_vm.placement,"offset":_vm.dropdownOffset,"fluid-width":_vm.fluidWidth,"panel-match-trigger-width":_vm.panelMatchTriggerWidth,"positioning-strategy":_vm.positioningStrategy},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_FOCUS_CONTENT,_vm.onFocusContent,_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(slotProps){return [_vm._t("toggle",null,null,slotProps)]}}:null,{key:"default",fn:function(ref){
923
936
  var visible = ref.visible;
924
937
  return [(_vm.headerText)?_c('div',{staticClass:"gl-flex gl-min-h-8 gl-items-center !gl-p-4",class:_vm.$options.HEADER_ITEMS_BORDER_CLASSES},[_c('div',{staticClass:"gl-grow gl-pr-2 gl-text-sm gl-font-bold gl-text-strong",attrs:{"id":_vm.headerId,"data-testid":"listbox-header-text"}},[_vm._v("\n "+_vm._s(_vm.headerText)+"\n ")]),_vm._v(" "),(_vm.showResetButton)?_c('gl-button',{staticClass:"!gl-m-0 !gl-w-auto gl-max-w-1/2 gl-flex-shrink-0 gl-text-ellipsis !gl-px-2 !gl-text-sm focus:!gl-focus-inset",attrs:{"category":"tertiary","size":"small","data-testid":"listbox-reset-button"},on:{"click":_vm.onResetButtonClicked}},[_vm._v("\n "+_vm._s(_vm.resetButtonLabel)+"\n ")]):_vm._e(),_vm._v(" "),(_vm.showSelectAllButton)?_c('gl-button',{staticClass:"!gl-m-0 !gl-w-auto gl-max-w-1/2 gl-flex-shrink-0 gl-text-ellipsis !gl-px-2 !gl-text-sm focus:!gl-focus-inset",attrs:{"category":"tertiary","size":"small","data-testid":"listbox-select-all-button"},on:{"click":_vm.onSelectAllButtonClicked}},[_vm._v("\n "+_vm._s(_vm.showSelectAllButtonLabel)+"\n ")]):_vm._e()],1):_vm._e(),_vm._v(" "),(_vm.searchable)?_c('div',{class:_vm.$options.HEADER_ITEMS_BORDER_CLASSES},[_c('gl-listbox-search-input',{ref:"searchBox",class:{ 'gl-listbox-topmost': !_vm.headerText },attrs:{"id":_vm.searchInputId,"data-testid":"listbox-search-input","role":"combobox","aria-expanded":String(visible),"aria-controls":_vm.listboxId,"aria-activedescendant":_vm.activeItemId,"aria-haspopup":"listbox","placeholder":_vm.searchPlaceholder},on:{"input":_vm.search,"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }$event.preventDefault();},_vm.onKeydown]},model:{value:(_vm.searchStr),callback:function ($$v) {_vm.searchStr=$$v;},expression:"searchStr"}}),_vm._v(" "),(_vm.searching)?_c('gl-loading-icon',{staticClass:"gl-my-3",attrs:{"data-testid":"listbox-search-loader","size":"md"}}):_vm._e()],1):_vm._e(),_vm._v(" "),(_vm.showList)?_c(_vm.listboxTag,{ref:"list",tag:"component",staticClass:"gl-new-dropdown-contents gl-new-dropdown-contents-with-scrim-overlay",class:_vm.listboxClasses,attrs:{"id":_vm.listboxId,"aria-busy":_vm.isBusy,"aria-labelledby":_vm.listboxAriaLabelledByID,"aria-multiselectable":_vm.multiple ? 'true' : undefined,"role":"listbox","tabindex":"0"},on:{"keydown":_vm.onKeydown}},[_c(_vm.itemTag,{tag:"component",staticClass:"top-scrim-wrapper",attrs:{"aria-hidden":"true","data-testid":"top-scrim"}},[_c('div',{staticClass:"top-scrim",class:{ 'top-scrim-light': !_vm.hasHeader, 'top-scrim-dark': _vm.hasHeader }})]),_vm._v(" "),_c(_vm.itemTag,{ref:"top-boundary",tag:"component",attrs:{"aria-hidden":"true"}}),_vm._v(" "),_vm._l((_vm.items),function(item,index){return [(_vm.isOption(item))?[_c('gl-listbox-item',_vm._b({key:_vm.listboxItemKey(item),attrs:{"id":_vm.generateItemId(item),"data-testid":("listbox-item-" + (item.value)),"is-highlighted":_vm.isHighlighted(item),"is-selected":_vm.isSelected(item),"is-focused":_vm.isFocused(item),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(item, $event)}}},'gl-listbox-item',_vm.listboxItemMoreItemsAriaAttributes(index),false),[_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,"text-sr-only":item.textSrOnly},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:_vm.listboxItemKey(option),attrs:{"id":_vm.generateItemId(option),"data-testid":("listbox-item-" + (option.value)),"is-highlighted":_vm.isHighlighted(option),"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)]]}),_vm._v(" "),(_vm.infiniteScrollLoading)?_c(_vm.itemTag,{tag:"component"},[_c('gl-loading-icon',{staticClass:"gl-my-3",attrs:{"data-testid":"listbox-infinite-scroll-loader","size":"md"}})],1):_vm._e(),_vm._v(" "),(_vm.showIntersectionObserver)?_c('gl-intersection-observer',{on:{"appear":_vm.onIntersectionObserverAppear}}):_vm._e(),_vm._v(" "),_c(_vm.itemTag,{ref:"bottom-boundary",tag:"component",attrs:{"aria-hidden":"true"}}),_vm._v(" "),_c(_vm.itemTag,{tag:"component",staticClass:"bottom-scrim-wrapper",attrs:{"aria-hidden":"true","data-testid":"bottom-scrim"}},[_c('div',{staticClass:"bottom-scrim",class:{ '!gl-rounded-none': _vm.hasFooter }})])],2):_vm._e(),_vm._v(" "),(_vm.announceSRSearchResults)?_c('span',{staticClass:"gl-sr-only",attrs:{"data-testid":"listbox-number-of-results","aria-live":"assertive"}},[_vm._t("search-summary-sr-only",function(){return [_vm._v("\n "+_vm._s(_vm.srOnlyResultsLabel(_vm.flattenedOptions.length))+"\n ")]})],2):_vm._e(),_vm._v(" "),(_vm.isBusy)?_c('span',{staticClass:"gl-sr-only",attrs:{"aria-live":"polite","data-testid":"listbox-loading-announcement"}},[_vm._v("\n "+_vm._s(_vm.loadingAnnouncementText)+"\n ")]):(_vm.showNoResultsText)?_c('div',{staticClass:"gl-py-3 gl-pl-7 gl-pr-5 gl-text-base gl-text-subtle",attrs:{"aria-live":"assertive","data-testid":"listbox-no-results-text"}},[_vm._v("\n "+_vm._s(_vm.noResultsText)+"\n ")]):_vm._e(),_vm._v(" "),_vm._t("footer")]}}],null,true)})};
925
938
  var __vue_staticRenderFns__ = [];