dockview-react 8.1.0 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dockview-react.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dockview-react
|
|
3
|
-
* @version 8.
|
|
3
|
+
* @version 8.3.0
|
|
4
4
|
* @link https://github.com/dockview/dockview
|
|
5
5
|
* @license MIT
|
|
6
6
|
*/
|
|
@@ -51,7 +51,7 @@ react_dom = __toESM(react_dom);
|
|
|
51
51
|
//#region ../dockview-core/dist/package/main.esm.mjs
|
|
52
52
|
/**
|
|
53
53
|
* dockview-core
|
|
54
|
-
* @version 8.
|
|
54
|
+
* @version 8.3.0
|
|
55
55
|
* @link https://github.com/dockview/dockview
|
|
56
56
|
* @license MIT
|
|
57
57
|
*/
|
|
@@ -1077,8 +1077,14 @@ react_dom = __toESM(react_dom);
|
|
|
1077
1077
|
container.appendChild(view.element);
|
|
1078
1078
|
let viewSize;
|
|
1079
1079
|
if (typeof size === "number") viewSize = size;
|
|
1080
|
-
else if (size.type === "split")
|
|
1081
|
-
|
|
1080
|
+
else if (size.type === "split") {
|
|
1081
|
+
const splitTarget = this.viewItems[size.index];
|
|
1082
|
+
if (splitTarget) {
|
|
1083
|
+
const half = Math.floor(splitTarget.size / 2);
|
|
1084
|
+
viewSize = splitTarget.size - half;
|
|
1085
|
+
splitTarget.size = half;
|
|
1086
|
+
} else viewSize = this.getViewSize(size.index) / 2;
|
|
1087
|
+
} else if (size.type === "invisible") viewSize = { cachedVisibleSize: size.cachedVisibleSize };
|
|
1082
1088
|
else viewSize = view.minimumSize;
|
|
1083
1089
|
const disposable = view.onDidChange((newSize) => this.onDidChange(viewItem, newSize.size));
|
|
1084
1090
|
const viewItem = new ViewItem(container, view, viewSize, { dispose: () => {
|
|
@@ -5718,7 +5724,7 @@ react_dom = __toESM(react_dom);
|
|
|
5718
5724
|
};
|
|
5719
5725
|
case "auto":
|
|
5720
5726
|
case void 0:
|
|
5721
|
-
default: return isCoarsePrimaryInput$
|
|
5727
|
+
default: return isCoarsePrimaryInput$2() ? {
|
|
5722
5728
|
html5: false,
|
|
5723
5729
|
pointer: true,
|
|
5724
5730
|
pointerHandlesMouse: true
|
|
@@ -5729,7 +5735,7 @@ react_dom = __toESM(react_dom);
|
|
|
5729
5735
|
};
|
|
5730
5736
|
}
|
|
5731
5737
|
}
|
|
5732
|
-
function isCoarsePrimaryInput$
|
|
5738
|
+
function isCoarsePrimaryInput$2() {
|
|
5733
5739
|
if (globalThis.window === void 0 || !globalThis.matchMedia) return false;
|
|
5734
5740
|
const coarse = globalThis.matchMedia("(pointer: coarse)").matches;
|
|
5735
5741
|
const fine = globalThis.matchMedia("(pointer: fine)").matches;
|
|
@@ -7850,11 +7856,28 @@ react_dom = __toESM(react_dom);
|
|
|
7850
7856
|
if (this._voidContainer && related && (related === this._voidContainer || this._voidContainer.contains(related))) return;
|
|
7851
7857
|
this.resetTabTransforms();
|
|
7852
7858
|
if (this._animState.sourceIndex === -1) {
|
|
7853
|
-
|
|
7854
|
-
(_this$group$model$dro2 = this.group.model.dropTargetContainer) === null || _this$group$model$dro2 === void 0 || (_this$group$model$dro2 = _this$group$model$dro2.model) === null || _this$group$model$dro2 === void 0 || _this$group$model$dro2.clear();
|
|
7859
|
+
this.clearHeaderAnchorOverlay();
|
|
7855
7860
|
this._animState = null;
|
|
7856
7861
|
} else this._animState.currentInsertionIndex = null;
|
|
7857
7862
|
}
|
|
7863
|
+
/**
|
|
7864
|
+
* Clear the anchored overlay only when this header is what rendered it.
|
|
7865
|
+
* The container is shared with the group's content drop target, which
|
|
7866
|
+
* renders into it on the same frame the cursor leaves the strip: the
|
|
7867
|
+
* pointer backend calls `handleDragOver` on the new target before the
|
|
7868
|
+
* global `onDragMove` that reaches us (#1612).
|
|
7869
|
+
*/
|
|
7870
|
+
clearHeaderAnchorOverlay() {
|
|
7871
|
+
var _container$model;
|
|
7872
|
+
const container = this.group.model.dropTargetContainer;
|
|
7873
|
+
const outline = container === null || container === void 0 ? void 0 : container.renderedOutline;
|
|
7874
|
+
if (outline && ![
|
|
7875
|
+
this._tabsList,
|
|
7876
|
+
this._voidContainer,
|
|
7877
|
+
this._extendedDropZone
|
|
7878
|
+
].some((scope) => scope === null || scope === void 0 ? void 0 : scope.contains(outline))) return;
|
|
7879
|
+
container === null || container === void 0 || (_container$model = container.model) === null || _container$model === void 0 || _container$model.clear();
|
|
7880
|
+
}
|
|
7858
7881
|
handleDragOver(event) {
|
|
7859
7882
|
var _this$accessor$option2;
|
|
7860
7883
|
if (!this._animState) return;
|
|
@@ -10395,7 +10418,11 @@ react_dom = __toESM(react_dom);
|
|
|
10395
10418
|
this.panels.forEach((panel) => {
|
|
10396
10419
|
this.rerender(panel);
|
|
10397
10420
|
});
|
|
10398
|
-
if (this._activePanel)
|
|
10421
|
+
if (this._activePanel) {
|
|
10422
|
+
this.contentContainer.renderPanel(this._activePanel, { asActive: true });
|
|
10423
|
+
const { width, height } = this.contentDimensions();
|
|
10424
|
+
this._activePanel.layout(width, height);
|
|
10425
|
+
}
|
|
10399
10426
|
}
|
|
10400
10427
|
get renderContainer() {
|
|
10401
10428
|
var _this$_overwriteRende;
|
|
@@ -11342,7 +11369,7 @@ react_dom = __toESM(react_dom);
|
|
|
11342
11369
|
this._group = value;
|
|
11343
11370
|
this._onDidGroupChange.fire({});
|
|
11344
11371
|
this.setupGroupEventListeners(oldGroup);
|
|
11345
|
-
this.
|
|
11372
|
+
this.fireLocationChange();
|
|
11346
11373
|
}
|
|
11347
11374
|
}
|
|
11348
11375
|
get group() {
|
|
@@ -11418,6 +11445,23 @@ react_dom = __toESM(react_dom);
|
|
|
11418
11445
|
exitMaximized() {
|
|
11419
11446
|
this.group.api.exitMaximized();
|
|
11420
11447
|
}
|
|
11448
|
+
/**
|
|
11449
|
+
* Report that this panel's location may have moved.
|
|
11450
|
+
*
|
|
11451
|
+
* A relocation touches the location more than once - the panel is
|
|
11452
|
+
* reparented into the destination group, then that group is tagged with
|
|
11453
|
+
* the location it ends up at - so the event is coalesced to the end of the
|
|
11454
|
+
* enclosing layout mutation and reports where the panel actually settled.
|
|
11455
|
+
* Firing each signal as it happened surfaced an intermediate `grid`
|
|
11456
|
+
* location the panel was never in, at a point where it was in neither
|
|
11457
|
+
* group's panel list. Outside a mutation this fires straight away.
|
|
11458
|
+
*/
|
|
11459
|
+
fireLocationChange() {
|
|
11460
|
+
this.accessor.deferLocationChange(this, () => {
|
|
11461
|
+
if (this.isDisposed) return;
|
|
11462
|
+
this._onDidLocationChange.fire({ location: this.location });
|
|
11463
|
+
});
|
|
11464
|
+
}
|
|
11421
11465
|
setupGroupEventListeners(previousGroup) {
|
|
11422
11466
|
var _previousGroup$isActi;
|
|
11423
11467
|
let _trackGroupActive = (_previousGroup$isActi = previousGroup === null || previousGroup === void 0 ? void 0 : previousGroup.isActive) !== null && _previousGroup$isActi !== void 0 ? _previousGroup$isActi : false;
|
|
@@ -11426,9 +11470,9 @@ react_dom = __toESM(react_dom);
|
|
|
11426
11470
|
const hasBecomeVisible = event.isVisible && !this.isVisible;
|
|
11427
11471
|
const isActivePanel = this.group.model.isPanelActive(this.panel);
|
|
11428
11472
|
if (hasBecomeHidden || hasBecomeVisible && isActivePanel) this._onDidVisibilityChange.fire(event);
|
|
11429
|
-
}), this.group.api.onDidLocationChange((
|
|
11473
|
+
}), this.group.api.onDidLocationChange(() => {
|
|
11430
11474
|
if (this.group !== this.panel.group) return;
|
|
11431
|
-
this.
|
|
11475
|
+
this.fireLocationChange();
|
|
11432
11476
|
}), this.group.api.onDidActiveChange(() => {
|
|
11433
11477
|
if (this.group !== this.panel.group) return;
|
|
11434
11478
|
if (_trackGroupActive !== this.isGroupActive) {
|
|
@@ -12206,7 +12250,6 @@ react_dom = __toESM(react_dom);
|
|
|
12206
12250
|
"AdvancedOverflow",
|
|
12207
12251
|
"AutoEdgeGroup",
|
|
12208
12252
|
"AutoHideEdgeGroup",
|
|
12209
|
-
"ContextMenu",
|
|
12210
12253
|
"DndCompass",
|
|
12211
12254
|
"KeyboardDocking",
|
|
12212
12255
|
"KeyboardNavigation",
|
|
@@ -12288,8 +12331,8 @@ react_dom = __toESM(react_dom);
|
|
|
12288
12331
|
* case: calling `undo()` having never set the option at all.
|
|
12289
12332
|
*
|
|
12290
12333
|
* Interaction handlers are queries in this sense too: a right-click reaching an
|
|
12291
|
-
* absent
|
|
12292
|
-
*
|
|
12334
|
+
* absent module means the app never asked for that feature, so it stays silent
|
|
12335
|
+
* (`?.`) and the browser's own behaviour applies. Options are where intent is
|
|
12293
12336
|
* declared; see `optionsModules.ts`.
|
|
12294
12337
|
*/
|
|
12295
12338
|
function assertModule(service, moduleName, context) {
|
|
@@ -12366,10 +12409,9 @@ react_dom = __toESM(react_dom);
|
|
|
12366
12409
|
*
|
|
12367
12410
|
* This is the "declared intent" diagnostic. It fires when the user asks for a
|
|
12368
12411
|
* feature via options, at construction and on every `updateOptions`. It
|
|
12369
|
-
* deliberately does *not* fire on user interaction:
|
|
12370
|
-
*
|
|
12371
|
-
*
|
|
12372
|
-
* app never wanted.
|
|
12412
|
+
* deliberately does *not* fire on user interaction: an interaction reaching an
|
|
12413
|
+
* absent module stays silent, because the `?.` service-slot call sites can't
|
|
12414
|
+
* tell a missing module from a feature the app never wanted.
|
|
12373
12415
|
*
|
|
12374
12416
|
* Rules are a flat list rather than a `Record<keyof DockviewOptions, ...>`
|
|
12375
12417
|
* because dockview's options are nested and value-gated: `overflow.mode:
|
|
@@ -12465,18 +12507,6 @@ react_dom = __toESM(react_dom);
|
|
|
12465
12507
|
moduleName: "AutoEdgeGroup",
|
|
12466
12508
|
when: (o) => isAnyEdgeGroupEnabled(o.dockToEdgeGroups)
|
|
12467
12509
|
},
|
|
12468
|
-
{
|
|
12469
|
-
optionKey: "getTabContextMenuItems",
|
|
12470
|
-
reason: "getTabContextMenuItems",
|
|
12471
|
-
moduleName: "ContextMenu",
|
|
12472
|
-
when: (o) => o.getTabContextMenuItems != null
|
|
12473
|
-
},
|
|
12474
|
-
{
|
|
12475
|
-
optionKey: "getTabGroupChipContextMenuItems",
|
|
12476
|
-
reason: "getTabGroupChipContextMenuItems",
|
|
12477
|
-
moduleName: "ContextMenu",
|
|
12478
|
-
when: (o) => o.getTabGroupChipContextMenuItems != null
|
|
12479
|
-
},
|
|
12480
12510
|
{
|
|
12481
12511
|
optionKey: "dndCompass",
|
|
12482
12512
|
reason: "dndCompass",
|
|
@@ -13343,6 +13373,267 @@ react_dom = __toESM(react_dom);
|
|
|
13343
13373
|
} });
|
|
13344
13374
|
}
|
|
13345
13375
|
});
|
|
13376
|
+
function popoverZIndexFor(target, group) {
|
|
13377
|
+
var _group$api, _group$api$isPeeking;
|
|
13378
|
+
if ((_group$api = group.api) === null || _group$api === void 0 || (_group$api$isPeeking = _group$api.isPeeking) === null || _group$api$isPeeking === void 0 ? void 0 : _group$api$isPeeking.call(_group$api)) return "calc(var(--dv-overlay-z-index, 999) + 100)";
|
|
13379
|
+
if (!(target instanceof HTMLElement)) return;
|
|
13380
|
+
const relativeParent = findRelativeZIndexParent(target);
|
|
13381
|
+
return (relativeParent === null || relativeParent === void 0 ? void 0 : relativeParent.style.zIndex) ? `calc(${relativeParent.style.zIndex} * 2)` : void 0;
|
|
13382
|
+
}
|
|
13383
|
+
let _nextId = 0;
|
|
13384
|
+
const nextContextMenuItemId = () => `dv-ctx-menu-item-${_nextId++}`;
|
|
13385
|
+
function isItemConfig(item) {
|
|
13386
|
+
return typeof item === "object";
|
|
13387
|
+
}
|
|
13388
|
+
function buildItem(label, close, action, disabled) {
|
|
13389
|
+
const el = document.createElement("div");
|
|
13390
|
+
el.className = "dv-context-menu-item";
|
|
13391
|
+
el.setAttribute("role", "menuitem");
|
|
13392
|
+
if (disabled) {
|
|
13393
|
+
el.classList.add("dv-context-menu-item--disabled");
|
|
13394
|
+
el.setAttribute("aria-disabled", "true");
|
|
13395
|
+
}
|
|
13396
|
+
el.textContent = label;
|
|
13397
|
+
if (!disabled) el.addEventListener("click", () => {
|
|
13398
|
+
action();
|
|
13399
|
+
close();
|
|
13400
|
+
});
|
|
13401
|
+
return el;
|
|
13402
|
+
}
|
|
13403
|
+
function buildSeparator() {
|
|
13404
|
+
const el = document.createElement("div");
|
|
13405
|
+
el.className = "dv-context-menu-separator";
|
|
13406
|
+
el.setAttribute("role", "separator");
|
|
13407
|
+
return el;
|
|
13408
|
+
}
|
|
13409
|
+
function isCoarsePrimaryInput$1() {
|
|
13410
|
+
if (globalThis.window === void 0 || !globalThis.matchMedia) return false;
|
|
13411
|
+
const coarse = globalThis.matchMedia("(pointer: coarse)").matches;
|
|
13412
|
+
const fine = globalThis.matchMedia("(pointer: fine)").matches;
|
|
13413
|
+
return coarse && !fine;
|
|
13414
|
+
}
|
|
13415
|
+
function buildRenameInput(tabGroup) {
|
|
13416
|
+
const wrapper = document.createElement("div");
|
|
13417
|
+
wrapper.className = "dv-context-menu-rename";
|
|
13418
|
+
const input = document.createElement("input");
|
|
13419
|
+
input.className = "dv-context-menu-rename-input";
|
|
13420
|
+
input.type = "text";
|
|
13421
|
+
input.placeholder = "Name This Group";
|
|
13422
|
+
input.value = tabGroup.label;
|
|
13423
|
+
input.addEventListener("input", () => {
|
|
13424
|
+
tabGroup.setLabel(input.value);
|
|
13425
|
+
});
|
|
13426
|
+
input.addEventListener("keydown", (e) => {
|
|
13427
|
+
if (e.key !== "Escape" && e.key !== "Enter") e.stopPropagation();
|
|
13428
|
+
});
|
|
13429
|
+
input.addEventListener("click", (e) => {
|
|
13430
|
+
e.stopPropagation();
|
|
13431
|
+
});
|
|
13432
|
+
wrapper.appendChild(input);
|
|
13433
|
+
if (!isCoarsePrimaryInput$1()) requestAnimationFrame(() => {
|
|
13434
|
+
input.focus();
|
|
13435
|
+
input.select();
|
|
13436
|
+
});
|
|
13437
|
+
return wrapper;
|
|
13438
|
+
}
|
|
13439
|
+
function buildColorPicker(tabGroup, palette) {
|
|
13440
|
+
const wrapper = document.createElement("div");
|
|
13441
|
+
wrapper.className = "dv-context-menu-color-picker";
|
|
13442
|
+
if (!palette.enabled) return wrapper;
|
|
13443
|
+
for (const entry of palette.entries()) {
|
|
13444
|
+
const swatch = document.createElement("div");
|
|
13445
|
+
swatch.className = "dv-context-menu-color-swatch";
|
|
13446
|
+
swatch.style.setProperty("--dv-tab-group-color", entry.value);
|
|
13447
|
+
if (entry.label) swatch.title = entry.label;
|
|
13448
|
+
if (tabGroup.color === entry.id) swatch.classList.add("dv-context-menu-color-swatch--selected");
|
|
13449
|
+
swatch.addEventListener("click", () => {
|
|
13450
|
+
tabGroup.setColor(entry.id);
|
|
13451
|
+
});
|
|
13452
|
+
wrapper.appendChild(swatch);
|
|
13453
|
+
}
|
|
13454
|
+
return wrapper;
|
|
13455
|
+
}
|
|
13456
|
+
var ContextMenuController = class {
|
|
13457
|
+
constructor(accessor) {
|
|
13458
|
+
this.accessor = accessor;
|
|
13459
|
+
}
|
|
13460
|
+
/**
|
|
13461
|
+
* A single maximize/restore toggle whose label and behaviour track the
|
|
13462
|
+
* group's live state: it reads *Restore* + calls `exitMaximized` when the
|
|
13463
|
+
* group is maximized, otherwise *Maximize* + `maximize`. Only grid groups
|
|
13464
|
+
* can be maximized, so the item is disabled for floating / popout panels
|
|
13465
|
+
* that are not already maximized.
|
|
13466
|
+
*/
|
|
13467
|
+
buildMaximizeItem(panel, close) {
|
|
13468
|
+
const isMaximized = panel.api.isMaximized();
|
|
13469
|
+
return buildItem(isMaximized ? "Restore" : "Maximize", close, isMaximized ? () => panel.api.exitMaximized() : () => panel.api.maximize(), !isMaximized && panel.api.location.type !== "grid");
|
|
13470
|
+
}
|
|
13471
|
+
/**
|
|
13472
|
+
* A single collapse/expand toggle whose label tracks the tab group's live
|
|
13473
|
+
* state: *Expand* when the group is already collapsed, otherwise *Collapse*.
|
|
13474
|
+
*/
|
|
13475
|
+
buildCollapseItem(tabGroup, close) {
|
|
13476
|
+
return buildItem(tabGroup.collapsed ? "Expand" : "Collapse", close, () => tabGroup.toggle());
|
|
13477
|
+
}
|
|
13478
|
+
/**
|
|
13479
|
+
* Whether to auto-inject the built-in Pin/Unpin item at the top of the tab
|
|
13480
|
+
* menu. True only when the PinnedTabs module is registered, pinning is
|
|
13481
|
+
* enabled, and the app has not opted out via `pinnedTabs.contextMenuItem:
|
|
13482
|
+
* false` (the item is on by default). This keeps pinning reachable from the
|
|
13483
|
+
* menu without the app having to return `'pin'` from
|
|
13484
|
+
* `getTabContextMenuItems` itself.
|
|
13485
|
+
*/
|
|
13486
|
+
_shouldInjectPin() {
|
|
13487
|
+
const pinnedTabs = this.accessor.options.pinnedTabs;
|
|
13488
|
+
return !!this.accessor.pinnedTabsService && !!(pinnedTabs === null || pinnedTabs === void 0 ? void 0 : pinnedTabs.enabled) && pinnedTabs.contextMenuItem !== false;
|
|
13489
|
+
}
|
|
13490
|
+
/**
|
|
13491
|
+
* The tab menu items: the app's own items (if any) with the built-in
|
|
13492
|
+
* `'pin'` item prepended when {@link _shouldInjectPin} applies, so the app
|
|
13493
|
+
* keeps full control of its list, and pinning is added without disturbing
|
|
13494
|
+
* it. Reuses the existing `'pin'` token rendering below.
|
|
13495
|
+
*/
|
|
13496
|
+
_resolveTabItems(panel, group, event) {
|
|
13497
|
+
var _this$accessor$option, _this$accessor$option2, _this$accessor$option3;
|
|
13498
|
+
const appItems = (_this$accessor$option = (_this$accessor$option2 = (_this$accessor$option3 = this.accessor.options).getTabContextMenuItems) === null || _this$accessor$option2 === void 0 ? void 0 : _this$accessor$option2.call(_this$accessor$option3, {
|
|
13499
|
+
panel,
|
|
13500
|
+
group,
|
|
13501
|
+
api: this.accessor.api,
|
|
13502
|
+
event
|
|
13503
|
+
})) !== null && _this$accessor$option !== void 0 ? _this$accessor$option : [];
|
|
13504
|
+
return this._shouldInjectPin() ? ["pin", ...appItems] : appItems;
|
|
13505
|
+
}
|
|
13506
|
+
/**
|
|
13507
|
+
* Render a custom `component` menu item and append it to `menuEl`. Builds
|
|
13508
|
+
* the framework renderer via the host's `createContextMenuItemComponent`
|
|
13509
|
+
* factory and initialises it. Shared by the tab menu and the chip menu,
|
|
13510
|
+
* which differ only in `identity`: the tab menu passes the `panel`, the chip
|
|
13511
|
+
* menu passes the `tabGroup`. No-op when no renderer could be created (no
|
|
13512
|
+
* factory configured, or the factory declined the component).
|
|
13513
|
+
*/
|
|
13514
|
+
appendComponentItem(menuEl, item, identity, group, close) {
|
|
13515
|
+
var _this$accessor$option4, _this$accessor$option5;
|
|
13516
|
+
const renderer = (_this$accessor$option4 = (_this$accessor$option5 = this.accessor.options).createContextMenuItemComponent) === null || _this$accessor$option4 === void 0 ? void 0 : _this$accessor$option4.call(_this$accessor$option5, {
|
|
13517
|
+
id: nextContextMenuItemId(),
|
|
13518
|
+
component: item.component
|
|
13519
|
+
});
|
|
13520
|
+
if (!renderer) return;
|
|
13521
|
+
renderer.init(_objectSpread2$1(_objectSpread2$1({}, identity), {}, {
|
|
13522
|
+
group,
|
|
13523
|
+
api: this.accessor.api,
|
|
13524
|
+
close,
|
|
13525
|
+
componentProps: item.componentProps
|
|
13526
|
+
}));
|
|
13527
|
+
menuEl.appendChild(renderer.element);
|
|
13528
|
+
}
|
|
13529
|
+
/**
|
|
13530
|
+
* The element for one built-in tab item, or `undefined` for a token this
|
|
13531
|
+
* version doesn't know (an app on a newer typings version, or plain JS):
|
|
13532
|
+
* an unrecognised token renders nothing rather than throwing.
|
|
13533
|
+
*/
|
|
13534
|
+
buildBuiltInTabItem(item, panel, group, close) {
|
|
13535
|
+
switch (item) {
|
|
13536
|
+
case "separator": return buildSeparator();
|
|
13537
|
+
case "close": return buildItem("Close", close, () => panel.api.close());
|
|
13538
|
+
case "closeOthers": return buildItem("Close Others", close, () => {
|
|
13539
|
+
group.panels.filter((p) => p !== panel).forEach((p) => p.api.close());
|
|
13540
|
+
});
|
|
13541
|
+
case "closeAll": return buildItem("Close All", close, () => {
|
|
13542
|
+
[...group.panels].forEach((p) => p.api.close());
|
|
13543
|
+
});
|
|
13544
|
+
case "closeLeft": {
|
|
13545
|
+
const index = group.panels.indexOf(panel);
|
|
13546
|
+
return buildItem("Close to the Left", close, () => {
|
|
13547
|
+
group.panels.filter((_, i) => i < index).forEach((p) => p.api.close());
|
|
13548
|
+
}, index <= 0);
|
|
13549
|
+
}
|
|
13550
|
+
case "closeRight": {
|
|
13551
|
+
const index = group.panels.indexOf(panel);
|
|
13552
|
+
return buildItem("Close to the Right", close, () => {
|
|
13553
|
+
group.panels.filter((_, i) => i > index).forEach((p) => p.api.close());
|
|
13554
|
+
}, index === -1 || index >= group.panels.length - 1);
|
|
13555
|
+
}
|
|
13556
|
+
case "maximize": return this.buildMaximizeItem(panel, close);
|
|
13557
|
+
case "float": return buildItem("Float", close, () => this.accessor.api.addFloatingGroup(panel), panel.api.location.type === "floating");
|
|
13558
|
+
case "popout": return buildItem("Open in New Window", close, () => {
|
|
13559
|
+
this.accessor.api.addPopoutGroup(panel);
|
|
13560
|
+
}, panel.api.location.type === "popout");
|
|
13561
|
+
case "pin": return buildItem(panel.api.isPinned ? "Unpin tab" : "Pin tab", close, () => panel.api.setPinned(!panel.api.isPinned));
|
|
13562
|
+
default: return;
|
|
13563
|
+
}
|
|
13564
|
+
}
|
|
13565
|
+
/**
|
|
13566
|
+
* Append one app-supplied item. A raw `element` is used as-is, a
|
|
13567
|
+
* `component` goes through the framework renderer, and a `label` builds the
|
|
13568
|
+
* default row; an item carrying none of the three renders nothing. Shared
|
|
13569
|
+
* by both menus, which differ only in `identity`.
|
|
13570
|
+
*/
|
|
13571
|
+
appendConfigItem(menuEl, item, identity, group, close) {
|
|
13572
|
+
if (item.element) menuEl.appendChild(item.element);
|
|
13573
|
+
else if (item.component) this.appendComponentItem(menuEl, item, identity, group, close);
|
|
13574
|
+
else if (item.label) menuEl.appendChild(buildItem(item.label, close, () => {
|
|
13575
|
+
var _item$action;
|
|
13576
|
+
return (_item$action = item.action) === null || _item$action === void 0 ? void 0 : _item$action.call(item);
|
|
13577
|
+
}, item.disabled));
|
|
13578
|
+
}
|
|
13579
|
+
show(panel, group, event) {
|
|
13580
|
+
const items = this._resolveTabItems(panel, group, event);
|
|
13581
|
+
if (items.length === 0) return;
|
|
13582
|
+
event.preventDefault();
|
|
13583
|
+
const popupService = this.accessor.getPopupServiceForGroup(group);
|
|
13584
|
+
const close = () => popupService.close();
|
|
13585
|
+
const menuEl = document.createElement("div");
|
|
13586
|
+
menuEl.className = "dv-context-menu";
|
|
13587
|
+
menuEl.setAttribute("role", "menu");
|
|
13588
|
+
for (const item of items) {
|
|
13589
|
+
if (isItemConfig(item)) {
|
|
13590
|
+
this.appendConfigItem(menuEl, item, { panel }, group, close);
|
|
13591
|
+
continue;
|
|
13592
|
+
}
|
|
13593
|
+
const el = this.buildBuiltInTabItem(item, panel, group, close);
|
|
13594
|
+
if (el) menuEl.appendChild(el);
|
|
13595
|
+
}
|
|
13596
|
+
popupService.openPopover(menuEl, {
|
|
13597
|
+
x: event.clientX,
|
|
13598
|
+
y: event.clientY,
|
|
13599
|
+
zIndex: popoverZIndexFor(event.target, group)
|
|
13600
|
+
});
|
|
13601
|
+
}
|
|
13602
|
+
showForChip(tabGroup, group, event) {
|
|
13603
|
+
if (!this.accessor.options.getTabGroupChipContextMenuItems) return;
|
|
13604
|
+
const items = this.accessor.options.getTabGroupChipContextMenuItems({
|
|
13605
|
+
tabGroup,
|
|
13606
|
+
group,
|
|
13607
|
+
api: this.accessor.api,
|
|
13608
|
+
event
|
|
13609
|
+
});
|
|
13610
|
+
if (items.length === 0) return;
|
|
13611
|
+
event.preventDefault();
|
|
13612
|
+
const popupService = this.accessor.getPopupServiceForGroup(group);
|
|
13613
|
+
const close = () => popupService.close();
|
|
13614
|
+
const menuEl = document.createElement("div");
|
|
13615
|
+
menuEl.className = "dv-context-menu";
|
|
13616
|
+
menuEl.setAttribute("role", "menu");
|
|
13617
|
+
for (const item of items) if (item === "separator") menuEl.appendChild(buildSeparator());
|
|
13618
|
+
else if (item === "rename") menuEl.appendChild(buildRenameInput(tabGroup));
|
|
13619
|
+
else if (item === "colorPicker") menuEl.appendChild(buildColorPicker(tabGroup, this.accessor.tabGroupColorPalette));
|
|
13620
|
+
else if (item === "collapse") menuEl.appendChild(this.buildCollapseItem(tabGroup, close));
|
|
13621
|
+
else if (item === "close") menuEl.appendChild(buildItem("Close All", close, () => {
|
|
13622
|
+
group.panels.filter((p) => tabGroup.containsPanel(p.id)).forEach((p) => p.api.close());
|
|
13623
|
+
}));
|
|
13624
|
+
else if (isItemConfig(item)) this.appendConfigItem(menuEl, item, { tabGroup }, group, close);
|
|
13625
|
+
popupService.openPopover(menuEl, {
|
|
13626
|
+
x: event.clientX,
|
|
13627
|
+
y: event.clientY,
|
|
13628
|
+
zIndex: popoverZIndexFor(event.target, group)
|
|
13629
|
+
});
|
|
13630
|
+
}
|
|
13631
|
+
};
|
|
13632
|
+
const ContextMenuModule = defineModule({
|
|
13633
|
+
name: "ContextMenu",
|
|
13634
|
+
serviceKey: "contextMenuService",
|
|
13635
|
+
create: (host) => new ContextMenuController(host)
|
|
13636
|
+
});
|
|
13346
13637
|
/**
|
|
13347
13638
|
* Internal list of the built-in modules that ship with the core. Registered
|
|
13348
13639
|
* automatically by DockviewComponent at construction time; not exported from
|
|
@@ -13358,7 +13649,8 @@ react_dom = __toESM(react_dom);
|
|
|
13358
13649
|
HeaderActionsModule,
|
|
13359
13650
|
LiveRegionModule,
|
|
13360
13651
|
AdvancedDnDModule,
|
|
13361
|
-
TabGroupChipsModule
|
|
13652
|
+
TabGroupChipsModule,
|
|
13653
|
+
ContextMenuModule
|
|
13362
13654
|
];
|
|
13363
13655
|
var PositionCache = class {
|
|
13364
13656
|
constructor() {
|
|
@@ -13388,6 +13680,13 @@ react_dom = __toESM(react_dom);
|
|
|
13388
13680
|
});
|
|
13389
13681
|
}
|
|
13390
13682
|
};
|
|
13683
|
+
/**
|
|
13684
|
+
* Placeholder handle marking "a reposition frame has been requested but the
|
|
13685
|
+
* real handle is not known yet". Never passed to `cancelAnimationFrame` in
|
|
13686
|
+
* practice — it is replaced within the same synchronous block — and harmless
|
|
13687
|
+
* if it were, since no frame carries this id.
|
|
13688
|
+
*/
|
|
13689
|
+
const SCHEDULED = -1;
|
|
13391
13690
|
function createFocusableElement() {
|
|
13392
13691
|
const element = document.createElement("div");
|
|
13393
13692
|
element.tabIndex = -1;
|
|
@@ -13400,12 +13699,13 @@ react_dom = __toESM(react_dom);
|
|
|
13400
13699
|
this.accessor = accessor;
|
|
13401
13700
|
this.map = {};
|
|
13402
13701
|
this._disposed = false;
|
|
13702
|
+
this._generation = 0;
|
|
13403
13703
|
this.positionCache = new PositionCache();
|
|
13404
|
-
this.pendingUpdates = /* @__PURE__ */ new Set();
|
|
13405
13704
|
this.addDisposables(Disposable.from(() => {
|
|
13406
13705
|
for (const value of Object.values(this.map)) {
|
|
13407
13706
|
value.disposable.dispose();
|
|
13408
13707
|
value.destroy.dispose();
|
|
13708
|
+
this.cancelPendingUpdate(value);
|
|
13409
13709
|
}
|
|
13410
13710
|
this._disposed = true;
|
|
13411
13711
|
}));
|
|
@@ -13432,11 +13732,24 @@ react_dom = __toESM(react_dom);
|
|
|
13432
13732
|
this.positionCache.invalidate();
|
|
13433
13733
|
(_entry$resize = entry.resize) === null || _entry$resize === void 0 || _entry$resize.call(entry);
|
|
13434
13734
|
}
|
|
13735
|
+
/**
|
|
13736
|
+
* Drop the reposition frame queued for a panel, if any. A queued frame is
|
|
13737
|
+
* bound to the reference container that was current when it was scheduled,
|
|
13738
|
+
* so it must be discarded whenever that container stops being the one the
|
|
13739
|
+
* overlay should track.
|
|
13740
|
+
*/
|
|
13741
|
+
cancelPendingUpdate(entry) {
|
|
13742
|
+
if (entry.pendingUpdate !== void 0) {
|
|
13743
|
+
cancelAnimationFrame(entry.pendingUpdate);
|
|
13744
|
+
entry.pendingUpdate = void 0;
|
|
13745
|
+
}
|
|
13746
|
+
}
|
|
13435
13747
|
detatch(panel) {
|
|
13436
13748
|
if (this.map[panel.api.id]) {
|
|
13437
|
-
const
|
|
13438
|
-
disposable.dispose();
|
|
13439
|
-
destroy.dispose();
|
|
13749
|
+
const entry = this.map[panel.api.id];
|
|
13750
|
+
entry.disposable.dispose();
|
|
13751
|
+
entry.destroy.dispose();
|
|
13752
|
+
this.cancelPendingUpdate(entry);
|
|
13440
13753
|
delete this.map[panel.api.id];
|
|
13441
13754
|
return true;
|
|
13442
13755
|
}
|
|
@@ -13452,22 +13765,73 @@ react_dom = __toESM(react_dom);
|
|
|
13452
13765
|
panel,
|
|
13453
13766
|
disposable: Disposable.NONE,
|
|
13454
13767
|
destroy: Disposable.NONE,
|
|
13455
|
-
element
|
|
13768
|
+
element,
|
|
13769
|
+
retainPreviousGeometry: false,
|
|
13770
|
+
positioned: false,
|
|
13771
|
+
generation: ++this._generation
|
|
13456
13772
|
};
|
|
13457
13773
|
}
|
|
13458
|
-
const
|
|
13774
|
+
const mapEntry = this.map[panel.api.id];
|
|
13775
|
+
/**
|
|
13776
|
+
* A *change* of reference container supersedes the previous `attach`:
|
|
13777
|
+
* take a fresh generation so its `resize` closure can no longer run,
|
|
13778
|
+
* and drop the frame it queued against the old container. During
|
|
13779
|
+
* `fromJSON({ reuseExistingPanels: true })` that old container is a
|
|
13780
|
+
* detached staging group measuring 0x0, so leaving its frame in flight
|
|
13781
|
+
* both wastes the update and delays the reposition against the real one.
|
|
13782
|
+
*
|
|
13783
|
+
* Re-attaching over the *same* container (re-open, active panel change)
|
|
13784
|
+
* deliberately leaves scheduled work alone: `repositionPanelOverlay`
|
|
13785
|
+
* (the auto-hide peek) schedules a frame carrying the sticky
|
|
13786
|
+
* `forceVisible`/`clip` state which `attach` does not re-apply, and a
|
|
13787
|
+
* peeked panel's `api.isVisible` is false — so discarding that frame
|
|
13788
|
+
* leaves `visibilityChanged` to hide the overlay and the peek renders
|
|
13789
|
+
* nothing. A newly created entry already holds a fresh generation, so
|
|
13790
|
+
* the stale closures a `detatch` left behind are fenced off either way.
|
|
13791
|
+
*/
|
|
13792
|
+
if (mapEntry.referenceContainer !== referenceContainer) {
|
|
13793
|
+
mapEntry.generation = ++this._generation;
|
|
13794
|
+
this.cancelPendingUpdate(mapEntry);
|
|
13795
|
+
mapEntry.referenceContainer = referenceContainer;
|
|
13796
|
+
/**
|
|
13797
|
+
* Arm the retain flag only here: it means "a replacement reference
|
|
13798
|
+
* container is awaiting layout", so the 0x0 early-return below
|
|
13799
|
+
* holds the last good box rather than blanking the panel mid-move.
|
|
13800
|
+
* Arming it on every re-attach instead would make a container that
|
|
13801
|
+
* genuinely collapses to zero keep its stale geometry forever.
|
|
13802
|
+
*
|
|
13803
|
+
* Gated on `positioned` because an overlay that has never been
|
|
13804
|
+
* positioned has no left/top/width/height, and `.dv-render-overlay`
|
|
13805
|
+
* defaults to 100%/100% — retaining "previous" geometry there would
|
|
13806
|
+
* pin the content over the whole container.
|
|
13807
|
+
*/
|
|
13808
|
+
mapEntry.retainPreviousGeometry = mapEntry.positioned;
|
|
13809
|
+
}
|
|
13810
|
+
const generation = mapEntry.generation;
|
|
13811
|
+
const focusContainer = mapEntry.element;
|
|
13459
13812
|
const contentElement = panel.view.content.element;
|
|
13460
13813
|
if (contentElement.parentElement !== focusContainer) focusContainer.appendChild(contentElement);
|
|
13461
13814
|
if (focusContainer.parentElement !== this.element) this.element.appendChild(focusContainer);
|
|
13462
13815
|
const resize = () => {
|
|
13463
13816
|
const panelId = panel.api.id;
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13817
|
+
const scheduling = this.map[panelId];
|
|
13818
|
+
if ((scheduling === null || scheduling === void 0 ? void 0 : scheduling.generation) !== generation) return;
|
|
13819
|
+
if (scheduling.pendingUpdate !== void 0) return;
|
|
13820
|
+
/**
|
|
13821
|
+
* Claim the slot *before* scheduling. `requestAnimationFrame` is
|
|
13822
|
+
* shimmed to run inline by some hosts (and by several suites here),
|
|
13823
|
+
* in which case the callback below clears `pendingUpdate` while
|
|
13824
|
+
* this call is still on the stack — assigning the handle afterwards
|
|
13825
|
+
* would resurrect a slot that is already spent and block every
|
|
13826
|
+
* later reposition. The sentinel is replaced by the real handle
|
|
13827
|
+
* only if the frame has not already run.
|
|
13828
|
+
*/
|
|
13829
|
+
scheduling.pendingUpdate = SCHEDULED;
|
|
13830
|
+
const handle = requestAnimationFrame(() => {
|
|
13467
13831
|
var _entry$forceVisible;
|
|
13468
|
-
this.pendingUpdates.delete(panelId);
|
|
13469
13832
|
const entry = this.map[panelId];
|
|
13470
|
-
if (
|
|
13833
|
+
if (entry) entry.pendingUpdate = void 0;
|
|
13834
|
+
if (this.isDisposed || (entry === null || entry === void 0 ? void 0 : entry.generation) !== generation) return;
|
|
13471
13835
|
const forceVisible = (_entry$forceVisible = entry.forceVisible) !== null && _entry$forceVisible !== void 0 ? _entry$forceVisible : false;
|
|
13472
13836
|
const clip = entry.clip;
|
|
13473
13837
|
const box = this.positionCache.getPosition(referenceContainer.element);
|
|
@@ -13476,6 +13840,15 @@ react_dom = __toESM(react_dom);
|
|
|
13476
13840
|
const top = box.top - box2.top;
|
|
13477
13841
|
const width = box.width;
|
|
13478
13842
|
const height = box.height;
|
|
13843
|
+
if (entry.retainPreviousGeometry && (width === 0 || height === 0)) {
|
|
13844
|
+
if (!panel.api.isVisible && !forceVisible) {
|
|
13845
|
+
focusContainer.style.visibility = "hidden";
|
|
13846
|
+
focusContainer.style.pointerEvents = "none";
|
|
13847
|
+
}
|
|
13848
|
+
return;
|
|
13849
|
+
}
|
|
13850
|
+
entry.retainPreviousGeometry = false;
|
|
13851
|
+
entry.positioned = true;
|
|
13479
13852
|
focusContainer.style.left = `${left}px`;
|
|
13480
13853
|
focusContainer.style.top = `${top}px`;
|
|
13481
13854
|
focusContainer.style.width = `${width}px`;
|
|
@@ -13504,11 +13877,30 @@ react_dom = __toESM(react_dom);
|
|
|
13504
13877
|
} else focusContainer.style.clipPath = "";
|
|
13505
13878
|
toggleClass(focusContainer, "dv-render-overlay-float", panel.group.api.location.type === "floating");
|
|
13506
13879
|
});
|
|
13880
|
+
if (scheduling.pendingUpdate === SCHEDULED) scheduling.pendingUpdate = handle;
|
|
13507
13881
|
};
|
|
13508
13882
|
const visibilityChanged = () => {
|
|
13509
13883
|
if (panel.api.isVisible) {
|
|
13884
|
+
var _this$map$panel$api$i;
|
|
13510
13885
|
this.positionCache.invalidate();
|
|
13511
13886
|
resize();
|
|
13887
|
+
/**
|
|
13888
|
+
* Existing geometry is safe to show while its replacement lays
|
|
13889
|
+
* out. `retainPreviousGeometry` is only set when geometry has
|
|
13890
|
+
* actually been written (see `attach`), so this can never
|
|
13891
|
+
* un-hide an overlay whose left/top/width/height are unset —
|
|
13892
|
+
* `.dv-render-overlay` is 100%/100% by default and would
|
|
13893
|
+
* otherwise cover the whole dock.
|
|
13894
|
+
*
|
|
13895
|
+
* The retained geometry is the panel's position in the previous
|
|
13896
|
+
* layout, so restoring a layout that moves the panel does paint
|
|
13897
|
+
* it at stale coordinates until the reposition lands. That is
|
|
13898
|
+
* bounded to the next frame now that a superseded `attach` can
|
|
13899
|
+
* no longer swallow the reposition (see `attach`); showing
|
|
13900
|
+
* stale-but-real geometry for a frame is the deliberate
|
|
13901
|
+
* trade-off against blanking the panel for the whole rebuild.
|
|
13902
|
+
*/
|
|
13903
|
+
if ((_this$map$panel$api$i = this.map[panel.api.id]) === null || _this$map$panel$api$i === void 0 ? void 0 : _this$map$panel$api$i.retainPreviousGeometry) focusContainer.style.visibility = "";
|
|
13512
13904
|
focusContainer.style.pointerEvents = "";
|
|
13513
13905
|
} else {
|
|
13514
13906
|
focusContainer.style.visibility = "hidden";
|
|
@@ -13725,7 +14117,17 @@ react_dom = __toESM(react_dom);
|
|
|
13725
14117
|
window: externalWindow
|
|
13726
14118
|
});
|
|
13727
14119
|
return new Promise((resolve, reject) => {
|
|
13728
|
-
externalWindow.addEventListener("unload", (
|
|
14120
|
+
externalWindow.addEventListener("unload", () => {});
|
|
14121
|
+
/**
|
|
14122
|
+
* `load` is the only event that resolves this promise with a
|
|
14123
|
+
* container, so a window that goes away first would leave the
|
|
14124
|
+
* caller awaiting a promise that never settles - and
|
|
14125
|
+
* `addPopoutGroup` holds its layout transaction open until it does.
|
|
14126
|
+
* Settle with `null` on close, the same signal a blocked popup
|
|
14127
|
+
* gives and one the caller already handles. `resolve` after the
|
|
14128
|
+
* fact is a no-op, so a `load` that arrived first still wins.
|
|
14129
|
+
*/
|
|
14130
|
+
disposable.addDisposables(_this.onWillClose(() => resolve(null)));
|
|
13729
14131
|
externalWindow.addEventListener("load", () => {
|
|
13730
14132
|
/**
|
|
13731
14133
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
|
|
@@ -13919,6 +14321,14 @@ react_dom = __toESM(react_dom);
|
|
|
13919
14321
|
}
|
|
13920
14322
|
};
|
|
13921
14323
|
var DropTargetAnchorContainer = class extends CompositeDisposable {
|
|
14324
|
+
/**
|
|
14325
|
+
* The element the live overlay was rendered for, `undefined` when nothing
|
|
14326
|
+
* is showing. The container is shared by every drop target, so a caller
|
|
14327
|
+
* tearing down only its own overlay must check this before `clear()`.
|
|
14328
|
+
*/
|
|
14329
|
+
get renderedOutline() {
|
|
14330
|
+
return this._model ? this._outline : void 0;
|
|
14331
|
+
}
|
|
13922
14332
|
get disabled() {
|
|
13923
14333
|
return this._disabled;
|
|
13924
14334
|
}
|
|
@@ -14220,6 +14630,10 @@ react_dom = __toESM(react_dom);
|
|
|
14220
14630
|
const index = position === "top" ? this._topIndex : this._bottomIndex;
|
|
14221
14631
|
if (index !== void 0) this._splitview.resizeView(index, size);
|
|
14222
14632
|
}
|
|
14633
|
+
/** The inner splitview's primary-axis (height) extent; zero until laid out. */
|
|
14634
|
+
get axisSize() {
|
|
14635
|
+
return this._splitview.size;
|
|
14636
|
+
}
|
|
14223
14637
|
updateMargin(gap) {
|
|
14224
14638
|
this._splitview.margin = gap;
|
|
14225
14639
|
}
|
|
@@ -14232,6 +14646,7 @@ react_dom = __toESM(react_dom);
|
|
|
14232
14646
|
constructor(container, dockviewElement, layoutGrid, gap = 0, defaultCollapsedSize = 35) {
|
|
14233
14647
|
this._disposables = new CompositeDisposable();
|
|
14234
14648
|
this._viewConfigs = /* @__PURE__ */ new Map();
|
|
14649
|
+
this._pendingSizes = /* @__PURE__ */ new Map();
|
|
14235
14650
|
this._currentWidth = 0;
|
|
14236
14651
|
this._currentHeight = 0;
|
|
14237
14652
|
this._gap = gap;
|
|
@@ -14322,11 +14737,13 @@ react_dom = __toESM(react_dom);
|
|
|
14322
14737
|
break;
|
|
14323
14738
|
}
|
|
14324
14739
|
this._disposables.addDisposables(view);
|
|
14740
|
+
if (!view.isCollapsed && !this._canResize(position)) this._pendingSizes.set(position, initialSize);
|
|
14325
14741
|
this.updateTheme(this._gap, this._defaultCollapsedSize);
|
|
14326
14742
|
return view;
|
|
14327
14743
|
}
|
|
14328
14744
|
layout(width, height) {
|
|
14329
14745
|
this._outerSplitview.layout(width, height);
|
|
14746
|
+
this._flushPendingSizes();
|
|
14330
14747
|
}
|
|
14331
14748
|
/**
|
|
14332
14749
|
* Called when the active theme changes. Updates splitview margins and
|
|
@@ -14390,6 +14807,7 @@ react_dom = __toESM(react_dom);
|
|
|
14390
14807
|
this._disposables.removeDisposable(view);
|
|
14391
14808
|
view.dispose();
|
|
14392
14809
|
this._viewConfigs.delete(position);
|
|
14810
|
+
this._pendingSizes.delete(position);
|
|
14393
14811
|
this.updateTheme(this._gap, this._defaultCollapsedSize);
|
|
14394
14812
|
}
|
|
14395
14813
|
hasEdgeGroup(position) {
|
|
@@ -14413,6 +14831,7 @@ react_dom = __toESM(react_dom);
|
|
|
14413
14831
|
this._middleColumn.setViewVisible(position, visible);
|
|
14414
14832
|
break;
|
|
14415
14833
|
}
|
|
14834
|
+
if (visible) this._flushPendingSizes();
|
|
14416
14835
|
}
|
|
14417
14836
|
isEdgeGroupVisible(position) {
|
|
14418
14837
|
switch (position) {
|
|
@@ -14430,20 +14849,63 @@ react_dom = __toESM(react_dom);
|
|
|
14430
14849
|
const view = this._getView(position);
|
|
14431
14850
|
if (!view) return;
|
|
14432
14851
|
view.setCollapsed(collapsed);
|
|
14433
|
-
|
|
14852
|
+
if (collapsed) {
|
|
14853
|
+
this._pendingSizes.delete(position);
|
|
14854
|
+
this._resizeView(position, view.collapsedSize);
|
|
14855
|
+
} else this.resizeEdgeGroup(position, view.lastExpandedSize);
|
|
14856
|
+
}
|
|
14857
|
+
/**
|
|
14858
|
+
* Resize the edge group at `position` along its primary axis (width for
|
|
14859
|
+
* `left`/`right`, height for `top`/`bottom`), clamped by the group's
|
|
14860
|
+
* constraints and the space available. Where `groupApi.setSize` lands.
|
|
14861
|
+
*
|
|
14862
|
+
* The size becomes the group's expanded size, so a collapsed group keeps
|
|
14863
|
+
* its strip and takes it on expand, and it survives a `toJSON` round-trip.
|
|
14864
|
+
*/
|
|
14865
|
+
resizeEdgeGroup(position, size) {
|
|
14866
|
+
const view = this._getView(position);
|
|
14867
|
+
if (!view || !Number.isFinite(size)) return;
|
|
14868
|
+
const target = Math.round(size);
|
|
14869
|
+
if (target <= 0) return;
|
|
14870
|
+
view.restoreExpandedSize(target);
|
|
14871
|
+
if (view.isCollapsed) {
|
|
14872
|
+
this._pendingSizes.delete(position);
|
|
14873
|
+
return;
|
|
14874
|
+
}
|
|
14875
|
+
if (this._canResize(position)) {
|
|
14876
|
+
this._pendingSizes.delete(position);
|
|
14877
|
+
this._resizeView(position, target);
|
|
14878
|
+
} else this._pendingSizes.set(position, target);
|
|
14879
|
+
}
|
|
14880
|
+
/** A resize lands only on a visible view (a hidden one is pinned to zero)
|
|
14881
|
+
* whose splitview has extent to distribute. */
|
|
14882
|
+
_canResize(position) {
|
|
14883
|
+
if (!this.isEdgeGroupVisible(position)) return false;
|
|
14884
|
+
return (position === "left" || position === "right" ? this._outerSplitview.size : this._middleColumn.axisSize) > 0;
|
|
14885
|
+
}
|
|
14886
|
+
_resizeView(position, size) {
|
|
14434
14887
|
switch (position) {
|
|
14435
14888
|
case "left":
|
|
14436
|
-
if (this._leftIndex !== void 0) this._outerSplitview.resizeView(this._leftIndex,
|
|
14889
|
+
if (this._leftIndex !== void 0) this._outerSplitview.resizeView(this._leftIndex, size);
|
|
14437
14890
|
break;
|
|
14438
14891
|
case "right":
|
|
14439
|
-
if (this._rightIndex !== void 0) this._outerSplitview.resizeView(this._rightIndex,
|
|
14892
|
+
if (this._rightIndex !== void 0) this._outerSplitview.resizeView(this._rightIndex, size);
|
|
14440
14893
|
break;
|
|
14441
14894
|
case "top":
|
|
14442
14895
|
case "bottom":
|
|
14443
|
-
this._middleColumn.resizeView(position,
|
|
14896
|
+
this._middleColumn.resizeView(position, size);
|
|
14444
14897
|
break;
|
|
14445
14898
|
}
|
|
14446
14899
|
}
|
|
14900
|
+
_flushPendingSizes() {
|
|
14901
|
+
if (this._pendingSizes.size === 0) return;
|
|
14902
|
+
for (const [position, size] of this._pendingSizes) {
|
|
14903
|
+
const view = this._getView(position);
|
|
14904
|
+
if (!view || view.isCollapsed || !this._canResize(position)) continue;
|
|
14905
|
+
this._pendingSizes.delete(position);
|
|
14906
|
+
this._resizeView(position, size);
|
|
14907
|
+
}
|
|
14908
|
+
}
|
|
14447
14909
|
isEdgeGroupCollapsed(position) {
|
|
14448
14910
|
var _this$_getView$isColl, _this$_getView;
|
|
14449
14911
|
return (_this$_getView$isColl = (_this$_getView = this._getView(position)) === null || _this$_getView === void 0 ? void 0 : _this$_getView.isCollapsed) !== null && _this$_getView$isColl !== void 0 ? _this$_getView$isColl : false;
|
|
@@ -14469,15 +14931,17 @@ react_dom = __toESM(react_dom);
|
|
|
14469
14931
|
maximumSize: Number.isFinite(view.configuredMaximumSize) ? view.configuredMaximumSize : void 0,
|
|
14470
14932
|
collapsedSize: view.configuredCollapsedSize
|
|
14471
14933
|
});
|
|
14472
|
-
const expandedSize = (view, isVisible, liveSize, cachedVisibleSize) => {
|
|
14934
|
+
const expandedSize = (view, position, isVisible, liveSize, cachedVisibleSize) => {
|
|
14473
14935
|
if (view.isCollapsed) return view.lastExpandedSize;
|
|
14936
|
+
const pending = this._pendingSizes.get(position);
|
|
14937
|
+
if (pending !== void 0) return pending;
|
|
14474
14938
|
if (!isVisible) return cachedVisibleSize !== null && cachedVisibleSize !== void 0 ? cachedVisibleSize : view.lastExpandedSize;
|
|
14475
14939
|
return liveSize;
|
|
14476
14940
|
};
|
|
14477
14941
|
if (this._leftView && this._leftIndex !== void 0) {
|
|
14478
14942
|
const visible = this._outerSplitview.isViewVisible(this._leftIndex);
|
|
14479
14943
|
edgeGroups.left = _objectSpread2$1({
|
|
14480
|
-
size: expandedSize(this._leftView, visible, this._outerSplitview.getViewSize(this._leftIndex), this._outerSplitview.getViewCachedVisibleSize(this._leftIndex)),
|
|
14944
|
+
size: expandedSize(this._leftView, "left", visible, this._outerSplitview.getViewSize(this._leftIndex), this._outerSplitview.getViewCachedVisibleSize(this._leftIndex)),
|
|
14481
14945
|
visible,
|
|
14482
14946
|
collapsed: this._leftView.isCollapsed || void 0
|
|
14483
14947
|
}, constraints(this._leftView));
|
|
@@ -14485,7 +14949,7 @@ react_dom = __toESM(react_dom);
|
|
|
14485
14949
|
if (this._rightView && this._rightIndex !== void 0) {
|
|
14486
14950
|
const visible = this._outerSplitview.isViewVisible(this._rightIndex);
|
|
14487
14951
|
edgeGroups.right = _objectSpread2$1({
|
|
14488
|
-
size: expandedSize(this._rightView, visible, this._outerSplitview.getViewSize(this._rightIndex), this._outerSplitview.getViewCachedVisibleSize(this._rightIndex)),
|
|
14952
|
+
size: expandedSize(this._rightView, "right", visible, this._outerSplitview.getViewSize(this._rightIndex), this._outerSplitview.getViewCachedVisibleSize(this._rightIndex)),
|
|
14489
14953
|
visible,
|
|
14490
14954
|
collapsed: this._rightView.isCollapsed || void 0
|
|
14491
14955
|
}, constraints(this._rightView));
|
|
@@ -14493,7 +14957,7 @@ react_dom = __toESM(react_dom);
|
|
|
14493
14957
|
if (this._topView) {
|
|
14494
14958
|
const visible = this._middleColumn.isViewVisible("top");
|
|
14495
14959
|
edgeGroups.top = _objectSpread2$1({
|
|
14496
|
-
size: expandedSize(this._topView, visible, this._middleColumn.getViewSize("top"), this._middleColumn.getViewCachedVisibleSize("top")),
|
|
14960
|
+
size: expandedSize(this._topView, "top", visible, this._middleColumn.getViewSize("top"), this._middleColumn.getViewCachedVisibleSize("top")),
|
|
14497
14961
|
visible,
|
|
14498
14962
|
collapsed: this._topView.isCollapsed || void 0
|
|
14499
14963
|
}, constraints(this._topView));
|
|
@@ -14501,7 +14965,7 @@ react_dom = __toESM(react_dom);
|
|
|
14501
14965
|
if (this._bottomView) {
|
|
14502
14966
|
const visible = this._middleColumn.isViewVisible("bottom");
|
|
14503
14967
|
edgeGroups.bottom = _objectSpread2$1({
|
|
14504
|
-
size: expandedSize(this._bottomView, visible, this._middleColumn.getViewSize("bottom"), this._middleColumn.getViewCachedVisibleSize("bottom")),
|
|
14968
|
+
size: expandedSize(this._bottomView, "bottom", visible, this._middleColumn.getViewSize("bottom"), this._middleColumn.getViewCachedVisibleSize("bottom")),
|
|
14505
14969
|
visible,
|
|
14506
14970
|
collapsed: this._bottomView.isCollapsed || void 0
|
|
14507
14971
|
}, constraints(this._bottomView));
|
|
@@ -14509,33 +14973,23 @@ react_dom = __toESM(react_dom);
|
|
|
14509
14973
|
return edgeGroups;
|
|
14510
14974
|
}
|
|
14511
14975
|
fromJSON(data) {
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
|
|
14518
|
-
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
(
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
if (
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
|
|
14529
|
-
(_this$_topView3 = this._topView) === null || _this$_topView3 === void 0 || _this$_topView3.setCollapsed((_data$top$collapsed = data.top.collapsed) !== null && _data$top$collapsed !== void 0 ? _data$top$collapsed : false);
|
|
14530
|
-
this._middleColumn.resizeView("top", data.top.collapsed ? (_this$_topView$collap = (_this$_topView4 = this._topView) === null || _this$_topView4 === void 0 ? void 0 : _this$_topView4.collapsedSize) !== null && _this$_topView$collap !== void 0 ? _this$_topView$collap : data.top.size : data.top.size);
|
|
14531
|
-
if (!data.top.visible) this._middleColumn.setViewVisible("top", false);
|
|
14532
|
-
}
|
|
14533
|
-
if (data.bottom) {
|
|
14534
|
-
var _this$_bottomView2, _this$_bottomView3, _data$bottom$collapse, _this$_bottomView$col, _this$_bottomView4;
|
|
14535
|
-
(_this$_bottomView2 = this._bottomView) === null || _this$_bottomView2 === void 0 || _this$_bottomView2.restoreExpandedSize(data.bottom.size);
|
|
14536
|
-
(_this$_bottomView3 = this._bottomView) === null || _this$_bottomView3 === void 0 || _this$_bottomView3.setCollapsed((_data$bottom$collapse = data.bottom.collapsed) !== null && _data$bottom$collapse !== void 0 ? _data$bottom$collapse : false);
|
|
14537
|
-
this._middleColumn.resizeView("bottom", data.bottom.collapsed ? (_this$_bottomView$col = (_this$_bottomView4 = this._bottomView) === null || _this$_bottomView4 === void 0 ? void 0 : _this$_bottomView4.collapsedSize) !== null && _this$_bottomView$col !== void 0 ? _this$_bottomView$col : data.bottom.size : data.bottom.size);
|
|
14538
|
-
if (!data.bottom.visible) this._middleColumn.setViewVisible("bottom", false);
|
|
14976
|
+
for (const position of [
|
|
14977
|
+
"left",
|
|
14978
|
+
"right",
|
|
14979
|
+
"top",
|
|
14980
|
+
"bottom"
|
|
14981
|
+
]) {
|
|
14982
|
+
var _state$collapsed;
|
|
14983
|
+
const state = data[position];
|
|
14984
|
+
const view = this._getView(position);
|
|
14985
|
+
if (!state || !view) continue;
|
|
14986
|
+
view.restoreExpandedSize(state.size);
|
|
14987
|
+
view.setCollapsed((_state$collapsed = state.collapsed) !== null && _state$collapsed !== void 0 ? _state$collapsed : false);
|
|
14988
|
+
if (state.collapsed) {
|
|
14989
|
+
this._pendingSizes.delete(position);
|
|
14990
|
+
this._resizeView(position, view.collapsedSize);
|
|
14991
|
+
} else this.resizeEdgeGroup(position, state.size);
|
|
14992
|
+
this.setEdgeGroupVisible(position, !!state.visible);
|
|
14539
14993
|
}
|
|
14540
14994
|
}
|
|
14541
14995
|
dispose() {
|
|
@@ -15125,6 +15579,7 @@ react_dom = __toESM(react_dom);
|
|
|
15125
15579
|
this._onWillDrop = new Emitter();
|
|
15126
15580
|
this.onWillDrop = this._onWillDrop.event;
|
|
15127
15581
|
this._mutationDepth = 0;
|
|
15582
|
+
this._pendingLocationChanges = /* @__PURE__ */ new Map();
|
|
15128
15583
|
this._origin = "user";
|
|
15129
15584
|
this._originDepth = 0;
|
|
15130
15585
|
this._onWillMutateLayout = new Emitter();
|
|
@@ -15222,7 +15677,7 @@ react_dom = __toESM(react_dom);
|
|
|
15222
15677
|
toggleClass(this.element, "dv-debug", !!options.debug);
|
|
15223
15678
|
this.updateTheme();
|
|
15224
15679
|
if (options.debug) this.addDisposables(new StrictEventsSequencing(this));
|
|
15225
|
-
this.addDisposables(this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15680
|
+
this.addDisposables(Disposable.from(() => this._pendingLocationChanges.clear()), this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
|
|
15226
15681
|
var _this$rootDropTargetC2, _this$floatingDropTar;
|
|
15227
15682
|
(_this$rootDropTargetC2 = this.rootDropTargetContainer.model) === null || _this$rootDropTargetC2 === void 0 || _this$rootDropTargetC2.clear();
|
|
15228
15683
|
(_this$floatingDropTar = this.floatingDropTargetContainer.model) === null || _this$floatingDropTar === void 0 || _this$floatingDropTar.clear();
|
|
@@ -15296,7 +15751,7 @@ react_dom = __toESM(react_dom);
|
|
|
15296
15751
|
return (_this$_popoutWindowSe3 = (_this$_popoutWindowSe4 = this._popoutWindowService) === null || _this$_popoutWindowSe4 === void 0 || (_this$_popoutWindowSe4 = _this$_popoutWindowSe4.findByGroup(group)) === null || _this$_popoutWindowSe4 === void 0 ? void 0 : _this$_popoutWindowSe4.popupService) !== null && _this$_popoutWindowSe3 !== void 0 ? _this$_popoutWindowSe3 : this.popupService;
|
|
15297
15752
|
}
|
|
15298
15753
|
addPopoutGroup(itemToPopout, options) {
|
|
15299
|
-
return this.
|
|
15754
|
+
return this.mutationAsync("popout", () => this._doAddPopoutGroup(itemToPopout, options));
|
|
15300
15755
|
}
|
|
15301
15756
|
/** Enumerate the popout groups currently open in their own windows. */
|
|
15302
15757
|
getPopouts() {
|
|
@@ -15393,15 +15848,32 @@ react_dom = __toESM(react_dom);
|
|
|
15393
15848
|
}
|
|
15394
15849
|
};
|
|
15395
15850
|
let floatingBox;
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15851
|
+
/**
|
|
15852
|
+
* Popping out rehomes panels into `group`, so like the floating
|
|
15853
|
+
* case it owes the caller an `onDidMovePanel` per panel. The
|
|
15854
|
+
* events are deferred until the window is wired up so listeners
|
|
15855
|
+
* observe the panels' final `popout` location.
|
|
15856
|
+
*/
|
|
15857
|
+
let movedPanels = [];
|
|
15858
|
+
if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) && isGroupAddedToDom) if (itemToPopout instanceof DockviewPanel) {
|
|
15859
|
+
const sourceGroup = itemToPopout.group;
|
|
15860
|
+
this.movingLock(() => {
|
|
15861
|
+
const panel = referenceGroup.model.removePanel(itemToPopout);
|
|
15862
|
+
group.model.openPanel(panel);
|
|
15863
|
+
});
|
|
15864
|
+
movedPanels = [{
|
|
15865
|
+
panel: itemToPopout,
|
|
15866
|
+
from: sourceGroup
|
|
15867
|
+
}];
|
|
15868
|
+
} else {
|
|
15401
15869
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15402
15870
|
from: referenceGroup,
|
|
15403
15871
|
to: group
|
|
15404
15872
|
}));
|
|
15873
|
+
movedPanels = group.panels.map((panel) => ({
|
|
15874
|
+
panel,
|
|
15875
|
+
from: referenceGroup
|
|
15876
|
+
}));
|
|
15405
15877
|
switch (referenceLocation) {
|
|
15406
15878
|
case "grid":
|
|
15407
15879
|
referenceGroup.api.setVisible(false);
|
|
@@ -15510,6 +15982,7 @@ react_dom = __toESM(react_dom);
|
|
|
15510
15982
|
group: value.popoutGroup,
|
|
15511
15983
|
window: value.getWindow()
|
|
15512
15984
|
});
|
|
15985
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15513
15986
|
return true;
|
|
15514
15987
|
}).catch((err) => {
|
|
15515
15988
|
console.error("dockview: failed to create popout.", err);
|
|
@@ -15587,6 +16060,16 @@ react_dom = __toESM(react_dom);
|
|
|
15587
16060
|
const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
|
|
15588
16061
|
const anchorPresent = members.includes(group);
|
|
15589
16062
|
const anchorIsSoleMember = anchorPresent && members.length === 1;
|
|
16063
|
+
/**
|
|
16064
|
+
* Popping a group out fires `onDidMovePanel` per panel, so closing the
|
|
16065
|
+
* window owes the caller the same: every panel in it is rehomed, into
|
|
16066
|
+
* the reference group the popout left behind or into a fresh grid slot.
|
|
16067
|
+
* `movingLock` suppresses onDidAddPanel / onDidRemovePanel on these
|
|
16068
|
+
* paths, so `onDidMovePanel` is the only event that can carry it. The
|
|
16069
|
+
* events are deferred to the end so listeners observe the panels at
|
|
16070
|
+
* their final group and location.
|
|
16071
|
+
*/
|
|
16072
|
+
const movedPanels = [];
|
|
15590
16073
|
if (genuineClose) for (const member of members) {
|
|
15591
16074
|
if (member === group) continue;
|
|
15592
16075
|
this.movingLock(() => {
|
|
@@ -15597,12 +16080,21 @@ react_dom = __toESM(react_dom);
|
|
|
15597
16080
|
});
|
|
15598
16081
|
this.redockGroupToMainGrid(member);
|
|
15599
16082
|
});
|
|
16083
|
+
for (const panel of member.panels) movedPanels.push({
|
|
16084
|
+
panel,
|
|
16085
|
+
from: member
|
|
16086
|
+
});
|
|
15600
16087
|
}
|
|
15601
16088
|
if (anchorPresent && isGroupAddedToDom && this.getPanel(referenceGroup.id)) {
|
|
16089
|
+
const rehomed = [...group.panels];
|
|
15602
16090
|
this.movingLock(() => moveGroupWithoutDestroying({
|
|
15603
16091
|
from: group,
|
|
15604
16092
|
to: referenceGroup
|
|
15605
16093
|
}));
|
|
16094
|
+
for (const panel of rehomed) movedPanels.push({
|
|
16095
|
+
panel,
|
|
16096
|
+
from: group
|
|
16097
|
+
});
|
|
15606
16098
|
if (!referenceGroup.api.isVisible) referenceGroup.api.setVisible(true);
|
|
15607
16099
|
if (this.getPanel(group.id)) this.doRemoveGroup(group, { skipPopoutAssociated: true });
|
|
15608
16100
|
} else if (anchorPresent && this.getPanel(group.id)) {
|
|
@@ -15633,10 +16125,15 @@ react_dom = __toESM(react_dom);
|
|
|
15633
16125
|
this.movingLock(() => {
|
|
15634
16126
|
this.doAddGroup(group, [0]);
|
|
15635
16127
|
});
|
|
16128
|
+
for (const panel of group.panels) movedPanels.push({
|
|
16129
|
+
panel,
|
|
16130
|
+
from: group
|
|
16131
|
+
});
|
|
15636
16132
|
}
|
|
15637
16133
|
this.doSetGroupAndPanelActive(group);
|
|
15638
16134
|
}
|
|
15639
16135
|
disposePopoutGridview();
|
|
16136
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15640
16137
|
}
|
|
15641
16138
|
addFloatingGroup(item, options) {
|
|
15642
16139
|
this.mutation("float", () => this._doAddFloatingGroup(item, options));
|
|
@@ -15645,7 +16142,15 @@ react_dom = __toESM(react_dom);
|
|
|
15645
16142
|
if (!assertModule(this._floatingGroupService, "FloatingGroup", "api.addFloatingGroup")) return;
|
|
15646
16143
|
if (item instanceof DockviewGroupPanel && item.model.location.type === "edge") return;
|
|
15647
16144
|
let group;
|
|
16145
|
+
/**
|
|
16146
|
+
* Floating relocates panels exactly like a drop onto the grid does, so
|
|
16147
|
+
* it owes the caller an `onDidMovePanel` per panel. The events are
|
|
16148
|
+
* deferred until the window is mounted below: only then do the panels
|
|
16149
|
+
* report their final `floating` location.
|
|
16150
|
+
*/
|
|
16151
|
+
let movedPanels = [];
|
|
15648
16152
|
if (item instanceof DockviewPanel) {
|
|
16153
|
+
const sourceGroup = item.group;
|
|
15649
16154
|
group = this.createGroup();
|
|
15650
16155
|
this._onDidAddGroup.fire(group);
|
|
15651
16156
|
this.movingLock(() => this.removePanel(item, {
|
|
@@ -15654,6 +16159,10 @@ react_dom = __toESM(react_dom);
|
|
|
15654
16159
|
skipSetActiveGroup: true
|
|
15655
16160
|
}));
|
|
15656
16161
|
this.movingLock(() => group.model.openPanel(item, { skipSetGroupActive: true }));
|
|
16162
|
+
movedPanels = [{
|
|
16163
|
+
panel: item,
|
|
16164
|
+
from: sourceGroup
|
|
16165
|
+
}];
|
|
15657
16166
|
} else {
|
|
15658
16167
|
var _this$_popoutWindowSe8;
|
|
15659
16168
|
group = item;
|
|
@@ -15670,11 +16179,21 @@ react_dom = __toESM(react_dom);
|
|
|
15670
16179
|
});
|
|
15671
16180
|
this.doRemoveGroup(popoutReferenceGroup, { skipDispose: true });
|
|
15672
16181
|
group = popoutReferenceGroup;
|
|
15673
|
-
|
|
15674
|
-
|
|
15675
|
-
|
|
15676
|
-
|
|
15677
|
-
}
|
|
16182
|
+
movedPanels = group.panels.map((panel) => ({
|
|
16183
|
+
panel,
|
|
16184
|
+
from: item
|
|
16185
|
+
}));
|
|
16186
|
+
} else {
|
|
16187
|
+
this.doRemoveGroup(item, {
|
|
16188
|
+
skipDispose: true,
|
|
16189
|
+
skipPopoutReturn: true,
|
|
16190
|
+
skipPopoutAssociated: false
|
|
16191
|
+
});
|
|
16192
|
+
movedPanels = group.panels.map((panel) => ({
|
|
16193
|
+
panel,
|
|
16194
|
+
from: group
|
|
16195
|
+
}));
|
|
16196
|
+
}
|
|
15678
16197
|
}
|
|
15679
16198
|
function getAnchoredBox() {
|
|
15680
16199
|
if (options === null || options === void 0 ? void 0 : options.position) {
|
|
@@ -15707,6 +16226,7 @@ react_dom = __toESM(react_dom);
|
|
|
15707
16226
|
skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
|
|
15708
16227
|
disableSmartGuides: options === null || options === void 0 ? void 0 : options.disableSmartGuides
|
|
15709
16228
|
});
|
|
16229
|
+
for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
|
|
15710
16230
|
}
|
|
15711
16231
|
/**
|
|
15712
16232
|
* Build an empty gridview configured to match the main grid's styling, for
|
|
@@ -15851,6 +16371,13 @@ react_dom = __toESM(react_dom);
|
|
|
15851
16371
|
position
|
|
15852
16372
|
};
|
|
15853
16373
|
group.model.headerPosition = position;
|
|
16374
|
+
const resizeDisposable = group.onDidChange((event) => {
|
|
16375
|
+
var _this$_shellManager3;
|
|
16376
|
+
if (!event) return;
|
|
16377
|
+
const size = position === "left" || position === "right" ? event.width : event.height;
|
|
16378
|
+
if (typeof size !== "number") return;
|
|
16379
|
+
(_this$_shellManager3 = this._shellManager) === null || _this$_shellManager3 === void 0 || _this$_shellManager3.resizeEdgeGroup(position, size);
|
|
16380
|
+
});
|
|
15854
16381
|
const autoCollapseDisposable = group.model.onDidRemovePanel(() => {
|
|
15855
16382
|
if (!group.model.isEmpty) return;
|
|
15856
16383
|
if (service.isAutoReveal(group)) queueMicrotask(() => {
|
|
@@ -15859,7 +16386,7 @@ react_dom = __toESM(react_dom);
|
|
|
15859
16386
|
});
|
|
15860
16387
|
else this.setEdgeGroupCollapsed(group, true);
|
|
15861
16388
|
});
|
|
15862
|
-
service.add(position, group, autoCollapseDisposable);
|
|
16389
|
+
service.add(position, group, new CompositeDisposable(autoCollapseDisposable, resizeDisposable));
|
|
15863
16390
|
if (options.autoHide !== void 0) service.setAutoHide(group, options.autoHide);
|
|
15864
16391
|
if (options.autoReveal !== void 0) service.setAutoReveal(group, options.autoReveal);
|
|
15865
16392
|
this._onDidAddGroup.fire(group);
|
|
@@ -15954,8 +16481,8 @@ react_dom = __toESM(react_dom);
|
|
|
15954
16481
|
}
|
|
15955
16482
|
/** The size an edge group expands to (pre-collapse); sizes the peek. */
|
|
15956
16483
|
getEdgeGroupExpandedSize(position) {
|
|
15957
|
-
var _this$_shellManager$g, _this$
|
|
15958
|
-
return (_this$_shellManager$g = (_this$
|
|
16484
|
+
var _this$_shellManager$g, _this$_shellManager4;
|
|
16485
|
+
return (_this$_shellManager$g = (_this$_shellManager4 = this._shellManager) === null || _this$_shellManager4 === void 0 ? void 0 : _this$_shellManager4.getEdgeGroupExpandedSize(position)) !== null && _this$_shellManager$g !== void 0 ? _this$_shellManager$g : 0;
|
|
15959
16486
|
}
|
|
15960
16487
|
/** Reposition a single `renderer:'always'` panel's overlay over its
|
|
15961
16488
|
* reference container, optionally forcing it visible (the auto-hide peek
|
|
@@ -16138,35 +16665,119 @@ react_dom = __toESM(react_dom);
|
|
|
16138
16665
|
if (typeof data !== "object" || data === null) throw new Error("dockview: serialized layout must be a non-null object");
|
|
16139
16666
|
if (!data.grid || ((_data$grid$root = data.grid.root) === null || _data$grid$root === void 0 ? void 0 : _data$grid$root.type) !== "branch" || !Array.isArray(data.grid.root.data)) throw new Error("dockview: root must be of type branch");
|
|
16140
16667
|
const existingPanels = /* @__PURE__ */ new Map();
|
|
16141
|
-
|
|
16668
|
+
const temporaryGroups = /* @__PURE__ */ new Map();
|
|
16669
|
+
const stagedPanels = [];
|
|
16670
|
+
const temporaryGroupDisposables = [];
|
|
16671
|
+
/**
|
|
16672
|
+
* The staging groups are detached from `_groups` and never enter the
|
|
16673
|
+
* grid, so nothing else will ever tear them down.
|
|
16674
|
+
*
|
|
16675
|
+
* `dispose()` reaches consumer `IContentRenderer.dispose()`, so one
|
|
16676
|
+
* throwing renderer must not abort the rest of the cleanup — that would
|
|
16677
|
+
* re-introduce the very leak this reclaims — nor replace the
|
|
16678
|
+
* deserialization error the caller is being given. Draining the list
|
|
16679
|
+
* also makes this safe to call more than once.
|
|
16680
|
+
*/
|
|
16681
|
+
const disposeTemporaryGroups = () => {
|
|
16682
|
+
for (const disposable of temporaryGroupDisposables) try {
|
|
16683
|
+
disposable.dispose();
|
|
16684
|
+
} catch (err) {
|
|
16685
|
+
console.error("dockview: failed to dispose a temporary group created for reuseExistingPanels", err);
|
|
16686
|
+
}
|
|
16687
|
+
temporaryGroupDisposables.length = 0;
|
|
16688
|
+
};
|
|
16142
16689
|
if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
|
|
16143
16690
|
/**
|
|
16144
|
-
*
|
|
16145
|
-
*
|
|
16146
|
-
*
|
|
16147
|
-
* 2. Remove that temporary group from the group mapping so that it doesn't get cleared when we clear the layout
|
|
16691
|
+
* Visible, always-rendered panels need individual staging groups
|
|
16692
|
+
* to remain active. Other reused panels can share a staging group.
|
|
16693
|
+
* The staging groups are excluded from the layout clear below.
|
|
16148
16694
|
*/
|
|
16149
|
-
tempGroup = this.createGroup();
|
|
16150
|
-
this._groups.delete(tempGroup.api.id);
|
|
16151
16695
|
const newPanels = Object.keys(data.panels);
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16696
|
+
let sharedTemporaryGroup;
|
|
16697
|
+
const createTemporaryGroup = () => {
|
|
16698
|
+
const temporaryGroup = this.createGroup();
|
|
16699
|
+
/**
|
|
16700
|
+
* Removing the group from `_groups` also drops the record's
|
|
16701
|
+
* `CompositeDisposable`, so capture it first and tear both it
|
|
16702
|
+
* and the group down in the `finally` below. Left undisposed a
|
|
16703
|
+
* staging group leaks its `ResizeObserver`, its
|
|
16704
|
+
* `onDidOptionsChange` subscription (retained by this
|
|
16705
|
+
* component's emitter) and the watermark its model mounts when
|
|
16706
|
+
* the group empties — once per reused panel, per `fromJSON`.
|
|
16707
|
+
*/
|
|
16708
|
+
const record = this._groups.get(temporaryGroup.api.id);
|
|
16709
|
+
this._groups.delete(temporaryGroup.api.id);
|
|
16710
|
+
temporaryGroupDisposables.push(Disposable.from(() => {
|
|
16711
|
+
/**
|
|
16712
|
+
* Reclaim the group's own resources, never its panels.
|
|
16713
|
+
* Staging is driven by the ids in `data.panels` while
|
|
16714
|
+
* reclaiming is driven by the group `views` that
|
|
16715
|
+
* reference them, so a panel whose state is present but
|
|
16716
|
+
* unreferenced is still staged here — and `dispose()`
|
|
16717
|
+
* on a non-empty group reaches the consumer's
|
|
16718
|
+
* `IContentRenderer.dispose()`. Emptying the group
|
|
16719
|
+
* first leaves those panels exactly as they were before
|
|
16720
|
+
* this teardown existed, which also keeps this safe
|
|
16721
|
+
* against any future path that rebuilds a panel under
|
|
16722
|
+
* an id that is live in the new layout.
|
|
16723
|
+
*/
|
|
16724
|
+
this.movingLock(() => {
|
|
16725
|
+
for (const panel of temporaryGroup.panels.slice()) temporaryGroup.model.removePanel(panel);
|
|
16726
|
+
});
|
|
16727
|
+
record === null || record === void 0 || record.disposable.dispose();
|
|
16728
|
+
temporaryGroup.dispose();
|
|
16729
|
+
}));
|
|
16730
|
+
return temporaryGroup;
|
|
16731
|
+
};
|
|
16732
|
+
/**
|
|
16733
|
+
* Staging and the clear below run before the deserialization
|
|
16734
|
+
* `try`, so a throw here (a consumer `onDidRemovePanel` handler, a
|
|
16735
|
+
* renderer teardown during `clear`) would escape without reclaiming
|
|
16736
|
+
* the staging groups already created.
|
|
16737
|
+
*
|
|
16738
|
+
* The creation loop is inside the guard too, not just the moves and
|
|
16739
|
+
* the clear: `createGroup()` reaches consumer code of its own —
|
|
16740
|
+
* `initialize()` mounts the watermark through
|
|
16741
|
+
* `createWatermarkComponent()` — so a throw on the n-th panel would
|
|
16742
|
+
* otherwise strand the n-1 staging groups already built.
|
|
16743
|
+
*/
|
|
16744
|
+
try {
|
|
16745
|
+
for (const panel of this.panels) if (newPanels.includes(panel.api.id)) {
|
|
16746
|
+
existingPanels.set(panel.api.id, panel);
|
|
16747
|
+
let temporaryGroup;
|
|
16748
|
+
if (panel.api.renderer === "always" && panel.api.isVisible) temporaryGroup = createTemporaryGroup();
|
|
16749
|
+
else {
|
|
16750
|
+
var _sharedTemporaryGroup;
|
|
16751
|
+
(_sharedTemporaryGroup = sharedTemporaryGroup) !== null && _sharedTemporaryGroup !== void 0 || (sharedTemporaryGroup = createTemporaryGroup());
|
|
16752
|
+
temporaryGroup = sharedTemporaryGroup;
|
|
16753
|
+
}
|
|
16754
|
+
temporaryGroups.set(panel.api.id, temporaryGroup);
|
|
16755
|
+
stagedPanels.push({
|
|
16756
|
+
panel,
|
|
16757
|
+
temporaryGroup
|
|
16758
|
+
});
|
|
16759
|
+
}
|
|
16760
|
+
this.movingLock(() => {
|
|
16761
|
+
stagedPanels.forEach(({ panel, temporaryGroup }) => {
|
|
16762
|
+
this.moveGroupOrPanel({
|
|
16763
|
+
from: {
|
|
16764
|
+
groupId: panel.api.group.api.id,
|
|
16765
|
+
panelId: panel.api.id
|
|
16766
|
+
},
|
|
16767
|
+
to: {
|
|
16768
|
+
group: temporaryGroup,
|
|
16769
|
+
position: "center"
|
|
16770
|
+
},
|
|
16771
|
+
keepEmptyGroups: true
|
|
16772
|
+
});
|
|
16165
16773
|
});
|
|
16166
16774
|
});
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16775
|
+
this.clear();
|
|
16776
|
+
} catch (err) {
|
|
16777
|
+
disposeTemporaryGroups();
|
|
16778
|
+
throw err;
|
|
16779
|
+
}
|
|
16780
|
+
} else this.clear();
|
|
16170
16781
|
const { grid, panels, activeGroup } = data;
|
|
16171
16782
|
try {
|
|
16172
16783
|
var _data$floatingGroups, _data$popoutGroups, _this$_popoutWindowSe12, _this$_floatingGroupS5, _this$_watermarkServi2;
|
|
@@ -16198,9 +16809,10 @@ react_dom = __toESM(react_dom);
|
|
|
16198
16809
|
* due to a corruption of input data.
|
|
16199
16810
|
*/
|
|
16200
16811
|
const existingPanel = existingPanels.get(child);
|
|
16201
|
-
|
|
16812
|
+
const temporaryGroup = temporaryGroups.get(child);
|
|
16813
|
+
if (temporaryGroup && existingPanel) {
|
|
16202
16814
|
this.movingLock(() => {
|
|
16203
|
-
|
|
16815
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16204
16816
|
});
|
|
16205
16817
|
createdPanels.push(existingPanel);
|
|
16206
16818
|
existingPanel.updateFromStateModel(panels[child]);
|
|
@@ -16230,7 +16842,7 @@ react_dom = __toESM(react_dom);
|
|
|
16230
16842
|
return createGroupFromSerializedState(node.data);
|
|
16231
16843
|
} });
|
|
16232
16844
|
this._layoutFromShell(width, height);
|
|
16233
|
-
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels);
|
|
16845
|
+
if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels, existingPanels, temporaryGroups);
|
|
16234
16846
|
this.deserializeFloatingWindows((_data$floatingGroups = data.floatingGroups) !== null && _data$floatingGroups !== void 0 ? _data$floatingGroups : [], createGroupFromSerializedState);
|
|
16235
16847
|
const popoutPromises = this.deserializePopoutWindows((_data$popoutGroups = data.popoutGroups) !== null && _data$popoutGroups !== void 0 ? _data$popoutGroups : [], createGroupFromSerializedState);
|
|
16236
16848
|
(_this$_popoutWindowSe12 = this._popoutWindowService) === null || _this$_popoutWindowSe12 === void 0 || _this$_popoutWindowSe12.finishRestoration(popoutPromises);
|
|
@@ -16267,6 +16879,8 @@ react_dom = __toESM(react_dom);
|
|
|
16267
16879
|
* expect trying to load a corrupted layout to result in an error and not silently fail...
|
|
16268
16880
|
*/
|
|
16269
16881
|
throw err;
|
|
16882
|
+
} finally {
|
|
16883
|
+
disposeTemporaryGroups();
|
|
16270
16884
|
}
|
|
16271
16885
|
this.debouncedUpdateAllPositions();
|
|
16272
16886
|
this._onDidLayoutFromJSON.fire();
|
|
@@ -16289,7 +16903,7 @@ react_dom = __toESM(react_dom);
|
|
|
16289
16903
|
members
|
|
16290
16904
|
};
|
|
16291
16905
|
}
|
|
16292
|
-
deserializeEdgeGroups(edgeGroups, panels) {
|
|
16906
|
+
deserializeEdgeGroups(edgeGroups, panels, existingPanels, temporaryGroups) {
|
|
16293
16907
|
const edgeService = assertModule(this._edgeGroupService, "EdgeGroup", "fromJSON edge restoration");
|
|
16294
16908
|
if (!edgeService) return;
|
|
16295
16909
|
for (const _position of [
|
|
@@ -16319,13 +16933,40 @@ react_dom = __toESM(react_dom);
|
|
|
16319
16933
|
if (groupState) {
|
|
16320
16934
|
const { views, activeView } = groupState;
|
|
16321
16935
|
const createdPanels = [];
|
|
16322
|
-
for (const panelId of views)
|
|
16323
|
-
|
|
16324
|
-
|
|
16936
|
+
for (const panelId of views) {
|
|
16937
|
+
if (!panels[panelId]) continue;
|
|
16938
|
+
/**
|
|
16939
|
+
* Reclaim a staged panel rather than rebuilding it, the
|
|
16940
|
+
* same way the grid path does. Deserializing here instead
|
|
16941
|
+
* would honour `reuseExistingPanels` everywhere except edge
|
|
16942
|
+
* groups: the live panel keeps sitting in its staging group
|
|
16943
|
+
* while a second panel is built under the same id, so the
|
|
16944
|
+
* consumer's renderer for the original is orphaned — never
|
|
16945
|
+
* disposed, and its element left inside the id-keyed
|
|
16946
|
+
* overlay entry the replacement now shares.
|
|
16947
|
+
*/
|
|
16948
|
+
const existingPanel = existingPanels.get(panelId);
|
|
16949
|
+
const temporaryGroup = temporaryGroups.get(panelId);
|
|
16950
|
+
if (temporaryGroup && existingPanel) {
|
|
16951
|
+
this.movingLock(() => {
|
|
16952
|
+
temporaryGroup.model.removePanel(existingPanel);
|
|
16953
|
+
});
|
|
16954
|
+
createdPanels.push(existingPanel);
|
|
16955
|
+
existingPanel.updateFromStateModel(panels[panelId]);
|
|
16956
|
+
} else {
|
|
16957
|
+
const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
|
|
16958
|
+
createdPanels.push(panel);
|
|
16959
|
+
}
|
|
16325
16960
|
}
|
|
16326
16961
|
for (const panel of createdPanels) {
|
|
16327
16962
|
const isActive = activeView === panel.id;
|
|
16328
|
-
|
|
16963
|
+
if (existingPanels.has(panel.api.id)) this.movingLock(() => {
|
|
16964
|
+
edgeGroup.model.openPanel(panel, {
|
|
16965
|
+
skipSetActive: !isActive,
|
|
16966
|
+
skipSetGroupActive: true
|
|
16967
|
+
});
|
|
16968
|
+
});
|
|
16969
|
+
else edgeGroup.model.openPanel(panel, {
|
|
16329
16970
|
skipSetActive: !isActive,
|
|
16330
16971
|
skipSetGroupActive: true
|
|
16331
16972
|
});
|
|
@@ -16749,22 +17390,100 @@ react_dom = __toESM(react_dom);
|
|
|
16749
17390
|
* outermost mutation.
|
|
16750
17391
|
*/
|
|
16751
17392
|
mutation(kind, func) {
|
|
16752
|
-
const
|
|
17393
|
+
const close = this.openMutation(kind);
|
|
17394
|
+
try {
|
|
17395
|
+
return func();
|
|
17396
|
+
} finally {
|
|
17397
|
+
close();
|
|
17398
|
+
}
|
|
17399
|
+
}
|
|
17400
|
+
/**
|
|
17401
|
+
* `mutation()` for an operation whose work continues after the synchronous
|
|
17402
|
+
* call returns. The transaction stays open until the returned promise
|
|
17403
|
+
* settles, so everything the operation does - the group it adds, the panels
|
|
17404
|
+
* it relocates - lands inside the bracket, matching the synchronous
|
|
17405
|
+
* move / float paths.
|
|
17406
|
+
*/
|
|
17407
|
+
mutationAsync(kind, func) {
|
|
17408
|
+
var _this = this;
|
|
17409
|
+
return _asyncToGenerator(function* () {
|
|
17410
|
+
const close = _this.openMutation(kind);
|
|
17411
|
+
try {
|
|
17412
|
+
return yield func();
|
|
17413
|
+
} finally {
|
|
17414
|
+
close();
|
|
17415
|
+
}
|
|
17416
|
+
})();
|
|
17417
|
+
}
|
|
17418
|
+
/**
|
|
17419
|
+
* Open a transaction and return the function that closes it. Shared by the
|
|
17420
|
+
* synchronous and asynchronous brackets; the returned function must be
|
|
17421
|
+
* called exactly once.
|
|
17422
|
+
*
|
|
17423
|
+
* Both ends key off the depth counter reaching zero rather than off which
|
|
17424
|
+
* bracket opened first. For synchronous nesting the two are the same thing
|
|
17425
|
+
* - brackets close in the order they opened - but asynchronous transactions
|
|
17426
|
+
* can *overlap* rather than nest (two `addPopoutGroup` calls in flight at
|
|
17427
|
+
* once, or a restore staggering several), and there the first to open is
|
|
17428
|
+
* not the last to close. Reporting on the opener would fire `didMutate`
|
|
17429
|
+
* while the other transaction was still doing structural work, which is the
|
|
17430
|
+
* very thing the async bracket exists to prevent. Overlapping transactions
|
|
17431
|
+
* therefore report as one, tagged with the kind of the last to finish.
|
|
17432
|
+
*/
|
|
17433
|
+
openMutation(kind) {
|
|
16753
17434
|
const origin = this._origin;
|
|
16754
|
-
if (
|
|
17435
|
+
if (this._mutationDepth === 0) this._onWillMutateLayout.fire({
|
|
16755
17436
|
kind,
|
|
16756
17437
|
origin
|
|
16757
17438
|
});
|
|
16758
17439
|
this._mutationDepth++;
|
|
16759
|
-
|
|
16760
|
-
return func();
|
|
16761
|
-
} finally {
|
|
17440
|
+
return () => {
|
|
16762
17441
|
this._mutationDepth--;
|
|
16763
|
-
if (
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
17442
|
+
if (this._mutationDepth === 0) {
|
|
17443
|
+
this.flushLocationChanges();
|
|
17444
|
+
this._onDidMutateLayout.fire({
|
|
17445
|
+
kind,
|
|
17446
|
+
origin
|
|
17447
|
+
});
|
|
17448
|
+
}
|
|
17449
|
+
};
|
|
17450
|
+
}
|
|
17451
|
+
/**
|
|
17452
|
+
* Coalesce a panel's `onDidLocationChange` to the end of the enclosing
|
|
17453
|
+
* transaction, or fire it immediately when no transaction is in flight.
|
|
17454
|
+
*
|
|
17455
|
+
* Relocating a panel touches its location twice: once as it is reparented
|
|
17456
|
+
* into the destination group - which, when that group has just been created
|
|
17457
|
+
* for a floating or popout window, has not been told where it lives yet -
|
|
17458
|
+
* and once as the group is tagged with its final location. Reporting each
|
|
17459
|
+
* signal as it happens therefore leaks an intermediate `grid` location the
|
|
17460
|
+
* panel was never in, at a moment when it belongs to neither group's panel
|
|
17461
|
+
* list and so is missing from `api.panels`.
|
|
17462
|
+
*
|
|
17463
|
+
* Deferring collapses those signals into a single event carrying the
|
|
17464
|
+
* settled location. Note the signals are deliberately *not* compared
|
|
17465
|
+
* against the panel's previous location: a panel can move between two
|
|
17466
|
+
* floating windows without its location type changing, and this event is
|
|
17467
|
+
* the only signal `OverlayRenderContainer` has to re-resolve the panel's
|
|
17468
|
+
* z-index against its new host window.
|
|
17469
|
+
*/
|
|
17470
|
+
deferLocationChange(key, fire) {
|
|
17471
|
+
if (this._mutationDepth === 0) {
|
|
17472
|
+
fire();
|
|
17473
|
+
return;
|
|
16767
17474
|
}
|
|
17475
|
+
this._pendingLocationChanges.set(key, fire);
|
|
17476
|
+
}
|
|
17477
|
+
/**
|
|
17478
|
+
* Report every panel whose location moved during the transaction that has
|
|
17479
|
+
* just closed. Each callback reads the panel's location at this point, so
|
|
17480
|
+
* what it reports is where the panel ended up.
|
|
17481
|
+
*/
|
|
17482
|
+
flushLocationChanges() {
|
|
17483
|
+
if (this._pendingLocationChanges.size === 0) return;
|
|
17484
|
+
const pending = Array.from(this._pendingLocationChanges.values());
|
|
17485
|
+
this._pendingLocationChanges.clear();
|
|
17486
|
+
for (const fire of pending) fire();
|
|
16768
17487
|
}
|
|
16769
17488
|
/**
|
|
16770
17489
|
* The origin of the operation currently in progress (`'user'` by default).
|
|
@@ -16805,6 +17524,18 @@ react_dom = __toESM(react_dom);
|
|
|
16805
17524
|
origin: this._origin
|
|
16806
17525
|
});
|
|
16807
17526
|
}
|
|
17527
|
+
/**
|
|
17528
|
+
* Announce that `panel` has finished relocating. Must be called once the
|
|
17529
|
+
* move has settled: `to` is read from the panel's current group, so an
|
|
17530
|
+
* early call would report the source group as the destination.
|
|
17531
|
+
*/
|
|
17532
|
+
fireDidMovePanel(panel, from) {
|
|
17533
|
+
this._onDidMovePanel.fire({
|
|
17534
|
+
panel,
|
|
17535
|
+
from,
|
|
17536
|
+
to: panel.group
|
|
17537
|
+
});
|
|
17538
|
+
}
|
|
16808
17539
|
moveGroupOrPanel(options) {
|
|
16809
17540
|
this.mutation("move", () => this._doMoveGroupOrPanel(options));
|
|
16810
17541
|
}
|
|
@@ -16865,10 +17596,7 @@ react_dom = __toESM(react_dom);
|
|
|
16865
17596
|
});
|
|
16866
17597
|
});
|
|
16867
17598
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(destinationGroup);
|
|
16868
|
-
this.
|
|
16869
|
-
panel: removedPanel,
|
|
16870
|
-
from: sourceGroup
|
|
16871
|
-
});
|
|
17599
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
16872
17600
|
} else {
|
|
16873
17601
|
/**
|
|
16874
17602
|
* Dropping a panel to the extremities of a group which will place that panel
|
|
@@ -16887,10 +17615,7 @@ react_dom = __toESM(react_dom);
|
|
|
16887
17615
|
const [sourceParentLocation, from] = tail(getGridLocation(sourceGroup.element));
|
|
16888
17616
|
if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
|
|
16889
17617
|
this.gridview.moveView(sourceParentLocation, from, to);
|
|
16890
|
-
this.
|
|
16891
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
16892
|
-
from: sourceGroup
|
|
16893
|
-
});
|
|
17618
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
16894
17619
|
return;
|
|
16895
17620
|
}
|
|
16896
17621
|
}
|
|
@@ -16918,13 +17643,10 @@ react_dom = __toESM(react_dom);
|
|
|
16918
17643
|
}));
|
|
16919
17644
|
this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
16920
17645
|
const updatedTargetLocation = getRelativeLocation(destinationGridview.orientation, getGridLocation(destinationGroup.element), destinationTarget);
|
|
16921
|
-
const newGroup = this.createGroupAtLocation(updatedTargetLocation,
|
|
17646
|
+
const newGroup = this.createGroupAtLocation(updatedTargetLocation, this.dropSizing(getGridLocation(destinationGroup.element)), void 0, destinationGridview);
|
|
16922
17647
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetActive: true }));
|
|
16923
17648
|
this.doSetGroupAndPanelActive(newGroup);
|
|
16924
|
-
this.
|
|
16925
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
16926
|
-
from: sourceGroup
|
|
16927
|
-
});
|
|
17649
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
16928
17650
|
return;
|
|
16929
17651
|
}
|
|
16930
17652
|
if (sourceGroup.api.location.type === "edge") {
|
|
@@ -16938,13 +17660,10 @@ react_dom = __toESM(react_dom);
|
|
|
16938
17660
|
skipSetActiveGroup: true
|
|
16939
17661
|
}));
|
|
16940
17662
|
if (!removedPanel) throw new Error(`dockview: No panel with id ${sourceItemId}`);
|
|
16941
|
-
const newGroup = this.createGroupAtLocation(targetLocation,
|
|
17663
|
+
const newGroup = this.createGroupAtLocation(targetLocation, this.dropSizing(referenceLocation), void 0, destinationGridview);
|
|
16942
17664
|
this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
16943
17665
|
this.doSetGroupAndPanelActive(newGroup);
|
|
16944
|
-
this.
|
|
16945
|
-
panel: removedPanel,
|
|
16946
|
-
from: sourceGroup
|
|
16947
|
-
});
|
|
17666
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
16948
17667
|
return;
|
|
16949
17668
|
}
|
|
16950
17669
|
const targetGroup = this.movingLock(() => this.doRemoveGroup(sourceGroup, {
|
|
@@ -16953,13 +17672,10 @@ react_dom = __toESM(react_dom);
|
|
|
16953
17672
|
}));
|
|
16954
17673
|
const updatedReferenceLocation = getGridLocation(destinationGroup.element);
|
|
16955
17674
|
const location = getRelativeLocation(destinationGridview.orientation, updatedReferenceLocation, destinationTarget);
|
|
16956
|
-
this.movingLock(() => this.doAddGroup(targetGroup, location,
|
|
17675
|
+
this.movingLock(() => this.doAddGroup(targetGroup, location, this.dropSizing(updatedReferenceLocation), destinationGridview));
|
|
16957
17676
|
this.setGroupLocationForRoot(targetGroup, destinationGridview);
|
|
16958
17677
|
this.doSetGroupAndPanelActive(targetGroup);
|
|
16959
|
-
this.
|
|
16960
|
-
panel: this.getGroupPanel(sourceItemId),
|
|
16961
|
-
from: sourceGroup
|
|
16962
|
-
});
|
|
17678
|
+
this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
|
|
16963
17679
|
} else {
|
|
16964
17680
|
/**
|
|
16965
17681
|
* The group we are removing from has many panels, we need to remove the panels we are moving,
|
|
@@ -16971,13 +17687,10 @@ react_dom = __toESM(react_dom);
|
|
|
16971
17687
|
}));
|
|
16972
17688
|
if (!removedPanel) throw new Error(`dockview: No panel with id ${sourceItemId}`);
|
|
16973
17689
|
const dropLocation = getRelativeLocation(destinationGridview.orientation, referenceLocation, destinationTarget);
|
|
16974
|
-
const group = this.createGroupAtLocation(dropLocation,
|
|
17690
|
+
const group = this.createGroupAtLocation(dropLocation, this.dropSizing(referenceLocation), void 0, destinationGridview);
|
|
16975
17691
|
this.movingLock(() => group.model.openPanel(removedPanel, { skipSetGroupActive: true }));
|
|
16976
17692
|
this.doSetGroupAndPanelActive(group);
|
|
16977
|
-
this.
|
|
16978
|
-
panel: removedPanel,
|
|
16979
|
-
from: sourceGroup
|
|
16980
|
-
});
|
|
17693
|
+
this.fireDidMovePanel(removedPanel, sourceGroup);
|
|
16981
17694
|
}
|
|
16982
17695
|
}
|
|
16983
17696
|
}
|
|
@@ -17012,16 +17725,13 @@ react_dom = __toESM(react_dom);
|
|
|
17012
17725
|
});
|
|
17013
17726
|
for (const panel of removedPanels) targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
|
|
17014
17727
|
if (!options.skipSetActive) this.doSetGroupAndPanelActive(targetGroup);
|
|
17015
|
-
for (const panel of removedPanels) this.
|
|
17016
|
-
panel,
|
|
17017
|
-
from: sourceGroup
|
|
17018
|
-
});
|
|
17728
|
+
for (const panel of removedPanels) this.fireDidMovePanel(panel, sourceGroup);
|
|
17019
17729
|
};
|
|
17020
17730
|
let targetGroup;
|
|
17021
17731
|
if (!destinationTarget || destinationTarget === "center" || !referenceLocation) targetGroup = destinationGroup;
|
|
17022
17732
|
else {
|
|
17023
17733
|
const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
|
|
17024
|
-
targetGroup = this.createGroupAtLocation(dropLocation);
|
|
17734
|
+
targetGroup = this.createGroupAtLocation(dropLocation, this.dropSizing(referenceLocation));
|
|
17025
17735
|
}
|
|
17026
17736
|
if (!options.keepEmptyGroups && sourceGroup.model.size === 0 && sourceGroup !== targetGroup) this.doRemoveGroup(sourceGroup, { skipActive: true });
|
|
17027
17737
|
addPanelsToGroup(targetGroup);
|
|
@@ -17036,10 +17746,12 @@ react_dom = __toESM(react_dom);
|
|
|
17036
17746
|
this.mutation("maximize", () => super.exitMaximizedGroup());
|
|
17037
17747
|
}
|
|
17038
17748
|
_doMoveGroup(options) {
|
|
17749
|
+
var _mergedPanels;
|
|
17039
17750
|
const from = options.from.group;
|
|
17040
17751
|
const to = options.to.group;
|
|
17041
17752
|
const target = options.to.position;
|
|
17042
17753
|
let source = from;
|
|
17754
|
+
let mergedPanels;
|
|
17043
17755
|
if (target === "center") {
|
|
17044
17756
|
const activePanel = from.activePanel;
|
|
17045
17757
|
const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
|
|
@@ -17057,6 +17769,7 @@ react_dom = __toESM(react_dom);
|
|
|
17057
17769
|
skipSetGroupActive: true
|
|
17058
17770
|
});
|
|
17059
17771
|
});
|
|
17772
|
+
mergedPanels = panels;
|
|
17060
17773
|
for (const snapshot of tabGroupSnapshots) {
|
|
17061
17774
|
const newTabGroup = to.model.createTabGroup({
|
|
17062
17775
|
label: snapshot.label,
|
|
@@ -17069,6 +17782,21 @@ react_dom = __toESM(react_dom);
|
|
|
17069
17782
|
if (options.skipSetActive !== true) this.doSetGroupAndPanelActive(to);
|
|
17070
17783
|
else if (!this.activePanel) this.doSetGroupAndPanelActive(to);
|
|
17071
17784
|
} else {
|
|
17785
|
+
const isReorderWithinBranch = (() => {
|
|
17786
|
+
if (from.api.location.type === "edge" || to.api.location.type === "edge") return false;
|
|
17787
|
+
const root = this.getGridviewForGroup(from);
|
|
17788
|
+
if (root !== this.getGridviewForGroup(to)) return false;
|
|
17789
|
+
let fromLocation;
|
|
17790
|
+
let toLocation;
|
|
17791
|
+
try {
|
|
17792
|
+
fromLocation = getGridLocation(from.element);
|
|
17793
|
+
toLocation = getGridLocation(to.element);
|
|
17794
|
+
} catch (_unused) {
|
|
17795
|
+
return false;
|
|
17796
|
+
}
|
|
17797
|
+
if (fromLocation.length === 0 || toLocation.length === 0) return false;
|
|
17798
|
+
return sequenceEquals(tail(fromLocation)[0], tail(toLocation)[0]) && getLocationOrientation(root.orientation, toLocation) === getDirectionOrientation(target);
|
|
17799
|
+
})();
|
|
17072
17800
|
if (from.api.location.type === "edge") {
|
|
17073
17801
|
/**
|
|
17074
17802
|
* Edge groups are permanent structural elements and must
|
|
@@ -17134,23 +17862,17 @@ react_dom = __toESM(react_dom);
|
|
|
17134
17862
|
const referenceLocation = getGridLocation(to.element);
|
|
17135
17863
|
const dropLocation = getRelativeLocation(destGridview.orientation, referenceLocation, target);
|
|
17136
17864
|
let size;
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
case "HORIZONTAL":
|
|
17142
|
-
size = referenceLocation.length % 2 == 0 ? from.api.height : from.api.width;
|
|
17143
|
-
break;
|
|
17865
|
+
if (isReorderWithinBranch) size = getDirectionOrientation(target) === "HORIZONTAL" ? from.api.width : from.api.height;
|
|
17866
|
+
else {
|
|
17867
|
+
var _referenceLocation;
|
|
17868
|
+
size = Sizing.Split((_referenceLocation = referenceLocation[referenceLocation.length - 1]) !== null && _referenceLocation !== void 0 ? _referenceLocation : 0);
|
|
17144
17869
|
}
|
|
17145
17870
|
destGridview.addView(source, size, dropLocation);
|
|
17146
17871
|
this.setGroupLocationForRoot(source, destGridview);
|
|
17147
17872
|
}
|
|
17148
17873
|
}
|
|
17149
|
-
source.panels.forEach((panel) => {
|
|
17150
|
-
this.
|
|
17151
|
-
panel,
|
|
17152
|
-
from
|
|
17153
|
-
});
|
|
17874
|
+
((_mergedPanels = mergedPanels) !== null && _mergedPanels !== void 0 ? _mergedPanels : source.panels).forEach((panel) => {
|
|
17875
|
+
this.fireDidMovePanel(panel, from);
|
|
17154
17876
|
});
|
|
17155
17877
|
this.debouncedUpdateAllPositions();
|
|
17156
17878
|
if (options.skipSetActive === false) {
|
|
@@ -17268,6 +17990,16 @@ react_dom = __toESM(react_dom);
|
|
|
17268
17990
|
});
|
|
17269
17991
|
return panel;
|
|
17270
17992
|
}
|
|
17993
|
+
/**
|
|
17994
|
+
* Sizing for a group created by a drop next to `referenceLocation`: half
|
|
17995
|
+
* of the group the overlay was drawn over, leaving its siblings alone, so
|
|
17996
|
+
* the panel lands in the region the overlay indicated (#1612). Gridview
|
|
17997
|
+
* rewrites the index to 0 when a cross-axis drop wraps the reference in a
|
|
17998
|
+
* new branch, so one value serves both paths.
|
|
17999
|
+
*/
|
|
18000
|
+
dropSizing(referenceLocation) {
|
|
18001
|
+
return Sizing.Split(referenceLocation.length === 0 ? 0 : referenceLocation[referenceLocation.length - 1]);
|
|
18002
|
+
}
|
|
17271
18003
|
createGroupAtLocation(location, size, options, gridview = this.gridview) {
|
|
17272
18004
|
const group = this.createGroup(options);
|
|
17273
18005
|
this.doAddGroup(group, location, size, gridview);
|
|
@@ -17327,22 +18059,22 @@ react_dom = __toESM(react_dom);
|
|
|
17327
18059
|
return location.length % 2 == 1 ? rootOrientation : orthogonal(rootOrientation);
|
|
17328
18060
|
}
|
|
17329
18061
|
updateTheme() {
|
|
17330
|
-
var _this$_options$theme, _this$_shellThemeClas, _theme$gap, _this$_popoutWindowSe23, _this$_popoutWindowSe24, _this$
|
|
18062
|
+
var _this$_options$theme, _this$_shellThemeClas, _theme$gap, _this$_popoutWindowSe23, _this$_popoutWindowSe24, _this$_shellManager5, _theme$edgeGroupColla, _theme$tabGroupIndica;
|
|
17331
18063
|
const theme = (_this$_options$theme = this._options.theme) !== null && _this$_options$theme !== void 0 ? _this$_options$theme : themeAbyss;
|
|
17332
18064
|
(_this$_shellThemeClas = this._shellThemeClassnames) === null || _this$_shellThemeClas === void 0 || _this$_shellThemeClas.setClassNames(theme.className);
|
|
17333
18065
|
const gap = (_theme$gap = theme.gap) !== null && _theme$gap !== void 0 ? _theme$gap : 0;
|
|
17334
18066
|
this.gridview.margin = gap;
|
|
17335
18067
|
for (const floating of this.floatingGroups) floating.gridview.margin = gap;
|
|
17336
18068
|
for (const entry of (_this$_popoutWindowSe23 = (_this$_popoutWindowSe24 = this._popoutWindowService) === null || _this$_popoutWindowSe24 === void 0 ? void 0 : _this$_popoutWindowSe24.entries) !== null && _this$_popoutWindowSe23 !== void 0 ? _this$_popoutWindowSe23 : []) entry.gridview.margin = gap;
|
|
17337
|
-
(_this$
|
|
18069
|
+
(_this$_shellManager5 = this._shellManager) === null || _this$_shellManager5 === void 0 || _this$_shellManager5.updateTheme(gap, (_theme$edgeGroupColla = theme.edgeGroupCollapsedSize) !== null && _theme$edgeGroupColla !== void 0 ? _theme$edgeGroupColla : 35);
|
|
17338
18070
|
if (theme.dndOverlayBorder === void 0) {
|
|
17339
|
-
var _this$
|
|
18071
|
+
var _this$_shellManager6;
|
|
17340
18072
|
this.element.style.removeProperty("--dv-drag-over-border");
|
|
17341
|
-
(_this$
|
|
18073
|
+
(_this$_shellManager6 = this._shellManager) === null || _this$_shellManager6 === void 0 || _this$_shellManager6.element.style.removeProperty("--dv-drag-over-border");
|
|
17342
18074
|
} else {
|
|
17343
|
-
var _this$
|
|
18075
|
+
var _this$_shellManager7;
|
|
17344
18076
|
this.element.style.setProperty("--dv-drag-over-border", theme.dndOverlayBorder);
|
|
17345
|
-
(_this$
|
|
18077
|
+
(_this$_shellManager7 = this._shellManager) === null || _this$_shellManager7 === void 0 || _this$_shellManager7.element.style.setProperty("--dv-drag-over-border", theme.dndOverlayBorder);
|
|
17346
18078
|
}
|
|
17347
18079
|
switch (theme.dndOverlayMounting) {
|
|
17348
18080
|
case "absolute":
|
|
@@ -19196,6 +19928,8 @@ exports.AdvancedDnDModule = AdvancedDnDModule;
|
|
|
19196
19928
|
exports.AdvancedDnDService = AdvancedDnDService;
|
|
19197
19929
|
exports.BaseGrid = BaseGrid;
|
|
19198
19930
|
exports.ContentContainer = ContentContainer;
|
|
19931
|
+
exports.ContextMenuController = ContextMenuController;
|
|
19932
|
+
exports.ContextMenuModule = ContextMenuModule;
|
|
19199
19933
|
exports.DEFAULT_TAB_GROUP_COLORS = DEFAULT_TAB_GROUP_COLORS;
|
|
19200
19934
|
exports.DefaultDockviewDeserialzier = DefaultDockviewDeserialzier;
|
|
19201
19935
|
exports.DefaultTab = DefaultTab;
|