Skip to content

Commit e9f8e36

Browse files
committed
More robust column dragging
Update vue to alpha 9
1 parent b6e61b6 commit e9f8e36

File tree

3 files changed

+123
-86
lines changed

3 files changed

+123
-86
lines changed

package-lock.json

+52-41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
"build": "webpack --env.prod"
77
},
88
"dependencies": {
9-
"vue": "^3.0.0-alpha.8"
9+
"vue": "^3.0.0-alpha.9"
1010
},
1111
"devDependencies": {
1212
"@types/w3c-css-typed-object-model-level-1": "^20180410.0.1",
13-
"@vue/compiler-sfc": "^3.0.0-alpha.8",
13+
"@vue/compiler-sfc": "^3.0.0-alpha.9",
1414
"css-loader": "^3.4.2",
1515
"ts-loader": "^6.2.1",
1616
"typescript": "^3.8.3",

src/animation/index.ts

+69-43
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,15 @@ export function useAnimations(columns: Column[], autoSized: Ref<boolean>) {
4343
resetTracking();
4444
});
4545

46-
return function headerPointerDown({ currentTarget: th, x, pointerId }: PointerEvent & { currentTarget: HTMLElement }, column: Column) {
46+
// Note that it's possible to skip pointerup events in some edge cases (at least happens in Chromium 82).
47+
// Examples include stressing the thing like a madman (not sure what triggers the bug then)
48+
// or judicious use of Alt-Tab when dragging.
49+
return function headerPointerDown({ currentTarget: th, x: x0, button }: PointerEvent & { currentTarget: HTMLElement }, column: Column) {
50+
if (button !== 0) return;
51+
4752
let i = columns.indexOf(column);
53+
// We missed a pointerup but nevermind, the old listeners are still in place
54+
if (column.dragged) return;
4855

4956
function thresholds() {
5057
return [
@@ -54,53 +61,72 @@ export function useAnimations(columns: Column[], autoSized: Ref<boolean>) {
5461
}
5562

5663
let [left, right] = thresholds();
57-
let translateX: CSSUnitValue;
64+
let translateX: CSSUnitValue;
5865
let transform: CSSTransformValue;
5966

60-
const preventClick = (e: Event) => e.stopImmediatePropagation();
61-
62-
const moveHandler = (event: PointerEvent) => {
63-
let delta = event.x - x;
64-
65-
// start dragging after a significant amount of movement
66-
if (!column.dragged) {
67-
if (Math.abs(delta) < 4) return;
68-
column.dragged = true;
69-
window.addEventListener('click', preventClick, { once: true, capture: true })
70-
transform = new CSSTransformValue([ new CSSTranslate(translateX = CSS.px(0), CSS.px(0)) ]);
71-
}
67+
const listeners = {
68+
handleEvent(e: PointerEvent) {
69+
switch (e.type) {
70+
case 'click':
71+
e.stopImmediatePropagation();
72+
break;
73+
case 'pointermove':
74+
this.move(e);
75+
break;
76+
case 'pointerup':
77+
if (e.button === 0)
78+
this.up();
79+
break;
80+
}
81+
},
7282

73-
// swap columns if required
74-
if (delta < left) {
75-
const other = columns[--i];
76-
x -= other.width;
77-
columns.splice(i, 2, column, other);
78-
delta = event.x - x;
79-
[left, right] = thresholds();
80-
}
81-
else if (delta > right) {
82-
const other = columns[++i];
83-
x += other.width;
84-
columns.splice(i - 1, 2, other, column);
85-
delta = event.x - x;
86-
[left, right] = thresholds();
87-
}
83+
move({ x, buttons }: PointerEvent) {
84+
let delta = x - x0;
85+
86+
// start dragging after a significant amount of movement
87+
if (!column.dragged) {
88+
if (Math.abs(delta) < 4) return;
89+
column.dragged = true;
90+
window.addEventListener('click', this, { once: true, capture: true })
91+
transform = new CSSTransformValue([ new CSSTranslate(translateX = CSS.px(0), CSS.px(0)) ]);
92+
}
93+
else if ((buttons & 1) === 0) {
94+
// button was released without us noticing. This is bad :(
95+
this.up();
96+
return;
97+
}
8898

89-
translateX.value = delta;
90-
th.attributeStyleMap.set('transform', transform);
99+
// swap columns if required
100+
if (delta < left) {
101+
const other = columns[--i];
102+
x0 -= other.width;
103+
delta = x - x0;
104+
columns.splice(i, 2, column, other);
105+
[left, right] = thresholds();
106+
}
107+
else if (delta > right) {
108+
const other = columns[++i];
109+
x0 += other.width;
110+
delta = x - x0;
111+
columns.splice(i - 1, 2, other, column);
112+
[left, right] = thresholds();
113+
}
114+
115+
translateX.value = delta;
116+
th.attributeStyleMap.set('transform', transform);
117+
},
118+
119+
up() {
120+
['pointermove', 'pointerup']
121+
.forEach(name => window.removeEventListener(name, this, true));
122+
if (!column.dragged) return;
123+
column.dragged = false;
124+
th.attributeStyleMap.delete('transform');
125+
setTimeout(() => window.removeEventListener('click', this, true), 0);
126+
}
91127
};
92128

93-
window.addEventListener('pointermove', moveHandler, true);
94-
95-
window.addEventListener('pointerup', () => {
96-
window.removeEventListener('pointermove', moveHandler, true);
97-
if (!column.dragged) return;
98-
column.dragged = false;
99-
th.attributeStyleMap.delete('transform');
100-
setTimeout(() => window.removeEventListener('click', preventClick, true), 0);
101-
}, {
102-
once: true,
103-
capture: true
104-
});
129+
['pointermove', 'pointerup']
130+
.forEach(name => window.addEventListener(name, listeners, true));
105131
}
106132
}

0 commit comments

Comments
 (0)