dockview-core 6.0.3 → 6.0.6
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/dist/cjs/dockview/components/titlebar/tabs.js +14 -4
- package/dist/cjs/dockview/dockviewComponent.js +126 -20
- package/dist/cjs/dockview/dockviewGroupPanelModel.js +5 -3
- package/dist/dockview-core.js +96 -19
- package/dist/dockview-core.min.js +2 -2
- package/dist/dockview-core.min.js.map +1 -1
- package/dist/dockview-core.min.noStyle.js +2 -2
- package/dist/dockview-core.min.noStyle.js.map +1 -1
- package/dist/dockview-core.noStyle.js +96 -19
- package/dist/esm/dockview/components/titlebar/tabs.js +14 -4
- package/dist/esm/dockview/dockviewComponent.js +76 -11
- package/dist/esm/dockview/dockviewGroupPanelModel.js +5 -3
- package/dist/package/main.cjs.js +96 -19
- package/dist/package/main.cjs.min.js +2 -2
- package/dist/package/main.esm.min.mjs +2 -2
- package/dist/package/main.esm.mjs +96 -19
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dockview-core
|
|
3
|
-
* @version 6.0.
|
|
3
|
+
* @version 6.0.6
|
|
4
4
|
* @link https://github.com/mathuo/dockview
|
|
5
5
|
* @license MIT
|
|
6
6
|
*/
|
|
@@ -7205,10 +7205,12 @@
|
|
|
7205
7205
|
const index = this.indexOf(id);
|
|
7206
7206
|
const tabToRemove = this._tabs.splice(index, 1)[0];
|
|
7207
7207
|
this._tabMap.delete(id);
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7208
|
+
if (tabToRemove) {
|
|
7209
|
+
const { value, disposable } = tabToRemove;
|
|
7210
|
+
disposable.dispose();
|
|
7211
|
+
value.dispose();
|
|
7212
|
+
value.element.remove();
|
|
7213
|
+
}
|
|
7212
7214
|
// If a non-source tab was removed during active drag, refresh positions
|
|
7213
7215
|
if (this._animState) {
|
|
7214
7216
|
this._animState.tabPositions = this.snapshotTabPositions();
|
|
@@ -7880,6 +7882,14 @@
|
|
|
7880
7882
|
// handles panel transfer and tab group recreation.
|
|
7881
7883
|
// Use the REAL tab group ID from transfer data, not the
|
|
7882
7884
|
// potentially stale one from _animState.
|
|
7885
|
+
//
|
|
7886
|
+
// Clear any inline gap margin / shifting class applied to
|
|
7887
|
+
// destination tabs during dragover. Cross-group moves don't
|
|
7888
|
+
// run the FLIP path, and `moveGroupOrPanel` only inserts new
|
|
7889
|
+
// panels — it doesn't recreate existing destination tabs, so
|
|
7890
|
+
// their inline `margin-left` would otherwise persist as a
|
|
7891
|
+
// visible gap (issue #1243).
|
|
7892
|
+
this.resetTabTransforms();
|
|
7883
7893
|
this.accessor.moveGroupOrPanel({
|
|
7884
7894
|
from: {
|
|
7885
7895
|
groupId: data.groupId,
|
|
@@ -9660,15 +9670,17 @@
|
|
|
9660
9670
|
if (position === 'center') {
|
|
9661
9671
|
return;
|
|
9662
9672
|
}
|
|
9663
|
-
if (data.panelId === null) {
|
|
9664
|
-
//
|
|
9673
|
+
if (data.panelId === null && !data.tabGroupId) {
|
|
9674
|
+
// Full-group drops on self are a no-op.
|
|
9675
|
+
// Tab-group drags are partial moves: an edge drop
|
|
9676
|
+
// splits the layout and creates a new group.
|
|
9665
9677
|
return;
|
|
9666
9678
|
}
|
|
9667
9679
|
}
|
|
9668
9680
|
}
|
|
9669
9681
|
if (type === 'header') {
|
|
9670
9682
|
if (data.groupId === this.id) {
|
|
9671
|
-
if (data.panelId === null) {
|
|
9683
|
+
if (data.panelId === null && !data.tabGroupId) {
|
|
9672
9684
|
return;
|
|
9673
9685
|
}
|
|
9674
9686
|
}
|
|
@@ -13536,7 +13548,7 @@
|
|
|
13536
13548
|
// Collapse when the group becomes empty
|
|
13537
13549
|
const autoCollapseDisposable = group.model.onDidRemovePanel(() => {
|
|
13538
13550
|
if (group.model.isEmpty) {
|
|
13539
|
-
this.
|
|
13551
|
+
this.setEdgeGroupCollapsed(group, true);
|
|
13540
13552
|
}
|
|
13541
13553
|
});
|
|
13542
13554
|
this._edgeGroupDisposables.set(position, autoCollapseDisposable);
|
|
@@ -13580,6 +13592,13 @@
|
|
|
13580
13592
|
setEdgeGroupCollapsed(group, collapsed) {
|
|
13581
13593
|
for (const [position, edgeGroup] of this._edgeGroups) {
|
|
13582
13594
|
if (edgeGroup === group) {
|
|
13595
|
+
if (this._shellManager.isEdgeGroupCollapsed(position) ===
|
|
13596
|
+
collapsed) {
|
|
13597
|
+
// Skip the splitview resize on a no-op: with non-zero
|
|
13598
|
+
// theme gap, redundant resizeView calls accumulate
|
|
13599
|
+
// rounding drift that gradually shrinks the group.
|
|
13600
|
+
return;
|
|
13601
|
+
}
|
|
13583
13602
|
this._shellManager.setEdgeGroupCollapsed(position, collapsed);
|
|
13584
13603
|
edgeGroup.api._onDidCollapsedChange.fire({
|
|
13585
13604
|
isCollapsed: collapsed,
|
|
@@ -14532,7 +14551,14 @@
|
|
|
14532
14551
|
const label = tabGroup.label;
|
|
14533
14552
|
const color = tabGroup.color;
|
|
14534
14553
|
const collapsed = tabGroup.collapsed;
|
|
14554
|
+
const componentParams = tabGroup.componentParams;
|
|
14535
14555
|
const panelIds = [...tabGroup.panelIds];
|
|
14556
|
+
// Capture the destination's grid location BEFORE potentially
|
|
14557
|
+
// removing the source group, in case source === destination and
|
|
14558
|
+
// the source becomes empty after panel removal.
|
|
14559
|
+
const referenceLocation = destinationTarget && destinationTarget !== 'center'
|
|
14560
|
+
? getGridLocation(destinationGroup.element)
|
|
14561
|
+
: undefined;
|
|
14536
14562
|
// Remove panels from the source group
|
|
14537
14563
|
const removedPanels = this.movingLock(() => panelIds
|
|
14538
14564
|
.map((pid) => sourceGroup.model.removePanel(pid, {
|
|
@@ -14543,11 +14569,6 @@
|
|
|
14543
14569
|
if (removedPanels.length === 0) {
|
|
14544
14570
|
return;
|
|
14545
14571
|
}
|
|
14546
|
-
if (!options.keepEmptyGroups &&
|
|
14547
|
-
sourceGroup.model.size === 0 &&
|
|
14548
|
-
sourceGroup !== destinationGroup) {
|
|
14549
|
-
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
14550
|
-
}
|
|
14551
14572
|
const addPanelsToGroup = (targetGroup) => {
|
|
14552
14573
|
this.movingLock(() => {
|
|
14553
14574
|
for (const panel of removedPanels) {
|
|
@@ -14563,6 +14584,7 @@
|
|
|
14563
14584
|
label,
|
|
14564
14585
|
color,
|
|
14565
14586
|
collapsed,
|
|
14587
|
+
componentParams,
|
|
14566
14588
|
});
|
|
14567
14589
|
for (const panel of removedPanels) {
|
|
14568
14590
|
targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
@@ -14577,15 +14599,27 @@
|
|
|
14577
14599
|
});
|
|
14578
14600
|
}
|
|
14579
14601
|
};
|
|
14580
|
-
|
|
14581
|
-
|
|
14602
|
+
let targetGroup;
|
|
14603
|
+
if (!destinationTarget ||
|
|
14604
|
+
destinationTarget === 'center' ||
|
|
14605
|
+
!referenceLocation) {
|
|
14606
|
+
targetGroup = destinationGroup;
|
|
14582
14607
|
}
|
|
14583
14608
|
else {
|
|
14584
|
-
const referenceLocation = getGridLocation(destinationGroup.element);
|
|
14585
14609
|
const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
|
|
14586
|
-
|
|
14587
|
-
addPanelsToGroup(newGroup);
|
|
14610
|
+
targetGroup = this.createGroupAtLocation(dropLocation);
|
|
14588
14611
|
}
|
|
14612
|
+
// Remove the source group if it became empty. We compare against
|
|
14613
|
+
// the actual targetGroup (which is a freshly-created group for
|
|
14614
|
+
// edge drops) rather than the originally-passed destinationGroup,
|
|
14615
|
+
// so a tab-group drag onto its own group's edge still cleans up
|
|
14616
|
+
// the now-empty source.
|
|
14617
|
+
if (!options.keepEmptyGroups &&
|
|
14618
|
+
sourceGroup.model.size === 0 &&
|
|
14619
|
+
sourceGroup !== targetGroup) {
|
|
14620
|
+
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
14621
|
+
}
|
|
14622
|
+
addPanelsToGroup(targetGroup);
|
|
14589
14623
|
}
|
|
14590
14624
|
moveGroup(options) {
|
|
14591
14625
|
const from = options.from.group;
|
|
@@ -14597,6 +14631,16 @@
|
|
|
14597
14631
|
let source = from;
|
|
14598
14632
|
if (target === 'center') {
|
|
14599
14633
|
const activePanel = from.activePanel;
|
|
14634
|
+
// Snapshot tab group metadata before removing panels so we
|
|
14635
|
+
// can recreate the tab groups in the destination after the
|
|
14636
|
+
// panels are merged in.
|
|
14637
|
+
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
14638
|
+
label: tg.label,
|
|
14639
|
+
color: tg.color,
|
|
14640
|
+
collapsed: tg.collapsed,
|
|
14641
|
+
componentParams: tg.componentParams,
|
|
14642
|
+
panelIds: [...tg.panelIds],
|
|
14643
|
+
}));
|
|
14600
14644
|
const panels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, {
|
|
14601
14645
|
skipSetActive: true,
|
|
14602
14646
|
})));
|
|
@@ -14611,6 +14655,17 @@
|
|
|
14611
14655
|
});
|
|
14612
14656
|
}
|
|
14613
14657
|
});
|
|
14658
|
+
for (const snapshot of tabGroupSnapshots) {
|
|
14659
|
+
const newTabGroup = to.model.createTabGroup({
|
|
14660
|
+
label: snapshot.label,
|
|
14661
|
+
color: snapshot.color,
|
|
14662
|
+
collapsed: snapshot.collapsed,
|
|
14663
|
+
componentParams: snapshot.componentParams,
|
|
14664
|
+
});
|
|
14665
|
+
for (const panelId of snapshot.panelIds) {
|
|
14666
|
+
to.model.addPanelToTabGroup(newTabGroup.id, panelId);
|
|
14667
|
+
}
|
|
14668
|
+
}
|
|
14614
14669
|
// Ensure group becomes active after move
|
|
14615
14670
|
if (options.skipSetActive !== true) {
|
|
14616
14671
|
// For center moves (merges), we need to ensure the target group is active
|
|
@@ -14634,6 +14689,17 @@
|
|
|
14634
14689
|
* positions `source` like any other moved group.
|
|
14635
14690
|
*/
|
|
14636
14691
|
const activePanel = from.activePanel;
|
|
14692
|
+
// Snapshot tab group metadata so the new group inherits
|
|
14693
|
+
// the tab grouping from the edge slot.
|
|
14694
|
+
const tabGroupSnapshots = from.model
|
|
14695
|
+
.getTabGroups()
|
|
14696
|
+
.map((tg) => ({
|
|
14697
|
+
label: tg.label,
|
|
14698
|
+
color: tg.color,
|
|
14699
|
+
collapsed: tg.collapsed,
|
|
14700
|
+
componentParams: tg.componentParams,
|
|
14701
|
+
panelIds: [...tg.panelIds],
|
|
14702
|
+
}));
|
|
14637
14703
|
const movedPanels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, { skipSetActive: true })));
|
|
14638
14704
|
source = this.createGroup();
|
|
14639
14705
|
this.movingLock(() => {
|
|
@@ -14644,6 +14710,17 @@
|
|
|
14644
14710
|
});
|
|
14645
14711
|
}
|
|
14646
14712
|
});
|
|
14713
|
+
for (const snapshot of tabGroupSnapshots) {
|
|
14714
|
+
const newTabGroup = source.model.createTabGroup({
|
|
14715
|
+
label: snapshot.label,
|
|
14716
|
+
color: snapshot.color,
|
|
14717
|
+
collapsed: snapshot.collapsed,
|
|
14718
|
+
componentParams: snapshot.componentParams,
|
|
14719
|
+
});
|
|
14720
|
+
for (const panelId of snapshot.panelIds) {
|
|
14721
|
+
source.model.addPanelToTabGroup(newTabGroup.id, panelId);
|
|
14722
|
+
}
|
|
14723
|
+
}
|
|
14647
14724
|
}
|
|
14648
14725
|
else {
|
|
14649
14726
|
switch (from.api.location.type) {
|
|
@@ -604,10 +604,12 @@ export class Tabs extends CompositeDisposable {
|
|
|
604
604
|
const index = this.indexOf(id);
|
|
605
605
|
const tabToRemove = this._tabs.splice(index, 1)[0];
|
|
606
606
|
this._tabMap.delete(id);
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
607
|
+
if (tabToRemove) {
|
|
608
|
+
const { value, disposable } = tabToRemove;
|
|
609
|
+
disposable.dispose();
|
|
610
|
+
value.dispose();
|
|
611
|
+
value.element.remove();
|
|
612
|
+
}
|
|
611
613
|
// If a non-source tab was removed during active drag, refresh positions
|
|
612
614
|
if (this._animState) {
|
|
613
615
|
this._animState.tabPositions = this.snapshotTabPositions();
|
|
@@ -1279,6 +1281,14 @@ export class Tabs extends CompositeDisposable {
|
|
|
1279
1281
|
// handles panel transfer and tab group recreation.
|
|
1280
1282
|
// Use the REAL tab group ID from transfer data, not the
|
|
1281
1283
|
// potentially stale one from _animState.
|
|
1284
|
+
//
|
|
1285
|
+
// Clear any inline gap margin / shifting class applied to
|
|
1286
|
+
// destination tabs during dragover. Cross-group moves don't
|
|
1287
|
+
// run the FLIP path, and `moveGroupOrPanel` only inserts new
|
|
1288
|
+
// panels — it doesn't recreate existing destination tabs, so
|
|
1289
|
+
// their inline `margin-left` would otherwise persist as a
|
|
1290
|
+
// visible gap (issue #1243).
|
|
1291
|
+
this.resetTabTransforms();
|
|
1282
1292
|
this.accessor.moveGroupOrPanel({
|
|
1283
1293
|
from: {
|
|
1284
1294
|
groupId: data.groupId,
|
|
@@ -924,7 +924,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
924
924
|
// Collapse when the group becomes empty
|
|
925
925
|
const autoCollapseDisposable = group.model.onDidRemovePanel(() => {
|
|
926
926
|
if (group.model.isEmpty) {
|
|
927
|
-
this.
|
|
927
|
+
this.setEdgeGroupCollapsed(group, true);
|
|
928
928
|
}
|
|
929
929
|
});
|
|
930
930
|
this._edgeGroupDisposables.set(position, autoCollapseDisposable);
|
|
@@ -968,6 +968,13 @@ export class DockviewComponent extends BaseGrid {
|
|
|
968
968
|
setEdgeGroupCollapsed(group, collapsed) {
|
|
969
969
|
for (const [position, edgeGroup] of this._edgeGroups) {
|
|
970
970
|
if (edgeGroup === group) {
|
|
971
|
+
if (this._shellManager.isEdgeGroupCollapsed(position) ===
|
|
972
|
+
collapsed) {
|
|
973
|
+
// Skip the splitview resize on a no-op: with non-zero
|
|
974
|
+
// theme gap, redundant resizeView calls accumulate
|
|
975
|
+
// rounding drift that gradually shrinks the group.
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
971
978
|
this._shellManager.setEdgeGroupCollapsed(position, collapsed);
|
|
972
979
|
edgeGroup.api._onDidCollapsedChange.fire({
|
|
973
980
|
isCollapsed: collapsed,
|
|
@@ -1920,7 +1927,14 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1920
1927
|
const label = tabGroup.label;
|
|
1921
1928
|
const color = tabGroup.color;
|
|
1922
1929
|
const collapsed = tabGroup.collapsed;
|
|
1930
|
+
const componentParams = tabGroup.componentParams;
|
|
1923
1931
|
const panelIds = [...tabGroup.panelIds];
|
|
1932
|
+
// Capture the destination's grid location BEFORE potentially
|
|
1933
|
+
// removing the source group, in case source === destination and
|
|
1934
|
+
// the source becomes empty after panel removal.
|
|
1935
|
+
const referenceLocation = destinationTarget && destinationTarget !== 'center'
|
|
1936
|
+
? getGridLocation(destinationGroup.element)
|
|
1937
|
+
: undefined;
|
|
1924
1938
|
// Remove panels from the source group
|
|
1925
1939
|
const removedPanels = this.movingLock(() => panelIds
|
|
1926
1940
|
.map((pid) => sourceGroup.model.removePanel(pid, {
|
|
@@ -1931,11 +1945,6 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1931
1945
|
if (removedPanels.length === 0) {
|
|
1932
1946
|
return;
|
|
1933
1947
|
}
|
|
1934
|
-
if (!options.keepEmptyGroups &&
|
|
1935
|
-
sourceGroup.model.size === 0 &&
|
|
1936
|
-
sourceGroup !== destinationGroup) {
|
|
1937
|
-
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
1938
|
-
}
|
|
1939
1948
|
const addPanelsToGroup = (targetGroup) => {
|
|
1940
1949
|
this.movingLock(() => {
|
|
1941
1950
|
for (const panel of removedPanels) {
|
|
@@ -1951,6 +1960,7 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1951
1960
|
label,
|
|
1952
1961
|
color,
|
|
1953
1962
|
collapsed,
|
|
1963
|
+
componentParams,
|
|
1954
1964
|
});
|
|
1955
1965
|
for (const panel of removedPanels) {
|
|
1956
1966
|
targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
@@ -1965,15 +1975,27 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1965
1975
|
});
|
|
1966
1976
|
}
|
|
1967
1977
|
};
|
|
1968
|
-
|
|
1969
|
-
|
|
1978
|
+
let targetGroup;
|
|
1979
|
+
if (!destinationTarget ||
|
|
1980
|
+
destinationTarget === 'center' ||
|
|
1981
|
+
!referenceLocation) {
|
|
1982
|
+
targetGroup = destinationGroup;
|
|
1970
1983
|
}
|
|
1971
1984
|
else {
|
|
1972
|
-
const referenceLocation = getGridLocation(destinationGroup.element);
|
|
1973
1985
|
const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
|
|
1974
|
-
|
|
1975
|
-
addPanelsToGroup(newGroup);
|
|
1986
|
+
targetGroup = this.createGroupAtLocation(dropLocation);
|
|
1976
1987
|
}
|
|
1988
|
+
// Remove the source group if it became empty. We compare against
|
|
1989
|
+
// the actual targetGroup (which is a freshly-created group for
|
|
1990
|
+
// edge drops) rather than the originally-passed destinationGroup,
|
|
1991
|
+
// so a tab-group drag onto its own group's edge still cleans up
|
|
1992
|
+
// the now-empty source.
|
|
1993
|
+
if (!options.keepEmptyGroups &&
|
|
1994
|
+
sourceGroup.model.size === 0 &&
|
|
1995
|
+
sourceGroup !== targetGroup) {
|
|
1996
|
+
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
1997
|
+
}
|
|
1998
|
+
addPanelsToGroup(targetGroup);
|
|
1977
1999
|
}
|
|
1978
2000
|
moveGroup(options) {
|
|
1979
2001
|
const from = options.from.group;
|
|
@@ -1985,6 +2007,16 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1985
2007
|
let source = from;
|
|
1986
2008
|
if (target === 'center') {
|
|
1987
2009
|
const activePanel = from.activePanel;
|
|
2010
|
+
// Snapshot tab group metadata before removing panels so we
|
|
2011
|
+
// can recreate the tab groups in the destination after the
|
|
2012
|
+
// panels are merged in.
|
|
2013
|
+
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
2014
|
+
label: tg.label,
|
|
2015
|
+
color: tg.color,
|
|
2016
|
+
collapsed: tg.collapsed,
|
|
2017
|
+
componentParams: tg.componentParams,
|
|
2018
|
+
panelIds: [...tg.panelIds],
|
|
2019
|
+
}));
|
|
1988
2020
|
const panels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, {
|
|
1989
2021
|
skipSetActive: true,
|
|
1990
2022
|
})));
|
|
@@ -1999,6 +2031,17 @@ export class DockviewComponent extends BaseGrid {
|
|
|
1999
2031
|
});
|
|
2000
2032
|
}
|
|
2001
2033
|
});
|
|
2034
|
+
for (const snapshot of tabGroupSnapshots) {
|
|
2035
|
+
const newTabGroup = to.model.createTabGroup({
|
|
2036
|
+
label: snapshot.label,
|
|
2037
|
+
color: snapshot.color,
|
|
2038
|
+
collapsed: snapshot.collapsed,
|
|
2039
|
+
componentParams: snapshot.componentParams,
|
|
2040
|
+
});
|
|
2041
|
+
for (const panelId of snapshot.panelIds) {
|
|
2042
|
+
to.model.addPanelToTabGroup(newTabGroup.id, panelId);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2002
2045
|
// Ensure group becomes active after move
|
|
2003
2046
|
if (options.skipSetActive !== true) {
|
|
2004
2047
|
// For center moves (merges), we need to ensure the target group is active
|
|
@@ -2022,6 +2065,17 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2022
2065
|
* positions `source` like any other moved group.
|
|
2023
2066
|
*/
|
|
2024
2067
|
const activePanel = from.activePanel;
|
|
2068
|
+
// Snapshot tab group metadata so the new group inherits
|
|
2069
|
+
// the tab grouping from the edge slot.
|
|
2070
|
+
const tabGroupSnapshots = from.model
|
|
2071
|
+
.getTabGroups()
|
|
2072
|
+
.map((tg) => ({
|
|
2073
|
+
label: tg.label,
|
|
2074
|
+
color: tg.color,
|
|
2075
|
+
collapsed: tg.collapsed,
|
|
2076
|
+
componentParams: tg.componentParams,
|
|
2077
|
+
panelIds: [...tg.panelIds],
|
|
2078
|
+
}));
|
|
2025
2079
|
const movedPanels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, { skipSetActive: true })));
|
|
2026
2080
|
source = this.createGroup();
|
|
2027
2081
|
this.movingLock(() => {
|
|
@@ -2032,6 +2086,17 @@ export class DockviewComponent extends BaseGrid {
|
|
|
2032
2086
|
});
|
|
2033
2087
|
}
|
|
2034
2088
|
});
|
|
2089
|
+
for (const snapshot of tabGroupSnapshots) {
|
|
2090
|
+
const newTabGroup = source.model.createTabGroup({
|
|
2091
|
+
label: snapshot.label,
|
|
2092
|
+
color: snapshot.color,
|
|
2093
|
+
collapsed: snapshot.collapsed,
|
|
2094
|
+
componentParams: snapshot.componentParams,
|
|
2095
|
+
});
|
|
2096
|
+
for (const panelId of snapshot.panelIds) {
|
|
2097
|
+
source.model.addPanelToTabGroup(newTabGroup.id, panelId);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2035
2100
|
}
|
|
2036
2101
|
else {
|
|
2037
2102
|
switch (from.api.location.type) {
|
|
@@ -1061,15 +1061,17 @@ export class DockviewGroupPanelModel extends CompositeDisposable {
|
|
|
1061
1061
|
if (position === 'center') {
|
|
1062
1062
|
return;
|
|
1063
1063
|
}
|
|
1064
|
-
if (data.panelId === null) {
|
|
1065
|
-
//
|
|
1064
|
+
if (data.panelId === null && !data.tabGroupId) {
|
|
1065
|
+
// Full-group drops on self are a no-op.
|
|
1066
|
+
// Tab-group drags are partial moves: an edge drop
|
|
1067
|
+
// splits the layout and creates a new group.
|
|
1066
1068
|
return;
|
|
1067
1069
|
}
|
|
1068
1070
|
}
|
|
1069
1071
|
}
|
|
1070
1072
|
if (type === 'header') {
|
|
1071
1073
|
if (data.groupId === this.id) {
|
|
1072
|
-
if (data.panelId === null) {
|
|
1074
|
+
if (data.panelId === null && !data.tabGroupId) {
|
|
1073
1075
|
return;
|
|
1074
1076
|
}
|
|
1075
1077
|
}
|
package/dist/package/main.cjs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dockview-core
|
|
3
|
-
* @version 6.0.
|
|
3
|
+
* @version 6.0.6
|
|
4
4
|
* @link https://github.com/mathuo/dockview
|
|
5
5
|
* @license MIT
|
|
6
6
|
*/
|
|
@@ -7201,10 +7201,12 @@ class Tabs extends CompositeDisposable {
|
|
|
7201
7201
|
const index = this.indexOf(id);
|
|
7202
7202
|
const tabToRemove = this._tabs.splice(index, 1)[0];
|
|
7203
7203
|
this._tabMap.delete(id);
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7204
|
+
if (tabToRemove) {
|
|
7205
|
+
const { value, disposable } = tabToRemove;
|
|
7206
|
+
disposable.dispose();
|
|
7207
|
+
value.dispose();
|
|
7208
|
+
value.element.remove();
|
|
7209
|
+
}
|
|
7208
7210
|
// If a non-source tab was removed during active drag, refresh positions
|
|
7209
7211
|
if (this._animState) {
|
|
7210
7212
|
this._animState.tabPositions = this.snapshotTabPositions();
|
|
@@ -7876,6 +7878,14 @@ class Tabs extends CompositeDisposable {
|
|
|
7876
7878
|
// handles panel transfer and tab group recreation.
|
|
7877
7879
|
// Use the REAL tab group ID from transfer data, not the
|
|
7878
7880
|
// potentially stale one from _animState.
|
|
7881
|
+
//
|
|
7882
|
+
// Clear any inline gap margin / shifting class applied to
|
|
7883
|
+
// destination tabs during dragover. Cross-group moves don't
|
|
7884
|
+
// run the FLIP path, and `moveGroupOrPanel` only inserts new
|
|
7885
|
+
// panels — it doesn't recreate existing destination tabs, so
|
|
7886
|
+
// their inline `margin-left` would otherwise persist as a
|
|
7887
|
+
// visible gap (issue #1243).
|
|
7888
|
+
this.resetTabTransforms();
|
|
7879
7889
|
this.accessor.moveGroupOrPanel({
|
|
7880
7890
|
from: {
|
|
7881
7891
|
groupId: data.groupId,
|
|
@@ -9656,15 +9666,17 @@ class DockviewGroupPanelModel extends CompositeDisposable {
|
|
|
9656
9666
|
if (position === 'center') {
|
|
9657
9667
|
return;
|
|
9658
9668
|
}
|
|
9659
|
-
if (data.panelId === null) {
|
|
9660
|
-
//
|
|
9669
|
+
if (data.panelId === null && !data.tabGroupId) {
|
|
9670
|
+
// Full-group drops on self are a no-op.
|
|
9671
|
+
// Tab-group drags are partial moves: an edge drop
|
|
9672
|
+
// splits the layout and creates a new group.
|
|
9661
9673
|
return;
|
|
9662
9674
|
}
|
|
9663
9675
|
}
|
|
9664
9676
|
}
|
|
9665
9677
|
if (type === 'header') {
|
|
9666
9678
|
if (data.groupId === this.id) {
|
|
9667
|
-
if (data.panelId === null) {
|
|
9679
|
+
if (data.panelId === null && !data.tabGroupId) {
|
|
9668
9680
|
return;
|
|
9669
9681
|
}
|
|
9670
9682
|
}
|
|
@@ -13532,7 +13544,7 @@ class DockviewComponent extends BaseGrid {
|
|
|
13532
13544
|
// Collapse when the group becomes empty
|
|
13533
13545
|
const autoCollapseDisposable = group.model.onDidRemovePanel(() => {
|
|
13534
13546
|
if (group.model.isEmpty) {
|
|
13535
|
-
this.
|
|
13547
|
+
this.setEdgeGroupCollapsed(group, true);
|
|
13536
13548
|
}
|
|
13537
13549
|
});
|
|
13538
13550
|
this._edgeGroupDisposables.set(position, autoCollapseDisposable);
|
|
@@ -13576,6 +13588,13 @@ class DockviewComponent extends BaseGrid {
|
|
|
13576
13588
|
setEdgeGroupCollapsed(group, collapsed) {
|
|
13577
13589
|
for (const [position, edgeGroup] of this._edgeGroups) {
|
|
13578
13590
|
if (edgeGroup === group) {
|
|
13591
|
+
if (this._shellManager.isEdgeGroupCollapsed(position) ===
|
|
13592
|
+
collapsed) {
|
|
13593
|
+
// Skip the splitview resize on a no-op: with non-zero
|
|
13594
|
+
// theme gap, redundant resizeView calls accumulate
|
|
13595
|
+
// rounding drift that gradually shrinks the group.
|
|
13596
|
+
return;
|
|
13597
|
+
}
|
|
13579
13598
|
this._shellManager.setEdgeGroupCollapsed(position, collapsed);
|
|
13580
13599
|
edgeGroup.api._onDidCollapsedChange.fire({
|
|
13581
13600
|
isCollapsed: collapsed,
|
|
@@ -14528,7 +14547,14 @@ class DockviewComponent extends BaseGrid {
|
|
|
14528
14547
|
const label = tabGroup.label;
|
|
14529
14548
|
const color = tabGroup.color;
|
|
14530
14549
|
const collapsed = tabGroup.collapsed;
|
|
14550
|
+
const componentParams = tabGroup.componentParams;
|
|
14531
14551
|
const panelIds = [...tabGroup.panelIds];
|
|
14552
|
+
// Capture the destination's grid location BEFORE potentially
|
|
14553
|
+
// removing the source group, in case source === destination and
|
|
14554
|
+
// the source becomes empty after panel removal.
|
|
14555
|
+
const referenceLocation = destinationTarget && destinationTarget !== 'center'
|
|
14556
|
+
? getGridLocation(destinationGroup.element)
|
|
14557
|
+
: undefined;
|
|
14532
14558
|
// Remove panels from the source group
|
|
14533
14559
|
const removedPanels = this.movingLock(() => panelIds
|
|
14534
14560
|
.map((pid) => sourceGroup.model.removePanel(pid, {
|
|
@@ -14539,11 +14565,6 @@ class DockviewComponent extends BaseGrid {
|
|
|
14539
14565
|
if (removedPanels.length === 0) {
|
|
14540
14566
|
return;
|
|
14541
14567
|
}
|
|
14542
|
-
if (!options.keepEmptyGroups &&
|
|
14543
|
-
sourceGroup.model.size === 0 &&
|
|
14544
|
-
sourceGroup !== destinationGroup) {
|
|
14545
|
-
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
14546
|
-
}
|
|
14547
14568
|
const addPanelsToGroup = (targetGroup) => {
|
|
14548
14569
|
this.movingLock(() => {
|
|
14549
14570
|
for (const panel of removedPanels) {
|
|
@@ -14559,6 +14580,7 @@ class DockviewComponent extends BaseGrid {
|
|
|
14559
14580
|
label,
|
|
14560
14581
|
color,
|
|
14561
14582
|
collapsed,
|
|
14583
|
+
componentParams,
|
|
14562
14584
|
});
|
|
14563
14585
|
for (const panel of removedPanels) {
|
|
14564
14586
|
targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
@@ -14573,15 +14595,27 @@ class DockviewComponent extends BaseGrid {
|
|
|
14573
14595
|
});
|
|
14574
14596
|
}
|
|
14575
14597
|
};
|
|
14576
|
-
|
|
14577
|
-
|
|
14598
|
+
let targetGroup;
|
|
14599
|
+
if (!destinationTarget ||
|
|
14600
|
+
destinationTarget === 'center' ||
|
|
14601
|
+
!referenceLocation) {
|
|
14602
|
+
targetGroup = destinationGroup;
|
|
14578
14603
|
}
|
|
14579
14604
|
else {
|
|
14580
|
-
const referenceLocation = getGridLocation(destinationGroup.element);
|
|
14581
14605
|
const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
|
|
14582
|
-
|
|
14583
|
-
addPanelsToGroup(newGroup);
|
|
14606
|
+
targetGroup = this.createGroupAtLocation(dropLocation);
|
|
14584
14607
|
}
|
|
14608
|
+
// Remove the source group if it became empty. We compare against
|
|
14609
|
+
// the actual targetGroup (which is a freshly-created group for
|
|
14610
|
+
// edge drops) rather than the originally-passed destinationGroup,
|
|
14611
|
+
// so a tab-group drag onto its own group's edge still cleans up
|
|
14612
|
+
// the now-empty source.
|
|
14613
|
+
if (!options.keepEmptyGroups &&
|
|
14614
|
+
sourceGroup.model.size === 0 &&
|
|
14615
|
+
sourceGroup !== targetGroup) {
|
|
14616
|
+
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
14617
|
+
}
|
|
14618
|
+
addPanelsToGroup(targetGroup);
|
|
14585
14619
|
}
|
|
14586
14620
|
moveGroup(options) {
|
|
14587
14621
|
const from = options.from.group;
|
|
@@ -14593,6 +14627,16 @@ class DockviewComponent extends BaseGrid {
|
|
|
14593
14627
|
let source = from;
|
|
14594
14628
|
if (target === 'center') {
|
|
14595
14629
|
const activePanel = from.activePanel;
|
|
14630
|
+
// Snapshot tab group metadata before removing panels so we
|
|
14631
|
+
// can recreate the tab groups in the destination after the
|
|
14632
|
+
// panels are merged in.
|
|
14633
|
+
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
14634
|
+
label: tg.label,
|
|
14635
|
+
color: tg.color,
|
|
14636
|
+
collapsed: tg.collapsed,
|
|
14637
|
+
componentParams: tg.componentParams,
|
|
14638
|
+
panelIds: [...tg.panelIds],
|
|
14639
|
+
}));
|
|
14596
14640
|
const panels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, {
|
|
14597
14641
|
skipSetActive: true,
|
|
14598
14642
|
})));
|
|
@@ -14607,6 +14651,17 @@ class DockviewComponent extends BaseGrid {
|
|
|
14607
14651
|
});
|
|
14608
14652
|
}
|
|
14609
14653
|
});
|
|
14654
|
+
for (const snapshot of tabGroupSnapshots) {
|
|
14655
|
+
const newTabGroup = to.model.createTabGroup({
|
|
14656
|
+
label: snapshot.label,
|
|
14657
|
+
color: snapshot.color,
|
|
14658
|
+
collapsed: snapshot.collapsed,
|
|
14659
|
+
componentParams: snapshot.componentParams,
|
|
14660
|
+
});
|
|
14661
|
+
for (const panelId of snapshot.panelIds) {
|
|
14662
|
+
to.model.addPanelToTabGroup(newTabGroup.id, panelId);
|
|
14663
|
+
}
|
|
14664
|
+
}
|
|
14610
14665
|
// Ensure group becomes active after move
|
|
14611
14666
|
if (options.skipSetActive !== true) {
|
|
14612
14667
|
// For center moves (merges), we need to ensure the target group is active
|
|
@@ -14630,6 +14685,17 @@ class DockviewComponent extends BaseGrid {
|
|
|
14630
14685
|
* positions `source` like any other moved group.
|
|
14631
14686
|
*/
|
|
14632
14687
|
const activePanel = from.activePanel;
|
|
14688
|
+
// Snapshot tab group metadata so the new group inherits
|
|
14689
|
+
// the tab grouping from the edge slot.
|
|
14690
|
+
const tabGroupSnapshots = from.model
|
|
14691
|
+
.getTabGroups()
|
|
14692
|
+
.map((tg) => ({
|
|
14693
|
+
label: tg.label,
|
|
14694
|
+
color: tg.color,
|
|
14695
|
+
collapsed: tg.collapsed,
|
|
14696
|
+
componentParams: tg.componentParams,
|
|
14697
|
+
panelIds: [...tg.panelIds],
|
|
14698
|
+
}));
|
|
14633
14699
|
const movedPanels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, { skipSetActive: true })));
|
|
14634
14700
|
source = this.createGroup();
|
|
14635
14701
|
this.movingLock(() => {
|
|
@@ -14640,6 +14706,17 @@ class DockviewComponent extends BaseGrid {
|
|
|
14640
14706
|
});
|
|
14641
14707
|
}
|
|
14642
14708
|
});
|
|
14709
|
+
for (const snapshot of tabGroupSnapshots) {
|
|
14710
|
+
const newTabGroup = source.model.createTabGroup({
|
|
14711
|
+
label: snapshot.label,
|
|
14712
|
+
color: snapshot.color,
|
|
14713
|
+
collapsed: snapshot.collapsed,
|
|
14714
|
+
componentParams: snapshot.componentParams,
|
|
14715
|
+
});
|
|
14716
|
+
for (const panelId of snapshot.panelIds) {
|
|
14717
|
+
source.model.addPanelToTabGroup(newTabGroup.id, panelId);
|
|
14718
|
+
}
|
|
14719
|
+
}
|
|
14643
14720
|
}
|
|
14644
14721
|
else {
|
|
14645
14722
|
switch (from.api.location.type) {
|