dockview-core 8.2.0 → 8.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * dockview-core
3
- * @version 8.2.0
3
+ * @version 8.3.1
4
4
  * @link https://github.com/dockview/dockview
5
5
  * @license MIT
6
6
  */
@@ -1055,8 +1055,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1055
1055
  container.appendChild(view.element);
1056
1056
  let viewSize;
1057
1057
  if (typeof size === "number") viewSize = size;
1058
- else if (size.type === "split") viewSize = this.getViewSize(size.index) / 2;
1059
- else if (size.type === "invisible") viewSize = { cachedVisibleSize: size.cachedVisibleSize };
1058
+ else if (size.type === "split") {
1059
+ const splitTarget = this.viewItems[size.index];
1060
+ if (splitTarget) {
1061
+ const half = Math.floor(splitTarget.size / 2);
1062
+ viewSize = splitTarget.size - half;
1063
+ splitTarget.size = half;
1064
+ } else viewSize = this.getViewSize(size.index) / 2;
1065
+ } else if (size.type === "invisible") viewSize = { cachedVisibleSize: size.cachedVisibleSize };
1060
1066
  else viewSize = view.minimumSize;
1061
1067
  const disposable = view.onDidChange((newSize) => this.onDidChange(viewItem, newSize.size));
1062
1068
  const viewItem = new ViewItem(container, view, viewSize, { dispose: () => {
@@ -4448,8 +4454,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
4448
4454
  for (const el of elements) {
4449
4455
  let current = el;
4450
4456
  while (current) {
4457
+ var _target$isHitTestTran;
4451
4458
  const target = this._targetByElement.get(current);
4452
- if (target) return target;
4459
+ if (target && !((_target$isHitTestTran = target.isHitTestTransparent) === null || _target$isHitTestTran === void 0 ? void 0 : _target$isHitTestTran.call(target))) return target;
4453
4460
  current = current.parentElement;
4454
4461
  }
4455
4462
  }
@@ -4545,10 +4552,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
4545
4552
  element: this.element,
4546
4553
  handleDragOver: (e) => this._onDragOver(e),
4547
4554
  handleDragLeave: () => this._onDragLeave(),
4548
- handleDrop: (e) => this._onDropEvent(e)
4555
+ handleDrop: (e) => this._onDropEvent(e),
4556
+ isHitTestTransparent: options.isHitTestTransparent
4549
4557
  };
4550
4558
  this.addDisposables(this._onDrop, this._onWillShowOverlay, PointerDragController.getInstance().registerTarget(handle));
4551
4559
  }
4560
+ clearOverlay() {
4561
+ this._clearOwnOverlay();
4562
+ }
4552
4563
  setTargetZones(zones) {
4553
4564
  this._acceptedTargetZonesSet = new Set(zones);
4554
4565
  }
@@ -5801,7 +5812,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
5801
5812
  };
5802
5813
  case "auto":
5803
5814
  case void 0:
5804
- default: return isCoarsePrimaryInput$1() ? {
5815
+ default: return isCoarsePrimaryInput$2() ? {
5805
5816
  html5: false,
5806
5817
  pointer: true,
5807
5818
  pointerHandlesMouse: true
@@ -5812,7 +5823,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
5812
5823
  };
5813
5824
  }
5814
5825
  }
