@gitlab/ui 128.2.0 → 128.2.2

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.
@@ -1,6 +1,5 @@
1
1
  import Vue from 'vue';
2
2
  import isFunction from 'lodash/isFunction';
3
- import isString from 'lodash/isString';
4
3
  import { DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME } from './constants';
5
4
 
6
5
  const itemValidator = item => {
@@ -16,28 +15,58 @@ group.items.every(isItem);
16
15
  const itemsValidator = items => items.every(isItem) || items.every(isGroup);
17
16
  const isListItem = tag => ['gl-disclosure-dropdown-group', 'gl-disclosure-dropdown-item', 'li'].includes(tag);
18
17
  const isValidSlotTagVue2 = vNode => {
19
- var _vNode$componentOptio;
20
- return Boolean(vNode) && isListItem(((_vNode$componentOptio = vNode.componentOptions) === null || _vNode$componentOptio === void 0 ? void 0 : _vNode$componentOptio.tag) || vNode.tag);
18
+ var _vNode$componentOptio, _vNode$componentOptio2, _vNode$componentOptio3, _vNode$componentOptio4;
19
+ if (!vNode) return false;
20
+ const tag = ((_vNode$componentOptio = vNode.componentOptions) === null || _vNode$componentOptio === void 0 ? void 0 : _vNode$componentOptio.tag) || vNode.tag;
21
+ if (isListItem(tag)) return true;
22
+ const componentName = (_vNode$componentOptio2 = vNode.componentOptions) === null || _vNode$componentOptio2 === void 0 ? void 0 : (_vNode$componentOptio3 = _vNode$componentOptio2.Ctor) === null || _vNode$componentOptio3 === void 0 ? void 0 : (_vNode$componentOptio4 = _vNode$componentOptio3.options) === null || _vNode$componentOptio4 === void 0 ? void 0 : _vNode$componentOptio4.name;
23
+ return [DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME].includes(componentName);
21
24
  };
22
25
  const isValidSlotTagVue3 = vNode => {
23
26
  var _vNode$type;
27
+ if (!vNode) return false;
24
28
  return [DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME].includes((_vNode$type = vNode.type) === null || _vNode$type === void 0 ? void 0 : _vNode$type.name) || vNode.type === 'li';
25
29
  };
30
+ const isSkippableVue2 = vNode => {
31
+ if (!vNode) return true;
32
+ if (vNode.isComment) return true;
33
+ if (!vNode.tag && typeof vNode.text === 'string' && !vNode.text.trim()) return true;
34
+ return false;
35
+ };
26
36
  const hasOnlyListItemsVue2 = defaultSlot => {
27
37
  const nodes = defaultSlot();
28
38
  if (!Array.isArray(nodes)) {
29
39
  return false;
30
40
  }
31
- const tags = nodes.filter(vNode => vNode.tag);
32
- return tags.length && tags.every(tag => isValidSlotTagVue2(tag));
41
+ const candidateNodes = nodes.filter(vNode => !isSkippableVue2(vNode));
42
+ if (candidateNodes.length === 0) return true;
43
+ return candidateNodes.every(vNode => isValidSlotTagVue2(vNode));
44
+ };
45
+ const isSkippableVue3 = vNode => {
46
+ var _vNode$children;
47
+ if (!vNode) return true;
48
+ if (vNode.type === Vue.Comment) return true;
49
+ if (vNode.type === Vue.Text && !((_vNode$children = vNode.children) !== null && _vNode$children !== void 0 && _vNode$children.trim())) return true;
50
+ if (vNode.type === Vue.Fragment && (!vNode.children || vNode.children.length === 0)) return true;
51
+ return false;
52
+ };
53
+ const validateNodesRecursiveVue3 = nodes => {
54
+ if (!Array.isArray(nodes) || nodes.length === 0) return true;
55
+ const candidateNodes = nodes.filter(vNode => !isSkippableVue3(vNode));
56
+ if (candidateNodes.length === 0) return true;
57
+ return candidateNodes.every(vNode => {
58
+ if (isValidSlotTagVue3(vNode)) return true;
59
+ if (vNode.type === Vue.Fragment && Array.isArray(vNode.children)) {
60
+ return validateNodesRecursiveVue3(vNode.children);
61
+ }
62
+ return false;
63
+ });
33
64
  };
34
65
  const hasOnlyListItemsVue3 = defaultSlot => {
35
66
  const nodes = defaultSlot();
36
67
  const fragment = nodes.find(node => Array.isArray(node.children) && node.children.length);
37
68
  const targetNodes = fragment ? fragment.children : nodes;
38
- return targetNodes
39
- // Remove empty text vNodes
40
- .filter(vNode => !isString(vNode.text) || vNode.text.trim().length > 0).every(vNode => isValidSlotTagVue3(vNode));
69
+ return validateNodesRecursiveVue3(targetNodes);
41
70
  };
42
71
  const hasOnlyListItems = defaultSlot => {
43
72
  if (!isFunction(defaultSlot)) {
@@ -198,9 +198,9 @@ var script = {
198
198
  const __vue_script__ = script;
199
199
 
200
200
  /* template */
201
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-border gl-h-full !gl-overflow-visible gl-rounded-lg gl-bg-default gl-p-5",class:_vm.containerClasses,attrs:{"id":_vm.panelId}},[_c('div',{staticClass:"gl-flex gl-h-full gl-flex-col"},[_c('div',{staticClass:"gl-mb-3 gl-flex gl-items-start gl-justify-between",attrs:{"data-testid":"panel-title"}},[_c('div',{staticClass:"gl-flex gl-items-center gl-overflow-hidden"},[(_vm.hasTitleIcon)?_c('gl-icon',{staticClass:"gl-mr-2",class:_vm.titleIconClass,attrs:{"name":_vm.titleIcon,"data-testid":"panel-title-icon"}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-min-w-0"},[(_vm.hasTitle)?_c('gl-truncate',{staticClass:"gl-font-bold gl-text-default",attrs:{"text":_vm.title,"with-tooltip":""}}):_vm._e(),_vm._v(" "),(_vm.subtitle)?_c('p',{staticClass:"gl-mb-0 gl-mt-1 gl-text-sm gl-text-subtle",attrs:{"data-testid":"panel-subtitle"}},[_vm._v("\n "+_vm._s(_vm.subtitle)+"\n ")]):_vm._e()],1),_vm._v(" "),(_vm.hasTitlePopover)?[_c('gl-icon',{staticClass:"gl-ml-2 gl-min-w-5",attrs:{"id":_vm.titlePopoverId,"data-testid":"panel-title-popover-icon","name":"information-o","variant":"info"}}),_vm._v(" "),_c('gl-popover',{attrs:{"data-testid":"panel-title-popover","boundary":"viewport","target":_vm.titlePopoverId,"css-classes":_vm.titlePopoverClasses},scopedSlots:_vm._u([(_vm.hasInfoPopoverTitleSlot)?{key:"title",fn:function(){return [_vm._t("info-popover-title")]},proxy:true}:null],null,true)},[_vm._v(" "),(_vm.hasInfoPopoverContentSlot)?[_vm._t("info-popover-content")]:_vm._e(),_vm._v(" "),(!_vm.hasInfoPopoverContentSlot)?[(_vm.hasTitlePopoverLink)?_c('gl-sprintf',{attrs:{"message":_vm.titlePopover.description},scopedSlots:_vm._u([{key:"link",fn:function(ref){
201
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-border gl-h-full !gl-overflow-visible gl-rounded-lg gl-bg-default gl-p-5",class:_vm.containerClasses,attrs:{"id":_vm.panelId}},[_c('div',{staticClass:"gl-flex gl-h-full gl-flex-col"},[_c('div',{staticClass:"gl-mb-3 gl-flex gl-items-start gl-justify-between",attrs:{"data-testid":"panel-title"}},[_c('div',{staticClass:"gl-flex gl-items-center gl-gap-2 gl-overflow-hidden"},[(_vm.hasTitleIcon)?_c('gl-icon',{class:_vm.titleIconClass,attrs:{"name":_vm.titleIcon,"data-testid":"panel-title-icon"}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-min-w-0"},[_c('div',{staticClass:"gl-flex gl-items-center gl-gap-2"},[(_vm.hasTitle)?_c('gl-truncate',{staticClass:"gl-min-w-0 gl-font-bold gl-text-default",attrs:{"text":_vm.title,"with-tooltip":""}}):_vm._e(),_vm._v(" "),(_vm.hasTitlePopover)?[_c('gl-icon',{staticClass:"gl-min-w-5",attrs:{"id":_vm.titlePopoverId,"data-testid":"panel-title-popover-icon","name":"information-o","variant":"info"}}),_vm._v(" "),_c('gl-popover',{attrs:{"data-testid":"panel-title-popover","boundary":"viewport","target":_vm.titlePopoverId,"css-classes":_vm.titlePopoverClasses},scopedSlots:_vm._u([(_vm.hasInfoPopoverTitleSlot)?{key:"title",fn:function(){return [_vm._t("info-popover-title")]},proxy:true}:null],null,true)},[_vm._v(" "),(_vm.hasInfoPopoverContentSlot)?[_vm._t("info-popover-content")]:_vm._e(),_vm._v(" "),(!_vm.hasInfoPopoverContentSlot)?[(_vm.hasTitlePopoverLink)?_c('gl-sprintf',{attrs:{"message":_vm.titlePopover.description},scopedSlots:_vm._u([{key:"link",fn:function(ref){
202
202
  var content = ref.content;
203
- return [_c('gl-link',{staticClass:"gl-text-sm",attrs:{"href":_vm.titlePopover.descriptionLink}},[_vm._v(_vm._s(content))])]}}],null,false,3051540671)}):[_vm._v(" "+_vm._s(_vm.titlePopover.description)+" ")]]:_vm._e()],2)]:_vm._e()],2),_vm._v(" "),(_vm.shouldShowActions || _vm.$scopedSlots.filters)?_c('div',{staticClass:"gl-flex gl-flex-col gl-items-end gl-gap-2",attrs:{"data-testid":"panel-actions-filters-container"}},[(_vm.shouldShowActions)?_c('gl-disclosure-dropdown',{attrs:{"items":_vm.actions,"icon":"ellipsis_v","toggle-text":_vm.actionsToggleText,"text-sr-only":"","no-caret":"","placement":"bottom-end","fluid-width":"","toggle-class":"gl-ml-1","category":"tertiary","positioning-strategy":"fixed","size":"small"},on:{"shown":function($event){return _vm.$emit('dropdownOpen')},"hidden":function($event){return _vm.$emit('dropdownClosed')}},scopedSlots:_vm._u([{key:"list-item",fn:function(ref){
203
+ return [_c('gl-link',{staticClass:"gl-text-sm",attrs:{"href":_vm.titlePopover.descriptionLink}},[_vm._v(_vm._s(content))])]}}],null,false,3051540671)}):[_vm._v(" "+_vm._s(_vm.titlePopover.description)+" ")]]:_vm._e()],2)]:_vm._e()],2),_vm._v(" "),(_vm.subtitle)?_c('p',{staticClass:"gl-mb-0 gl-mt-1 gl-text-sm gl-text-subtle",attrs:{"data-testid":"panel-subtitle"}},[_vm._v("\n "+_vm._s(_vm.subtitle)+"\n ")]):_vm._e()])],1),_vm._v(" "),(_vm.shouldShowActions || _vm.$scopedSlots.filters)?_c('div',{staticClass:"gl-flex gl-flex-col gl-items-end gl-gap-2",attrs:{"data-testid":"panel-actions-filters-container"}},[(_vm.shouldShowActions)?_c('gl-disclosure-dropdown',{attrs:{"items":_vm.actions,"icon":"ellipsis_v","toggle-text":_vm.actionsToggleText,"text-sr-only":"","no-caret":"","placement":"bottom-end","fluid-width":"","toggle-class":"gl-ml-1","category":"tertiary","positioning-strategy":"fixed","size":"small"},on:{"shown":function($event){return _vm.$emit('dropdownOpen')},"hidden":function($event){return _vm.$emit('dropdownClosed')}},scopedSlots:_vm._u([{key:"list-item",fn:function(ref){
204
204
  var item = ref.item;
205
205
  return [_c('span',[_vm._v(_vm._s(item.text))])]}}],null,false,3418607560)}):_vm._e(),_vm._v(" "),(_vm.$scopedSlots.filters)?_c('div',{staticClass:"gl-flex gl-items-center gl-justify-end",attrs:{"data-testid":"panel-filters-container"}},[_vm._t("filters")],2):_vm._e()],1):_vm._e()]),_vm._v(" "),_c('div',{class:_vm.bodyClasses},[(_vm.loading)?[_c('gl-loading-icon',{staticClass:"gl-min-h-8 gl-w-full",attrs:{"size":"lg"}}),_vm._v(" "),(_vm.isLoadingDelayed)?_c('div',{staticClass:"gl-w-full gl-text-subtle",attrs:{"data-testId":"panel-loading-delayed-indicator"}},[_vm._v("\n "+_vm._s(_vm.loadingDelayedText)+"\n ")]):_vm._e()]:_vm._t("body")],2),_vm._v(" "),_vm._t("alert-message",null,{"panelId":_vm.panelId})],2)])};
