dockview 1.7.5 → 1.8.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 (50) hide show
  1. package/README.md +2 -1
  2. package/dist/cjs/dockview/dockview.d.ts +4 -2
  3. package/dist/cjs/dockview/dockview.d.ts.map +1 -1
  4. package/dist/cjs/dockview/dockview.js +23 -5
  5. package/dist/cjs/dockview/dockview.js.map +1 -1
  6. package/dist/cjs/dockview/{groupControlsRenderer.d.ts → headerActionsRenderer.d.ts} +6 -5
  7. package/dist/cjs/dockview/headerActionsRenderer.d.ts.map +1 -0
  8. package/dist/cjs/dockview/{groupControlsRenderer.js → headerActionsRenderer.js} +17 -16
  9. package/dist/cjs/dockview/{groupControlsRenderer.js.map → headerActionsRenderer.js.map} +1 -1
  10. package/dist/cjs/index.d.ts +1 -1
  11. package/dist/cjs/index.d.ts.map +1 -1
  12. package/dist/cjs/svg.d.ts +3 -3
  13. package/dist/cjs/svg.d.ts.map +1 -1
  14. package/dist/dockview.amd.js +839 -163
  15. package/dist/dockview.amd.js.map +1 -0
  16. package/dist/dockview.amd.min.js +3 -2
  17. package/dist/dockview.amd.min.js.map +1 -0
  18. package/dist/dockview.amd.min.noStyle.js +3 -2
  19. package/dist/dockview.amd.min.noStyle.js.map +1 -0
  20. package/dist/dockview.amd.noStyle.js +839 -163
  21. package/dist/dockview.amd.noStyle.js.map +1 -0
  22. package/dist/dockview.cjs.js +839 -163
  23. package/dist/dockview.cjs.js.map +1 -0
  24. package/dist/dockview.esm.js +840 -163
  25. package/dist/dockview.esm.js.map +1 -0
  26. package/dist/dockview.esm.min.js +3 -2
  27. package/dist/dockview.esm.min.js.map +1 -0
  28. package/dist/dockview.js +839 -163
  29. package/dist/dockview.js.map +1 -0
  30. package/dist/dockview.min.js +3 -2
  31. package/dist/dockview.min.js.map +1 -0
  32. package/dist/dockview.min.noStyle.js +3 -2
  33. package/dist/dockview.min.noStyle.js.map +1 -0
  34. package/dist/dockview.noStyle.js +839 -163
  35. package/dist/dockview.noStyle.js.map +1 -0
  36. package/dist/esm/dockview/dockview.d.ts +4 -2
  37. package/dist/esm/dockview/dockview.d.ts.map +1 -1
  38. package/dist/esm/dockview/dockview.js +23 -5
  39. package/dist/esm/dockview/dockview.js.map +1 -1
  40. package/dist/esm/dockview/{groupControlsRenderer.d.ts → headerActionsRenderer.d.ts} +6 -5
  41. package/dist/esm/dockview/headerActionsRenderer.d.ts.map +1 -0
  42. package/dist/esm/dockview/{groupControlsRenderer.js → headerActionsRenderer.js} +3 -2
  43. package/dist/esm/dockview/{groupControlsRenderer.js.map → headerActionsRenderer.js.map} +1 -1
  44. package/dist/esm/index.d.ts +1 -1
  45. package/dist/esm/index.d.ts.map +1 -1
  46. package/dist/esm/svg.d.ts +3 -3
  47. package/dist/esm/svg.d.ts.map +1 -1
  48. package/package.json +6 -6
  49. package/dist/cjs/dockview/groupControlsRenderer.d.ts.map +0 -1
  50. package/dist/esm/dockview/groupControlsRenderer.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * dockview
3
- * @version 1.7.5
3
+ * @version 1.8.0
4
4
  * @link https://github.com/mathuo/dockview
5
5
  * @license MIT
6
6
  */
@@ -293,6 +293,31 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
293
293
  }
294
294
  }
295
295
 
