dockview-core 6.0.1 → 6.0.5

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 6.0.1
3
+ * @version 6.0.5
4
4
  * @link https://github.com/mathuo/dockview
5
5
  * @license MIT
6
6
  */
@@ -2826,6 +2826,8 @@ class Resizable extends CompositeDisposable {
2826
2826
  }
2827
2827
  constructor(parentElement, disableResizing = false) {
2828
2828
  super();
2829
+ this._lastWidth = -1;
2830
+ this._lastHeight = -1;
2829
2831
  this._disableResizing = disableResizing;
2830
2832
  this._element = parentElement;
2831
2833
  this.addDisposables(watchElementResize(this._element, (entry) => {
@@ -2862,7 +2864,16 @@ class Resizable extends CompositeDisposable {
2862
2864
  */
2863
2865
  return;
2864
2866
  }
2865
- const { width, height } = entry.contentRect;
2867
+ // Round to integers to absorb sub-pixel jitter from
2868
+ // fractional devicePixelRatio (e.g. multi-monitor setups),
2869
+ // which would otherwise re-fire layout in a feedback loop.
2870
+ const width = Math.round(entry.contentRect.width);
2871
+ const height = Math.round(entry.contentRect.height);
2872
+ if (width === this._lastWidth && height === this._lastHeight) {
2873
+ return;
2874
+ }
2875
+ this._lastWidth = width;
2876
+ this._lastHeight = height;
2866
2877
  this.layout(width, height);
2867
2878
  }));
2868
2879
  }
@@ -5444,6 +5455,9 @@ class GroupDragHandler extends DragHandler {
5444
5455
  if (this.group.api.location.type === 'floating' && !_event.shiftKey) {
5445
5456
  return true;
5446
5457
  }
5458
+ if (this.group.api.location.type === 'edge' && this.group.size === 0) {
5459
+ return true;
5460
+ }
5447
5461
  return false;
5448
5462
  }
5449
5463
  getData(dragEvent) {
@@ -11291,8 +11305,14 @@ class OverlayRenderContainer extends CompositeDisposable {
11291
11305
  };
11292
11306
  }
11293
11307
  const focusContainer = this.map[panel.api.id].element;
11294
- if (panel.view.content.element.parentElement !== focusContainer) {
11295
- focusContainer.appendChild(panel.view.content.element);
11308
+ // Capture the content element now so the destroy disposable below
11309
+ // does not re-query the renderer's `element` getter during teardown.
11310
+ // Some framework adapters (e.g. dockview-angular) tear down their
11311
+ // backing renderer before this disposable fires; reading through the
11312
+ // getter at that point can throw.
11313
+ const contentElement = panel.view.content.element;
11314
+ if (contentElement.parentElement !== focusContainer) {
11315
+ focusContainer.appendChild(contentElement);
11296
11316
  }
11297
11317
  if (focusContainer.parentElement !== this.element) {
11298
11318
  this.element.appendChild(focusContainer);
@@ -11403,8 +11423,8 @@ class OverlayRenderContainer extends CompositeDisposable {
11403
11423
  }));
