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
  */
@@ -323,6 +323,31 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
323
323
  }
324
324
  }
325
325
 
326
+ function createComponent(id, componentName, components = {}, frameworkComponents = {}, createFrameworkComponent, fallback) {
327
+ const Component = typeof componentName === 'string'
328
+ ? components[componentName]
329
+ : undefined;
330
+ const FrameworkComponent = typeof componentName === 'string'
331
+ ? frameworkComponents[componentName]
332
+ : undefined;
333
+ if (Component && FrameworkComponent) {
334
+ throw new Error(`Cannot create '${id}'. component '${componentName}' registered as both a component and frameworkComponent`);
335
+ }
336
+ if (FrameworkComponent) {
337
+ if (!createFrameworkComponent) {
338
+ throw new Error(`Cannot create '${id}' for framework component '${componentName}'. you must register a frameworkPanelWrapper to use framework components`);
339
+ }
340
+ return createFrameworkComponent.createComponent(id, componentName, FrameworkComponent);
341
+ }
342
+ if (!Component) {
343
+ if (fallback) {
344
+ return fallback();
345
+ }
346
+ throw new Error(`Cannot create '${id}', no component '${componentName}' provided`);
347
+ }
348
+ return new Component(id, componentName);
349
+ }
350
+
326
351
  function watchElementResize(element, cb) {
327
352
  const observer = new ResizeObserver((entires) => {
328
353
  /**
@@ -436,31 +461,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
436
461
  refreshState() {
437
462
  this._refreshStateHandler();
438
463
  }
439
- }
440
-
441
- function createComponent(id, componentName, components = {}, frameworkComponents = {}, createFrameworkComponent, fallback) {
442
- const Component = typeof componentName === 'string'
443
- ? components[componentName]
444
- : undefined;
445
- const FrameworkComponent = typeof componentName === 'string'
446
- ? frameworkComponents[componentName]
447
- : undefined;
448
- if (Component && FrameworkComponent) {
449
- throw new Error(`Cannot create '${id}'. component '${componentName}' registered as both a component and frameworkComponent`);
450
- }
451
- if (FrameworkComponent) {
452
- if (!createFrameworkComponent) {
453
- throw new Error(`Cannot create '${id}' for framework component '${componentName}'. you must register a frameworkPanelWrapper to use framework components`);
454
- }
455
- return createFrameworkComponent.createComponent(id, componentName, FrameworkComponent);
456
- }
457
- if (!Component) {
458
- if (fallback) {
459
- return fallback();
460
- }
461
- throw new Error(`Cannot create '${id}', no component '${componentName}' provided`);
462
- }
463
- return new Component(id, componentName);
464
+ }
465
+ // quasi: apparently, but not really; seemingly
466
+ const QUASI_PREVENT_DEFAULT_KEY = 'dv-quasiPreventDefault';
467
+ // mark an event directly for other listeners to check
468
+ function quasiPreventDefault(event) {
469
+ event[QUASI_PREVENT_DEFAULT_KEY] = true;
470
+ }
471
+ // check if this event has been marked
472
+ function quasiDefaultPrevented(event) {
473
+ return event[QUASI_PREVENT_DEFAULT_KEY];
464
474
  }
465
475
 
466
476
  function tail(arr) {
@@ -511,6 +521,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
511
521
  }
512
522
  }
513
523
  return -1;
524
+ }
525
+ function remove(array, value) {
526
+ const index = array.findIndex((t) => t === value);
527
+ if (index > -1) {
528
+ array.splice(index, 1);
529
+ return true;
530
+ }
531
+ return false;
514
532
  }
515
533
 
516
534
  const clamp = (value, min, max) => {
@@ -940,7 +958,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
940
958
  //add sash
941
959
  const sash = document.createElement('div');
942
960
  sash.className = 'sash';
943
- const onStart = (event) => {
961
+ const onPointerStart = (event) => {
944
962
  for (const item of this.viewItems) {
945
963
  item.enabled = false;
946
964
  }
@@ -999,11 +1017,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
999
1017
  size: snappedViewItem.size,
1000
1018
  };
1001
1019
  }
1002
- //
1003
- const mousemove = (mousemoveEvent) => {
1020
+ const onPointerMove = (event) => {
1004
1021
  const current = this._orientation === exports.Orientation.HORIZONTAL
1005
- ? mousemoveEvent.clientX
1006
- : mousemoveEvent.clientY;
1022
+ ? event.clientX
1023
+ : event.clientY;
1007
1024
  const delta = current - start;
1008
1025
  this.resize(sashIndex, delta, sizes, undefined, undefined, minDelta, maxDelta, snapBefore, snapAfter);
1009
1026
  this.distributeEmptySpace();
@@ -1017,18 +1034,20 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1017
1034
  iframe.style.pointerEvents = 'auto';
1018
1035
  }
1019
1036
  this.saveProportions();
1020
- document.removeEventListener('mousemove', mousemove);
1021
- document.removeEventListener('mouseup', end);
1037
+ document.removeEventListener('pointermove', onPointerMove);
1038
+ document.removeEventListener('pointerup', end);
1039
+ document.removeEventListener('pointercancel', end);
1022
1040
  this._onDidSashEnd.fire(undefined);
1023
1041
  };
1024
- document.addEventListener('mousemove', mousemove);
1025
- document.addEventListener('mouseup', end);
1042
+ document.addEventListener('pointermove', onPointerMove);
1043
+ document.addEventListener('pointerup', end);
1044
+ document.addEventListener('pointercancel', end);
1026
1045
  };
1027
- sash.addEventListener('mousedown', onStart);
1046
+ sash.addEventListener('pointerdown', onPointerStart);
1028
1047
  const sashItem = {
1029
1048
  container: sash,
1030
1049
  disposable: () => {
1031
- sash.removeEventListener('mousedown', onStart);
1050
+ sash.removeEventListener('pointerdown', onPointerStart);
1032
1051
  this.sashContainer.removeChild(sash);
1033
1052
  },
1034
1053
  };
@@ -1652,7 +1671,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1652
1671
  : true,
1653
1672
  };
1654
1673
  }),
1655
- size: this.size,
1674
+ size: this.orthogonalSize,
1656
1675
  };
1657
1676
  this.children = childDescriptors.map((c) => c.node);
1658
1677
  this.splitview = new Splitview(this.element, {
@@ -1715,7 +1734,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1715
1734
  layout(size, orthogonalSize) {
1716
1735
  this._size = orthogonalSize;
1717
1736
  this._orthogonalSize = size;
1718
- this.splitview.layout(this.size, this.orthogonalSize);
1737
+ this.splitview.layout(orthogonalSize, size);
1719
1738
  }
1720
1739
  addChild(node, size, index, skipLayout) {
1721
1740
  if (index < 0 || index > this.children.length) {
@@ -1940,9 +1959,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1940
1959
  this._deserialize(json.root, orientation, deserializer, height);
1941
1960
  }
1942
1961
  _deserialize(root, orientation, deserializer, orthogonalSize) {
1943
- this.root = this._deserializeNode(root, orientation, deserializer, orthogonalSize, true);
1962
+ this.root = this._deserializeNode(root, orientation, deserializer, orthogonalSize);
1944
1963
  }
1945
- _deserializeNode(node, orientation, deserializer, orthogonalSize, isRoot = false) {
1964
+ _deserializeNode(node, orientation, deserializer, orthogonalSize) {
1946
1965
  let result;
1947
1966
  if (node.type === 'branch') {
1948
1967
  const serializedChildren = node.data;
@@ -1952,9 +1971,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1952
1971
  visible: serializedChild.visible,
1953
1972
  };
1954
1973
  });
1955
- // HORIZONTAL => height=orthogonalsize width=size
1956
- // VERTICAL => height=size width=orthogonalsize
1957
- result = new BranchNode(orientation, this.proportionalLayout, this.styles, isRoot ? orthogonalSize : node.size, isRoot ? node.size : orthogonalSize, children);
1974
+ result = new BranchNode(orientation, this.proportionalLayout, this.styles, node.size, // <- orthogonal size - flips at each depth
1975
+ orthogonalSize, // <- size - flips at each depth
1976
+ children);
1958
1977
  }
1959
1978
  else {
1960
1979
  result = new LeafNode(deserializer.fromJSON(node), orientation, orthogonalSize, node.size);
@@ -1987,7 +2006,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1987
2006
  const oldRoot = this.root;
1988
2007
  oldRoot.element.remove();
1989
2008
  this._root = new BranchNode(orthogonal(oldRoot.orientation), this.proportionalLayout, this.styles, this.root.orthogonalSize, this.root.size);
1990
- if (oldRoot.children.length === 1) {
2009
+ if (oldRoot.children.length === 0) ;
2010
+ else if (oldRoot.children.length === 1) {
1991
2011
  // can remove one level of redundant branching if there is only a single child
1992
2012
  const childReference = oldRoot.children[0];
1993
2013
  const child = oldRoot.removeChild(0); // remove to prevent disposal when disposing of unwanted root
@@ -2121,52 +2141,70 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2121
2141
  if (!(parent instanceof BranchNode)) {
2122
2142
  throw new Error('Invalid location');
2123
2143
  }
2124
- const node = parent.children[index];
2125
- if (!(node instanceof LeafNode)) {
2144
+ const nodeToRemove = parent.children[index];
2145
+ if (!(nodeToRemove instanceof LeafNode)) {
2126
2146
  throw new Error('Invalid location');
2127
2147
  }
2128
2148
  parent.removeChild(index, sizing);
2129
- if (parent.children.length === 0) {
2130
- return node.view;
2131
- }
2132
- if (parent.children.length > 1) {
2133
- return node.view;
2134
- }
2149
+ nodeToRemove.dispose();
2150
+ if (parent.children.length !== 1) {
2151
+ return nodeToRemove.view;
2152
+ }
2153
+ // if the parent has only one child and we know the parent is a BranchNode we can make the tree
2154
+ // more efficiently spaced by replacing the parent BranchNode with the child.
2155
+ // if that child is a LeafNode then we simply replace the BranchNode with the child otherwise if the child
2156
+ // is a BranchNode too we should spread it's children into the grandparent.
2157
+ // refer to the remaining child as the sibling
2135
2158
  const sibling = parent.children[0];
2136
2159
  if (pathToParent.length === 0) {
2137
- // parent is root
2160
+ // if the parent is root
2138
2161
  if (sibling instanceof LeafNode) {
2139
- return node.view;
2162
+ // if the sibling is a leaf node no action is required
2163
+ return nodeToRemove.view;
2140
2164
  }
2141
- // we must promote sibling to be the new root
2165
+ // otherwise the sibling is a branch node. since the parent is the root and the root has only one child
2166
+ // which is a branch node we can just set this branch node to be the new root node
2167
+ // for good housekeeping we'll removing the sibling from it's existing tree
2142
2168
  parent.removeChild(0, sizing);
2169
+ // and set that sibling node to be root
2143
2170
  this.root = sibling;
2144
- return node.view;
2171
+ return nodeToRemove.view;
2145
2172
  }
2173
+ // otherwise the parent is apart of a large sub-tree
2146
2174
  const [grandParent, ..._] = [...pathToParent].reverse();
2147
2175
  const [parentIndex, ...__] = [...rest].reverse();
2148
2176
  const isSiblingVisible = parent.isChildVisible(0);
2177
+ // either way we need to remove the sibling from it's existing tree
2149
2178
  parent.removeChild(0, sizing);
2179
+ // note the sizes of all of the grandparents children
2150
2180
  const sizes = grandParent.children.map((_size, i) => grandParent.getChildSize(i));
2151
- grandParent.removeChild(parentIndex, sizing);
2181
+ // remove the parent from the grandparent since we are moving the sibling to take the parents place
2182
+ // this parent is no longer used and can be disposed of
2183
+ grandParent.removeChild(parentIndex, sizing).dispose();
2152
2184
  if (sibling instanceof BranchNode) {
2185
+ // replace the parent with the siblings children
2153
2186
  sizes.splice(parentIndex, 1, ...sibling.children.map((c) => c.size));
2187
+ // and add those siblings to the grandparent
2154
2188
  for (let i = 0; i < sibling.children.length; i++) {
2155
2189
  const child = sibling.children[i];
2156
2190
  grandParent.addChild(child, child.size, parentIndex + i);
2157
2191
  }
2158
2192
  }
2159
2193
  else {
2194
+ // otherwise create a new leaf node and add that to the grandparent
2160
2195
  const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), sibling.size);
2161
2196
  const siblingSizing = isSiblingVisible
2162
2197
  ? sibling.orthogonalSize
2163
2198
  : exports.Sizing.Invisible(sibling.orthogonalSize);
2164
2199
  grandParent.addChild(newSibling, siblingSizing, parentIndex);
2165
2200
  }
2201
+ // the containing node of the sibling is no longer required and can be disposed of
2202
+ sibling.dispose();
2203
+ // resize everything
2166
2204
  for (let i = 0; i < sizes.length; i++) {
2167
2205
  grandParent.resizeChild(i, sizes[i]);
2168
2206
  }
2169
- return node.view;
2207
+ return nodeToRemove.view;
2170
2208
  }
2171
2209
  layout(width, height) {
2172
2210
  const [size, orthogonalSize] = this.root.orientation === exports.Orientation.HORIZONTAL
@@ -2485,6 +2523,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2485
2523
  addPanel(options) {
2486
2524
  return this.component.addPanel(options);
2487
2525
  }
2526
+ removePanel(panel) {
2527
+ this.component.removePanel(panel);
2528
+ }
2488
2529
  addGroup(options) {
2489
2530
  return this.component.addGroup(options);
2490
2531
  }
@@ -2503,6 +2544,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2503
2544
  getGroup(id) {
2504
2545
  return this.component.getPanel(id);
2505
2546
  }
2547
+ addFloatingGroup(item, coord) {
2548
+ return this.component.addFloatingGroup(item, coord);
2549
+ }
2506
2550
  fromJSON(data) {
2507
2551
  this.component.fromJSON(data);
2508
2552
  }
@@ -2595,10 +2639,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2595
2639
  this._onDrop = new Emitter();
2596
2640
  this.onDrop = this._onDrop.event;
2597
2641
  // use a set to take advantage of #<set>.has
2598
- const acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2642
+ this._acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2599
2643
  this.addDisposables(this._onDrop, new DragAndDropObserver(this.element, {
2600
2644
  onDragEnter: () => undefined,
2601
2645
  onDragOver: (e) => {
2646
+ if (this._acceptedTargetZonesSet.size === 0) {
2647
+ this.removeDropTarget();
2648
+ return;
2649
+ }
2602
2650
  const width = this.element.clientWidth;
2603
2651
  const height = this.element.clientHeight;
2604
2652
  if (width === 0 || height === 0) {
@@ -2607,20 +2655,28 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2607
2655
  const rect = e.currentTarget.getBoundingClientRect();
2608
2656
  const x = e.clientX - rect.left;
2609
2657
  const y = e.clientY - rect.top;
2610
- const quadrant = this.calculateQuadrant(acceptedTargetZonesSet, x, y, width, height);
2611
- if (quadrant === null) {
2658
+ const quadrant = this.calculateQuadrant(this._acceptedTargetZonesSet, x, y, width, height);
2659
+ /**
2660
+ * If the event has already been used by another DropTarget instance
2661
+ * then don't show a second drop target, only one target should be
2662
+ * active at any one time
2663
+ */
2664
+ if (this.isAlreadyUsed(e) || quadrant === null) {
2612
2665
  // no drop target should be displayed
2613
2666
  this.removeDropTarget();
2614
2667
  return;
2615
2668
  }
2616
2669
  if (typeof this.options.canDisplayOverlay === 'boolean') {
2617
2670
  if (!this.options.canDisplayOverlay) {
2671
+ this.removeDropTarget();
2618
2672
  return;
2619
2673
  }
2620
2674
  }
2621
2675
  else if (!this.options.canDisplayOverlay(e, quadrant)) {
2676
+ this.removeDropTarget();
2622
2677
  return;
2623
2678
  }
2679
+ this.markAsUsed(e);
2624
2680
  if (!this.targetElement) {
2625
2681
  this.targetElement = document.createElement('div');
2626
2682
  this.targetElement.className = 'drop-target-dropzone';
@@ -2631,12 +2687,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2631
2687
  this.element.classList.add('drop-target');
2632
2688
  this.element.append(this.targetElement);
2633
2689
  }
2634
- if (this.options.acceptedTargetZones.length === 0) {
2635
- return;
2636
- }
2637
- if (!this.targetElement || !this.overlayElement) {
2638
- return;
2639
- }
2640
2690
  this.toggleClasses(quadrant, width, height);
2641
2691
  this.setState(quadrant);
2642
2692
  },
@@ -2659,10 +2709,26 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2659
2709
  },
2660
2710
  }));
