@mintplayer/ng-bootstrap 20.6.0 → 20.6.1
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.
|
@@ -1341,6 +1341,28 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1341
1341
|
this.startDragPointerTracking();
|
|
1342
1342
|
event.dataTransfer.effectAllowed = 'move';
|
|
1343
1343
|
event.dataTransfer.setData('text/plain', pane);
|
|
1344
|
+
// Preferred UX: if the dragged tab is the only one in its stack,
|
|
1345
|
+
// immediately convert to a floating window unless it is already the
|
|
1346
|
+
// only pane in a floating window (this case is handled by reuse logic).
|
|
1347
|
+
if (this.dragState && this.dragState.floatingIndex !== null && this.dragState.floatingIndex < 0) {
|
|
1348
|
+
const loc = this.resolveStackLocation(this.dragState.sourcePath);
|
|
1349
|
+
if (loc && Array.isArray(loc.node.panes) && loc.node.panes.length === 1) {
|
|
1350
|
+
let shouldConvert = false;
|
|
1351
|
+
if (loc.context === "docked") {
|
|
1352
|
+
shouldConvert = true;
|
|
1353
|
+
}
|
|
1354
|
+
else if (loc.context === "floating") {
|
|
1355
|
+
const floating = this.floatingLayouts[loc.index];
|
|
1356
|
+
const totalPanes = floating && floating.root ? this.countPanesInTree(floating.root) : 0;
|
|
1357
|
+
shouldConvert = totalPanes > 1; // not the only pane in this floating window
|
|
1358
|
+
}
|
|
1359
|
+
if (shouldConvert) {
|
|
1360
|
+
const startX = Number.isFinite(event.clientX) ? event.clientX : (this.dragState.startClientX ?? 0);
|
|
1361
|
+
const startY = Number.isFinite(event.clientY) ? event.clientY : (this.dragState.startClientY ?? 0);
|
|
1362
|
+
this.convertPendingTabDragToFloating(startX, startY);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1344
1366
|
}
|
|
1345
1367
|
preparePaneDragSource(path, pane, stackEl, event) {
|
|
1346
1368
|
const location = this.resolveStackLocation(path);
|
|
@@ -1607,6 +1629,8 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1607
1629
|
if (this.dropJoystick.dataset['visible'] !== 'true') {
|
|
1608
1630
|
this.hideDropIndicator();
|
|
1609
1631
|
}
|
|
1632
|
+
// Also ensure any in-header placeholder is cleared when not over a stack
|
|
1633
|
+
this.clearHeaderDragPlaceholder();
|
|
1610
1634
|
return;
|
|
1611
1635
|
}
|
|
1612
1636
|
// If we moved to a different target stack, reset any sticky zone so
|
|
@@ -1617,7 +1641,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1617
1641
|
}
|
|
1618
1642
|
// Previous behavior hid the indicator and returned early here; instead,
|
|
1619
1643
|
// allow the live-reorder branch below to handle in-header drags.
|
|
1620
|
-
// While
|
|
1644
|
+
// While dragging within the same header, show a placeholder and suppress joystick/indicator
|
|
1621
1645
|
if (this.dragState &&
|
|
1622
1646
|
this.dragState.floatingIndex !== null &&
|
|
1623
1647
|
this.dragState.floatingIndex < 0 &&
|
|
@@ -1628,16 +1652,12 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1628
1652
|
if (inHeaderByBounds || inHeaderByHitTest) {
|
|
1629
1653
|
const header = stack.querySelector('.dock-stack__header');
|
|
1630
1654
|
if (header) {
|
|
1655
|
+
// Ensure placeholder exists and move it as the pointer moves
|
|
1656
|
+
this.ensureHeaderDragPlaceholder(header, this.dragState.pane);
|
|
1631
1657
|
const idx = this.computeHeaderInsertIndex(header, clientX);
|
|
1632
1658
|
if (this.dragState.liveReorderIndex !== idx) {
|
|
1633
|
-
this.ensureHeaderDragPlaceholder(header, this.dragState.pane);
|
|
1634
1659
|
this.updateHeaderDragPlaceholderPosition(header, idx);
|
|
1635
|
-
|
|
1636
|
-
if (location) {
|
|
1637
|
-
this.reorderPaneInLocationAtIndex(location, this.dragState.pane, idx);
|
|
1638
|
-
this.render();
|
|
1639
|
-
this.dispatchLayoutChanged();
|
|
1640
|
-
}
|
|
1660
|
+
// Keep model reordering until drop; only move the placeholder now
|
|
1641
1661
|
this.dragState.liveReorderIndex = idx;
|
|
1642
1662
|
}
|
|
1643
1663
|
}
|
|
@@ -1645,6 +1665,8 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1645
1665
|
return;
|
|
1646
1666
|
}
|
|
1647
1667
|
}
|
|
1668
|
+
// Leaving the header: ensure any placeholder is removed immediately
|
|
1669
|
+
this.clearHeaderDragPlaceholder();
|
|
1648
1670
|
const zoneHint = this.findDropZoneByPoint(clientX, clientY);
|
|
1649
1671
|
const zone = this.computeDropZone(stack, { clientX, clientY }, zoneHint);
|
|
1650
1672
|
this.showDropIndicator(stack, zone);
|
|
@@ -1687,11 +1709,14 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1687
1709
|
placeholder.type = 'button';
|
|
1688
1710
|
placeholder.classList.add('dock-tab');
|
|
1689
1711
|
placeholder.dataset['placeholder'] = 'true';
|
|
1690
|
-
placeholder
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1712
|
+
// Keep the placeholder visually empty but reserving the same width
|
|
1713
|
+
placeholder.textContent = '';
|
|
1714
|
+
placeholder.setAttribute('aria-hidden', 'true');
|
|
1715
|
+
placeholder.style.width = `${dragged.offsetWidth}px`;
|
|
1716
|
+
// Hide the original dragged tab so it doesn't duplicate visually and free up its slot
|
|
1717
|
+
dragged.style.display = 'none';
|
|
1718
|
+
// Insert placeholder in the original position of the dragged tab
|
|
1719
|
+
header.insertBefore(placeholder, dragged);
|
|
1695
1720
|
if (this.dragState) {
|
|
1696
1721
|
this.dragState.placeholderHeader = header;
|
|
1697
1722
|
this.dragState.placeholderEl = placeholder;
|
|
@@ -1703,8 +1728,9 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1703
1728
|
if (!placeholder) {
|
|
1704
1729
|
return;
|
|
1705
1730
|
}
|
|
1731
|
+
const draggedPane = this.dragState?.pane ?? null;
|
|
1706
1732
|
const tabs = Array.from(header.querySelectorAll('.dock-tab'))
|
|
1707
|
-
.filter((t) => t !== placeholder);
|
|
1733
|
+
.filter((t) => t !== placeholder && (!draggedPane || t.dataset['pane'] !== draggedPane));
|
|
1708
1734
|
const clampedTarget = Math.max(0, Math.min(targetIndex, tabs.length));
|
|
1709
1735
|
const ref = tabs[clampedTarget] ?? null;
|
|
1710
1736
|
header.insertBefore(placeholder, ref);
|
|
@@ -1718,7 +1744,7 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1718
1744
|
? (Array.from(header.querySelectorAll('.dock-tab')).find((t) => t.dataset['pane'] === this.dragState?.pane) ?? null)
|
|
1719
1745
|
: null;
|
|
1720
1746
|
if (dragged) {
|
|
1721
|
-
dragged.style.
|
|
1747
|
+
dragged.style.display = '';
|
|
1722
1748
|
}
|
|
1723
1749
|
}
|
|
1724
1750
|
if (ph && ph.parentElement) {
|
|
@@ -1872,20 +1898,41 @@ class MintDockManagerElement extends HTMLElement {
|
|
|
1872
1898
|
this.dispatchLayoutChanged();
|
|
1873
1899
|
}
|
|
1874
1900
|
// Compute the intended tab insert index within a header based on pointer X
|
|
1901
|
+
// Adds a slight rightward bias and uses the placeholder rect (if present)
|
|
1902
|
+
// to ensure offsets are correct even when the dragged tab is display:none.
|
|
1875
1903
|
computeHeaderInsertIndex(header, clientX) {
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1878
|
-
if (tabs.length === 0) {
|
|
1904
|
+
const allTabs = Array.from(header.querySelectorAll('.dock-tab'));
|
|
1905
|
+
if (allTabs.length === 0) {
|
|
1879
1906
|
return 0;
|
|
1880
1907
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1908
|
+
const draggedPane = this.dragState?.pane ?? null;
|
|
1909
|
+
const draggedEl = draggedPane
|
|
1910
|
+
? (allTabs.find((t) => t.dataset['pane'] === draggedPane) ?? null)
|
|
1911
|
+
: null;
|
|
1912
|
+
const placeholderEl = header.querySelector('.dock-tab[data-placeholder="true"]');
|
|
1913
|
+
const targets = allTabs.filter((t) => t !== draggedEl && t !== placeholderEl);
|
|
1914
|
+
if (targets.length === 0) {
|
|
1915
|
+
return 0;
|
|
1916
|
+
}
|
|
1917
|
+
const rightBias = 12;
|
|
1918
|
+
const leftBias = 0;
|
|
1919
|
+
const baseRect = placeholderEl
|
|
1920
|
+
? placeholderEl.getBoundingClientRect()
|
|
1921
|
+
: draggedEl
|
|
1922
|
+
? draggedEl.getBoundingClientRect()
|
|
1923
|
+
: null;
|
|
1924
|
+
const rectValid = !!baseRect && Number.isFinite(baseRect.width) && baseRect.width > 0;
|
|
1925
|
+
const draggedCenter = rectValid && baseRect ? baseRect.left + baseRect.width / 2 : null;
|
|
1926
|
+
for (let i = 0; i < targets.length; i += 1) {
|
|
1927
|
+
const rect = targets[i].getBoundingClientRect();
|
|
1928
|
+
const baseMid = rect.left + rect.width / 2;
|
|
1929
|
+
const isRightOfDragged = draggedCenter !== null ? baseMid >= draggedCenter : false;
|
|
1930
|
+
const mid = isRightOfDragged ? baseMid + rightBias : baseMid - leftBias;
|
|
1884
1931
|
if (clientX < mid) {
|
|
1885
1932
|
return i;
|
|
1886
1933
|
}
|
|
1887
1934
|
}
|
|
1888
|
-
return
|
|
1935
|
+
return targets.length;
|
|
1889
1936
|
}
|
|
1890
1937
|
reorderPaneInLocationAtIndex(location, pane, targetIndex) {
|
|
1891
1938
|
const panes = location.node.panes;
|