206
206
  var __vue_staticRenderFns__ = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "128.2.0",
3
+ "version": "128.2.2",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -131,7 +131,7 @@
131
131
  "autoprefixer": "10.4.23",
132
132
  "axe-playwright": "^2.2.2",
133
133
  "babel-loader": "^9.2.1",
134
- "cypress": "15.8.2",
134
+ "cypress": "15.9.0",
135
135
  "cypress-real-events": "^1.15.0",
136
136
  "dompurify": "^3.1.2",
137
137
  "emoji-regex": "^10.6.0",
@@ -165,7 +165,7 @@
165
165
  "start-server-and-test": "^2.1.3",
166
166
  "storybook": "^7.6.20",
167
167
  "storybook-dark-mode": "4.0.2",
168
- "style-dictionary": "^5.1.3",
168
+ "style-dictionary": "^5.1.4",
169
169
  "style-loader": "^4",
170
170
  "tailwindcss": "3.4.19",
171
171
  "vue": "2.7.16",
@@ -1,6 +1,5 @@
1
1
  import Vue from 'vue';
2
2
  import isFunction from 'lodash/isFunction';
3
- import isString from 'lodash/isString';
4
3
  import { DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME } from './constants';
5
4
 
6
5
  const itemValidator = (item) => item?.text?.length > 0 && !Array.isArray(item?.items);