2661
2711
  }
2712
+ setTargetZones(acceptedTargetZones) {
2713
+ this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
2714
+ }
2662
2715
  dispose() {
2663
2716
  this.removeDropTarget();
2664
2717
  super.dispose();
2665
2718
  }
2719
+ /**
2720
+ * Add a property to the event object for other potential listeners to check
2721
+ */
2722
+ markAsUsed(event) {
2723
+ event[Droptarget.USED_EVENT_ID] = true;
2724
+ }
2725
+ /**
2726
+ * Check is the event has already been used by another instance od DropTarget
2727
+ */
2728
+ isAlreadyUsed(event) {
2729
+ const value = event[Droptarget.USED_EVENT_ID];
2730
+ return typeof value === 'boolean' && value;
2731
+ }
2666
2732
  toggleClasses(quadrant, width, height) {
2667
2733
  var _a, _b, _c, _d;
2668
2734
  if (!this.overlayElement) {
@@ -2757,6 +2823,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2757
2823
  }
2758
2824
  }
2759
2825
  }
2826
+ Droptarget.USED_EVENT_ID = '__dockview_droptarget_event_is_used__';
2760
2827
  function calculateQuadrantAsPercentage(overlayType, x, y, width, height, threshold) {
2761
2828
  const xp = (100 * x) / width;
2762
2829
  const yp = (100 * y) / height;
@@ -2886,8 +2953,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2886
2953
  this.addDisposables(this._onDragStart, this.dataDisposable, this.pointerEventsDisposable);
2887
2954
  this.configure();
2888
2955
  }