296
+ function createComponent(id, componentName, components = {}, frameworkComponents = {}, createFrameworkComponent, fallback) {
297
+ const Component = typeof componentName === 'string'
298
+ ? components[componentName]
299
+ : undefined;
300
+ const FrameworkComponent = typeof componentName === 'string'
301
+ ? frameworkComponents[componentName]
302
+ : undefined;
303
+ if (Component && FrameworkComponent) {
304
+ throw new Error(`Cannot create '${id}'. component '${componentName}' registered as both a component and frameworkComponent`);
305
+ }
306
+ if (FrameworkComponent) {
307
+ if (!createFrameworkComponent) {
308
+ throw new Error(`Cannot create '${id}' for framework component '${componentName}'. you must register a frameworkPanelWrapper to use framework components`);
309
+ }
310
+ return createFrameworkComponent.createComponent(id, componentName, FrameworkComponent);
311
+ }
312
+ if (!Component) {
313
+ if (fallback) {
314
+ return fallback();
315
+ }
316
+ throw new Error(`Cannot create '${id}', no component '${componentName}' provided`);
317
+ }
318
+ return new Component(id, componentName);
319
+ }
320
+
296
321
  function watchElementResize(element, cb) {
297
322
  const observer = new ResizeObserver((entires) => {
298
323
  /**
@@ -406,31 +431,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
406
431
  refreshState() {
407
432
  this._refreshStateHandler();
408
433
  }
409
- }
410
-
411
- function createComponent(id, componentName, components = {}, frameworkComponents = {}, createFrameworkComponent, fallback) {
412
- const Component = typeof componentName === 'string'
413
- ? components[componentName]
414
- : undefined;
415
- const FrameworkComponent = typeof componentName === 'string'
416
- ? frameworkComponents[componentName]
417
- : undefined;
418
- if (Component && FrameworkComponent) {
419
- throw new Error(`Cannot create '${id}'. component '${componentName}' registered as both a component and frameworkComponent`);
420
- }
421
- if (FrameworkComponent) {
422
- if (!createFrameworkComponent) {
423
- throw new Error(`Cannot create '${id}' for framework component '${componentName}'. you must register a frameworkPanelWrapper to use framework components`);
424
- }
425
- return createFrameworkComponent.createComponent(id, componentName, FrameworkComponent);
426
- }
427
- if (!Component) {
428
- if (fallback) {
429
- return fallback();
430
- }
431
- throw new Error(`Cannot create '${id}', no component '${componentName}' provided`);
432
- }
433
- return new Component(id, componentName);
434
+ }
435
+ // quasi: apparently, but not really; seemingly
436
+ const QUASI_PREVENT_DEFAULT_KEY = 'dv-quasiPreventDefault';
437
+ // mark an event directly for other listeners to check
438
+ function quasiPreventDefault(event) {
439
+ event[QUASI_PREVENT_DEFAULT_KEY] = true;
440
+ }
441
+ // check if this event has been marked
442
+ function quasiDefaultPrevented(event) {
443
+ return event[QUASI_PREVENT_DEFAULT_KEY];
434
444
  }
435
445
 
436
446
  function tail(arr) {
@@ -481,6 +491,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
481
491
  }
482
492
  }
483
493
  return -1;
494
+ }
495
+ function remove(array, value) {
496
+ const index = array.findIndex((t) => t === value);
497
+ if (index > -1) {
498
+ array.splice(index, 1);
499
+ return true;
500
+ }
501
+ return false;
484
502
  }
485
503
 
486
504
  const clamp = (value, min, max) => {
@@ -910,7 +928,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
910
928
  //add sash
911
929
  const sash = document.createElement('div');
912
930
  sash.className = 'sash';
913
- const onStart = (event) => {
931
+ const onPointerStart = (event) => {
914
932
  for (const item of this.viewItems) {
915
933
  item.enabled = false;
916
934
  }
@@ -969,11 +987,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
969
987
  size: snappedViewItem.size,
970
988
  };
971
989
  }
972
- //
973
- const mousemove = (mousemoveEvent) => {
990
+ const onPointerMove = (event) => {
974
991
  const current = this._orientation === exports.Orientation.HORIZONTAL
975
- ? mousemoveEvent.clientX
976
- : mousemoveEvent.clientY;
992
+ ? event.clientX
993
+ : event.clientY;
977
994
  const delta = current - start;
978
995
  this.resize(sashIndex, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter);
979
996
  this.distributeEmptySpace();
@@ -987,18 +1004,20 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
987
1004
  iframe.style.pointerEvents = 'auto';
988
1005
  }
989
1006
  this.saveProportions();
990
- document.removeEventListener('mousemove', mousemove);
991
- document.removeEventListener('mouseup', end);
1007
+ document.removeEventListener('pointermove', onPointerMove);
1008
+ document.removeEventListener('pointerup', end);
1009
+ document.removeEventListener('pointercancel', end);
992
1010
  this._onDidSashEnd.fire(undefined);
993
1011
  };
994
- document.addEventListener('mousemove', mousemove);
995
- document.addEventListener('mouseup', end);
1012
+ document.addEventListener('pointermove', onPointerMove);
1013
+ document.addEventListener('pointerup', end);
1014
+ document.addEventListener('pointercancel', end);
996
1015
  };
997
- sash.addEventListener('mousedown', onStart);
1016
+ sash.addEventListener('pointerdown', onPointerStart);
998
1017
  const sashItem = {
999
1018
  container: sash,
1000
1019
  disposable: () => {
1001
- sash.removeEventListener('mousedown', onStart);
1020
+ sash.removeEventListener('pointerdown', onPointerStart);
1002
1021
  this.sashContainer.removeChild(sash);
1003
1022
  },
1004
1023
  };
@@ -1622,7 +1641,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1622
1641
  : true,
1623
1642
  };
1624
1643
  }),
1625
- size: this.size,
1644
+ size: this.orthogonalSize,
1626
1645
  };
1627
1646
  this.children = childDescriptors.map((c) => c.node);
1628
1647
  this.splitview = new Splitview(this.element, {
@@ -1685,7 +1704,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1685
1704
  layout(size, orthogonalSize) {
1686
1705
  this._size = orthogonalSize;
1687
1706
  this._orthogonalSize = size;
1688
- this.splitview.layout(this.size, this.orthogonalSize);
1707
+ this.splitview.layout(orthogonalSize, size);
1689
1708
  }
1690
1709
  addChild(node, size, index, skipLayout) {
1691
1710
  if (index < 0 || index > this.children.length) {
@@ -1910,9 +1929,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1910
1929
  this._deserialize(json.root, orientation, deserializer, height);
1911
1930
  }
1912
1931
  _deserialize(root, orientation, deserializer, orthogonalSize) {
1913
- this.root = this._deserializeNode(root, orientation, deserializer, orthogonalSize, true);
1932
+ this.root = this._deserializeNode(root, orientation, deserializer, orthogonalSize);
1914
1933
  }
1915
- _deserializeNode(node, orientation, deserializer, orthogonalSize, isRoot = false) {
1934
+ _deserializeNode(node, orientation, deserializer, orthogonalSize) {
1916
1935
  let result;
1917
1936
  if (node.type === 'branch') {
1918
1937
  const serializedChildren = node.data;
@@ -1922,9 +1941,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1922
1941
  visible: serializedChild.visible,
1923
1942
  };
1924
1943
  });
1925
- // HORIZONTAL => height=orthogonalsize width=size
1926
- // VERTICAL => height=size width=orthogonalsize
1927
- result = new BranchNode(orientation, this.proportionalLayout, this.styles, isRoot ? orthogonalSize : node.size, isRoot ? node.size : orthogonalSize, children);
1944
+ result = new BranchNode(orientation, this.proportionalLayout, this.styles, node.size, // <- orthogonal size - flips at each depth
1945
+ orthogonalSize, // <- size - flips at each depth
1946
+ children);
1928
1947
  }
1929
1948
  else {
1930
1949
  result = new LeafNode(deserializer.fromJSON(node), orientation, orthogonalSize, node.size);
@@ -1957,7 +1976,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1957
1976
  const oldRoot = this.root;
1958
1977
  oldRoot.element.remove();
1959
1978
  this._root = new BranchNode(orthogonal(oldRoot.orientation), this.proportionalLayout, this.styles, this.root.orthogonalSize, this.root.size);
1960
- if (oldRoot.children.length === 1) {
1979
+ if (oldRoot.children.length === 0) ;
1980
+ else if (oldRoot.children.length === 1) {
1961
1981
  // can remove one level of redundant branching if there is only a single child
1962
1982
  const childReference = oldRoot.children[0];
1963
1983
  const child = oldRoot.removeChild(0); // remove to prevent disposal when disposing of unwanted root
@@ -2091,52 +2111,70 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2091
2111
  if (!(parent instanceof BranchNode)) {
2092
2112
  throw new Error('Invalid location');
2093
2113
  }
2094
- const node = parent.children[index];
2095
- if (!(node instanceof LeafNode)) {
2114
+ const nodeToRemove = parent.children[index];
2115
+ if (!(nodeToRemove instanceof LeafNode)) {
2096
2116
  throw new Error('Invalid location');
2097
2117
  }
2098
2118
  parent.removeChild(index, sizing);
2099
- if (parent.children.length === 0) {
2100
- return node.view;
2101
- }
2102
- if (parent.children.length > 1) {
2103
- return node.view;
2104
- }
2119
+ nodeToRemove.dispose();
2120
+ if (parent.children.length !== 1) {
2121
+ return nodeToRemove.view;
2122
+ }
2123
+ // if the parent has only one child and we know the parent is a BranchNode we can make the tree
2124
+ // more efficiently spaced by replacing the parent BranchNode with the child.
2125
+ // if that child is a LeafNode then we simply replace the BranchNode with the child otherwise if the child
2126
+ // is a BranchNode too we should spread it's children into the grandparent.
2127
+ // refer to the remaining child as the sibling
2105
2128
  const sibling = parent.children[0];
2106
2129
  if (pathToParent.length === 0) {
2107
- // parent is root
2130
+ // if the parent is root
2108
2131
  if (sibling instanceof LeafNode) {
2109
- return node.view;
2132
+ // if the sibling is a leaf node no action is required
2133
+ return nodeToRemove.view;
2110
2134
  }
2111
- // we must promote sibling to be the new root
2135
+ // otherwise the sibling is a branch node. since the parent is the root and the root has only one child
2136
+ // which is a branch node we can just set this branch node to be the new root node
2137
+ // for good housekeeping we'll removing the sibling from it's existing tree
2112
2138
  parent.removeChild(0, sizing);
2139
+ // and set that sibling node to be root
2113
2140
  this.root = sibling;
2114
- return node.view;
2141
+ return nodeToRemove.view;
2115
2142
  }
2143
+ // otherwise the parent is apart of a large sub-tree
2116
2144
  const [grandParent, ..._] = [...pathToParent].reverse();
2117
2145
  const [parentIndex, ...__] = [...rest].reverse();
2118
2146
  const isSiblingVisible = parent.isChildVisible(0);
2147
+ // either way we need to remove the sibling from it's existing tree
2119
2148
  parent.removeChild(0, sizing);
2149
+ // note the sizes of all of the grandparents children
2120
2150
  const sizes = grandParent.children.map((_size, i) => grandParent.getChildSize(i));
2121
- grandParent.removeChild(parentIndex, sizing);
2151
+ // remove the parent from the grandparent since we are moving the sibling to take the parents place
2152
+ // this parent is no longer used and can be disposed of
2153
+ grandParent.removeChild(parentIndex, sizing).dispose();
2122
2154
  if (sibling instanceof BranchNode) {
2155
+ // replace the parent with the siblings children
2123
2156
  sizes.splice(parentIndex, 1, ...sibling.children.map((c) => c.size));
2157
+ // and add those siblings to the grandparent
2124
2158
  for (let i = 0; i < sibling.children.length; i++) {
2125
2159
  const child = sibling.children[i];
2126
2160
  grandParent.addChild(child, child.size, parentIndex + i);
2127
2161
  }
2128
2162
  }
2129
2163
  else {
2164
+ // otherwise create a new leaf node and add that to the grandparent
2130
2165
  const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), sibling.size);
2131
2166
  const siblingSizing = isSiblingVisible
2132
2167
  ? sibling.orthogonalSize
2133
2168
  : exports.Sizing.Invisible(sibling.orthogonalSize);
2134
2169
  grandParent.addChild(newSibling, siblingSizing, parentIndex);
2135
2170
  }
2171
+ // the containing node of the sibling is no longer required and can be disposed of
2172
+ sibling.dispose();
2173
+ // resize everything
2136
2174
  for (let i = 0; i < sizes.length; i++) {
2137
2175
  grandParent.resizeChild(i, sizes[i]);
2138
2176
  }
2139
- return node.view;
2177
+ return nodeToRemove.view;
2140
2178
  }
2141
2179
  layout(width, height) {
2142
2180
  const [size, orthogonalSize] = this.root.orientation === exports.Orientation.HORIZONTAL
@@ -2455,6 +2493,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2455
2493
  addPanel(options) {
2456
2494
  return this.component.addPanel(options);
2457
2495
  }
2496
+ removePanel(panel) {
2497
+ this.component.removePanel(panel);
2498
+ }
2458
2499
  addGroup(options) {
2459
2500
  return this.component.addGroup(options);
2460
2501
  }
@@ -2473,6 +2514,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2473
2514
  getGroup(id) {
2474
2515
  return this.component.getPanel(id);
2475
2516
  }
2517
+ addFloatingGroup(item, coord) {
2518
+ return this.component.addFloatingGroup(item, coord);
2519
+ }
2476
2520
  fromJSON(data) {
2477
2521
  this.component.fromJSON(data);
2478
2522
  }
@@ -2565,10 +2609,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2565
2609
  this._onDrop = new Emitter();
2566
2610
  this.onDrop = this._onDrop.event;
2567
2611
  // use a set to take advantage of #<set>.has
2568
- const acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2612
+ this._acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2569
2613
  this.addDisposables(this._onDrop, new DragAndDropObserver(this.element, {
2570
2614
  onDragEnter: () => undefined,
2571
2615
  onDragOver: (e) => {
2616
+ if (this._acceptedTargetZonesSet.size === 0) {
2617
+ this.removeDropTarget();
2618
+ return;
2619
+ }
2572
2620
  const width = this.element.clientWidth;
2573
2621
  const height = this.element.clientHeight;
2574
2622
  if (width === 0 || height === 0) {
@@ -2577,20 +2625,28 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2577
2625
  const rect = e.currentTarget.getBoundingClientRect();
2578
2626
  const x = e.clientX - rect.left;
2579
2627
  const y = e.clientY - rect.top;
2580
- const quadrant = this.calculateQuadrant(acceptedTargetZonesSet, x, y, width, height);
2581
- if (quadrant === null) {
2628
+ const quadrant = this.calculateQuadrant(this._acceptedTargetZonesSet, x, y, width, height);
2629
+ /**
2630
+ * If the event has already been used by another DropTarget instance
2631
+ * then don't show a second drop target, only one target should be
2632
+ * active at any one time
2633
+ */
2634
+ if (this.isAlreadyUsed(e) || quadrant === null) {
2582
2635
  // no drop target should be displayed
2583
2636
  this.removeDropTarget();
2584
2637
  return;
2585
2638
  }
2586
2639
  if (typeof this.options.canDisplayOverlay === 'boolean') {
2587
2640
  if (!this.options.canDisplayOverlay) {
2641
+ this.removeDropTarget();
2588
2642
  return;
2589
2643
  }
2590
2644
  }
2591
2645
  else if (!this.options.canDisplayOverlay(e, quadrant)) {
2646
+ this.removeDropTarget();
2592
2647
  return;
2593
2648
  }
2649
+ this.markAsUsed(e);
2594
2650
  if (!this.targetElement) {
2595
2651
  this.targetElement = document.createElement('div');
2596
2652
  this.targetElement.className = 'drop-target-dropzone';
@@ -2601,12 +2657,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2601
2657
  this.element.classList.add('drop-target');
2602
2658
  this.element.append(this.targetElement);
2603
2659
  }
2604
- if (this.options.acceptedTargetZones.length === 0) {
2605
- return;
2606
- }
2607
- if (!this.targetElement || !this.overlayElement) {
2608
- return;
2609
- }
2610
2660
  this.toggleClasses(quadrant, width, height);
2611
2661
  this.setState(quadrant);
2612
2662
  },
@@ -2629,10 +2679,26 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2629
2679
  },
2630
2680
  }));