11404
11424
  this.map[panel.api.id].destroy = exports.DockviewDisposable.from(() => {
11405
11425
  var _a;
11406
- if (panel.view.content.element.parentElement === focusContainer) {
11407
- focusContainer.removeChild(panel.view.content.element);
11426
+ if (contentElement.parentElement === focusContainer) {
11427
+ focusContainer.removeChild(contentElement);
11408
11428
  }
11409
11429
  (_a = focusContainer.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(focusContainer);
11410
11430
  });
@@ -12259,7 +12279,12 @@ class ShellManager {
12259
12279
  this._middleIndex = 0;
12260
12280
  this._outerSplitview.addView(this._middleColumn, { type: 'distribute' }, 0);
12261
12281
  this._disposables.addDisposables(watchElementResize(this._shellElement, (entry) => {
12262
- const { width, height } = entry.contentRect;
12282
+ const width = Math.round(entry.contentRect.width);
12283
+ const height = Math.round(entry.contentRect.height);
12284
+ if (width === this._currentWidth &&
12285
+ height === this._currentHeight) {
12286
+ return;
12287
+ }
12263
12288
  this._currentWidth = width;
12264
12289
  this._currentHeight = height;
12265
12290
  this.layout(width, height);
@@ -13329,10 +13354,20 @@ class DockviewComponent extends BaseGrid {
13329
13354
  if (event.isActive) {
13330
13355
  overlay.bringToFront();
13331
13356
  }
13332
- }), watchElementResize(group.element, (entry) => {
13333
- const { width, height } = entry.contentRect;
13334
- group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
13335
- }));
13357
+ }), (() => {
13358
+ let lastWidth = -1;
13359
+ let lastHeight = -1;
13360
+ return watchElementResize(group.element, (entry) => {
13361
+ const width = Math.round(entry.contentRect.width);
13362
+ const height = Math.round(entry.contentRect.height);
13363
+ if (width === lastWidth && height === lastHeight) {
13364
+ return;
13365
+ }
13366
+ lastWidth = width;
13367
+ lastHeight = height;
13368
+ group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
13369
+ });
13370
+ })());
13336
13371
  floatingGroupPanel.addDisposables(overlay.onDidChange(() => {
13337
13372
  // this is either a resize or a move
13338
13373
  // to inform the panels .layout(...) the group with it's current size
@@ -14552,6 +14587,10 @@ class DockviewComponent extends BaseGrid {
14552
14587
  const from = options.from.group;
14553
14588
  const to = options.to.group;
14554
14589
  const target = options.to.position;
14590
+ // The group whose panels end up at the target. For non-edge moves
14591
+ // we relocate `from` itself; for edge moves we move panels into a
14592
+ // freshly created group so the edge slot stays anchored.
14593
+ let source = from;
14555
14594
  if (target === 'center') {
14556
14595
  const activePanel = from.activePanel;
14557
14596
  const panels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, {
@@ -14581,55 +14620,79 @@ class DockviewComponent extends BaseGrid {
14581
14620
  }
14582
14621
  }
14583
14622
  else {
14584
- switch (from.api.location.type) {
14585
- case 'grid':
14586
- this.gridview.removeView(getGridLocation(from.element));
14587
- break;
14588
- case 'floating': {
14589
- const selectedFloatingGroup = this._floatingGroups.find((x) => x.group === from);
14590
- if (!selectedFloatingGroup) {
14591
- throw new Error('dockview: failed to find floating group');
14592
- }
14593
- selectedFloatingGroup.dispose();
14594
- break;
14595
- }
14596
- case 'popout': {
14597
- const selectedPopoutGroup = this._popoutGroups.find((x) => x.popoutGroup === from);
14598
- if (!selectedPopoutGroup) {
14599
- throw new Error('dockview: failed to find popout group');
14600
- }
14601
- // Remove from popout groups list to prevent automatic restoration
14602
- const index = this._popoutGroups.indexOf(selectedPopoutGroup);
14603
- if (index >= 0) {
14604
- this._popoutGroups.splice(index, 1);
14623
+ if (from.api.location.type === 'edge') {
14624
+ /**
14625
+ * Edge groups are permanent structural elements and must
14626
+ * stay anchored in their edge slot. Move the panels into a
14627
+ * new group; the auto-collapse listener registered in
14628
+ * addEdgeGroup will collapse the now-empty edge slot once
14629
+ * the last panel leaves. The placement code below then
14630
+ * positions `source` like any other moved group.
14631
+ */
14632
+ const activePanel = from.activePanel;
14633
+ const movedPanels = this.movingLock(() => [...from.panels].map((p) => from.model.removePanel(p.id, { skipSetActive: true })));
14634
+ source = this.createGroup();
14635
+ this.movingLock(() => {
14636
+ for (const panel of movedPanels) {
14637
+ source.model.openPanel(panel, {
14638
+ skipSetActive: panel !== activePanel,
14639
+ skipSetGroupActive: true,
14640
+ });
14605
14641
  }
14606
- // Clean up the reference group (ghost) if it exists and is hidden
14607
- if (selectedPopoutGroup.referenceGroup) {
14608
- const referenceGroup = this.getPanel(selectedPopoutGroup.referenceGroup);
14609
- if (referenceGroup && !referenceGroup.api.isVisible) {
14610
- this.doRemoveGroup(referenceGroup, {
14611
- skipActive: true,
14612
- });
14642
+ });
14643
+ }
14644
+ else {
14645
+ switch (from.api.location.type) {
14646
+ case 'grid':
14647
+ this.gridview.removeView(getGridLocation(from.element));
14648
+ break;
14649
+ case 'floating': {
14650
+ const selectedFloatingGroup = this._floatingGroups.find((x) => x.group === from);
14651
+ if (!selectedFloatingGroup) {
14652
+ throw new Error('dockview: failed to find floating group');
14613
14653
  }
14654
+ selectedFloatingGroup.dispose();
14655
+ break;
14614
14656
  }
14615
- // Manually dispose the window without triggering restoration
14616
- selectedPopoutGroup.window.dispose();
14617
- // Update group's location and containers for target
14618
- if (to.api.location.type === 'grid') {
14619
- from.model.renderContainer =
14620
- this.overlayRenderContainer;
14621
- from.model.dropTargetContainer =
14622
- this.rootDropTargetContainer;
14623
- from.model.location = { type: 'grid' };
14624
- }
14625
- else if (to.api.location.type === 'floating') {
14626
- from.model.renderContainer =
14627
- this.overlayRenderContainer;
14628
- from.model.dropTargetContainer =
14629
- this.rootDropTargetContainer;
14630
- from.model.location = { type: 'floating' };
14657
+ case 'popout': {
14658
+ const selectedPopoutGroup = this._popoutGroups.find((x) => x.popoutGroup === from);
14659
+ if (!selectedPopoutGroup) {
14660
+ throw new Error('dockview: failed to find popout group');
14661
+ }
14662
+ // Remove from popout groups list to prevent automatic restoration
14663
+ const index = this._popoutGroups.indexOf(selectedPopoutGroup);
14664
+ if (index >= 0) {
14665
+ this._popoutGroups.splice(index, 1);
14666
+ }
14667
+ // Clean up the reference group (ghost) if it exists and is hidden
14668
+ if (selectedPopoutGroup.referenceGroup) {
14669
+ const referenceGroup = this.getPanel(selectedPopoutGroup.referenceGroup);
14670
+ if (referenceGroup &&
14671
+ !referenceGroup.api.isVisible) {
14672
+ this.doRemoveGroup(referenceGroup, {
14673
+ skipActive: true,
14674
+ });
14675
+ }
14676
+ }
14677
+ // Manually dispose the window without triggering restoration
14678
+ selectedPopoutGroup.window.dispose();
14679
+ // Update group's location and containers for target
14680
+ if (to.api.location.type === 'grid') {
14681
+ from.model.renderContainer =
14682
+ this.overlayRenderContainer;
14683
+ from.model.dropTargetContainer =
14684
+ this.rootDropTargetContainer;
14685
+ from.model.location = { type: 'grid' };
14686
+ }
14687
+ else if (to.api.location.type === 'floating') {
14688
+ from.model.renderContainer =
14689
+ this.overlayRenderContainer;
14690
+ from.model.dropTargetContainer =
14691
+ this.rootDropTargetContainer;
14692
+ from.model.location = { type: 'floating' };
14693
+ }
14694
+ break;
14631
14695
  }
14632
- break;
14633
14696
  }
14634
14697
  }
14635
14698
  // For moves to grid locations
@@ -14652,7 +14715,7 @@ class DockviewComponent extends BaseGrid {
14652
14715
  : from.api.width;
14653
14716
  break;
14654
14717
  }
14655
- this.gridview.addView(from, size, dropLocation);
14718
+ this.gridview.addView(source, size, dropLocation);
14656
14719
  }
14657
14720
  else if (to.api.location.type === 'floating') {
14658
14721
  // For moves to floating locations, add as floating group
@@ -14680,7 +14743,7 @@ class DockviewComponent extends BaseGrid {
14680
14743
  else {
14681
14744
  top = 50; // Default fallback
14682
14745
  }
14683
- this.addFloatingGroup(from, {
14746
+ this.addFloatingGroup(source, {
14684
14747
  height: box.height,
14685
14748
  width: box.width,
14686
14749
  position: {
@@ -14691,7 +14754,7 @@ class DockviewComponent extends BaseGrid {
14691
14754
  }
14692
14755
  }
14693
14756
  }
14694
- from.panels.forEach((panel) => {
14757
+ source.panels.forEach((panel) => {
14695
14758
  this._onDidMovePanel.fire({ panel, from });
14696
14759
  });
14697
14760
  this.debouncedUpdateAllPositions();
@@ -14702,6 +14765,11 @@ class DockviewComponent extends BaseGrid {
14702
14765
  const targetGroup = to !== null && to !== void 0 ? to : from;
14703
14766
  this.doSetGroupAndPanelActive(targetGroup);
14704
14767
  }
14768
+ else if (source !== from && options.skipSetActive !== true) {
14769
+ // Edge group moves create a fresh `source` group; activate it
14770
+ // by default so the moved panels receive focus.
14771
+ this.doSetGroupAndPanelActive(source);
14772
+ }
14705
14773
  }
14706
14774
  doSetGroupActive(group) {
14707
14775
  super.doSetGroupActive(group);