-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpanel-splitter.js
97 lines (80 loc) · 3.25 KB
/
panel-splitter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import runCallbacks from '@cfware/callback-array-once';
import ShadowElement, {html, template, css, adoptedStyleSheets, createBoundEventListeners, define, reflectStringProperties, reflectBooleanProperties, reflectNumericProperties} from '@cfware/shadow-element';
import calculateSize from './calculate-size.js';
const getVariableNames = vertical => {
if (vertical) {
return ['clientHeight', 'screenY', 'height'];
}
return ['clientWidth', 'screenX', 'width'];
};
class PanelSplitter extends ShadowElement {
constructor() {
super();
const selectionchange = () => window.getSelection().removeAllRanges();
this.addEventListener('mousedown', mouseDownEvent => {
if (mouseDownEvent.button !== 0) {
return;
}
const {previousElementSibling, nextElementSibling, vertical} = this;
const [clientSize, eventVariable, styleVariable] = getVariableNames(vertical);
const originalPosition = mouseDownEvent[eventVariable];
const originalNextSize = nextElementSibling[clientSize];
const totalSize = previousElementSibling[clientSize] + originalNextSize;
const cleanupFns = [
() => this.dispatchEvent(new Event('moved'))
];
const handlers = {
mousemove: event => {
const requestNext = originalPosition + originalNextSize - event[eventVariable];
let calcNext = calculateSize(requestNext, this.minNext, this.maxNext, this.snapNext);
const requestPrevious = totalSize - calcNext;
const calcPrevious = calculateSize(requestPrevious, this.minPrev, this.maxPrev, this.snapPrev);
if (requestPrevious !== calcPrevious) {
calcNext = totalSize - calcPrevious;
}
if (this.adjust !== 'after') {
previousElementSibling.style[styleVariable] = `${calcPrevious}px`;
}
if (this.adjust !== 'before') {
nextElementSibling.style[styleVariable] = `${calcNext}px`;
}
}
};
for (const type of ['blur', 'mouseup', 'mouseleave']) {
handlers[type] = () => runCallbacks(cleanupFns);
}
selectionchange();
cleanupFns.push(
...this[createBoundEventListeners](document, {selectionchange}),
...this[createBoundEventListeners](window, handlers)
);
});
}
static [adoptedStyleSheets] = [
css`
:host {
cursor: col-resize;
user-select: none;
min-width: 4px;
min-height: 4px;
}
:host([vertical]) {
cursor: row-resize;
}
`
];
get [template]() {
return html``;
}
}
reflectBooleanProperties(PanelSplitter, ['vertical']);
reflectStringProperties(PanelSplitter, {adjust: 'both'});
reflectNumericProperties(PanelSplitter, {
snapPrev: 8,
minPrev: 0,
maxPrev: 0,
snapNext: 8,
minNext: 0,
maxNext: 0
});
PanelSplitter[define]('panel-splitter');