@gitlab/ui 103.4.1 → 103.5.1
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 +14 -0
- package/dist/components/base/accordion/accordion_item.js +4 -5
- package/dist/components/utilities/intersperse/intersperse.js +18 -4
- package/dist/utils/is_slot_empty.js +11 -6
- package/package.json +6 -5
- package/src/components/base/accordion/accordion_item.vue +3 -4
- package/src/components/utilities/intersperse/intersperse.vue +21 -5
- package/src/index.js +0 -1
- package/src/scss/components.scss +0 -1
- package/src/utils/is_slot_empty.js +10 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [103.5.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v103.5.0...v103.5.1) (2024-11-26)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **GlIntersperse:** Ignore empty nodes in Vue 3 ([91ec35b](https://gitlab.com/gitlab-org/gitlab-ui/commit/91ec35b664aa9c8a8959247e92dd29c1409e57ea))
|
|
7
|
+
|
|
8
|
+
# [103.5.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v103.4.1...v103.5.0) (2024-11-22)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **GlAccordion:** add chevron animation ([fee4ef4](https://gitlab.com/gitlab-org/gitlab-ui/commit/fee4ef4dac649ee09ce3f9a9a2610d68fe9a8e88))
|
|
14
|
+
|
|
1
15
|
## [103.4.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v103.4.0...v103.4.1) (2024-11-22)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import uniqueId from 'lodash/uniqueId';
|
|
2
2
|
import { BCollapse } from '../../../vendor/bootstrap-vue/src/components/collapse/collapse';
|
|
3
|
+
import GlAnimatedChevronRightDownIcon from '../animated_icon/animated_chevron_right_down_icon';
|
|
3
4
|
import { GlCollapseToggleDirective } from '../../../directives/collapse_toggle';
|
|
4
5
|
import GlButton from '../button/button';
|
|
5
6
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
@@ -8,7 +9,8 @@ var script = {
|
|
|
8
9
|
name: 'GlAccordionItem',
|
|
9
10
|
components: {
|
|
10
11
|
BCollapse,
|
|
11
|
-
GlButton
|
|
12
|
+
GlButton,
|
|
13
|
+
GlAnimatedChevronRightDownIcon
|
|
12
14
|
},
|
|
13
15
|
directives: {
|
|
14
16
|
GlCollapseToggle: GlCollapseToggleDirective
|
|
@@ -77,9 +79,6 @@ var script = {
|
|
|
77
79
|
accordion() {
|
|
78
80
|
return this.accordionSetId() || undefined;
|
|
79
81
|
},
|
|
80
|
-
icon() {
|
|
81
|
-
return this.isVisible ? 'chevron-down' : 'chevron-right';
|
|
82
|
-
},
|
|
83
82
|
buttonTitle() {
|
|
84
83
|
return this.isVisible && this.titleVisible ? this.titleVisible : this.title;
|
|
85
84
|
}
|
|
@@ -98,7 +97,7 @@ var script = {
|
|
|
98
97
|
const __vue_script__ = script;
|
|
99
98
|
|
|
100
99
|
/* template */
|
|
101
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-accordion-item"},[_c(_vm.headerComponent,{tag:"component",staticClass:"gl-accordion-item-header",class:_vm.headerClass},[_c('gl-button',{directives:[{name:"gl-collapse-toggle",rawName:"v-gl-collapse-toggle",value:(_vm.accordionItemId),expression:"accordionItemId"}],attrs:{"variant":"link","button-text-classes":"gl-flex",
|
|
100
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-accordion-item"},[_c(_vm.headerComponent,{tag:"component",staticClass:"gl-accordion-item-header",class:_vm.headerClass},[_c('gl-button',{directives:[{name:"gl-collapse-toggle",rawName:"v-gl-collapse-toggle",value:(_vm.accordionItemId),expression:"accordionItemId"}],attrs:{"variant":"link","button-text-classes":"gl-flex"}},[_c('gl-animated-chevron-right-down-icon',{attrs:{"is-on":_vm.isVisible}}),_vm._v("\n "+_vm._s(_vm.buttonTitle)+"\n ")],1)],1),_vm._v(" "),_c('b-collapse',{staticClass:"gl-mt-3 gl-text-base",attrs:{"id":_vm.accordionItemId,"visible":_vm.isVisible,"accordion":_vm.accordion,"data-testid":("accordion-item-collapse-" + _vm.accordionItemId)},model:{value:(_vm.isVisible),callback:function ($$v) {_vm.isVisible=$$v;},expression:"isVisible"}},[_vm._t("default")],2)],1)};
|
|
102
101
|
var __vue_staticRenderFns__ = [];
|
|
103
102
|
|
|
104
103
|
/* style */
|
|
@@ -1,13 +1,27 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
1
2
|
import compose from 'lodash/fp/compose';
|
|
2
3
|
import fill from 'lodash/fp/fill';
|
|
3
4
|
import filter from 'lodash/fp/filter';
|
|
4
5
|
import { insert, intersperse } from '../../../utils/data_utils';
|
|
6
|
+
import { isVnodeEmpty } from '../../../utils/is_slot_empty';
|
|
5
7
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
6
8
|
|
|
7
9
|
//
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
10
|
+
const filterEmptyNodesVue2 = filter(vNode => typeof vNode.tag === 'string' || vNode.text.trim() !== '');
|
|
11
|
+
const {
|
|
12
|
+
Fragment
|
|
13
|
+
} = Vue;
|
|
14
|
+
const filterEmptyNodesVue3 = vNode => {
|
|
15
|
+
return vNode.reduce((acc, node) => {
|
|
16
|
+
if (Fragment && node.type === Fragment && Array.isArray(node.children)) {
|
|
17
|
+
acc.push(...node.children);
|
|
18
|
+
} else {
|
|
19
|
+
acc.push(node);
|
|
20
|
+
}
|
|
21
|
+
return acc;
|
|
22
|
+
}, []).filter(node => !isVnodeEmpty(node));
|
|
23
|
+
};
|
|
24
|
+
const filterEmptyNodes = Vue.version.startsWith('3') ? filterEmptyNodesVue3 : filterEmptyNodesVue2;
|
|
11
25
|
const insertAfterSecondLastItem = insert(-1);
|
|
12
26
|
const replaceSecondLastItem = fill(-2, -1);
|
|
13
27
|
|
|
@@ -44,7 +58,7 @@ var script = {
|
|
|
44
58
|
slots,
|
|
45
59
|
data
|
|
46
60
|
} = context;
|
|
47
|
-
const filterAndSeparate = compose(addLastSeparator(lastSeparator), intersperse(separator),
|
|
61
|
+
const filterAndSeparate = compose(addLastSeparator(lastSeparator), intersperse(separator), filterEmptyNodes);
|
|
48
62
|
return createElement('span', data, filterAndSeparate(slots().default));
|
|
49
63
|
}
|
|
50
64
|
};
|
|
@@ -3,23 +3,28 @@ import Vue from 'vue';
|
|
|
3
3
|
// Fragment will be available only in Vue.js 3
|
|
4
4
|
const {
|
|
5
5
|
Fragment,
|
|
6
|
-
Comment
|
|
6
|
+
Comment,
|
|
7
|
+
Text
|
|
7
8
|
} = Vue;
|
|
8
9
|
function callIfNeeded(fnOrResult, args) {
|
|
9
10
|
return fnOrResult instanceof Function ? fnOrResult(args) : fnOrResult;
|
|
10
11
|
}
|
|
11
|
-
function
|
|
12
|
+
function isVnodeEmpty(vnode) {
|
|
12
13
|
if (!vnode || Comment && vnode.type === Comment) {
|
|
13
14
|
return true;
|
|
14
15
|
}
|
|
16
|
+
if (Text && vnode.type === Text && !vnode.children.trim()) {
|
|
17
|
+
// Vue.js 3 text string is located in the children
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
15
20
|
if (Array.isArray(vnode)) {
|
|
16
21
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
17
|
-
return vnode.every(
|
|
22
|
+
return vnode.every(isVnodeEmpty);
|
|
18
23
|
}
|
|
19
24
|
if (Fragment && vnode.type === Fragment) {
|
|
20
25
|
// Vue.js 3 fragment, check children
|
|
21
26
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
22
|
-
return vnode.children.every(
|
|
27
|
+
return vnode.children.every(isVnodeEmpty);
|
|
23
28
|
}
|
|
24
29
|
return false;
|
|
25
30
|
}
|
|
@@ -32,7 +37,7 @@ function isSlotEmpty(vueInstance, slot, slotArgs) {
|
|
|
32
37
|
callIfNeeded(vueInstance.$slots[slot] || vueInstance.$scopedSlots[slot], slotArgs) : (_vueInstance$$scopedS = (_vueInstance$$scopedS2 = vueInstance.$scopedSlots)[slot]) === null || _vueInstance$$scopedS === void 0 ? void 0 : _vueInstance$$scopedS.call(_vueInstance$$scopedS2, slotArgs);
|
|
33
38
|
|
|
34
39
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
35
|
-
return
|
|
40
|
+
return isVnodeEmpty(slotContent);
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
export { isSlotEmpty };
|
|
43
|
+
export { isSlotEmpty, isVnodeEmpty };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "103.
|
|
3
|
+
"version": "103.5.1",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -143,16 +143,17 @@
|
|
|
143
143
|
"axe-core": "^4.2.3",
|
|
144
144
|
"babel-jest": "29.0.1",
|
|
145
145
|
"babel-loader": "^8.0.5",
|
|
146
|
-
"cypress": "13.
|
|
146
|
+
"cypress": "13.16.0",
|
|
147
147
|
"cypress-axe": "^1.4.0",
|
|
148
148
|
"cypress-real-events": "^1.11.0",
|
|
149
149
|
"dompurify": "^3.1.2",
|
|
150
150
|
"emoji-regex": "^10.0.0",
|
|
151
151
|
"esbuild": "^0.18.0",
|
|
152
152
|
"eslint": "8.57.1",
|
|
153
|
+
"eslint-formatter-gitlab": "^5.1.0",
|
|
153
154
|
"eslint-import-resolver-jest": "3.0.2",
|
|
154
155
|
"eslint-plugin-cypress": "3.6.0",
|
|
155
|
-
"eslint-plugin-storybook": "0.
|
|
156
|
+
"eslint-plugin-storybook": "0.11.1",
|
|
156
157
|
"gitlab-api-async-iterator": "^1.3.1",
|
|
157
158
|
"glob": "10.3.3",
|
|
158
159
|
"globby": "^11.1.0",
|
|
@@ -167,8 +168,8 @@
|
|
|
167
168
|
"module-alias": "^2.2.2",
|
|
168
169
|
"npm-run-all": "^4.1.5",
|
|
169
170
|
"pikaday": "^1.8.0",
|
|
170
|
-
"playwright": "^1.
|
|
171
|
-
"playwright-core": "^1.
|
|
171
|
+
"playwright": "^1.49.0",
|
|
172
|
+
"playwright-core": "^1.49.0",
|
|
172
173
|
"postcss": "8.4.28",
|
|
173
174
|
"postcss-loader": "^7.0.2",
|
|
174
175
|
"postcss-scss": "4.0.4",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import uniqueId from 'lodash/uniqueId';
|
|
3
3
|
import { BCollapse } from '../../../vendor/bootstrap-vue/src/components/collapse/collapse';
|
|
4
|
+
import GlAnimatedChevronRightDownIcon from '../animated_icon/animated_chevron_right_down_icon.vue';
|
|
4
5
|
import { GlCollapseToggleDirective } from '../../../directives/collapse_toggle';
|
|
5
6
|
import GlButton from '../button/button.vue';
|
|
6
7
|
|
|
@@ -9,6 +10,7 @@ export default {
|
|
|
9
10
|
components: {
|
|
10
11
|
BCollapse,
|
|
11
12
|
GlButton,
|
|
13
|
+
GlAnimatedChevronRightDownIcon,
|
|
12
14
|
},
|
|
13
15
|
directives: {
|
|
14
16
|
GlCollapseToggle: GlCollapseToggleDirective,
|
|
@@ -77,9 +79,6 @@ export default {
|
|
|
77
79
|
accordion() {
|
|
78
80
|
return this.accordionSetId() || undefined;
|
|
79
81
|
},
|
|
80
|
-
icon() {
|
|
81
|
-
return this.isVisible ? 'chevron-down' : 'chevron-right';
|
|
82
|
-
},
|
|
83
82
|
buttonTitle() {
|
|
84
83
|
return this.isVisible && this.titleVisible ? this.titleVisible : this.title;
|
|
85
84
|
},
|
|
@@ -102,8 +101,8 @@ export default {
|
|
|
102
101
|
v-gl-collapse-toggle="accordionItemId"
|
|
103
102
|
variant="link"
|
|
104
103
|
button-text-classes="gl-flex"
|
|
105
|
-
:icon="icon"
|
|
106
104
|
>
|
|
105
|
+
<gl-animated-chevron-right-down-icon :is-on="isVisible" />
|
|
107
106
|
{{ buttonTitle }}
|
|
108
107
|
</gl-button>
|
|
109
108
|
</component>
|
|
@@ -1,15 +1,31 @@
|
|
|
1
1
|
<!-- eslint-disable vue/multi-word-component-names -->
|
|
2
2
|
<script>
|
|
3
|
+
import Vue from 'vue';
|
|
3
4
|
import compose from 'lodash/fp/compose';
|
|
4
5
|
import fill from 'lodash/fp/fill';
|
|
5
6
|
import filter from 'lodash/fp/filter';
|
|
6
|
-
|
|
7
7
|
import { intersperse, insert } from '../../../utils/data_utils';
|
|
8
|
+
import { isVnodeEmpty } from '../../../utils/is_slot_empty';
|
|
9
|
+
|
|
10
|
+
const filterEmptyNodesVue2 = filter(
|
|
11
|
+
(vNode) => typeof vNode.tag === 'string' || vNode.text.trim() !== ''
|
|
12
|
+
);
|
|
8
13
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
14
|
+
const { Fragment } = Vue;
|
|
15
|
+
const filterEmptyNodesVue3 = (vNode) => {
|
|
16
|
+
return vNode
|
|
17
|
+
.reduce((acc, node) => {
|
|
18
|
+
if (Fragment && node.type === Fragment && Array.isArray(node.children)) {
|
|
19
|
+
acc.push(...node.children);
|
|
20
|
+
} else {
|
|
21
|
+
acc.push(node);
|
|
22
|
+
}
|
|
23
|
+
return acc;
|
|
24
|
+
}, [])
|
|
25
|
+
.filter((node) => !isVnodeEmpty(node));
|
|
26
|
+
};
|
|
12
27
|
|
|
28
|
+
const filterEmptyNodes = Vue.version.startsWith('3') ? filterEmptyNodesVue3 : filterEmptyNodesVue2;
|
|
13
29
|
const insertAfterSecondLastItem = insert(-1);
|
|
14
30
|
const replaceSecondLastItem = fill(-2, -1);
|
|
15
31
|
|
|
@@ -51,7 +67,7 @@ export default {
|
|
|
51
67
|
const filterAndSeparate = compose(
|
|
52
68
|
addLastSeparator(lastSeparator),
|
|
53
69
|
intersperse(separator),
|
|
54
|
-
|
|
70
|
+
filterEmptyNodes
|
|
55
71
|
);
|
|
56
72
|
|
|
57
73
|
return createElement('span', data, filterAndSeparate(slots().default));
|
package/src/index.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
// builds. We do this to avoid having the stylesheet included multiple times in Storybook.
|
|
5
5
|
|
|
6
6
|
// Components
|
|
7
|
-
// ADD COMPONENT EXPORTS - needed for yarn generate:component. Do not remove
|
|
8
7
|
export { default as GlDuoWorkflowPrompt } from './components/experimental/duo/workflow/components/duo_workflow_prompt/duo_workflow_prompt.vue';
|
|
9
8
|
export { default as GlDuoWorkflowPanel } from './components/experimental/duo/workflow/components/duo_workflow_panel/duo_workflow_panel.vue';
|
|
10
9
|
export { default as GlTableLite } from './components/base/table_lite/table_lite.vue';
|
package/src/scss/components.scss
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
// Import component stylesheets located in components here. i.e.
|
|
3
3
|
// @import '../components/base/dropdown/dropdown'
|
|
4
4
|
//
|
|
5
|
-
// ADD COMPONENT IMPORTS - needed for yarn generate:component. Do not remove
|
|
6
5
|
@import '../components/experimental/duo/chat/duo_chat';
|
|
7
6
|
@import '../components/experimental/duo/chat/components/duo_chat_message/duo_chat_message';
|
|
8
7
|
@import '../components/experimental/duo/chat/components/duo_chat_loader/duo_chat_loader';
|
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
2
|
|
|
3
3
|
// Fragment will be available only in Vue.js 3
|
|
4
|
-
const { Fragment, Comment } = Vue;
|
|
4
|
+
const { Fragment, Comment, Text } = Vue;
|
|
5
5
|
|
|
6
6
|
function callIfNeeded(fnOrResult, args) {
|
|
7
7
|
return fnOrResult instanceof Function ? fnOrResult(args) : fnOrResult;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
function
|
|
10
|
+
export function isVnodeEmpty(vnode) {
|
|
11
11
|
if (!vnode || (Comment && vnode.type === Comment)) {
|
|
12
12
|
return true;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
if (Text && vnode.type === Text && !vnode.children.trim()) {
|
|
16
|
+
// Vue.js 3 text string is located in the children
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
if (Array.isArray(vnode)) {
|
|
16
21
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
17
|
-
return vnode.every(
|
|
22
|
+
return vnode.every(isVnodeEmpty);
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
if (Fragment && vnode.type === Fragment) {
|
|
21
26
|
// Vue.js 3 fragment, check children
|
|
22
27
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
23
|
-
return vnode.children.every(
|
|
28
|
+
return vnode.children.every(isVnodeEmpty);
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
return false;
|
|
@@ -36,5 +41,5 @@ export function isSlotEmpty(vueInstance, slot, slotArgs) {
|
|
|
36
41
|
: vueInstance.$scopedSlots[slot]?.(slotArgs);
|
|
37
42
|
|
|
38
43
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
39
|
-
return
|
|
44
|
+
return isVnodeEmpty(slotContent);
|
|
40
45
|
}
|