dockview-core 6.2.1 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/cjs/api/dockviewGroupPanelApi.d.ts +10 -1
  2. package/dist/cjs/api/dockviewGroupPanelApi.js +16 -0
  3. package/dist/cjs/dnd/groupDragHandler.js +34 -12
  4. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +2 -2
  5. package/dist/cjs/dockview/components/titlebar/tabs.js +9 -2
  6. package/dist/cjs/dockview/components/titlebar/voidContainer.js +6 -0
  7. package/dist/cjs/dockview/dockviewComponent.d.ts +1 -0
  8. package/dist/cjs/dockview/dockviewComponent.js +187 -125
  9. package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +1 -0
  10. package/dist/cjs/dockview/dockviewGroupPanelModel.js +9 -0
  11. package/dist/cjs/dockview/dockviewPanel.js +5 -0
  12. package/dist/cjs/dockview/dockviewPanelModel.d.ts +2 -0
  13. package/dist/cjs/dockview/dockviewPanelModel.js +8 -0
  14. package/dist/cjs/dockview/framework.d.ts +8 -0
  15. package/dist/cjs/dockview/options.d.ts +13 -2
  16. package/dist/cjs/dockview/options.js +2 -0
  17. package/dist/cjs/dom.d.ts +5 -1
  18. package/dist/cjs/dom.js +14 -2
  19. package/dist/cjs/index.d.ts +1 -1
  20. package/dist/cjs/overlay/overlayRenderContainer.js +13 -3
  21. package/dist/cjs/popoutWindow.d.ts +2 -0
  22. package/dist/cjs/popoutWindow.js +3 -1
  23. package/dist/dockview-core.js +169 -30
  24. package/dist/dockview-core.min.js +2 -2
  25. package/dist/dockview-core.min.js.map +1 -1
  26. package/dist/dockview-core.min.noStyle.js +2 -2
  27. package/dist/dockview-core.min.noStyle.js.map +1 -1
  28. package/dist/dockview-core.noStyle.js +169 -30
  29. package/dist/esm/api/dockviewGroupPanelApi.d.ts +10 -1
  30. package/dist/esm/api/dockviewGroupPanelApi.js +12 -0
  31. package/dist/esm/dnd/groupDragHandler.js +34 -12
  32. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +2 -2
  33. package/dist/esm/dockview/components/titlebar/tabs.js +12 -2
  34. package/dist/esm/dockview/components/titlebar/voidContainer.js +6 -0
  35. package/dist/esm/dockview/dockviewComponent.d.ts +1 -0
  36. package/dist/esm/dockview/dockviewComponent.js +49 -7
  37. package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +1 -0
  38. package/dist/esm/dockview/dockviewGroupPanelModel.js +9 -0
  39. package/dist/esm/dockview/dockviewPanel.js +5 -0
  40. package/dist/esm/dockview/dockviewPanelModel.d.ts +2 -0
  41. package/dist/esm/dockview/dockviewPanelModel.js +8 -0
  42. package/dist/esm/dockview/framework.d.ts +8 -0
  43. package/dist/esm/dockview/options.d.ts +13 -2
  44. package/dist/esm/dockview/options.js +2 -0
  45. package/dist/esm/dom.d.ts +5 -1
  46. package/dist/esm/dom.js +13 -2
  47. package/dist/esm/index.d.ts +1 -1
  48. package/dist/esm/overlay/overlayRenderContainer.js +13 -3
  49. package/dist/esm/popoutWindow.d.ts +2 -0
  50. package/dist/esm/popoutWindow.js +3 -1
  51. package/dist/package/main.cjs.js +169 -30
  52. package/dist/package/main.cjs.min.js +2 -2
  53. package/dist/package/main.esm.min.mjs +2 -2
  54. package/dist/package/main.esm.mjs +169 -30
  55. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * dockview-core
3
- * @version 6.2.1
3
+ * @version 6.3.0
4
4
  * @link https://github.com/mathuo/dockview
5
5
  * @license MIT
6
6
  */