2631
2681
  }
2682
+ setTargetZones(acceptedTargetZones) {
2683
+ this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
2684
+ }
2632
2685
  dispose() {
2633
2686
  this.removeDropTarget();
2634
2687
  super.dispose();
2635
2688
  }
2689
+ /**
2690
+ * Add a property to the event object for other potential listeners to check
2691
+ */
2692
+ markAsUsed(event) {
2693
+ event[Droptarget.USED_EVENT_ID] = true;
2694
+ }
2695
+ /**
2696
+ * Check is the event has already been used by another instance od DropTarget
2697
+ */
2698
+ isAlreadyUsed(event) {
2699
+ const value = event[Droptarget.USED_EVENT_ID];
2700
+ return typeof value === 'boolean' && value;
2701
+ }
2636
2702
  toggleClasses(quadrant, width, height) {
2637
2703
  var _a, _b, _c, _d;
2638
2704
  if (!this.overlayElement) {
@@ -2727,6 +2793,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2727
2793
  }
2728
2794
  }
2729
2795
  }
2796
+ Droptarget.USED_EVENT_ID = '__dockview_droptarget_event_is_used__';
2730
2797
  function calculateQuadrantAsPercentage(overlayType, x, y, width, height, threshold) {
2731
2798
  const xp = (100 * x) / width;
2732
2799
  const yp = (100 * y) / height;
@@ -2856,8 +2923,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2856
2923
  this.addDisposables(this._onDragStart, this.dataDisposable, this.pointerEventsDisposable);
2857
2924
  this.configure();
2858
2925
  }