5815
- function isCoarsePrimaryInput$1() {
5826
+ function isCoarsePrimaryInput$2() {
5816
5827
  if (globalThis.window === void 0 || !globalThis.matchMedia) return false;
5817
5828
  const coarse = globalThis.matchMedia("(pointer: coarse)").matches;
5818
5829
  const fine = globalThis.matchMedia("(pointer: fine)").matches;
@@ -5868,6 +5879,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
5868
5879
  if (this.accessor.id === (data === null || data === void 0 ? void 0 : data.viewId)) {
5869
5880
  var _this$accessor$option;
5870
5881
  if (((_this$accessor$option = this.accessor.options.theme) === null || _this$accessor$option === void 0 ? void 0 : _this$accessor$option.tabAnimation) === "smooth") return false;
5882
+ if (data.tabGroupId && this.group.model.getTabGroupForPanel(this.panel.id)) return false;
5871
5883
  return true;
5872
5884
  }
5873
5885
  return this.group.model.canDisplayOverlay(event, position, "tab");
@@ -7315,7 +7327,23 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
7315
7327
  }
7316
7328
  updateDirection() {
7317
7329
  const isVertical = this._ctx.getDirection() === "vertical";
7318
- for (const [, entry] of this._chipRenderers) entry.dropTarget.setTargetZones(isVertical ? ["top"] : ["left"]);
7330
+ for (const [, entry] of this._chipRenderers) {
7331
+ const zones = isVertical ? ["top"] : ["left"];
7332
+ entry.dropTarget.setTargetZones(zones);
7333
+ entry.pointerDropTarget.setTargetZones(zones);
7334
+ }
7335
+ }
7336
+ /**
7337
+ * Drop any overlay the chips are showing. A group move is committed by a
7338
+ * capturing listener on the tabs list that stops the event, so the chip
7339
+ * target under the cursor never sees the drop that would clear its own.
7340
+ */
7341
+ clearChipDropOverlays() {
7342
+ for (const [, entry] of this._chipRenderers) {
7343
+ var _entry$dropTarget, _entry$pointerDropTar;
7344
+ (_entry$dropTarget = entry.dropTarget) === null || _entry$dropTarget === void 0 || _entry$dropTarget.clearOverlay();
7345
+ (_entry$pointerDropTar = entry.pointerDropTarget) === null || _entry$pointerDropTar === void 0 || _entry$pointerDropTar.clearOverlay();
7346
+ }
7319
7347
  }
7320
7348
  snapshotChipWidths() {
7321
7349
  const widths = /* @__PURE__ */ new Map();
@@ -7564,9 +7592,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
7564
7592
  };
7565
7593
  if (chip instanceof TabGroupChip) disposables.push(chip.onContextMenu(onContextMenu));
7566
7594
  else disposables.push(new LongPressDetector(chip.element, { onLongPress: onContextMenu }), addDisposableListener(chip.element, "contextmenu", onContextMenu));
7567
- const isVertical = this._ctx.getDirection() === "vertical";
7568
- const dropTarget = new Droptarget(chip.element, {
7569
- acceptedTargetZones: isVertical ? ["top"] : ["left"],
7595
+ const dropTargetOptions = {
7596
+ acceptedTargetZones: this._ctx.getDirection() === "vertical" ? ["top"] : ["left"],
7570
7597
  overlayModel: { activationSize: {
7571
7598
  value: 100,
7572
7599
  type: "percentage"
@@ -7577,15 +7604,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
7577
7604
  const data = getPanelData();
7578
7605
  if (this._ctx.accessor.id === (data === null || data === void 0 ? void 0 : data.viewId)) {
7579
7606
  var _this$_ctx$accessor$o3;
7580
- if (((_this$_ctx$accessor$o3 = this._ctx.accessor.options.theme) === null || _this$_ctx$accessor$o3 === void 0 ? void 0 : _this$_ctx$accessor$o3.tabAnimation) === "smooth") return false;
7607
+ if (((_this$_ctx$accessor$o3 = this._ctx.accessor.options.theme) === null || _this$_ctx$accessor$o3 === void 0 ? void 0 : _this$_ctx$accessor$o3.tabAnimation) === "smooth" && !data.tabGroupId) return false;
7581
7608
  return true;
7582
7609
  }
7583
7610
  return this._ctx.group.model.canDisplayOverlay(event, position, "tab");
7584
7611
  }
7585
- });
7586
- disposables.push(dropTarget, dropTarget.onDrop((event) => {
7612
+ };
7613
+ const dropTarget = html5Backend.createDropTarget(chip.element, dropTargetOptions);
7614
+ const pointerDropTarget = pointerBackend.createDropTarget(chip.element, dropTargetOptions);
7615
+ const onDrop = (event) => {
7587
7616
  this._callbacks.onChipDrop(tabGroup, event);
7588
- }));
7617
+ };
7618
+ disposables.push(dropTarget, dropTarget.onDrop(onDrop), pointerDropTarget, pointerDropTarget.onDrop(onDrop));
7589
7619
  const disposable = new CompositeDisposable(...disposables);
7590
7620
  this._chipRenderers.set(tabGroup.id, {
7591
7621
  chip,
@@ -7593,7 +7623,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
7593
7623
  pointerDragSource: dragSources.pointerDragSource,
7594
7624
  dragSourcesDisposable: dragSources.disposable,
7595
7625
  disposable,
7596
- dropTarget
7626
+ dropTarget,
7627
+ pointerDropTarget
7597
7628
  });
7598
7629
  if (tabGroup.collapsed) this._skipNextCollapseAnimation = true;
7599
7630
  }
@@ -7838,7 +7869,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
7838
7869
  * dragover bridge may have installed.
7839
7870
  */
7840
7871
  handlePointerDragEnd(e) {
7841
- if (e && this._animState && this._animState.sourceIndex !== -1 && !this._animState.sourceTabGroupId && this._animState.currentInsertionIndex !== null && this.isPointInsideTabsList(e.clientX, e.clientY)) this.commitPointerReorder(e.pointerEvent);
7872
+ if (e && this._animState && this._animState.sourceIndex !== -1 && this._animState.currentInsertionIndex !== null && this.isPointInsideTabsList(e.clientX, e.clientY)) {
7873
+ const sourceTabGroupId = this._animState.sourceTabGroupId;
7874
+ if (sourceTabGroupId) {
7875
+ const insertionIndex = this._animState.currentInsertionIndex;
7876
+ this._animState = null;
7877
+ this.commitGroupMove(sourceTabGroupId, insertionIndex);
7878
+ } else this.commitPointerReorder(e.pointerEvent);
7879
+ }
7842
7880
  this._pointerInsideTabsList = false;
7843
7881
  this.resetDragAnimation();
7844
7882
  }
@@ -7967,11 +8005,28 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
7967
8005
  if (this._voidContainer && related && (related === this._voidContainer || this._voidContainer.contains(related))) return;
7968
8006
  this.resetTabTransforms();
7969
8007
  if (this._animState.sourceIndex === -1) {
7970
- var _this$group$model$dro2;
7971
- (_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();
8008
+ this.clearHeaderAnchorOverlay();
7972
8009
  this._animState = null;
7973
8010
  } else this._animState.currentInsertionIndex = null;
7974
8011
  }
8012
+ /**
8013
+ * Clear the anchored overlay only when this header is what rendered it.
8014
+ * The container is shared with the group's content drop target, which
8015
+ * renders into it on the same frame the cursor leaves the strip: the
8016
+ * pointer backend calls `handleDragOver` on the new target before the
8017
+ * global `onDragMove` that reaches us (#1612).
8018
+ */
8019
+ clearHeaderAnchorOverlay() {
8020
+ var _container$model;
8021
+ const container = this.group.model.dropTargetContainer;
8022
+ const outline = container === null || container === void 0 ? void 0 : container.renderedOutline;
8023
+ if (outline && ![
8024
+ this._tabsList,
8025
+ this._voidContainer,
8026
+ this._extendedDropZone
8027
+ ].some((scope) => scope === null || scope === void 0 ? void 0 : scope.contains(outline))) return;
8028
+ container === null || container === void 0 || (_container$model = container.model) === null || _container$model === void 0 || _container$model.clear();
8029
+ }
7975
8030
  handleDragOver(event) {
7976
8031
  var _this$accessor$option2;
7977
8032
  if (!this._animState) return;
@@ -8457,6 +8512,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
8457
8512
  commitGroupMove(sourceTabGroupId, insertionIndex) {
8458
8513
  const data = getPanelData();
8459
8514
  this._tabGroupManager.disposeChipDrag(sourceTabGroupId);
8515
+ this._tabGroupManager.clearChipDropOverlays();
8460
8516
  if (this.group.model.getTabGroups().some((tg) => tg.id === sourceTabGroupId)) {
8461
8517
  var _this$accessor$option3;
8462
8518
  if (((_this$accessor$option3 = this.accessor.options.theme) === null || _this$accessor$option3 === void 0 ? void 0 : _this$accessor$option3.tabAnimation) === "smooth") {
@@ -8814,7 +8870,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
8814
8870
  }
8815
8871
  });
8816
8872
  this._reorder = new TabReorderController(this);
8817
- this.addDisposables(this._onOverflowTabsChange, this._observerDisposable, this._pointerActivation, this._onWillShowOverlay, this._onDrop, this._onTabDragStart, this._reorder, PointerDragController.getInstance().onDragEnd((e) => {
8873
+ const tabsListPointerTarget = pointerBackend.createDropTarget(this._tabsList, {
8874
+ acceptedTargetZones: ["center"],
8875
+ canDisplayOverlay: () => false,
8876
+ isHitTestTransparent: () => {
8877
+ const data = getPanelData();
8878
+ if ((data === null || data === void 0 ? void 0 : data.viewId) !== this.accessor.id || data.groupId !== this.group.id) return true;
8879
+ return data.panelId === null && !data.tabGroupId;
8880
+ }
8881
+ });
8882
+ this.addDisposables(tabsListPointerTarget, this._onOverflowTabsChange, this._observerDisposable, this._pointerActivation, this._onWillShowOverlay, this._onDrop, this._onTabDragStart, this._reorder, PointerDragController.getInstance().onDragEnd((e) => {
8818
8883
  this._reorder.handlePointerDragEnd(e);
8819
8884
  }), PointerDragController.getInstance().onDragMove((e) => {
8820
8885
  this._reorder.handlePointerDragMove(e.clientX, e.clientY);
@@ -9290,6 +9355,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
9290
9355
  * (when the source tab is currently to the left of the target slot, its
9291
9356
  * removal shifts the insertion index down by one). Always clears
9292
9357
  * `targetTabGroupId` so the dropped tab lands outside the group.
9358
+ *
9359
+ * A chip dropped on a chip is a group move: the panel path would route it
9360
+ * through the cross-group machinery, which rebuilds the tab group under a
9361
+ * new id.
9293
9362
  */
9294
9363
  _handleChipDrop(tabGroup, event) {
9295
9364
  const firstPanelId = tabGroup.panelIds[0];
@@ -9297,6 +9366,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
9297
9366
  const insertionIndex = this._tabs.findIndex((x) => x.value.panel.id === firstPanelId);
9298
9367
  if (insertionIndex === -1) return;
9299
9368
  const data = getPanelData();
9369
+ if (data === null || data === void 0 ? void 0 : data.tabGroupId) {
9370
+ var _animState$currentIns2;
9371
+ const animState = this._animState;
9372
+ this._animState = null;
9373
+ this._pendingCollapse = false;
9374
+ this._commitGroupMove(data.tabGroupId, (_animState$currentIns2 = animState === null || animState === void 0 ? void 0 : animState.currentInsertionIndex) !== null && _animState$currentIns2 !== void 0 ? _animState$currentIns2 : insertionIndex);
9375
+ return;
9376
+ }
9300
9377
  const sourceIndex = (data === null || data === void 0 ? void 0 : data.groupId) === this.group.id && (data === null || data === void 0 ? void 0 : data.panelId) ? this._tabs.findIndex((x) => x.value.panel.id === data.panelId) : -1;
9301
9378
  const adjustedIndex = insertionIndex - (sourceIndex !== -1 && sourceIndex < insertionIndex ? 1 : 0);
9302
9379
  this._onDrop.fire({
@@ -12401,7 +12478,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
12401
12478
  "AdvancedOverflow",
12402
12479
  "AutoEdgeGroup",
12403
12480
  "AutoHideEdgeGroup",
12404
- "ContextMenu",
12405
12481
  "DndCompass",
12406
12482
  "KeyboardDocking",
12407
12483
  "KeyboardNavigation",
@@ -12483,8 +12559,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
12483
12559
  * case: calling `undo()` having never set the option at all.
12484
12560
  *
12485
12561
  * Interaction handlers are queries in this sense too: a right-click reaching an
12486
- * absent ContextMenu module means the app never asked for one, so it stays
12487
- * silent (`?.`) and the browser's own menu shows. Options are where intent is
12562
+ * absent module means the app never asked for that feature, so it stays silent
12563
+ * (`?.`) and the browser's own behaviour applies. Options are where intent is
12488
12564
  * declared; see `optionsModules.ts`.
12489
12565
  */
12490
12566
  function assertModule(service, moduleName, context) {
@@ -12564,10 +12640,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
12564
12640
  *
12565
12641
  * This is the "declared intent" diagnostic. It fires when the user asks for a
12566
12642
  * feature via options, at construction and on every `updateOptions`. It
12567
- * deliberately does *not* fire on user interaction: right-clicking without the
12568
- * ContextMenu module stays silent (the browser's own menu shows), because the
12569
- * `?.` service-slot call sites can't tell a missing module from a feature the
12570
- * app never wanted.
12643
+ * deliberately does *not* fire on user interaction: an interaction reaching an
12644
+ * absent module stays silent, because the `?.` service-slot call sites can't
12645
+ * tell a missing module from a feature the app never wanted.
12571
12646
  *
12572
12647
  * Rules are a flat list rather than a `Record<keyof DockviewOptions, ...>`
12573
12648
  * because dockview's options are nested and value-gated: `overflow.mode:
@@ -12663,18 +12738,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
12663
12738
  moduleName: "AutoEdgeGroup",
12664
12739
  when: (o) => isAnyEdgeGroupEnabled(o.dockToEdgeGroups)
12665
12740
  },
12666
- {
12667
- optionKey: "getTabContextMenuItems",
12668
- reason: "getTabContextMenuItems",
12669
- moduleName: "ContextMenu",
12670
- when: (o) => o.getTabContextMenuItems != null
12671
- },
12672
- {
12673
- optionKey: "getTabGroupChipContextMenuItems",
12674
- reason: "getTabGroupChipContextMenuItems",
12675
- moduleName: "ContextMenu",
12676
- when: (o) => o.getTabGroupChipContextMenuItems != null
12677
- },
12678
12741
  {
12679
12742
  optionKey: "dndCompass",
12680
12743
  reason: "dndCompass",
@@ -13575,6 +13638,270 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13575
13638
  }
13576
13639
  });
13577
13640
 
13641
+ //#endregion
13642
+ //#region src/dockview/contextMenuService.ts
13643
+ function popoverZIndexFor(target, group) {
13644
+ var _group$api, _group$api$isPeeking;
13645
+ 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)";
13646
+ if (!(target instanceof HTMLElement)) return;
13647
+ const relativeParent = findRelativeZIndexParent(target);
13648
+ return (relativeParent === null || relativeParent === void 0 ? void 0 : relativeParent.style.zIndex) ? `calc(${relativeParent.style.zIndex} * 2)` : void 0;
13649
+ }
13650
+ let _nextId = 0;
13651
+ const nextContextMenuItemId = () => `dv-ctx-menu-item-${_nextId++}`;
13652
+ function isItemConfig(item) {
13653
+ return typeof item === "object";
13654
+ }
13655
+ function buildItem(label, close, action, disabled) {
13656
+ const el = document.createElement("div");
13657
+ el.className = "dv-context-menu-item";
13658
+ el.setAttribute("role", "menuitem");
13659
+ if (disabled) {
13660
+ el.classList.add("dv-context-menu-item--disabled");
13661
+ el.setAttribute("aria-disabled", "true");
13662
+ }
13663
+ el.textContent = label;
13664
+ if (!disabled) el.addEventListener("click", () => {
13665
+ action();
13666
+ close();
13667
+ });
13668
+ return el;
13669
+ }
13670
+ function buildSeparator() {
13671
+ const el = document.createElement("div");
13672
+ el.className = "dv-context-menu-separator";
13673
+ el.setAttribute("role", "separator");
13674
+ return el;
13675
+ }
13676
+ function isCoarsePrimaryInput$1() {
13677
+ if (globalThis.window === void 0 || !globalThis.matchMedia) return false;
13678
+ const coarse = globalThis.matchMedia("(pointer: coarse)").matches;
13679
+ const fine = globalThis.matchMedia("(pointer: fine)").matches;
13680
+ return coarse && !fine;
13681
+ }
13682
+ function buildRenameInput(tabGroup) {
13683
+ const wrapper = document.createElement("div");
13684
+ wrapper.className = "dv-context-menu-rename";
13685
+ const input = document.createElement("input");
13686
+ input.className = "dv-context-menu-rename-input";
13687
+ input.type = "text";
13688
+ input.placeholder = "Name This Group";
13689
+ input.value = tabGroup.label;
13690
+ input.addEventListener("input", () => {
13691
+ tabGroup.setLabel(input.value);
13692
+ });
13693
+ input.addEventListener("keydown", (e) => {
13694
+ if (e.key !== "Escape" && e.key !== "Enter") e.stopPropagation();
13695
+ });
13696
+ input.addEventListener("click", (e) => {
13697
+ e.stopPropagation();
13698
+ });
13699
+ wrapper.appendChild(input);
13700
+ if (!isCoarsePrimaryInput$1()) requestAnimationFrame(() => {
13701
+ input.focus();
13702
+ input.select();
13703
+ });
13704
+ return wrapper;
13705
+ }
13706
+ function buildColorPicker(tabGroup, palette) {
13707
+ const wrapper = document.createElement("div");
13708
+ wrapper.className = "dv-context-menu-color-picker";
13709
+ if (!palette.enabled) return wrapper;
13710
+ for (const entry of palette.entries()) {
13711
+ const swatch = document.createElement("div");
13712
+ swatch.className = "dv-context-menu-color-swatch";
13713
+ swatch.style.setProperty("--dv-tab-group-color", entry.value);
13714
+ if (entry.label) swatch.title = entry.label;
13715
+ if (tabGroup.color === entry.id) swatch.classList.add("dv-context-menu-color-swatch--selected");
13716
+ swatch.addEventListener("click", () => {
13717
+ tabGroup.setColor(entry.id);
13718
+ });
13719
+ wrapper.appendChild(swatch);
13720
+ }
13721
+ return wrapper;
13722
+ }
13723
+ var ContextMenuController = class {
13724
+ constructor(accessor) {
13725
+ this.accessor = accessor;
13726
+ }
13727
+ /**
13728
+ * A single maximize/restore toggle whose label and behaviour track the
13729
+ * group's live state: it reads *Restore* + calls `exitMaximized` when the
13730
+ * group is maximized, otherwise *Maximize* + `maximize`. Only grid groups
13731
+ * can be maximized, so the item is disabled for floating / popout panels
13732
+ * that are not already maximized.
13733
+ */
13734
+ buildMaximizeItem(panel, close) {
13735
+ const isMaximized = panel.api.isMaximized();
13736
+ return buildItem(isMaximized ? "Restore" : "Maximize", close, isMaximized ? () => panel.api.exitMaximized() : () => panel.api.maximize(), !isMaximized && panel.api.location.type !== "grid");
13737
+ }
13738
+ /**
13739
+ * A single collapse/expand toggle whose label tracks the tab group's live
13740
+ * state: *Expand* when the group is already collapsed, otherwise *Collapse*.
13741
+ */
13742
+ buildCollapseItem(tabGroup, close) {
13743
+ return buildItem(tabGroup.collapsed ? "Expand" : "Collapse", close, () => tabGroup.toggle());
13744
+ }
13745
+ /**
13746
+ * Whether to auto-inject the built-in Pin/Unpin item at the top of the tab
13747
+ * menu. True only when the PinnedTabs module is registered, pinning is
13748
+ * enabled, and the app has not opted out via `pinnedTabs.contextMenuItem:
13749
+ * false` (the item is on by default). This keeps pinning reachable from the
13750
+ * menu without the app having to return `'pin'` from
13751
+ * `getTabContextMenuItems` itself.
13752
+ */
13753
+ _shouldInjectPin() {
13754
+ const pinnedTabs = this.accessor.options.pinnedTabs;
13755
+ return !!this.accessor.pinnedTabsService && !!(pinnedTabs === null || pinnedTabs === void 0 ? void 0 : pinnedTabs.enabled) && pinnedTabs.contextMenuItem !== false;
13756
+ }
13757
+ /**
13758
+ * The tab menu items: the app's own items (if any) with the built-in
13759
+ * `'pin'` item prepended when {@link _shouldInjectPin} applies, so the app
13760
+ * keeps full control of its list, and pinning is added without disturbing
13761
+ * it. Reuses the existing `'pin'` token rendering below.
13762
+ */
13763
+ _resolveTabItems(panel, group, event) {
13764
+ var _this$accessor$option, _this$accessor$option2, _this$accessor$option3;
13765
+ 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, {
13766
+ panel,
13767
+ group,
13768
+ api: this.accessor.api,
13769
+ event
13770
+ })) !== null && _this$accessor$option !== void 0 ? _this$accessor$option : [];
13771
+ return this._shouldInjectPin() ? ["pin", ...appItems] : appItems;
13772
+ }
13773
+ /**
13774
+ * Render a custom `component` menu item and append it to `menuEl`. Builds
13775
+ * the framework renderer via the host's `createContextMenuItemComponent`
13776
+ * factory and initialises it. Shared by the tab menu and the chip menu,
13777
+ * which differ only in `identity`: the tab menu passes the `panel`, the chip
13778
+ * menu passes the `tabGroup`. No-op when no renderer could be created (no
13779
+ * factory configured, or the factory declined the component).
13780
+ */
13781
+ appendComponentItem(menuEl, item, identity, group, close) {
13782
+ var _this$accessor$option4, _this$accessor$option5;
13783
+ 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, {
13784
+ id: nextContextMenuItemId(),
13785
+ component: item.component
13786
+ });
13787
+ if (!renderer) return;
13788
+ renderer.init(_objectSpread2(_objectSpread2({}, identity), {}, {
13789
+ group,
13790
+ api: this.accessor.api,
13791
+ close,
13792
+ componentProps: item.componentProps
13793
+ }));
13794
+ menuEl.appendChild(renderer.element);
13795
+ }
13796
+ /**
13797
+ * The element for one built-in tab item, or `undefined` for a token this
13798
+ * version doesn't know (an app on a newer typings version, or plain JS):
13799
+ * an unrecognised token renders nothing rather than throwing.
13800
+ */
13801
+ buildBuiltInTabItem(item, panel, group, close) {
13802
+ switch (item) {
13803
+ case "separator": return buildSeparator();
13804
+ case "close": return buildItem("Close", close, () => panel.api.close());
13805
+ case "closeOthers": return buildItem("Close Others", close, () => {
13806
+ group.panels.filter((p) => p !== panel).forEach((p) => p.api.close());
13807
+ });
13808
+ case "closeAll": return buildItem("Close All", close, () => {
13809
+ [...group.panels].forEach((p) => p.api.close());
13810
+ });
13811
+ case "closeLeft": {
13812
+ const index = group.panels.indexOf(panel);
13813
+ return buildItem("Close to the Left", close, () => {
13814
+ group.panels.filter((_, i) => i < index).forEach((p) => p.api.close());
13815
+ }, index <= 0);
13816
+ }
13817
+ case "closeRight": {
13818
+ const index = group.panels.indexOf(panel);
13819
+ return buildItem("Close to the Right", close, () => {
13820
+ group.panels.filter((_, i) => i > index).forEach((p) => p.api.close());
13821
+ }, index === -1 || index >= group.panels.length - 1);
13822
+ }
13823
+ case "maximize": return this.buildMaximizeItem(panel, close);
13824
+ case "float": return buildItem("Float", close, () => this.accessor.api.addFloatingGroup(panel), panel.api.location.type === "floating");
13825
+ case "popout": return buildItem("Open in New Window", close, () => {
13826
+ this.accessor.api.addPopoutGroup(panel);
13827
+ }, panel.api.location.type === "popout");
13828
+ case "pin": return buildItem(panel.api.isPinned ? "Unpin tab" : "Pin tab", close, () => panel.api.setPinned(!panel.api.isPinned));
13829
+ default: return;
13830
+ }
13831
+ }
13832
+ /**
13833
+ * Append one app-supplied item. A raw `element` is used as-is, a
13834
+ * `component` goes through the framework renderer, and a `label` builds the
13835
+ * default row; an item carrying none of the three renders nothing. Shared
13836
+ * by both menus, which differ only in `identity`.
13837
+ */
13838
+ appendConfigItem(menuEl, item, identity, group, close) {
13839
+ if (item.element) menuEl.appendChild(item.element);
13840
+ else if (item.component) this.appendComponentItem(menuEl, item, identity, group, close);
13841
+ else if (item.label) menuEl.appendChild(buildItem(item.label, close, () => {
13842
+ var _item$action;
13843
+ return (_item$action = item.action) === null || _item$action === void 0 ? void 0 : _item$action.call(item);
13844
+ }, item.disabled));
13845
+ }
13846
+ show(panel, group, event) {
13847
+ const items = this._resolveTabItems(panel, group, event);
13848
+ if (items.length === 0) return;
13849
+ event.preventDefault();
13850
+ const popupService = this.accessor.getPopupServiceForGroup(group);
13851
+ const close = () => popupService.close();
13852
+ const menuEl = document.createElement("div");
13853
+ menuEl.className = "dv-context-menu";
13854
+ menuEl.setAttribute("role", "menu");
13855
+ for (const item of items) {
13856
+ if (isItemConfig(item)) {
13857
+ this.appendConfigItem(menuEl, item, { panel }, group, close);
13858
+ continue;
13859
+ }
13860
+ const el = this.buildBuiltInTabItem(item, panel, group, close);
13861
+ if (el) menuEl.appendChild(el);
13862
+ }
13863
+ popupService.openPopover(menuEl, {
13864
+ x: event.clientX,
13865
+ y: event.clientY,
13866
+ zIndex: popoverZIndexFor(event.target, group)
13867
+ });
13868
+ }
13869
+ showForChip(tabGroup, group, event) {
13870
+ if (!this.accessor.options.getTabGroupChipContextMenuItems) return;
13871
+ const items = this.accessor.options.getTabGroupChipContextMenuItems({
13872
+ tabGroup,
13873
+ group,
13874
+ api: this.accessor.api,
13875
+ event
13876
+ });
13877
+ if (items.length === 0) return;
13878
+ event.preventDefault();
13879
+ const popupService = this.accessor.getPopupServiceForGroup(group);
13880
+ const close = () => popupService.close();
13881
+ const menuEl = document.createElement("div");
13882
+ menuEl.className = "dv-context-menu";
13883
+ menuEl.setAttribute("role", "menu");
13884
+ for (const item of items) if (item === "separator") menuEl.appendChild(buildSeparator());
13885
+ else if (item === "rename") menuEl.appendChild(buildRenameInput(tabGroup));
13886
+ else if (item === "colorPicker") menuEl.appendChild(buildColorPicker(tabGroup, this.accessor.tabGroupColorPalette));
13887
+ else if (item === "collapse") menuEl.appendChild(this.buildCollapseItem(tabGroup, close));
13888
+ else if (item === "close") menuEl.appendChild(buildItem("Close All", close, () => {
13889
+ group.panels.filter((p) => tabGroup.containsPanel(p.id)).forEach((p) => p.api.close());
13890
+ }));
13891
+ else if (isItemConfig(item)) this.appendConfigItem(menuEl, item, { tabGroup }, group, close);
13892
+ popupService.openPopover(menuEl, {
13893
+ x: event.clientX,
13894
+ y: event.clientY,
13895
+ zIndex: popoverZIndexFor(event.target, group)
13896
+ });
13897
+ }
13898
+ };
13899
+ const ContextMenuModule = defineModule({
13900
+ name: "ContextMenu",
13901
+ serviceKey: "contextMenuService",
13902
+ create: (host) => new ContextMenuController(host)
13903
+ });
13904
+
13578
13905
  //#endregion
13579
13906
  //#region src/dockview/allModules.ts
13580
13907
  /**
@@ -13592,7 +13919,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13592
13919
  HeaderActionsModule,
13593
13920
  LiveRegionModule,
13594
13921
  AdvancedDnDModule,
13595
- TabGroupChipsModule
13922
+ TabGroupChipsModule,
13923
+ ContextMenuModule
13596
13924
  ];
13597
13925
 
13598
13926
  //#endregion
@@ -14284,6 +14612,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14284
14612
  //#endregion
14285
14613
  //#region src/dnd/dropTargetAnchorContainer.ts
14286
14614
  var DropTargetAnchorContainer = class extends CompositeDisposable {
14615
+ /**
14616
+ * The element the live overlay was rendered for, `undefined` when nothing
14617
+ * is showing. The container is shared by every drop target, so a caller
14618
+ * tearing down only its own overlay must check this before `clear()`.
14619
+ */
14620
+ get renderedOutline() {
14621
+ return this._model ? this._outline : void 0;
14622
+ }
14287
14623
  get disabled() {
14288
14624
  return this._disabled;
14289
14625
  }
@@ -14588,6 +14924,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14588
14924
  const index = position === "top" ? this._topIndex : this._bottomIndex;
14589
14925
  if (index !== void 0) this._splitview.resizeView(index, size);
14590
14926
  }
14927
+ /** The inner splitview's primary-axis (height) extent; zero until laid out. */
14928
+ get axisSize() {
14929
+ return this._splitview.size;
14930
+ }
14591
14931
  updateMargin(gap) {
14592
14932
  this._splitview.margin = gap;
14593
14933
  }
@@ -14600,6 +14940,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14600
14940
  constructor(container, dockviewElement, layoutGrid, gap = 0, defaultCollapsedSize = 35) {
14601
14941
  this._disposables = new CompositeDisposable();
14602
14942
  this._viewConfigs = /* @__PURE__ */ new Map();
14943
+ this._pendingSizes = /* @__PURE__ */ new Map();
14603
14944
  this._currentWidth = 0;
14604
14945
  this._currentHeight = 0;
14605
14946
  this._gap = gap;
@@ -14690,11 +15031,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14690
15031
  break;
14691
15032
  }
14692
15033
  this._disposables.addDisposables(view);
15034
+ if (!view.isCollapsed && !this._canResize(position)) this._pendingSizes.set(position, initialSize);
14693
15035
  this.updateTheme(this._gap, this._defaultCollapsedSize);
14694
15036
  return view;
14695
15037
  }
14696
15038
  layout(width, height) {
14697
15039
  this._outerSplitview.layout(width, height);
15040
+ this._flushPendingSizes();
14698
15041
  }
14699
15042
  /**
14700
15043
  * Called when the active theme changes. Updates splitview margins and
@@ -14758,6 +15101,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14758
15101
  this._disposables.removeDisposable(view);
14759
15102
  view.dispose();
14760
15103
  this._viewConfigs.delete(position);
15104
+ this._pendingSizes.delete(position);
14761
15105
  this.updateTheme(this._gap, this._defaultCollapsedSize);
14762
15106
  }
14763
15107
  hasEdgeGroup(position) {
@@ -14781,6 +15125,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14781
15125
  this._middleColumn.setViewVisible(position, visible);
14782
15126
  break;
14783
15127
  }
15128
+ if (visible) this._flushPendingSizes();
14784
15129
  }
14785
15130
  isEdgeGroupVisible(position) {
14786
15131
  switch (position) {
@@ -14798,20 +15143,63 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14798
15143
  const view = this._getView(position);
14799
15144
  if (!view) return;
14800
15145
  view.setCollapsed(collapsed);
14801
- const targetSize = collapsed ? view.collapsedSize : view.lastExpandedSize;
15146
+ if (collapsed) {
15147
+ this._pendingSizes.delete(position);
15148
+ this._resizeView(position, view.collapsedSize);
15149
+ } else this.resizeEdgeGroup(position, view.lastExpandedSize);
15150
+ }
15151
+ /**
15152
+ * Resize the edge group at `position` along its primary axis (width for
15153
+ * `left`/`right`, height for `top`/`bottom`), clamped by the group's
15154
+ * constraints and the space available. Where `groupApi.setSize` lands.
15155
+ *
15156
+ * The size becomes the group's expanded size, so a collapsed group keeps
15157
+ * its strip and takes it on expand, and it survives a `toJSON` round-trip.
15158
+ */
15159
+ resizeEdgeGroup(position, size) {
15160
+ const view = this._getView(position);
15161
+ if (!view || !Number.isFinite(size)) return;
15162
+ const target = Math.round(size);
15163
+ if (target <= 0) return;
15164
+ view.restoreExpandedSize(target);
15165
+ if (view.isCollapsed) {
15166
+ this._pendingSizes.delete(position);
15167
+ return;
15168
+ }
15169
+ if (this._canResize(position)) {
15170
+ this._pendingSizes.delete(position);
15171
+ this._resizeView(position, target);
15172
+ } else this._pendingSizes.set(position, target);
15173
+ }
15174
+ /** A resize lands only on a visible view (a hidden one is pinned to zero)
15175
+ * whose splitview has extent to distribute. */
15176
+ _canResize(position) {
15177
+ if (!this.isEdgeGroupVisible(position)) return false;
15178
+ return (position === "left" || position === "right" ? this._outerSplitview.size : this._middleColumn.axisSize) > 0;
15179
+ }
15180
+ _resizeView(position, size) {
14802
15181
  switch (position) {
14803
15182
  case "left":
14804
- if (this._leftIndex !== void 0) this._outerSplitview.resizeView(this._leftIndex, targetSize);
15183
+ if (this._leftIndex !== void 0) this._outerSplitview.resizeView(this._leftIndex, size);
14805
15184
  break;
14806
15185
  case "right":
14807
- if (this._rightIndex !== void 0) this._outerSplitview.resizeView(this._rightIndex, targetSize);
15186
+ if (this._rightIndex !== void 0) this._outerSplitview.resizeView(this._rightIndex, size);
14808
15187
  break;
14809
15188
  case "top":
14810
15189
  case "bottom":
14811
- this._middleColumn.resizeView(position, targetSize);
15190
+ this._middleColumn.resizeView(position, size);
14812
15191
  break;
14813
15192
  }
14814
15193
  }
15194
+ _flushPendingSizes() {
15195
+ if (this._pendingSizes.size === 0) return;
15196
+ for (const [position, size] of this._pendingSizes) {
15197
+ const view = this._getView(position);
15198
+ if (!view || view.isCollapsed || !this._canResize(position)) continue;
15199
+ this._pendingSizes.delete(position);
15200
+ this._resizeView(position, size);
15201
+ }
15202
+ }
14815
15203
  isEdgeGroupCollapsed(position) {
14816
15204
  var _this$_getView$isColl, _this$_getView;
14817
15205
  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;
@@ -14837,15 +15225,17 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14837
15225
  maximumSize: Number.isFinite(view.configuredMaximumSize) ? view.configuredMaximumSize : void 0,
14838
15226
  collapsedSize: view.configuredCollapsedSize
14839
15227
  });
14840
- const expandedSize = (view, isVisible, liveSize, cachedVisibleSize) => {
15228
+ const expandedSize = (view, position, isVisible, liveSize, cachedVisibleSize) => {
14841
15229
  if (view.isCollapsed) return view.lastExpandedSize;
15230
+ const pending = this._pendingSizes.get(position);
15231
+ if (pending !== void 0) return pending;
14842
15232
  if (!isVisible) return cachedVisibleSize !== null && cachedVisibleSize !== void 0 ? cachedVisibleSize : view.lastExpandedSize;
14843
15233
  return liveSize;
14844
15234
  };
14845
15235
  if (this._leftView && this._leftIndex !== void 0) {
14846
15236
  const visible = this._outerSplitview.isViewVisible(this._leftIndex);
14847
15237
  edgeGroups.left = _objectSpread2({
14848
- size: expandedSize(this._leftView, visible, this._outerSplitview.getViewSize(this._leftIndex), this._outerSplitview.getViewCachedVisibleSize(this._leftIndex)),
15238
+ size: expandedSize(this._leftView, "left", visible, this._outerSplitview.getViewSize(this._leftIndex), this._outerSplitview.getViewCachedVisibleSize(this._leftIndex)),
14849
15239
  visible,
14850
15240
  collapsed: this._leftView.isCollapsed || void 0
14851
15241
  }, constraints(this._leftView));
@@ -14853,7 +15243,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14853
15243
  if (this._rightView && this._rightIndex !== void 0) {
14854
15244
  const visible = this._outerSplitview.isViewVisible(this._rightIndex);
14855
15245
  edgeGroups.right = _objectSpread2({
14856
- size: expandedSize(this._rightView, visible, this._outerSplitview.getViewSize(this._rightIndex), this._outerSplitview.getViewCachedVisibleSize(this._rightIndex)),
15246
+ size: expandedSize(this._rightView, "right", visible, this._outerSplitview.getViewSize(this._rightIndex), this._outerSplitview.getViewCachedVisibleSize(this._rightIndex)),
14857
15247
  visible,
14858
15248
  collapsed: this._rightView.isCollapsed || void 0
14859
15249
  }, constraints(this._rightView));
@@ -14861,7 +15251,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14861
15251
  if (this._topView) {
14862
15252
  const visible = this._middleColumn.isViewVisible("top");
14863
15253
  edgeGroups.top = _objectSpread2({
14864
- size: expandedSize(this._topView, visible, this._middleColumn.getViewSize("top"), this._middleColumn.getViewCachedVisibleSize("top")),
15254
+ size: expandedSize(this._topView, "top", visible, this._middleColumn.getViewSize("top"), this._middleColumn.getViewCachedVisibleSize("top")),
14865
15255
  visible,
14866
15256
  collapsed: this._topView.isCollapsed || void 0
14867
15257
  }, constraints(this._topView));
@@ -14869,7 +15259,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14869
15259
  if (this._bottomView) {
14870
15260
  const visible = this._middleColumn.isViewVisible("bottom");
14871
15261
  edgeGroups.bottom = _objectSpread2({
14872
- size: expandedSize(this._bottomView, visible, this._middleColumn.getViewSize("bottom"), this._middleColumn.getViewCachedVisibleSize("bottom")),
15262
+ size: expandedSize(this._bottomView, "bottom", visible, this._middleColumn.getViewSize("bottom"), this._middleColumn.getViewCachedVisibleSize("bottom")),
14873
15263
  visible,
14874
15264
  collapsed: this._bottomView.isCollapsed || void 0
14875
15265
  }, constraints(this._bottomView));
@@ -14877,33 +15267,23 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
14877
15267
  return edgeGroups;
14878
15268
  }
14879
15269
  fromJSON(data) {
14880
- if (data.left && this._leftIndex !== void 0) {
14881
- var _this$_leftView2, _this$_leftView3, _data$left$collapsed, _this$_leftView$colla, _this$_leftView4;
14882
- (_this$_leftView2 = this._leftView) === null || _this$_leftView2 === void 0 || _this$_leftView2.restoreExpandedSize(data.left.size);
14883
- (_this$_leftView3 = this._leftView) === null || _this$_leftView3 === void 0 || _this$_leftView3.setCollapsed((_data$left$collapsed = data.left.collapsed) !== null && _data$left$collapsed !== void 0 ? _data$left$collapsed : false);
14884
- this._outerSplitview.resizeView(this._leftIndex, data.left.collapsed ? (_this$_leftView$colla = (_this$_leftView4 = this._leftView) === null || _this$_leftView4 === void 0 ? void 0 : _this$_leftView4.collapsedSize) !== null && _this$_leftView$colla !== void 0 ? _this$_leftView$colla : data.left.size : data.left.size);
14885
- if (!data.left.visible) this._outerSplitview.setViewVisible(this._leftIndex, false);
14886
- }
14887
- if (data.right && this._rightIndex !== void 0) {
14888
- var _this$_rightView2, _this$_rightView3, _data$right$collapsed, _this$_rightView$coll, _this$_rightView4;
14889
- (_this$_rightView2 = this._rightView) === null || _this$_rightView2 === void 0 || _this$_rightView2.restoreExpandedSize(data.right.size);
14890
- (_this$_rightView3 = this._rightView) === null || _this$_rightView3 === void 0 || _this$_rightView3.setCollapsed((_data$right$collapsed = data.right.collapsed) !== null && _data$right$collapsed !== void 0 ? _data$right$collapsed : false);
14891
- this._outerSplitview.resizeView(this._rightIndex, data.right.collapsed ? (_this$_rightView$coll = (_this$_rightView4 = this._rightView) === null || _this$_rightView4 === void 0 ? void 0 : _this$_rightView4.collapsedSize) !== null && _this$_rightView$coll !== void 0 ? _this$_rightView$coll : data.right.size : data.right.size);
14892
- if (!data.right.visible) this._outerSplitview.setViewVisible(this._rightIndex, false);
14893
- }
14894
- if (data.top) {
14895
- var _this$_topView2, _this$_topView3, _data$top$collapsed, _this$_topView$collap, _this$_topView4;
14896
- (_this$_topView2 = this._topView) === null || _this$_topView2 === void 0 || _this$_topView2.restoreExpandedSize(data.top.size);
14897
- (_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);
14898
- 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);
14899
- if (!data.top.visible) this._middleColumn.setViewVisible("top", false);
14900
- }
14901
- if (data.bottom) {
14902
- var _this$_bottomView2, _this$_bottomView3, _data$bottom$collapse, _this$_bottomView$col, _this$_bottomView4;
14903
- (_this$_bottomView2 = this._bottomView) === null || _this$_bottomView2 === void 0 || _this$_bottomView2.restoreExpandedSize(data.bottom.size);
14904
- (_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);
14905
- 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);
14906
- if (!data.bottom.visible) this._middleColumn.setViewVisible("bottom", false);
15270
+ for (const position of [
15271
+ "left",
15272
+ "right",
15273
+ "top",
15274
+ "bottom"
15275
+ ]) {
15276
+ var _state$collapsed;
15277
+ const state = data[position];
15278
+ const view = this._getView(position);
15279
+ if (!state || !view) continue;
15280
+ view.restoreExpandedSize(state.size);
15281
+ view.setCollapsed((_state$collapsed = state.collapsed) !== null && _state$collapsed !== void 0 ? _state$collapsed : false);
15282
+ if (state.collapsed) {
15283
+ this._pendingSizes.delete(position);
15284
+ this._resizeView(position, view.collapsedSize);
15285
+ } else this.resizeEdgeGroup(position, state.size);
15286
+ this.setEdgeGroupVisible(position, !!state.visible);
14907
15287
  }
14908
15288
  }
14909
15289
  dispose() {
@@ -16071,10 +16451,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16071
16451
  group = this.createGroup();
16072
16452
  this._onDidAddGroup.fire(group);
16073
16453
  this.movingLock(() => this.removePanel(item, {
16074
- removeEmptyGroup: true,
16454
+ removeEmptyGroup: false,
16075
16455
  skipDispose: true,
16076
16456
  skipSetActiveGroup: true
16077
16457
  }));
16458
+ this.removeGroupIfEmpty(sourceGroup);
16078
16459
  this.movingLock(() => group.model.openPanel(item, { skipSetGroupActive: true }));
16079
16460
  movedPanels = [{
16080
16461
  panel: item,
@@ -16145,6 +16526,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16145
16526
  });
16146
16527
  for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
16147
16528
  }
16529
+ removeGroupIfEmpty(group) {
16530
+ if (group.model.size === 0) this.doRemoveGroup(group, { skipActive: true });
16531
+ }
16148
16532
  /**
16149
16533
  * Build an empty gridview configured to match the main grid's styling, for
16150
16534
  * hosting a nested layout inside a floating or popout window.
@@ -16288,6 +16672,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16288
16672
  position
16289
16673
  };
16290
16674
  group.model.headerPosition = position;
16675
+ const resizeDisposable = group.onDidChange((event) => {
16676
+ var _this$_shellManager3;
16677
+ if (!event) return;
16678
+ const size = position === "left" || position === "right" ? event.width : event.height;
16679
+ if (typeof size !== "number") return;
16680
+ (_this$_shellManager3 = this._shellManager) === null || _this$_shellManager3 === void 0 || _this$_shellManager3.resizeEdgeGroup(position, size);
16681
+ });
16291
16682
  const autoCollapseDisposable = group.model.onDidRemovePanel(() => {
16292
16683
  if (!group.model.isEmpty) return;
16293
16684
  if (service.isAutoReveal(group)) queueMicrotask(() => {
@@ -16296,7 +16687,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16296
16687
  });
16297
16688
  else this.setEdgeGroupCollapsed(group, true);
16298
16689
  });
16299
- service.add(position, group, autoCollapseDisposable);
16690
+ service.add(position, group, new CompositeDisposable(autoCollapseDisposable, resizeDisposable));
16300
16691
  if (options.autoHide !== void 0) service.setAutoHide(group, options.autoHide);
16301
16692
  if (options.autoReveal !== void 0) service.setAutoReveal(group, options.autoReveal);
16302
16693
  this._onDidAddGroup.fire(group);
@@ -16391,8 +16782,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16391
16782
  }
16392
16783
  /** The size an edge group expands to (pre-collapse); sizes the peek. */
16393
16784
  getEdgeGroupExpandedSize(position) {
16394
- var _this$_shellManager$g, _this$_shellManager3;
16395
- return (_this$_shellManager$g = (_this$_shellManager3 = this._shellManager) === null || _this$_shellManager3 === void 0 ? void 0 : _this$_shellManager3.getEdgeGroupExpandedSize(position)) !== null && _this$_shellManager$g !== void 0 ? _this$_shellManager$g : 0;
16785
+ var _this$_shellManager$g, _this$_shellManager4;
16786
+ 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;
16396
16787
  }
16397
16788
  /** Reposition a single `renderer:'always'` panel's overlay over its
16398
16789
  * reference container, optionally forcing it visible (the auto-hide peek
@@ -17553,7 +17944,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17553
17944
  }));
17554
17945
  this.doRemoveGroup(sourceGroup, { skipActive: true });
17555
17946
  const updatedTargetLocation = getRelativeLocation(destinationGridview.orientation, getGridLocation(destinationGroup.element), destinationTarget);
17556
- const newGroup = this.createGroupAtLocation(updatedTargetLocation, void 0, void 0, destinationGridview);
17947
+ const newGroup = this.createGroupAtLocation(updatedTargetLocation, this.dropSizing(getGridLocation(destinationGroup.element)), void 0, destinationGridview);
17557
17948
  this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetActive: true }));
17558
17949
  this.doSetGroupAndPanelActive(newGroup);
17559
17950
  this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
@@ -17570,7 +17961,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17570
17961
  skipSetActiveGroup: true
17571
17962
  }));
17572
17963
  if (!removedPanel) throw new Error(`dockview: No panel with id ${sourceItemId}`);
17573
- const newGroup = this.createGroupAtLocation(targetLocation, void 0, void 0, destinationGridview);
17964
+ const newGroup = this.createGroupAtLocation(targetLocation, this.dropSizing(referenceLocation), void 0, destinationGridview);
17574
17965
  this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetGroupActive: true }));
17575
17966
  this.doSetGroupAndPanelActive(newGroup);
17576
17967
  this.fireDidMovePanel(removedPanel, sourceGroup);
@@ -17582,7 +17973,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17582
17973
  }));
17583
17974
  const updatedReferenceLocation = getGridLocation(destinationGroup.element);
17584
17975
  const location = getRelativeLocation(destinationGridview.orientation, updatedReferenceLocation, destinationTarget);
17585
- this.movingLock(() => this.doAddGroup(targetGroup, location, void 0, destinationGridview));
17976
+ this.movingLock(() => this.doAddGroup(targetGroup, location, this.dropSizing(updatedReferenceLocation), destinationGridview));
17586
17977
  this.setGroupLocationForRoot(targetGroup, destinationGridview);
17587
17978
  this.doSetGroupAndPanelActive(targetGroup);
17588
17979
  this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
@@ -17597,7 +17988,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17597
17988
  }));
17598
17989
  if (!removedPanel) throw new Error(`dockview: No panel with id ${sourceItemId}`);
17599
17990
  const dropLocation = getRelativeLocation(destinationGridview.orientation, referenceLocation, destinationTarget);
17600
- const group = this.createGroupAtLocation(dropLocation, void 0, void 0, destinationGridview);
17991
+ const group = this.createGroupAtLocation(dropLocation, this.dropSizing(referenceLocation), void 0, destinationGridview);
17601
17992
  this.movingLock(() => group.model.openPanel(removedPanel, { skipSetGroupActive: true }));
17602
17993
  this.doSetGroupAndPanelActive(group);
17603
17994
  this.fireDidMovePanel(removedPanel, sourceGroup);
@@ -17641,7 +18032,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17641
18032
  if (!destinationTarget || destinationTarget === "center" || !referenceLocation) targetGroup = destinationGroup;
17642
18033
  else {
17643
18034
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
17644
- targetGroup = this.createGroupAtLocation(dropLocation);
18035
+ targetGroup = this.createGroupAtLocation(dropLocation, this.dropSizing(referenceLocation));
17645
18036
  }
17646
18037
  if (!options.keepEmptyGroups && sourceGroup.model.size === 0 && sourceGroup !== targetGroup) this.doRemoveGroup(sourceGroup, { skipActive: true });
17647
18038
  addPanelsToGroup(targetGroup);
@@ -17692,6 +18083,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17692
18083
  if (options.skipSetActive !== true) this.doSetGroupAndPanelActive(to);
17693
18084
  else if (!this.activePanel) this.doSetGroupAndPanelActive(to);
17694
18085
  } else {
18086
+ const isReorderWithinBranch = (() => {
18087
+ if (from.api.location.type === "edge" || to.api.location.type === "edge") return false;
18088
+ const root = this.getGridviewForGroup(from);
18089
+ if (root !== this.getGridviewForGroup(to)) return false;
18090
+ let fromLocation;
18091
+ let toLocation;
18092
+ try {
18093
+ fromLocation = getGridLocation(from.element);
18094
+ toLocation = getGridLocation(to.element);
18095
+ } catch (_unused) {
18096
+ return false;
18097
+ }
18098
+ if (fromLocation.length === 0 || toLocation.length === 0) return false;
18099
+ return sequenceEquals(tail(fromLocation)[0], tail(toLocation)[0]) && getLocationOrientation(root.orientation, toLocation) === getDirectionOrientation(target);
18100
+ })();
17695
18101
  if (from.api.location.type === "edge") {
17696
18102
  /**
17697
18103
  * Edge groups are permanent structural elements and must
@@ -17757,13 +18163,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17757
18163
  const referenceLocation = getGridLocation(to.element);
17758
18164
  const dropLocation = getRelativeLocation(destGridview.orientation, referenceLocation, target);
17759
18165
  let size;
17760
- switch (destGridview.orientation) {
17761
- case "VERTICAL":
17762
- size = referenceLocation.length % 2 == 0 ? from.api.width : from.api.height;
17763
- break;
17764
- case "HORIZONTAL":
17765
- size = referenceLocation.length % 2 == 0 ? from.api.height : from.api.width;
17766
- break;
18166
+ if (isReorderWithinBranch) size = getDirectionOrientation(target) === "HORIZONTAL" ? from.api.width : from.api.height;
18167
+ else {
18168
+ var _referenceLocation;
18169
+ size = Sizing.Split((_referenceLocation = referenceLocation[referenceLocation.length - 1]) !== null && _referenceLocation !== void 0 ? _referenceLocation : 0);
17767
18170
  }
17768
18171
  destGridview.addView(source, size, dropLocation);
17769
18172
  this.setGroupLocationForRoot(source, destGridview);
@@ -17888,6 +18291,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17888
18291
  });
17889
18292
  return panel;
17890
18293
  }
18294
+ /**
18295
+ * Sizing for a group created by a drop next to `referenceLocation`: half
18296
+ * of the group the overlay was drawn over, leaving its siblings alone, so
18297
+ * the panel lands in the region the overlay indicated (#1612). Gridview
18298
+ * rewrites the index to 0 when a cross-axis drop wraps the reference in a
18299
+ * new branch, so one value serves both paths.
18300
+ */
18301
+ dropSizing(referenceLocation) {
18302
+ return Sizing.Split(referenceLocation.length === 0 ? 0 : referenceLocation[referenceLocation.length - 1]);
18303
+ }
17891
18304
  createGroupAtLocation(location, size, options, gridview = this.gridview) {
17892
18305
  const group = this.createGroup(options);
17893
18306
  this.doAddGroup(group, location, size, gridview);
@@ -17947,22 +18360,22 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17947
18360
  return location.length % 2 == 1 ? rootOrientation : orthogonal(rootOrientation);
17948
18361
  }
17949
18362
  updateTheme() {
17950
- var _this$_options$theme, _this$_shellThemeClas, _theme$gap, _this$_popoutWindowSe23, _this$_popoutWindowSe24, _this$_shellManager4, _theme$edgeGroupColla, _theme$tabGroupIndica;
18363
+ var _this$_options$theme, _this$_shellThemeClas, _theme$gap, _this$_popoutWindowSe23, _this$_popoutWindowSe24, _this$_shellManager5, _theme$edgeGroupColla, _theme$tabGroupIndica;
17951
18364
  const theme = (_this$_options$theme = this._options.theme) !== null && _this$_options$theme !== void 0 ? _this$_options$theme : themeAbyss;
17952
18365
  (_this$_shellThemeClas = this._shellThemeClassnames) === null || _this$_shellThemeClas === void 0 || _this$_shellThemeClas.setClassNames(theme.className);
17953
18366
  const gap = (_theme$gap = theme.gap) !== null && _theme$gap !== void 0 ? _theme$gap : 0;
17954
18367
  this.gridview.margin = gap;
17955
18368
  for (const floating of this.floatingGroups) floating.gridview.margin = gap;
17956
18369
  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;
17957
- (_this$_shellManager4 = this._shellManager) === null || _this$_shellManager4 === void 0 || _this$_shellManager4.updateTheme(gap, (_theme$edgeGroupColla = theme.edgeGroupCollapsedSize) !== null && _theme$edgeGroupColla !== void 0 ? _theme$edgeGroupColla : 35);
18370
+ (_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);
17958
18371
  if (theme.dndOverlayBorder === void 0) {
17959
- var _this$_shellManager5;
18372
+ var _this$_shellManager6;
17960
18373
  this.element.style.removeProperty("--dv-drag-over-border");
17961
- (_this$_shellManager5 = this._shellManager) === null || _this$_shellManager5 === void 0 || _this$_shellManager5.element.style.removeProperty("--dv-drag-over-border");
18374
+ (_this$_shellManager6 = this._shellManager) === null || _this$_shellManager6 === void 0 || _this$_shellManager6.element.style.removeProperty("--dv-drag-over-border");
17962
18375
  } else {
17963
- var _this$_shellManager6;
18376
+ var _this$_shellManager7;
17964
18377
  this.element.style.setProperty("--dv-drag-over-border", theme.dndOverlayBorder);
17965
- (_this$_shellManager6 = this._shellManager) === null || _this$_shellManager6 === void 0 || _this$_shellManager6.element.style.setProperty("--dv-drag-over-border", theme.dndOverlayBorder);
18378
+ (_this$_shellManager7 = this._shellManager) === null || _this$_shellManager7 === void 0 || _this$_shellManager7.element.style.setProperty("--dv-drag-over-border", theme.dndOverlayBorder);
17966
18379
  }
17967
18380
  switch (theme.dndOverlayMounting) {
17968
18381
  case "absolute":
@@ -18865,6 +19278,8 @@ exports.AdvancedDnDModule = AdvancedDnDModule;
18865
19278
  exports.AdvancedDnDService = AdvancedDnDService;
18866
19279
  exports.BaseGrid = BaseGrid;
18867
19280
  exports.ContentContainer = ContentContainer;
19281
+ exports.ContextMenuController = ContextMenuController;
19282
+ exports.ContextMenuModule = ContextMenuModule;
18868
19283
  exports.DEFAULT_TAB_GROUP_COLORS = DEFAULT_TAB_GROUP_COLORS;
18869
19284
  exports.DefaultDockviewDeserialzier = DefaultDockviewDeserialzier;
18870
19285
  exports.DefaultTab = DefaultTab;