@gitlab/ui 86.5.0 → 86.6.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.
- package/CHANGELOG.md +14 -0
- package/dist/components/base/badge/badge.js +1 -1
- package/dist/directives/outside/outside.js +89 -39
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
- package/src/components/base/badge/badge.scss +13 -7
- package/src/components/base/badge/badge.vue +1 -5
- package/src/directives/outside/outside.js +81 -41
- package/src/directives/outside/outside.md +92 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [86.6.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v86.5.1...v86.6.0) (2024-07-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **OutsideDirective:** Add Event Listener for focusin ([aee99c5](https://gitlab.com/gitlab-org/gitlab-ui/commit/aee99c56b926d9468030774c4bd33eac01f4f601))
|
|
7
|
+
|
|
8
|
+
## [86.5.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v86.5.0...v86.5.1) (2024-07-10)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **GlBadge:** remove content wrapper element ([275887c](https://gitlab.com/gitlab-org/gitlab-ui/commit/275887c30c25be2257a40a88cde2f62a1198fc7e))
|
|
14
|
+
|
|
1
15
|
# [86.5.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v86.4.1...v86.5.0) (2024-07-10)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -68,7 +68,7 @@ var script = {
|
|
|
68
68
|
const __vue_script__ = script;
|
|
69
69
|
|
|
70
70
|
/* template */
|
|
71
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-badge',_vm._b({staticClass:"gl-badge",class:{ 'gl-px-2!': !_vm.$scopedSlots.default },attrs:{"variant":_vm.variant,"role":_vm.role,"aria-label":_vm.ariaLabel,"pill":""}},'b-badge',_vm.$attrs,false),[(_vm.icon)?_c('gl-icon',{staticClass:"gl-badge-icon",class:{ '-gl-ml-2 gl-ml-n2': _vm.isCircularIcon },attrs:{"size":_vm.iconSizeComputed,"name":_vm.icon}}):_vm._e(),_vm._v(" "),
|
|
71
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-badge',_vm._b({staticClass:"gl-badge",class:{ 'gl-px-2!': !_vm.$scopedSlots.default },attrs:{"variant":_vm.variant,"role":_vm.role,"aria-label":_vm.ariaLabel,"pill":""}},'b-badge',_vm.$attrs,false),[(_vm.icon)?_c('gl-icon',{staticClass:"gl-badge-icon",class:{ '-gl-ml-2 gl-ml-n2': _vm.isCircularIcon },attrs:{"size":_vm.iconSizeComputed,"name":_vm.icon}}):_vm._e(),_vm._v(" "),_vm._t("default")],2)};
|
|
72
72
|
var __vue_staticRenderFns__ = [];
|
|
73
73
|
|
|
74
74
|
/* style */
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Map<HTMLElement, Function>
|
|
2
|
+
* Map<HTMLElement, { callback: Function, eventTypes: Array<string> }>
|
|
3
3
|
*/
|
|
4
4
|
const callbacks = new Map();
|
|
5
|
+
const click = 'click';
|
|
6
|
+
const focusin = 'focusin';
|
|
7
|
+
const supportedEventTypes = [click, focusin];
|
|
8
|
+
const defaultEventType = click;
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
11
|
+
* A Set to keep track of currently active event types.
|
|
12
|
+
* This ensures that event listeners are only added for the event types that are in use.
|
|
13
|
+
*
|
|
14
|
+
* @type {Set<string>}
|
|
8
15
|
*/
|
|
9
|
-
|
|
16
|
+
const activeEventTypes = new Set();
|
|
10
17
|
let lastMousedown = null;
|
|
11
18
|
const globalListener = event => {
|
|
12
|
-
callbacks.forEach((
|
|
13
|
-
|
|
19
|
+
callbacks.forEach((_ref, element) => {
|
|
20
|
+
let {
|
|
21
|
+
callback,
|
|
22
|
+
eventTypes
|
|
23
|
+
} = _ref;
|
|
24
|
+
const originalEvent = event.type === click ? lastMousedown || event : event;
|
|
14
25
|
if (
|
|
15
26
|
// Ignore events that aren't targeted outside the element
|
|
16
|
-
element.contains(originalEvent.target)
|
|
27
|
+
element.contains(originalEvent.target) ||
|
|
28
|
+
// Ignore events that aren't the specified types for this element
|
|
29
|
+
!eventTypes.includes(event.type)) {
|
|
17
30
|
return;
|
|
18
31
|
}
|
|
19
32
|
try {
|
|
@@ -25,7 +38,9 @@ const globalListener = event => {
|
|
|
25
38
|
}
|
|
26
39
|
}
|
|
27
40
|
});
|
|
28
|
-
|
|
41
|
+
if (event.type === click) {
|
|
42
|
+
lastMousedown = null;
|
|
43
|
+
}
|
|
29
44
|
};
|
|
30
45
|
|
|
31
46
|
// We need to listen for mouse events because text selection fires click event only when selection ends.
|
|
@@ -34,39 +49,72 @@ const globalListener = event => {
|
|
|
34
49
|
const onMousedown = event => {
|
|
35
50
|
lastMousedown = event;
|
|
36
51
|
};
|
|
37
|
-
const startListening =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
const startListening = eventTypes => {
|
|
53
|
+
eventTypes.forEach(eventType => {
|
|
54
|
+
if (!activeEventTypes.has(eventType)) {
|
|
55
|
+
// Listening to mousedown events, ensures that a text selection doesn't trigger the
|
|
56
|
+
// GlOutsideDirective 'click' callback if the selection started within the target element.
|
|
57
|
+
if (eventType === click) {
|
|
58
|
+
document.addEventListener('mousedown', onMousedown);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Added { capture: true } to all event types to prevent the behavior discussed in https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1686#note_412545027
|
|
62
|
+
// Ensures the event listener handles the event in the capturing phase, avoiding issues encountered previously.
|
|
63
|
+
// Cannot be tested with Jest or Cypress, but can be tested with Playwright in the future: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/4272#note_1947425384
|
|
64
|
+
document.addEventListener(eventType, globalListener, {
|
|
65
|
+
capture: true
|
|
66
|
+
});
|
|
67
|
+
activeEventTypes.add(eventType);
|
|
68
|
+
}
|
|
47
69
|
});
|
|
48
|
-
listening = true;
|
|
49
70
|
lastMousedown = null;
|
|
50
71
|
};
|
|
51
|
-
const stopListening =
|
|
52
|
-
|
|
53
|
-
|
|
72
|
+
const stopListening = eventTypesToUnbind => {
|
|
73
|
+
eventTypesToUnbind.forEach(eventType => {
|
|
74
|
+
if (activeEventTypes.has(eventType)) {
|
|
75
|
+
if ([...callbacks.values()].every(_ref2 => {
|
|
76
|
+
let {
|
|
77
|
+
eventTypes
|
|
78
|
+
} = _ref2;
|
|
79
|
+
return !eventTypes.includes(eventType);
|
|
80
|
+
})) {
|
|
81
|
+
document.removeEventListener(eventType, globalListener);
|
|
82
|
+
activeEventTypes.delete(eventType);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (eventTypesToUnbind.includes(click) && !activeEventTypes.has(click)) {
|
|
87
|
+
document.removeEventListener('mousedown', onMousedown);
|
|
54
88
|
}
|
|
55
|
-
document.removeEventListener('mousedown', onMousedown);
|
|
56
|
-
document.removeEventListener('click', globalListener);
|
|
57
|
-
listening = false;
|
|
58
89
|
};
|
|
59
|
-
|
|
90
|
+
function parseBinding(_ref3) {
|
|
60
91
|
let {
|
|
92
|
+
arg,
|
|
61
93
|
value,
|
|
62
|
-
|
|
63
|
-
} =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
94
|
+
modifiers
|
|
95
|
+
} = _ref3;
|
|
96
|
+
const modifiersList = Object.keys(modifiers);
|
|
97
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
98
|
+
if (typeof value !== 'function') {
|
|
99
|
+
throw new Error(`[GlOutsideDirective] Value must be a function; got ${typeof value}!`);
|
|
100
|
+
}
|
|
101
|
+
if (typeof arg !== 'undefined') {
|
|
102
|
+
throw new Error(`[GlOutsideDirective] Arguments are not supported. Consider using modifiers instead.`);
|
|
103
|
+
}
|
|
104
|
+
if (modifiersList.some(modifier => !supportedEventTypes.includes(modifier))) {
|
|
105
|
+
throw new Error(`[GlOutsideDirective] Cannot bind ${modifiersList} events; supported event types are: ${supportedEventTypes.join(', ')}`);
|
|
106
|
+
}
|
|
69
107
|
}
|
|
108
|
+
return {
|
|
109
|
+
callback: value,
|
|
110
|
+
eventTypes: modifiersList.length > 0 ? modifiersList : [defaultEventType]
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const bind = (el, bindings) => {
|
|
114
|
+
const {
|
|
115
|
+
callback,
|
|
116
|
+
eventTypes
|
|
117
|
+
} = parseBinding(bindings);
|
|
70
118
|
if (callbacks.has(el)) {
|
|
71
119
|
// This element is already bound. This is possible if two components, which
|
|
72
120
|
// share the same root node, (i.e., one is a higher-order component
|
|
@@ -79,15 +127,17 @@ const bind = (el, _ref) => {
|
|
|
79
127
|
// element.
|
|
80
128
|
return;
|
|
81
129
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
130
|
+
callbacks.set(el, {
|
|
131
|
+
callback,
|
|
132
|
+
eventTypes
|
|
133
|
+
});
|
|
134
|
+
startListening(eventTypes);
|
|
86
135
|
};
|
|
87
136
|
const unbind = el => {
|
|
88
|
-
callbacks.
|
|
89
|
-
if (
|
|
90
|
-
|
|
137
|
+
const entry = callbacks.get(el);
|
|
138
|
+
if (entry) {
|
|
139
|
+
callbacks.delete(el);
|
|
140
|
+
stopListening(entry.eventTypes);
|
|
91
141
|
}
|
|
92
142
|
};
|
|
93
143
|
const OutsideDirective = {
|