@@ -20,16 +19,29 @@ const itemsValidator = (items) => items.every(isItem) || items.every(isGroup);
20
19
  const isListItem = (tag) =>
21
20
  ['gl-disclosure-dropdown-group', 'gl-disclosure-dropdown-item', 'li'].includes(tag);
22
21
 
23
- const isValidSlotTagVue2 = (vNode) =>
24
- Boolean(vNode) && isListItem(vNode.componentOptions?.tag || vNode.tag);
22
+ const isValidSlotTagVue2 = (vNode) => {
23
+ if (!vNode) return false;
24
+ const tag = vNode.componentOptions?.tag || vNode.tag;
25
+ if (isListItem(tag)) return true;
26
+ const componentName = vNode.componentOptions?.Ctor?.options?.name;
27
+ return [DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME].includes(componentName);
28
+ };
25
29
 
26
30
  const isValidSlotTagVue3 = (vNode) => {
31
+ if (!vNode) return false;
27
32
  return (
28
33
  [DISCLOSURE_DROPDOWN_ITEM_NAME, DISCLOSURE_DROPDOWN_GROUP_NAME].includes(vNode.type?.name) ||
29
34
  vNode.type === 'li'
30
35
  );
31
36
  };
32
37
 
38
+ const isSkippableVue2 = (vNode) => {
39
+ if (!vNode) return true;
40
+ if (vNode.isComment) return true;
41
+ if (!vNode.tag && typeof vNode.text === 'string' && !vNode.text.trim()) return true;
42
+ return false;
43
+ };
44
+
33
45
  const hasOnlyListItemsVue2 = (defaultSlot) => {
34
46
  const nodes = defaultSlot();
35
47
 
@@ -37,9 +49,35 @@ const hasOnlyListItemsVue2 = (defaultSlot) => {
37
49
  return false;
38
50
  }
39
51
 
40
- const tags = nodes.filter((vNode) => vNode.tag);
52
+ const candidateNodes = nodes.filter((vNode) => !isSkippableVue2(vNode));
53
+
54
+ if (candidateNodes.length === 0) return true;
55
+
56
+ return candidateNodes.every((vNode) => isValidSlotTagVue2(vNode));
57
+ };
58
+
59
+ const isSkippableVue3 = (vNode) => {
60
+ if (!vNode) return true;
61
+ if (vNode.type === Vue.Comment) return true;
62
+ if (vNode.type === Vue.Text && !vNode.children?.trim()) return true;
63
+ if (vNode.type === Vue.Fragment && (!vNode.children || vNode.children.length === 0)) return true;
64
+ return false;
65
+ };
66
+
67
+ const validateNodesRecursiveVue3 = (nodes) => {
68
+ if (!Array.isArray(nodes) || nodes.length === 0) return true;
69
+
70
+ const candidateNodes = nodes.filter((vNode) => !isSkippableVue3(vNode));
71
+
72
+ if (candidateNodes.length === 0) return true;
41
73
 
42
- return tags.length && tags.every((tag) => isValidSlotTagVue2(tag));
74
+ return candidateNodes.every((vNode) => {
75
+ if (isValidSlotTagVue3(vNode)) return true;
76
+ if (vNode.type === Vue.Fragment && Array.isArray(vNode.children)) {
77
+ return validateNodesRecursiveVue3(vNode.children);
78
+ }
79
+ return false;
80
+ });
43
81
  };
