dockview-core 8.0.0 → 8.2.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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * dockview-core
3
- * @version 8.0.0
3
+ * @version 8.2.0
4
4
  * @link https://github.com/dockview/dockview
5
5
  * @license MIT
6
6
  */
@@ -21,7 +21,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
21
21
  //#endregion
22
22
  //#region src/dnd/dataTransfer.ts
23
23
  var _LocalSelectionTransfer;
24
- var TransferObject = class {};
24
+ var TransferObject = class {
25
+ constructor() {}
26
+ };
25
27
  var PanelTransfer = class extends TransferObject {
26
28
  constructor(viewId, groupId, panelId, tabGroupId) {
27
29
  super();
@@ -214,7 +216,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
214
216
  this.options = options;
215
217
  this._listeners = [];
216
218
  this._disposed = false;
217
- this._pauseTokens = /* @__PURE__ */ new Set();
218
219
  }
219
220
  get event() {
220
221
  if (!this._event) {
@@ -235,14 +236,26 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
235
236
  }
236
237
  fire(e) {
237
238
  var _this$options2;
238
- if (this._pauseTokens.size > 0) return;
239
+ if (this._pauseTokens !== void 0 && this._pauseTokens.size > 0) return;
239
240
  if ((_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.replay) this._last = e;
240
- for (const listener of this._listeners.slice()) listener.callback(e);
241
+ const listeners = this._listeners;
242
+ const length = listeners.length;
243
+ if (length === 0) return;
244
+ if (length === 1) {
245
+ listeners[0].callback(e);
246
+ return;
247
+ }
248
+ for (const listener of listeners.slice()) listener.callback(e);
241
249
  }
242
250
  pause() {
251
+ var _this$_pauseTokens;
243
252
  const token = {};
253
+ (_this$_pauseTokens = this._pauseTokens) !== null && _this$_pauseTokens !== void 0 || (this._pauseTokens = /* @__PURE__ */ new Set());
244
254
  this._pauseTokens.add(token);
245
- return Disposable.from(() => this._pauseTokens.delete(token));
255
+ return Disposable.from(() => {
256
+ var _this$_pauseTokens2;
257
+ return (_this$_pauseTokens2 = this._pauseTokens) === null || _this$_pauseTokens2 === void 0 ? void 0 : _this$_pauseTokens2.delete(token);
258
+ });
246
259
  }
247
260
  dispose() {
248
261
  if (!this._disposed) {
@@ -545,8 +558,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
545
558
  let previousScreenX = window.screenX;
546
559
  let previousScreenY = window.screenY;
547
560
  let timeout;
561
+ let rafHandle = 0;
562
+ let stopped = false;
548
563
  const checkMovement = () => {
549
- if (window.closed) return;
564
+ if (stopped || window.closed) return;
550
565
  const currentScreenX = window.screenX;
551
566
  const currentScreenY = window.screenY;
552
567
  if (currentScreenX !== previousScreenX || currentScreenY !== previousScreenY) {
@@ -557,9 +572,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
557
572
  previousScreenX = currentScreenX;
558
573
  previousScreenY = currentScreenY;
559
574
  }
560
- requestAnimationFrame(checkMovement);
575
+ rafHandle = requestAnimationFrame(checkMovement);
561
576
  };
562
577
  checkMovement();
578
+ const disposeEmitter = emitter.dispose.bind(emitter);
579
+ emitter.dispose = () => {
580
+ if (!stopped) {
581
+ stopped = true;
582
+ cancelAnimationFrame(rafHandle);
583
+ clearTimeout(timeout);
584
+ }
585
+ disposeEmitter();
586
+ };
563
587
  return emitter;
564
588
  }
565
589
  function onDidWindowResizeEnd(element, cb) {
@@ -695,6 +719,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
695
719
  set size(size) {
696
720
  this._size = size;
697
721
  }
722
+ setContainerGeometry(prop, value) {
723
+ if (this._appliedStyles[prop] === value) return;
724
+ this._appliedStyles[prop] = value;
725
+ this.container.style[prop] = value;
726
+ }
698
727
  get size() {
699
728
  return this._size;
700
729
  }
@@ -730,6 +759,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
730
759
  this.view = view;
731
760
  this.disposable = disposable;
732
761
  this._cachedVisibleSize = void 0;
762
+ this._appliedStyles = {};
733
763
  if (typeof size === "number") {
734
764
  this._size = size;
735
765
  this._cachedVisibleSize = void 0;
@@ -778,6 +808,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
778
808
  LayoutPriority["Normal"] = "normal";
779
809
  return LayoutPriority;
780
810
  }({});
811
+ function setSashPosition(sash, left, top) {
812
+ if (sash.appliedLeft !== left) {
813
+ sash.appliedLeft = left;
814
+ sash.container.style.left = left;
815
+ }
816
+ if (sash.appliedTop !== top) {
817
+ sash.appliedTop = top;
818
+ sash.container.style.top = top;
819
+ }
820
+ }
781
821
  let Sizing;
782
822
  (function(_Sizing) {
783
823
  _Sizing.Distribute = { type: "distribute" };
@@ -896,10 +936,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
896
936
  pushToEnd(upIndexes, i);
897
937
  pushToEnd(downIndexes, i);
898
938
  }
899
- const upItems = upIndexes.map((i) => this.viewItems[i]);
900
- const upSizes = upIndexes.map((i) => sizes[i]);
901
- const downItems = downIndexes.map((i) => this.viewItems[i]);
902
- const downSizes = downIndexes.map((i) => sizes[i]);
903
939
  const minDeltaUp = upIndexes.reduce((_, i) => _ + this.viewItems[i].minimumSize - sizes[i], 0);
904
940
  const maxDeltaUp = upIndexes.reduce((_, i) => _ + this.viewItems[i].maximumSize - sizes[i], 0);
905
941
  const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((_, i) => _ + sizes[i] - this.viewItems[i].minimumSize, 0);
@@ -923,19 +959,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
923
959
  const tentativeDelta = clamp(delta, minDelta, maxDelta);
924
960
  let actualDelta = 0;
925
961
  let deltaUp = tentativeDelta;
926
- for (let i = 0; i < upItems.length; i++) {
927
- const item = upItems[i];
928
- const size = clamp(upSizes[i] + deltaUp, item.minimumSize, item.maximumSize);
929
- const viewDelta = size - upSizes[i];
962
+ for (const upIndex of upIndexes) {
963
+ const item = this.viewItems[upIndex];
964
+ const priorSize = sizes[upIndex];
965
+ const size = clamp(priorSize + deltaUp, item.minimumSize, item.maximumSize);
966
+ const viewDelta = size - priorSize;
930
967
  actualDelta += viewDelta;
931
968
  deltaUp -= viewDelta;
932
969
  item.size = size;
933
970
  }
934
971
  let deltaDown = actualDelta;
935
- for (let i = 0; i < downItems.length; i++) {
936
- const item = downItems[i];
937
- const size = clamp(downSizes[i] - deltaDown, item.minimumSize, item.maximumSize);
938
- const viewDelta = size - downSizes[i];
972
+ for (const downIndex of downIndexes) {
973
+ const item = this.viewItems[downIndex];
974
+ const priorSize = sizes[downIndex];
975
+ const size = clamp(priorSize - deltaDown, item.minimumSize, item.maximumSize);
976
+ const viewDelta = size - priorSize;
939
977
  deltaDown += viewDelta;
940
978
  item.size = size;
941
979
  }
@@ -1183,13 +1221,22 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1183
1221
  this.saveProportions();
1184
1222
  }
1185
1223
  distributeEmptySpace(lowPriorityIndex) {
1186
- const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1224
+ let contentSize = 0;
1225
+ for (const item of this.viewItems) contentSize += item.size;
1187
1226
  let emptyDelta = this.size - contentSize;
1227
+ if (emptyDelta === 0) return;
1188
1228
  const indexes = range(this.viewItems.length - 1, -1);
1189
- const lowPriorityIndexes = indexes.filter((i) => this.viewItems[i].priority === "low");
1190
- const highPriorityIndexes = indexes.filter((i) => this.viewItems[i].priority === "high");
1191
- for (const index of highPriorityIndexes) pushToStart(indexes, index);
1192
- for (const index of lowPriorityIndexes) pushToEnd(indexes, index);
1229
+ let hasPriority = false;
1230
+ for (const item of this.viewItems) if (item.priority === "low" || item.priority === "high") {
1231
+ hasPriority = true;
1232
+ break;
1233
+ }
1234
+ if (hasPriority) {
1235
+ const lowPriorityIndexes = indexes.filter((i) => this.viewItems[i].priority === "low");
1236
+ const highPriorityIndexes = indexes.filter((i) => this.viewItems[i].priority === "high");
1237
+ for (const index of highPriorityIndexes) pushToStart(indexes, index);
1238
+ for (const index of lowPriorityIndexes) pushToEnd(indexes, index);
1239
+ }
1193
1240
  if (typeof lowPriorityIndex === "number") pushToEnd(indexes, lowPriorityIndex);
1194
1241
  for (let i = 0; emptyDelta !== 0 && i < indexes.length; i++) {
1195
1242
  const item = this.viewItems[indexes[i]];
@@ -1212,49 +1259,45 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1212
1259
  * For each view `i` the offet must be adjusted by `m * i/(n - 1)`.
1213
1260
  */
1214
1261
  layoutViews() {
1215
- this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1262
+ let contentSize = 0;
1263
+ let visibleViewCount = 0;
1264
+ for (const item of this.viewItems) {
1265
+ contentSize += item.size;
1266
+ if (item.visible) visibleViewCount++;
1267
+ }
1268
+ this._contentSize = contentSize;
1216
1269
  this.updateSashEnablement();
1217
1270
  if (this.viewItems.length === 0) return;
1218
- const visibleViewItems = this.viewItems.filter((i) => i.visible);
1219
- const sashCount = Math.max(0, visibleViewItems.length - 1);
1220
- const marginReducedSize = this.margin * sashCount / Math.max(1, visibleViewItems.length);
1271
+ const sashCount = Math.max(0, visibleViewCount - 1);
1272
+ const marginReducedSize = this.margin * sashCount / Math.max(1, visibleViewCount);
1221
1273
  let totalLeftOffset = 0;
1222
1274
  const viewLeftOffsets = [];
1223
1275
  const sashWidth = 4;
1224
- const runningVisiblePanelCount = this.viewItems.reduce((arr, viewItem, i) => {
1225
- const flag = viewItem.visible ? 1 : 0;
1226
- if (i === 0) arr.push(flag);
1227
- else arr.push(arr[i - 1] + flag);
1228
- return arr;
1229
- }, []);
1276
+ let runningVisiblePanelCount = 0;
1230
1277
  this.viewItems.forEach((view, i) => {
1231
1278
  totalLeftOffset += this.viewItems[i].size;
1232
1279
  viewLeftOffsets.push(totalLeftOffset);
1280
+ runningVisiblePanelCount += view.visible ? 1 : 0;
1233
1281
  const size = view.visible ? view.size - marginReducedSize : 0;
1234
- const visiblePanelsBeforeThisView = Math.max(0, runningVisiblePanelCount[i] - 1);
1282
+ const visiblePanelsBeforeThisView = Math.max(0, runningVisiblePanelCount - 1);
1235
1283
  const offset = i === 0 || visiblePanelsBeforeThisView === 0 ? 0 : viewLeftOffsets[i - 1] + visiblePanelsBeforeThisView / sashCount * marginReducedSize;
1236
1284
  if (i < this.viewItems.length - 1) {
1237
1285
  const newSize = view.visible ? offset + size - sashWidth / 2 + this.margin / 2 : offset;
1238
- if (this._orientation === "HORIZONTAL") {
1239
- this.sashes[i].container.style.left = `${newSize}px`;
1240
- this.sashes[i].container.style.top = `0px`;
1241
- }
1242
- if (this._orientation === "VERTICAL") {
1243
- this.sashes[i].container.style.left = `0px`;
1244
- this.sashes[i].container.style.top = `${newSize}px`;
1245
- }
1286
+ const sash = this.sashes[i];
1287
+ if (this._orientation === "HORIZONTAL") setSashPosition(sash, `${newSize}px`, `0px`);
1288
+ if (this._orientation === "VERTICAL") setSashPosition(sash, `0px`, `${newSize}px`);
1246
1289
  }
1247
1290
  if (this._orientation === "HORIZONTAL") {
1248
- view.container.style.width = `${size}px`;
1249
- view.container.style.left = `${offset}px`;
1250
- view.container.style.top = "";
1251
- view.container.style.height = "";
1291
+ view.setContainerGeometry("width", `${size}px`);
1292
+ view.setContainerGeometry("left", `${offset}px`);
1293
+ view.setContainerGeometry("top", "");
1294
+ view.setContainerGeometry("height", "");
1252
1295
  }
1253
1296
  if (this._orientation === "VERTICAL") {
1254
- view.container.style.height = `${size}px`;
1255
- view.container.style.top = `${offset}px`;
1256
- view.container.style.width = "";
1257
- view.container.style.left = "";
1297
+ view.setContainerGeometry("height", `${size}px`);
1298
+ view.setContainerGeometry("top", `${offset}px`);
1299
+ view.setContainerGeometry("width", "");
1300
+ view.setContainerGeometry("left", "");
1258
1301
  }
1259
1302
  view.view.layout(view.size - marginReducedSize, this._orthogonalSize);
1260
1303
  });
@@ -1272,6 +1315,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1272
1315
  }
1273
1316
  }
1274
1317
  updateSashEnablement() {
1318
+ if (this.sashes.length === 0) return;
1275
1319
  let previous = false;
1276
1320
  const collapsesDown = this.viewItems.map((i) => previous = i.size - i.minimumSize > 0 || previous);
1277
1321
  previous = false;
@@ -1578,10 +1622,20 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1578
1622
  return this.orientation === "HORIZONTAL" ? this.orthogonalSize : this.size;
1579
1623
  }
1580
1624
  get minimumSize() {
1581
- return this.children.length === 0 ? 0 : Math.max(...this.children.map((c, index) => this.splitview.isViewVisible(index) ? c.minimumOrthogonalSize : 0));
1625
+ if (this._cachedMinimumSize === void 0) {
1626
+ let value = 0;
1627
+ for (let index = 0; index < this.children.length; index++) if (this.splitview.isViewVisible(index)) value = Math.max(value, this.children[index].minimumOrthogonalSize);
1628
+ this._cachedMinimumSize = value;
1629
+ }
1630
+ return this._cachedMinimumSize;
1582
1631
  }
1583
1632
  get maximumSize() {
1584
- return Math.min(...this.children.map((c, index) => this.splitview.isViewVisible(index) ? c.maximumOrthogonalSize : Number.POSITIVE_INFINITY));
1633
+ if (this._cachedMaximumSize === void 0) {
1634
+ let value = Number.POSITIVE_INFINITY;
1635
+ for (let index = 0; index < this.children.length; index++) if (this.splitview.isViewVisible(index)) value = Math.min(value, this.children[index].maximumOrthogonalSize);
1636
+ this._cachedMaximumSize = value;
1637
+ }
1638
+ return this._cachedMaximumSize;
1585
1639
  }
1586
1640
  get minimumOrthogonalSize() {
1587
1641
  return this.splitview.minimumSize;
@@ -1608,15 +1662,29 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1608
1662
  return this.orientation === "HORIZONTAL" ? this.maximumSize : this.maximumOrthogonalSize;
1609
1663
  }
1610
1664
  get priority() {
1665
+ var _this$_cachedPriority;
1666
+ (_this$_cachedPriority = this._cachedPriority) !== null && _this$_cachedPriority !== void 0 || (this._cachedPriority = this.computePriority());
1667
+ return this._cachedPriority;
1668
+ }
1669
+ computePriority() {
1611
1670
  if (this.children.length === 0) return "normal";
1612
- const priorities = new Set(this.children.map((c) => {
1613
- var _c$priority;
1614
- return (_c$priority = c.priority) !== null && _c$priority !== void 0 ? _c$priority : "normal";
1615
- }));
1616
- if (priorities.has("high")) return "high";
1617
- else if (priorities.has("low")) return "low";
1671
+ let hasHigh = false;
1672
+ let hasLow = false;
1673
+ for (const child of this.children) {
1674
+ var _child$priority;
1675
+ const priority = (_child$priority = child.priority) !== null && _child$priority !== void 0 ? _child$priority : "normal";
1676
+ if (priority === "high") hasHigh = true;
1677
+ else if (priority === "low") hasLow = true;
1678
+ }
1679
+ if (hasHigh) return "high";
1680
+ else if (hasLow) return "low";
1618
1681
  return "normal";
1619
1682
  }
1683
+ invalidateCachedSizes() {
1684
+ this._cachedMinimumSize = void 0;
1685
+ this._cachedMaximumSize = void 0;
1686
+ this._cachedPriority = void 0;
1687
+ }
1620
1688
  get disabled() {
1621
1689
  return this.splitview.disabled;
1622
1690
  }
@@ -1692,6 +1760,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1692
1760
  if (this.splitview.isViewVisible(index) === visible) return;
1693
1761
  const wereAllChildrenHidden = this.splitview.contentSize === 0;
1694
1762
  this.splitview.setViewVisible(index, visible);
1763
+ this.invalidateCachedSizes();
1695
1764
  const areAllChildrenHidden = this.splitview.contentSize === 0;
1696
1765
  if (visible && wereAllChildrenHidden || !visible && areAllChildrenHidden) this._onDidVisibilityChange.fire({ visible });
1697
1766
  }
@@ -1740,12 +1809,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
1740
1809
  return child;
1741
1810
  }
1742
1811
  setupChildrenEvents() {
1812
+ this.invalidateCachedSizes();
1743
1813
  this._childrenDisposable.dispose();
1744
1814
  this._childrenDisposable = new CompositeDisposable(Event.any(...this.children.map((c) => c.onDidChange))((e) => {
1745
1815
  /**
1746
1816
  * indicate a change has occured to allows any re-rendering but don't bubble
1747
1817
  * event because that was specific to this branch
1748
1818
  */
1819
+ this.invalidateCachedSizes();
1749
1820
  this._onDidChange.fire({ size: e.orthogonalSize });
1750
1821
  }), ...this.children.map((c, i) => {
1751
1822
  if (c instanceof BranchNode) return c.onDidVisibilityChange(({ visible }) => {
@@ -3422,7 +3493,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
3422
3493
  * Add a group and return the created object.
3423
3494
  */
3424
3495
  addGroup(options) {
3425
- return this.component.addGroup(options);
3496
+ return this.component.withOrigin("api", () => this.component.addGroup(options));
3426
3497
  }
3427
3498
  /**
3428
3499
  * Close all groups and panels.
@@ -3560,13 +3631,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
3560
3631
  this.activatePrevious(options);
3561
3632
  }
3562
3633
  maximizeGroup(panel) {
3563
- this.component.maximizeGroup(panel.group);
3634
+ this.component.withOrigin("api", () => this.component.maximizeGroup(panel.group));
3564
3635
  }
3565
3636
  hasMaximizedGroup() {
3566
3637
  return this.component.hasMaximizedGroup();
3567
3638
  }
3568
3639
  exitMaximizedGroup() {
3569
- this.component.exitMaximizedGroup();
3640
+ this.component.withOrigin("api", () => this.component.exitMaximizedGroup());
3570
3641
  }
3571
3642
  get onDidMaximizedGroupChange() {
3572
3643
  return this.component.onDidMaximizedGroupChange;
@@ -5521,9 +5592,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
5521
5592
  const doRender = ((_options$asActive = options === null || options === void 0 ? void 0 : options.asActive) !== null && _options$asActive !== void 0 ? _options$asActive : true) || this.panel && this.group.isPanelActive(this.panel);
5522
5593
  if (((_this$panel = this.panel) === null || _this$panel === void 0 ? void 0 : _this$panel.view.content.element.parentElement) === this._element) {
5523
5594
  var _this$panel$view$cont, _this$panel$view$cont2;
5524
- /**
5525
- * If the currently attached panel is mounted directly to the content then remove it
5526
- */
5527
5595
  this.panel.view.content.element.remove();
5528
5596
  (_this$panel$view$cont = (_this$panel$view$cont2 = this.panel.view.content).onHide) === null || _this$panel$view$cont === void 0 || _this$panel$view$cont.call(_this$panel$view$cont2);
5529
5597
  }
@@ -6264,7 +6332,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
6264
6332
  this.element.appendChild(this._scrollbar);
6265
6333
  this.addDisposables(addDisposableListener(this.element, "wheel", (event) => {
6266
6334
  this._scrollOffset += event.deltaY * Scrollbar.MouseWheelSpeed;
6267
- this.calculateScrollbarStyles();
6335
+ this.scheduleStyleUpdate();
6268
6336
  }), addDisposableListener(this._scrollbar, "pointerdown", (event) => {
6269
6337
  var _this$_scrollbar$owne;
6270
6338
  event.preventDefault();
@@ -6276,7 +6344,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
6276
6344
  const delta = this._orientation === "horizontal" ? event.clientX - originalClient : event.clientY - originalClient;
6277
6345
  const p = (this._orientation === "horizontal" ? this.element.clientWidth : this.element.clientHeight) / (this._orientation === "horizontal" ? this.scrollableElement.scrollWidth : this.scrollableElement.scrollHeight);
6278
6346
  this._scrollOffset = originalScrollOffset + delta / p;
6279
- this.calculateScrollbarStyles();
6347
+ this.scheduleStyleUpdate();
6280
6348
  };
6281
6349
  const onEnd = () => {
6282
6350
  toggleClass(this.element, "dv-scrollable-scrolling", false);
@@ -6288,10 +6356,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
6288
6356
  doc.addEventListener("pointerup", onEnd);
6289
6357
  doc.addEventListener("pointercancel", onEnd);
6290
6358
  }), addDisposableListener(this.element, "scroll", () => {
6291
- this.calculateScrollbarStyles();
6359
+ this.scheduleStyleUpdate();
6292
6360
  }), addDisposableListener(this.scrollableElement, "scroll", () => {
6293
6361
  this._scrollOffset = this._orientation === "horizontal" ? this.scrollableElement.scrollLeft : this.scrollableElement.scrollTop;
6294
- this.calculateScrollbarStyles();
6362
+ this.scheduleStyleUpdate();
6295
6363
  }), watchElementResize(this.element, () => {
6296
6364
  toggleClass(this.element, "dv-scrollable-resizing", true);
6297
6365
  if (this._animationTimer) clearTimeout(this._animationTimer);
@@ -6299,9 +6367,29 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
6299
6367
  clearTimeout(this._animationTimer);
6300
6368
  toggleClass(this.element, "dv-scrollable-resizing", false);
6301
6369
  }, 500);
6302
- this.calculateScrollbarStyles();
6370
+ this.scheduleStyleUpdate();
6371
+ }), Disposable.from(() => {
6372
+ if (this._pendingStyleFrame !== void 0) {
6373
+ cancelAnimationFrame(this._pendingStyleFrame);
6374
+ this._pendingStyleFrame = void 0;
6375
+ }
6303
6376
  }));
6304
6377
  }
6378
+ /**
6379
+ * Coalesce the scrollbar restyle to one pass per animation frame. The
6380
+ * wheel / scroll / pointermove handlers can each fire many times per frame,
6381
+ * and `calculateScrollbarStyles` both reads layout (`clientWidth`/
6382
+ * `scrollWidth`) and writes styles + `scrollLeft`/`scrollTop`; running it
6383
+ * synchronously per event caused repeated read→write→read reflow. Batching
6384
+ * to a frame keeps a burst of events to a single measure+write.
6385
+ */
6386
+ scheduleStyleUpdate() {
6387
+ if (this._pendingStyleFrame !== void 0) return;
6388
+ this._pendingStyleFrame = requestAnimationFrame(() => {
6389
+ this._pendingStyleFrame = void 0;
6390
+ this.calculateScrollbarStyles();
6391
+ });
6392
+ }
6305
6393
  calculateScrollbarStyles() {
6306
6394
  const clientSize = this._orientation === "horizontal" ? this.element.clientWidth : this.element.clientHeight;
6307
6395
  const scrollSize = this._orientation === "horizontal" ? this.scrollableElement.scrollWidth : this.scrollableElement.scrollHeight;
@@ -8762,8 +8850,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
8762
8850
  }, true), addDisposableListener(this._tabsList, "dragend", () => {
8763
8851
  this._reorder.resetDragAnimation();
8764
8852
  }), addDisposableListener(this._tabsList, "drop", (event) => {
8765
- var _this$accessor$option, _this$group$model$dro;
8766
- if (!this._animState || this._animState.currentInsertionIndex === null) return;
8853
+ var _this$_animState3, _this$accessor$option, _this$group$model$dro;
8854
+ if (((_this$_animState3 = this._animState) === null || _this$_animState3 === void 0 ? void 0 : _this$_animState3.currentInsertionIndex) == null) return;
8767
8855
  if (((_this$accessor$option = this.accessor.options.theme) === null || _this$accessor$option === void 0 ? void 0 : _this$accessor$option.tabAnimation) !== "smooth" && !this._animState.sourceTabGroupId) return;
8768
8856
  event.stopPropagation();
8769
8857
  event.preventDefault();
@@ -8968,7 +9056,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
8968
9056
  };
8969
9057
  this._pendingCollapse = true;
8970
9058
  requestAnimationFrame(() => {
8971
- var _this$_animState3, _this$_animState3$cur;
9059
+ var _this$_animState4, _this$_animState4$cur;
8972
9060
  this._pendingCollapse = false;
8973
9061
  if (!this._animState) return;
8974
9062
  if (!this._tabsList.classList.contains("dv-tabs-container--wrap")) {
@@ -8976,7 +9064,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
8976
9064
  toggleClass(tab.element, "dv-tab--dragging", true);
8977
9065
  tab.element.offsetHeight;
8978
9066
  }
8979
- (_this$_animState3$cur = (_this$_animState3 = this._animState).currentInsertionIndex) !== null && _this$_animState3$cur !== void 0 || (_this$_animState3.currentInsertionIndex = sourceIndex);
9067
+ (_this$_animState4$cur = (_this$_animState4 = this._animState).currentInsertionIndex) !== null && _this$_animState4$cur !== void 0 || (_this$_animState4.currentInsertionIndex = sourceIndex);
8980
9068
  this.applyDragOverTransforms(true);
8981
9069
  tab.element.style.removeProperty("transition");
8982
9070
  });
@@ -9065,8 +9153,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
9065
9153
  }
9066
9154
  }
9067
9155
  delete(id) {
9068
- var _this$_animState4;
9069
- if (((_this$_animState4 = this._animState) === null || _this$_animState4 === void 0 ? void 0 : _this$_animState4.sourceTabId) === id) {
9156
+ var _this$_animState5;
9157
+ if (((_this$_animState5 = this._animState) === null || _this$_animState5 === void 0 ? void 0 : _this$_animState5.sourceTabId) === id) {
9070
9158
  this.resetTabTransforms();
9071
9159
  this._animState = null;
9072
9160
  }
@@ -9183,7 +9271,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
9183
9271
  const groupPanelIds = new Set(tabGroup.panelIds);
9184
9272
  this._pendingCollapse = true;
9185
9273
  requestAnimationFrame(() => {
9186
- var _this$_animState5, _this$_animState5$cur;
9274
+ var _this$_animState6, _this$_animState6$cur;
9187
9275
  this._pendingCollapse = false;
9188
9276
  if (!this._animState) return;
9189
9277
  for (const t of this._tabs) if (groupPanelIds.has(t.value.panel.id)) {
@@ -9198,7 +9286,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
9198
9286
  this._tabsList.offsetHeight;
9199
9287
  const underline = this._tabGroupManager.groupUnderlines.get(tabGroup.id);
9200
9288
  if (underline) underline.style.display = "none";
9201
- (_this$_animState5$cur = (_this$_animState5 = this._animState).currentInsertionIndex) !== null && _this$_animState5$cur !== void 0 || (_this$_animState5.currentInsertionIndex = firstIdx);
9289
+ (_this$_animState6$cur = (_this$_animState6 = this._animState).currentInsertionIndex) !== null && _this$_animState6$cur !== void 0 || (_this$_animState6.currentInsertionIndex = firstIdx);
9202
9290
  this.applyDragOverTransforms(true);
9203
9291
  for (const t of this._tabs) if (groupPanelIds.has(t.value.panel.id)) t.value.element.style.removeProperty("transition");
9204
9292
  if (chipEntry) chipEntry.chip.element.style.removeProperty("transition");
@@ -9933,6 +10021,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
9933
10021
  set headerPosition(value) {
9934
10022
  var _this$_activePanel;
9935
10023
  this._headerPosition = value;
10024
+ this.invalidateHeaderSize();
9936
10025
  removeClasses(this.container, "dv-groupview-header-top", "dv-groupview-header-bottom", "dv-groupview-header-left", "dv-groupview-header-right");
9937
10026
  addClasses(this.container, `dv-groupview-header-${value}`);
9938
10027
  const direction = value === "top" || value === "bottom" ? "horizontal" : "vertical";
@@ -10074,7 +10163,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
10074
10163
  this.header.hidden = !!options.hideHeader;
10075
10164
  this.locked = (_options$locked = options.locked) !== null && _options$locked !== void 0 ? _options$locked : false;
10076
10165
  this.headerPosition = (_options$headerPositi = options.headerPosition) !== null && _options$headerPositi !== void 0 ? _options$headerPositi : accessor.defaultHeaderPosition;
10077
- this.addDisposables(this._onDidPanelTitleChange.event(() => this.updateAccessibleLabel()), this._onTabDragStart, this._onGroupDragStart, this._onWillShowOverlay, this.tabsContainer.onTabDragStart((event) => {
10166
+ this.addDisposables(watchElementResize(this.tabsContainer.element, () => {
10167
+ if (this.isDisposed) return;
10168
+ const size = this.measureHeaderSize();
10169
+ if (size !== this._cachedHeaderSize) {
10170
+ this._cachedHeaderSize = size;
10171
+ this.layout(this._width, this._height);
10172
+ }
10173
+ }), this._onDidPanelTitleChange.event(() => this.updateAccessibleLabel()), this._onTabDragStart, this._onGroupDragStart, this._onWillShowOverlay, this.tabsContainer.onTabDragStart((event) => {
10078
10174
  this._onTabDragStart.fire(event);
10079
10175
  }), this.tabsContainer.onGroupDragStart((event) => {
10080
10176
  this._onGroupDragStart.fire(event);
@@ -10439,7 +10535,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
10439
10535
  this.panels.forEach((panel) => {
10440
10536
  this.rerender(panel);
10441
10537
  });
10442
- if (this._activePanel) this.contentContainer.renderPanel(this._activePanel, { asActive: true });
10538
+ if (this._activePanel) {
10539
+ this.contentContainer.renderPanel(this._activePanel, { asActive: true });
10540
+ const { width, height } = this.contentDimensions();
10541
+ this._activePanel.layout(width, height);
10542
+ }
10443
10543
  }
10444
10544
  get renderContainer() {
10445
10545
  var _this$_overwriteRende;
@@ -10531,16 +10631,11 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
10531
10631
  (_this$_activePanel3 = this._activePanel) === null || _this$_activePanel3 === void 0 || _this$_activePanel3.focus();
10532
10632
  }
10533
10633
  openPanel(panel, options = {}) {
10534
- /**
10535
- * set the panel group
10536
- * add the panel
10537
- * check if group active
10538
- * check if panel active
10539
- */
10540
10634
  if (typeof options.index !== "number" || options.index > this.panels.length) options.index = this.panels.length;
10541
10635
  const skipSetActive = !!options.skipSetActive;
10542
10636
  panel.updateParentGroup(this.groupPanel, { skipSetActive: options.skipSetActive });
10543
10637
  this.doAddPanel(panel, options.index, { skipSetActive });
10638
+ this.invalidateHeaderSize();
10544
10639
  if (this._activePanel === panel) {
10545
10640
  this.contentContainer.renderPanel(panel, { asActive: true });
10546
10641
  return;
@@ -10603,6 +10698,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
10603
10698
  * changing) down to the content + active panel.
10604
10699
  */
10605
10700
  relayout() {
10701
+ this.invalidateHeaderSize();
10606
10702
  this.layout(this._width, this._height);
10607
10703
  }
10608
10704
  /**
@@ -10612,17 +10708,32 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
10612
10708
  * width); a hidden header has `display:none` so its `offset*` is 0 and
10613
10709
  * nothing is subtracted.
10614
10710
  */
10615
- contentDimensions() {
10711
+ /**
10712
+ * Measure the header's extent along its occupied axis. This is the single
10713
+ * forced-reflow read; it now runs only on a cache miss (first layout after
10714
+ * a header change) and inside the header's ResizeObserver — not on every
10715
+ * layout frame.
10716
+ */
10717
+ measureHeaderSize() {
10616
10718
  const headerEl = this.tabsContainer.element;
10719
+ return this.headerPosition === "top" || this.headerPosition === "bottom" ? headerEl.offsetHeight : headerEl.offsetWidth;
10720
+ }
10721
+ invalidateHeaderSize() {
10722
+ this._cachedHeaderSize = void 0;
10723
+ }
10724
+ contentDimensions() {
10725
+ var _this$_cachedHeaderSi;
10617
10726
  const horizontal = this.headerPosition === "top" || this.headerPosition === "bottom";
10727
+ const headerSize = (_this$_cachedHeaderSi = this._cachedHeaderSize) !== null && _this$_cachedHeaderSi !== void 0 ? _this$_cachedHeaderSi : this._cachedHeaderSize = this.measureHeaderSize();
10618
10728
  return {
10619
- width: horizontal ? this._width : Math.max(0, this._width - headerEl.offsetWidth),
10620
- height: horizontal ? Math.max(0, this._height - headerEl.offsetHeight) : this._height
10729
+ width: horizontal ? this._width : Math.max(0, this._width - headerSize),
10730
+ height: horizontal ? Math.max(0, this._height - headerSize) : this._height
10621
10731
  };
10622
10732
  }
10623
10733
  _removePanel(panel, options) {
10624
10734
  const isActivePanel = this._activePanel === panel;
10625
10735
  this.doRemovePanel(panel);
10736
+ this.invalidateHeaderSize();
10626
10737
  if (isActivePanel && this.panels.length > 0) {
10627
10738
  const nextPanel = this.mostRecentlyUsed[0];
10628
10739
  this.openPanel(nextPanel, {
@@ -10948,6 +11059,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
10948
11059
  if (typeof event.minimumHeight === "number" || typeof event.minimumHeight === "function") this._minimumHeight = event.minimumHeight;
10949
11060
  if (typeof event.maximumWidth === "number" || typeof event.maximumWidth === "function") this._maximumWidth = event.maximumWidth;
10950
11061
  if (typeof event.maximumHeight === "number" || typeof event.maximumHeight === "function") this._maximumHeight = event.maximumHeight;
11062
+ this._onDidChange.fire(void 0);
10951
11063
  }), this.api.onDidSizeChange((event) => {
10952
11064
  this._onDidChange.fire({
10953
11065
  height: event.height,
@@ -11067,20 +11179,22 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
11067
11179
  return this._group.model.headerPosition;
11068
11180
  }
11069
11181
  moveTo(options) {
11070
- var _options$group, _options$position, _options$skipSetActiv, _options$position2;
11071
11182
  if (!this._group) throw new Error(NOT_INITIALIZED_MESSAGE);
11072
- const group = (_options$group = options.group) !== null && _options$group !== void 0 ? _options$group : this.accessor.addGroup({
11073
- direction: positionToDirection((_options$position = options.position) !== null && _options$position !== void 0 ? _options$position : "right"),
11074
- skipSetActive: (_options$skipSetActiv = options.skipSetActive) !== null && _options$skipSetActiv !== void 0 ? _options$skipSetActiv : false
11075
- });
11076
- this.accessor.moveGroupOrPanel({
11077
- from: { groupId: this._group.id },
11078
- to: {
11079
- group,
11080
- position: options.group ? (_options$position2 = options.position) !== null && _options$position2 !== void 0 ? _options$position2 : "center" : "center",
11081
- index: options.index
11082
- },
11083
- skipSetActive: options.skipSetActive
11183
+ this.accessor.withOrigin("api", () => {
11184
+ var _options$group, _options$position, _options$skipSetActiv, _options$position2;
11185
+ const group = (_options$group = options.group) !== null && _options$group !== void 0 ? _options$group : this.accessor.addGroup({
11186
+ direction: positionToDirection((_options$position = options.position) !== null && _options$position !== void 0 ? _options$position : "right"),
11187
+ skipSetActive: (_options$skipSetActiv = options.skipSetActive) !== null && _options$skipSetActiv !== void 0 ? _options$skipSetActiv : false
11188
+ });
11189
+ this.accessor.moveGroupOrPanel({
11190
+ from: { groupId: this._group.id },
11191
+ to: {
11192
+ group,
11193
+ position: options.group ? (_options$position2 = options.position) !== null && _options$position2 !== void 0 ? _options$position2 : "center" : "center",
11194
+ index: options.index
11195
+ },
11196
+ skipSetActive: options.skipSetActive
11197
+ });
11084
11198
  });
11085
11199
  }
11086
11200
  maximize() {
@@ -11390,7 +11504,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
11390
11504
  this._group = value;
11391
11505
  this._onDidGroupChange.fire({});
11392
11506
  this.setupGroupEventListeners(oldGroup);
11393
- this._onDidLocationChange.fire({ location: this.group.api.location });
11507
+ this.fireLocationChange();
11394
11508
  }
11395
11509
  }
11396
11510
  get group() {
@@ -11429,18 +11543,20 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
11429
11543
  this.accessor.withOrigin("api", () => super.setActive());
11430
11544
  }
11431
11545
  moveTo(options) {
11432
- var _options$group, _options$position;
11433
- this.accessor.moveGroupOrPanel({
11434
- from: {
11435
- groupId: this._group.id,
11436
- panelId: this.panel.id
11437
- },
11438
- to: {
11439
- group: (_options$group = options.group) !== null && _options$group !== void 0 ? _options$group : this._group,
11440
- position: options.group ? (_options$position = options.position) !== null && _options$position !== void 0 ? _options$position : "center" : "center",
11441
- index: options.index
11442
- },
11443
- skipSetActive: options.skipSetActive
11546
+ this.accessor.withOrigin("api", () => {
11547
+ var _options$group, _options$position;
11548
+ return this.accessor.moveGroupOrPanel({
11549
+ from: {
11550
+ groupId: this._group.id,
11551
+ panelId: this.panel.id
11552
+ },
11553
+ to: {
11554
+ group: (_options$group = options.group) !== null && _options$group !== void 0 ? _options$group : this._group,
11555
+ position: options.group ? (_options$position = options.position) !== null && _options$position !== void 0 ? _options$position : "center" : "center",
11556
+ index: options.index
11557
+ },
11558
+ skipSetActive: options.skipSetActive
11559
+ });
11444
11560
  });
11445
11561
  }
11446
11562
  setTitle(title) {
@@ -11464,6 +11580,23 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
11464
11580
  exitMaximized() {
11465
11581
  this.group.api.exitMaximized();
11466
11582
  }
11583
+ /**
11584
+ * Report that this panel's location may have moved.
11585
+ *
11586
+ * A relocation touches the location more than once - the panel is
11587
+ * reparented into the destination group, then that group is tagged with
11588
+ * the location it ends up at - so the event is coalesced to the end of the
11589
+ * enclosing layout mutation and reports where the panel actually settled.
11590
+ * Firing each signal as it happened surfaced an intermediate `grid`
11591
+ * location the panel was never in, at a point where it was in neither
11592
+ * group's panel list. Outside a mutation this fires straight away.
11593
+ */
11594
+ fireLocationChange() {
11595
+ this.accessor.deferLocationChange(this, () => {
11596
+ if (this.isDisposed) return;
11597
+ this._onDidLocationChange.fire({ location: this.location });
11598
+ });
11599
+ }
11467
11600
  setupGroupEventListeners(previousGroup) {
11468
11601
  var _previousGroup$isActi;
11469
11602
  let _trackGroupActive = (_previousGroup$isActi = previousGroup === null || previousGroup === void 0 ? void 0 : previousGroup.isActive) !== null && _previousGroup$isActi !== void 0 ? _previousGroup$isActi : false;
@@ -11472,9 +11605,9 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
11472
11605
  const hasBecomeVisible = event.isVisible && !this.isVisible;
11473
11606
  const isActivePanel = this.group.model.isPanelActive(this.panel);
11474
11607
  if (hasBecomeHidden || hasBecomeVisible && isActivePanel) this._onDidVisibilityChange.fire(event);
11475
- }), this.group.api.onDidLocationChange((event) => {
11608
+ }), this.group.api.onDidLocationChange(() => {
11476
11609
  if (this.group !== this.panel.group) return;
11477
- this._onDidLocationChange.fire(event);
11610
+ this.fireLocationChange();
11478
11611
  }), this.group.api.onDidActiveChange(() => {
11479
11612
  if (this.group !== this.panel.group) return;
11480
11613
  if (_trackGroupActive !== this.isGroupActive) {
@@ -12550,12 +12683,6 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
12550
12683
  moduleName: "ContextMenu",
12551
12684
  when: (o) => o.getTabGroupChipContextMenuItems != null
12552
12685
  },
12553
- {
12554
- optionKey: "createContextMenuItemComponent",
12555
- reason: "createContextMenuItemComponent",
12556
- moduleName: "ContextMenu",
12557
- when: (o) => o.createContextMenuItemComponent != null
12558
- },
12559
12686
  {
12560
12687
  optionKey: "dndCompass",
12561
12688
  reason: "dndCompass",
@@ -13284,7 +13411,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13284
13411
  prev = next;
13285
13412
  const panel = group.activePanel;
13286
13413
  if (!panel) return;
13287
- const kind = next === "floating" ? "float" : next === "popout" ? "popout" : "dock";
13414
+ let kind;
13415
+ switch (next) {
13416
+ case "floating":
13417
+ kind = "float";
13418
+ break;
13419
+ case "popout":
13420
+ kind = "popout";
13421
+ break;
13422
+ default:
13423
+ kind = "dock";
13424
+ break;
13425
+ }
13288
13426
  this._announce(panel, kind);
13289
13427
  });
13290
13428
  this._locationSubs.set(group.id, sub);
@@ -13336,29 +13474,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13336
13474
 
13337
13475
  //#endregion
13338
13476
  //#region src/dockview/advancedDnDService.ts
13339
- /** Cursor offset of the group drag ghost, matched to the long-shipped default. */
13477
+ /** Cursor offset of the group drag ghost. */
13340
13478
  const GROUP_DRAG_GHOST_OFFSET_X = 30;
13341
13479
  const GROUP_DRAG_GHOST_OFFSET_Y = -10;
13342
13480
  /**
13343
- * The narrow surface the {@link AdvancedDnDService} needs from the host
13344
- * (the `DockviewComponent`).
13345
- *
13346
- * The `onWill*` emitters stay on the component so the public event shape is
13347
- * unchanged whether or not this module is registered; the service is only the
13348
- * dispatch point those fires are routed through. Engine policy (e.g. the
13349
- * `disableDnd` guard) stays on the component, ahead of the dispatch.
13350
- */
13351
- /**
13352
13481
  * Owns the dispatch of the advanced drag-and-drop hooks: `onWillDragPanel`,
13353
- * `onWillDragGroup`, `onWillDrop` and `onWillShowOverlay`.
13354
- *
13355
- * At this stage the service is a thin dispatcher that forwards to the host's
13356
- * emitters; the customisation surface it gates (custom drop overlays, custom
13357
- * group drag ghosts, hook veto/transform behaviour) is currently inlined in
13358
- * core and is extracted into this service in later phases. Routing the
13359
- * dispatch through a module slot is what lets that customisation layer move
13360
- * into a separately-distributed package in a future major version without
13361
- * changing the public event surface.
13482
+ * `onWillDragGroup`, `onWillDrop` and `onWillShowOverlay`, forwarding each to
13483
+ * the host's emitters so the public event shape is unchanged whether or not
13484
+ * this module is registered.
13362
13485
  *
13363
13486
  * The service holds no drag state of its own. The gesture is driven by the
13364
13487
  * DnD backends, and the per-group subscriptions live on the component's group
@@ -13484,7 +13607,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13484
13607
  //#region src/overlay/overlayRenderContainer.ts
13485
13608
  var PositionCache = class {
13486
13609
  constructor() {
13487
- this.cache = /* @__PURE__ */ new Map();
13610
+ this.cache = /* @__PURE__ */ new WeakMap();
13488
13611
  this.currentFrameId = 0;
13489
13612
  this.rafId = null;
13490
13613
  }
@@ -13510,6 +13633,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13510
13633
  });
13511
13634
  }
13512
13635
  };
13636
+ /**
13637
+ * Placeholder handle marking "a reposition frame has been requested but the
13638
+ * real handle is not known yet". Never passed to `cancelAnimationFrame` in
13639
+ * practice — it is replaced within the same synchronous block — and harmless
13640
+ * if it were, since no frame carries this id.
13641
+ */
13642
+ const SCHEDULED = -1;
13513
13643
  function createFocusableElement() {
13514
13644
  const element = document.createElement("div");
13515
13645
  element.tabIndex = -1;
@@ -13522,12 +13652,13 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13522
13652
  this.accessor = accessor;
13523
13653
  this.map = {};
13524
13654
  this._disposed = false;
13655
+ this._generation = 0;
13525
13656
  this.positionCache = new PositionCache();
13526
- this.pendingUpdates = /* @__PURE__ */ new Set();
13527
13657
  this.addDisposables(Disposable.from(() => {
13528
13658
  for (const value of Object.values(this.map)) {
13529
13659
  value.disposable.dispose();
13530
13660
  value.destroy.dispose();
13661
+ this.cancelPendingUpdate(value);
13531
13662
  }
13532
13663
  this._disposed = true;
13533
13664
  }));
@@ -13554,11 +13685,24 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13554
13685
  this.positionCache.invalidate();
13555
13686
  (_entry$resize = entry.resize) === null || _entry$resize === void 0 || _entry$resize.call(entry);
13556
13687
  }
13688
+ /**
13689
+ * Drop the reposition frame queued for a panel, if any. A queued frame is
13690
+ * bound to the reference container that was current when it was scheduled,
13691
+ * so it must be discarded whenever that container stops being the one the
13692
+ * overlay should track.
13693
+ */
13694
+ cancelPendingUpdate(entry) {
13695
+ if (entry.pendingUpdate !== void 0) {
13696
+ cancelAnimationFrame(entry.pendingUpdate);
13697
+ entry.pendingUpdate = void 0;
13698
+ }
13699
+ }
13557
13700
  detatch(panel) {
13558
13701
  if (this.map[panel.api.id]) {
13559
- const { disposable, destroy } = this.map[panel.api.id];
13560
- disposable.dispose();
13561
- destroy.dispose();
13702
+ const entry = this.map[panel.api.id];
13703
+ entry.disposable.dispose();
13704
+ entry.destroy.dispose();
13705
+ this.cancelPendingUpdate(entry);
13562
13706
  delete this.map[panel.api.id];
13563
13707
  return true;
13564
13708
  }
@@ -13574,22 +13718,73 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13574
13718
  panel,
13575
13719
  disposable: Disposable.NONE,
13576
13720
  destroy: Disposable.NONE,
13577
- element
13721
+ element,
13722
+ retainPreviousGeometry: false,
13723
+ positioned: false,
13724
+ generation: ++this._generation
13578
13725
  };
13579
13726
  }
13580
- const focusContainer = this.map[panel.api.id].element;
13727
+ const mapEntry = this.map[panel.api.id];
13728
+ /**
13729
+ * A *change* of reference container supersedes the previous `attach`:
13730
+ * take a fresh generation so its `resize` closure can no longer run,
13731
+ * and drop the frame it queued against the old container. During
13732
+ * `fromJSON({ reuseExistingPanels: true })` that old container is a
13733
+ * detached staging group measuring 0x0, so leaving its frame in flight
13734
+ * both wastes the update and delays the reposition against the real one.
13735
+ *
13736
+ * Re-attaching over the *same* container (re-open, active panel change)
13737
+ * deliberately leaves scheduled work alone: `repositionPanelOverlay`
13738
+ * (the auto-hide peek) schedules a frame carrying the sticky
13739
+ * `forceVisible`/`clip` state which `attach` does not re-apply, and a
13740
+ * peeked panel's `api.isVisible` is false — so discarding that frame
13741
+ * leaves `visibilityChanged` to hide the overlay and the peek renders
13742
+ * nothing. A newly created entry already holds a fresh generation, so
13743
+ * the stale closures a `detatch` left behind are fenced off either way.
13744
+ */
13745
+ if (mapEntry.referenceContainer !== referenceContainer) {
13746
+ mapEntry.generation = ++this._generation;
13747
+ this.cancelPendingUpdate(mapEntry);
13748
+ mapEntry.referenceContainer = referenceContainer;
13749
+ /**
13750
+ * Arm the retain flag only here: it means "a replacement reference
13751
+ * container is awaiting layout", so the 0x0 early-return below
13752
+ * holds the last good box rather than blanking the panel mid-move.
13753
+ * Arming it on every re-attach instead would make a container that
13754
+ * genuinely collapses to zero keep its stale geometry forever.
13755
+ *
13756
+ * Gated on `positioned` because an overlay that has never been
13757
+ * positioned has no left/top/width/height, and `.dv-render-overlay`
13758
+ * defaults to 100%/100% — retaining "previous" geometry there would
13759
+ * pin the content over the whole container.
13760
+ */
13761
+ mapEntry.retainPreviousGeometry = mapEntry.positioned;
13762
+ }
13763
+ const generation = mapEntry.generation;
13764
+ const focusContainer = mapEntry.element;
13581
13765
  const contentElement = panel.view.content.element;
13582
13766
  if (contentElement.parentElement !== focusContainer) focusContainer.appendChild(contentElement);
13583
13767
  if (focusContainer.parentElement !== this.element) this.element.appendChild(focusContainer);
13584
13768
  const resize = () => {
13585
13769
  const panelId = panel.api.id;
13586
- if (this.pendingUpdates.has(panelId)) return;
13587
- this.pendingUpdates.add(panelId);
13588
- requestAnimationFrame(() => {
13770
+ const scheduling = this.map[panelId];
13771
+ if ((scheduling === null || scheduling === void 0 ? void 0 : scheduling.generation) !== generation) return;
13772
+ if (scheduling.pendingUpdate !== void 0) return;
13773
+ /**
13774
+ * Claim the slot *before* scheduling. `requestAnimationFrame` is
13775
+ * shimmed to run inline by some hosts (and by several suites here),
13776
+ * in which case the callback below clears `pendingUpdate` while
13777
+ * this call is still on the stack — assigning the handle afterwards
13778
+ * would resurrect a slot that is already spent and block every
13779
+ * later reposition. The sentinel is replaced by the real handle
13780
+ * only if the frame has not already run.
13781
+ */
13782
+ scheduling.pendingUpdate = SCHEDULED;
13783
+ const handle = requestAnimationFrame(() => {
13589
13784
  var _entry$forceVisible;
13590
- this.pendingUpdates.delete(panelId);
13591
13785
  const entry = this.map[panelId];
13592
- if (this.isDisposed || !entry) return;
13786
+ if (entry) entry.pendingUpdate = void 0;
13787
+ if (this.isDisposed || (entry === null || entry === void 0 ? void 0 : entry.generation) !== generation) return;
13593
13788
  const forceVisible = (_entry$forceVisible = entry.forceVisible) !== null && _entry$forceVisible !== void 0 ? _entry$forceVisible : false;
13594
13789
  const clip = entry.clip;
13595
13790
  const box = this.positionCache.getPosition(referenceContainer.element);
@@ -13598,6 +13793,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13598
13793
  const top = box.top - box2.top;
13599
13794
  const width = box.width;
13600
13795
  const height = box.height;
13796
+ if (entry.retainPreviousGeometry && (width === 0 || height === 0)) {
13797
+ if (!panel.api.isVisible && !forceVisible) {
13798
+ focusContainer.style.visibility = "hidden";
13799
+ focusContainer.style.pointerEvents = "none";
13800
+ }
13801
+ return;
13802
+ }
13803
+ entry.retainPreviousGeometry = false;
13804
+ entry.positioned = true;
13601
13805
  focusContainer.style.left = `${left}px`;
13602
13806
  focusContainer.style.top = `${top}px`;
13603
13807
  focusContainer.style.width = `${width}px`;
@@ -13626,11 +13830,30 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13626
13830
  } else focusContainer.style.clipPath = "";
13627
13831
  toggleClass(focusContainer, "dv-render-overlay-float", panel.group.api.location.type === "floating");
13628
13832
  });
13833
+ if (scheduling.pendingUpdate === SCHEDULED) scheduling.pendingUpdate = handle;
13629
13834
  };
13630
13835
  const visibilityChanged = () => {
13631
13836
  if (panel.api.isVisible) {
13837
+ var _this$map$panel$api$i;
13632
13838
  this.positionCache.invalidate();
13633
13839
  resize();
13840
+ /**
13841
+ * Existing geometry is safe to show while its replacement lays
13842
+ * out. `retainPreviousGeometry` is only set when geometry has
13843
+ * actually been written (see `attach`), so this can never
13844
+ * un-hide an overlay whose left/top/width/height are unset —
13845
+ * `.dv-render-overlay` is 100%/100% by default and would
13846
+ * otherwise cover the whole dock.
13847
+ *
13848
+ * The retained geometry is the panel's position in the previous
13849
+ * layout, so restoring a layout that moves the panel does paint
13850
+ * it at stale coordinates until the reposition lands. That is
13851
+ * bounded to the next frame now that a superseded `attach` can
13852
+ * no longer swallow the reposition (see `attach`); showing
13853
+ * stale-but-real geometry for a frame is the deliberate
13854
+ * trade-off against blanking the panel for the whole rebuild.
13855
+ */
13856
+ 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 = "";
13634
13857
  focusContainer.style.pointerEvents = "";
13635
13858
  } else {
13636
13859
  focusContainer.style.visibility = "hidden";
@@ -13853,7 +14076,17 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
13853
14076
  window: externalWindow
13854
14077
  });
13855
14078
  return new Promise((resolve, reject) => {
13856
- externalWindow.addEventListener("unload", (e) => {});
14079
+ externalWindow.addEventListener("unload", () => {});
14080
+ /**
14081
+ * `load` is the only event that resolves this promise with a
14082
+ * container, so a window that goes away first would leave the
14083
+ * caller awaiting a promise that never settles - and
14084
+ * `addPopoutGroup` holds its layout transaction open until it does.
14085
+ * Settle with `null` on close, the same signal a blocked popup
14086
+ * gives and one the caller already handles. `resolve` after the
14087
+ * fact is a no-op, so a `load` that arrived first still wins.
14088
+ */
14089
+ disposable.addDisposables(_this.onWillClose(() => resolve(null)));
13857
14090
  externalWindow.addEventListener("load", () => {
13858
14091
  /**
13859
14092
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
@@ -15153,7 +15386,22 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15153
15386
  const rect = candidate.element.getBoundingClientRect();
15154
15387
  const dx = rect.left + rect.width / 2 - fromX;
15155
15388
  const dy = rect.top + rect.height / 2 - fromY;
15156
- if (!(direction === "left" ? dx < 0 && Math.abs(dx) >= Math.abs(dy) : direction === "right" ? dx > 0 && Math.abs(dx) >= Math.abs(dy) : direction === "up" ? dy < 0 && Math.abs(dy) >= Math.abs(dx) : dy > 0 && Math.abs(dy) >= Math.abs(dx))) continue;
15389
+ let inDirection;
15390
+ switch (direction) {
15391
+ case "left":
15392
+ inDirection = dx < 0 && Math.abs(dx) >= Math.abs(dy);
15393
+ break;
15394
+ case "right":
15395
+ inDirection = dx > 0 && Math.abs(dx) >= Math.abs(dy);
15396
+ break;
15397
+ case "up":
15398
+ inDirection = dy < 0 && Math.abs(dy) >= Math.abs(dx);
15399
+ break;
15400
+ default:
15401
+ inDirection = dy > 0 && Math.abs(dy) >= Math.abs(dx);
15402
+ break;
15403
+ }
15404
+ if (!inDirection) continue;
15157
15405
  const distance = dx * dx + dy * dy;
15158
15406
  if (distance < bestDistance) {
15159
15407
  bestDistance = distance;
@@ -15256,6 +15504,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15256
15504
  this._onWillDrop = new Emitter();
15257
15505
  this.onWillDrop = this._onWillDrop.event;
15258
15506
  this._mutationDepth = 0;
15507
+ this._pendingLocationChanges = /* @__PURE__ */ new Map();
15259
15508
  this._origin = "user";
15260
15509
  this._originDepth = 0;
15261
15510
  this._onWillMutateLayout = new Emitter();
@@ -15353,7 +15602,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15353
15602
  toggleClass(this.element, "dv-debug", !!options.debug);
15354
15603
  this.updateTheme();
15355
15604
  if (options.debug) this.addDisposables(new StrictEventsSequencing(this));
15356
- this.addDisposables(this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
15605
+ this.addDisposables(Disposable.from(() => this._pendingLocationChanges.clear()), this.rootDropTargetContainer, this.floatingDropTargetContainer, addDisposableListener(this._shellManager.element, "dragend", () => {
15357
15606
  var _this$rootDropTargetC2, _this$floatingDropTar;
15358
15607
  (_this$rootDropTargetC2 = this.rootDropTargetContainer.model) === null || _this$rootDropTargetC2 === void 0 || _this$rootDropTargetC2.clear();
15359
15608
  (_this$floatingDropTar = this.floatingDropTargetContainer.model) === null || _this$floatingDropTar === void 0 || _this$floatingDropTar.clear();
@@ -15427,7 +15676,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15427
15676
  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;
15428
15677
  }
15429
15678
  addPopoutGroup(itemToPopout, options) {
15430
- return this.mutation("popout", () => this._doAddPopoutGroup(itemToPopout, options));
15679
+ return this.mutationAsync("popout", () => this._doAddPopoutGroup(itemToPopout, options));
15431
15680
  }
15432
15681
  /** Enumerate the popout groups currently open in their own windows. */
15433
15682
  getPopouts() {
@@ -15524,15 +15773,32 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15524
15773
  }
15525
15774
  };
15526
15775
  let floatingBox;
15527
- if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) && isGroupAddedToDom) if (itemToPopout instanceof DockviewPanel) this.movingLock(() => {
15528
- const panel = referenceGroup.model.removePanel(itemToPopout);
15529
- group.model.openPanel(panel);
15530
- });
15531
- else {
15776
+ /**
15777
+ * Popping out rehomes panels into `group`, so like the floating
15778
+ * case it owes the caller an `onDidMovePanel` per panel. The
15779
+ * events are deferred until the window is wired up so listeners
15780
+ * observe the panels' final `popout` location.
15781
+ */
15782
+ let movedPanels = [];
15783
+ if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) && isGroupAddedToDom) if (itemToPopout instanceof DockviewPanel) {
15784
+ const sourceGroup = itemToPopout.group;
15785
+ this.movingLock(() => {
15786
+ const panel = referenceGroup.model.removePanel(itemToPopout);
15787
+ group.model.openPanel(panel);
15788
+ });
15789
+ movedPanels = [{
15790
+ panel: itemToPopout,
15791
+ from: sourceGroup
15792
+ }];
15793
+ } else {
15532
15794
  this.movingLock(() => moveGroupWithoutDestroying({
15533
15795
  from: referenceGroup,
15534
15796
  to: group
15535
15797
  }));
15798
+ movedPanels = group.panels.map((panel) => ({
15799
+ panel,
15800
+ from: referenceGroup
15801
+ }));
15536
15802
  switch (referenceLocation) {
15537
15803
  case "grid":
15538
15804
  referenceGroup.api.setVisible(false);
@@ -15641,6 +15907,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15641
15907
  group: value.popoutGroup,
15642
15908
  window: value.getWindow()
15643
15909
  });
15910
+ for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
15644
15911
  return true;
15645
15912
  }).catch((err) => {
15646
15913
  console.error("dockview: failed to create popout.", err);
@@ -15718,6 +15985,16 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15718
15985
  const members = this.groups.filter((candidate) => popoutGridview.element.contains(candidate.element));
15719
15986
  const anchorPresent = members.includes(group);
15720
15987
  const anchorIsSoleMember = anchorPresent && members.length === 1;
15988
+ /**
15989
+ * Popping a group out fires `onDidMovePanel` per panel, so closing the
15990
+ * window owes the caller the same: every panel in it is rehomed, into
15991
+ * the reference group the popout left behind or into a fresh grid slot.
15992
+ * `movingLock` suppresses onDidAddPanel / onDidRemovePanel on these
15993
+ * paths, so `onDidMovePanel` is the only event that can carry it. The
15994
+ * events are deferred to the end so listeners observe the panels at
15995
+ * their final group and location.
15996
+ */
15997
+ const movedPanels = [];
15721
15998
  if (genuineClose) for (const member of members) {
15722
15999
  if (member === group) continue;
15723
16000
  this.movingLock(() => {
@@ -15728,12 +16005,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15728
16005
  });
15729
16006
  this.redockGroupToMainGrid(member);
15730
16007
  });
16008
+ for (const panel of member.panels) movedPanels.push({
16009
+ panel,
16010
+ from: member
16011
+ });
15731
16012
  }
15732
16013
  if (anchorPresent && isGroupAddedToDom && this.getPanel(referenceGroup.id)) {
16014
+ const rehomed = [...group.panels];
15733
16015
  this.movingLock(() => moveGroupWithoutDestroying({
15734
16016
  from: group,
15735
16017
  to: referenceGroup
15736
16018
  }));
16019
+ for (const panel of rehomed) movedPanels.push({
16020
+ panel,
16021
+ from: group
16022
+ });
15737
16023
  if (!referenceGroup.api.isVisible) referenceGroup.api.setVisible(true);
15738
16024
  if (this.getPanel(group.id)) this.doRemoveGroup(group, { skipPopoutAssociated: true });
15739
16025
  } else if (anchorPresent && this.getPanel(group.id)) {
@@ -15764,10 +16050,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15764
16050
  this.movingLock(() => {
15765
16051
  this.doAddGroup(group, [0]);
15766
16052
  });
16053
+ for (const panel of group.panels) movedPanels.push({
16054
+ panel,
16055
+ from: group
16056
+ });
15767
16057
  }
15768
16058
  this.doSetGroupAndPanelActive(group);
15769
16059
  }
15770
16060
  disposePopoutGridview();
16061
+ for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
15771
16062
  }
15772
16063
  addFloatingGroup(item, options) {
15773
16064
  this.mutation("float", () => this._doAddFloatingGroup(item, options));
@@ -15776,7 +16067,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15776
16067
  if (!assertModule(this._floatingGroupService, "FloatingGroup", "api.addFloatingGroup")) return;
15777
16068
  if (item instanceof DockviewGroupPanel && item.model.location.type === "edge") return;
15778
16069
  let group;
16070
+ /**
16071
+ * Floating relocates panels exactly like a drop onto the grid does, so
16072
+ * it owes the caller an `onDidMovePanel` per panel. The events are
16073
+ * deferred until the window is mounted below: only then do the panels
16074
+ * report their final `floating` location.
16075
+ */
16076
+ let movedPanels = [];
15779
16077
  if (item instanceof DockviewPanel) {
16078
+ const sourceGroup = item.group;
15780
16079
  group = this.createGroup();
15781
16080
  this._onDidAddGroup.fire(group);
15782
16081
  this.movingLock(() => this.removePanel(item, {
@@ -15785,6 +16084,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15785
16084
  skipSetActiveGroup: true
15786
16085
  }));
15787
16086
  this.movingLock(() => group.model.openPanel(item, { skipSetGroupActive: true }));
16087
+ movedPanels = [{
16088
+ panel: item,
16089
+ from: sourceGroup
16090
+ }];
15788
16091
  } else {
15789
16092
  var _this$_popoutWindowSe8;
15790
16093
  group = item;
@@ -15801,11 +16104,21 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15801
16104
  });
15802
16105
  this.doRemoveGroup(popoutReferenceGroup, { skipDispose: true });
15803
16106
  group = popoutReferenceGroup;
15804
- } else this.doRemoveGroup(item, {
15805
- skipDispose: true,
15806
- skipPopoutReturn: true,
15807
- skipPopoutAssociated: false
15808
- });
16107
+ movedPanels = group.panels.map((panel) => ({
16108
+ panel,
16109
+ from: item
16110
+ }));
16111
+ } else {
16112
+ this.doRemoveGroup(item, {
16113
+ skipDispose: true,
16114
+ skipPopoutReturn: true,
16115
+ skipPopoutAssociated: false
16116
+ });
16117
+ movedPanels = group.panels.map((panel) => ({
16118
+ panel,
16119
+ from: group
16120
+ }));
16121
+ }
15809
16122
  }
15810
16123
  function getAnchoredBox() {
15811
16124
  if (options === null || options === void 0 ? void 0 : options.position) {
@@ -15838,6 +16151,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
15838
16151
  skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
15839
16152
  disableSmartGuides: options === null || options === void 0 ? void 0 : options.disableSmartGuides
15840
16153
  });
16154
+ for (const { panel, from } of movedPanels) this.fireDidMovePanel(panel, from);
15841
16155
  }
15842
16156
  /**
15843
16157
  * Build an empty gridview configured to match the main grid's styling, for
@@ -16001,11 +16315,15 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16001
16315
  /**
16002
16316
  * Reveal (create-or-fill) the edge group at `position` and move the dragged
16003
16317
  * item described by `data` into it. A newly created edge group is created
16004
- * collapsed and flagged `autoReveal` so it tears down to zero footprint when
16005
- * later emptied. If an edge group already exists there it is reused: the
16006
- * panel is added to its tabs and its collapsed/toggled state is left as-is
16007
- * (never re-created; `addEdgeGroup` throws on a duplicate position). No-op if
16008
- * the EdgeGroup module is absent.
16318
+ * collapsed, flagged `autoReveal` so it tears down to zero footprint when
16319
+ * later emptied, and takes its auto-hide state from `options.autoHide`. If an
16320
+ * edge group already exists there it is reused: the panel is added to its
16321
+ * tabs and its collapsed/toggled *and auto-hide* state are left as-is (never
16322
+ * re-created; `addEdgeGroup` throws on a duplicate position). This keeps a
16323
+ * drag-reveal from silently converting a static edge group into an
16324
+ * auto-hiding one; to change an existing group's auto-hide, call
16325
+ * `api.getEdgeGroup(position)?.setAutoHide(...)` directly. No-op if the
16326
+ * EdgeGroup module is absent.
16009
16327
  *
16010
16328
  * This is the primitive behind the dock-to-edge groups: the two-band
16011
16329
  * drag-reveal affordance routes its outer-band drops here.
@@ -16024,7 +16342,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16024
16342
  collapsed: true
16025
16343
  });
16026
16344
  group = service.get(position);
16027
- } else if ((options === null || options === void 0 ? void 0 : options.autoHide) !== void 0) this.setEdgeGroupAutoHide(group, options.autoHide);
16345
+ }
16028
16346
  if (!group) return;
16029
16347
  this.moveGroupOrPanel({
16030
16348
  from: {
@@ -16265,35 +16583,119 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16265
16583
  if (typeof data !== "object" || data === null) throw new Error("dockview: serialized layout must be a non-null object");
16266
16584
  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");
16267
16585
  const existingPanels = /* @__PURE__ */ new Map();
16268
- let tempGroup;
16586
+ const temporaryGroups = /* @__PURE__ */ new Map();
16587
+ const stagedPanels = [];
16588
+ const temporaryGroupDisposables = [];
16589
+ /**
16590
+ * The staging groups are detached from `_groups` and never enter the
16591
+ * grid, so nothing else will ever tear them down.
16592
+ *
16593
+ * `dispose()` reaches consumer `IContentRenderer.dispose()`, so one
16594
+ * throwing renderer must not abort the rest of the cleanup — that would
16595
+ * re-introduce the very leak this reclaims — nor replace the
16596
+ * deserialization error the caller is being given. Draining the list
16597
+ * also makes this safe to call more than once.
16598
+ */
16599
+ const disposeTemporaryGroups = () => {
16600
+ for (const disposable of temporaryGroupDisposables) try {
16601
+ disposable.dispose();
16602
+ } catch (err) {
16603
+ console.error("dockview: failed to dispose a temporary group created for reuseExistingPanels", err);
16604
+ }
16605
+ temporaryGroupDisposables.length = 0;
16606
+ };
16269
16607
  if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
16270
16608
  /**
16271
- * What are we doing here?
16272
- *
16273
- * 1. Create a temporary group to hold any panels that currently exist and that also exist in the new layout
16274
- * 2. Remove that temporary group from the group mapping so that it doesn't get cleared when we clear the layout
16609
+ * Visible, always-rendered panels need individual staging groups
16610
+ * to remain active. Other reused panels can share a staging group.
16611
+ * The staging groups are excluded from the layout clear below.
16275
16612
  */
16276
- tempGroup = this.createGroup();
16277
- this._groups.delete(tempGroup.api.id);
16278
16613
  const newPanels = Object.keys(data.panels);
16279
- for (const panel of this.panels) if (newPanels.includes(panel.api.id)) existingPanels.set(panel.api.id, panel);
16280
- this.movingLock(() => {
16281
- Array.from(existingPanels.values()).forEach((panel) => {
16282
- this.moveGroupOrPanel({
16283
- from: {
16284
- groupId: panel.api.group.api.id,
16285
- panelId: panel.api.id
16286
- },
16287
- to: {
16288
- group: tempGroup,
16289
- position: "center"
16290
- },
16291
- keepEmptyGroups: true
16614
+ let sharedTemporaryGroup;
16615
+ const createTemporaryGroup = () => {
16616
+ const temporaryGroup = this.createGroup();
16617
+ /**
16618
+ * Removing the group from `_groups` also drops the record's
16619
+ * `CompositeDisposable`, so capture it first and tear both it
16620
+ * and the group down in the `finally` below. Left undisposed a
16621
+ * staging group leaks its `ResizeObserver`, its
16622
+ * `onDidOptionsChange` subscription (retained by this
16623
+ * component's emitter) and the watermark its model mounts when
16624
+ * the group empties — once per reused panel, per `fromJSON`.
16625
+ */
16626
+ const record = this._groups.get(temporaryGroup.api.id);
16627
+ this._groups.delete(temporaryGroup.api.id);
16628
+ temporaryGroupDisposables.push(Disposable.from(() => {
16629
+ /**
16630
+ * Reclaim the group's own resources, never its panels.
16631
+ * Staging is driven by the ids in `data.panels` while
16632
+ * reclaiming is driven by the group `views` that
16633
+ * reference them, so a panel whose state is present but
16634
+ * unreferenced is still staged here — and `dispose()`
16635
+ * on a non-empty group reaches the consumer's
16636
+ * `IContentRenderer.dispose()`. Emptying the group
16637
+ * first leaves those panels exactly as they were before
16638
+ * this teardown existed, which also keeps this safe
16639
+ * against any future path that rebuilds a panel under
16640
+ * an id that is live in the new layout.
16641
+ */
16642
+ this.movingLock(() => {
16643
+ for (const panel of temporaryGroup.panels.slice()) temporaryGroup.model.removePanel(panel);
16644
+ });
16645
+ record === null || record === void 0 || record.disposable.dispose();
16646
+ temporaryGroup.dispose();
16647
+ }));
16648
+ return temporaryGroup;
16649
+ };
16650
+ /**
16651
+ * Staging and the clear below run before the deserialization
16652
+ * `try`, so a throw here (a consumer `onDidRemovePanel` handler, a
16653
+ * renderer teardown during `clear`) would escape without reclaiming
16654
+ * the staging groups already created.
16655
+ *
16656
+ * The creation loop is inside the guard too, not just the moves and
16657
+ * the clear: `createGroup()` reaches consumer code of its own —
16658
+ * `initialize()` mounts the watermark through
16659
+ * `createWatermarkComponent()` — so a throw on the n-th panel would
16660
+ * otherwise strand the n-1 staging groups already built.
16661
+ */
16662
+ try {
16663
+ for (const panel of this.panels) if (newPanels.includes(panel.api.id)) {
16664
+ existingPanels.set(panel.api.id, panel);
16665
+ let temporaryGroup;
16666
+ if (panel.api.renderer === "always" && panel.api.isVisible) temporaryGroup = createTemporaryGroup();
16667
+ else {
16668
+ var _sharedTemporaryGroup;
16669
+ (_sharedTemporaryGroup = sharedTemporaryGroup) !== null && _sharedTemporaryGroup !== void 0 || (sharedTemporaryGroup = createTemporaryGroup());
16670
+ temporaryGroup = sharedTemporaryGroup;
16671
+ }
16672
+ temporaryGroups.set(panel.api.id, temporaryGroup);
16673
+ stagedPanels.push({
16674
+ panel,
16675
+ temporaryGroup
16676
+ });
16677
+ }
16678
+ this.movingLock(() => {
16679
+ stagedPanels.forEach(({ panel, temporaryGroup }) => {
16680
+ this.moveGroupOrPanel({
16681
+ from: {
16682
+ groupId: panel.api.group.api.id,
16683
+ panelId: panel.api.id
16684
+ },
16685
+ to: {
16686
+ group: temporaryGroup,
16687
+ position: "center"
16688
+ },
16689
+ keepEmptyGroups: true
16690
+ });
16292
16691
  });
16293
16692
  });
16294
- });
16295
- }
16296
- this.clear();
16693
+ this.clear();
16694
+ } catch (err) {
16695
+ disposeTemporaryGroups();
16696
+ throw err;
16697
+ }
16698
+ } else this.clear();
16297
16699
  const { grid, panels, activeGroup } = data;
16298
16700
  try {
16299
16701
  var _data$floatingGroups, _data$popoutGroups, _this$_popoutWindowSe12, _this$_floatingGroupS5, _this$_watermarkServi2;
@@ -16325,9 +16727,10 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16325
16727
  * due to a corruption of input data.
16326
16728
  */
16327
16729
  const existingPanel = existingPanels.get(child);
16328
- if (tempGroup && existingPanel) {
16730
+ const temporaryGroup = temporaryGroups.get(child);
16731
+ if (temporaryGroup && existingPanel) {
16329
16732
  this.movingLock(() => {
16330
- tempGroup.model.removePanel(existingPanel);
16733
+ temporaryGroup.model.removePanel(existingPanel);
16331
16734
  });
16332
16735
  createdPanels.push(existingPanel);
16333
16736
  existingPanel.updateFromStateModel(panels[child]);
@@ -16357,7 +16760,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16357
16760
  return createGroupFromSerializedState(node.data);
16358
16761
  } });
16359
16762
  this._layoutFromShell(width, height);
16360
- if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels);
16763
+ if (data.edgeGroups) this.deserializeEdgeGroups(data.edgeGroups, panels, existingPanels, temporaryGroups);
16361
16764
  this.deserializeFloatingWindows((_data$floatingGroups = data.floatingGroups) !== null && _data$floatingGroups !== void 0 ? _data$floatingGroups : [], createGroupFromSerializedState);
16362
16765
  const popoutPromises = this.deserializePopoutWindows((_data$popoutGroups = data.popoutGroups) !== null && _data$popoutGroups !== void 0 ? _data$popoutGroups : [], createGroupFromSerializedState);
16363
16766
  (_this$_popoutWindowSe12 = this._popoutWindowService) === null || _this$_popoutWindowSe12 === void 0 || _this$_popoutWindowSe12.finishRestoration(popoutPromises);
@@ -16394,6 +16797,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16394
16797
  * expect trying to load a corrupted layout to result in an error and not silently fail...
16395
16798
  */
16396
16799
  throw err;
16800
+ } finally {
16801
+ disposeTemporaryGroups();
16397
16802
  }
16398
16803
  this.debouncedUpdateAllPositions();
16399
16804
  this._onDidLayoutFromJSON.fire();
@@ -16416,7 +16821,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16416
16821
  members
16417
16822
  };
16418
16823
  }
16419
- deserializeEdgeGroups(edgeGroups, panels) {
16824
+ deserializeEdgeGroups(edgeGroups, panels, existingPanels, temporaryGroups) {
16420
16825
  const edgeService = assertModule(this._edgeGroupService, "EdgeGroup", "fromJSON edge restoration");
16421
16826
  if (!edgeService) return;
16422
16827
  for (const _position of [
@@ -16446,13 +16851,40 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16446
16851
  if (groupState) {
16447
16852
  const { views, activeView } = groupState;
16448
16853
  const createdPanels = [];
16449
- for (const panelId of views) if (panels[panelId]) {
16450
- const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
16451
- createdPanels.push(panel);
16854
+ for (const panelId of views) {
16855
+ if (!panels[panelId]) continue;
16856
+ /**
16857
+ * Reclaim a staged panel rather than rebuilding it, the
16858
+ * same way the grid path does. Deserializing here instead
16859
+ * would honour `reuseExistingPanels` everywhere except edge
16860
+ * groups: the live panel keeps sitting in its staging group
16861
+ * while a second panel is built under the same id, so the
16862
+ * consumer's renderer for the original is orphaned — never
16863
+ * disposed, and its element left inside the id-keyed
16864
+ * overlay entry the replacement now shares.
16865
+ */
16866
+ const existingPanel = existingPanels.get(panelId);
16867
+ const temporaryGroup = temporaryGroups.get(panelId);
16868
+ if (temporaryGroup && existingPanel) {
16869
+ this.movingLock(() => {
16870
+ temporaryGroup.model.removePanel(existingPanel);
16871
+ });
16872
+ createdPanels.push(existingPanel);
16873
+ existingPanel.updateFromStateModel(panels[panelId]);
16874
+ } else {
16875
+ const panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
16876
+ createdPanels.push(panel);
16877
+ }
16452
16878
  }
16453
16879
  for (const panel of createdPanels) {
16454
16880
  const isActive = activeView === panel.id;
16455
- edgeGroup.model.openPanel(panel, {
16881
+ if (existingPanels.has(panel.api.id)) this.movingLock(() => {
16882
+ edgeGroup.model.openPanel(panel, {
16883
+ skipSetActive: !isActive,
16884
+ skipSetGroupActive: true
16885
+ });
16886
+ });
16887
+ else edgeGroup.model.openPanel(panel, {
16456
16888
  skipSetActive: !isActive,
16457
16889
  skipSetGroupActive: true
16458
16890
  });
@@ -16555,6 +16987,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16555
16987
  height: options.initialHeight
16556
16988
  };
16557
16989
  let index;
16990
+ const shouldSkipSetActive = (group) => !!options.inactive && group.model.size > 0;
16558
16991
  if (options.position) if (isPanelOptionsWithPanel(options.position)) {
16559
16992
  const referencePanel = typeof options.position.referencePanel === "string" ? this.getGroupPanel(options.position.referencePanel) : options.position.referencePanel;
16560
16993
  index = options.position.index;
@@ -16577,7 +17010,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16577
17010
  const group = this.orthogonalize(directionToPosition(options.position.direction));
16578
17011
  const panel = this.createPanel(options, group);
16579
17012
  group.model.openPanel(panel, {
16580
- skipSetActive: options.inactive,
17013
+ skipSetActive: shouldSkipSetActive(group),
16581
17014
  skipSetGroupActive: options.inactive,
16582
17015
  index
16583
17016
  });
@@ -16604,14 +17037,14 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16604
17037
  }));
16605
17038
  panel = this.createPanel(options, group);
16606
17039
  group.model.openPanel(panel, {
16607
- skipSetActive: options.inactive,
17040
+ skipSetActive: shouldSkipSetActive(group),
16608
17041
  skipSetGroupActive: options.inactive,
16609
17042
  index
16610
17043
  });
16611
17044
  } else if (referenceGroup.api.location.type === "floating" || referenceGroup.api.location.type === "edge" || target === "center") {
16612
17045
  panel = this.createPanel(options, referenceGroup);
16613
17046
  referenceGroup.model.openPanel(panel, {
16614
- skipSetActive: options.inactive,
17047
+ skipSetActive: shouldSkipSetActive(referenceGroup),
16615
17048
  skipSetGroupActive: options.inactive,
16616
17049
  index
16617
17050
  });
@@ -16626,7 +17059,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16626
17059
  const group = this.createGroupAtLocation(relativeLocation, this.orientationAtLocation(relativeLocation) === "VERTICAL" ? initial === null || initial === void 0 ? void 0 : initial.height : initial === null || initial === void 0 ? void 0 : initial.width);
16627
17060
  panel = this.createPanel(options, group);
16628
17061
  group.model.openPanel(panel, {
16629
- skipSetActive: options.inactive,
17062
+ skipSetActive: shouldSkipSetActive(group),
16630
17063
  skipSetGroupActive: options.inactive,
16631
17064
  index
16632
17065
  });
@@ -16643,7 +17076,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16643
17076
  }));
16644
17077
  panel = this.createPanel(options, group);
16645
17078
  group.model.openPanel(panel, {
16646
- skipSetActive: options.inactive,
17079
+ skipSetActive: shouldSkipSetActive(group),
16647
17080
  skipSetGroupActive: options.inactive,
16648
17081
  index
16649
17082
  });
@@ -16651,7 +17084,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16651
17084
  const group = this.createGroupAtLocation([0], this.gridview.orientation === "VERTICAL" ? initial === null || initial === void 0 ? void 0 : initial.height : initial === null || initial === void 0 ? void 0 : initial.width);
16652
17085
  panel = this.createPanel(options, group);
16653
17086
  group.model.openPanel(panel, {
16654
- skipSetActive: options.inactive,
17087
+ skipSetActive: shouldSkipSetActive(group),
16655
17088
  skipSetGroupActive: options.inactive,
16656
17089
  index
16657
17090
  });
@@ -16875,22 +17308,100 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16875
17308
  * outermost mutation.
16876
17309
  */
16877
17310
  mutation(kind, func) {
16878
- const outer = this._mutationDepth === 0;
17311
+ const close = this.openMutation(kind);
17312
+ try {
17313
+ return func();
17314
+ } finally {
17315
+ close();
17316
+ }
17317
+ }
17318
+ /**
17319
+ * `mutation()` for an operation whose work continues after the synchronous
17320
+ * call returns. The transaction stays open until the returned promise
17321
+ * settles, so everything the operation does - the group it adds, the panels
17322
+ * it relocates - lands inside the bracket, matching the synchronous
17323
+ * move / float paths.
17324
+ */
17325
+ mutationAsync(kind, func) {
17326
+ var _this = this;
17327
+ return _asyncToGenerator(function* () {
17328
+ const close = _this.openMutation(kind);
17329
+ try {
17330
+ return yield func();
17331
+ } finally {
17332
+ close();
17333
+ }
17334
+ })();
17335
+ }
17336
+ /**
17337
+ * Open a transaction and return the function that closes it. Shared by the
17338
+ * synchronous and asynchronous brackets; the returned function must be
17339
+ * called exactly once.
17340
+ *
17341
+ * Both ends key off the depth counter reaching zero rather than off which
17342
+ * bracket opened first. For synchronous nesting the two are the same thing
17343
+ * - brackets close in the order they opened - but asynchronous transactions
17344
+ * can *overlap* rather than nest (two `addPopoutGroup` calls in flight at
17345
+ * once, or a restore staggering several), and there the first to open is
17346
+ * not the last to close. Reporting on the opener would fire `didMutate`
17347
+ * while the other transaction was still doing structural work, which is the
17348
+ * very thing the async bracket exists to prevent. Overlapping transactions
17349
+ * therefore report as one, tagged with the kind of the last to finish.
17350
+ */
17351
+ openMutation(kind) {
16879
17352
  const origin = this._origin;
16880
- if (outer) this._onWillMutateLayout.fire({
17353
+ if (this._mutationDepth === 0) this._onWillMutateLayout.fire({
16881
17354
  kind,
16882
17355
  origin
16883
17356
  });
16884
17357
  this._mutationDepth++;
16885
- try {
16886
- return func();
16887
- } finally {
17358
+ return () => {
16888
17359
  this._mutationDepth--;
16889
- if (outer) this._onDidMutateLayout.fire({
16890
- kind,
16891
- origin
16892
- });
17360
+ if (this._mutationDepth === 0) {
17361
+ this.flushLocationChanges();
17362
+ this._onDidMutateLayout.fire({
17363
+ kind,
17364
+ origin
17365
+ });
17366
+ }
17367
+ };
17368
+ }
17369
+ /**
17370
+ * Coalesce a panel's `onDidLocationChange` to the end of the enclosing
17371
+ * transaction, or fire it immediately when no transaction is in flight.
17372
+ *
17373
+ * Relocating a panel touches its location twice: once as it is reparented
17374
+ * into the destination group - which, when that group has just been created
17375
+ * for a floating or popout window, has not been told where it lives yet -
17376
+ * and once as the group is tagged with its final location. Reporting each
17377
+ * signal as it happens therefore leaks an intermediate `grid` location the
17378
+ * panel was never in, at a moment when it belongs to neither group's panel
17379
+ * list and so is missing from `api.panels`.
17380
+ *
17381
+ * Deferring collapses those signals into a single event carrying the
17382
+ * settled location. Note the signals are deliberately *not* compared
17383
+ * against the panel's previous location: a panel can move between two
17384
+ * floating windows without its location type changing, and this event is
17385
+ * the only signal `OverlayRenderContainer` has to re-resolve the panel's
17386
+ * z-index against its new host window.
17387
+ */
17388
+ deferLocationChange(key, fire) {
17389
+ if (this._mutationDepth === 0) {
17390
+ fire();
17391
+ return;
16893
17392
  }
17393
+ this._pendingLocationChanges.set(key, fire);
17394
+ }
17395
+ /**
17396
+ * Report every panel whose location moved during the transaction that has
17397
+ * just closed. Each callback reads the panel's location at this point, so
17398
+ * what it reports is where the panel ended up.
17399
+ */
17400
+ flushLocationChanges() {
17401
+ if (this._pendingLocationChanges.size === 0) return;
17402
+ const pending = Array.from(this._pendingLocationChanges.values());
17403
+ this._pendingLocationChanges.clear();
17404
+ for (const fire of pending) fire();
16894
17405
  }
16895
17406
  /**
16896
17407
  * The origin of the operation currently in progress (`'user'` by default).
@@ -16931,6 +17442,18 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16931
17442
  origin: this._origin
16932
17443
  });
16933
17444
  }
17445
+ /**
17446
+ * Announce that `panel` has finished relocating. Must be called once the
17447
+ * move has settled: `to` is read from the panel's current group, so an
17448
+ * early call would report the source group as the destination.
17449
+ */
17450
+ fireDidMovePanel(panel, from) {
17451
+ this._onDidMovePanel.fire({
17452
+ panel,
17453
+ from,
17454
+ to: panel.group
17455
+ });
17456
+ }
16934
17457
  moveGroupOrPanel(options) {
16935
17458
  this.mutation("move", () => this._doMoveGroupOrPanel(options));
16936
17459
  }
@@ -16991,10 +17514,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
16991
17514
  });
16992
17515
  });
16993
17516
  if (!options.skipSetActive) this.doSetGroupAndPanelActive(destinationGroup);
16994
- this._onDidMovePanel.fire({
16995
- panel: removedPanel,
16996
- from: sourceGroup
16997
- });
17517
+ this.fireDidMovePanel(removedPanel, sourceGroup);
16998
17518
  } else {
16999
17519
  /**
17000
17520
  * Dropping a panel to the extremities of a group which will place that panel
@@ -17013,10 +17533,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17013
17533
  const [sourceParentLocation, from] = tail(getGridLocation(sourceGroup.element));
17014
17534
  if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
17015
17535
  this.gridview.moveView(sourceParentLocation, from, to);
17016
- this._onDidMovePanel.fire({
17017
- panel: this.getGroupPanel(sourceItemId),
17018
- from: sourceGroup
17019
- });
17536
+ this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
17020
17537
  return;
17021
17538
  }
17022
17539
  }
@@ -17047,10 +17564,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17047
17564
  const newGroup = this.createGroupAtLocation(updatedTargetLocation, void 0, void 0, destinationGridview);
17048
17565
  this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetActive: true }));
17049
17566
  this.doSetGroupAndPanelActive(newGroup);
17050
- this._onDidMovePanel.fire({
17051
- panel: this.getGroupPanel(sourceItemId),
17052
- from: sourceGroup
17053
- });
17567
+ this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
17054
17568
  return;
17055
17569
  }
17056
17570
  if (sourceGroup.api.location.type === "edge") {
@@ -17067,10 +17581,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17067
17581
  const newGroup = this.createGroupAtLocation(targetLocation, void 0, void 0, destinationGridview);
17068
17582
  this.movingLock(() => newGroup.model.openPanel(removedPanel, { skipSetGroupActive: true }));
17069
17583
  this.doSetGroupAndPanelActive(newGroup);
17070
- this._onDidMovePanel.fire({
17071
- panel: removedPanel,
17072
- from: sourceGroup
17073
- });
17584
+ this.fireDidMovePanel(removedPanel, sourceGroup);
17074
17585
  return;
17075
17586
  }
17076
17587
  const targetGroup = this.movingLock(() => this.doRemoveGroup(sourceGroup, {
@@ -17082,10 +17593,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17082
17593
  this.movingLock(() => this.doAddGroup(targetGroup, location, void 0, destinationGridview));
17083
17594
  this.setGroupLocationForRoot(targetGroup, destinationGridview);
17084
17595
  this.doSetGroupAndPanelActive(targetGroup);
17085
- this._onDidMovePanel.fire({
17086
- panel: this.getGroupPanel(sourceItemId),
17087
- from: sourceGroup
17088
- });
17596
+ this.fireDidMovePanel(this.getGroupPanel(sourceItemId), sourceGroup);
17089
17597
  } else {
17090
17598
  /**
17091
17599
  * The group we are removing from has many panels, we need to remove the panels we are moving,
@@ -17100,10 +17608,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17100
17608
  const group = this.createGroupAtLocation(dropLocation, void 0, void 0, destinationGridview);
17101
17609
  this.movingLock(() => group.model.openPanel(removedPanel, { skipSetGroupActive: true }));
17102
17610
  this.doSetGroupAndPanelActive(group);
17103
- this._onDidMovePanel.fire({
17104
- panel: removedPanel,
17105
- from: sourceGroup
17106
- });
17611
+ this.fireDidMovePanel(removedPanel, sourceGroup);
17107
17612
  }
17108
17613
  }
17109
17614
  }
@@ -17138,10 +17643,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17138
17643
  });
17139
17644
  for (const panel of removedPanels) targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
17140
17645
  if (!options.skipSetActive) this.doSetGroupAndPanelActive(targetGroup);
17141
- for (const panel of removedPanels) this._onDidMovePanel.fire({
17142
- panel,
17143
- from: sourceGroup
17144
- });
17646
+ for (const panel of removedPanels) this.fireDidMovePanel(panel, sourceGroup);
17145
17647
  };
17146
17648
  let targetGroup;
17147
17649
  if (!destinationTarget || destinationTarget === "center" || !referenceLocation) targetGroup = destinationGroup;
@@ -17162,10 +17664,12 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17162
17664
  this.mutation("maximize", () => super.exitMaximizedGroup());
17163
17665
  }
17164
17666
  _doMoveGroup(options) {
17667
+ var _mergedPanels;
17165
17668
  const from = options.from.group;
17166
17669
  const to = options.to.group;
17167
17670
  const target = options.to.position;
17168
17671
  let source = from;
17672
+ let mergedPanels;
17169
17673
  if (target === "center") {
17170
17674
  const activePanel = from.activePanel;
17171
17675
  const tabGroupSnapshots = from.model.getTabGroups().map((tg) => ({
@@ -17183,6 +17687,7 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17183
17687
  skipSetGroupActive: true
17184
17688
  });
17185
17689
  });
17690
+ mergedPanels = panels;
17186
17691
  for (const snapshot of tabGroupSnapshots) {
17187
17692
  const newTabGroup = to.model.createTabGroup({
17188
17693
  label: snapshot.label,
@@ -17272,11 +17777,8 @@ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toString
17272
17777
  this.setGroupLocationForRoot(source, destGridview);
17273
17778
  }
17274
17779
  }
17275
- source.panels.forEach((panel) => {
17276
- this._onDidMovePanel.fire({
17277
- panel,
17278
- from
17279
- });
17780
+ ((_mergedPanels = mergedPanels) !== null && _mergedPanels !== void 0 ? _mergedPanels : source.panels).forEach((panel) => {
17781
+ this.fireDidMovePanel(panel, from);
17280
17782
  });
17281
17783
  this.debouncedUpdateAllPositions();
17282
17784
  if (options.skipSetActive === false) {