2926
+ isCancelled(_event) {
2927
+ return false;
2928
+ }
2859
2929
  configure() {
2860
2930
  this.addDisposables(this._onDragStart, addDisposableListener(this.el, 'dragstart', (event) => {
2931
+ if (this.isCancelled(event)) {
2932
+ event.preventDefault();
2933
+ return;
2934
+ }
2861
2935
  const iframes = [
2862
2936
  ...getElementsByTagName('iframe'),
2863
2937
  ...getElementsByTagName('webview'),
@@ -2931,13 +3005,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2931
3005
  if (event.defaultPrevented) {
2932
3006
  return;
2933
3007
  }
2934
- /**
2935
- * TODO: alternative to stopPropagation
2936
- *
2937
- * I need to stop the event propagation here since otherwise it'll be intercepted by event handlers
2938
- * on the tabs-container. I cannot use event.preventDefault() since I need the on DragStart event to occur
2939
- */
2940
- event.stopPropagation();
2941
3008
  this._onChanged.fire(event);
2942
3009
  }));
2943
3010
  this.droptarget = new Droptarget(this._element, {
@@ -2995,6 +3062,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2995
3062
  this.accessorId = accessorId;
2996
3063
  this.group = group;
2997
3064
  this.panelTransfer = LocalSelectionTransfer.getInstance();
3065
+ this.addDisposables(addDisposableListener(element, 'mousedown', (e) => {
3066
+ if (e.shiftKey) {
3067
+ /**
3068
+ * You cannot call e.preventDefault() because that will prevent drag events from firing
3069
+ * but we also need to stop any group overlay drag events from occuring
3070
+ * Use a custom event marker that can be checked by the overlay drag events
3071
+ */
3072
+ quasiPreventDefault(e);
3073
+ }
3074
+ }, true));
3075
+ }
3076
+ isCancelled(_event) {
3077
+ if (this.group.api.isFloating && !_event.shiftKey) {
3078
+ return true;
3079
+ }
3080
+ return false;
2998
3081
  }
2999
3082
  getData(dataTransfer) {
3000
3083
  this.panelTransfer.setData([new PanelTransfer(this.accessorId, this.group.id, null)], PanelTransfer.prototype);
@@ -3085,17 +3168,30 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3085
3168
  hide() {
3086
3169
  this._element.style.display = 'none';
3087
3170
  }
3088
- setActionElement(element) {
3089
- if (this.actions === element) {
3171
+ setRightActionsElement(element) {
3172
+ if (this.rightActions === element) {
3173
+ return;
3174
+ }
3175
+ if (this.rightActions) {
3176
+ this.rightActions.remove();
3177
+ this.rightActions = undefined;
3178
+ }
3179
+ if (element) {
3180
+ this.rightActionsContainer.appendChild(element);
3181
+ this.rightActions = element;
3182
+ }
3183
+ }
3184
+ setLeftActionsElement(element) {
3185
+ if (this.leftActions === element) {
3090
3186
  return;
3091
3187
  }
3092
- if (this.actions) {
3093
- this.actions.remove();
3094
- this.actions = undefined;
3188
+ if (this.leftActions) {
3189
+ this.leftActions.remove();
3190
+ this.leftActions = undefined;
3095
3191
  }
3096
3192
  if (element) {
3097
- this.actionContainer.appendChild(element);
3098
- this.actions = element;
3193
+ this.leftActionsContainer.appendChild(element);
3194
+ this.leftActions = element;
3099
3195
  }
3100
3196
  }
3101
3197
  get element() {
@@ -3130,19 +3226,35 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3130
3226
  toggleClass(this._element, 'dv-single-tab', this.size === 1);
3131
3227
  }
3132
3228
  }));
3133
- this.actionContainer = document.createElement('div');
3134
- this.actionContainer.className = 'action-container';
3229
+ this.rightActionsContainer = document.createElement('div');
3230
+ this.rightActionsContainer.className = 'right-actions-container';
3231
+ this.leftActionsContainer = document.createElement('div');
3232
+ this.leftActionsContainer.className = 'left-actions-container';
3135
3233
  this.tabContainer = document.createElement('div');
3136
3234
  this.tabContainer.className = 'tabs-container';
3137
3235
  this.voidContainer = new VoidContainer(this.accessor, this.group);
3138
3236
  this._element.appendChild(this.tabContainer);
3237
+ this._element.appendChild(this.leftActionsContainer);
3139
3238
  this._element.appendChild(this.voidContainer.element);
3140
- this._element.appendChild(this.actionContainer);
3239
+ this._element.appendChild(this.rightActionsContainer);
3141
3240
  this.addDisposables(this.voidContainer, this.voidContainer.onDrop((event) => {
3142
3241
  this._onDrop.fire({
3143
3242
  event: event.nativeEvent,
3144
3243
  index: this.tabs.length,
3145
3244
  });
3245
+ }), addDisposableListener(this.voidContainer.element, 'mousedown', (event) => {
3246
+ const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3247
+ if (isFloatingGroupsEnabled &&
3248
+ event.shiftKey &&
3249
+ !this.group.api.isFloating) {
3250
+ event.preventDefault();
3251
+ const { top, left } = this.element.getBoundingClientRect();
3252
+ const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
3253
+ this.accessor.addFloatingGroup(this.group, {
3254
+ x: left - rootLeft + 20,
3255
+ y: top - rootTop + 20,
3256
+ }, { inDragMode: true });
3257
+ }
3146
3258
  }), addDisposableListener(this.tabContainer, 'mousedown', (event) => {
3147
3259
  if (event.defaultPrevented) {
3148
3260
  return;
@@ -3196,6 +3308,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3196
3308
  tabToAdd.setContent(panel.view.tab);
3197
3309
  const disposable = CompositeDisposable.from(tabToAdd.onChanged((event) => {
3198
3310
  var _a;
3311
+ const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3312
+ const isFloatingWithOnePanel = this.group.api.isFloating && this.size === 1;
3313
+ if (isFloatingGroupsEnabled &&
3314
+ !isFloatingWithOnePanel &&
3315
+ event.shiftKey) {
3316
+ event.preventDefault();
3317
+ const panel = this.accessor.getGroupPanel(tabToAdd.panelId);
3318
+ const { top, left } = tabToAdd.element.getBoundingClientRect();
3319
+ const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
3320
+ this.accessor.addFloatingGroup(panel, {
3321
+ x: left - rootLeft,
3322
+ y: top - rootTop,
3323
+ }, { inDragMode: true });
3324
+ return;
3325
+ }
3199
3326
  const alreadyFocused = panel.id === ((_a = this.group.model.activePanel) === null || _a === void 0 ? void 0 : _a.id) &&
3200
3327
  this.group.model.isContentFocused;
3201
3328
  const isLeftClick = event.button === 0;
@@ -3265,6 +3392,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3265
3392
  }
3266
3393
  return isAncestor(document.activeElement, this.contentContainer.element);
3267
3394
  }
3395
+ get isFloating() {
3396
+ return this._isFloating;
3397
+ }
3398
+ set isFloating(value) {
3399
+ this._isFloating = value;
3400
+ this.dropTarget.setTargetZones(value ? ['center'] : ['top', 'bottom', 'left', 'right', 'center']);
3401
+ toggleClass(this.container, 'dv-groupview-floating', value);
3402
+ this.groupPanel.api._onDidFloatingStateChange.fire({
3403
+ isFloating: this.isFloating,
3404
+ });
3405
+ }
3268
3406
  constructor(container, accessor, id, options, groupPanel) {
3269
3407
  super();
3270
3408
  this.container = container;
@@ -3274,6 +3412,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3274
3412
  this.groupPanel = groupPanel;
3275
3413
  this._isGroupActive = false;
3276
3414
  this._locked = false;
3415
+ this._isFloating = false;
3277
3416
  this.mostRecentlyUsed = [];
3278
3417
  this._onDidChange = new Emitter();
3279
3418
  this.onDidChange = this._onDidChange.event;
@@ -3290,7 +3429,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3290
3429
  this.onDidRemovePanel = this._onDidRemovePanel.event;
3291
3430
  this._onDidActivePanelChange = new Emitter();
3292
3431
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
3293
- this.container.classList.add('groupview');
3432
+ toggleClass(this.container, 'groupview', true);
3294
3433
  this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
3295
3434
  this.contentContainer = new ContentContainer();
3296
3435
  this.dropTarget = new Droptarget(this.contentContainer.element, {
@@ -3300,6 +3439,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3300
3439
  return false;
3301
3440
  }
3302
3441
  const data = getPanelData();
3442
+ if (!data && event.shiftKey && !this.isFloating) {
3443
+ return false;
3444
+ }
3303
3445
  if (data && data.viewId === this.accessor.id) {
3304
3446
  if (data.groupId === this.id) {
3305
3447
  if (position === 'center') {
@@ -3344,14 +3486,25 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3344
3486
  // correctly initialized
3345
3487
  this.setActive(this.isActive, true, true);
3346
3488
  this.updateContainer();
3347
- if (this.accessor.options.createGroupControlElement) {
3348
- this._control = this.accessor.options.createGroupControlElement(this.groupPanel);
3349
- this.addDisposables(this._control);
3350
- this._control.init({
3489
+ if (this.accessor.options.createRightHeaderActionsElement) {
3490
+ this._rightHeaderActions =
3491
+ this.accessor.options.createRightHeaderActionsElement(this.groupPanel);
3492
+ this.addDisposables(this._rightHeaderActions);
3493
+ this._rightHeaderActions.init({
3494
+ containerApi: new DockviewApi(this.accessor),
3495
+ api: this.groupPanel.api,
3496
+ });
3497
+ this.tabsContainer.setRightActionsElement(this._rightHeaderActions.element);
3498
+ }
3499
+ if (this.accessor.options.createLeftHeaderActionsElement) {
3500
+ this._leftHeaderActions =
3501
+ this.accessor.options.createLeftHeaderActionsElement(this.groupPanel);
3502
+ this.addDisposables(this._leftHeaderActions);
3503
+ this._leftHeaderActions.init({
3351
3504
  containerApi: new DockviewApi(this.accessor),
3352
3505
  api: this.groupPanel.api,
3353
3506
  });
3354
- this.tabsContainer.setActionElement(this._control.element);
3507
+ this.tabsContainer.setLeftActionsElement(this._leftHeaderActions.element);
3355
3508
  }
3356
3509
  }
3357
3510
  indexOf(panel) {
@@ -3484,7 +3637,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3484
3637
  return this._activePanel === panel;
3485
3638
  }
3486
3639
  updateActions(element) {
3487
- this.tabsContainer.setActionElement(element);
3640
+ this.tabsContainer.setRightActionsElement(element);
3488
3641
  }
3489
3642
  setActive(isGroupActive, skipFocus = false, force = false) {
3490
3643
  var _a, _b, _c, _d;
@@ -3656,9 +3809,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3656
3809
  }
3657
3810
  }
3658
3811
  dispose() {
3659
- var _a, _b;
3812
+ var _a, _b, _c;
3660
3813
  super.dispose();
3661
- (_b = (_a = this.watermark) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
3814
+ (_a = this.watermark) === null || _a === void 0 ? void 0 : _a.element.remove();
3815
+ (_c = (_b = this.watermark) === null || _b === void 0 ? void 0 : _b.dispose) === null || _c === void 0 ? void 0 : _c.call(_b);
3662
3816
  for (const panel of this.panels) {
3663
3817
  panel.dispose();
3664
3818
  }
@@ -4452,8 +4606,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4452
4606
  get isActive() {
4453
4607
  return this.api.isActive;
4454
4608
  }
4455
- constructor(id, component, options) {
4456
- super(id, component, new GridviewPanelApiImpl(id));
4609
+ constructor(id, component, options, api) {
4610
+ super(id, component, api !== null && api !== void 0 ? api : new GridviewPanelApiImpl(id));
4457
4611
  this._evaluatedMinimumWidth = 0;
4458
4612
  this._evaluatedMaximumWidth = Number.MAX_SAFE_INTEGER;
4459
4613
  this._evaluatedMinimumHeight = 0;
@@ -4551,6 +4705,32 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4551
4705
  }
4552
4706
  }
4553
4707
 
4708
+ class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
4709
+ get isFloating() {
4710
+ if (!this._group) {
4711
+ throw new Error(`DockviewGroupPanelApiImpl not initialized`);
4712
+ }
4713
+ return this._group.model.isFloating;
4714
+ }
4715
+ constructor(id, accessor) {
4716
+ super(id);
4717
+ this.accessor = accessor;
4718
+ this._onDidFloatingStateChange = new Emitter();
4719
+ this.onDidFloatingStateChange = this._onDidFloatingStateChange.event;
4720
+ this.addDisposables(this._onDidFloatingStateChange);
4721
+ }
4722
+ moveTo(options) {
4723
+ var _a;
4724
+ if (!this._group) {
4725
+ throw new Error(`DockviewGroupPanelApiImpl not initialized`);
4726
+ }
4727
+ this.accessor.moveGroupOrPanel(options.group, this._group.id, undefined, (_a = options.position) !== null && _a !== void 0 ? _a : 'center');
4728
+ }
4729
+ initialize(group) {
4730
+ this._group = group;
4731
+ }
4732
+ }
4733
+
4554
4734
  class DockviewGroupPanel extends GridviewPanel {
4555
4735
  get panels() {
4556
4736
  return this._model.panels;
@@ -4577,7 +4757,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4577
4757
  super(id, 'groupview_default', {
4578
4758
  minimumHeight: 100,
4579
4759
  minimumWidth: 100,
4580
- });
4760
+ }, new DockviewGroupPanelApiImpl(id, accessor));
4761
+ this.api.initialize(this); // cannot use 'this' after after 'super' call
4581
4762
  this._model = new DockviewGroupPanelModel(this.element, accessor, id, options, this);
4582
4763
  }
4583
4764
  initialize() {
@@ -4595,7 +4776,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4595
4776
  return this._model;
4596
4777
  }
4597
4778
  toJSON() {
4598
- // TODO fix typing
4599
4779
  return this.model.toJSON();
4600
4780
  }
4601
4781
  }
@@ -4649,9 +4829,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4649
4829
  get group() {
4650
4830
  return this._group;
4651
4831
  }
4652
- constructor(panel, group) {
4832
+ constructor(panel, group, accessor) {
4653
4833
  super(panel.id);
4654
4834
  this.panel = panel;
4835
+ this.accessor = accessor;
4655
4836
  this._onDidTitleChange = new Emitter();
4656
4837
  this.onDidTitleChange = this._onDidTitleChange.event;
4657
4838
  this._onDidActiveGroupChange = new Emitter();
@@ -4663,6 +4844,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4663
4844
  this._group = group;
4664
4845
  this.addDisposables(this.disposable, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
4665
4846
  }
4847
+ moveTo(options) {
4848
+ var _a;
4849
+ this.accessor.moveGroupOrPanel(options.group, this._group.id, this.panel.id, (_a = options.position) !== null && _a !== void 0 ? _a : 'center', options.index);
4850
+ }
4666
4851
  setTitle(title) {
4667
4852
  this.panel.setTitle(title);
4668
4853
  }
@@ -4687,7 +4872,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4687
4872
  this.containerApi = containerApi;
4688
4873
  this.view = view;
4689
4874
  this._group = group;
4690
- this.api = new DockviewPanelApiImpl(this, this._group);
4875
+ this.api = new DockviewPanelApiImpl(this, this._group, accessor);
4691
4876
  this.addDisposables(this.api.onActiveChange(() => {
4692
4877
  accessor.setActivePanel(this);
4693
4878
  }), this.api.onDidSizeChange((event) => {
@@ -5028,6 +5213,296 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5028
5213
  }
5029
5214
  }
5030
5215
 
5216
+ const bringElementToFront = (() => {
5217
+ let previous = null;
5218
+ function pushToTop(element) {
5219
+ if (previous !== element && previous !== null) {
5220
+ toggleClass(previous, 'dv-bring-to-front', false);
5221
+ }
5222
+ toggleClass(element, 'dv-bring-to-front', true);
5223
+ previous = element;
5224
+ }
5225
+ return pushToTop;
5226
+ })();
5227
+ class Overlay extends CompositeDisposable {
5228
+ constructor(options) {
5229
+ super();
5230
+ this.options = options;
5231
+ this._element = document.createElement('div');
5232
+ this._onDidChange = new Emitter();
5233
+ this.onDidChange = this._onDidChange.event;
5234
+ this._onDidChangeEnd = new Emitter();
5235
+ this.onDidChangeEnd = this._onDidChangeEnd.event;
5236
+ this.addDisposables(this._onDidChange, this._onDidChangeEnd);
5237
+ this._element.className = 'dv-resize-container';
5238
+ this.setupResize('top');
5239
+ this.setupResize('bottom');
5240
+ this.setupResize('left');
5241
+ this.setupResize('right');
5242
+ this.setupResize('topleft');
5243
+ this.setupResize('topright');
5244
+ this.setupResize('bottomleft');
5245
+ this.setupResize('bottomright');
5246
+ this._element.appendChild(this.options.content);
5247
+ this.options.container.appendChild(this._element);
5248
+ // if input bad resize within acceptable boundaries
5249
+ this.setBounds({
5250
+ height: this.options.height,
5251
+ width: this.options.width,
5252
+ top: this.options.top,
5253
+ left: this.options.left,
5254
+ });
5255
+ }
5256
+ setBounds(bounds = {}) {
5257
+ if (typeof bounds.height === 'number') {
5258
+ this._element.style.height = `${bounds.height}px`;
5259
+ }
5260
+ if (typeof bounds.width === 'number') {
5261
+ this._element.style.width = `${bounds.width}px`;
5262
+ }
5263
+ if (typeof bounds.top === 'number') {
5264
+ this._element.style.top = `${bounds.top}px`;
5265
+ }
5266
+ if (typeof bounds.left === 'number') {
5267
+ this._element.style.left = `${bounds.left}px`;
5268
+ }
5269
+ const containerRect = this.options.container.getBoundingClientRect();
5270
+ const overlayRect = this._element.getBoundingClientRect();
5271
+ // region: ensure bounds within allowable limits
5272
+ // a minimum width of minimumViewportWidth must be inside the viewport
5273
+ const xOffset = Math.max(0, overlayRect.width - this.options.minimumInViewportWidth);
5274
+ // a minimum height of minimumViewportHeight must be inside the viewport
5275
+ const yOffset = Math.max(0, overlayRect.height - this.options.minimumInViewportHeight);
5276
+ const left = clamp(overlayRect.left - containerRect.left, -xOffset, Math.max(0, containerRect.width - overlayRect.width + xOffset));
5277
+ const top = clamp(overlayRect.top - containerRect.top, -yOffset, Math.max(0, containerRect.height - overlayRect.height + yOffset));
5278
+ this._element.style.left = `${left}px`;
5279
+ this._element.style.top = `${top}px`;
5280
+ this._onDidChange.fire();
5281
+ }
5282
+ toJSON() {
5283
+ const container = this.options.container.getBoundingClientRect();
5284
+ const element = this._element.getBoundingClientRect();
5285
+ return {
5286
+ top: element.top - container.top,
5287
+ left: element.left - container.left,
5288
+ width: element.width,
5289
+ height: element.height,
5290
+ };
5291
+ }
5292
+ setupDrag(dragTarget, options = { inDragMode: false }) {
5293
+ const move = new MutableDisposable();
5294
+ const track = () => {
5295
+ let offset = null;
5296
+ const iframes = [
5297
+ ...getElementsByTagName('iframe'),
5298
+ ...getElementsByTagName('webview'),
5299
+ ];
5300
+ for (const iframe of iframes) {
5301
+ iframe.style.pointerEvents = 'none';
5302
+ }
5303
+ move.value = new CompositeDisposable({
5304
+ dispose: () => {
5305
+ for (const iframe of iframes) {
5306
+ iframe.style.pointerEvents = 'auto';
5307
+ }
5308
+ },
5309
+ }, addDisposableWindowListener(window, 'mousemove', (e) => {
5310
+ const containerRect = this.options.container.getBoundingClientRect();
5311
+ const x = e.clientX - containerRect.left;
5312
+ const y = e.clientY - containerRect.top;
5313
+ toggleClass(this._element, 'dv-resize-container-dragging', true);
5314
+ const overlayRect = this._element.getBoundingClientRect();
5315
+ if (offset === null) {
5316
+ offset = {
5317
+ x: e.clientX - overlayRect.left,
5318
+ y: e.clientY - overlayRect.top,
5319
+ };
5320
+ }
5321
+ const xOffset = Math.max(0, overlayRect.width - this.options.minimumInViewportWidth);
5322
+ const yOffset = Math.max(0, overlayRect.height -
5323
+ this.options.minimumInViewportHeight);
5324
+ const left = clamp(x - offset.x, -xOffset, Math.max(0, containerRect.width - overlayRect.width + xOffset));
5325
+ const top = clamp(y - offset.y, -yOffset, Math.max(0, containerRect.height - overlayRect.height + yOffset));
5326
+ this.setBounds({ top, left });
5327
+ }), addDisposableWindowListener(window, 'mouseup', () => {
5328
+ toggleClass(this._element, 'dv-resize-container-dragging', false);
5329
+ move.dispose();
5330
+ this._onDidChangeEnd.fire();
5331
+ }));
5332
+ };
5333
+ this.addDisposables(move, addDisposableListener(dragTarget, 'mousedown', (event) => {
5334
+ if (event.defaultPrevented) {
5335
+ event.preventDefault();
5336
+ return;
5337
+ }
5338
+ // if somebody has marked this event then treat as a defaultPrevented
5339
+ // without actually calling event.preventDefault()
5340
+ if (quasiDefaultPrevented(event)) {
5341
+ return;
5342
+ }
5343
+ track();
5344
+ }), addDisposableListener(this.options.content, 'mousedown', (event) => {
5345
+ if (event.defaultPrevented) {
5346
+ return;
5347
+ }
5348
+ // if somebody has marked this event then treat as a defaultPrevented
5349
+ // without actually calling event.preventDefault()
5350
+ if (quasiDefaultPrevented(event)) {
5351
+ return;
5352
+ }
5353
+ if (event.shiftKey) {
5354
+ track();
5355
+ }
5356
+ }), addDisposableListener(this.options.content, 'mousedown', () => {
5357
+ bringElementToFront(this._element);
5358
+ }, true));
5359
+ bringElementToFront(this._element);
5360
+ if (options.inDragMode) {
5361
+ track();
5362
+ }
5363
+ }
5364
+ setupResize(direction) {
5365
+ const resizeHandleElement = document.createElement('div');
5366
+ resizeHandleElement.className = `dv-resize-handle-${direction}`;
5367
+ this._element.appendChild(resizeHandleElement);
5368
+ const move = new MutableDisposable();
5369
+ this.addDisposables(move, addDisposableListener(resizeHandleElement, 'mousedown', (e) => {
5370
+ e.preventDefault();
5371
+ let startPosition = null;
5372
+ const iframes = [
5373
+ ...getElementsByTagName('iframe'),
5374
+ ...getElementsByTagName('webview'),
5375
+ ];
5376
+ for (const iframe of iframes) {
5377
+ iframe.style.pointerEvents = 'none';
5378
+ }
5379
+ move.value = new CompositeDisposable(addDisposableWindowListener(window, 'mousemove', (e) => {
5380
+ const containerRect = this.options.container.getBoundingClientRect();
5381
+ const overlayRect = this._element.getBoundingClientRect();
5382
+ const y = e.clientY - containerRect.top;
5383
+ const x = e.clientX - containerRect.left;
5384
+ if (startPosition === null) {
5385
+ // record the initial dimensions since as all subsequence moves are relative to this
5386
+ startPosition = {
5387
+ originalY: y,
5388
+ originalHeight: overlayRect.height,
5389
+ originalX: x,
5390
+ originalWidth: overlayRect.width,
5391
+ };
5392
+ }
5393
+ let top = undefined;
5394
+ let height = undefined;
5395
+ let left = undefined;
5396
+ let width = undefined;
5397
+ const minimumInViewportHeight = this.options.minimumInViewportHeight;
5398
+ const minimumInViewportWidth = this.options.minimumInViewportWidth;
5399
+ function moveTop() {
5400
+ top = clamp(y, -Number.MAX_VALUE, startPosition.originalY +
5401
+ startPosition.originalHeight >
5402
+ containerRect.height
5403
+ ? containerRect.height -
5404
+ minimumInViewportHeight
5405
+ : Math.max(0, startPosition.originalY +
5406
+ startPosition.originalHeight -
5407
+ Overlay.MINIMUM_HEIGHT));
5408
+ height =
5409
+ startPosition.originalY +
5410
+ startPosition.originalHeight -
5411
+ top;
5412
+ }
5413
+ function moveBottom() {
5414
+ top =
5415
+ startPosition.originalY -
5416
+ startPosition.originalHeight;
5417
+ height = clamp(y - top, top < 0
5418
+ ? -top + minimumInViewportHeight
5419
+ : Overlay.MINIMUM_HEIGHT, Number.MAX_VALUE);
5420
+ }
5421
+ function moveLeft() {
5422
+ left = clamp(x, -Number.MAX_VALUE, startPosition.originalX +
5423
+ startPosition.originalWidth >
5424
+ containerRect.width
5425
+ ? containerRect.width -
5426
+ minimumInViewportWidth
5427
+ : Math.max(0, startPosition.originalX +
5428
+ startPosition.originalWidth -
5429
+ Overlay.MINIMUM_WIDTH));
5430
+ width =
5431
+ startPosition.originalX +
5432
+ startPosition.originalWidth -
5433
+ left;
5434
+ }
5435
+ function moveRight() {
5436
+ left =
5437
+ startPosition.originalX -
5438
+ startPosition.originalWidth;
5439
+ width = clamp(x - left, left < 0
5440
+ ? -left + minimumInViewportWidth
5441
+ : Overlay.MINIMUM_WIDTH, Number.MAX_VALUE);
5442
+ }
5443
+ switch (direction) {
5444
+ case 'top':
5445
+ moveTop();
5446
+ break;
5447
+ case 'bottom':
5448
+ moveBottom();
5449
+ break;
5450
+ case 'left':
5451
+ moveLeft();
5452
+ break;
5453
+ case 'right':
5454
+ moveRight();
5455
+ break;
5456
+ case 'topleft':
5457
+ moveTop();
5458
+ moveLeft();
5459
+ break;
5460
+ case 'topright':
5461
+ moveTop();
5462
+ moveRight();
5463
+ break;
5464
+ case 'bottomleft':
5465
+ moveBottom();
5466
+ moveLeft();
5467
+ break;
5468
+ case 'bottomright':
5469
+ moveBottom();
5470
+ moveRight();
5471
+ break;
5472
+ }
5473
+ this.setBounds({ height, width, top, left });
5474
+ }), {
5475
+ dispose: () => {
5476
+ for (const iframe of iframes) {
5477
+ iframe.style.pointerEvents = 'auto';
5478
+ }
5479
+ },
5480
+ }, addDisposableWindowListener(window, 'mouseup', () => {
5481
+ move.dispose();
5482
+ this._onDidChangeEnd.fire();
5483
+ }));
5484
+ }));
5485
+ }
5486
+ dispose() {
5487
+ this._element.remove();
5488
+ super.dispose();
5489
+ }
5490
+ }
5491
+ Overlay.MINIMUM_HEIGHT = 20;
5492
+ Overlay.MINIMUM_WIDTH = 20;
5493
+
5494
+ class DockviewFloatingGroupPanel extends CompositeDisposable {
5495
+ constructor(group, overlay) {
5496
+ super();
5497
+ this.group = group;
5498
+ this.overlay = overlay;
5499
+ this.addDisposables(overlay);
5500
+ }
5501
+ position(bounds) {
5502
+ this.overlay.setBounds(bounds);
5503
+ }
5504
+ }
5505
+
5031
5506
  class DockviewComponent extends BaseGrid {
5032
5507
  get orientation() {
5033
5508
  return this.gridview.orientation;
@@ -5068,7 +5543,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5068
5543
  this.onDidLayoutFromJSON = this._onDidLayoutFromJSON.event;
5069
5544
  this._onDidActivePanelChange = new Emitter();
5070
5545
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
5071
- this.element.classList.add('dv-dockview');
5546
+ this.floatingGroups = [];
5547
+ toggleClass(this.gridview.element, 'dv-dockview', true);
5072
5548
  this.addDisposables(this._onDidDrop, exports.DockviewEvent.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
5073
5549
  this.updateWatermark();
5074
5550
  }), exports.DockviewEvent.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidActivePanelChange)(() => {
@@ -5098,6 +5574,11 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5098
5574
  if (data.viewId !== this.id) {
5099
5575
  return false;
5100
5576
  }
5577
+ if (position === 'center') {
5578
+ // center drop target is only allowed if there are no panels in the grid
5579
+ // floating panels are allowed
5580
+ return this.gridview.length === 0;
5581
+ }
5101
5582
  return true;
5102
5583
  }
5103
5584
  if (this.options.showDndOverlay) {
@@ -5110,7 +5591,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5110
5591
  }
5111
5592
  return false;
5112
5593
  },
5113
- acceptedTargetZones: ['top', 'bottom', 'left', 'right'],
5594
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
5114
5595
  overlayModel: {
5115
5596
  activationSize: { type: 'pixels', value: 10 },
5116
5597
  size: { type: 'pixels', value: 20 },
@@ -5128,6 +5609,75 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5128
5609
  this._api = new DockviewApi(this);
5129
5610
  this.updateWatermark();
5130
5611
  }
5612
+ addFloatingGroup(item, coord, options) {
5613
+ var _a, _b;
5614
+ let group;
5615
+ if (item instanceof DockviewPanel) {
5616
+ group = this.createGroup();
5617
+ this.removePanel(item, {
5618
+ removeEmptyGroup: true,
5619
+ skipDispose: true,
5620
+ });
5621
+ group.model.openPanel(item);
5622
+ }
5623
+ else {
5624
+ group = item;
5625
+ const skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
5626
+ options.skipRemoveGroup;
5627
+ if (!skip) {
5628
+ this.doRemoveGroup(item, { skipDispose: true });
5629
+ }
5630
+ }
5631
+ group.model.isFloating = true;
5632
+ const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number' ? Math.max(coord.x, 0) : 100;
5633
+ const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number' ? Math.max(coord.y, 0) : 100;
5634
+ const overlay = new Overlay({
5635
+ container: this.gridview.element,
5636
+ content: group.element,
5637
+ height: (_a = coord === null || coord === void 0 ? void 0 : coord.height) !== null && _a !== void 0 ? _a : 300,
5638
+ width: (_b = coord === null || coord === void 0 ? void 0 : coord.width) !== null && _b !== void 0 ? _b : 300,
5639
+ left: overlayLeft,
5640
+ top: overlayTop,
5641
+ minimumInViewportWidth: 100,
5642
+ minimumInViewportHeight: 100,
5643
+ });
5644
+ const el = group.element.querySelector('.void-container');
5645
+ if (!el) {
5646
+ throw new Error('failed to find drag handle');
5647
+ }
5648
+ overlay.setupDrag(el, {
5649
+ inDragMode: typeof (options === null || options === void 0 ? void 0 : options.inDragMode) === 'boolean'
5650
+ ? options.inDragMode
5651
+ : false,
5652
+ });
5653
+ const floatingGroupPanel = new DockviewFloatingGroupPanel(group, overlay);
5654
+ const disposable = watchElementResize(group.element, (entry) => {
5655
+ const { width, height } = entry.contentRect;
5656
+ group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
5657
+ });
5658
+ floatingGroupPanel.addDisposables(overlay.onDidChange(() => {
5659
+ // this is either a resize or a move
5660
+ // to inform the panels .layout(...) the group with it's current size
5661
+ // don't care about resize since the above watcher handles that
5662
+ group.layout(group.height, group.width);
5663
+ }), overlay.onDidChangeEnd(() => {
5664
+ this._bufferOnDidLayoutChange.fire();
5665
+ }), group.onDidChange((event) => {
5666
+ overlay.setBounds({
5667
+ height: event === null || event === void 0 ? void 0 : event.height,
5668
+ width: event === null || event === void 0 ? void 0 : event.width,
5669
+ });
5670
+ }), {
5671
+ dispose: () => {
5672
+ disposable.dispose();
5673
+ group.model.isFloating = false;
5674
+ remove(this.floatingGroups, floatingGroupPanel);
5675
+ this.updateWatermark();
5676
+ },
5677
+ });
5678
+ this.floatingGroups.push(floatingGroupPanel);
5679
+ this.updateWatermark();
5680
+ }
5131
5681
  orthogonalize(position) {
5132
5682
  switch (position) {
5133
5683
  case 'top':
@@ -5150,6 +5700,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5150
5700
  switch (position) {
5151
5701
  case 'top':
5152
5702
  case 'left':
5703
+ case 'center':
5153
5704
  return this.createGroupAtLocation([0]); // insert into first position
5154
5705
  case 'bottom':
5155
5706
  case 'right':
@@ -5167,6 +5718,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5167
5718
  }
5168
5719
  this.layout(this.gridview.width, this.gridview.height, true);
5169
5720
  }
5721
+ layout(width, height, forceResize) {
5722
+ super.layout(width, height, forceResize);
5723
+ if (this.floatingGroups) {
5724
+ for (const floating of this.floatingGroups) {
5725
+ // ensure floting groups stay within visible boundaries
5726
+ floating.overlay.setBounds();
5727
+ }
5728
+ }
5729
+ }
5170
5730
  focus() {
5171
5731
  var _a;
5172
5732
  (_a = this.activeGroup) === null || _a === void 0 ? void 0 : _a.focus();
@@ -5229,51 +5789,81 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5229
5789
  collection[panel.id] = panel.toJSON();
5230
5790
  return collection;
5231
5791
  }, {});
5232
- return {
5792
+ const floats = this.floatingGroups.map((floatingGroup) => {
5793
+ return {
5794
+ data: floatingGroup.group.toJSON(),
5795
+ position: floatingGroup.overlay.toJSON(),
5796
+ };
5797
+ });
5798
+ const result = {
5233
5799
  grid: data,
5234
5800
  panels,
5235
5801
  activeGroup: (_a = this.activeGroup) === null || _a === void 0 ? void 0 : _a.id,
5236
5802
  };
5803
+ if (floats.length > 0) {
5804
+ result.floatingGroups = floats;
5805
+ }
5806
+ return result;
5237
5807
  }
5238
5808
  fromJSON(data) {
5809
+ var _a;
5239
5810
  this.clear();
5240
5811
  const { grid, panels, activeGroup } = data;
5241
5812
  if (grid.root.type !== 'branch' || !Array.isArray(grid.root.data)) {
5242
5813
  throw new Error('root must be of type branch');
5243
5814
  }
5815
+ // take note of the existing dimensions
5816
+ const width = this.width;
5817
+ const height = this.height;
5818
+ const createGroupFromSerializedState = (data) => {
5819
+ const { id, locked, hideHeader, views, activeView } = data;
5820
+ const group = this.createGroup({
5821
+ id,
5822
+ locked: !!locked,
5823
+ hideHeader: !!hideHeader,
5824
+ });
5825
+ this._onDidAddGroup.fire(group);
5826
+ for (const child of views) {
5827
+ const panel = this._deserializer.fromJSON(panels[child], group);
5828
+ const isActive = typeof activeView === 'string' && activeView === panel.id;
5829
+ group.model.openPanel(panel, {
5830
+ skipSetPanelActive: !isActive,
5831
+ skipSetGroupActive: true,
5832
+ });
5833
+ }
5834
+ if (!group.activePanel && group.panels.length > 0) {
5835
+ group.model.openPanel(group.panels[group.panels.length - 1], {
5836
+ skipSetGroupActive: true,
5837
+ });
5838
+ }
5839
+ return group;
5840
+ };
5244
5841
  this.gridview.deserialize(grid, {
5245
5842
  fromJSON: (node) => {
5246
- const { id, locked, hideHeader, views, activeView } = node.data;
5247
- const group = this.createGroup({
5248
- id,
5249
- locked: !!locked,
5250
- hideHeader: !!hideHeader,
5251
- });
5252
- this._onDidAddGroup.fire(group);
5253
- for (const child of views) {
5254
- const panel = this._deserializer.fromJSON(panels[child], group);
5255
- const isActive = typeof activeView === 'string' &&
5256
- activeView === panel.id;
5257
- group.model.openPanel(panel, {
5258
- skipSetPanelActive: !isActive,
5259
- skipSetGroupActive: true,
5260
- });
5261
- }
5262
- if (!group.activePanel && group.panels.length > 0) {
5263
- group.model.openPanel(group.panels[group.panels.length - 1], {
5264
- skipSetGroupActive: true,
5265
- });
5266
- }
5267
- return group;
5843
+ return createGroupFromSerializedState(node.data);
5268
5844
  },
5269
5845
  });
5846
+ this.layout(width, height, true);
5847
+ const serializedFloatingGroups = (_a = data.floatingGroups) !== null && _a !== void 0 ? _a : [];
5848
+ for (const serializedFloatingGroup of serializedFloatingGroups) {
5849
+ const { data, position } = serializedFloatingGroup;
5850
+ const group = createGroupFromSerializedState(data);
5851
+ this.addFloatingGroup(group, {
5852
+ x: position.left,
5853
+ y: position.top,
5854
+ height: position.height,
5855
+ width: position.width,
5856
+ }, { skipRemoveGroup: true, inDragMode: false });
5857
+ }
5858
+ for (const floatingGroup of this.floatingGroups) {
5859
+ floatingGroup.overlay.setBounds();
5860
+ }
5270
5861
  if (typeof activeGroup === 'string') {
5271
5862
  const panel = this.getPanel(activeGroup);
5272
5863
  if (panel) {
5273
5864
  this.doSetGroupActive(panel);
5274
5865
  }
5275
5866
  }
5276
- this.gridview.layout(this.width, this.height);
5277
5867
  this._onDidLayoutFromJSON.fire();
5278
5868
  }
5279
5869
  clear() {
@@ -5282,7 +5872,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5282
5872
  const hasActivePanel = !!this.activePanel;
5283
5873
  for (const group of groups) {
5284
5874
  // remove the group will automatically remove the panels
5285
- this.removeGroup(group, true);
5875
+ this.removeGroup(group, { skipActive: true });
5286
5876
  }
5287
5877
  if (hasActiveGroup) {
5288
5878
  this.doSetGroupActive(undefined);
@@ -5304,6 +5894,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5304
5894
  throw new Error(`panel with id ${options.id} already exists`);
5305
5895
  }
5306
5896
  let referenceGroup;
5897
+ if (options.position && options.floating) {
5898
+ throw new Error('you can only provide one of: position, floating as arguments to .addPanel(...)');
5899
+ }
5307
5900
  if (options.position) {
5308
5901
  if (isPanelOptionsWithPanel(options.position)) {
5309
5902
  const referencePanel = typeof options.position.referencePanel === 'string'
@@ -5336,7 +5929,20 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5336
5929
  let panel;
5337
5930
  if (referenceGroup) {
5338
5931
  const target = toTarget(((_b = options.position) === null || _b === void 0 ? void 0 : _b.direction) || 'within');
5339
- if (target === 'center') {
5932
+ if (options.floating) {
5933
+ const group = this.createGroup();
5934
+ panel = this.createPanel(options, group);
5935
+ group.model.openPanel(panel);
5936
+ const o = typeof options.floating === 'object' &&
5937
+ options.floating !== null
5938
+ ? options.floating
5939
+ : {};
5940
+ this.addFloatingGroup(group, o, {
5941
+ inDragMode: false,
5942
+ skipRemoveGroup: true,
5943
+ });
5944
+ }
5945
+ else if (referenceGroup.api.isFloating || target === 'center') {
5340
5946
  panel = this.createPanel(options, referenceGroup);
5341
5947
  referenceGroup.model.openPanel(panel);
5342
5948
  }
@@ -5348,6 +5954,19 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5348
5954
  group.model.openPanel(panel);
5349
5955
  }
5350
5956
  }
5957
+ else if (options.floating) {
5958
+ const group = this.createGroup();
5959
+ panel = this.createPanel(options, group);
5960
+ group.model.openPanel(panel);
5961
+ const o = typeof options.floating === 'object' &&
5962
+ options.floating !== null
5963
+ ? options.floating
5964
+ : {};
5965
+ this.addFloatingGroup(group, o, {
5966
+ inDragMode: false,
5967
+ skipRemoveGroup: true,
5968
+ });
5969
+ }
5351
5970
  else {
5352
5971
  const group = this.createGroupAtLocation();
5353
5972
  panel = this.createPanel(options, group);
@@ -5364,7 +5983,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5364
5983
  throw new Error(`cannot remove panel ${panel.id}. it's missing a group.`);
5365
5984
  }
5366
5985
  group.model.removePanel(panel);
5367
- panel.dispose();
5986
+ if (!options.skipDispose) {
5987
+ panel.dispose();
5988
+ }
5368
5989
  if (group.size === 0 && options.removeEmptyGroup) {
5369
5990
  this.removeGroup(group);
5370
5991
  }
@@ -5379,7 +6000,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5379
6000
  }
5380
6001
  updateWatermark() {
5381
6002
  var _a, _b;
5382
- if (this.groups.length === 0) {
6003
+ if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
5383
6004
  if (!this.watermark) {
5384
6005
  this.watermark = this.createWatermarkComponent();
5385
6006
  this.watermark.init({
@@ -5388,7 +6009,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5388
6009
  const watermarkContainer = document.createElement('div');
5389
6010
  watermarkContainer.className = 'dv-watermark-container';
5390
6011
  watermarkContainer.appendChild(this.watermark.element);
5391
- this.element.appendChild(watermarkContainer);
6012
+ this.gridview.element.appendChild(watermarkContainer);
5392
6013
  }
5393
6014
  }
5394
6015
  else if (this.watermark) {
@@ -5438,15 +6059,28 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5438
6059
  return group;
5439
6060
  }
5440
6061
  }
5441
- removeGroup(group, skipActive = false) {
6062
+ removeGroup(group, options) {
6063
+ var _a;
5442
6064
  const panels = [...group.panels]; // reassign since group panels will mutate
5443
6065
  for (const panel of panels) {
5444
6066
  this.removePanel(panel, {
5445
6067
  removeEmptyGroup: false,
5446
- skipDispose: false,
6068
+ skipDispose: (_a = options === null || options === void 0 ? void 0 : options.skipDispose) !== null && _a !== void 0 ? _a : false,
5447
6069
  });
5448
6070
  }
5449
- super.doRemoveGroup(group, { skipActive });
6071
+ this.doRemoveGroup(group, options);
6072
+ }
6073
+ doRemoveGroup(group, options) {
6074
+ const floatingGroup = this.floatingGroups.find((_) => _.group === group);
6075
+ if (floatingGroup) {
6076
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6077
+ floatingGroup.group.dispose();
6078
+ this._groups.delete(group.id);
6079
+ }
6080
+ floatingGroup.dispose();
6081
+ return floatingGroup.group;
6082
+ }
6083
+ return super.doRemoveGroup(group, options);
5450
6084
  }
5451
6085
  moveGroupOrPanel(destinationGroup, sourceGroupId, sourceItemId, destinationTarget, destinationIndex) {
5452
6086
  var _a;
@@ -5477,25 +6111,26 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5477
6111
  const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
5478
6112
  if (sourceGroup && sourceGroup.size < 2) {
5479
6113
  const [targetParentLocation, to] = tail(targetLocation);
5480
- const sourceLocation = getGridLocation(sourceGroup.element);
5481
- const [sourceParentLocation, from] = tail(sourceLocation);
5482
- if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
5483
- // special case when 'swapping' two views within same grid location
5484
- // if a group has one tab - we are essentially moving the 'group'
5485
- // which is equivalent to swapping two views in this case
5486
- this.gridview.moveView(sourceParentLocation, from, to);
5487
- }
5488
- else {
5489
- // source group will become empty so delete the group
5490
- const targetGroup = this.doRemoveGroup(sourceGroup, {
5491
- skipActive: true,
5492
- skipDispose: true,
5493
- });
5494
- // after deleting the group we need to re-evaulate the ref location
5495
- const updatedReferenceLocation = getGridLocation(destinationGroup.element);
5496
- const location = getRelativeLocation(this.gridview.orientation, updatedReferenceLocation, destinationTarget);
5497
- this.doAddGroup(targetGroup, location);
6114
+ const isFloating = this.floatingGroups.find((x) => x.group === sourceGroup);
6115
+ if (!isFloating) {
6116
+ const sourceLocation = getGridLocation(sourceGroup.element);
6117
+ const [sourceParentLocation, from] = tail(sourceLocation);
6118
+ if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
6119
+ // special case when 'swapping' two views within same grid location
6120
+ // if a group has one tab - we are essentially moving the 'group'
6121
+ // which is equivalent to swapping two views in this case
6122
+ this.gridview.moveView(sourceParentLocation, from, to);
6123
+ }
5498
6124
  }
6125
+ // source group will become empty so delete the group
6126
+ const targetGroup = this.doRemoveGroup(sourceGroup, {
6127
+ skipActive: true,
6128
+ skipDispose: true,
6129
+ });
6130
+ // after deleting the group we need to re-evaulate the ref location
6131
+ const updatedReferenceLocation = getGridLocation(destinationGroup.element);
6132
+ const location = getRelativeLocation(this.gridview.orientation, updatedReferenceLocation, destinationTarget);
6133
+ this.doAddGroup(targetGroup, location);
5499
6134
  }
5500
6135
  else {
5501
6136
  const groupItem = (sourceGroup === null || sourceGroup === void 0 ? void 0 : sourceGroup.model.removePanel(sourceItemId)) ||
@@ -5524,7 +6159,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5524
6159
  }
5525
6160
  }
5526
6161
  else {
5527
- this.gridview.removeView(getGridLocation(sourceGroup.element));
6162
+ const floatingGroup = this.floatingGroups.find((x) => x.group === sourceGroup);
6163
+ if (floatingGroup) {
6164
+ floatingGroup.dispose();
6165
+ }
6166
+ else {
6167
+ this.gridview.removeView(getGridLocation(sourceGroup.element));
6168
+ }
5528
6169
  const referenceLocation = getGridLocation(referenceGroup.element);
5529
6170
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, target);
5530
6171
  this.gridview.addView(sourceGroup, exports.Sizing.Distribute, dropLocation);
@@ -5679,6 +6320,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5679
6320
  this.clear();
5680
6321
  const { grid, activePanel } = serializedGridview;
5681
6322
  const queue = [];
6323
+ // take note of the existing dimensions
6324
+ const width = this.width;
6325
+ const height = this.height;
5682
6326
  this.gridview.deserialize(grid, {
5683
6327
  fromJSON: (node) => {
5684
6328
  const { data } = node;
@@ -5704,7 +6348,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5704
6348
  return view;
5705
6349
  },
5706
6350
  });
5707
- this.layout(this.width, this.height, true);
6351
+ this.layout(width, height, true);
5708
6352
  queue.forEach((f) => f());
5709
6353
  if (typeof activePanel === 'string') {
5710
6354
  const panel = this.getPanel(activePanel);
@@ -6018,6 +6662,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6018
6662
  this.clear();
6019
6663
  const { views, orientation, size, activeView } = serializedSplitview;
6020
6664
  const queue = [];
6665
+ // take note of the existing dimensions
6666
+ const width = this.width;
6667
+ const height = this.height;
6021
6668
  this.splitview = new Splitview(this.element, {
6022
6669
  orientation,
6023
6670
  proportionalLayout: this.options.proportionalLayout,
@@ -6054,7 +6701,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6054
6701
  }),
6055
6702
  },
6056
6703
  });
6057
- this.layout(this.width, this.height);
6704
+ this.layout(width, height);
6058
6705
  queue.forEach((f) => f());
6059
6706
  if (typeof activeView === 'string') {
6060
6707
  const panel = this.getPanel(activeView);
@@ -6321,6 +6968,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6321
6968
  this.clear();
6322
6969
  const { views, size } = serializedPaneview;
6323
6970
  const queue = [];
6971
+ // take note of the existing dimensions
6972
+ const width = this.width;
6973
+ const height = this.height;
6324
6974
  this.paneview = new Paneview(this.element, {
6325
6975
  orientation: exports.Orientation.VERTICAL,
6326
6976
  descriptor: {
@@ -6376,7 +7026,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6376
7026
  }),
6377
7027
  },
6378
7028
  });
6379
- this.layout(this.width, this.height);
7029
+ this.layout(width, height);
6380
7030
  queue.forEach((f) => f());
6381
7031
  this._onDidLayoutfromJSON.fire();
6382
7032
  }
@@ -6759,7 +7409,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6759
7409
  }
6760
7410
  }
6761
7411
 
6762
- class ReactGroupControlsRendererPart {
7412
+ class ReactHeaderActionsRendererPart {
6763
7413
  get element() {
6764
7414
  return this._element;
6765
7415
  }
@@ -6796,6 +7446,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6796
7446
  panels: this._group.model.panels,
6797
7447
  activePanel: this._group.model.activePanel,
6798
7448
  isGroupActive: this._group.api.isActive,
7449
+ group: this._group,
6799
7450
  });
6800
7451
  }
6801
7452
  update(event) {
@@ -6829,7 +7480,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6829
7480
  function createGroupControlElement(component, store) {
6830
7481
  return component
6831
7482
  ? (groupPanel) => {
6832
- return new ReactGroupControlsRendererPart(component, store, groupPanel);
7483
+ return new ReactHeaderActionsRendererPart(component, store, groupPanel);
6833
7484
  }
6834
7485
  : undefined;
6835
7486
  }
@@ -6886,8 +7537,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6886
7537
  ? { separatorBorder: 'transparent' }
6887
7538
  : undefined,
6888
7539
  showDndOverlay: props.showDndOverlay,
6889
- createGroupControlElement: createGroupControlElement(props.groupControlComponent, { addPortal }),
7540
+ createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7541
+ createRightHeaderActionsElement: createGroupControlElement(props.rightHeaderActionsComponent, { addPortal }),
6890
7542
  singleTabMode: props.singleTabMode,
7543
+ disableFloatingGroups: props.disableFloatingGroups,
6891
7544
  });
6892
7545
  const { clientWidth, clientHeight } = domRef.current;
6893
7546
  dockview.layout(clientWidth, clientHeight);
@@ -6946,6 +7599,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6946
7599
  frameworkTabComponents: props.tabComponents,
6947
7600
  });
6948
7601
  }, [props.tabComponents]);
7602
+ React__namespace.useEffect(() => {
7603
+ if (!dockviewRef.current) {
7604
+ return;
7605
+ }
7606
+ dockviewRef.current.updateOptions({
7607
+ disableFloatingGroups: props.disableFloatingGroups,
7608
+ });
7609
+ }, [props.disableFloatingGroups]);
6949
7610
  React__namespace.useEffect(() => {
6950
7611
  if (!dockviewRef.current) {
6951
7612
  return;
@@ -6967,9 +7628,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6967
7628
  return;
6968
7629
  }
6969
7630
  dockviewRef.current.updateOptions({
6970
- createGroupControlElement: createGroupControlElement(props.groupControlComponent, { addPortal }),
7631
+ createRightHeaderActionsElement: createGroupControlElement(props.rightHeaderActionsComponent, { addPortal }),
7632
+ });
7633
+ }, [props.rightHeaderActionsComponent]);
7634
+ React__namespace.useEffect(() => {
7635
+ if (!dockviewRef.current) {
7636
+ return;
7637
+ }
7638
+ dockviewRef.current.updateOptions({
7639
+ createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
6971
7640
  });
6972
- }, [props.groupControlComponent]);
7641
+ }, [props.leftHeaderActionsComponent]);
6973
7642
  return (React__namespace.createElement("div", { className: props.className, style: { height: '100%', width: '100%' }, ref: domRef }, portals));
6974
7643
  });
6975
7644
  DockviewReact.displayName = 'DockviewComponent';
@@ -6988,6 +7657,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6988
7657
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
6989
7658
  PERFORMANCE OF THIS SOFTWARE.
6990
7659
  ***************************************************************************** */
7660
+ /* global Reflect, Promise, SuppressedError, Symbol */
7661
+
6991
7662
 
6992
7663
  function __rest(s, e) {
6993
7664
  var t = {};
@@ -6999,7 +7670,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6999
7670
  t[p[i]] = s[p[i]];
7000
7671
  }
7001
7672
  return t;
7002
- }
7673
+ }
7674
+
7675
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
7676
+ var e = new Error(message);
7677
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
7678
+ };
7003
7679
 
7004
7680
  const CloseButton = () => (React__namespace.createElement("svg", { height: "11", width: "11", viewBox: "0 0 28 28", "aria-hidden": 'false', focusable: false, className: "dockview-svg" },
7005
7681
  React__namespace.createElement("path", { d: "M2.1 27.3L0 25.2L11.55 13.65L0 2.1L2.1 0L13.65 11.55L25.2 0L27.3 2.1L15.75 13.65L27.3 25.2L25.2 27.3L13.65 15.75L2.1 27.3Z" })));
@@ -7327,6 +8003,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
7327
8003
  exports.positionToDirection = positionToDirection;
7328
8004
  exports.toTarget = toTarget;
7329
8005
  exports.usePortalsLifecycle = usePortalsLifecycle;
7330
- exports.watchElementResize = watchElementResize;
7331
8006
 
7332
8007
  }));
8008
+ //# sourceMappingURL=dockview.amd.noStyle.js.map