44
82
 
45
83
  const hasOnlyListItemsVue3 = (defaultSlot) => {
@@ -47,12 +85,7 @@ const hasOnlyListItemsVue3 = (defaultSlot) => {
47
85
  const fragment = nodes.find((node) => Array.isArray(node.children) && node.children.length);
48
86
  const targetNodes = fragment ? fragment.children : nodes;
49
87
 
50
- return (
51
- targetNodes
52
- // Remove empty text vNodes
53
- .filter((vNode) => !isString(vNode.text) || vNode.text.trim().length > 0)
54
- .every((vNode) => isValidSlotTagVue3(vNode))
55
- );
88
+ return validateNodesRecursiveVue3(targetNodes);
56
89
  };
57
90
 
58
91
  const hasOnlyListItems = (defaultSlot) => {
@@ -206,22 +206,59 @@ export default {
206
206
  >
207
207
  <div class="gl-flex gl-h-full gl-flex-col">
208
208
  <div class="gl-mb-3 gl-flex gl-items-start gl-justify-between" data-testid="panel-title">
209
- <div class="gl-flex gl-items-center gl-overflow-hidden">
209
+ <div class="gl-flex gl-items-center gl-gap-2 gl-overflow-hidden">
210
210
  <gl-icon
211
211
  v-if="hasTitleIcon"
212
- class="gl-mr-2"
213
212
  :class="titleIconClass"
214
213
  :name="titleIcon"
215
214
  data-testid="panel-title-icon"
216
215
  />
217
216
 
218
217
  <div class="gl-min-w-0">
219
- <gl-truncate
220
- v-if="hasTitle"
221
- class="gl-font-bold gl-text-default"
222
- :text="title"
223
- with-tooltip
224
- />
218
+ <div class="gl-flex gl-items-center gl-gap-2">
219
+ <gl-truncate
220
+ v-if="hasTitle"
221
+ class="gl-min-w-0 gl-font-bold gl-text-default"
222
+ :text="title"
223
+ with-tooltip
224
+ />
225
+ <template v-if="hasTitlePopover">
226
+ <gl-icon
227
+ :id="titlePopoverId"
228
+ class="gl-min-w-5"
229
+ data-testid="panel-title-popover-icon"
230
+ name="information-o"
231
+ variant="info"
232
+ />
233
+ <gl-popover
234
+ data-testid="panel-title-popover"
235
+ boundary="viewport"
236
+ :target="titlePopoverId"
237
+ :css-classes="titlePopoverClasses"
238
+ >
239
+ <!-- @slot The title of the info popover. -->
240
+ <template v-if="hasInfoPopoverTitleSlot" #title>
241
+ <slot name="info-popover-title"></slot>
242
+ </template>
243
+
244
+ <!-- @slot The content of the info popover. -->
245
+ <template v-if="hasInfoPopoverContentSlot">
246
+ <slot name="info-popover-content"></slot>
247
+ </template>
248
+
249
+ <template v-if="!hasInfoPopoverContentSlot">
250
+ <gl-sprintf v-if="hasTitlePopoverLink" :message="titlePopover.description">
251
+ <template #link="{ content }">
252
+ <gl-link :href="titlePopover.descriptionLink" class="gl-text-sm">{{
253
+ content
254
+ }}</gl-link>
255
+ </template>
256
+ </gl-sprintf>
257
+ <template v-else> {{ titlePopover.description }} </template>
258
+ </template>
259
+ </gl-popover>
260
+ </template>
261
+ </div>
225
262
 
226
263
  <p
227
264
  v-if="subtitle"
@@ -231,43 +268,6 @@ export default {
231
268
  {{ subtitle }}
232
269
  </p>
233
270
  </div>
234
-
235
- <template v-if="hasTitlePopover">
236
- <gl-icon
237
- :id="titlePopoverId"
238
- class="gl-ml-2 gl-min-w-5"
239
- data-testid="panel-title-popover-icon"
240
- name="information-o"
241
- variant="info"
242
- />
243
- <gl-popover
244
- data-testid="panel-title-popover"
245
- boundary="viewport"
246
- :target="titlePopoverId"
247
- :css-classes="titlePopoverClasses"
248
- >
249
- <!-- @slot The title of the info popover. -->
250
- <template v-if="hasInfoPopoverTitleSlot" #title>
251
- <slot name="info-popover-title"></slot>
252
- </template>
253
-
254
- <!-- @slot The content of the info popover. -->
255
- <template v-if="hasInfoPopoverContentSlot">
256
- <slot name="info-popover-content"></slot>
257
- </template>
258
-
259
- <template v-if="!hasInfoPopoverContentSlot">
260
- <gl-sprintf v-if="hasTitlePopoverLink" :message="titlePopover.description">
261
- <template #link="{ content }">
262
- <gl-link :href="titlePopover.descriptionLink" class="gl-text-sm">{{
263
- content
264
- }}</gl-link>
265
- </template>
266
- </gl-sprintf>
267
- <template v-else> {{ titlePopover.description }} </template>
268
- </template>
269
- </gl-popover>
270
- </template>
271
271
  </div>
272
272
 
273
273
  <div