@mintplayer/ng-bootstrap 21.22.0 → 21.23.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/fesm2022/mintplayer-ng-bootstrap-accordion.mjs +20 -20
- package/fesm2022/mintplayer-ng-bootstrap-accordion.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-alert.mjs +8 -8
- package/fesm2022/mintplayer-ng-bootstrap-alert.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-badge.mjs +5 -5
- package/fesm2022/mintplayer-ng-bootstrap-badge.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-breadcrumb.mjs +6 -6
- package/fesm2022/mintplayer-ng-bootstrap-breadcrumb.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-button-group.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-button-group.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-button-type.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-button-type.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-calendar-month.mjs +9 -9
- package/fesm2022/mintplayer-ng-bootstrap-calendar-month.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-calendar.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-calendar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-card.mjs +8 -8
- package/fesm2022/mintplayer-ng-bootstrap-card.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-carousel.mjs +25 -25
- package/fesm2022/mintplayer-ng-bootstrap-carousel.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-close.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-close.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-code-snippet.mjs +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-code-snippet.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-color-picker.mjs +58 -58
- package/fesm2022/mintplayer-ng-bootstrap-color-picker.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-container.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-container.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-context-menu.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-context-menu.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-copy.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-copy.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-datatable.mjs +20 -20
- package/fesm2022/mintplayer-ng-bootstrap-datatable.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-datepicker.mjs +6 -6
- package/fesm2022/mintplayer-ng-bootstrap-datepicker.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-dock.mjs +789 -1175
- package/fesm2022/mintplayer-ng-bootstrap-dock.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-dropdown-divider.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-dropdown-divider.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-dropdown-menu.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-dropdown-menu.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-dropdown.mjs +15 -15
- package/fesm2022/mintplayer-ng-bootstrap-dropdown.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-enhanced-paste.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-enhanced-paste.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-enum.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-enum.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-file-upload.mjs +16 -16
- package/fesm2022/mintplayer-ng-bootstrap-file-upload.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-floating-labels.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-floating-labels.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-font-color.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-font-color.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-for.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-for.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-form.mjs +11 -11
- package/fesm2022/mintplayer-ng-bootstrap-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-grid.mjs +26 -26
- package/fesm2022/mintplayer-ng-bootstrap-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-has-overlay.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-has-overlay.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-has-property.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-has-property.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-in-list.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-in-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-input-group.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-input-group.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-instance-of.mjs +14 -14
- package/fesm2022/mintplayer-ng-bootstrap-instance-of.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-let.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-let.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-linify.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-linify.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-list-group.mjs +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-list-group.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-markdown.mjs +12 -12
- package/fesm2022/mintplayer-ng-bootstrap-markdown.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-marquee.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-marquee.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-modal.mjs +24 -24
- package/fesm2022/mintplayer-ng-bootstrap-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-multiselect.mjs +24 -24
- package/fesm2022/mintplayer-ng-bootstrap-multiselect.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-navbar-toggler.mjs +5 -5
- package/fesm2022/mintplayer-ng-bootstrap-navbar-toggler.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-navbar.mjs +58 -58
- package/fesm2022/mintplayer-ng-bootstrap-navbar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-navigation-lock.mjs +8 -8
- package/fesm2022/mintplayer-ng-bootstrap-navigation-lock.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-no-noscript.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-no-noscript.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-offcanvas.mjs +40 -40
- package/fesm2022/mintplayer-ng-bootstrap-offcanvas.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-ordinal-number.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-ordinal-number.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-pagination.mjs +12 -12
- package/fesm2022/mintplayer-ng-bootstrap-pagination.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-parallax.mjs +6 -6
- package/fesm2022/mintplayer-ng-bootstrap-parallax.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-placeholder.mjs +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-placeholder.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-playlist-toggler.mjs +5 -5
- package/fesm2022/mintplayer-ng-bootstrap-playlist-toggler.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-popover.mjs +20 -20
- package/fesm2022/mintplayer-ng-bootstrap-popover.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-priority-nav.mjs +30 -30
- package/fesm2022/mintplayer-ng-bootstrap-priority-nav.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-progress-bar.mjs +17 -17
- package/fesm2022/mintplayer-ng-bootstrap-progress-bar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-range.mjs +9 -9
- package/fesm2022/mintplayer-ng-bootstrap-range.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-rating.mjs +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-rating.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-resizable.mjs +25 -25
- package/fesm2022/mintplayer-ng-bootstrap-resizable.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-scheduler.mjs +16 -16
- package/fesm2022/mintplayer-ng-bootstrap-scheduler.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-scrollspy.mjs +14 -14
- package/fesm2022/mintplayer-ng-bootstrap-scrollspy.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-searchbox.mjs +24 -24
- package/fesm2022/mintplayer-ng-bootstrap-searchbox.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-select.mjs +19 -19
- package/fesm2022/mintplayer-ng-bootstrap-select.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-select2.mjs +20 -20
- package/fesm2022/mintplayer-ng-bootstrap-select2.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-shell.mjs +11 -11
- package/fesm2022/mintplayer-ng-bootstrap-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-signature-pad.mjs +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-signature-pad.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-slugify.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-slugify.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-spinner.mjs +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-spinner.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-split-string.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-split-string.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-sticky-footer.mjs +6 -6
- package/fesm2022/mintplayer-ng-bootstrap-sticky-footer.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-tab-control.mjs +57 -67
- package/fesm2022/mintplayer-ng-bootstrap-tab-control.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-table.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-table.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-timepicker.mjs +8 -8
- package/fesm2022/mintplayer-ng-bootstrap-timepicker.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-toast.mjs +24 -24
- package/fesm2022/mintplayer-ng-bootstrap-toast.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-toggle-button.mjs +22 -22
- package/fesm2022/mintplayer-ng-bootstrap-toggle-button.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-tooltip.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-tooltip.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-treeview.mjs +14 -14
- package/fesm2022/mintplayer-ng-bootstrap-treeview.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-trust-html.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-trust-html.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-typeahead.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-typeahead.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-uc-first.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-uc-first.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-user-agent.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-user-agent.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-viewport.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-viewport.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-virtual-datatable.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-virtual-datatable.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-web-components-scheduler-core.mjs +1356 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-scheduler-core.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-scheduler.mjs +3819 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-scheduler.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-splitter.mjs +731 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-splitter.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-tab-control.mjs +549 -0
- package/fesm2022/mintplayer-ng-bootstrap-web-components-tab-control.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-bootstrap-word-count.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-word-count.mjs.map +1 -1
- package/package.json +20 -6
- package/types/mintplayer-ng-bootstrap-dock.d.ts +55 -19
- package/types/mintplayer-ng-bootstrap-scheduler.d.ts +2 -2
- package/types/mintplayer-ng-bootstrap-tab-control.d.ts +7 -11
- package/types/mintplayer-ng-bootstrap-web-components-scheduler-core.d.ts +890 -0
- package/types/mintplayer-ng-bootstrap-web-components-scheduler.d.ts +354 -0
- package/types/mintplayer-ng-bootstrap-web-components-splitter.d.ts +165 -0
- package/types/mintplayer-ng-bootstrap-web-components-tab-control.d.ts +95 -0
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
import { unsafeCSS, LitElement, html } from 'lit';
|
|
2
|
+
|
|
3
|
+
var ResizeState;
|
|
4
|
+
(function (ResizeState) {
|
|
5
|
+
ResizeState["Idle"] = "idle";
|
|
6
|
+
ResizeState["Resizing"] = "resizing";
|
|
7
|
+
})(ResizeState || (ResizeState = {}));
|
|
8
|
+
|
|
9
|
+
class SplitterStateManager {
|
|
10
|
+
constructor(initialState) {
|
|
11
|
+
this.listeners = new Set();
|
|
12
|
+
this.state = {
|
|
13
|
+
orientation: 'horizontal',
|
|
14
|
+
panelSizes: [],
|
|
15
|
+
previewSizes: null,
|
|
16
|
+
resizeOperation: null,
|
|
17
|
+
...initialState,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
getState() {
|
|
21
|
+
return { ...this.state };
|
|
22
|
+
}
|
|
23
|
+
subscribe(listener) {
|
|
24
|
+
this.listeners.add(listener);
|
|
25
|
+
return () => {
|
|
26
|
+
this.listeners.delete(listener);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
notifyListeners() {
|
|
30
|
+
const stateCopy = this.getState();
|
|
31
|
+
for (const listener of this.listeners) {
|
|
32
|
+
listener(stateCopy);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
setOrientation(orientation) {
|
|
36
|
+
if (this.state.orientation !== orientation) {
|
|
37
|
+
this.state = { ...this.state, orientation };
|
|
38
|
+
this.notifyListeners();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
setPanelSizes(sizes) {
|
|
42
|
+
this.state = { ...this.state, panelSizes: [...sizes] };
|
|
43
|
+
this.notifyListeners();
|
|
44
|
+
}
|
|
45
|
+
setPreviewSizes(sizes) {
|
|
46
|
+
this.state = { ...this.state, previewSizes: sizes ? [...sizes] : null };
|
|
47
|
+
this.notifyListeners();
|
|
48
|
+
}
|
|
49
|
+
startResize(operation) {
|
|
50
|
+
this.state = {
|
|
51
|
+
...this.state,
|
|
52
|
+
resizeOperation: { ...operation },
|
|
53
|
+
};
|
|
54
|
+
this.notifyListeners();
|
|
55
|
+
}
|
|
56
|
+
updateResize(previewSizes) {
|
|
57
|
+
this.state = {
|
|
58
|
+
...this.state,
|
|
59
|
+
previewSizes: [...previewSizes],
|
|
60
|
+
};
|
|
61
|
+
this.notifyListeners();
|
|
62
|
+
}
|
|
63
|
+
endResize(finalSizes) {
|
|
64
|
+
this.state = {
|
|
65
|
+
...this.state,
|
|
66
|
+
panelSizes: [...finalSizes],
|
|
67
|
+
previewSizes: null,
|
|
68
|
+
resizeOperation: null,
|
|
69
|
+
};
|
|
70
|
+
this.notifyListeners();
|
|
71
|
+
}
|
|
72
|
+
cancelResize() {
|
|
73
|
+
this.state = {
|
|
74
|
+
...this.state,
|
|
75
|
+
previewSizes: null,
|
|
76
|
+
resizeOperation: null,
|
|
77
|
+
};
|
|
78
|
+
this.notifyListeners();
|
|
79
|
+
}
|
|
80
|
+
isResizing() {
|
|
81
|
+
return this.state.resizeOperation?.state === ResizeState.Resizing;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function normalizePointerEvent(event) {
|
|
86
|
+
const isTouch = 'touches' in event;
|
|
87
|
+
let clientX;
|
|
88
|
+
let clientY;
|
|
89
|
+
if (isTouch) {
|
|
90
|
+
const touch = event.touches[0] || event.changedTouches[0];
|
|
91
|
+
clientX = touch.clientX;
|
|
92
|
+
clientY = touch.clientY;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
clientX = event.clientX;
|
|
96
|
+
clientY = event.clientY;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
clientX,
|
|
100
|
+
clientY,
|
|
101
|
+
point: { x: clientX, y: clientY },
|
|
102
|
+
originalEvent: event,
|
|
103
|
+
isTouch,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
class InputHandler {
|
|
108
|
+
constructor(callbacks) {
|
|
109
|
+
this.isActive = false;
|
|
110
|
+
this.currentDividerIndex = -1;
|
|
111
|
+
this.currentDividerElement = null;
|
|
112
|
+
this.callbacks = callbacks;
|
|
113
|
+
this.boundMouseMove = this.handleMouseMove.bind(this);
|
|
114
|
+
this.boundMouseUp = this.handleMouseUp.bind(this);
|
|
115
|
+
this.boundTouchMove = this.handleTouchMove.bind(this);
|
|
116
|
+
this.boundTouchEnd = this.handleTouchEnd.bind(this);
|
|
117
|
+
}
|
|
118
|
+
attachDividerListeners(divider, index) {
|
|
119
|
+
divider.addEventListener('mousedown', (e) => this.handleMouseDown(e, index, divider));
|
|
120
|
+
divider.addEventListener('touchstart', (e) => this.handleTouchStart(e, index, divider), { passive: false });
|
|
121
|
+
}
|
|
122
|
+
handleMouseDown(event, dividerIndex, dividerElement) {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
this.startResize(event, dividerIndex, dividerElement);
|
|
125
|
+
document.addEventListener('mousemove', this.boundMouseMove);
|
|
126
|
+
document.addEventListener('mouseup', this.boundMouseUp);
|
|
127
|
+
}
|
|
128
|
+
handleMouseMove(event) {
|
|
129
|
+
if (!this.isActive)
|
|
130
|
+
return;
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
this.callbacks.onResizeMove(normalizePointerEvent(event));
|
|
133
|
+
}
|
|
134
|
+
handleMouseUp(event) {
|
|
135
|
+
if (!this.isActive)
|
|
136
|
+
return;
|
|
137
|
+
this.endResize(event);
|
|
138
|
+
document.removeEventListener('mousemove', this.boundMouseMove);
|
|
139
|
+
document.removeEventListener('mouseup', this.boundMouseUp);
|
|
140
|
+
}
|
|
141
|
+
handleTouchStart(event, dividerIndex, dividerElement) {
|
|
142
|
+
event.preventDefault();
|
|
143
|
+
this.startResize(event, dividerIndex, dividerElement);
|
|
144
|
+
document.addEventListener('touchmove', this.boundTouchMove, { passive: false });
|
|
145
|
+
document.addEventListener('touchend', this.boundTouchEnd);
|
|
146
|
+
document.addEventListener('touchcancel', this.boundTouchEnd);
|
|
147
|
+
}
|
|
148
|
+
handleTouchMove(event) {
|
|
149
|
+
if (!this.isActive)
|
|
150
|
+
return;
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
this.callbacks.onResizeMove(normalizePointerEvent(event));
|
|
153
|
+
}
|
|
154
|
+
handleTouchEnd(event) {
|
|
155
|
+
if (!this.isActive)
|
|
156
|
+
return;
|
|
157
|
+
this.endResize(event);
|
|
158
|
+
document.removeEventListener('touchmove', this.boundTouchMove);
|
|
159
|
+
document.removeEventListener('touchend', this.boundTouchEnd);
|
|
160
|
+
document.removeEventListener('touchcancel', this.boundTouchEnd);
|
|
161
|
+
}
|
|
162
|
+
startResize(event, dividerIndex, dividerElement) {
|
|
163
|
+
this.isActive = true;
|
|
164
|
+
this.currentDividerIndex = dividerIndex;
|
|
165
|
+
this.currentDividerElement = dividerElement;
|
|
166
|
+
this.callbacks.onResizeStart(normalizePointerEvent(event), dividerIndex, dividerElement);
|
|
167
|
+
}
|
|
168
|
+
endResize(event) {
|
|
169
|
+
this.callbacks.onResizeEnd(normalizePointerEvent(event));
|
|
170
|
+
this.isActive = false;
|
|
171
|
+
this.currentDividerIndex = -1;
|
|
172
|
+
this.currentDividerElement = null;
|
|
173
|
+
}
|
|
174
|
+
dispose() {
|
|
175
|
+
document.removeEventListener('mousemove', this.boundMouseMove);
|
|
176
|
+
document.removeEventListener('mouseup', this.boundMouseUp);
|
|
177
|
+
document.removeEventListener('touchmove', this.boundTouchMove);
|
|
178
|
+
document.removeEventListener('touchend', this.boundTouchEnd);
|
|
179
|
+
document.removeEventListener('touchcancel', this.boundTouchEnd);
|
|
180
|
+
this.isActive = false;
|
|
181
|
+
this.currentDividerIndex = -1;
|
|
182
|
+
this.currentDividerElement = null;
|
|
183
|
+
}
|
|
184
|
+
getIsActive() {
|
|
185
|
+
return this.isActive;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
class ResizeManager {
|
|
190
|
+
constructor(options = {}) {
|
|
191
|
+
this.options = {
|
|
192
|
+
minPanelSize: options.minPanelSize ?? 50,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
computePanelSizes(panels, orientation) {
|
|
196
|
+
return panels.map((panel) => {
|
|
197
|
+
const rect = panel.getBoundingClientRect();
|
|
198
|
+
return orientation === 'horizontal' ? rect.width : rect.height;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
createResizeOperation(startPoint, currentSizes, dividerIndex, dividerElement) {
|
|
202
|
+
return {
|
|
203
|
+
state: ResizeState.Resizing,
|
|
204
|
+
startPosition: { ...startPoint },
|
|
205
|
+
sizes: [...currentSizes],
|
|
206
|
+
indexBefore: dividerIndex,
|
|
207
|
+
indexAfter: dividerIndex + 1,
|
|
208
|
+
dividerElement,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
calculatePreviewSizes(operation, currentPoint, orientation) {
|
|
212
|
+
const { startPosition, sizes, indexBefore, indexAfter } = operation;
|
|
213
|
+
const delta = orientation === 'horizontal'
|
|
214
|
+
? currentPoint.x - startPosition.x
|
|
215
|
+
: currentPoint.y - startPosition.y;
|
|
216
|
+
const newSizes = [...sizes];
|
|
217
|
+
const sizeBefore = sizes[indexBefore];
|
|
218
|
+
const sizeAfter = sizes[indexAfter];
|
|
219
|
+
let newSizeBefore = sizeBefore + delta;
|
|
220
|
+
let newSizeAfter = sizeAfter - delta;
|
|
221
|
+
// Apply minimum size constraints
|
|
222
|
+
if (newSizeBefore < this.options.minPanelSize) {
|
|
223
|
+
const adjustment = this.options.minPanelSize - newSizeBefore;
|
|
224
|
+
newSizeBefore = this.options.minPanelSize;
|
|
225
|
+
newSizeAfter -= adjustment;
|
|
226
|
+
}
|
|
227
|
+
if (newSizeAfter < this.options.minPanelSize) {
|
|
228
|
+
const adjustment = this.options.minPanelSize - newSizeAfter;
|
|
229
|
+
newSizeAfter = this.options.minPanelSize;
|
|
230
|
+
newSizeBefore -= adjustment;
|
|
231
|
+
}
|
|
232
|
+
// Final clamp
|
|
233
|
+
newSizeBefore = Math.max(newSizeBefore, this.options.minPanelSize);
|
|
234
|
+
newSizeAfter = Math.max(newSizeAfter, this.options.minPanelSize);
|
|
235
|
+
newSizes[indexBefore] = newSizeBefore;
|
|
236
|
+
newSizes[indexAfter] = newSizeAfter;
|
|
237
|
+
return newSizes;
|
|
238
|
+
}
|
|
239
|
+
setMinPanelSize(size) {
|
|
240
|
+
this.options.minPanelSize = size;
|
|
241
|
+
}
|
|
242
|
+
getMinPanelSize() {
|
|
243
|
+
return this.options.minPanelSize;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// AUTO-GENERATED — do not edit by hand.
|
|
248
|
+
// Source: splitter.styles.scss
|
|
249
|
+
// Regenerate with the codegen-wc Nx target.
|
|
250
|
+
const splitterStyles = unsafeCSS(`:host {
|
|
251
|
+
display: block;
|
|
252
|
+
width: 100%;
|
|
253
|
+
height: 100%;
|
|
254
|
+
--mp-splitter-size: 8px;
|
|
255
|
+
--mp-splitter-thumb-margin: 3px;
|
|
256
|
+
--mp-splitter-divider-color: #eee;
|
|
257
|
+
--mp-splitter-divider-hover-color: #1389fd;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
:host([touch-mode]) {
|
|
261
|
+
--mp-splitter-thumb-margin: 20px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
* {
|
|
265
|
+
box-sizing: border-box;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.splitter-container {
|
|
269
|
+
display: flex;
|
|
270
|
+
width: 100%;
|
|
271
|
+
height: 100%;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.splitter-container.horizontal {
|
|
275
|
+
flex-direction: row;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.splitter-container.vertical {
|
|
279
|
+
flex-direction: column;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.panel-wrapper {
|
|
283
|
+
overflow: hidden;
|
|
284
|
+
position: relative;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.panel-wrapper.flex-grow {
|
|
288
|
+
flex: 1 1 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/* Divider base styles */
|
|
292
|
+
.divider {
|
|
293
|
+
flex-shrink: 0;
|
|
294
|
+
transition: background-color 0.15s ease-in-out;
|
|
295
|
+
z-index: 3;
|
|
296
|
+
touch-action: none;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.divider::before {
|
|
300
|
+
content: "";
|
|
301
|
+
display: block;
|
|
302
|
+
background-color: var(--mp-splitter-divider-color);
|
|
303
|
+
background-position: center center;
|
|
304
|
+
background-repeat: no-repeat;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.divider:hover::before,
|
|
308
|
+
.divider.active::before {
|
|
309
|
+
background-color: var(--mp-splitter-divider-hover-color);
|
|
310
|
+
border-radius: calc(var(--mp-splitter-size) / 2);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Horizontal splitter styles */
|
|
314
|
+
.splitter-container.horizontal > .divider {
|
|
315
|
+
width: calc(var(--mp-splitter-size) + 2 * var(--mp-splitter-thumb-margin));
|
|
316
|
+
height: 100%;
|
|
317
|
+
cursor: col-resize;
|
|
318
|
+
border-left: var(--mp-splitter-thumb-margin) solid transparent;
|
|
319
|
+
border-right: var(--mp-splitter-thumb-margin) solid transparent;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.splitter-container.horizontal > .divider::before {
|
|
323
|
+
height: 100%;
|
|
324
|
+
width: var(--mp-splitter-size);
|
|
325
|
+
margin: 0 auto;
|
|
326
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.splitter-container.horizontal > .panel-wrapper:not(:first-child) {
|
|
330
|
+
margin-left: calc(-1 * var(--mp-splitter-thumb-margin));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.splitter-container.horizontal > .panel-wrapper:not(:last-child) {
|
|
334
|
+
margin-right: calc(-1 * var(--mp-splitter-thumb-margin));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* Vertical splitter styles */
|
|
338
|
+
.splitter-container.vertical > .divider {
|
|
339
|
+
width: 100%;
|
|
340
|
+
height: calc(var(--mp-splitter-size) + 2 * var(--mp-splitter-thumb-margin));
|
|
341
|
+
cursor: row-resize;
|
|
342
|
+
border-top: var(--mp-splitter-thumb-margin) solid transparent;
|
|
343
|
+
border-bottom: var(--mp-splitter-thumb-margin) solid transparent;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.splitter-container.vertical > .divider::before {
|
|
347
|
+
height: var(--mp-splitter-size);
|
|
348
|
+
width: 100%;
|
|
349
|
+
margin: auto 0;
|
|
350
|
+
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFCAMAAABl/6zIAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAABRJREFUeAFjYGRkwIMJSeMHlBkOABP7AEGzSuPKAAAAAElFTkSuQmCC);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.splitter-container.vertical > .panel-wrapper:not(:first-child) {
|
|
354
|
+
margin-top: calc(-1 * var(--mp-splitter-thumb-margin));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.splitter-container.vertical > .panel-wrapper:not(:last-child) {
|
|
358
|
+
margin-bottom: calc(-1 * var(--mp-splitter-thumb-margin));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* Resizing state */
|
|
362
|
+
:host([resizing]) .splitter-container {
|
|
363
|
+
cursor: col-resize;
|
|
364
|
+
user-select: none;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
:host([resizing]) .splitter-container.vertical {
|
|
368
|
+
cursor: row-resize;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* Slot content styling */
|
|
372
|
+
::slotted(*) {
|
|
373
|
+
width: 100%;
|
|
374
|
+
height: 100%;
|
|
375
|
+
}`);
|
|
376
|
+
|
|
377
|
+
class MpSplitter extends LitElement {
|
|
378
|
+
static { this.styles = [splitterStyles]; }
|
|
379
|
+
static get observedAttributes() {
|
|
380
|
+
return [
|
|
381
|
+
...(super.observedAttributes ?? []),
|
|
382
|
+
'orientation',
|
|
383
|
+
'min-panel-size',
|
|
384
|
+
'touch-mode',
|
|
385
|
+
];
|
|
386
|
+
}
|
|
387
|
+
constructor() {
|
|
388
|
+
super();
|
|
389
|
+
this.container = null;
|
|
390
|
+
this.panelWrappers = [];
|
|
391
|
+
this.dividers = [];
|
|
392
|
+
this.slotElement = null;
|
|
393
|
+
this.mutationObserver = null;
|
|
394
|
+
this.containerResizeObserver = null;
|
|
395
|
+
this.unsubscribeState = null;
|
|
396
|
+
this.stateManager = new SplitterStateManager();
|
|
397
|
+
this.resizeManager = new ResizeManager();
|
|
398
|
+
this.inputHandler = new InputHandler({
|
|
399
|
+
onResizeStart: this.handleResizeStart.bind(this),
|
|
400
|
+
onResizeMove: this.handleResizeMove.bind(this),
|
|
401
|
+
onResizeEnd: this.handleResizeEnd.bind(this),
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
render() {
|
|
405
|
+
return html `
|
|
406
|
+
<div class="splitter-container"></div>
|
|
407
|
+
<slot></slot>
|
|
408
|
+
`;
|
|
409
|
+
}
|
|
410
|
+
firstUpdated() {
|
|
411
|
+
this.container = this.shadowRoot.querySelector('.splitter-container');
|
|
412
|
+
this.container.classList.add(this.orientation);
|
|
413
|
+
this.slotElement = this.shadowRoot.querySelector('slot');
|
|
414
|
+
// Hide the default slot - we'll project content ourselves via named slots.
|
|
415
|
+
this.slotElement.style.display = 'none';
|
|
416
|
+
this.slotElement.addEventListener('slotchange', () => {
|
|
417
|
+
this.updatePanelsFromSlot();
|
|
418
|
+
});
|
|
419
|
+
this.setupMutationObserver();
|
|
420
|
+
this.subscribeToState();
|
|
421
|
+
this.setupContainerResizeObserver();
|
|
422
|
+
// Initial setup after first render
|
|
423
|
+
requestAnimationFrame(() => {
|
|
424
|
+
this.updatePanelsFromSlot();
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
disconnectedCallback() {
|
|
428
|
+
this.inputHandler.dispose();
|
|
429
|
+
if (this.mutationObserver) {
|
|
430
|
+
this.mutationObserver.disconnect();
|
|
431
|
+
this.mutationObserver = null;
|
|
432
|
+
}
|
|
433
|
+
if (this.containerResizeObserver) {
|
|
434
|
+
this.containerResizeObserver.disconnect();
|
|
435
|
+
this.containerResizeObserver = null;
|
|
436
|
+
}
|
|
437
|
+
if (this.unsubscribeState) {
|
|
438
|
+
this.unsubscribeState();
|
|
439
|
+
this.unsubscribeState = null;
|
|
440
|
+
}
|
|
441
|
+
super.disconnectedCallback();
|
|
442
|
+
}
|
|
443
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
444
|
+
super.attributeChangedCallback(name, oldValue, newValue);
|
|
445
|
+
if (oldValue === newValue)
|
|
446
|
+
return;
|
|
447
|
+
switch (name) {
|
|
448
|
+
case 'orientation':
|
|
449
|
+
this.stateManager.setOrientation(newValue || 'horizontal');
|
|
450
|
+
this.updateContainerOrientation();
|
|
451
|
+
break;
|
|
452
|
+
case 'min-panel-size':
|
|
453
|
+
const parsedSize = newValue ? parseInt(newValue, 10) : 50;
|
|
454
|
+
this.resizeManager.setMinPanelSize(!isNaN(parsedSize) ? parsedSize : 50);
|
|
455
|
+
break;
|
|
456
|
+
case 'touch-mode':
|
|
457
|
+
// Handled by CSS via :host([touch-mode])
|
|
458
|
+
break;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// Public API
|
|
462
|
+
get orientation() {
|
|
463
|
+
return this.getAttribute('orientation') || 'horizontal';
|
|
464
|
+
}
|
|
465
|
+
set orientation(value) {
|
|
466
|
+
this.setAttribute('orientation', value);
|
|
467
|
+
}
|
|
468
|
+
get minPanelSize() {
|
|
469
|
+
const attr = this.getAttribute('min-panel-size');
|
|
470
|
+
return attr ? parseInt(attr, 10) : 50;
|
|
471
|
+
}
|
|
472
|
+
set minPanelSize(value) {
|
|
473
|
+
this.setAttribute('min-panel-size', String(value));
|
|
474
|
+
}
|
|
475
|
+
get touchMode() {
|
|
476
|
+
return this.hasAttribute('touch-mode');
|
|
477
|
+
}
|
|
478
|
+
set touchMode(value) {
|
|
479
|
+
if (value) {
|
|
480
|
+
this.setAttribute('touch-mode', '');
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
this.removeAttribute('touch-mode');
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
getPanelSizes() {
|
|
487
|
+
return this.stateManager.getState().panelSizes;
|
|
488
|
+
}
|
|
489
|
+
setPanelSizes(sizes) {
|
|
490
|
+
this.applyPanelSizes(sizes);
|
|
491
|
+
this.stateManager.setPanelSizes(sizes);
|
|
492
|
+
}
|
|
493
|
+
// Private methods
|
|
494
|
+
setupMutationObserver() {
|
|
495
|
+
this.mutationObserver = new MutationObserver(() => {
|
|
496
|
+
this.updatePanelsFromSlot();
|
|
497
|
+
});
|
|
498
|
+
this.mutationObserver.observe(this, {
|
|
499
|
+
childList: true,
|
|
500
|
+
subtree: false,
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
subscribeToState() {
|
|
504
|
+
this.unsubscribeState = this.stateManager.subscribe((state) => {
|
|
505
|
+
if (state.resizeOperation) {
|
|
506
|
+
this.setAttribute('resizing', '');
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
this.removeAttribute('resizing');
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
updatePanelsFromSlot() {
|
|
514
|
+
if (!this.container)
|
|
515
|
+
return;
|
|
516
|
+
const children = Array.from(this.children).filter((child) => child instanceof HTMLElement);
|
|
517
|
+
if (children.length === 0)
|
|
518
|
+
return;
|
|
519
|
+
// Clear existing wrappers and dividers
|
|
520
|
+
this.container.innerHTML = '';
|
|
521
|
+
this.panelWrappers = [];
|
|
522
|
+
this.dividers = [];
|
|
523
|
+
// Create panel wrappers with slots for each child
|
|
524
|
+
children.forEach((child, index) => {
|
|
525
|
+
const wrapper = document.createElement('div');
|
|
526
|
+
wrapper.className = 'panel-wrapper flex-grow';
|
|
527
|
+
// Create a named slot for this child
|
|
528
|
+
const namedSlot = document.createElement('slot');
|
|
529
|
+
const slotName = `panel-${index}`;
|
|
530
|
+
namedSlot.name = slotName;
|
|
531
|
+
child.slot = slotName;
|
|
532
|
+
wrapper.appendChild(namedSlot);
|
|
533
|
+
this.panelWrappers.push(wrapper);
|
|
534
|
+
this.container.appendChild(wrapper);
|
|
535
|
+
// Add divider between panels
|
|
536
|
+
if (index < children.length - 1) {
|
|
537
|
+
const divider = document.createElement('div');
|
|
538
|
+
divider.className = 'divider';
|
|
539
|
+
this.inputHandler.attachDividerListeners(divider, index);
|
|
540
|
+
this.dividers.push(divider);
|
|
541
|
+
this.container.appendChild(divider);
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
// Re-apply previously-stored sizes when the panel count still matches.
|
|
545
|
+
// Two cases where this matters:
|
|
546
|
+
// 1. setPanelSizes() was called before firstUpdated's raf populated
|
|
547
|
+
// the wrappers (e.g., the dock schedules its own raf inside
|
|
548
|
+
// renderSplit) — without this, the early call is silently dropped.
|
|
549
|
+
// 2. Slot children change after a drag (e.g., layout re-render) — the
|
|
550
|
+
// wrappers get recreated with `flex: 1 1 0` (equal sizes) and would
|
|
551
|
+
// otherwise discard the user's drag result.
|
|
552
|
+
const storedSizes = this.stateManager.getState().panelSizes;
|
|
553
|
+
if (storedSizes.length > 0 && storedSizes.length === this.panelWrappers.length) {
|
|
554
|
+
this.applyPanelSizes(storedSizes);
|
|
555
|
+
// Consumer-supplied sizes (e.g., from the dock's renderSplit) often
|
|
556
|
+
// sum to the full container size because the consumer doesn't know
|
|
557
|
+
// mp-splitter's internal divider widths. Defer one raf so dividers
|
|
558
|
+
// have laid out, then rescale stored sizes against the actual panel
|
|
559
|
+
// space (container - dividers). Without this step ResizeObserver
|
|
560
|
+
// alone can't catch the discrepancy because the container size
|
|
561
|
+
// hasn't changed — only the panel/divider split inside it has.
|
|
562
|
+
requestAnimationFrame(() => this.handleContainerResize());
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
// No stored sizes (or count mismatch) — pin from the measured layout
|
|
566
|
+
// once the browser has run layout for the new wrappers. A nested raf
|
|
567
|
+
// is needed because the wrappers were created in this very turn and
|
|
568
|
+
// their getBoundingClientRect would return 0 if read synchronously.
|
|
569
|
+
requestAnimationFrame(() => {
|
|
570
|
+
const current = this.stateManager.getState().panelSizes;
|
|
571
|
+
if (current.length === this.panelWrappers.length && current.length > 0) {
|
|
572
|
+
// A consumer (e.g., the dock) called setPanelSizes() between our
|
|
573
|
+
// raf scheduling and execution. Honour their values instead of
|
|
574
|
+
// overwriting with measurements.
|
|
575
|
+
this.applyPanelSizes(current);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
this.pinSizesFromCurrentLayout();
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Read each panel-wrapper's measured pixel size and persist it as the
|
|
583
|
+
* authoritative panel size. After this runs, every wrapper carries an
|
|
584
|
+
* inline `width` (or `height`) — content intrinsic size cannot leak into
|
|
585
|
+
* the parent flex container, so a nested splitter's drag does not shift
|
|
586
|
+
* the parent's layout.
|
|
587
|
+
*/
|
|
588
|
+
pinSizesFromCurrentLayout() {
|
|
589
|
+
if (this.panelWrappers.length === 0)
|
|
590
|
+
return;
|
|
591
|
+
const sizeProperty = this.orientation === 'horizontal' ? 'width' : 'height';
|
|
592
|
+
const measured = this.panelWrappers.map((wrapper) => wrapper.getBoundingClientRect()[sizeProperty]);
|
|
593
|
+
// Layout hasn't run yet for these wrappers — bail rather than write
|
|
594
|
+
// 0 px sizes that would collapse every panel.
|
|
595
|
+
if (measured.every((v) => v <= 0))
|
|
596
|
+
return;
|
|
597
|
+
this.applyPanelSizes(measured);
|
|
598
|
+
this.stateManager.setPanelSizes(measured);
|
|
599
|
+
}
|
|
600
|
+
setupContainerResizeObserver() {
|
|
601
|
+
if (!this.container || typeof ResizeObserver === 'undefined')
|
|
602
|
+
return;
|
|
603
|
+
this.containerResizeObserver = new ResizeObserver(() => {
|
|
604
|
+
this.handleContainerResize();
|
|
605
|
+
});
|
|
606
|
+
this.containerResizeObserver.observe(this.container);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* When the splitter's container resizes (window resize, parent splitter
|
|
610
|
+
* pinning its sizes, etc.), scale every panel-wrapper proportionally so
|
|
611
|
+
* the existing ratios are preserved. Without this we'd be stuck with the
|
|
612
|
+
* original pixel sizes when the surrounding viewport changes — what
|
|
613
|
+
* `flex-basis: 0` gave master "for free".
|
|
614
|
+
*/
|
|
615
|
+
handleContainerResize() {
|
|
616
|
+
if (!this.container || this.panelWrappers.length === 0)
|
|
617
|
+
return;
|
|
618
|
+
// applyPanelSizes runs continuously during a drag; its writes can fire
|
|
619
|
+
// ResizeObserver via subpixel rounding. The drag math already keeps
|
|
620
|
+
// panels summing to the container — don't fight it.
|
|
621
|
+
if (this.stateManager.isResizing())
|
|
622
|
+
return;
|
|
623
|
+
const stored = this.stateManager.getState().panelSizes;
|
|
624
|
+
if (stored.length === 0 || stored.length !== this.panelWrappers.length)
|
|
625
|
+
return;
|
|
626
|
+
const rect = this.container.getBoundingClientRect();
|
|
627
|
+
const containerSize = this.orientation === 'horizontal' ? rect.width : rect.height;
|
|
628
|
+
if (containerSize <= 0)
|
|
629
|
+
return;
|
|
630
|
+
const dividerProperty = this.orientation === 'horizontal' ? 'width' : 'height';
|
|
631
|
+
const dividerTotal = this.dividers.reduce((sum, divider) => sum + divider.getBoundingClientRect()[dividerProperty], 0);
|
|
632
|
+
// Adjacent panel-wrappers carry negative margins (`margin-left` /
|
|
633
|
+
// `margin-right` of `-thumb-margin`) so they visually overlap the
|
|
634
|
+
// divider's transparent borders. In the flex calculation those negative
|
|
635
|
+
// margins reduce a divider's effective width contribution; if we ignore
|
|
636
|
+
// them we under-target by 2 * (N-1) * thumb px and the container gets
|
|
637
|
+
// a gap at the trailing edge.
|
|
638
|
+
const startMarginProp = this.orientation === 'horizontal' ? 'marginLeft' : 'marginTop';
|
|
639
|
+
const endMarginProp = this.orientation === 'horizontal' ? 'marginRight' : 'marginBottom';
|
|
640
|
+
const marginTotal = this.panelWrappers.reduce((sum, wrapper) => {
|
|
641
|
+
const cs = getComputedStyle(wrapper);
|
|
642
|
+
return sum + parseFloat(cs[startMarginProp]) + parseFloat(cs[endMarginProp]);
|
|
643
|
+
}, 0);
|
|
644
|
+
const targetPanelTotal = Math.max(0, containerSize - dividerTotal - marginTotal);
|
|
645
|
+
const previousPanelTotal = stored.reduce((a, b) => a + b, 0);
|
|
646
|
+
if (previousPanelTotal <= 0)
|
|
647
|
+
return;
|
|
648
|
+
// Below 1 px we'd be amplifying our own subpixel writes. Skip.
|
|
649
|
+
if (Math.abs(targetPanelTotal - previousPanelTotal) < 1)
|
|
650
|
+
return;
|
|
651
|
+
const scale = targetPanelTotal / previousPanelTotal;
|
|
652
|
+
const newSizes = stored.map((s) => s * scale);
|
|
653
|
+
this.applyPanelSizes(newSizes);
|
|
654
|
+
this.stateManager.setPanelSizes(newSizes);
|
|
655
|
+
}
|
|
656
|
+
updateContainerOrientation() {
|
|
657
|
+
if (!this.container)
|
|
658
|
+
return;
|
|
659
|
+
this.container.className = `splitter-container ${this.orientation}`;
|
|
660
|
+
}
|
|
661
|
+
handleResizeStart(event, dividerIndex, dividerElement) {
|
|
662
|
+
const sizes = this.resizeManager.computePanelSizes(this.panelWrappers, this.orientation);
|
|
663
|
+
const operation = this.resizeManager.createResizeOperation(event.point, sizes, dividerIndex, dividerElement);
|
|
664
|
+
this.stateManager.startResize(operation);
|
|
665
|
+
dividerElement.classList.add('active');
|
|
666
|
+
this.dispatchEvent(new CustomEvent('resize-start', {
|
|
667
|
+
bubbles: true,
|
|
668
|
+
detail: {
|
|
669
|
+
sizes,
|
|
670
|
+
orientation: this.orientation,
|
|
671
|
+
},
|
|
672
|
+
}));
|
|
673
|
+
}
|
|
674
|
+
handleResizeMove(event) {
|
|
675
|
+
const state = this.stateManager.getState();
|
|
676
|
+
if (!state.resizeOperation)
|
|
677
|
+
return;
|
|
678
|
+
const previewSizes = this.resizeManager.calculatePreviewSizes(state.resizeOperation, event.point, this.orientation);
|
|
679
|
+
this.stateManager.updateResize(previewSizes);
|
|
680
|
+
this.applyPanelSizes(previewSizes);
|
|
681
|
+
this.dispatchEvent(new CustomEvent('resizing', {
|
|
682
|
+
bubbles: true,
|
|
683
|
+
detail: {
|
|
684
|
+
sizes: previewSizes,
|
|
685
|
+
orientation: this.orientation,
|
|
686
|
+
},
|
|
687
|
+
}));
|
|
688
|
+
}
|
|
689
|
+
handleResizeEnd(_event) {
|
|
690
|
+
const state = this.stateManager.getState();
|
|
691
|
+
if (!state.resizeOperation)
|
|
692
|
+
return;
|
|
693
|
+
const finalSizes = state.previewSizes || state.resizeOperation.sizes;
|
|
694
|
+
if (state.resizeOperation.dividerElement) {
|
|
695
|
+
state.resizeOperation.dividerElement.classList.remove('active');
|
|
696
|
+
}
|
|
697
|
+
this.stateManager.endResize(finalSizes);
|
|
698
|
+
this.dispatchEvent(new CustomEvent('resize-end', {
|
|
699
|
+
bubbles: true,
|
|
700
|
+
detail: {
|
|
701
|
+
sizes: finalSizes,
|
|
702
|
+
orientation: this.orientation,
|
|
703
|
+
},
|
|
704
|
+
}));
|
|
705
|
+
}
|
|
706
|
+
applyPanelSizes(sizes) {
|
|
707
|
+
const sizeProperty = this.orientation === 'horizontal' ? 'width' : 'height';
|
|
708
|
+
const resetProperty = this.orientation === 'horizontal' ? 'height' : 'width';
|
|
709
|
+
this.panelWrappers.forEach((wrapper, index) => {
|
|
710
|
+
if (sizes[index] !== undefined) {
|
|
711
|
+
wrapper.style[sizeProperty] = `${sizes[index]}px`;
|
|
712
|
+
wrapper.style[resetProperty] = '';
|
|
713
|
+
wrapper.classList.remove('flex-grow');
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
// Auto-register the custom element
|
|
719
|
+
if (typeof customElements !== 'undefined' &&
|
|
720
|
+
!customElements.get('mp-splitter')) {
|
|
721
|
+
customElements.define('mp-splitter', MpSplitter);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// Main component export
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Generated bundle index. Do not edit.
|
|
728
|
+
*/
|
|
729
|
+
|
|
730
|
+
export { InputHandler, MpSplitter, ResizeManager, ResizeState, SplitterStateManager, normalizePointerEvent, splitterStyles };
|
|
731
|
+
//# sourceMappingURL=mintplayer-ng-bootstrap-web-components-splitter.mjs.map
|