@@ -474,8 +474,10 @@ function quasiPreventDefault(event) {
474
474
  function quasiDefaultPrevented(event) {
475
475
  return event[QUASI_PREVENT_DEFAULT_KEY];
476
476
  }
477
- function addStyles(document, styleSheetList) {
477
+ function addStyles(document, styleSheetList, options = {}) {
478
478
  const styleSheets = Array.from(styleSheetList);
479
+ const { nonce } = options;
480
+ const resolvedNonce = typeof nonce === 'function' ? nonce(document) : nonce;
479
481
  for (const styleSheet of styleSheets) {
480
482
  if (styleSheet.href) {
481
483
  const link = document.createElement('link');
@@ -483,6 +485,10 @@ function addStyles(document, styleSheetList) {
483
485
  link.type = styleSheet.type;
484
486
  link.rel = 'stylesheet';
485
487
  document.head.appendChild(link);
488
+ // The <link> will load and apply its rules in the target
489
+ // document. Reading cssRules here would duplicate them
490
+ // (and throws for cross-origin sheets).
491
+ continue;
486
492
  }
487
493
  let cssTexts = [];
488
494
  try {
@@ -493,11 +499,16 @@ function addStyles(document, styleSheetList) {
493
499
  catch (err) {
494
500
  console.warn('dockview: failed to access stylesheet rules due to security restrictions', err);
495
501
  }
502
+ const fragment = document.createDocumentFragment();
496
503
  for (const rule of cssTexts) {
497
504
  const style = document.createElement('style');
505
+ if (resolvedNonce) {
506
+ style.setAttribute('nonce', resolvedNonce);
507
+ }
498
508
  style.appendChild(document.createTextNode(rule));
499
- document.head.appendChild(style);
509
+ fragment.appendChild(style);
500
510
  }
511
+ document.head.appendChild(fragment);
501
512
  }
502
513
  }
503
514
  function getDomNodePagePosition(domNode) {
@@ -5489,19 +5500,41 @@ class GroupDragHandler extends DragHandler {
5489
5500
  const bgColor = style.getPropertyValue('--dv-activegroup-visiblepanel-tab-background-color');
5490
5501
  const color = style.getPropertyValue('--dv-activegroup-visiblepanel-tab-color');
5491
5502
  if (dataTransfer) {
5492
- const ghostElement = document.createElement('div');
5493
- ghostElement.style.backgroundColor = bgColor;
5494
- ghostElement.style.color = color;
5495
- ghostElement.style.padding = '2px 8px';
5496
- ghostElement.style.height = '24px';
5497
- ghostElement.style.fontSize = '11px';
5498
- ghostElement.style.lineHeight = '20px';
5499
- ghostElement.style.borderRadius = '12px';
5500
- ghostElement.style.position = 'absolute';
5501
- ghostElement.style.pointerEvents = 'none';
5502
- ghostElement.style.top = '-9999px';
5503
- ghostElement.textContent = `Multiple Panels (${this.group.size})`;
5503
+ const createGhost = this.accessor.options.createGroupDragGhostComponent;
5504
+ let ghostElement;
5505
+ let customRenderer;
5506
+ if (createGhost) {
5507
+ customRenderer = createGhost(this.group);
5508
+ customRenderer.init({
5509
+ group: this.group,
5510
+ api: this.accessor.api,
5511
+ });
5512
+ ghostElement = customRenderer.element;
5513
+ ghostElement.style.position = 'absolute';
5514
+ ghostElement.style.pointerEvents = 'none';
5515
+ ghostElement.style.top = '-9999px';
5516
+ }
5517
+ else {
5518
+ ghostElement = document.createElement('div');
5519
+ ghostElement.style.backgroundColor = bgColor;
5520
+ ghostElement.style.color = color;
5521
+ ghostElement.style.padding = '2px 8px';
5522
+ ghostElement.style.height = '24px';
5523
+ ghostElement.style.fontSize = '11px';
5524
+ ghostElement.style.lineHeight = '20px';
5525
+ ghostElement.style.borderRadius = '12px';
5526
+ ghostElement.style.position = 'absolute';
5527
+ ghostElement.style.pointerEvents = 'none';
5528
+ ghostElement.style.top = '-9999px';
5529
+ ghostElement.textContent = `Multiple Panels (${this.group.size})`;
5530
+ }
5504
5531
  addGhostImage(dataTransfer, ghostElement, { y: -10, x: 30 });
5532
+ if (customRenderer === null || customRenderer === void 0 ? void 0 : customRenderer.dispose) {
5533
+ // addGhostImage removes the element from the DOM on the next
5534
+ // tick; dispose the framework renderer on the same schedule.
5535
+ const renderer = customRenderer;
5536
+ setTimeout(() => { var _a; return (_a = renderer.dispose) === null || _a === void 0 ? void 0 : _a.call(renderer); }, 0);
5537
+ }
5505
5538
  }
5506
5539
  return {
5507
5540
  dispose: () => {
@@ -5534,6 +5567,12 @@ class VoidContainer extends CompositeDisposable {
5534
5567
  this.dropTarget = new Droptarget(this._element, {
5535
5568
  acceptedTargetZones: ['center'],
5536
5569
  canDisplayOverlay: (event, position) => {
5570
+ if (this.group.api.locked) {
5571
+ // Dropping on the void/header space adds the panel
5572
+ // to this group, which `locked` is meant to prevent
5573
+ // (both `true` and `'no-drop-target'`).
5574
+ return false;
5575
+ }
5537
5576
  const data = getPanelData();
5538
5577
  if (data && this.accessor.id === data.viewId) {
5539
5578
  return true;
@@ -6115,7 +6154,7 @@ class WrapTabGroupIndicator extends BaseTabGroupIndicator {
6115
6154
  let svg = underline.firstElementChild;
6116
6155
  let path;
6117
6156
  if (!svg || svg.tagName !== 'svg') {
6118
- underline.innerHTML = '';
6157
+ underline.replaceChildren();
6119
6158
  svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
6120
6159
  svg.style.display = 'block';
6121
6160
  path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
@@ -6213,7 +6252,7 @@ class NoneTabGroupIndicator extends BaseTabGroupIndicator {
6213
6252
  underline.style.display = '';
6214
6253
  // Clear any SVG content left over from a mode switch
6215
6254
  if (underline.firstElementChild) {
6216
- underline.innerHTML = '';
6255
+ underline.replaceChildren();
6217
6256
  }
6218
6257
  underline.style.backgroundColor = color;
6219
6258
  if (isVertical) {
@@ -7606,11 +7645,15 @@ class Tabs extends CompositeDisposable {
7606
7645
  if (!isInsideRange && !isJustBeforeGroup) {
7607
7646
  continue;
7608
7647
  }
7609
- if (isGroupDrag) {
7648
+ if (isGroupDrag && isInsideRange) {
7610
7649
  // A group cannot be dropped inside another group.
7611
7650
  // Snap the insertion index to just before or just
7612
7651
  // after this group based on cursor position relative
7613
- // to the group's midpoint.
7652
+ // to the group's midpoint. Only applies when the
7653
+ // insertion would land *inside* the group — for
7654
+ // `isJustBeforeGroup`, the index is already outside
7655
+ // (immediately left of the group) and is a valid
7656
+ // drop position, so leave it untouched (issue #1264).
7614
7657
  const groupMid = (firstIdx + lastIdx + 1) / 2;
7615
7658
  if (insertionIndex < groupMid) {
7616
7659
  insertionIndex = firstIdx;
@@ -7621,6 +7664,12 @@ class Tabs extends CompositeDisposable {
7621
7664
  // targetTabGroupId stays null
7622
7665
  break;
7623
7666
  }
7667
+ if (isGroupDrag && isJustBeforeGroup) {
7668
+ // Cursor is just before the group — accept this
7669
+ // index as-is. Groups can be dropped at the slot
7670
+ // immediately left of another group's first tab.
7671
+ break;
7672
+ }
7624
7673
  if (isJustBeforeGroup) {
7625
7674
  // Check whether only the source tab (or source group
7626
7675
  // tabs) sits between insertionIndex and firstIdx.
@@ -8462,6 +8511,7 @@ const PROPERTY_KEYS_DOCKVIEW = (() => {
8462
8511
  disableFloatingGroups: undefined,
8463
8512
  floatingGroupBounds: undefined,
8464
8513
  popoutUrl: undefined,
8514
+ nonce: undefined,
8465
8515
  defaultRenderer: undefined,
8466
8516
  defaultHeaderPosition: undefined,
8467
8517
  debug: undefined,
@@ -8477,6 +8527,7 @@ const PROPERTY_KEYS_DOCKVIEW = (() => {
8477
8527
  getTabContextMenuItems: undefined,
8478
8528
  getTabGroupChipContextMenuItems: undefined,
8479
8529
  createTabGroupChipComponent: undefined,
8530
+ createGroupDragGhostComponent: undefined,
8480
8531
  tabGroupColors: undefined,
8481
8532
  tabGroupAccent: undefined,
8482
8533
  };
@@ -9169,6 +9220,15 @@ class DockviewGroupPanelModel extends CompositeDisposable {
9169
9220
  refreshTabGroupAccent() {
9170
9221
  this.tabsContainer.refreshTabGroupAccent();
9171
9222
  }
9223
+ refreshWatermark() {
9224
+ var _a, _b;
9225
+ if (this.watermark) {
9226
+ this.watermark.element.remove();
9227
+ (_b = (_a = this.watermark).dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
9228
+ this.watermark = undefined;
9229
+ }
9230
+ this.updateContainer();
9231
+ }
9172
9232
  getTabGroupForPanel(panelId) {
9173
9233
  return this._findTabGroupForPanel(panelId);
9174
9234
  }
@@ -9999,6 +10059,18 @@ class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
9999
10059
  }
10000
10060
  return this._group.model.location;
10001
10061
  }
10062
+ get locked() {
10063
+ if (!this._group) {
10064
+ throw new Error(NOT_INITIALIZED_MESSAGE);
10065
+ }
10066
+ return this._group.locked;
10067
+ }
10068
+ set locked(value) {
10069
+ if (!this._group) {
10070
+ throw new Error(NOT_INITIALIZED_MESSAGE);
10071
+ }
10072
+ this._group.locked = value;
10073
+ }
10002
10074
  constructor(id, accessor) {
10003
10075
  super(id, '__dockviewgroup__');
10004
10076
  this.accessor = accessor;
@@ -10589,6 +10661,11 @@ class DockviewPanel extends CompositeDisposable {
10589
10661
  const didTitleChange = title !== this.title;
10590
10662
  if (didTitleChange) {
10591
10663
  this._title = title;
10664
+ // keep the view-model's cached init params in sync so that tab
10665
+ // renderers constructed lazily (e.g. the header overflow
10666
+ // dropdown via createTabRenderer) see the updated title
10667
+ // (#914).
10668
+ this.view.setTitle(title);
10592
10669
  this.api._onDidTitleChange.fire({ title });
10593
10670
  }
10594
10671
  }
@@ -10749,6 +10826,14 @@ class DockviewPanelModel {
10749
10826
  this.content.init(params);
10750
10827
  this.tab.init(Object.assign(Object.assign({}, params), { tabLocation: 'header' }));
10751
10828
  }
10829
+ setTitle(title) {
10830
+ // keep the cached init params in sync so that tab renderers created
10831
+ // lazily after the title changes (e.g. for the header overflow
10832
+ // dropdown) see the current title rather than the stale original.
10833
+ if (this._params) {
10834
+ this._params.title = title;
10835
+ }
10836
+ }
10752
10837
  layout(width, height) {
10753
10838
  var _a, _b;
10754
10839
  (_b = (_a = this.content).layout) === null || _b === void 0 ? void 0 : _b.call(_a, width, height);
@@ -11388,10 +11473,20 @@ class OverlayRenderContainer extends CompositeDisposable {
11388
11473
  focusContainer.style.top = `${top}px`;
11389
11474
  focusContainer.style.width = `${width}px`;
11390
11475
  focusContainer.style.height = `${height}px`;
11391
- // Reveal after the first position is applied (was hidden to
11392
- // prevent a flash at 0,0 before the initial layout fires).
11393
- if (focusContainer.style.visibility === 'hidden') {
11476
+ // Sync visibility/pointer-events with the panel's current
11477
+ // visibility at paint time. visibilityChanged() may have
11478
+ // flipped to hidden between scheduling this rAF and now;
11479
+ // unconditionally clearing `visibility:hidden` here would
11480
+ // leave a hidden panel visually visible at a stale position,
11481
+ // because onDidDimensionsChange skips non-visible panels and
11482
+ // never recomputes their box on subsequent resizes.
11483
+ if (panel.api.isVisible) {
11394
11484
  focusContainer.style.visibility = '';
11485
+ focusContainer.style.pointerEvents = '';
11486
+ }
11487
+ else {
11488
+ focusContainer.style.visibility = 'hidden';
11489
+ focusContainer.style.pointerEvents = 'none';
11395
11490
  }
11396
11491
  toggleClass(focusContainer, 'dv-render-overlay-float', panel.group.api.location.type === 'floating');
11397
11492
  });
@@ -11658,7 +11753,9 @@ class PopoutWindow extends CompositeDisposable {
11658
11753
  const externalDocument = externalWindow.document;
11659
11754
  externalDocument.title = document.title;
11660
11755
  externalDocument.body.appendChild(container);
11661
- addStyles(externalDocument, window.document.styleSheets);
11756
+ addStyles(externalDocument, window.document.styleSheets, {
11757
+ nonce: this.options.nonce,
11758
+ });
11662
11759
  /**
11663
11760
  * beforeunload must be registered after load for reasons I could not determine
11664
11761
  * otherwise the beforeunload event will not fire when the window is closed
@@ -12848,6 +12945,7 @@ class DockviewComponent extends BaseGrid {
12848
12945
  this._floatingGroups = [];
12849
12946
  this._popoutGroups = [];
12850
12947
  this._popoutRestorationPromise = Promise.resolve();
12948
+ this._popoutRestorationCleanups = new Set();
12851
12949
  this._onDidRemoveGroup = new Emitter();
12852
12950
  this.onDidRemoveGroup = this._onDidRemoveGroup.event;
12853
12951
  this._onDidAddGroup = new Emitter();
@@ -12953,6 +13051,14 @@ class DockviewComponent extends BaseGrid {
12953
13051
  this._bufferOnDidLayoutChange.fire();
12954
13052
  }), exports.DockviewDisposable.from(() => {
12955
13053
  var _a;
13054
+ // Cancel any pending popout-restoration timers scheduled by
13055
+ // fromJSON so they don't open new browser windows after
13056
+ // dispose, and resolve their promises so callers awaiting
13057
+ // popoutRestorationPromise don't hang. See issue #851.
13058
+ for (const cleanup of [...this._popoutRestorationCleanups]) {
13059
+ cleanup();
13060
+ }
13061
+ this._popoutRestorationCleanups.clear();
12956
13062
  // iterate over a copy of the array since .dispose() mutates the original array
12957
13063
  for (const group of [...this._floatingGroups]) {
12958
13064
  group.dispose();
@@ -13049,7 +13155,7 @@ class DockviewComponent extends BaseGrid {
13049
13155
  return (_a = this._popoutPopupServices.get(group.id)) !== null && _a !== void 0 ? _a : this.popupService;
13050
13156
  }
13051
13157
  addPopoutGroup(itemToPopout, options) {
13052
- var _a, _b, _c, _d, _e;
13158
+ var _a, _b, _c, _d, _e, _f;
13053
13159
  if (itemToPopout instanceof DockviewGroupPanel &&
13054
13160
  itemToPopout.model.location.type === 'edge') {
13055
13161
  // edge groups are permanent structural elements and cannot be popped out
@@ -13084,6 +13190,7 @@ class DockviewComponent extends BaseGrid {
13084
13190
  height: box.height,
13085
13191
  onDidOpen: options === null || options === void 0 ? void 0 : options.onDidOpen,
13086
13192
  onWillClose: options === null || options === void 0 ? void 0 : options.onWillClose,
13193
+ nonce: (_f = this.options) === null || _f === void 0 ? void 0 : _f.nonce,
13087
13194
  });
13088
13195
  const popoutWindowDisposable = new CompositeDisposable(_window, _window.onDidClose(() => {
13089
13196
  popoutWindowDisposable.dispose();
@@ -13501,7 +13608,7 @@ class DockviewComponent extends BaseGrid {
13501
13608
  }
13502
13609
  }
13503
13610
  updateOptions(options) {
13504
- var _a, _b, _c;
13611
+ var _a, _b, _c, _d, _e;
13505
13612
  super.updateOptions(options);
13506
13613
  if ('floatingGroupBounds' in options) {
13507
13614
  for (const group of this._floatingGroups) {
@@ -13542,8 +13649,19 @@ class DockviewComponent extends BaseGrid {
13542
13649
  group.model.updateHeaderActions();
13543
13650
  }
13544
13651
  }
13652
+ if ('createWatermarkComponent' in options) {
13653
+ if (this._watermark) {
13654
+ this._watermark.element.parentElement.remove();
13655
+ (_d = (_c = this._watermark).dispose) === null || _d === void 0 ? void 0 : _d.call(_c);
13656
+ this._watermark = null;
13657
+ }
13658
+ this.updateWatermark();
13659
+ for (const group of this.groups) {
13660
+ group.model.refreshWatermark();
13661
+ }
13662
+ }
13545
13663
  if ('tabGroupColors' in options || 'tabGroupAccent' in options) {
13546
- this._tabGroupColorPalette.setEntries((_c = this._options.tabGroupColors) !== null && _c !== void 0 ? _c : DEFAULT_TAB_GROUP_COLORS);
13664
+ this._tabGroupColorPalette.setEntries((_e = this._options.tabGroupColors) !== null && _e !== void 0 ? _e : DEFAULT_TAB_GROUP_COLORS);
13547
13665
  this._tabGroupColorPalette.enabled =
13548
13666
  this._options.tabGroupAccent !== 'off';
13549
13667
  for (const group of this.groups) {
@@ -13969,7 +14087,23 @@ class DockviewComponent extends BaseGrid {
13969
14087
  const group = createGroupFromSerializedState(data);
13970
14088
  // Add a small delay for each popup after the first to avoid browser popup blocking
13971
14089
  const popoutPromise = new Promise((resolve) => {
13972
- setTimeout(() => {
14090
+ const cleanup = () => {
14091
+ this._popoutRestorationCleanups.delete(cleanup);
14092
+ clearTimeout(handle);
14093
+ resolve();
14094
+ };
14095
+ const handle = setTimeout(() => {
14096
+ this._popoutRestorationCleanups.delete(cleanup);
14097
+ // Guard against the component being disposed before
14098
+ // this timer fires. Under React StrictMode the
14099
+ // component is mounted -> disposed -> remounted, and
14100
+ // without this guard the first instance's queued
14101
+ // restoration would open a second popout window.
14102
+ // See issue #851.
14103
+ if (this.isDisposed) {
14104
+ resolve();
14105
+ return;
14106
+ }
13973
14107
  this.addPopoutGroup(group, {
13974
14108
  position: position !== null && position !== void 0 ? position : undefined,
13975
14109
  overridePopoutGroup: gridReferenceGroup
@@ -13982,6 +14116,7 @@ class DockviewComponent extends BaseGrid {
13982
14116
  });
13983
14117
  resolve();
13984
14118
  }, index * DESERIALIZATION_POPOUT_DELAY_MS); // 100ms delay between each popup
14119
+ this._popoutRestorationCleanups.add(cleanup);
13985
14120
  });
13986
14121
  popoutPromises.push(popoutPromise);
13987
14122
  });
@@ -14512,8 +14647,11 @@ class DockviewComponent extends BaseGrid {
14512
14647
  * the source group is a popout group with a single panel
14513
14648
  *
14514
14649
  * 1. remove the panel from the group without triggering any events
14515
- * 2. remove the popout group
14516
- * 3. create a new group at the requested location and add that panel
14650
+ * 2. remove the popout group — this may cascade-remove the empty
14651
+ * reference group it left behind in the main grid (see
14652
+ * doRemoveGroup for popout groups), which can shift grid indices
14653
+ * 3. recompute the target location now that the grid is stable
14654
+ * 4. create a new group at the recomputed location and add that panel
14517
14655
  */
14518
14656
  const popoutGroup = this._popoutGroups.find((group) => group.popoutGroup === sourceGroup);
14519
14657
  const removedPanel = this.movingLock(() => popoutGroup.popoutGroup.model.removePanel(popoutGroup.popoutGroup.panels[0], {
@@ -14521,7 +14659,8 @@ class DockviewComponent extends BaseGrid {
14521
14659
  skipSetActiveGroup: true,
14522
14660
  }));
14523
14661
  this.doRemoveGroup(sourceGroup, { skipActive: true });
14524
- const newGroup = this.createGroupAtLocation(targetLocation);
14662
+ const updatedTargetLocation = getRelativeLocation(this.gridview.orientation, getGridLocation(destinationGroup.element), destinationTarget);
14663
+ const newGroup = this.createGroupAtLocation(updatedTargetLocation);
14525
14664
  this.movingLock(() => newGroup.model.openPanel(removedPanel, {
14526
14665
  skipSetActive: true,
14527
14666
  }));