@mintplayer/ng-bootstrap 20.6.1 → 20.6.3
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/dock/index.d.ts +19 -0
- package/fesm2022/mintplayer-ng-bootstrap-accordion.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-accordion.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-alert.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-alert.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-async-host-binding.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-badge.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-badge.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-breadcrumb.mjs +10 -10
- 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 +3 -3
- 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 +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-calendar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-card.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-card.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-carousel.mjs +13 -13
- 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 +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-code-snippet.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-color-picker.mjs +28 -28
- 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 +7 -7
- package/fesm2022/mintplayer-ng-bootstrap-context-menu.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-copy.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-copy.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-datatable.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-datatable.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-datepicker.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-datepicker.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-dock.mjs +769 -15
- 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 +13 -13
- 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 +13 -13
- 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 +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-for.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-form.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-grid.mjs +19 -19
- package/fesm2022/mintplayer-ng-bootstrap-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-has-id.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-has-overlay.mjs +3 -3
- 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 +16 -16
- package/fesm2022/mintplayer-ng-bootstrap-instance-of.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-let.mjs +3 -3
- 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 +10 -10
- 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 +25 -25
- package/fesm2022/mintplayer-ng-bootstrap-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-multiselect.mjs +16 -16
- package/fesm2022/mintplayer-ng-bootstrap-multiselect.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-navbar-toggler.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-navbar-toggler.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-navbar.mjs +31 -31
- package/fesm2022/mintplayer-ng-bootstrap-navbar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-navigation-lock.mjs +10 -10
- 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 +157 -203
- 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 +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-pagination.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-parallax.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-parallax.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-placeholder.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-placeholder.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-playlist-toggler.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-playlist-toggler.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-popover.mjs +16 -16
- package/fesm2022/mintplayer-ng-bootstrap-popover.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-progress-bar.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-progress-bar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-range.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-range.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-rating.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-rating.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-resizable.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-resizable.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-scheduler.mjs +25 -25
- package/fesm2022/mintplayer-ng-bootstrap-scheduler.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-scrollspy.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-scrollspy.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-searchbox.mjs +16 -16
- package/fesm2022/mintplayer-ng-bootstrap-searchbox.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-select.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-select.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-select2.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-select2.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-shell.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-signature-pad.mjs +3 -3
- 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 +4 -4
- 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-splitter.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-splitter.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-sticky-footer.mjs +10 -10
- package/fesm2022/mintplayer-ng-bootstrap-sticky-footer.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-tab-control.mjs +13 -13
- package/fesm2022/mintplayer-ng-bootstrap-tab-control.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-table.mjs +4 -4
- package/fesm2022/mintplayer-ng-bootstrap-table.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-timepicker.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-timepicker.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-toast.mjs +25 -25
- package/fesm2022/mintplayer-ng-bootstrap-toast.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap-toggle-button.mjs +13 -13
- 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 +10 -10
- 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 +3 -3
- 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-word-count.mjs +3 -3
- package/fesm2022/mintplayer-ng-bootstrap-word-count.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-bootstrap.mjs.map +1 -1
- package/offcanvas/index.d.ts +41 -59
- package/package.json +12 -12
|
@@ -9,10 +9,10 @@ class BsDockPaneComponent {
|
|
|
9
9
|
throw new Error('bs-dock-pane requires a unique "name" input.');
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
13
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.
|
|
12
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockPaneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
13
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.13", type: BsDockPaneComponent, isStandalone: false, selector: "bs-dock-pane", inputs: { name: "name", title: "title" }, viewQueries: [{ propertyName: "template", first: true, predicate: TemplateRef, descendants: true, static: true }], ngImport: i0, template: `<ng-template><ng-content></ng-content></ng-template>`, isInline: true }); }
|
|
14
14
|
}
|
|
15
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
15
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockPaneComponent, decorators: [{
|
|
16
16
|
type: Component,
|
|
17
17
|
args: [{
|
|
18
18
|
selector: 'bs-dock-pane',
|
|
@@ -39,6 +39,7 @@ const templateHtml = `
|
|
|
39
39
|
box-sizing: border-box;
|
|
40
40
|
font-family: inherit;
|
|
41
41
|
color: inherit;
|
|
42
|
+
--dock-split-gap: 0.25rem;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
.dock-root,
|
|
@@ -73,6 +74,13 @@ const templateHtml = `
|
|
|
73
74
|
z-index: 5;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
.dock-intersections-layer {
|
|
78
|
+
position: absolute;
|
|
79
|
+
inset: 0;
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
z-index: 120;
|
|
82
|
+
}
|
|
83
|
+
|
|
76
84
|
.dock-floating {
|
|
77
85
|
position: absolute;
|
|
78
86
|
display: flex;
|
|
@@ -127,7 +135,8 @@ const templateHtml = `
|
|
|
127
135
|
transition: background 120ms ease;
|
|
128
136
|
}
|
|
129
137
|
|
|
130
|
-
.dock-floating__resizer:hover
|
|
138
|
+
.dock-floating__resizer:hover,
|
|
139
|
+
.dock-floating__resizer[data-resizing='true'] {
|
|
131
140
|
background: rgba(148, 163, 184, 0.4);
|
|
132
141
|
}
|
|
133
142
|
|
|
@@ -200,7 +209,7 @@ const templateHtml = `
|
|
|
200
209
|
.dock-split {
|
|
201
210
|
display: flex;
|
|
202
211
|
flex: 1 1 0;
|
|
203
|
-
gap:
|
|
212
|
+
gap: var(--dock-split-gap);
|
|
204
213
|
position: relative;
|
|
205
214
|
}
|
|
206
215
|
|
|
@@ -228,11 +237,17 @@ const templateHtml = `
|
|
|
228
237
|
.dock-split[data-direction="horizontal"] > .dock-split__divider {
|
|
229
238
|
width: 0.5rem;
|
|
230
239
|
cursor: col-resize;
|
|
240
|
+
/* Extend through perpendicular gaps for visual continuity */
|
|
241
|
+
margin-top: calc(var(--dock-split-gap) * -1);
|
|
242
|
+
margin-bottom: calc(var(--dock-split-gap) * -1);
|
|
231
243
|
}
|
|
232
244
|
|
|
233
245
|
.dock-split[data-direction="vertical"] > .dock-split__divider {
|
|
234
246
|
height: 0.5rem;
|
|
235
247
|
cursor: row-resize;
|
|
248
|
+
/* Extend through perpendicular gaps for visual continuity */
|
|
249
|
+
margin-left: calc(var(--dock-split-gap) * -1);
|
|
250
|
+
margin-right: calc(var(--dock-split-gap) * -1);
|
|
236
251
|
}
|
|
237
252
|
|
|
238
253
|
.dock-split__divider::after {
|
|
@@ -261,6 +276,45 @@ const templateHtml = `
|
|
|
261
276
|
background: rgba(59, 130, 246, 0.35);
|
|
262
277
|
}
|
|
263
278
|
|
|
279
|
+
.dock-intersection-handle {
|
|
280
|
+
position: absolute;
|
|
281
|
+
width: 1rem;
|
|
282
|
+
height: 1rem;
|
|
283
|
+
margin-left: -0.5rem;
|
|
284
|
+
margin-top: -0.5rem;
|
|
285
|
+
border-radius: 0.375rem;
|
|
286
|
+
background: rgba(59, 130, 246, 0.2);
|
|
287
|
+
border: 1px solid rgba(59, 130, 246, 0.6);
|
|
288
|
+
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.2);
|
|
289
|
+
cursor: all-scroll;
|
|
290
|
+
pointer-events: auto;
|
|
291
|
+
opacity: 0;
|
|
292
|
+
transition: background 120ms ease, border-color 120ms ease, opacity 120ms ease;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.dock-intersection-handle:hover,
|
|
296
|
+
.dock-intersection-handle:focus-visible,
|
|
297
|
+
.dock-intersection-handle[data-visible='true'],
|
|
298
|
+
.dock-intersection-handle[data-resizing='true'] {
|
|
299
|
+
background: rgba(59, 130, 246, 0.35);
|
|
300
|
+
border-color: rgba(59, 130, 246, 0.9);
|
|
301
|
+
opacity: 1;
|
|
302
|
+
outline: none;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.dock-snap-marker {
|
|
306
|
+
position: absolute;
|
|
307
|
+
width: 6px;
|
|
308
|
+
height: 6px;
|
|
309
|
+
margin-left: -3px;
|
|
310
|
+
margin-top: -3px;
|
|
311
|
+
border-radius: 50%;
|
|
312
|
+
background: rgba(59, 130, 246, 0.7);
|
|
313
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
|
|
314
|
+
pointer-events: none;
|
|
315
|
+
z-index: 130;
|
|
316
|
+
}
|
|
317
|
+
|
|
264
318
|
.dock-stack {
|
|
265
319
|
display: flex;
|
|
266
320
|
flex-direction: column;
|
|
@@ -409,6 +463,7 @@ const templateHtml = `
|
|
|
409
463
|
<div class="dock-root">
|
|
410
464
|
<div class="dock-docked"></div>
|
|
411
465
|
<div class="dock-floating-layer"></div>
|
|
466
|
+
<div class="dock-intersections-layer dock-intersection-layer"></div>
|
|
412
467
|
</div>
|
|
413
468
|
<div class="dock-drop-indicator"></div>
|
|
414
469
|
<div class="dock-drop-joystick" data-visible="false">
|
|
@@ -477,8 +532,93 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
477
532
|
}
|
|
478
533
|
static get observedAttributes() {
|
|
479
534
|
return ['layout'];
|
|
535
|
+
// return ['layout', 'debug-snap-markers'];
|
|
480
536
|
}
|
|
481
537
|
static { this.instanceCounter = 0; }
|
|
538
|
+
renderSnapMarkersForDivider() {
|
|
539
|
+
if (!this.showSnapMarkers)
|
|
540
|
+
return;
|
|
541
|
+
const layer = this.shadowRoot?.querySelector('.dock-intersections-layer, .dock-intersection-layer');
|
|
542
|
+
if (!layer)
|
|
543
|
+
return;
|
|
544
|
+
// Clear previous
|
|
545
|
+
Array.from(layer.querySelectorAll('.dock-snap-marker')).forEach((el) => el.remove());
|
|
546
|
+
if (!this.resizeState || !this.activeSnapAxis || this.activeSnapTargets.length === 0)
|
|
547
|
+
return;
|
|
548
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
549
|
+
const dRect = this.resizeState.divider.getBoundingClientRect();
|
|
550
|
+
if (this.activeSnapAxis === 'x') {
|
|
551
|
+
const y = dRect.top + dRect.height / 2 - rootRect.top;
|
|
552
|
+
this.activeSnapTargets.forEach((sx) => {
|
|
553
|
+
const dot = this.documentRef.createElement('div');
|
|
554
|
+
dot.className = 'dock-snap-marker';
|
|
555
|
+
dot.style.left = `${rootRect.left + sx - rootRect.left}px`;
|
|
556
|
+
dot.style.top = `${y}px`;
|
|
557
|
+
layer.appendChild(dot);
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
else if (this.activeSnapAxis === 'y') {
|
|
561
|
+
const x = dRect.left + dRect.width / 2 - rootRect.left;
|
|
562
|
+
this.activeSnapTargets.forEach((sy) => {
|
|
563
|
+
const dot = this.documentRef.createElement('div');
|
|
564
|
+
dot.className = 'dock-snap-marker';
|
|
565
|
+
dot.style.left = `${x}px`;
|
|
566
|
+
dot.style.top = `${rootRect.top + sy - rootRect.top}px`;
|
|
567
|
+
layer.appendChild(dot);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
renderSnapMarkersForCorner() {
|
|
572
|
+
if (!this.showSnapMarkers)
|
|
573
|
+
return;
|
|
574
|
+
const layer = this.shadowRoot?.querySelector('.dock-intersections-layer, .dock-intersection-layer');
|
|
575
|
+
if (!layer)
|
|
576
|
+
return;
|
|
577
|
+
Array.from(layer.querySelectorAll('.dock-snap-marker')).forEach((el) => el.remove());
|
|
578
|
+
if (!this.cornerResizeState)
|
|
579
|
+
return;
|
|
580
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
581
|
+
// Compute representative center lines from first entries
|
|
582
|
+
let centerX = null;
|
|
583
|
+
let centerY = null;
|
|
584
|
+
const st = this.cornerResizeState;
|
|
585
|
+
if (st.vs.length > 0) {
|
|
586
|
+
const vRect = st.vs[0].container.querySelector(':scope > .dock-split__divider')?.getBoundingClientRect();
|
|
587
|
+
if (vRect)
|
|
588
|
+
centerX = vRect.left + vRect.width / 2 - rootRect.left;
|
|
589
|
+
}
|
|
590
|
+
if (st.hs.length > 0) {
|
|
591
|
+
const hRect = st.hs[0].container.querySelector(':scope > .dock-split__divider')?.getBoundingClientRect();
|
|
592
|
+
if (hRect)
|
|
593
|
+
centerY = hRect.top + hRect.height / 2 - rootRect.top;
|
|
594
|
+
}
|
|
595
|
+
if (centerY != null) {
|
|
596
|
+
this.cornerSnapXTargets.forEach((sx) => {
|
|
597
|
+
const dot = this.documentRef.createElement('div');
|
|
598
|
+
dot.className = 'dock-snap-marker';
|
|
599
|
+
dot.style.left = `${sx}px`;
|
|
600
|
+
dot.style.top = `${centerY}px`;
|
|
601
|
+
layer.appendChild(dot);
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
if (centerX != null) {
|
|
605
|
+
this.cornerSnapYTargets.forEach((sy) => {
|
|
606
|
+
const dot = this.documentRef.createElement('div');
|
|
607
|
+
dot.className = 'dock-snap-marker';
|
|
608
|
+
dot.style.left = `${centerX}px`;
|
|
609
|
+
dot.style.top = `${sy}px`;
|
|
610
|
+
layer.appendChild(dot);
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
clearSnapMarkers() {
|
|
615
|
+
if (!this.showSnapMarkers)
|
|
616
|
+
return;
|
|
617
|
+
const layer = this.shadowRoot?.querySelector('.dock-intersections-layer, .dock-intersection-layer');
|
|
618
|
+
if (!layer)
|
|
619
|
+
return;
|
|
620
|
+
Array.from(layer.querySelectorAll('.dock-snap-marker')).forEach((el) => el.remove());
|
|
621
|
+
}
|
|
482
622
|
constructor() {
|
|
483
623
|
super();
|
|
484
624
|
this.dropJoystickTarget = null;
|
|
@@ -490,10 +630,22 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
490
630
|
this.dragState = null;
|
|
491
631
|
this.floatingDragState = null;
|
|
492
632
|
this.floatingResizeState = null;
|
|
633
|
+
this.intersectionRaf = null;
|
|
634
|
+
this.intersectionHandles = new Map();
|
|
635
|
+
this.cornerResizeState = null;
|
|
493
636
|
this.pointerTrackingActive = false;
|
|
494
637
|
this.dragPointerTrackingActive = false;
|
|
495
638
|
this.lastDragPointerPosition = null;
|
|
639
|
+
// Localized snapping while dragging a divider
|
|
640
|
+
this.activeSnapAxis = null;
|
|
641
|
+
this.activeSnapTargets = [];
|
|
642
|
+
// Localized snapping while dragging an intersection handle
|
|
643
|
+
this.cornerSnapXTargets = [];
|
|
644
|
+
this.cornerSnapYTargets = [];
|
|
645
|
+
// Debug: render snap markers while dragging
|
|
646
|
+
this.showSnapMarkers = false;
|
|
496
647
|
this.pendingDragEndTimeout = null;
|
|
648
|
+
this.previousSplitSizes = new Map();
|
|
497
649
|
const documentRef = this.resolveDocument();
|
|
498
650
|
this.documentRef = documentRef;
|
|
499
651
|
this.windowRef = this.resolveWindow(documentRef);
|
|
@@ -543,6 +695,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
543
695
|
this.onDragTouchMove = this.onDragTouchMove.bind(this);
|
|
544
696
|
this.onDragMouseUp = this.onDragMouseUp.bind(this);
|
|
545
697
|
this.onDragTouchEnd = this.onDragTouchEnd.bind(this);
|
|
698
|
+
this.onWindowResize = this.onWindowResize.bind(this);
|
|
546
699
|
}
|
|
547
700
|
connectedCallback() {
|
|
548
701
|
if (!this.hasAttribute('role')) {
|
|
@@ -577,6 +730,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
577
730
|
win?.addEventListener('dragover', this.onGlobalDragOver);
|
|
578
731
|
win?.addEventListener('drag', this.onDrag);
|
|
579
732
|
win?.addEventListener('dragend', this.onGlobalDragEnd, true);
|
|
733
|
+
win?.addEventListener('resize', this.onWindowResize);
|
|
580
734
|
}
|
|
581
735
|
disconnectedCallback() {
|
|
582
736
|
this.rootEl.removeEventListener('dragover', this.onDragOver);
|
|
@@ -593,11 +747,19 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
593
747
|
win?.removeEventListener('pointermove', this.onPointerMove);
|
|
594
748
|
win?.removeEventListener('pointerup', this.onPointerUp);
|
|
595
749
|
this.pointerTrackingActive = false;
|
|
750
|
+
const win2 = this.windowRef;
|
|
751
|
+
win2?.removeEventListener('resize', this.onWindowResize);
|
|
596
752
|
}
|
|
597
753
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
598
754
|
if (name === 'layout') {
|
|
599
755
|
this.layout = newValue ? this.parseLayout(newValue) : null;
|
|
600
756
|
}
|
|
757
|
+
else if (name === 'debug-snap-markers') {
|
|
758
|
+
this.showSnapMarkers = !(newValue === null || newValue === 'false' || newValue === '0');
|
|
759
|
+
if (!this.showSnapMarkers) {
|
|
760
|
+
this.clearSnapMarkers();
|
|
761
|
+
}
|
|
762
|
+
}
|
|
601
763
|
}
|
|
602
764
|
get layout() {
|
|
603
765
|
return {
|
|
@@ -673,6 +835,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
673
835
|
this.dockedEl.appendChild(fragment);
|
|
674
836
|
}
|
|
675
837
|
this.renderFloatingPanes();
|
|
838
|
+
this.scheduleRenderIntersectionHandles();
|
|
676
839
|
}
|
|
677
840
|
renderNode(node, path, floatingIndex) {
|
|
678
841
|
if (node.kind === 'split') {
|
|
@@ -767,6 +930,479 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
767
930
|
this.floatingLayerEl.appendChild(wrapper);
|
|
768
931
|
});
|
|
769
932
|
}
|
|
933
|
+
onWindowResize() {
|
|
934
|
+
// Recompute intersection handles on window resize
|
|
935
|
+
this.scheduleRenderIntersectionHandles();
|
|
936
|
+
}
|
|
937
|
+
scheduleRenderIntersectionHandles() {
|
|
938
|
+
this.intersectionRaf = null;
|
|
939
|
+
this.renderIntersectionHandles();
|
|
940
|
+
}
|
|
941
|
+
renderIntersectionHandles() {
|
|
942
|
+
const layer = this.shadowRoot?.querySelector('.dock-intersections-layer, .dock-intersection-layer');
|
|
943
|
+
if (!layer)
|
|
944
|
+
return;
|
|
945
|
+
// Keep existing handles; we will diff and update positions
|
|
946
|
+
// 1) Clean up legacy handles (created before keying) that lack a data-key
|
|
947
|
+
Array.from(layer.querySelectorAll('.dock-intersection-handle'))
|
|
948
|
+
.filter((el) => !el.dataset['key'])
|
|
949
|
+
.forEach((el) => el.remove());
|
|
950
|
+
// 2) Rebuild the internal map from DOM to avoid drifting state and dedupe duplicates
|
|
951
|
+
const domByKey = new Map();
|
|
952
|
+
Array.from(layer.querySelectorAll('.dock-intersection-handle[data-key]')).forEach((el) => {
|
|
953
|
+
const key = el.dataset['key'] ?? '';
|
|
954
|
+
if (!key)
|
|
955
|
+
return;
|
|
956
|
+
if (domByKey.has(key)) {
|
|
957
|
+
// Remove duplicates with the same key, keep the first one
|
|
958
|
+
el.remove();
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
domByKey.set(key, el);
|
|
962
|
+
// Ensure listener is attached only once
|
|
963
|
+
if (!el.dataset['listener']) {
|
|
964
|
+
el.dataset['listener'] = '1';
|
|
965
|
+
// Listener will be (re)assigned later when we know the current h/v pair
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
// Sync internal map with DOM
|
|
969
|
+
this.intersectionHandles = domByKey;
|
|
970
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
971
|
+
// If a corner resize is active, only update that handle's position and avoid creating new ones
|
|
972
|
+
if (this.cornerResizeState) {
|
|
973
|
+
const st = this.cornerResizeState;
|
|
974
|
+
const h0 = st.hs[0];
|
|
975
|
+
const v0 = st.vs[0];
|
|
976
|
+
const hPathStr = this.formatPath(h0.path);
|
|
977
|
+
const vPathStr = this.formatPath(v0.path);
|
|
978
|
+
const key = `${hPathStr}:${h0.index}|${vPathStr}:${v0.index}`;
|
|
979
|
+
// Find divider elements corresponding to active paths
|
|
980
|
+
const hDiv = this.shadowRoot?.querySelector(`.dock-split__divider[data-path="${hPathStr}"][data-index="${h0.index}"]`);
|
|
981
|
+
const vDiv = this.shadowRoot?.querySelector(`.dock-split__divider[data-path="${vPathStr}"][data-index="${v0.index}"]`);
|
|
982
|
+
if (hDiv && vDiv) {
|
|
983
|
+
const hr = hDiv.getBoundingClientRect();
|
|
984
|
+
const vr = vDiv.getBoundingClientRect();
|
|
985
|
+
const x = vr.left + vr.width / 2 - rootRect.left;
|
|
986
|
+
const y = hr.top + hr.height / 2 - rootRect.top;
|
|
987
|
+
const handle = st.handle;
|
|
988
|
+
if (!handle.dataset['key']) {
|
|
989
|
+
handle.dataset['key'] = key;
|
|
990
|
+
}
|
|
991
|
+
this.intersectionHandles.set(key, handle);
|
|
992
|
+
handle.style.left = `${x}px`;
|
|
993
|
+
handle.style.top = `${y}px`;
|
|
994
|
+
// Remove any other handles that don't match the active key
|
|
995
|
+
Array.from(layer.querySelectorAll('.dock-intersection-handle')).forEach((el) => {
|
|
996
|
+
if ((el.dataset['key'] ?? '') !== key) {
|
|
997
|
+
el.remove();
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
// Normalize internal map as well
|
|
1001
|
+
this.intersectionHandles = new Map([[key, handle]]);
|
|
1002
|
+
}
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
const allDividers = Array.from(this.shadowRoot?.querySelectorAll('.dock-split__divider') ?? []);
|
|
1006
|
+
const hDividers = [];
|
|
1007
|
+
const vDividers = [];
|
|
1008
|
+
allDividers.forEach((el) => {
|
|
1009
|
+
const orientation = el.dataset['orientation'] ?? undefined;
|
|
1010
|
+
const rect = el.getBoundingClientRect();
|
|
1011
|
+
const container = el.closest('.dock-split');
|
|
1012
|
+
const path = this.parsePath(el.dataset['path']);
|
|
1013
|
+
const pathStr = el.dataset['path'] ?? '';
|
|
1014
|
+
const index = Number.parseInt(el.dataset['index'] ?? '', 10);
|
|
1015
|
+
if (!container || !Number.isFinite(index))
|
|
1016
|
+
return;
|
|
1017
|
+
const info = { el, rect, path, pathStr, index, container };
|
|
1018
|
+
// Note: node.direction === 'horizontal' means the split lays out children left-to-right,
|
|
1019
|
+
// which yields a VERTICAL divider bar. So mapping is inverted here.
|
|
1020
|
+
if (orientation === 'horizontal') {
|
|
1021
|
+
vDividers.push(info);
|
|
1022
|
+
}
|
|
1023
|
+
else if (orientation === 'vertical') {
|
|
1024
|
+
hDividers.push(info);
|
|
1025
|
+
}
|
|
1026
|
+
});
|
|
1027
|
+
const desiredKeys = new Set();
|
|
1028
|
+
const tol = 24; // px tolerance to account for gaps and subpixel layout
|
|
1029
|
+
const groupMap = new Map();
|
|
1030
|
+
const groupPairs = new Map();
|
|
1031
|
+
hDividers.forEach((h) => {
|
|
1032
|
+
const hCenterY = h.rect.top + h.rect.height / 2;
|
|
1033
|
+
vDividers.forEach((v) => {
|
|
1034
|
+
const vCenterX = v.rect.left + v.rect.width / 2;
|
|
1035
|
+
const dx = vCenterX < h.rect.left ? h.rect.left - vCenterX : vCenterX > h.rect.right ? vCenterX - h.rect.right : 0;
|
|
1036
|
+
const dy = hCenterY < v.rect.top ? v.rect.top - hCenterY : hCenterY > v.rect.bottom ? hCenterY - v.rect.bottom : 0;
|
|
1037
|
+
if (dx > tol || dy > tol)
|
|
1038
|
+
return;
|
|
1039
|
+
const x = vCenterX - rootRect.left;
|
|
1040
|
+
const y = hCenterY - rootRect.top;
|
|
1041
|
+
const key = `${h.pathStr}:${h.index}|${v.pathStr}:${v.index}`;
|
|
1042
|
+
const gk = `${Math.round(x)}:${Math.round(y)}`;
|
|
1043
|
+
let handle = groupMap.get(gk);
|
|
1044
|
+
if (!handle) {
|
|
1045
|
+
// Try reuse via existing pair mapping
|
|
1046
|
+
handle = this.intersectionHandles.get(key) ?? null;
|
|
1047
|
+
if (!handle) {
|
|
1048
|
+
handle = this.documentRef.createElement('div');
|
|
1049
|
+
handle.classList.add('dock-intersection-handle', 'glyph');
|
|
1050
|
+
handle.setAttribute('role', 'separator');
|
|
1051
|
+
handle.setAttribute('aria-label', 'Resize split intersection');
|
|
1052
|
+
handle.dataset['key'] = key;
|
|
1053
|
+
handle.dataset['listener'] = '1';
|
|
1054
|
+
handle.addEventListener('pointerdown', (ev) => this.beginCornerResize(ev, h, v, handle));
|
|
1055
|
+
handle.addEventListener('dblclick', (ev) => this.onIntersectionDoubleClick(ev, handle));
|
|
1056
|
+
layer.appendChild(handle);
|
|
1057
|
+
}
|
|
1058
|
+
groupMap.set(gk, handle);
|
|
1059
|
+
}
|
|
1060
|
+
// Track pairs for this group and map all pair keys to the same handle
|
|
1061
|
+
const arr = groupPairs.get(gk) ?? [];
|
|
1062
|
+
arr.push({ h: { pathStr: h.pathStr ?? '', index: h.index }, v: { pathStr: v.pathStr ?? '', index: v.index } });
|
|
1063
|
+
groupPairs.set(gk, arr);
|
|
1064
|
+
this.intersectionHandles.set(key, handle);
|
|
1065
|
+
// Update position for the grouped handle
|
|
1066
|
+
handle.style.left = `${x}px`;
|
|
1067
|
+
handle.style.top = `${y}px`;
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
// Attach grouped pairs data to each handle and prune stale ones
|
|
1071
|
+
const keep = new Set(groupMap.values());
|
|
1072
|
+
groupMap.forEach((handle, gk) => {
|
|
1073
|
+
const pairs = groupPairs.get(gk) ?? [];
|
|
1074
|
+
handle.dataset['pairs'] = JSON.stringify(pairs);
|
|
1075
|
+
});
|
|
1076
|
+
Array.from(layer.querySelectorAll('.dock-intersection-handle')).forEach((el) => {
|
|
1077
|
+
if (!keep.has(el)) {
|
|
1078
|
+
el.remove();
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
// Reset intersectionHandles to only currently mapped keys
|
|
1082
|
+
const newMap = new Map();
|
|
1083
|
+
groupPairs.forEach((pairs, gk) => {
|
|
1084
|
+
const handle = groupMap.get(gk);
|
|
1085
|
+
pairs.forEach((p) => newMap.set(`${p.h.pathStr}:${p.h.index}|${p.v.pathStr}:${p.v.index}`, handle));
|
|
1086
|
+
});
|
|
1087
|
+
this.intersectionHandles = newMap;
|
|
1088
|
+
}
|
|
1089
|
+
beginCornerResize(event, h, v, handle) {
|
|
1090
|
+
event.preventDefault();
|
|
1091
|
+
// Build pairs from dataset if available (grouped intersections), otherwise from the provided pair
|
|
1092
|
+
const pairsRaw = handle.dataset['pairs'];
|
|
1093
|
+
const parsed = pairsRaw ? JSON.parse(pairsRaw) : [];
|
|
1094
|
+
const hs = [];
|
|
1095
|
+
const vs = [];
|
|
1096
|
+
const ensureHV = (pathStr, index, axis) => {
|
|
1097
|
+
const path = this.parsePath(pathStr);
|
|
1098
|
+
if (!path)
|
|
1099
|
+
return;
|
|
1100
|
+
const div = this.shadowRoot?.querySelector(`.dock-split__divider[data-path="${pathStr}"][data-index="${index}"]`) ?? null;
|
|
1101
|
+
const container = div?.closest('.dock-split');
|
|
1102
|
+
if (!container)
|
|
1103
|
+
return;
|
|
1104
|
+
if (axis === 'h') {
|
|
1105
|
+
const children = Array.from(container.querySelectorAll(':scope > .dock-split__child'));
|
|
1106
|
+
const initial = children.map((c) => c.getBoundingClientRect().height);
|
|
1107
|
+
hs.push({ path, index, container, initialSizes: initial, before: initial[index], after: initial[index + 1] });
|
|
1108
|
+
}
|
|
1109
|
+
else {
|
|
1110
|
+
const children = Array.from(container.querySelectorAll(':scope > .dock-split__child'));
|
|
1111
|
+
const initial = children.map((c) => c.getBoundingClientRect().width);
|
|
1112
|
+
vs.push({ path, index, container, initialSizes: initial, before: initial[index], after: initial[index + 1] });
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
if (parsed.length > 0) {
|
|
1116
|
+
parsed.forEach((p) => { ensureHV(p.h.pathStr, p.h.index, 'h'); ensureHV(p.v.pathStr, p.v.index, 'v'); });
|
|
1117
|
+
}
|
|
1118
|
+
else if (h.path && v.path) {
|
|
1119
|
+
ensureHV(this.formatPath(h.path), h.index, 'h');
|
|
1120
|
+
ensureHV(this.formatPath(v.path), v.index, 'v');
|
|
1121
|
+
}
|
|
1122
|
+
if (hs.length === 0 && vs.length === 0)
|
|
1123
|
+
return;
|
|
1124
|
+
try {
|
|
1125
|
+
handle.setPointerCapture(event.pointerId);
|
|
1126
|
+
handle.dataset['resizing'] = 'true';
|
|
1127
|
+
handle.classList.add('hovering');
|
|
1128
|
+
}
|
|
1129
|
+
catch { }
|
|
1130
|
+
this.cornerResizeState = {
|
|
1131
|
+
pointerId: event.pointerId,
|
|
1132
|
+
handle,
|
|
1133
|
+
hs: hs.map((e) => ({ path: this.clonePath(e.path), index: e.index, container: e.container, beforeSize: e.before, afterSize: e.after, initialSizes: e.initialSizes, startY: event.clientY })),
|
|
1134
|
+
vs: vs.map((e) => ({ path: this.clonePath(e.path), index: e.index, container: e.container, beforeSize: e.before, afterSize: e.after, initialSizes: e.initialSizes, startX: event.clientX })),
|
|
1135
|
+
};
|
|
1136
|
+
this.startPointerTracking();
|
|
1137
|
+
// Ensure handle has a stable key (use group if present)
|
|
1138
|
+
if (!handle.dataset['key']) {
|
|
1139
|
+
handle.dataset['key'] = handle.dataset['group'] ?? '';
|
|
1140
|
+
}
|
|
1141
|
+
this.renderSnapMarkersForCorner();
|
|
1142
|
+
// Compute localized snap targets for this intersection
|
|
1143
|
+
try {
|
|
1144
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
1145
|
+
// Use first pair to define the crossing lines
|
|
1146
|
+
let centerX = null;
|
|
1147
|
+
let centerY = null;
|
|
1148
|
+
// Resolve one vertical bar (from vs) and one horizontal bar (from hs)
|
|
1149
|
+
if (vs.length > 0) {
|
|
1150
|
+
const vPair = vs[0];
|
|
1151
|
+
const vPathStr = this.formatPath(vPair.path);
|
|
1152
|
+
const vDiv = this.shadowRoot?.querySelector(`.dock-split__divider[data-path="${vPathStr}"][data-index="${vPair.index}"]`) ?? null;
|
|
1153
|
+
const vr = vDiv?.getBoundingClientRect();
|
|
1154
|
+
if (vr)
|
|
1155
|
+
centerX = vr.left + vr.width / 2;
|
|
1156
|
+
}
|
|
1157
|
+
if (hs.length > 0) {
|
|
1158
|
+
const hPair = hs[0];
|
|
1159
|
+
const hPathStr = this.formatPath(hPair.path);
|
|
1160
|
+
const hDiv = this.shadowRoot?.querySelector(`.dock-split__divider[data-path="${hPathStr}"][data-index="${hPair.index}"]`) ?? null;
|
|
1161
|
+
const hr = hDiv?.getBoundingClientRect();
|
|
1162
|
+
if (hr)
|
|
1163
|
+
centerY = hr.top + hr.height / 2;
|
|
1164
|
+
}
|
|
1165
|
+
const xTargets = [];
|
|
1166
|
+
const yTargets = [];
|
|
1167
|
+
const allDividers = Array.from(this.shadowRoot?.querySelectorAll('.dock-split__divider') ?? []);
|
|
1168
|
+
allDividers.forEach((el) => {
|
|
1169
|
+
const o = el.dataset['orientation'] ?? undefined;
|
|
1170
|
+
const r = el.getBoundingClientRect();
|
|
1171
|
+
if (o === 'horizontal' && centerY != null) {
|
|
1172
|
+
// vertical bar → contributes X if it crosses centerY
|
|
1173
|
+
if (centerY >= r.top && centerY <= r.bottom) {
|
|
1174
|
+
xTargets.push(r.left + r.width / 2 - rootRect.left);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
else if (o === 'vertical' && centerX != null) {
|
|
1178
|
+
// horizontal bar → contributes Y if it crosses centerX
|
|
1179
|
+
if (centerX >= r.left && centerX <= r.right) {
|
|
1180
|
+
yTargets.push(r.top + r.height / 2 - rootRect.top);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
this.cornerSnapXTargets = xTargets;
|
|
1185
|
+
this.cornerSnapYTargets = yTargets;
|
|
1186
|
+
}
|
|
1187
|
+
catch {
|
|
1188
|
+
this.cornerSnapXTargets = [];
|
|
1189
|
+
this.cornerSnapYTargets = [];
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
handleCornerResizeMove(event) {
|
|
1193
|
+
const state = this.cornerResizeState;
|
|
1194
|
+
if (!state || state.pointerId !== event.pointerId)
|
|
1195
|
+
return;
|
|
1196
|
+
const snapValue = (val, total, active) => {
|
|
1197
|
+
if (!active || total <= 0)
|
|
1198
|
+
return val;
|
|
1199
|
+
const ratios = [1 / 3, 1 / 2, 2 / 3];
|
|
1200
|
+
const r = val / total;
|
|
1201
|
+
let best = ratios[0];
|
|
1202
|
+
let d = Math.abs(r - best);
|
|
1203
|
+
for (let i = 1; i < ratios.length; i++) {
|
|
1204
|
+
const dd = Math.abs(r - ratios[i]);
|
|
1205
|
+
if (dd < d) {
|
|
1206
|
+
d = dd;
|
|
1207
|
+
best = ratios[i];
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
return best * total;
|
|
1211
|
+
};
|
|
1212
|
+
// Axis snapping to nearby intersections
|
|
1213
|
+
const tol = 10;
|
|
1214
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
1215
|
+
let clientX = event.clientX;
|
|
1216
|
+
let clientY = event.clientY;
|
|
1217
|
+
if (this.cornerSnapXTargets.length) {
|
|
1218
|
+
let best = clientX, bestDist = tol + 1;
|
|
1219
|
+
this.cornerSnapXTargets.forEach((sx) => {
|
|
1220
|
+
const px = rootRect.left + sx;
|
|
1221
|
+
const d = Math.abs(px - clientX);
|
|
1222
|
+
if (d < bestDist) {
|
|
1223
|
+
bestDist = d;
|
|
1224
|
+
best = px;
|
|
1225
|
+
}
|
|
1226
|
+
});
|
|
1227
|
+
if (bestDist <= tol)
|
|
1228
|
+
clientX = best;
|
|
1229
|
+
}
|
|
1230
|
+
if (this.cornerSnapYTargets.length) {
|
|
1231
|
+
let best = clientY, bestDist = tol + 1;
|
|
1232
|
+
this.cornerSnapYTargets.forEach((sy) => {
|
|
1233
|
+
const py = rootRect.top + sy;
|
|
1234
|
+
const d = Math.abs(py - clientY);
|
|
1235
|
+
if (d < bestDist) {
|
|
1236
|
+
bestDist = d;
|
|
1237
|
+
best = py;
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
if (bestDist <= tol)
|
|
1241
|
+
clientY = best;
|
|
1242
|
+
}
|
|
1243
|
+
// Update all horizontal bars (vertical splits) with Y delta
|
|
1244
|
+
state.hs.forEach((h) => {
|
|
1245
|
+
const node = this.resolveSplitNode(h.path);
|
|
1246
|
+
if (!node)
|
|
1247
|
+
return;
|
|
1248
|
+
const deltaY = clientY - h.startY;
|
|
1249
|
+
const minSize = 48;
|
|
1250
|
+
const pairTotal = h.beforeSize + h.afterSize;
|
|
1251
|
+
let newBefore = Math.min(Math.max(h.beforeSize + deltaY, minSize), pairTotal - minSize);
|
|
1252
|
+
newBefore = snapValue(newBefore, pairTotal, event.shiftKey);
|
|
1253
|
+
const newAfter = pairTotal - newBefore;
|
|
1254
|
+
const sizesPx = [...h.initialSizes];
|
|
1255
|
+
sizesPx[h.index] = newBefore;
|
|
1256
|
+
sizesPx[h.index + 1] = newAfter;
|
|
1257
|
+
const total = sizesPx.reduce((a, s) => a + s, 0);
|
|
1258
|
+
const normalized = total > 0 ? sizesPx.map((s) => s / total) : [];
|
|
1259
|
+
node.sizes = normalized;
|
|
1260
|
+
const children = Array.from(h.container.querySelectorAll(':scope > .dock-split__child'));
|
|
1261
|
+
normalized.forEach((size, idx) => { if (children[idx])
|
|
1262
|
+
children[idx].style.flex = `${Math.max(size, 0)} 1 0`; });
|
|
1263
|
+
});
|
|
1264
|
+
// Update all vertical bars (horizontal splits) with X delta
|
|
1265
|
+
state.vs.forEach((v) => {
|
|
1266
|
+
const node = this.resolveSplitNode(v.path);
|
|
1267
|
+
if (!node)
|
|
1268
|
+
return;
|
|
1269
|
+
const deltaX = clientX - v.startX;
|
|
1270
|
+
const minSize = 48;
|
|
1271
|
+
const pairTotal = v.beforeSize + v.afterSize;
|
|
1272
|
+
let newBefore = Math.min(Math.max(v.beforeSize + deltaX, minSize), pairTotal - minSize);
|
|
1273
|
+
newBefore = snapValue(newBefore, pairTotal, event.shiftKey);
|
|
1274
|
+
const newAfter = pairTotal - newBefore;
|
|
1275
|
+
const sizesPx = [...v.initialSizes];
|
|
1276
|
+
sizesPx[v.index] = newBefore;
|
|
1277
|
+
sizesPx[v.index + 1] = newAfter;
|
|
1278
|
+
const total = sizesPx.reduce((a, s) => a + s, 0);
|
|
1279
|
+
const normalized = total > 0 ? sizesPx.map((s) => s / total) : [];
|
|
1280
|
+
node.sizes = normalized;
|
|
1281
|
+
const children = Array.from(v.container.querySelectorAll(':scope > .dock-split__child'));
|
|
1282
|
+
normalized.forEach((size, idx) => { if (children[idx])
|
|
1283
|
+
children[idx].style.flex = `${Math.max(size, 0)} 1 0`; });
|
|
1284
|
+
});
|
|
1285
|
+
this.dispatchLayoutChanged();
|
|
1286
|
+
}
|
|
1287
|
+
endCornerResize(pointerId) {
|
|
1288
|
+
const state = this.cornerResizeState;
|
|
1289
|
+
if (!state || pointerId !== state.pointerId)
|
|
1290
|
+
return;
|
|
1291
|
+
try {
|
|
1292
|
+
state.handle.releasePointerCapture(state.pointerId);
|
|
1293
|
+
}
|
|
1294
|
+
catch { }
|
|
1295
|
+
state.handle.dataset['resizing'] = 'false';
|
|
1296
|
+
this.cornerResizeState = null;
|
|
1297
|
+
// Re-render handles to account for new positions
|
|
1298
|
+
this.scheduleRenderIntersectionHandles();
|
|
1299
|
+
this.cornerSnapXTargets = [];
|
|
1300
|
+
this.cornerSnapYTargets = [];
|
|
1301
|
+
}
|
|
1302
|
+
onIntersectionDoubleClick(event, handle) {
|
|
1303
|
+
event.preventDefault();
|
|
1304
|
+
const pairsRaw = handle.dataset['pairs'];
|
|
1305
|
+
const parsed = pairsRaw ? JSON.parse(pairsRaw) : [];
|
|
1306
|
+
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
1307
|
+
const k = handle.dataset['key'] ?? '';
|
|
1308
|
+
const parts = k.split('|');
|
|
1309
|
+
if (parts.length === 2) {
|
|
1310
|
+
const [hPart, vPart] = parts;
|
|
1311
|
+
const hi = hPart.lastIndexOf(':');
|
|
1312
|
+
const vi = vPart.lastIndexOf(':');
|
|
1313
|
+
if (hi > 0 && vi > 0) {
|
|
1314
|
+
const hPathStr = hPart.slice(0, hi);
|
|
1315
|
+
const vPathStr = vPart.slice(0, vi);
|
|
1316
|
+
const hIdx = Number.parseInt(hPart.slice(hi + 1), 10);
|
|
1317
|
+
const vIdx = Number.parseInt(vPart.slice(vi + 1), 10);
|
|
1318
|
+
parsed.push({ h: { pathStr: hPathStr, index: hIdx }, v: { pathStr: vPathStr, index: vIdx } });
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if (parsed.length === 0)
|
|
1323
|
+
return;
|
|
1324
|
+
const splitKeys = new Set();
|
|
1325
|
+
parsed.forEach((p) => { splitKeys.add(p.h.pathStr); splitKeys.add(p.v.pathStr); });
|
|
1326
|
+
let hasStored = false;
|
|
1327
|
+
splitKeys.forEach((k) => { if (this.previousSplitSizes.has(k))
|
|
1328
|
+
hasStored = true; });
|
|
1329
|
+
const applySizes = (pathStr, mutate) => {
|
|
1330
|
+
const path = this.parsePath(pathStr);
|
|
1331
|
+
if (!path)
|
|
1332
|
+
return;
|
|
1333
|
+
const node = this.resolveSplitNode(path);
|
|
1334
|
+
if (!node)
|
|
1335
|
+
return;
|
|
1336
|
+
const sizes = this.normalizeSizesArray(node.sizes ?? [], node.children.length);
|
|
1337
|
+
// Find divider index from any divider belonging to this path
|
|
1338
|
+
const divEl = this.shadowRoot?.querySelector(`.dock-split__divider[data-path="${pathStr}"]`);
|
|
1339
|
+
const index = divEl ? Number.parseInt(divEl.dataset['index'] ?? '0', 10) : 0;
|
|
1340
|
+
const newSizes = mutate([...sizes], index);
|
|
1341
|
+
node.sizes = newSizes;
|
|
1342
|
+
const segments = path.segments.join('/');
|
|
1343
|
+
const container = this.shadowRoot?.querySelector(`.dock-split[data-path="${segments}"]`);
|
|
1344
|
+
if (container) {
|
|
1345
|
+
const children = Array.from(container.querySelectorAll(':scope > .dock-split__child'));
|
|
1346
|
+
newSizes.forEach((s, i) => { if (children[i])
|
|
1347
|
+
children[i].style.flex = `${Math.max(s, 0)} 1 0`; });
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
if (hasStored) {
|
|
1351
|
+
// Restore stored sizes
|
|
1352
|
+
this.previousSplitSizes.forEach((sizes, pathStr) => {
|
|
1353
|
+
const path = this.parsePath(pathStr);
|
|
1354
|
+
const node = path ? this.resolveSplitNode(path) : null;
|
|
1355
|
+
if (!node)
|
|
1356
|
+
return;
|
|
1357
|
+
const norm = this.normalizeSizesArray(sizes, node.children.length);
|
|
1358
|
+
node.sizes = norm;
|
|
1359
|
+
const segments = path.segments.join('/');
|
|
1360
|
+
const container = this.shadowRoot?.querySelector(`.dock-split[data-path="${segments}"]`);
|
|
1361
|
+
if (container) {
|
|
1362
|
+
const children = Array.from(container.querySelectorAll(':scope > .dock-split__child'));
|
|
1363
|
+
norm.forEach((s, i) => { if (children[i])
|
|
1364
|
+
children[i].style.flex = `${Math.max(s, 0)} 1 0`; });
|
|
1365
|
+
}
|
|
1366
|
+
});
|
|
1367
|
+
this.previousSplitSizes.clear();
|
|
1368
|
+
}
|
|
1369
|
+
else {
|
|
1370
|
+
// Equalize the two panes adjacent to each divider and store previous sizes
|
|
1371
|
+
const touched = new Set();
|
|
1372
|
+
parsed.forEach((p) => {
|
|
1373
|
+
[p.h.pathStr, p.v.pathStr].forEach((key) => {
|
|
1374
|
+
if (touched.has(key))
|
|
1375
|
+
return;
|
|
1376
|
+
const path = this.parsePath(key);
|
|
1377
|
+
const node = path ? this.resolveSplitNode(path) : null;
|
|
1378
|
+
if (node && Array.isArray(node.sizes)) {
|
|
1379
|
+
this.previousSplitSizes.set(key, [...node.sizes]);
|
|
1380
|
+
}
|
|
1381
|
+
touched.add(key);
|
|
1382
|
+
});
|
|
1383
|
+
applySizes(p.h.pathStr, (sizes, idx) => {
|
|
1384
|
+
const total = (sizes[idx] ?? 0) + (sizes[idx + 1] ?? 0);
|
|
1385
|
+
if (total <= 0)
|
|
1386
|
+
return sizes;
|
|
1387
|
+
sizes[idx] = total / 2;
|
|
1388
|
+
sizes[idx + 1] = total / 2;
|
|
1389
|
+
const sum = sizes.reduce((a, s) => a + s, 0);
|
|
1390
|
+
return sum > 0 ? sizes.map((s) => s / sum) : sizes;
|
|
1391
|
+
});
|
|
1392
|
+
applySizes(p.v.pathStr, (sizes, idx) => {
|
|
1393
|
+
const total = (sizes[idx] ?? 0) + (sizes[idx + 1] ?? 0);
|
|
1394
|
+
if (total <= 0)
|
|
1395
|
+
return sizes;
|
|
1396
|
+
sizes[idx] = total / 2;
|
|
1397
|
+
sizes[idx + 1] = total / 2;
|
|
1398
|
+
const sum = sizes.reduce((a, s) => a + s, 0);
|
|
1399
|
+
return sum > 0 ? sizes.map((s) => s / sum) : sizes;
|
|
1400
|
+
});
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
this.dispatchLayoutChanged();
|
|
1404
|
+
this.scheduleRenderIntersectionHandles();
|
|
1405
|
+
}
|
|
770
1406
|
beginFloatingDrag(event, index, wrapper, handle) {
|
|
771
1407
|
const floating = this.floatingLayouts[index];
|
|
772
1408
|
if (!floating) {
|
|
@@ -803,6 +1439,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
803
1439
|
event.stopPropagation();
|
|
804
1440
|
try {
|
|
805
1441
|
handle.setPointerCapture(event.pointerId);
|
|
1442
|
+
handle.dataset['resizing'] = 'true';
|
|
806
1443
|
}
|
|
807
1444
|
catch (err) {
|
|
808
1445
|
/* pointer capture may not be supported */
|
|
@@ -848,6 +1485,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
848
1485
|
}
|
|
849
1486
|
try {
|
|
850
1487
|
state.handle.releasePointerCapture(state.pointerId);
|
|
1488
|
+
delete state.handle.dataset['resizing'];
|
|
851
1489
|
}
|
|
852
1490
|
catch (err) {
|
|
853
1491
|
/* no-op */
|
|
@@ -997,7 +1635,8 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
997
1635
|
if (this.pointerTrackingActive &&
|
|
998
1636
|
!this.resizeState &&
|
|
999
1637
|
!this.floatingDragState &&
|
|
1000
|
-
!this.floatingResizeState
|
|
1638
|
+
!this.floatingResizeState &&
|
|
1639
|
+
!this.cornerResizeState) {
|
|
1001
1640
|
const win = this.windowRef;
|
|
1002
1641
|
win?.removeEventListener('pointermove', this.onPointerMove);
|
|
1003
1642
|
win?.removeEventListener('pointerup', this.onPointerUp);
|
|
@@ -1059,6 +1698,13 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1059
1698
|
divider.classList.add('dock-split__divider');
|
|
1060
1699
|
divider.setAttribute('role', 'separator');
|
|
1061
1700
|
divider.tabIndex = 0;
|
|
1701
|
+
// Tag divider with metadata for intersection detection
|
|
1702
|
+
const dividerPath = typeof floatingIndex === 'number'
|
|
1703
|
+
? { type: 'floating', index: floatingIndex, segments: [...path] }
|
|
1704
|
+
: { type: 'docked', segments: [...path] };
|
|
1705
|
+
divider.dataset['path'] = this.formatPath(dividerPath);
|
|
1706
|
+
divider.dataset['index'] = String(index);
|
|
1707
|
+
divider.dataset['orientation'] = node.direction;
|
|
1062
1708
|
divider.addEventListener('pointerdown', (event) => this.beginResize(event, container, floatingIndex !== undefined
|
|
1063
1709
|
? { type: 'floating', index: floatingIndex, segments: [...path] }
|
|
1064
1710
|
: { type: 'docked', segments: [...path] }, index));
|
|
@@ -1183,19 +1829,121 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1183
1829
|
afterSize,
|
|
1184
1830
|
};
|
|
1185
1831
|
this.startPointerTracking();
|
|
1832
|
+
// Compute localized snap targets: intersections with perpendicular dividers near this divider
|
|
1833
|
+
try {
|
|
1834
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
1835
|
+
const dividerRect = divider.getBoundingClientRect();
|
|
1836
|
+
const allDividers = Array.from(this.shadowRoot?.querySelectorAll('.dock-split__divider') ?? []);
|
|
1837
|
+
const targets = [];
|
|
1838
|
+
if (orientation === 'horizontal') {
|
|
1839
|
+
// Current bar is vertical → snap X to centers of other vertical bars (no crossing check needed)
|
|
1840
|
+
allDividers.forEach((el) => {
|
|
1841
|
+
if (el === divider)
|
|
1842
|
+
return;
|
|
1843
|
+
const o = el.dataset['orientation'] ?? undefined;
|
|
1844
|
+
if (o !== 'horizontal')
|
|
1845
|
+
return; // vertical divider bars (split direction horizontal)
|
|
1846
|
+
const r = el.getBoundingClientRect();
|
|
1847
|
+
const xCenter = r.left + r.width / 2 - rootRect.left;
|
|
1848
|
+
targets.push(xCenter);
|
|
1849
|
+
});
|
|
1850
|
+
this.activeSnapAxis = 'x';
|
|
1851
|
+
this.activeSnapTargets = targets;
|
|
1852
|
+
this.renderSnapMarkersForDivider();
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
// Current bar is horizontal → snap Y to centers of other horizontal bars (no crossing check needed)
|
|
1856
|
+
allDividers.forEach((el) => {
|
|
1857
|
+
if (el === divider)
|
|
1858
|
+
return;
|
|
1859
|
+
const o = el.dataset['orientation'] ?? undefined;
|
|
1860
|
+
if (o !== 'vertical')
|
|
1861
|
+
return; // horizontal divider bars (split direction vertical)
|
|
1862
|
+
const r = el.getBoundingClientRect();
|
|
1863
|
+
const yCenter = r.top + r.height / 2 - rootRect.top;
|
|
1864
|
+
targets.push(yCenter);
|
|
1865
|
+
});
|
|
1866
|
+
this.activeSnapAxis = 'y';
|
|
1867
|
+
this.activeSnapTargets = targets;
|
|
1868
|
+
this.renderSnapMarkersForDivider();
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
catch {
|
|
1872
|
+
this.activeSnapAxis = null;
|
|
1873
|
+
this.activeSnapTargets = [];
|
|
1874
|
+
this.clearSnapMarkers();
|
|
1875
|
+
}
|
|
1186
1876
|
}
|
|
1187
1877
|
onPointerMove(event) {
|
|
1878
|
+
if (this.cornerResizeState && event.pointerId === this.cornerResizeState.pointerId) {
|
|
1879
|
+
this.handleCornerResizeMove(event);
|
|
1880
|
+
}
|
|
1188
1881
|
if (this.resizeState && event.pointerId === this.resizeState.pointerId) {
|
|
1189
1882
|
const state = this.resizeState;
|
|
1190
1883
|
const splitNode = this.resolveSplitNode(state.path);
|
|
1191
1884
|
if (!splitNode) {
|
|
1192
1885
|
return;
|
|
1193
1886
|
}
|
|
1194
|
-
|
|
1887
|
+
let currentPos = state.orientation === 'horizontal' ? event.clientX : event.clientY;
|
|
1888
|
+
// Localized axis snap near neighboring intersections
|
|
1889
|
+
const tol = 10;
|
|
1890
|
+
const rootRect = this.rootEl.getBoundingClientRect();
|
|
1891
|
+
if (this.activeSnapTargets.length) {
|
|
1892
|
+
if (state.orientation === 'horizontal' && this.activeSnapAxis === 'x') {
|
|
1893
|
+
// Vertical divider snapping along X
|
|
1894
|
+
let closest = Number.POSITIVE_INFINITY;
|
|
1895
|
+
let best = currentPos;
|
|
1896
|
+
const pointerX = event.clientX;
|
|
1897
|
+
this.activeSnapTargets.forEach((sx) => {
|
|
1898
|
+
const px = rootRect.left + sx;
|
|
1899
|
+
const d = Math.abs(pointerX - px);
|
|
1900
|
+
if (d < closest) {
|
|
1901
|
+
closest = d;
|
|
1902
|
+
best = px;
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
if (closest <= tol)
|
|
1906
|
+
currentPos = best;
|
|
1907
|
+
this.renderSnapMarkersForDivider();
|
|
1908
|
+
}
|
|
1909
|
+
else if (state.orientation === 'vertical' && this.activeSnapAxis === 'y') {
|
|
1910
|
+
// Horizontal divider snapping along Y
|
|
1911
|
+
let closest = Number.POSITIVE_INFINITY;
|
|
1912
|
+
let best = currentPos;
|
|
1913
|
+
const pointerY = event.clientY;
|
|
1914
|
+
this.activeSnapTargets.forEach((sy) => {
|
|
1915
|
+
const py = rootRect.top + sy;
|
|
1916
|
+
const d = Math.abs(pointerY - py);
|
|
1917
|
+
if (d < closest) {
|
|
1918
|
+
closest = d;
|
|
1919
|
+
best = py;
|
|
1920
|
+
}
|
|
1921
|
+
});
|
|
1922
|
+
if (closest <= tol)
|
|
1923
|
+
currentPos = best;
|
|
1924
|
+
this.renderSnapMarkersForDivider();
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1195
1927
|
const delta = currentPos - state.startPos;
|
|
1196
1928
|
const minSize = 48;
|
|
1197
1929
|
const pairTotal = state.beforeSize + state.afterSize;
|
|
1198
|
-
let newBefore =
|
|
1930
|
+
let newBefore = state.beforeSize + delta;
|
|
1931
|
+
// Optional snap with Shift
|
|
1932
|
+
if (event.shiftKey && pairTotal > 0) {
|
|
1933
|
+
const ratios = [1 / 3, 1 / 2, 2 / 3];
|
|
1934
|
+
const target = newBefore / pairTotal;
|
|
1935
|
+
let best = ratios[0];
|
|
1936
|
+
let bestDist = Math.abs(target - best);
|
|
1937
|
+
for (let i = 1; i < ratios.length; i++) {
|
|
1938
|
+
const d = Math.abs(target - ratios[i]);
|
|
1939
|
+
if (d < bestDist) {
|
|
1940
|
+
best = ratios[i];
|
|
1941
|
+
bestDist = d;
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
newBefore = best * pairTotal;
|
|
1945
|
+
}
|
|
1946
|
+
newBefore = Math.min(Math.max(newBefore, minSize), pairTotal - minSize);
|
|
1199
1947
|
let newAfter = pairTotal - newBefore;
|
|
1200
1948
|
if (!Number.isFinite(newBefore) || !Number.isFinite(newAfter)) {
|
|
1201
1949
|
return;
|
|
@@ -1226,11 +1974,17 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1226
1974
|
}
|
|
1227
1975
|
}
|
|
1228
1976
|
onPointerUp(event) {
|
|
1977
|
+
if (this.cornerResizeState && event.pointerId === this.cornerResizeState.pointerId) {
|
|
1978
|
+
this.endCornerResize(event.pointerId);
|
|
1979
|
+
}
|
|
1229
1980
|
if (this.resizeState && event.pointerId === this.resizeState.pointerId) {
|
|
1230
1981
|
const divider = this.resizeState.divider;
|
|
1231
1982
|
divider.dataset['resizing'] = 'false';
|
|
1232
1983
|
divider.releasePointerCapture(this.resizeState.pointerId);
|
|
1233
1984
|
this.resizeState = null;
|
|
1985
|
+
this.scheduleRenderIntersectionHandles();
|
|
1986
|
+
this.activeSnapAxis = null;
|
|
1987
|
+
this.activeSnapTargets = [];
|
|
1234
1988
|
}
|
|
1235
1989
|
if (this.floatingDragState && event.pointerId === this.floatingDragState.pointerId) {
|
|
1236
1990
|
this.endFloatingDrag(event.pointerId);
|
|
@@ -3159,10 +3913,10 @@ class BsDockManagerComponent {
|
|
|
3159
3913
|
cloneLayout(layout) {
|
|
3160
3914
|
return JSON.parse(JSON.stringify(layout));
|
|
3161
3915
|
}
|
|
3162
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
3163
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.
|
|
3916
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockManagerComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3917
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.13", type: BsDockManagerComponent, isStandalone: false, selector: "bs-dock-manager", inputs: { layout: "layout" }, outputs: { layoutChange: "layoutChange", layoutSnapshotChange: "layoutSnapshotChange" }, queries: [{ propertyName: "panes", predicate: BsDockPaneComponent }], viewQueries: [{ propertyName: "managerRef", first: true, predicate: ["manager"], descendants: true, static: true }], ngImport: i0, template: "<mint-dock-manager\n #manager\n class=\"bs-dock-manager\"\n [attr.layout]=\"layoutString\"\n (dock-layout-changed)=\"onLayoutChanged($event)\"\n>\n <ng-container *ngFor=\"let pane of panes; trackBy: trackByPane\">\n <div class=\"bs-dock-pane\" [attr.slot]=\"pane.name\">\n <ng-container *ngTemplateOutlet=\"pane.template\"></ng-container>\n </div>\n </ng-container>\n</mint-dock-manager>\n", styles: [":host{display:block;width:100%;height:100%}.bs-dock-manager{display:block;width:100%;height:100%}.bs-dock-pane{display:contents}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3164
3918
|
}
|
|
3165
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
3919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockManagerComponent, decorators: [{
|
|
3166
3920
|
type: Component,
|
|
3167
3921
|
args: [{ selector: 'bs-dock-manager', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<mint-dock-manager\n #manager\n class=\"bs-dock-manager\"\n [attr.layout]=\"layoutString\"\n (dock-layout-changed)=\"onLayoutChanged($event)\"\n>\n <ng-container *ngFor=\"let pane of panes; trackBy: trackByPane\">\n <div class=\"bs-dock-pane\" [attr.slot]=\"pane.name\">\n <ng-container *ngTemplateOutlet=\"pane.template\"></ng-container>\n </div>\n </ng-container>\n</mint-dock-manager>\n", styles: [":host{display:block;width:100%;height:100%}.bs-dock-manager{display:block;width:100%;height:100%}.bs-dock-pane{display:contents}\n"] }]
|
|
3168
3922
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: Document, decorators: [{
|
|
@@ -3183,11 +3937,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
3183
3937
|
}] } });
|
|
3184
3938
|
|
|
3185
3939
|
class BsDockModule {
|
|
3186
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.
|
|
3187
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.
|
|
3188
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.
|
|
3940
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
3941
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.13", ngImport: i0, type: BsDockModule, declarations: [BsDockManagerComponent, BsDockPaneComponent], imports: [CommonModule], exports: [BsDockManagerComponent, BsDockPaneComponent] }); }
|
|
3942
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockModule, imports: [CommonModule] }); }
|
|
3189
3943
|
}
|
|
3190
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.
|
|
3944
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: BsDockModule, decorators: [{
|
|
3191
3945
|
type: NgModule,
|
|
3192
3946
|
args: [{
|
|
3193
3947
|
declarations: [BsDockManagerComponent, BsDockPaneComponent],
|