2956
+ isCancelled(_event) {
2957
+ return false;
2958
+ }
2889
2959
  configure() {
2890
2960
  this.addDisposables(this._onDragStart, addDisposableListener(this.el, 'dragstart', (event) => {
2961
+ if (this.isCancelled(event)) {
2962
+ event.preventDefault();
2963
+ return;
2964
+ }
2891
2965
  const iframes = [
2892
2966
  ...getElementsByTagName('iframe'),
2893
2967
  ...getElementsByTagName('webview'),
@@ -2961,13 +3035,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2961
3035
  if (event.defaultPrevented) {
2962
3036
  return;
2963
3037
  }
2964
- /**
2965
- * TODO: alternative to stopPropagation
2966
- *
2967
- * I need to stop the event propagation here since otherwise it'll be intercepted by event handlers
2968
- * on the tabs-container. I cannot use event.preventDefault() since I need the on DragStart event to occur
2969
- */
2970
- event.stopPropagation();
2971
3038
  this._onChanged.fire(event);
2972
3039
  }));
2973
3040
  this.droptarget = new Droptarget(this._element, {
@@ -3025,6 +3092,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3025
3092
  this.accessorId = accessorId;
3026
3093
  this.group = group;
3027
3094
  this.panelTransfer = LocalSelectionTransfer.getInstance();
3095
+ this.addDisposables(addDisposableListener(element, 'mousedown', (e) => {
3096
+ if (e.shiftKey) {
3097
+ /**
3098
+ * You cannot call e.preventDefault() because that will prevent drag events from firing
3099
+ * but we also need to stop any group overlay drag events from occuring
3100
+ * Use a custom event marker that can be checked by the overlay drag events
3101
+ */
3102
+ quasiPreventDefault(e);
3103
+ }
3104
+ }, true));
3105
+ }
3106
+ isCancelled(_event) {
3107
+ if (this.group.api.isFloating && !_event.shiftKey) {
3108
+ return true;
3109
+ }
3110
+ return false;
3028
3111
  }
3029
3112
  getData(dataTransfer) {
3030
3113
  this.panelTransfer.setData([new PanelTransfer(this.accessorId, this.group.id, null)], PanelTransfer.prototype);
@@ -3115,17 +3198,30 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3115
3198
  hide() {
3116
3199
  this._element.style.display = 'none';
3117
3200
  }
3118
- setActionElement(element) {
3119
- if (this.actions === element) {
3201
+ setRightActionsElement(element) {
3202
+ if (this.rightActions === element) {
3203
+ return;
3204
+ }
3205
+ if (this.rightActions) {
3206
+ this.rightActions.remove();
3207
+ this.rightActions = undefined;
3208
+ }
3209
+ if (element) {
3210
+ this.rightActionsContainer.appendChild(element);
3211
+ this.rightActions = element;
3212
+ }
3213
+ }
3214
+ setLeftActionsElement(element) {
3215
+ if (this.leftActions === element) {
3120
3216
  return;
3121
3217
  }
3122
- if (this.actions) {
3123
- this.actions.remove();
3124
- this.actions = undefined;
3218
+ if (this.leftActions) {
3219
+ this.leftActions.remove();
3220
+ this.leftActions = undefined;
3125
3221
  }
3126
3222
  if (element) {
3127
- this.actionContainer.appendChild(element);
3128
- this.actions = element;
3223
+ this.leftActionsContainer.appendChild(element);
3224
+ this.leftActions = element;
3129
3225
  }
3130
3226
  }
3131
3227
  get element() {
@@ -3160,19 +3256,35 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3160
3256
  toggleClass(this._element, 'dv-single-tab', this.size === 1);
3161
3257
  }
3162
3258
  }));
3163
- this.actionContainer = document.createElement('div');
3164
- this.actionContainer.className = 'action-container';
3259
+ this.rightActionsContainer = document.createElement('div');
3260
+ this.rightActionsContainer.className = 'right-actions-container';
3261
+ this.leftActionsContainer = document.createElement('div');
3262
+ this.leftActionsContainer.className = 'left-actions-container';
3165
3263
  this.tabContainer = document.createElement('div');
3166
3264
  this.tabContainer.className = 'tabs-container';
3167
3265
  this.voidContainer = new VoidContainer(this.accessor, this.group);
3168
3266
  this._element.appendChild(this.tabContainer);
3267
+ this._element.appendChild(this.leftActionsContainer);
3169
3268
  this._element.appendChild(this.voidContainer.element);
3170
- this._element.appendChild(this.actionContainer);
3269
+ this._element.appendChild(this.rightActionsContainer);
3171
3270
  this.addDisposables(this.voidContainer, this.voidContainer.onDrop((event) => {
3172
3271
  this._onDrop.fire({
3173
3272
  event: event.nativeEvent,
3174
3273
  index: this.tabs.length,
3175
3274
  });
3275
+ }), addDisposableListener(this.voidContainer.element, 'mousedown', (event) => {
3276
+ const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3277
+ if (isFloatingGroupsEnabled &&
3278
+ event.shiftKey &&
3279
+ !this.group.api.isFloating) {
3280
+ event.preventDefault();
3281
+ const { top, left } = this.element.getBoundingClientRect();
3282
+ const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
3283
+ this.accessor.addFloatingGroup(this.group, {
3284
+ x: left - rootLeft + 20,
3285
+ y: top - rootTop + 20,
3286
+ }, { inDragMode: true });
3287
+ }
3176
3288
  }), addDisposableListener(this.tabContainer, 'mousedown', (event) => {
3177
3289
  if (event.defaultPrevented) {
3178
3290
  return;
@@ -3226,6 +3338,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3226
3338
  tabToAdd.setContent(panel.view.tab);
3227
3339
  const disposable = CompositeDisposable.from(tabToAdd.onChanged((event) => {
3228
3340
  var _a;
3341
+ const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3342
+ const isFloatingWithOnePanel = this.group.api.isFloating && this.size === 1;
3343
+ if (isFloatingGroupsEnabled &&
3344
+ !isFloatingWithOnePanel &&
3345
+ event.shiftKey) {
3346
+ event.preventDefault();
3347
+ const panel = this.accessor.getGroupPanel(tabToAdd.panelId);
3348
+ const { top, left } = tabToAdd.element.getBoundingClientRect();
3349
+ const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
3350
+ this.accessor.addFloatingGroup(panel, {
3351
+ x: left - rootLeft,
3352
+ y: top - rootTop,
3353
+ }, { inDragMode: true });
3354
+ return;
3355
+ }
3229
3356
  const alreadyFocused = panel.id === ((_a = this.group.model.activePanel) === null || _a === void 0 ? void 0 : _a.id) &&
3230
3357
  this.group.model.isContentFocused;
3231
3358
  const isLeftClick = event.button === 0;
@@ -3295,6 +3422,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3295
3422
  }
3296
3423
  return isAncestor(document.activeElement, this.contentContainer.element);
3297
3424
  }
3425
+ get isFloating() {
3426
+ return this._isFloating;
3427
+ }
3428
+ set isFloating(value) {
3429
+ this._isFloating = value;
3430
+ this.dropTarget.setTargetZones(value ? ['center'] : ['top', 'bottom', 'left', 'right', 'center']);
3431
+ toggleClass(this.container, 'dv-groupview-floating', value);
3432
+ this.groupPanel.api._onDidFloatingStateChange.fire({
3433
+ isFloating: this.isFloating,
3434
+ });
3435
+ }
3298
3436
  constructor(container, accessor, id, options, groupPanel) {
3299
3437
  super();
3300
3438
  this.container = container;
@@ -3304,6 +3442,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3304
3442
  this.groupPanel = groupPanel;
3305
3443
  this._isGroupActive = false;
3306
3444
  this._locked = false;
3445
+ this._isFloating = false;
3307
3446
  this.mostRecentlyUsed = [];
3308
3447
  this._onDidChange = new Emitter();
3309
3448
  this.onDidChange = this._onDidChange.event;
@@ -3320,7 +3459,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3320
3459
  this.onDidRemovePanel = this._onDidRemovePanel.event;
3321
3460
  this._onDidActivePanelChange = new Emitter();
3322
3461
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
3323
- this.container.classList.add('groupview');
3462
+ toggleClass(this.container, 'groupview', true);
3324
3463
  this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
3325
3464
  this.contentContainer = new ContentContainer();
3326
3465
  this.dropTarget = new Droptarget(this.contentContainer.element, {
@@ -3330,6 +3469,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3330
3469
  return false;
3331
3470
  }
3332
3471
  const data = getPanelData();
3472
+ if (!data && event.shiftKey && !this.isFloating) {
3473
+ return false;
3474
+ }
3333
3475
  if (data && data.viewId === this.accessor.id) {
3334
3476
  if (data.groupId === this.id) {
3335
3477
  if (position === 'center') {
@@ -3374,14 +3516,25 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3374
3516
  // correctly initialized
3375
3517
  this.setActive(this.isActive, true, true);
3376
3518
  this.updateContainer();
3377
- if (this.accessor.options.createGroupControlElement) {
3378
- this._control = this.accessor.options.createGroupControlElement(this.groupPanel);
3379
- this.addDisposables(this._control);
3380
- this._control.init({
3519
+ if (this.accessor.options.createRightHeaderActionsElement) {
3520
+ this._rightHeaderActions =
3521
+ this.accessor.options.createRightHeaderActionsElement(this.groupPanel);
3522
+ this.addDisposables(this._rightHeaderActions);
3523
+ this._rightHeaderActions.init({
3524
+ containerApi: new DockviewApi(this.accessor),
3525
+ api: this.groupPanel.api,
3526
+ });
3527
+ this.tabsContainer.setRightActionsElement(this._rightHeaderActions.element);
3528
+ }
3529
+ if (this.accessor.options.createLeftHeaderActionsElement) {
3530
+ this._leftHeaderActions =
3531
+ this.accessor.options.createLeftHeaderActionsElement(this.groupPanel);
3532
+ this.addDisposables(this._leftHeaderActions);
3533
+ this._leftHeaderActions.init({
3381
3534
  containerApi: new DockviewApi(this.accessor),
3382
3535
  api: this.groupPanel.api,
3383
3536
  });
3384
- this.tabsContainer.setActionElement(this._control.element);
3537
+ this.tabsContainer.setLeftActionsElement(this._leftHeaderActions.element);
3385
3538
  }
3386
3539
  }
3387
3540
  indexOf(panel) {
@@ -3514,7 +3667,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3514
3667
  return this._activePanel === panel;
3515
3668
  }
3516
3669
  updateActions(element) {
3517
- this.tabsContainer.setActionElement(element);
3670
+ this.tabsContainer.setRightActionsElement(element);
3518
3671
  }
3519
3672
  setActive(isGroupActive, skipFocus = false, force = false) {
3520
3673
  var _a, _b, _c, _d;
@@ -3686,9 +3839,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3686
3839
  }
3687
3840
  }
3688
3841
  dispose() {
3689
- var _a, _b;
3842
+ var _a, _b, _c;
3690
3843
  super.dispose();
3691
- (_b = (_a = this.watermark) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
3844
+ (_a = this.watermark) === null || _a === void 0 ? void 0 : _a.element.remove();
3845
+ (_c = (_b = this.watermark) === null || _b === void 0 ? void 0 : _b.dispose) === null || _c === void 0 ? void 0 : _c.call(_b);
3692
3846
  for (const panel of this.panels) {
3693
3847
  panel.dispose();
3694
3848
  }
@@ -4482,8 +4636,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4482
4636
  get isActive() {
4483
4637
  return this.api.isActive;
4484
4638
  }
4485
- constructor(id, component, options) {
4486
- super(id, component, new GridviewPanelApiImpl(id));
4639
+ constructor(id, component, options, api) {
4640
+ super(id, component, api !== null && api !== void 0 ? api : new GridviewPanelApiImpl(id));
4487
4641
  this._evaluatedMinimumWidth = 0;
4488
4642
  this._evaluatedMaximumWidth = Number.MAX_SAFE_INTEGER;
4489
4643
  this._evaluatedMinimumHeight = 0;
@@ -4581,6 +4735,32 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4581
4735
  }
4582
4736
  }
4583
4737
 
4738
+ class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
4739
+ get isFloating() {
4740
+ if (!this._group) {
4741
+ throw new Error(`DockviewGroupPanelApiImpl not initialized`);
4742
+ }
4743
+ return this._group.model.isFloating;
4744
+ }
4745
+ constructor(id, accessor) {
4746
+ super(id);
4747
+ this.accessor = accessor;
4748
+ this._onDidFloatingStateChange = new Emitter();
4749
+ this.onDidFloatingStateChange = this._onDidFloatingStateChange.event;
4750
+ this.addDisposables(this._onDidFloatingStateChange);
4751
+ }
4752
+ moveTo(options) {
4753
+ var _a;
4754
+ if (!this._group) {
4755
+ throw new Error(`DockviewGroupPanelApiImpl not initialized`);
4756
+ }
4757
+ this.accessor.moveGroupOrPanel(options.group, this._group.id, undefined, (_a = options.position) !== null && _a !== void 0 ? _a : 'center');
4758
+ }
4759
+ initialize(group) {
4760
+ this._group = group;
4761
+ }
4762
+ }
4763
+
4584
4764
  class DockviewGroupPanel extends GridviewPanel {
4585
4765
  get panels() {
4586
4766
  return this._model.panels;
@@ -4607,7 +4787,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4607
4787
  super(id, 'groupview_default', {
4608
4788
  minimumHeight: 100,
4609
4789
  minimumWidth: 100,
4610
- });
4790
+ }, new DockviewGroupPanelApiImpl(id, accessor));
4791
+ this.api.initialize(this); // cannot use 'this' after after 'super' call
4611
4792
  this._model = new DockviewGroupPanelModel(this.element, accessor, id, options, this);
4612
4793
  }
4613
4794
  initialize() {
@@ -4625,7 +4806,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4625
4806
  return this._model;
4626
4807
  }
4627
4808
  toJSON() {
4628
- // TODO fix typing
4629
4809
  return this.model.toJSON();
4630
4810
  }
4631
4811
  }
@@ -4679,9 +4859,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4679
4859
  get group() {
4680
4860
  return this._group;
4681
4861
  }
4682
- constructor(panel, group) {
4862
+ constructor(panel, group, accessor) {
4683
4863
  super(panel.id);
4684
4864
  this.panel = panel;
4865
+ this.accessor = accessor;
4685
4866
  this._onDidTitleChange = new Emitter();
4686
4867
  this.onDidTitleChange = this._onDidTitleChange.event;
4687
4868
  this._onDidActiveGroupChange = new Emitter();
@@ -4693,6 +4874,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4693
4874
  this._group = group;
4694
4875
  this.addDisposables(this.disposable, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
4695
4876
  }
4877
+ moveTo(options) {
4878
+ var _a;
4879
+ this.accessor.moveGroupOrPanel(options.group, this._group.id, this.panel.id, (_a = options.position) !== null && _a !== void 0 ? _a : 'center', options.index);
4880
+ }
4696
4881
  setTitle(title) {
4697
4882
  this.panel.setTitle(title);
4698
4883
  }
@@ -4717,7 +4902,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4717
4902
  this.containerApi = containerApi;
4718
4903
  this.view = view;
4719
4904
  this._group = group;
4720
- this.api = new DockviewPanelApiImpl(this, this._group);
4905
+ this.api = new DockviewPanelApiImpl(this, this._group, accessor);
4721
4906
  this.addDisposables(this.api.onActiveChange(() => {
4722
4907
  accessor.setActivePanel(this);
4723
4908
  }), this.api.onDidSizeChange((event) => {
@@ -5058,6 +5243,296 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5058
5243
  }
5059
5244
  }
5060
5245
 
5246
+ const bringElementToFront = (() => {
5247
+ let previous = null;
5248
+ function pushToTop(element) {
5249
+ if (previous !== element && previous !== null) {
5250
+ toggleClass(previous, 'dv-bring-to-front', false);
5251
+ }
5252
+ toggleClass(element, 'dv-bring-to-front', true);
5253
+ previous = element;
5254
+ }
5255
+ return pushToTop;
5256
+ })();
5257
+ class Overlay extends CompositeDisposable {
5258
+ constructor(options) {
5259
+ super();
5260
+ this.options = options;
5261
+ this._element = document.createElement('div');
5262
+ this._onDidChange = new Emitter();
5263
+ this.onDidChange = this._onDidChange.event;
5264
+ this._onDidChangeEnd = new Emitter();
5265
+ this.onDidChangeEnd = this._onDidChangeEnd.event;
5266
+ this.addDisposables(this._onDidChange, this._onDidChangeEnd);
5267
+ this._element.className = 'dv-resize-container';
5268
+ this.setupResize('top');
5269
+ this.setupResize('bottom');
5270
+ this.setupResize('left');
5271
+ this.setupResize('right');
5272
+ this.setupResize('topleft');
5273
+ this.setupResize('topright');
5274
+ this.setupResize('bottomleft');
5275
+ this.setupResize('bottomright');
5276
+ this._element.appendChild(this.options.content);
5277
+ this.options.container.appendChild(this._element);
5278
+ // if input bad resize within acceptable boundaries
5279
+ this.setBounds({
5280
+ height: this.options.height,
5281
+ width: this.options.width,
5282
+ top: this.options.top,
5283
+ left: this.options.left,
5284
+ });
5285
+ }
5286
+ setBounds(bounds = {}) {
5287
+ if (typeof bounds.height === 'number') {
5288
+ this._element.style.height = `${bounds.height}px`;
5289
+ }
5290
+ if (typeof bounds.width === 'number') {
5291
+ this._element.style.width = `${bounds.width}px`;
5292
+ }
5293
+ if (typeof bounds.top === 'number') {
5294
+ this._element.style.top = `${bounds.top}px`;
5295
+ }
5296
+ if (typeof bounds.left === 'number') {
5297
+ this._element.style.left = `${bounds.left}px`;
5298
+ }
5299
+ const containerRect = this.options.container.getBoundingClientRect();
5300
+ const overlayRect = this._element.getBoundingClientRect();
5301
+ // region: ensure bounds within allowable limits
5302
+ // a minimum width of minimumViewportWidth must be inside the viewport
5303
+ const xOffset = Math.max(0, overlayRect.width - this.options.minimumInViewportWidth);
5304
+ // a minimum height of minimumViewportHeight must be inside the viewport
5305
+ const yOffset = Math.max(0, overlayRect.height - this.options.minimumInViewportHeight);
5306
+ const left = clamp(overlayRect.left - containerRect.left, -xOffset, Math.max(0, containerRect.width - overlayRect.width + xOffset));
5307
+ const top = clamp(overlayRect.top - containerRect.top, -yOffset, Math.max(0, containerRect.height - overlayRect.height + yOffset));
5308
+ this._element.style.left = `${left}px`;
5309
+ this._element.style.top = `${top}px`;
5310
+ this._onDidChange.fire();
5311
+ }
5312
+ toJSON() {
5313
+ const container = this.options.container.getBoundingClientRect();
5314
+ const element = this._element.getBoundingClientRect();
5315
+ return {
5316
+ top: element.top - container.top,
5317
+ left: element.left - container.left,
5318
+ width: element.width,
5319
+ height: element.height,
5320
+ };
5321
+ }
5322
+ setupDrag(dragTarget, options = { inDragMode: false }) {
5323
+ const move = new MutableDisposable();
5324
+ const track = () => {
5325
+ let offset = null;
5326
+ const iframes = [
5327
+ ...getElementsByTagName('iframe'),
5328
+ ...getElementsByTagName('webview'),
5329
+ ];
5330
+ for (const iframe of iframes) {
5331
+ iframe.style.pointerEvents = 'none';
5332
+ }
5333
+ move.value = new CompositeDisposable({
5334
+ dispose: () => {
5335
+ for (const iframe of iframes) {
5336
+ iframe.style.pointerEvents = 'auto';
5337
+ }
5338
+ },
5339
+ }, addDisposableWindowListener(window, 'mousemove', (e) => {
5340
+ const containerRect = this.options.container.getBoundingClientRect();
5341
+ const x = e.clientX - containerRect.left;
5342
+ const y = e.clientY - containerRect.top;
5343
+ toggleClass(this._element, 'dv-resize-container-dragging', true);
5344
+ const overlayRect = this._element.getBoundingClientRect();
5345
+ if (offset === null) {
5346
+ offset = {
5347
+ x: e.clientX - overlayRect.left,
5348
+ y: e.clientY - overlayRect.top,
5349
+ };
5350
+ }
5351
+ const xOffset = Math.max(0, overlayRect.width - this.options.minimumInViewportWidth);
5352
+ const yOffset = Math.max(0, overlayRect.height -
5353
+ this.options.minimumInViewportHeight);
5354
+ const left = clamp(x - offset.x, -xOffset, Math.max(0, containerRect.width - overlayRect.width + xOffset));
5355
+ const top = clamp(y - offset.y, -yOffset, Math.max(0, containerRect.height - overlayRect.height + yOffset));
5356
+ this.setBounds({ top, left });
5357
+ }), addDisposableWindowListener(window, 'mouseup', () => {
5358
+ toggleClass(this._element, 'dv-resize-container-dragging', false);
5359
+ move.dispose();
5360
+ this._onDidChangeEnd.fire();
5361
+ }));
5362
+ };
5363
+ this.addDisposables(move, addDisposableListener(dragTarget, 'mousedown', (event) => {
5364
+ if (event.defaultPrevented) {
5365
+ event.preventDefault();
5366
+ return;
5367
+ }
5368
+ // if somebody has marked this event then treat as a defaultPrevented
5369
+ // without actually calling event.preventDefault()
5370
+ if (quasiDefaultPrevented(event)) {
5371
+ return;
5372
+ }
5373
+ track();
5374
+ }), addDisposableListener(this.options.content, 'mousedown', (event) => {
5375
+ if (event.defaultPrevented) {
5376
+ return;
5377
+ }
5378
+ // if somebody has marked this event then treat as a defaultPrevented
5379
+ // without actually calling event.preventDefault()
5380
+ if (quasiDefaultPrevented(event)) {
5381
+ return;
5382
+ }
5383
+ if (event.shiftKey) {
5384
+ track();
5385
+ }
5386
+ }), addDisposableListener(this.options.content, 'mousedown', () => {
5387
+ bringElementToFront(this._element);
5388
+ }, true));
5389
+ bringElementToFront(this._element);
5390
+ if (options.inDragMode) {
5391
+ track();
5392
+ }
5393
+ }
5394
+ setupResize(direction) {
5395
+ const resizeHandleElement = document.createElement('div');
5396
+ resizeHandleElement.className = `dv-resize-handle-${direction}`;
5397
+ this._element.appendChild(resizeHandleElement);
5398
+ const move = new MutableDisposable();
5399
+ this.addDisposables(move, addDisposableListener(resizeHandleElement, 'mousedown', (e) => {
5400
+ e.preventDefault();
5401
+ let startPosition = null;
5402
+ const iframes = [
5403
+ ...getElementsByTagName('iframe'),
5404
+ ...getElementsByTagName('webview'),
5405
+ ];
5406
+ for (const iframe of iframes) {
5407
+ iframe.style.pointerEvents = 'none';
5408
+ }
5409
+ move.value = new CompositeDisposable(addDisposableWindowListener(window, 'mousemove', (e) => {
5410
+ const containerRect = this.options.container.getBoundingClientRect();
5411
+ const overlayRect = this._element.getBoundingClientRect();
5412
+ const y = e.clientY - containerRect.top;
5413
+ const x = e.clientX - containerRect.left;
5414
+ if (startPosition === null) {
5415
+ // record the initial dimensions since as all subsequence moves are relative to this
5416
+ startPosition = {
5417
+ originalY: y,
5418
+ originalHeight: overlayRect.height,
5419
+ originalX: x,
5420
+ originalWidth: overlayRect.width,
5421
+ };
5422
+ }
5423
+ let top = undefined;
5424
+ let height = undefined;
5425
+ let left = undefined;
5426
+ let width = undefined;
5427
+ const minimumInViewportHeight = this.options.minimumInViewportHeight;
5428
+ const minimumInViewportWidth = this.options.minimumInViewportWidth;
5429
+ function moveTop() {
5430
+ top = clamp(y, -Number.MAX_VALUE, startPosition.originalY +
5431
+ startPosition.originalHeight >
5432
+ containerRect.height
5433
+ ? containerRect.height -
5434
+ minimumInViewportHeight
5435
+ : Math.max(0, startPosition.originalY +
5436
+ startPosition.originalHeight -
5437
+ Overlay.MINIMUM_HEIGHT));
5438
+ height =
5439
+ startPosition.originalY +
5440
+ startPosition.originalHeight -
5441
+ top;
5442
+ }
5443
+ function moveBottom() {
5444
+ top =
5445
+ startPosition.originalY -
5446
+ startPosition.originalHeight;
5447
+ height = clamp(y - top, top < 0
5448
+ ? -top + minimumInViewportHeight
5449
+ : Overlay.MINIMUM_HEIGHT, Number.MAX_VALUE);
5450
+ }
5451
+ function moveLeft() {
5452
+ left = clamp(x, -Number.MAX_VALUE, startPosition.originalX +
5453
+ startPosition.originalWidth >
5454
+ containerRect.width
5455
+ ? containerRect.width -
5456
+ minimumInViewportWidth
5457
+ : Math.max(0, startPosition.originalX +
5458
+ startPosition.originalWidth -
5459
+ Overlay.MINIMUM_WIDTH));
5460
+ width =
5461
+ startPosition.originalX +
5462
+ startPosition.originalWidth -
5463
+ left;
5464
+ }
5465
+ function moveRight() {
5466
+ left =
5467
+ startPosition.originalX -
5468
+ startPosition.originalWidth;
5469
+ width = clamp(x - left, left < 0
5470
+ ? -left + minimumInViewportWidth
5471
+ : Overlay.MINIMUM_WIDTH, Number.MAX_VALUE);
5472
+ }
5473
+ switch (direction) {
5474
+ case 'top':
5475
+ moveTop();
5476
+ break;
5477
+ case 'bottom':
5478
+ moveBottom();
5479
+ break;
5480
+ case 'left':
5481
+ moveLeft();
5482
+ break;
5483
+ case 'right':
5484
+ moveRight();
5485
+ break;
5486
+ case 'topleft':
5487
+ moveTop();
5488
+ moveLeft();
5489
+ break;
5490
+ case 'topright':
5491
+ moveTop();
5492
+ moveRight();
5493
+ break;
5494
+ case 'bottomleft':
5495
+ moveBottom();
5496
+ moveLeft();
5497
+ break;
5498
+ case 'bottomright':
5499
+ moveBottom();
5500
+ moveRight();
5501
+ break;
5502
+ }
5503
+ this.setBounds({ height, width, top, left });
5504
+ }), {
5505
+ dispose: () => {
5506
+ for (const iframe of iframes) {
5507
+ iframe.style.pointerEvents = 'auto';
5508
+ }
5509
+ },
5510
+ }, addDisposableWindowListener(window, 'mouseup', () => {
5511
+ move.dispose();
5512
+ this._onDidChangeEnd.fire();
5513
+ }));
5514
+ }));
5515
+ }
5516
+ dispose() {
5517
+ this._element.remove();
5518
+ super.dispose();
5519
+ }
5520
+ }
5521
+ Overlay.MINIMUM_HEIGHT = 20;
5522
+ Overlay.MINIMUM_WIDTH = 20;
5523
+
5524
+ class DockviewFloatingGroupPanel extends CompositeDisposable {
5525
+ constructor(group, overlay) {
5526
+ super();
5527
+ this.group = group;
5528
+ this.overlay = overlay;
5529
+ this.addDisposables(overlay);
5530
+ }
5531
+ position(bounds) {
5532
+ this.overlay.setBounds(bounds);
5533
+ }
5534
+ }
5535
+
5061
5536
  class DockviewComponent extends BaseGrid {
5062
5537
  get orientation() {
5063
5538
  return this.gridview.orientation;
@@ -5098,7 +5573,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5098
5573
  this.onDidLayoutFromJSON = this._onDidLayoutFromJSON.event;
5099
5574
  this._onDidActivePanelChange = new Emitter();
5100
5575
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
5101
- this.element.classList.add('dv-dockview');
5576
+ this.floatingGroups = [];
5577
+ toggleClass(this.gridview.element, 'dv-dockview', true);
5102
5578
  this.addDisposables(this._onDidDrop, exports.DockviewEvent.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
5103
5579
  this.updateWatermark();
5104
5580
  }), exports.DockviewEvent.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidActivePanelChange)(() => {
@@ -5128,6 +5604,11 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5128
5604
  if (data.viewId !== this.id) {
5129
5605
  return false;
5130
5606
  }
5607
+ if (position === 'center') {
5608
+ // center drop target is only allowed if there are no panels in the grid
5609
+ // floating panels are allowed
5610
+ return this.gridview.length === 0;
5611
+ }
5131
5612
  return true;
5132
5613
  }
5133
5614
  if (this.options.showDndOverlay) {
@@ -5140,7 +5621,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5140
5621
  }
5141
5622
  return false;
5142
5623
  },
5143
- acceptedTargetZones: ['top', 'bottom', 'left', 'right'],
5624
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
5144
5625
  overlayModel: {
5145
5626
  activationSize: { type: 'pixels', value: 10 },
5146
5627
  size: { type: 'pixels', value: 20 },
@@ -5158,6 +5639,75 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5158
5639
  this._api = new DockviewApi(this);
5159
5640
  this.updateWatermark();
5160
5641
  }
5642
+ addFloatingGroup(item, coord, options) {
5643
+ var _a, _b;
5644
+ let group;
5645
+ if (item instanceof DockviewPanel) {
5646
+ group = this.createGroup();
5647
+ this.removePanel(item, {
5648
+ removeEmptyGroup: true,
5649
+ skipDispose: true,
5650
+ });
5651
+ group.model.openPanel(item);
5652
+ }
5653
+ else {
5654
+ group = item;
5655
+ const skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
5656
+ options.skipRemoveGroup;
5657
+ if (!skip) {
5658
+ this.doRemoveGroup(item, { skipDispose: true });
5659
+ }
5660
+ }
5661
+ group.model.isFloating = true;
5662
+ const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number' ? Math.max(coord.x, 0) : 100;
5663
+ const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number' ? Math.max(coord.y, 0) : 100;
5664
+ const overlay = new Overlay({
5665
+ container: this.gridview.element,
5666
+ content: group.element,
5667
+ height: (_a = coord === null || coord === void 0 ? void 0 : coord.height) !== null && _a !== void 0 ? _a : 300,
5668
+ width: (_b = coord === null || coord === void 0 ? void 0 : coord.width) !== null && _b !== void 0 ? _b : 300,
5669
+ left: overlayLeft,
5670
+ top: overlayTop,
5671
+ minimumInViewportWidth: 100,
5672
+ minimumInViewportHeight: 100,
5673
+ });
5674
+ const el = group.element.querySelector('.void-container');
5675
+ if (!el) {
5676
+ throw new Error('failed to find drag handle');
5677
+ }
5678
+ overlay.setupDrag(el, {
5679
+ inDragMode: typeof (options === null || options === void 0 ? void 0 : options.inDragMode) === 'boolean'
5680
+ ? options.inDragMode
5681
+ : false,
5682
+ });
5683
+ const floatingGroupPanel = new DockviewFloatingGroupPanel(group, overlay);
5684
+ const disposable = watchElementResize(group.element, (entry) => {
5685
+ const { width, height } = entry.contentRect;
5686
+ group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
5687
+ });
5688
+ floatingGroupPanel.addDisposables(overlay.onDidChange(() => {
5689
+ // this is either a resize or a move
5690
+ // to inform the panels .layout(...) the group with it's current size
5691
+ // don't care about resize since the above watcher handles that
5692
+ group.layout(group.height, group.width);
5693
+ }), overlay.onDidChangeEnd(() => {
5694
+ this._bufferOnDidLayoutChange.fire();
5695
+ }), group.onDidChange((event) => {
5696
+ overlay.setBounds({
5697
+ height: event === null || event === void 0 ? void 0 : event.height,
5698
+ width: event === null || event === void 0 ? void 0 : event.width,
5699
+ });
5700
+ }), {
5701
+ dispose: () => {
5702
+ disposable.dispose();
5703
+ group.model.isFloating = false;
5704
+ remove(this.floatingGroups, floatingGroupPanel);
5705
+ this.updateWatermark();
5706
+ },
5707
+ });
5708
+ this.floatingGroups.push(floatingGroupPanel);
5709
+ this.updateWatermark();
5710
+ }
5161
5711
  orthogonalize(position) {
5162
5712
  switch (position) {
5163
5713
  case 'top':
@@ -5180,6 +5730,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5180
5730
  switch (position) {
5181
5731
  case 'top':
5182
5732
  case 'left':
5733
+ case 'center':
5183
5734
  return this.createGroupAtLocation([0]); // insert into first position
5184
5735
  case 'bottom':
5185
5736
  case 'right':
@@ -5197,6 +5748,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5197
5748
  }
5198
5749
  this.layout(this.gridview.width, this.gridview.height, true);
5199
5750
  }
5751
+ layout(width, height, forceResize) {
5752
+ super.layout(width, height, forceResize);
5753
+ if (this.floatingGroups) {
5754
+ for (const floating of this.floatingGroups) {
5755
+ // ensure floting groups stay within visible boundaries
5756
+ floating.overlay.setBounds();
5757
+ }
5758
+ }
5759
+ }
5200
5760
  focus() {
5201
5761
  var _a;
5202
5762
  (_a = this.activeGroup) === null || _a === void 0 ? void 0 : _a.focus();
@@ -5259,51 +5819,81 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5259
5819
  collection[panel.id] = panel.toJSON();
5260
5820
  return collection;
5261
5821
  }, {});
5262
- return {
5822
+ const floats = this.floatingGroups.map((floatingGroup) => {
5823
+ return {
5824
+ data: floatingGroup.group.toJSON(),
5825
+ position: floatingGroup.overlay.toJSON(),
5826
+ };
5827
+ });
5828
+ const result = {
5263
5829
  grid: data,
5264
5830
  panels,
5265
5831
  activeGroup: (_a = this.activeGroup) === null || _a === void 0 ? void 0 : _a.id,
5266
5832
  };
5833
+ if (floats.length > 0) {
5834
+ result.floatingGroups = floats;
5835
+ }
5836
+ return result;
5267
5837
  }
5268
5838
  fromJSON(data) {
5839
+ var _a;
5269
5840
  this.clear();
5270
5841
  const { grid, panels, activeGroup } = data;
5271
5842
  if (grid.root.type !== 'branch' || !Array.isArray(grid.root.data)) {
5272
5843
  throw new Error('root must be of type branch');
5273
5844
  }
5845
+ // take note of the existing dimensions
5846
+ const width = this.width;
5847
+ const height = this.height;
5848
+ const createGroupFromSerializedState = (data) => {
5849
+ const { id, locked, hideHeader, views, activeView } = data;
5850
+ const group = this.createGroup({
5851
+ id,
5852
+ locked: !!locked,
5853
+ hideHeader: !!hideHeader,
5854
+ });
5855
+ this._onDidAddGroup.fire(group);
5856
+ for (const child of views) {
5857
+ const panel = this._deserializer.fromJSON(panels[child], group);
5858
+ const isActive = typeof activeView === 'string' && activeView === panel.id;
5859
+ group.model.openPanel(panel, {
5860
+ skipSetPanelActive: !isActive,
5861
+ skipSetGroupActive: true,
5862
+ });
5863
+ }
5864
+ if (!group.activePanel && group.panels.length > 0) {
5865
+ group.model.openPanel(group.panels[group.panels.length - 1], {
5866
+ skipSetGroupActive: true,
5867
+ });
5868
+ }
5869
+ return group;
5870
+ };
5274
5871
  this.gridview.deserialize(grid, {
5275
5872
  fromJSON: (node) => {
5276
- const { id, locked, hideHeader, views, activeView } = node.data;
5277
- const group = this.createGroup({
5278
- id,
5279
- locked: !!locked,
5280
- hideHeader: !!hideHeader,
5281
- });
5282
- this._onDidAddGroup.fire(group);
5283
- for (const child of views) {
5284
- const panel = this._deserializer.fromJSON(panels[child], group);
5285
- const isActive = typeof activeView === 'string' &&
5286
- activeView === panel.id;
5287
- group.model.openPanel(panel, {
5288
- skipSetPanelActive: !isActive,
5289
- skipSetGroupActive: true,
5290
- });
5291
- }
5292
- if (!group.activePanel && group.panels.length > 0) {
5293
- group.model.openPanel(group.panels[group.panels.length - 1], {
5294
- skipSetGroupActive: true,
5295
- });
5296
- }
5297
- return group;
5873
+ return createGroupFromSerializedState(node.data);
5298
5874
  },
5299
5875
  });
5876
+ this.layout(width, height, true);
5877
+ const serializedFloatingGroups = (_a = data.floatingGroups) !== null && _a !== void 0 ? _a : [];
5878
+ for (const serializedFloatingGroup of serializedFloatingGroups) {
5879
+ const { data, position } = serializedFloatingGroup;
5880
+ const group = createGroupFromSerializedState(data);
5881
+ this.addFloatingGroup(group, {
5882
+ x: position.left,
5883
+ y: position.top,
5884
+ height: position.height,
5885
+ width: position.width,
5886
+ }, { skipRemoveGroup: true, inDragMode: false });
5887
+ }
5888
+ for (const floatingGroup of this.floatingGroups) {
5889
+ floatingGroup.overlay.setBounds();
5890
+ }
5300
5891
  if (typeof activeGroup === 'string') {
5301
5892
  const panel = this.getPanel(activeGroup);
5302
5893
  if (panel) {
5303
5894
  this.doSetGroupActive(panel);
5304
5895
  }
5305
5896
  }
5306
- this.gridview.layout(this.width, this.height);
5307
5897
  this._onDidLayoutFromJSON.fire();
5308
5898
  }
5309
5899
  clear() {
@@ -5312,7 +5902,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5312
5902
  const hasActivePanel = !!this.activePanel;
5313
5903
  for (const group of groups) {
5314
5904
  // remove the group will automatically remove the panels
5315
- this.removeGroup(group, true);
5905
+ this.removeGroup(group, { skipActive: true });
5316
5906
  }
5317
5907
  if (hasActiveGroup) {
5318
5908
  this.doSetGroupActive(undefined);
@@ -5334,6 +5924,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5334
5924
  throw new Error(`panel with id ${options.id} already exists`);
5335
5925
  }
5336
5926
  let referenceGroup;
5927
+ if (options.position && options.floating) {
5928
+ throw new Error('you can only provide one of: position, floating as arguments to .addPanel(...)');
5929
+ }
5337
5930
  if (options.position) {
5338
5931
  if (isPanelOptionsWithPanel(options.position)) {
5339
5932
  const referencePanel = typeof options.position.referencePanel === 'string'
@@ -5366,7 +5959,20 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5366
5959
  let panel;
5367
5960
  if (referenceGroup) {
5368
5961
  const target = toTarget(((_b = options.position) === null || _b === void 0 ? void 0 : _b.direction) || 'within');
5369
- if (target === 'center') {
5962
+ if (options.floating) {
5963
+ const group = this.createGroup();
5964
+ panel = this.createPanel(options, group);
5965
+ group.model.openPanel(panel);
5966
+ const o = typeof options.floating === 'object' &&
5967
+ options.floating !== null
5968
+ ? options.floating
5969
+ : {};
5970
+ this.addFloatingGroup(group, o, {
5971
+ inDragMode: false,
5972
+ skipRemoveGroup: true,
5973
+ });
5974
+ }
5975
+ else if (referenceGroup.api.isFloating || target === 'center') {
5370
5976
  panel = this.createPanel(options, referenceGroup);
5371
5977
  referenceGroup.model.openPanel(panel);
5372
5978
  }
@@ -5378,6 +5984,19 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5378
5984
  group.model.openPanel(panel);
5379
5985
  }
5380
5986
  }
5987
+ else if (options.floating) {
5988
+ const group = this.createGroup();
5989
+ panel = this.createPanel(options, group);
5990
+ group.model.openPanel(panel);
5991
+ const o = typeof options.floating === 'object' &&
5992
+ options.floating !== null
5993
+ ? options.floating
5994
+ : {};
5995
+ this.addFloatingGroup(group, o, {
5996
+ inDragMode: false,
5997
+ skipRemoveGroup: true,
5998
+ });
5999
+ }
5381
6000
  else {
5382
6001
  const group = this.createGroupAtLocation();
5383
6002
  panel = this.createPanel(options, group);
@@ -5394,7 +6013,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5394
6013
  throw new Error(`cannot remove panel ${panel.id}. it's missing a group.`);
5395
6014
  }
5396
6015
  group.model.removePanel(panel);
5397
- panel.dispose();
6016
+ if (!options.skipDispose) {
6017
+ panel.dispose();
6018
+ }
5398
6019
  if (group.size === 0 && options.removeEmptyGroup) {
5399
6020
  this.removeGroup(group);
5400
6021
  }
@@ -5409,7 +6030,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5409
6030
  }
5410
6031
  updateWatermark() {
5411
6032
  var _a, _b;
5412
- if (this.groups.length === 0) {
6033
+ if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
5413
6034
  if (!this.watermark) {
5414
6035
  this.watermark = this.createWatermarkComponent();
5415
6036
  this.watermark.init({
@@ -5418,7 +6039,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5418
6039
  const watermarkContainer = document.createElement('div');
5419
6040
  watermarkContainer.className = 'dv-watermark-container';
5420
6041
  watermarkContainer.appendChild(this.watermark.element);
5421
- this.element.appendChild(watermarkContainer);
6042
+ this.gridview.element.appendChild(watermarkContainer);
5422
6043
  }
5423
6044
  }
5424
6045
  else if (this.watermark) {
@@ -5468,15 +6089,28 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5468
6089
  return group;
5469
6090
  }
5470
6091
  }
5471
- removeGroup(group, skipActive = false) {
6092
+ removeGroup(group, options) {
6093
+ var _a;
5472
6094
  const panels = [...group.panels]; // reassign since group panels will mutate
5473
6095
  for (const panel of panels) {
5474
6096
  this.removePanel(panel, {
5475
6097
  removeEmptyGroup: false,
5476
- skipDispose: false,
6098
+ skipDispose: (_a = options === null || options === void 0 ? void 0 : options.skipDispose) !== null && _a !== void 0 ? _a : false,
5477
6099
  });
5478
6100
  }
5479
- super.doRemoveGroup(group, { skipActive });
6101
+ this.doRemoveGroup(group, options);
6102
+ }
6103
+ doRemoveGroup(group, options) {
6104
+ const floatingGroup = this.floatingGroups.find((_) => _.group === group);
6105
+ if (floatingGroup) {
6106
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6107
+ floatingGroup.group.dispose();
6108
+ this._groups.delete(group.id);
6109
+ }
6110
+ floatingGroup.dispose();
6111
+ return floatingGroup.group;
6112
+ }
6113
+ return super.doRemoveGroup(group, options);
5480
6114
  }
5481
6115
  moveGroupOrPanel(destinationGroup, sourceGroupId, sourceItemId, destinationTarget, destinationIndex) {
5482
6116
  var _a;
@@ -5507,25 +6141,26 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5507
6141
  const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
5508
6142
  if (sourceGroup && sourceGroup.size < 2) {
5509
6143
  const [targetParentLocation, to] = tail(targetLocation);
5510
- const sourceLocation = getGridLocation(sourceGroup.element);
5511
- const [sourceParentLocation, from] = tail(sourceLocation);
5512
- if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
5513
- // special case when 'swapping' two views within same grid location
5514
- // if a group has one tab - we are essentially moving the 'group'
5515
- // which is equivalent to swapping two views in this case
5516
- this.gridview.moveView(sourceParentLocation, from, to);
5517
- }
5518
- else {
5519
- // source group will become empty so delete the group
5520
- const targetGroup = this.doRemoveGroup(sourceGroup, {
5521
- skipActive: true,
5522
- skipDispose: true,
5523
- });
5524
- // after deleting the group we need to re-evaulate the ref location
5525
- const updatedReferenceLocation = getGridLocation(destinationGroup.element);
5526
- const location = getRelativeLocation(this.gridview.orientation, updatedReferenceLocation, destinationTarget);
5527
- this.doAddGroup(targetGroup, location);
6144
+ const isFloating = this.floatingGroups.find((x) => x.group === sourceGroup);
6145
+ if (!isFloating) {
6146
+ const sourceLocation = getGridLocation(sourceGroup.element);
6147
+ const [sourceParentLocation, from] = tail(sourceLocation);
6148
+ if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
6149
+ // special case when 'swapping' two views within same grid location
6150
+ // if a group has one tab - we are essentially moving the 'group'
6151
+ // which is equivalent to swapping two views in this case
6152
+ this.gridview.moveView(sourceParentLocation, from, to);
6153
+ }
5528
6154
  }
6155
+ // source group will become empty so delete the group
6156
+ const targetGroup = this.doRemoveGroup(sourceGroup, {
6157
+ skipActive: true,
6158
+ skipDispose: true,
6159
+ });
6160
+ // after deleting the group we need to re-evaulate the ref location
6161
+ const updatedReferenceLocation = getGridLocation(destinationGroup.element);
6162
+ const location = getRelativeLocation(this.gridview.orientation, updatedReferenceLocation, destinationTarget);
6163
+ this.doAddGroup(targetGroup, location);
5529
6164
  }
5530
6165
  else {
5531
6166
  const groupItem = (sourceGroup === null || sourceGroup === void 0 ? void 0 : sourceGroup.model.removePanel(sourceItemId)) ||
@@ -5554,7 +6189,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5554
6189
  }
5555
6190
  }
5556
6191
  else {
5557
- this.gridview.removeView(getGridLocation(sourceGroup.element));
6192
+ const floatingGroup = this.floatingGroups.find((x) => x.group === sourceGroup);
6193
+ if (floatingGroup) {
6194
+ floatingGroup.dispose();
6195
+ }
6196
+ else {
6197
+ this.gridview.removeView(getGridLocation(sourceGroup.element));
6198
+ }
5558
6199
  const referenceLocation = getGridLocation(referenceGroup.element);
5559
6200
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, target);
5560
6201
  this.gridview.addView(sourceGroup, exports.Sizing.Distribute, dropLocation);
@@ -5709,6 +6350,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5709
6350
  this.clear();
5710
6351
  const { grid, activePanel } = serializedGridview;
5711
6352
  const queue = [];
6353
+ // take note of the existing dimensions
6354
+ const width = this.width;
6355
+ const height = this.height;
5712
6356
  this.gridview.deserialize(grid, {
5713
6357
  fromJSON: (node) => {
5714
6358
  const { data } = node;
@@ -5734,7 +6378,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5734
6378
  return view;
5735
6379
  },
5736
6380
  });
5737
- this.layout(this.width, this.height, true);
6381
+ this.layout(width, height, true);
5738
6382
  queue.forEach((f) => f());
5739
6383
  if (typeof activePanel === 'string') {
5740
6384
  const panel = this.getPanel(activePanel);
@@ -6048,6 +6692,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6048
6692
  this.clear();
6049
6693
  const { views, orientation, size, activeView } = serializedSplitview;
6050
6694
  const queue = [];
6695
+ // take note of the existing dimensions
6696
+ const width = this.width;
6697
+ const height = this.height;
6051
6698
  this.splitview = new Splitview(this.element, {
6052
6699
  orientation,
6053
6700
  proportionalLayout: this.options.proportionalLayout,
@@ -6084,7 +6731,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6084
6731
  }),
6085
6732
  },
6086
6733
  });
6087
- this.layout(this.width, this.height);
6734
+ this.layout(width, height);
6088
6735
  queue.forEach((f) => f());
6089
6736
  if (typeof activeView === 'string') {
6090
6737
  const panel = this.getPanel(activeView);
@@ -6351,6 +6998,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6351
6998
  this.clear();
6352
6999
  const { views, size } = serializedPaneview;
6353
7000
  const queue = [];
7001
+ // take note of the existing dimensions
7002
+ const width = this.width;
7003
+ const height = this.height;
6354
7004
  this.paneview = new Paneview(this.element, {
6355
7005
  orientation: exports.Orientation.VERTICAL,
6356
7006
  descriptor: {
@@ -6406,7 +7056,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6406
7056
  }),
6407
7057
  },
6408
7058
  });
6409
- this.layout(this.width, this.height);
7059
+ this.layout(width, height);
6410
7060
  queue.forEach((f) => f());
6411
7061
  this._onDidLayoutfromJSON.fire();
6412
7062
  }
@@ -6789,7 +7439,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6789
7439
  }
6790
7440
  }
6791
7441
 
6792
- class ReactGroupControlsRendererPart {
7442
+ class ReactHeaderActionsRendererPart {
6793
7443
  get element() {
6794
7444
  return this._element;
6795
7445
  }
@@ -6826,6 +7476,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6826
7476
  panels: this._group.model.panels,
6827
7477
  activePanel: this._group.model.activePanel,
6828
7478
  isGroupActive: this._group.api.isActive,
7479
+ group: this._group,
6829
7480
  });
6830
7481
  }
6831
7482
  update(event) {
@@ -6859,7 +7510,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6859
7510
  function createGroupControlElement(component, store) {
6860
7511
  return component
6861
7512
  ? (groupPanel) => {
6862
- return new ReactGroupControlsRendererPart(component, store, groupPanel);
7513
+ return new ReactHeaderActionsRendererPart(component, store, groupPanel);
6863
7514
  }
6864
7515
  : undefined;
6865
7516
  }
@@ -6916,8 +7567,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6916
7567
  ? { separatorBorder: 'transparent' }
6917
7568
  : undefined,
6918
7569
  showDndOverlay: props.showDndOverlay,
6919
- createGroupControlElement: createGroupControlElement(props.groupControlComponent, { addPortal }),
7570
+ createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7571
+ createRightHeaderActionsElement: createGroupControlElement(props.rightHeaderActionsComponent, { addPortal }),
6920
7572
  singleTabMode: props.singleTabMode,
7573
+ disableFloatingGroups: props.disableFloatingGroups,
6921
7574
  });
6922
7575
  const { clientWidth, clientHeight } = domRef.current;
6923
7576
  dockview.layout(clientWidth, clientHeight);
@@ -6976,6 +7629,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6976
7629
  frameworkTabComponents: props.tabComponents,
6977
7630
  });
6978
7631
  }, [props.tabComponents]);
7632
+ React__namespace.useEffect(() => {
7633
+ if (!dockviewRef.current) {
7634
+ return;
7635
+ }
7636
+ dockviewRef.current.updateOptions({
7637
+ disableFloatingGroups: props.disableFloatingGroups,
7638
+ });
7639
+ }, [props.disableFloatingGroups]);
6979
7640
  React__namespace.useEffect(() => {
6980
7641
  if (!dockviewRef.current) {
6981
7642
  return;
@@ -6997,9 +7658,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6997
7658
  return;
6998
7659
  }
6999
7660
  dockviewRef.current.updateOptions({
7000
- createGroupControlElement: createGroupControlElement(props.groupControlComponent, { addPortal }),
7661
+ createRightHeaderActionsElement: createGroupControlElement(props.rightHeaderActionsComponent, { addPortal }),
7662
+ });
7663
+ }, [props.rightHeaderActionsComponent]);
7664
+ React__namespace.useEffect(() => {
7665
+ if (!dockviewRef.current) {
7666
+ return;
7667
+ }
7668
+ dockviewRef.current.updateOptions({
7669
+ createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7001
7670
  });
7002
- }, [props.groupControlComponent]);
7671
+ }, [props.leftHeaderActionsComponent]);
7003
7672
  return (React__namespace.createElement("div", { className: props.className, style: { height: '100%', width: '100%' }, ref: domRef }, portals));
7004
7673
  });
7005
7674
  DockviewReact.displayName = 'DockviewComponent';
@@ -7018,6 +7687,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
7018
7687
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
7019
7688
  PERFORMANCE OF THIS SOFTWARE.
7020
7689
  ***************************************************************************** */
7690
+ /* global Reflect, Promise, SuppressedError, Symbol */
7691
+
7021
7692
 
7022
7693
  function __rest(s, e) {
7023
7694
  var t = {};
@@ -7029,7 +7700,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
7029
7700
  t[p[i]] = s[p[i]];
7030
7701
  }
7031
7702
  return t;
7032
- }
7703
+ }
7704
+
7705
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
7706
+ var e = new Error(message);
7707
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
7708
+ };
7033
7709
 
7034
7710
  const CloseButton = () => (React__namespace.createElement("svg", { height: "11", width: "11", viewBox: "0 0 28 28", "aria-hidden": 'false', focusable: false, className: "dockview-svg" },
7035
7711
  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" })));
@@ -7357,6 +8033,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
7357
8033
  exports.positionToDirection = positionToDirection;
7358
8034
  exports.toTarget = toTarget;
7359
8035
  exports.usePortalsLifecycle = usePortalsLifecycle;
7360
- exports.watchElementResize = watchElementResize;
7361
8036
 
7362
8037
  }));
8038
+ //# sourceMappingURL=dockview.amd.js.map