@gitlab/ui 67.1.0 → 67.2.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 +7 -0
- package/dist/directives/outside/outside.js +14 -1
- package/dist/tokens/css/tokens.css +1 -1
- package/dist/tokens/css/tokens.dark.css +1 -1
- package/dist/tokens/js/tokens.dark.js +1 -1
- package/dist/tokens/js/tokens.js +1 -1
- package/dist/tokens/scss/_tokens.dark.scss +1 -1
- package/dist/tokens/scss/_tokens.scss +1 -1
- package/package.json +3 -3
- package/src/directives/outside/outside.js +14 -1
- package/src/directives/outside/outside.spec.js +19 -25
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [67.2.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v67.1.0...v67.2.0) (2023-10-30)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **GlOutsideDirective:** respect mousedown events before click ([e2d72d5](https://gitlab.com/gitlab-org/gitlab-ui/commit/e2d72d5cc4d90c57fea3eb54f43d68338cab5ab4))
|
|
7
|
+
|
|
1
8
|
# [67.1.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v67.0.0...v67.1.0) (2023-10-27)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -9,15 +9,17 @@ const callbacks = new Map();
|
|
|
9
9
|
* Is a global listener already set up?
|
|
10
10
|
*/
|
|
11
11
|
let listening = false;
|
|
12
|
+
let lastMousedown = null;
|
|
12
13
|
const globalListener = event => {
|
|
13
14
|
callbacks.forEach((_ref, element) => {
|
|
14
15
|
let {
|
|
15
16
|
bindTimeStamp,
|
|
16
17
|
callback
|
|
17
18
|
} = _ref;
|
|
19
|
+
const originalEvent = lastMousedown || event;
|
|
18
20
|
if (
|
|
19
21
|
// Ignore events that aren't targeted outside the element
|
|
20
|
-
element.contains(
|
|
22
|
+
element.contains(originalEvent.target) ||
|
|
21
23
|
// Only consider events triggered after the directive was bound
|
|
22
24
|
event.timeStamp <= bindTimeStamp) {
|
|
23
25
|
return;
|
|
@@ -31,20 +33,31 @@ const globalListener = event => {
|
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
});
|
|
36
|
+
lastMousedown = null;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// We need to listen for mouse events because text selection fires click event only when selection ends.
|
|
40
|
+
// This means that the click event target could differ from the element where it originally started.
|
|
41
|
+
// As example: if we use mouse events we could guarantee that selecting text within a dropdown won't close it.
|
|
42
|
+
const onMousedown = event => {
|
|
43
|
+
lastMousedown = event;
|
|
34
44
|
};
|
|
35
45
|
const startListening = () => {
|
|
36
46
|
if (listening) {
|
|
37
47
|
return;
|
|
38
48
|
}
|
|
49
|
+
document.addEventListener('mousedown', onMousedown);
|
|
39
50
|
document.addEventListener('click', globalListener, {
|
|
40
51
|
capture: true
|
|
41
52
|
});
|
|
42
53
|
listening = true;
|
|
54
|
+
lastMousedown = null;
|
|
43
55
|
};
|
|
44
56
|
const stopListening = () => {
|
|
45
57
|
if (!listening) {
|
|
46
58
|
return;
|
|
47
59
|
}
|
|
60
|
+
document.removeEventListener('mousedown', onMousedown);
|
|
48
61
|
document.removeEventListener('click', globalListener);
|
|
49
62
|
listening = false;
|
|
50
63
|
};
|
package/dist/tokens/js/tokens.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "67.
|
|
3
|
+
"version": "67.2.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"@gitlab/eslint-plugin": "19.2.0",
|
|
95
95
|
"@gitlab/fonts": "^1.3.0",
|
|
96
96
|
"@gitlab/stylelint-config": "5.0.1",
|
|
97
|
-
"@gitlab/svgs": "3.
|
|
97
|
+
"@gitlab/svgs": "3.68.0",
|
|
98
98
|
"@rollup/plugin-commonjs": "^11.1.0",
|
|
99
99
|
"@rollup/plugin-node-resolve": "^7.1.3",
|
|
100
100
|
"@rollup/plugin-replace": "^2.3.2",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"babel-loader": "^8.0.5",
|
|
123
123
|
"babel-plugin-require-context-hook": "^1.0.0",
|
|
124
124
|
"bootstrap": "4.6.2",
|
|
125
|
-
"cypress": "13.3.
|
|
125
|
+
"cypress": "13.3.3",
|
|
126
126
|
"cypress-axe": "^1.4.0",
|
|
127
127
|
"dompurify": "^3.0.0",
|
|
128
128
|
"emoji-regex": "^10.0.0",
|
|
@@ -9,12 +9,14 @@ const callbacks = new Map();
|
|
|
9
9
|
* Is a global listener already set up?
|
|
10
10
|
*/
|
|
11
11
|
let listening = false;
|
|
12
|
+
let lastMousedown = null;
|
|
12
13
|
|
|
13
14
|
const globalListener = (event) => {
|
|
14
15
|
callbacks.forEach(({ bindTimeStamp, callback }, element) => {
|
|
16
|
+
const originalEvent = lastMousedown || event;
|
|
15
17
|
if (
|
|
16
18
|
// Ignore events that aren't targeted outside the element
|
|
17
|
-
element.contains(
|
|
19
|
+
element.contains(originalEvent.target) ||
|
|
18
20
|
// Only consider events triggered after the directive was bound
|
|
19
21
|
event.timeStamp <= bindTimeStamp
|
|
20
22
|
) {
|
|
@@ -30,6 +32,14 @@ const globalListener = (event) => {
|
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
});
|
|
35
|
+
lastMousedown = null;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// We need to listen for mouse events because text selection fires click event only when selection ends.
|
|
39
|
+
// This means that the click event target could differ from the element where it originally started.
|
|
40
|
+
// As example: if we use mouse events we could guarantee that selecting text within a dropdown won't close it.
|
|
41
|
+
const onMousedown = (event) => {
|
|
42
|
+
lastMousedown = event;
|
|
33
43
|
};
|
|
34
44
|
|
|
35
45
|
const startListening = () => {
|
|
@@ -37,8 +47,10 @@ const startListening = () => {
|
|
|
37
47
|
return;
|
|
38
48
|
}
|
|
39
49
|
|
|
50
|
+
document.addEventListener('mousedown', onMousedown);
|
|
40
51
|
document.addEventListener('click', globalListener, { capture: true });
|
|
41
52
|
listening = true;
|
|
53
|
+
lastMousedown = null;
|
|
42
54
|
};
|
|
43
55
|
|
|
44
56
|
const stopListening = () => {
|
|
@@ -46,6 +58,7 @@ const stopListening = () => {
|
|
|
46
58
|
return;
|
|
47
59
|
}
|
|
48
60
|
|
|
61
|
+
document.removeEventListener('mousedown', onMousedown);
|
|
49
62
|
document.removeEventListener('click', globalListener);
|
|
50
63
|
listening = false;
|
|
51
64
|
};
|
|
@@ -126,35 +126,14 @@ describe('outside directive', () => {
|
|
|
126
126
|
expect(document.addEventListener).not.toHaveBeenCalled();
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
it('attaches the global listener on first initialisation', async () => {
|
|
130
|
-
await createComponent();
|
|
131
|
-
|
|
132
|
-
expect(document.addEventListener.mock.calls).toEqual([
|
|
133
|
-
['click', expect.any(Function), { capture: true }],
|
|
134
|
-
]);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
129
|
it('detaches the global listener when last binding is removed', async () => {
|
|
138
130
|
await createComponent();
|
|
139
131
|
|
|
140
132
|
wrapper.destroy();
|
|
141
133
|
|
|
142
|
-
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('only binds once, even with multiple instances', async () => {
|
|
146
|
-
await createComponent({
|
|
147
|
-
template: `
|
|
148
|
-
<div>
|
|
149
|
-
<div v-outside="onClick"></div>
|
|
150
|
-
<div v-outside="onClick"></div>
|
|
151
|
-
</div>
|
|
152
|
-
`,
|
|
153
|
-
});
|
|
134
|
+
document.body.dispatchEvent(new MouseEvent('click'));
|
|
154
135
|
|
|
155
|
-
expect(
|
|
156
|
-
['click', expect.any(Function), { capture: true }],
|
|
157
|
-
]);
|
|
136
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
158
137
|
});
|
|
159
138
|
|
|
160
139
|
it('only unbinds once there are no instances', async () => {
|
|
@@ -173,12 +152,16 @@ describe('outside directive', () => {
|
|
|
173
152
|
wrapper.setData({ instances: 1 });
|
|
174
153
|
await wrapper.vm.$nextTick();
|
|
175
154
|
|
|
176
|
-
|
|
155
|
+
document.body.dispatchEvent(new MouseEvent('click'));
|
|
156
|
+
|
|
157
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
177
158
|
|
|
178
159
|
wrapper.setData({ instances: 0 });
|
|
179
160
|
await wrapper.vm.$nextTick();
|
|
180
161
|
|
|
181
|
-
|
|
162
|
+
document.body.dispatchEvent(new MouseEvent('click'));
|
|
163
|
+
|
|
164
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
182
165
|
});
|
|
183
166
|
});
|
|
184
167
|
|
|
@@ -341,4 +324,15 @@ describe('outside directive', () => {
|
|
|
341
324
|
expect(global.console.error.mock.calls).toEqual([[thrownError]]);
|
|
342
325
|
});
|
|
343
326
|
});
|
|
327
|
+
|
|
328
|
+
describe('mousedown before click', () => {
|
|
329
|
+
it('respects mousedown event before click', async () => {
|
|
330
|
+
await createComponent();
|
|
331
|
+
|
|
332
|
+
find('inside').trigger('mousedown');
|
|
333
|
+
find('outside').trigger('click');
|
|
334
|
+
|
|
335
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
336
|
+
});
|
|
337
|
+
});
|
|
344
338
|
});
|