dockview 1.8.5 → 1.9.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 (46) hide show
  1. package/README.md +15 -10
  2. package/dist/cjs/dockview/defaultTab.js.map +1 -1
  3. package/dist/cjs/dockview/dockview.d.ts +3 -1
  4. package/dist/cjs/dockview/dockview.d.ts.map +1 -1
  5. package/dist/cjs/dockview/dockview.js +2 -0
  6. package/dist/cjs/dockview/dockview.js.map +1 -1
  7. package/dist/cjs/dockview/reactWatermarkPart.js.map +1 -1
  8. package/dist/cjs/gridview/gridview.js.map +1 -1
  9. package/dist/cjs/gridview/view.js.map +1 -1
  10. package/dist/cjs/paneview/paneview.js.map +1 -1
  11. package/dist/cjs/react.js.map +1 -1
  12. package/dist/cjs/splitview/splitview.js.map +1 -1
  13. package/dist/cjs/splitview/view.js.map +1 -1
  14. package/dist/dockview.amd.js +897 -169
  15. package/dist/dockview.amd.js.map +1 -1
  16. package/dist/dockview.amd.min.js +2 -2
  17. package/dist/dockview.amd.min.js.map +1 -1
  18. package/dist/dockview.amd.min.noStyle.js +2 -2
  19. package/dist/dockview.amd.min.noStyle.js.map +1 -1
  20. package/dist/dockview.amd.noStyle.js +897 -169
  21. package/dist/dockview.amd.noStyle.js.map +1 -1
  22. package/dist/dockview.cjs.js +897 -169
  23. package/dist/dockview.cjs.js.map +1 -1
  24. package/dist/dockview.esm.js +897 -169
  25. package/dist/dockview.esm.js.map +1 -1
  26. package/dist/dockview.esm.min.js +2 -2
  27. package/dist/dockview.esm.min.js.map +1 -1
  28. package/dist/dockview.js +897 -169
  29. package/dist/dockview.js.map +1 -1
  30. package/dist/dockview.min.js +2 -2
  31. package/dist/dockview.min.js.map +1 -1
  32. package/dist/dockview.min.noStyle.js +2 -2
  33. package/dist/dockview.min.noStyle.js.map +1 -1
  34. package/dist/dockview.noStyle.js +897 -169
  35. package/dist/dockview.noStyle.js.map +1 -1
  36. package/dist/esm/dockview/defaultTab.js.map +1 -1
  37. package/dist/esm/dockview/dockview.d.ts +3 -1
  38. package/dist/esm/dockview/dockview.d.ts.map +1 -1
  39. package/dist/esm/dockview/dockview.js +2 -0
  40. package/dist/esm/dockview/dockview.js.map +1 -1
  41. package/dist/esm/dockview/reactWatermarkPart.js.map +1 -1
  42. package/dist/esm/gridview/gridview.js.map +1 -1
  43. package/dist/esm/paneview/paneview.js.map +1 -1
  44. package/dist/esm/react.js.map +1 -1
  45. package/dist/esm/splitview/splitview.js.map +1 -1
  46. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * dockview
3
- * @version 1.8.5
3
+ * @version 1.9.0
4
4
  * @link https://github.com/mathuo/dockview
5
5
  * @license MIT
6
6
  */
@@ -263,6 +263,14 @@ var Disposable;
263
263
  // noop
264
264
  },
265
265
  };
266
+ function from(func) {
267
+ return {
268
+ dispose: () => {
269
+ func();
270
+ },
271
+ };
272
+ }
273
+ Disposable.from = from;
266
274
  })(Disposable || (Disposable = {}));
267
275
  class CompositeDisposable {
268
276
  get isDisposed() {
@@ -447,6 +455,61 @@ function quasiPreventDefault(event) {
447
455
  function quasiDefaultPrevented(event) {
448
456
  return event[QUASI_PREVENT_DEFAULT_KEY];
449
457
  }
458
+ function addStyles(document, styleSheetList) {
459
+ const styleSheets = Array.from(styleSheetList);
460
+ for (const styleSheet of styleSheets) {
461
+ if (styleSheet.href) {
462
+ const link = document.createElement('link');
463
+ link.href = styleSheet.href;
464
+ link.type = styleSheet.type;
465
+ link.rel = 'stylesheet';
466
+ document.head.appendChild(link);
467
+ }
468
+ let cssTexts = [];
469
+ try {
470
+ if (styleSheet.cssRules) {
471
+ cssTexts = Array.from(styleSheet.cssRules).map((rule) => rule.cssText);
472
+ }
473
+ }
474
+ catch (err) {
475
+ // security errors (lack of permissions), ignore
476
+ }
477
+ for (const rule of cssTexts) {
478
+ const style = document.createElement('style');
479
+ style.appendChild(document.createTextNode(rule));
480
+ document.head.appendChild(style);
481
+ }
482
+ }
483
+ }
484
+ function getDomNodePagePosition(domNode) {
485
+ const { left, top, width, height } = domNode.getBoundingClientRect();
486
+ return {
487
+ left: left + window.scrollX,
488
+ top: top + window.scrollY,
489
+ width: width,
490
+ height: height,
491
+ };
492
+ }
493
+ /**
494
+ * Check whether an element is in the DOM (including the Shadow DOM)
495
+ * @see https://terodox.tech/how-to-tell-if-an-element-is-in-the-dom-including-the-shadow-dom/
496
+ */
497
+ function isInDocument(element) {
498
+ let currentElement = element;
499
+ while (currentElement === null || currentElement === void 0 ? void 0 : currentElement.parentNode) {
500
+ if (currentElement.parentNode === document) {
501
+ return true;
502
+ }
503
+ else if (currentElement.parentNode instanceof DocumentFragment) {
504
+ // handle shadow DOMs
505
+ currentElement = currentElement.parentNode.host;
506
+ }
507
+ else {
508
+ currentElement = currentElement.parentNode;
509
+ }
510
+ }
511
+ return false;
512
+ }
450
513
 
451
514
  function tail(arr) {
452
515
  if (arr.length === 0) {
@@ -644,6 +707,9 @@ var Sizing;
644
707
  Sizing.Invisible = Invisible;
645
708
  })(Sizing || (Sizing = {}));
646
709
  class Splitview {
710
+ get contentSize() {
711
+ return this._contentSize;
712
+ }
647
713
  get size() {
648
714
  return this._size;
649
715
  }
@@ -709,7 +775,7 @@ class Splitview {
709
775
  this.sashes = [];
710
776
  this._size = 0;
711
777
  this._orthogonalSize = 0;
712
- this.contentSize = 0;
778
+ this._contentSize = 0;
713
779
  this._proportions = undefined;
714
780
  this._startSnappingEnabled = true;
715
781
  this._endSnappingEnabled = true;
@@ -828,7 +894,7 @@ class Splitview {
828
894
  );
829
895
  });
830
896
  // Initialize content size and proportions for first layout
831
- this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
897
+ this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
832
898
  this.saveProportions();
833
899
  }
834
900
  }
@@ -1102,7 +1168,7 @@ class Splitview {
1102
1168
  this.addView(view, sizing, to);
1103
1169
  }
1104
1170
  layout(size, orthogonalSize) {
1105
- const previousSize = Math.max(this.size, this.contentSize);
1171
+ const previousSize = Math.max(this.size, this._contentSize);
1106
1172
  this.size = size;
1107
1173
  this.orthogonalSize = orthogonalSize;
1108
1174
  if (!this.proportions) {
@@ -1112,9 +1178,23 @@ class Splitview {
1112
1178
  this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);
1113
1179
  }
1114
1180
  else {
1181
+ let total = 0;
1182
+ for (let i = 0; i < this.viewItems.length; i++) {
1183
+ const item = this.viewItems[i];
1184
+ const proportion = this.proportions[i];
1185
+ if (typeof proportion === 'number') {
1186
+ total += proportion;
1187
+ }
1188
+ else {
1189
+ size -= item.size;
1190
+ }
1191
+ }
1115
1192
  for (let i = 0; i < this.viewItems.length; i++) {
1116
1193
  const item = this.viewItems[i];
1117
- item.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);
1194
+ const proportion = this.proportions[i];
1195
+ if (typeof proportion === 'number' && total > 0) {
1196
+ item.size = clamp(Math.round((proportion * size) / total), item.minimumSize, item.maximumSize);
1197
+ }
1118
1198
  }
1119
1199
  }
1120
1200
  this.distributeEmptySpace();
@@ -1151,12 +1231,12 @@ class Splitview {
1151
1231
  }
1152
1232
  }
1153
1233
  saveProportions() {
1154
- if (this.proportionalLayout && this.contentSize > 0) {
1155
- this._proportions = this.viewItems.map((i) => i.size / this.contentSize);
1234
+ if (this.proportionalLayout && this._contentSize > 0) {
1235
+ this._proportions = this.viewItems.map((i) => i.visible ? i.size / this._contentSize : undefined);
1156
1236
  }
1157
1237
  }
1158
1238
  layoutViews() {
1159
- this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1239
+ this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1160
1240
  let sum = 0;
1161
1241
  const x = [];
1162
1242
  this.updateSashEnablement();
@@ -1250,7 +1330,7 @@ class Splitview {
1250
1330
  }
1251
1331
  else if (snappedAfter &&
1252
1332
  collapsesDown[index] &&
1253
- (position < this.contentSize || this.endSnappingEnabled)) {
1333
+ (position < this._contentSize || this.endSnappingEnabled)) {
1254
1334
  this.updateSash(sash, SashState.MAXIMUM);
1255
1335
  }
1256
1336
  else {
@@ -1539,7 +1619,6 @@ class LeafNode {
1539
1619
  setVisible(visible) {
1540
1620
  if (this.view.setVisible) {
1541
1621
  this.view.setVisible(visible);
1542
- this._onDidChange.fire({});
1543
1622
  }
1544
1623
  }
1545
1624
  layout(size, orthogonalSize) {
@@ -1571,10 +1650,14 @@ class BranchNode extends CompositeDisposable {
1571
1650
  get minimumSize() {
1572
1651
  return this.children.length === 0
1573
1652
  ? 0
1574
- : Math.max(...this.children.map((c) => c.minimumOrthogonalSize));
1653
+ : Math.max(...this.children.map((c, index) => this.splitview.isViewVisible(index)
1654
+ ? c.minimumOrthogonalSize
1655
+ : 0));
1575
1656
  }
1576
1657
  get maximumSize() {
1577
- return Math.min(...this.children.map((c) => c.maximumOrthogonalSize));
1658
+ return Math.min(...this.children.map((c, index) => this.splitview.isViewVisible(index)
1659
+ ? c.maximumOrthogonalSize
1660
+ : Number.POSITIVE_INFINITY));
1578
1661
  }
1579
1662
  get minimumOrthogonalSize() {
1580
1663
  return this.splitview.minimumSize;
@@ -1632,6 +1715,8 @@ class BranchNode extends CompositeDisposable {
1632
1715
  this.children = [];
1633
1716
  this._onDidChange = new Emitter();
1634
1717
  this.onDidChange = this._onDidChange.event;
1718
+ this._onDidVisibilityChange = new Emitter();
1719
+ this.onDidVisibilityChange = this._onDidVisibilityChange.event;
1635
1720
  this._orthogonalSize = orthogonalSize;
1636
1721
  this._size = size;
1637
1722
  this.element = document.createElement('div');
@@ -1666,7 +1751,7 @@ class BranchNode extends CompositeDisposable {
1666
1751
  styles,
1667
1752
  });
1668
1753
  }
1669
- this.addDisposables(this._onDidChange, this.splitview.onDidSashEnd(() => {
1754
+ this.addDisposables(this._onDidChange, this._onDidVisibilityChange, this.splitview.onDidSashEnd(() => {
1670
1755
  this._onDidChange.fire({});
1671
1756
  }));
1672
1757
  this.setupChildrenEvents();
@@ -1689,7 +1774,15 @@ class BranchNode extends CompositeDisposable {
1689
1774
  if (this.splitview.isViewVisible(index) === visible) {
1690
1775
  return;
1691
1776
  }
1777
+ const wereAllChildrenHidden = this.splitview.contentSize === 0;
1692
1778
  this.splitview.setViewVisible(index, visible);
1779
+ const areAllChildrenHidden = this.splitview.contentSize === 0;
1780
+ // If all children are hidden then the parent should hide the entire splitview
1781
+ // If the entire splitview is hidden then the parent should show the splitview when a child is shown
1782
+ if ((visible && wereAllChildrenHidden) ||
1783
+ (!visible && areAllChildrenHidden)) {
1784
+ this._onDidVisibilityChange.fire(visible);
1785
+ }
1693
1786
  }
1694
1787
  moveChild(from, to) {
1695
1788
  if (from === to) {
@@ -1753,13 +1846,20 @@ class BranchNode extends CompositeDisposable {
1753
1846
  }
1754
1847
  setupChildrenEvents() {
1755
1848
  this._childrenDisposable.dispose();
1756
- this._childrenDisposable = Event.any(...this.children.map((c) => c.onDidChange))((e) => {
1849
+ this._childrenDisposable = new CompositeDisposable(Event.any(...this.children.map((c) => c.onDidChange))((e) => {
1757
1850
  /**
1758
1851
  * indicate a change has occured to allows any re-rendering but don't bubble
1759
1852
  * event because that was specific to this branch
1760
1853
  */
1761
1854
  this._onDidChange.fire({ size: e.orthogonalSize });
1762
- });
1855
+ }), ...this.children.map((c, i) => {
1856
+ if (c instanceof BranchNode) {
1857
+ return c.onDidVisibilityChange((visible) => {
1858
+ this.setChildVisible(i, visible);
1859
+ });
1860
+ }
1861
+ return Disposable.NONE;
1862
+ }));
1763
1863
  }
1764
1864
  dispose() {
1765
1865
  this._childrenDisposable.dispose();
@@ -1920,7 +2020,69 @@ class Gridview {
1920
2020
  get maximumHeight() {
1921
2021
  return this.root.maximumHeight;
1922
2022
  }
2023
+ maximizedView() {
2024
+ var _a;
2025
+ return (_a = this._maximizedNode) === null || _a === void 0 ? void 0 : _a.view;
2026
+ }
2027
+ hasMaximizedView() {
2028
+ return this._maximizedNode !== undefined;
2029
+ }
2030
+ maximizeView(view) {
2031
+ const location = getGridLocation(view.element);
2032
+ const [_, node] = this.getNode(location);
2033
+ if (!(node instanceof LeafNode)) {
2034
+ return;
2035
+ }
2036
+ if (this._maximizedNode === node) {
2037
+ return;
2038
+ }
2039
+ if (this.hasMaximizedView()) {
2040
+ this.exitMaximizedView();
2041
+ }
2042
+ function hideAllViewsBut(parent, exclude) {
2043
+ for (let i = 0; i < parent.children.length; i++) {
2044
+ const child = parent.children[i];
2045
+ if (child instanceof LeafNode) {
2046
+ if (child !== exclude) {
2047
+ parent.setChildVisible(i, false);
2048
+ }
2049
+ }
2050
+ else {
2051
+ hideAllViewsBut(child, exclude);
2052
+ }
2053
+ }
2054
+ }
2055
+ hideAllViewsBut(this.root, node);
2056
+ this._maximizedNode = node;
2057
+ this._onDidMaxmizedNodeChange.fire();
2058
+ }
2059
+ exitMaximizedView() {
2060
+ if (!this._maximizedNode) {
2061
+ return;
2062
+ }
2063
+ function showViewsInReverseOrder(parent) {
2064
+ for (let index = parent.children.length - 1; index >= 0; index--) {
2065
+ const child = parent.children[index];
2066
+ if (child instanceof LeafNode) {
2067
+ parent.setChildVisible(index, true);
2068
+ }
2069
+ else {
2070
+ showViewsInReverseOrder(child);
2071
+ }
2072
+ }
2073
+ }
2074
+ showViewsInReverseOrder(this.root);
2075
+ this._maximizedNode = undefined;
2076
+ this._onDidMaxmizedNodeChange.fire();
2077
+ }
1923
2078
  serialize() {
2079
+ if (this.hasMaximizedView()) {
2080
+ /**
2081
+ * do not persist maximized view state but we must first exit any maximized views
2082
+ * before serialization to ensure the correct dimensions are persisted
2083
+ */
2084
+ this.exitMaximizedView();
2085
+ }
1924
2086
  const root = serializeBranchNode(this.getView(), this.orientation);
1925
2087
  return {
1926
2088
  root,
@@ -1932,7 +2094,9 @@ class Gridview {
1932
2094
  dispose() {
1933
2095
  this.disposable.dispose();
1934
2096
  this._onDidChange.dispose();
2097
+ this._onDidMaxmizedNodeChange.dispose();
1935
2098
  this.root.dispose();
2099
+ this._maximizedNode = undefined;
1936
2100
  this.element.remove();
1937
2101
  }
1938
2102
  clear() {
@@ -1973,6 +2137,7 @@ class Gridview {
1973
2137
  const oldRoot = this._root;
1974
2138
  if (oldRoot) {
1975
2139
  oldRoot.dispose();
2140
+ this._maximizedNode = undefined;
1976
2141
  this.element.removeChild(oldRoot.element);
1977
2142
  }
1978
2143
  this._root = root;
@@ -2059,9 +2224,12 @@ class Gridview {
2059
2224
  constructor(proportionalLayout, styles, orientation) {
2060
2225
  this.proportionalLayout = proportionalLayout;
2061
2226
  this.styles = styles;
2227
+ this._maximizedNode = undefined;
2062
2228
  this.disposable = new MutableDisposable();
2063
2229
  this._onDidChange = new Emitter();
2064
2230
  this.onDidChange = this._onDidChange.event;
2231
+ this._onDidMaxmizedNodeChange = new Emitter();
2232
+ this.onDidMaxmizedNodeChange = this._onDidMaxmizedNodeChange.event;
2065
2233
  this.element = document.createElement('div');
2066
2234
  this.element.className = 'grid-view';
2067
2235
  this.root = new BranchNode(orientation, proportionalLayout, styles, 0, 0);
@@ -2075,6 +2243,9 @@ class Gridview {
2075
2243
  return parent.isChildVisible(index);
2076
2244
  }
2077
2245
  setViewVisible(location, visible) {
2246
+ if (this.hasMaximizedView()) {
2247
+ this.exitMaximizedView();
2248
+ }
2078
2249
  const [rest, index] = tail(location);
2079
2250
  const [, parent] = this.getNode(rest);
2080
2251
  if (!(parent instanceof BranchNode)) {
@@ -2083,6 +2254,9 @@ class Gridview {
2083
2254
  parent.setChildVisible(index, visible);
2084
2255
  }
2085
2256
  moveView(parentLocation, from, to) {
2257
+ if (this.hasMaximizedView()) {
2258
+ this.exitMaximizedView();
2259
+ }
2086
2260
  const [, parent] = this.getNode(parentLocation);
2087
2261
  if (!(parent instanceof BranchNode)) {
2088
2262
  throw new Error('Invalid location');
@@ -2090,6 +2264,9 @@ class Gridview {
2090
2264
  parent.moveChild(from, to);
2091
2265
  }
2092
2266
  addView(view, size, location) {
2267
+ if (this.hasMaximizedView()) {
2268
+ this.exitMaximizedView();
2269
+ }
2093
2270
  const [rest, index] = tail(location);
2094
2271
  const [pathToParent, parent] = this.getNode(rest);
2095
2272
  if (parent instanceof BranchNode) {
@@ -2122,6 +2299,9 @@ class Gridview {
2122
2299
  return this.removeView(location, sizing);
2123
2300
  }
2124
2301
  removeView(location, sizing) {
2302
+ if (this.hasMaximizedView()) {
2303
+ this.exitMaximizedView();
2304
+ }
2125
2305
  const [rest, index] = tail(location);
2126
2306
  const [pathToParent, parent] = this.getNode(rest);
2127
2307
  if (!(parent instanceof BranchNode)) {
@@ -2859,6 +3039,24 @@ class DockviewApi {
2859
3039
  moveToPrevious(options) {
2860
3040
  this.component.moveToPrevious(options);
2861
3041
  }
3042
+ maximizeGroup(panel) {
3043
+ this.component.maximizeGroup(panel.group);
3044
+ }
3045
+ hasMaximizedGroup() {
3046
+ return this.component.hasMaximizedGroup();
3047
+ }
3048
+ exitMaxmizedGroup() {
3049
+ this.component.exitMaximizedGroup();
3050
+ }
3051
+ get onDidMaxmizedGroupChange() {
3052
+ return this.component.onDidMaxmizedGroupChange;
3053
+ }
3054
+ /**
3055
+ * Add a popout group in a new Window
3056
+ */
3057
+ addPopoutGroup(item, options) {
3058
+ this.component.addPopoutGroup(item, options);
3059
+ }
2862
3060
  }
2863
3061
 
2864
3062
  class DragAndDropObserver extends CompositeDisposable {
@@ -2869,29 +3067,44 @@ class DragAndDropObserver extends CompositeDisposable {
2869
3067
  this.target = null;
2870
3068
  this.registerListeners();
2871
3069
  }
3070
+ onDragEnter(e) {
3071
+ this.target = e.target;
3072
+ this.callbacks.onDragEnter(e);
3073
+ }
3074
+ onDragOver(e) {
3075
+ e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
3076
+ if (this.callbacks.onDragOver) {
3077
+ this.callbacks.onDragOver(e);
3078
+ }
3079
+ }
3080
+ onDragLeave(e) {
3081
+ if (this.target === e.target) {
3082
+ this.target = null;
3083
+ this.callbacks.onDragLeave(e);
3084
+ }
3085
+ }
3086
+ onDragEnd(e) {
3087
+ this.target = null;
3088
+ this.callbacks.onDragEnd(e);
3089
+ }
3090
+ onDrop(e) {
3091
+ this.callbacks.onDrop(e);
3092
+ }
2872
3093
  registerListeners() {
2873
3094
  this.addDisposables(addDisposableListener(this.element, 'dragenter', (e) => {
2874
- this.target = e.target;
2875
- this.callbacks.onDragEnter(e);
3095
+ this.onDragEnter(e);
2876
3096
  }, true));
2877
3097
  this.addDisposables(addDisposableListener(this.element, 'dragover', (e) => {
2878
- e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
2879
- if (this.callbacks.onDragOver) {
2880
- this.callbacks.onDragOver(e);
2881
- }
3098
+ this.onDragOver(e);
2882
3099
  }, true));
2883
3100
  this.addDisposables(addDisposableListener(this.element, 'dragleave', (e) => {
2884
- if (this.target === e.target) {
2885
- this.target = null;
2886
- this.callbacks.onDragLeave(e);
2887
- }
3101
+ this.onDragLeave(e);
2888
3102
  }));
2889
3103
  this.addDisposables(addDisposableListener(this.element, 'dragend', (e) => {
2890
- this.target = null;
2891
- this.callbacks.onDragEnd(e);
3104
+ this.onDragEnd(e);
2892
3105
  }));
2893
3106
  this.addDisposables(addDisposableListener(this.element, 'drop', (e) => {
2894
- this.callbacks.onDrop(e);
3107
+ this.onDrop(e);
2895
3108
  }));
2896
3109
  }
2897
3110
  }
@@ -2943,7 +3156,7 @@ class Droptarget extends CompositeDisposable {
2943
3156
  this.onDrop = this._onDrop.event;
2944
3157
  // use a set to take advantage of #<set>.has
2945
3158
  this._acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2946
- this.addDisposables(this._onDrop, new DragAndDropObserver(this.element, {
3159
+ this.dnd = new DragAndDropObserver(this.element, {
2947
3160
  onDragEnter: () => undefined,
2948
3161
  onDragOver: (e) => {
2949
3162
  if (this._acceptedTargetZonesSet.size === 0) {
@@ -3010,7 +3223,8 @@ class Droptarget extends CompositeDisposable {
3010
3223
  this._onDrop.fire({ position: state, nativeEvent: e });
3011
3224
  }
3012
3225
  },
3013
- }));
3226
+ });
3227
+ this.addDisposables(this._onDrop, this.dnd);
3014
3228
  }
3015
3229
  setTargetZones(acceptedTargetZones) {
3016
3230
  this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
@@ -3166,12 +3380,22 @@ function calculateQuadrantAsPixels(overlayType, x, y, width, height, threshold)
3166
3380
  return 'center';
3167
3381
  }
3168
3382
 
3383
+ var DockviewDropTargets;
3384
+ (function (DockviewDropTargets) {
3385
+ DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3386
+ DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3387
+ DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3388
+ DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3389
+ })(DockviewDropTargets || (DockviewDropTargets = {}));
3390
+
3169
3391
  class ContentContainer extends CompositeDisposable {
3170
3392
  get element() {
3171
3393
  return this._element;
3172
3394
  }
3173
- constructor() {
3395
+ constructor(accessor, group) {
3174
3396
  super();
3397
+ this.accessor = accessor;
3398
+ this.group = group;
3175
3399
  this.disposable = new MutableDisposable();
3176
3400
  this._onDidFocus = new Emitter();
3177
3401
  this.onDidFocus = this._onDidFocus.event;
@@ -3181,11 +3405,38 @@ class ContentContainer extends CompositeDisposable {
3181
3405
  this._element.className = 'content-container';
3182
3406
  this._element.tabIndex = -1;
3183
3407
  this.addDisposables(this._onDidFocus, this._onDidBlur);
3184
- // for hosted containers
3185
- // 1) register a drop target on the host
3186
- // 2) register window dragStart events to disable pointer events
3187
- // 3) register dragEnd events
3188
- // 4) register mouseMove events (if no buttons are present we take this as a dragEnd event)
3408
+ this.dropTarget = new Droptarget(this.element, {
3409
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3410
+ canDisplayOverlay: (event, position) => {
3411
+ if (this.group.locked === 'no-drop-target' ||
3412
+ (this.group.locked && position === 'center')) {
3413
+ return false;
3414
+ }
3415
+ const data = getPanelData();
3416
+ if (!data &&
3417
+ event.shiftKey &&
3418
+ this.group.location !== 'floating') {
3419
+ return false;
3420
+ }
3421
+ if (data && data.viewId === this.accessor.id) {
3422
+ if (data.groupId === this.group.id) {
3423
+ if (position === 'center') {
3424
+ // don't allow to drop on self for center position
3425
+ return false;
3426
+ }
3427
+ if (data.panelId === null) {
3428
+ // don't allow group move to drop anywhere on self
3429
+ return false;
3430
+ }
3431
+ }
3432
+ const groupHasOnePanelAndIsActiveDragElement = this.group.panels.length === 1 &&
3433
+ data.groupId === this.group.id;
3434
+ return !groupHasOnePanelAndIsActiveDragElement;
3435
+ }
3436
+ return this.group.canDisplayOverlay(event, position, DockviewDropTargets.Panel);
3437
+ },
3438
+ });
3439
+ this.addDisposables(this.dropTarget);
3189
3440
  }
3190
3441
  show() {
3191
3442
  this.element.style.display = '';
@@ -3193,23 +3444,43 @@ class ContentContainer extends CompositeDisposable {
3193
3444
  hide() {
3194
3445
  this.element.style.display = 'none';
3195
3446
  }
3196
- openPanel(panel) {
3197
- var _a;
3198
- if (this.panel === panel) {
3199
- return;
3200
- }
3201
- if (this.panel) {
3202
- if ((_a = this.panel.view) === null || _a === void 0 ? void 0 : _a.content) {
3203
- this._element.removeChild(this.panel.view.content.element);
3204
- }
3205
- this.panel = undefined;
3447
+ renderPanel(panel, options = { asActive: true }) {
3448
+ const doRender = options.asActive ||
3449
+ (this.panel && this.group.isPanelActive(this.panel));
3450
+ if (this.panel &&
3451
+ this.panel.view.content.element.parentElement === this._element) {
3452
+ /**
3453
+ * If the currently attached panel is mounted directly to the content then remove it
3454
+ */
3455
+ this._element.removeChild(this.panel.view.content.element);
3206
3456
  }
3207
3457
  this.panel = panel;
3208
- const disposable = new CompositeDisposable();
3209
- if (this.panel.view) {
3210
- const _onDidFocus = this.panel.view.content.onDidFocus;
3211
- const _onDidBlur = this.panel.view.content.onDidBlur;
3212
- const focusTracker = trackFocus(this._element);
3458
+ let container;
3459
+ switch (panel.api.renderer) {
3460
+ case 'onlyWhenVisibile':
3461
+ this.accessor.overlayRenderContainer.detatch(panel);
3462
+ if (this.panel) {
3463
+ if (doRender) {
3464
+ this._element.appendChild(this.panel.view.content.element);
3465
+ }
3466
+ }
3467
+ container = this._element;
3468
+ break;
3469
+ case 'always':
3470
+ if (panel.view.content.element.parentElement === this._element) {
3471
+ this._element.removeChild(panel.view.content.element);
3472
+ }
3473
+ container = this.accessor.overlayRenderContainer.attach({
3474
+ panel,
3475
+ referenceContainer: this,
3476
+ });
3477
+ break;
3478
+ }
3479
+ if (doRender) {
3480
+ const _onDidFocus = panel.view.content.onDidFocus;
3481
+ const _onDidBlur = panel.view.content.onDidBlur;
3482
+ const focusTracker = trackFocus(container);
3483
+ const disposable = new CompositeDisposable();
3213
3484
  disposable.addDisposables(focusTracker, focusTracker.onDidFocus(() => this._onDidFocus.fire()), focusTracker.onDidBlur(() => this._onDidBlur.fire()));
3214
3485
  if (_onDidFocus) {
3215
3486
  disposable.addDisposables(_onDidFocus(() => this._onDidFocus.fire()));
@@ -3217,17 +3488,23 @@ class ContentContainer extends CompositeDisposable {
3217
3488
  if (_onDidBlur) {
3218
3489
  disposable.addDisposables(_onDidBlur(() => this._onDidBlur.fire()));
3219
3490
  }
3220
- this._element.appendChild(this.panel.view.content.element);
3491
+ this.disposable.value = disposable;
3221
3492
  }
3222
- this.disposable.value = disposable;
3493
+ }
3494
+ openPanel(panel) {
3495
+ if (this.panel === panel) {
3496
+ return;
3497
+ }
3498
+ this.renderPanel(panel);
3223
3499
  }
3224
3500
  layout(_width, _height) {
3225
3501
  // noop
3226
3502
  }
3227
3503
  closePanel() {
3228
- var _a, _b, _c;
3229
- if ((_c = (_b = (_a = this.panel) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.element) {
3230
- this._element.removeChild(this.panel.view.content.element);
3504
+ if (this.panel) {
3505
+ if (this.accessor.options.defaultRenderer === 'onlyWhenVisibile') {
3506
+ this._element.removeChild(this.panel.view.content.element);
3507
+ }
3231
3508
  this.panel = undefined;
3232
3509
  }
3233
3510
  }
@@ -3237,14 +3514,6 @@ class ContentContainer extends CompositeDisposable {
3237
3514
  }
3238
3515
  }
3239
3516
 
3240
- var DockviewDropTargets;
3241
- (function (DockviewDropTargets) {
3242
- DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3243
- DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3244
- DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3245
- DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3246
- })(DockviewDropTargets || (DockviewDropTargets = {}));
3247
-
3248
3517
  class DragHandler extends CompositeDisposable {
3249
3518
  constructor(el) {
3250
3519
  super();
@@ -3419,7 +3688,7 @@ class GroupDragHandler extends DragHandler {
3419
3688
  }, true));
3420
3689
  }
3421
3690
  isCancelled(_event) {
3422
- if (this.group.api.isFloating && !_event.shiftKey) {
3691
+ if (this.group.api.location === 'floating' && !_event.shiftKey) {
3423
3692
  return true;
3424
3693
  }
3425
3694
  return false;
@@ -3621,7 +3890,7 @@ class TabsContainer extends CompositeDisposable {
3621
3890
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3622
3891
  if (isFloatingGroupsEnabled &&
3623
3892
  event.shiftKey &&
3624
- !this.group.api.isFloating) {
3893
+ this.group.api.location !== 'floating') {
3625
3894
  event.preventDefault();
3626
3895
  const { top, left } = this.element.getBoundingClientRect();
3627
3896
  const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
@@ -3686,7 +3955,7 @@ class TabsContainer extends CompositeDisposable {
3686
3955
  }), tab.onChanged((event) => {
3687
3956
  var _a;
3688
3957
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3689
- const isFloatingWithOnePanel = this.group.api.isFloating && this.size === 1;
3958
+ const isFloatingWithOnePanel = this.group.api.location === 'floating' && this.size === 1;
3690
3959
  if (isFloatingGroupsEnabled &&
3691
3960
  !isFloatingWithOnePanel &&
3692
3961
  event.shiftKey) {
@@ -3769,15 +4038,37 @@ class DockviewGroupPanelModel extends CompositeDisposable {
3769
4038
  }
3770
4039
  return isAncestor(document.activeElement, this.contentContainer.element);
3771
4040
  }
3772
- get isFloating() {
3773
- return this._isFloating;
3774
- }
3775
- set isFloating(value) {
3776
- this._isFloating = value;
3777
- this.dropTarget.setTargetZones(value ? ['center'] : ['top', 'bottom', 'left', 'right', 'center']);
3778
- toggleClass(this.container, 'dv-groupview-floating', value);
3779
- this.groupPanel.api._onDidFloatingStateChange.fire({
3780
- isFloating: this.isFloating,
4041
+ get location() {
4042
+ return this._location;
4043
+ }
4044
+ set location(value) {
4045
+ this._location = value;
4046
+ toggleClass(this.container, 'dv-groupview-floating', false);
4047
+ toggleClass(this.container, 'dv-groupview-popout', false);
4048
+ switch (value) {
4049
+ case 'grid':
4050
+ this.contentContainer.dropTarget.setTargetZones([
4051
+ 'top',
4052
+ 'bottom',
4053
+ 'left',
4054
+ 'right',
4055
+ 'center',
4056
+ ]);
4057
+ break;
4058
+ case 'floating':
4059
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4060
+ this.contentContainer.dropTarget.setTargetZones(value
4061
+ ? ['center']
4062
+ : ['top', 'bottom', 'left', 'right', 'center']);
4063
+ toggleClass(this.container, 'dv-groupview-floating', true);
4064
+ break;
4065
+ case 'popout':
4066
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4067
+ toggleClass(this.container, 'dv-groupview-popout', true);
4068
+ break;
4069
+ }
4070
+ this.groupPanel.api._onDidLocationChange.fire({
4071
+ location: this.location,
3781
4072
  });
3782
4073
  }
3783
4074
  constructor(container, accessor, id, options, groupPanel) {
@@ -3790,7 +4081,7 @@ class DockviewGroupPanelModel extends CompositeDisposable {
3790
4081
  this.groupPanel = groupPanel;
3791
4082
  this._isGroupActive = false;
3792
4083
  this._locked = false;
3793
- this._isFloating = false;
4084
+ this._location = 'grid';
3794
4085
  this.mostRecentlyUsed = [];
3795
4086
  this._onDidChange = new Emitter();
3796
4087
  this.onDidChange = this._onDidChange.event;
@@ -3813,35 +4104,7 @@ class DockviewGroupPanelModel extends CompositeDisposable {
3813
4104
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
3814
4105
  toggleClass(this.container, 'groupview', true);
3815
4106
  this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
3816
- this.contentContainer = new ContentContainer();
3817
- this.dropTarget = new Droptarget(this.contentContainer.element, {
3818
- acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3819
- canDisplayOverlay: (event, position) => {
3820
- if (this.locked === 'no-drop-target' ||
3821
- (this.locked && position === 'center')) {
3822
- return false;
3823
- }
3824
- const data = getPanelData();
3825
- if (!data && event.shiftKey && !this.isFloating) {
3826
- return false;
3827
- }
3828
- if (data && data.viewId === this.accessor.id) {
3829
- if (data.groupId === this.id) {
3830
- if (position === 'center') {
3831
- // don't allow to drop on self for center position
3832
- return false;
3833
- }
3834
- if (data.panelId === null) {
3835
- // don't allow group move to drop anywhere on self
3836
- return false;
3837
- }
3838
- }
3839
- const groupHasOnePanelAndIsActiveDragElement = this._panels.length === 1 && data.groupId === this.id;
3840
- return !groupHasOnePanelAndIsActiveDragElement;
3841
- }
3842
- return this.canDisplayOverlay(event, position, DockviewDropTargets.Panel);
3843
- },
3844
- });
4107
+ this.contentContainer = new ContentContainer(this.accessor, this);
3845
4108
  container.append(this.tabsContainer.element, this.contentContainer.element);
3846
4109
  this.header.hidden = !!options.hideHeader;
3847
4110
  this.locked = (_a = options.locked) !== null && _a !== void 0 ? _a : false;
@@ -3855,7 +4118,7 @@ class DockviewGroupPanelModel extends CompositeDisposable {
3855
4118
  this.accessor.doSetGroupActive(this.groupPanel, true);
3856
4119
  }), this.contentContainer.onDidBlur(() => {
3857
4120
  // noop
3858
- }), this.dropTarget.onDrop((event) => {
4121
+ }), this.contentContainer.dropTarget.onDrop((event) => {
3859
4122
  this.handleDropEvent(event.nativeEvent, event.position);
3860
4123
  }), this._onMove, this._onDidChange, this._onDidDrop, this._onDidAddPanel, this._onDidRemovePanel, this._onDidActivePanelChange);
3861
4124
  }
@@ -3904,6 +4167,9 @@ class DockviewGroupPanelModel extends CompositeDisposable {
3904
4167
  this.tabsContainer.setPrefixActionsElement(this._prefixHeaderActions.element);
3905
4168
  }
3906
4169
  }
4170
+ rerender(panel) {
4171
+ this.contentContainer.renderPanel(panel, { asActive: false });
4172
+ }
3907
4173
  indexOf(panel) {
3908
4174
  return this.tabsContainer.indexOf(panel.id);
3909
4175
  }
@@ -4095,12 +4361,12 @@ class DockviewGroupPanelModel extends CompositeDisposable {
4095
4361
  doAddPanel(panel, index = this.panels.length, skipSetActive = false) {
4096
4362
  const existingPanel = this._panels.indexOf(panel);
4097
4363
  const hasExistingPanel = existingPanel > -1;
4364
+ this.tabsContainer.show();
4365
+ this.contentContainer.show();
4098
4366
  this.tabsContainer.openPanel(panel, index);
4099
4367
  if (!skipSetActive) {
4100
4368
  this.contentContainer.openPanel(panel);
4101
4369
  }
4102
- this.tabsContainer.show();
4103
- this.contentContainer.show();
4104
4370
  if (hasExistingPanel) {
4105
4371
  // TODO - need to ensure ordering hasn't changed and if it has need to re-order this.panels
4106
4372
  return;
@@ -4216,7 +4482,6 @@ class DockviewGroupPanelModel extends CompositeDisposable {
4216
4482
  for (const panel of this.panels) {
4217
4483
  panel.dispose();
4218
4484
  }
4219
- this.dropTarget.dispose();
4220
4485
  this.tabsContainer.dispose();
4221
4486
  this.contentContainer.dispose();
4222
4487
  }
@@ -4255,7 +4520,7 @@ class Resizable extends CompositeDisposable {
4255
4520
  if (this.disableResizing) {
4256
4521
  return;
4257
4522
  }
4258
- if (!document.body.contains(this._element)) {
4523
+ if (!isInDocument(this._element)) {
4259
4524
  /**
4260
4525
  * since the event is dispatched through requestAnimationFrame there is a small chance
4261
4526
  * the component is no longer attached to the DOM, if that is the case the dimensions
@@ -4347,6 +4612,21 @@ class BaseGrid extends Resizable {
4347
4612
  isVisible(panel) {
4348
4613
  return this.gridview.isViewVisible(getGridLocation(panel.element));
4349
4614
  }
4615
+ maximizeGroup(panel) {
4616
+ this.gridview.maximizeView(panel);
4617
+ }
4618
+ isMaximizedGroup(panel) {
4619
+ return this.gridview.maximizedView() === panel;
4620
+ }
4621
+ exitMaximizedGroup() {
4622
+ this.gridview.exitMaximizedView();
4623
+ }
4624
+ hasMaximizedGroup() {
4625
+ return this.gridview.hasMaximizedView();
4626
+ }
4627
+ get onDidMaxmizedGroupChange() {
4628
+ return this.gridview.onDidMaxmizedNodeChange;
4629
+ }
4350
4630
  doAddGroup(group, location = [0], size) {
4351
4631
  this.gridview.addView(group, size !== null && size !== void 0 ? size : Sizing.Distribute, location);
4352
4632
  this._onDidAddGroup.fire(group);
@@ -5123,32 +5403,63 @@ class GridviewPanel extends BasePanelView {
5123
5403
  }
5124
5404
  }
5125
5405
 
5406
+ // TODO find a better way to initialize and avoid needing null checks
5407
+ const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
5126
5408
  class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
5127
- get isFloating() {
5409
+ get location() {
5128
5410
  if (!this._group) {
5129
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5411
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5130
5412
  }
5131
- return this._group.model.isFloating;
5413
+ return this._group.model.location;
5132
5414
  }
5133
5415
  constructor(id, accessor) {
5134
5416
  super(id);
5135
5417
  this.accessor = accessor;
5136
- this._onDidFloatingStateChange = new Emitter();
5137
- this.onDidFloatingStateChange = this._onDidFloatingStateChange.event;
5138
- this.addDisposables(this._onDidFloatingStateChange);
5418
+ this._onDidLocationChange = new Emitter();
5419
+ this.onDidLocationChange = this._onDidLocationChange.event;
5420
+ this.addDisposables(this._onDidLocationChange);
5139
5421
  }
5140
5422
  moveTo(options) {
5141
- var _a;
5423
+ var _a, _b, _c;
5424
+ if (!this._group) {
5425
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5426
+ }
5427
+ const group = (_a = options.group) !== null && _a !== void 0 ? _a : this.accessor.addGroup({
5428
+ direction: positionToDirection((_b = options.position) !== null && _b !== void 0 ? _b : 'right'),
5429
+ });
5430
+ this.accessor.moveGroupOrPanel(group, this._group.id, undefined, options.group ? (_c = options.position) !== null && _c !== void 0 ? _c : 'center' : 'center');
5431
+ }
5432
+ maximize() {
5433
+ if (!this._group) {
5434
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5435
+ }
5436
+ if (this.location !== 'grid') {
5437
+ // only grid groups can be maximized
5438
+ return;
5439
+ }
5440
+ this.accessor.maximizeGroup(this._group);
5441
+ }
5442
+ isMaximized() {
5142
5443
  if (!this._group) {
5143
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5444
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5445
+ }
5446
+ return this.accessor.isMaximizedGroup(this._group);
5447
+ }
5448
+ exitMaximized() {
5449
+ if (!this._group) {
5450
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5451
+ }
5452
+ if (this.isMaximized()) {
5453
+ this.accessor.exitMaximizedGroup();
5144
5454
  }
5145
- this.accessor.moveGroupOrPanel(options.group, this._group.id, undefined, (_a = options.position) !== null && _a !== void 0 ? _a : 'center');
5146
5455
  }
5147
5456
  initialize(group) {
5148
5457
  this._group = group;
5149
5458
  }
5150
5459
  }
5151
5460
 
5461
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH = 100;
5462
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT = 100;
5152
5463
  class DockviewGroupPanel extends GridviewPanel {
5153
5464
  get panels() {
5154
5465
  return this._model.panels;
@@ -5173,8 +5484,8 @@ class DockviewGroupPanel extends GridviewPanel {
5173
5484
  }
5174
5485
  constructor(accessor, id, options) {
5175
5486
  super(id, 'groupview_default', {
5176
- minimumHeight: 100,
5177
- minimumWidth: 100,
5487
+ minimumHeight: MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT,
5488
+ minimumWidth: MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH,
5178
5489
  }, new DockviewGroupPanelApiImpl(id, accessor));
5179
5490
  this.api.initialize(this); // cannot use 'this' after after 'super' call
5180
5491
  this._model = new DockviewGroupPanelModel(this.element, accessor, id, options, this);
@@ -5228,8 +5539,10 @@ class DockviewPanelApiImpl extends GridviewPanelApiImpl {
5228
5539
  return this.panel.title;
5229
5540
  }
5230
5541
  get isGroupActive() {
5231
- var _a;
5232
- return !!((_a = this.group) === null || _a === void 0 ? void 0 : _a.isActive);
5542
+ return this.group.isActive;
5543
+ }
5544
+ get renderer() {
5545
+ return this.panel.renderer;
5233
5546
  }
5234
5547
  set group(value) {
5235
5548
  const isOldGroupActive = this.isGroupActive;
@@ -5257,10 +5570,12 @@ class DockviewPanelApiImpl extends GridviewPanelApiImpl {
5257
5570
  this.onDidActiveGroupChange = this._onDidActiveGroupChange.event;
5258
5571
  this._onDidGroupChange = new Emitter();
5259
5572
  this.onDidGroupChange = this._onDidGroupChange.event;
5573
+ this._onDidRendererChange = new Emitter();
5574
+ this.onDidRendererChange = this._onDidRendererChange.event;
5260
5575
  this.disposable = new MutableDisposable();
5261
5576
  this.initialize(panel);
5262
5577
  this._group = group;
5263
- this.addDisposables(this.disposable, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5578
+ this.addDisposables(this.disposable, this._onDidRendererChange, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5264
5579
  }
5265
5580
  moveTo(options) {
5266
5581
  var _a;
@@ -5269,9 +5584,21 @@ class DockviewPanelApiImpl extends GridviewPanelApiImpl {
5269
5584
  setTitle(title) {
5270
5585
  this.panel.setTitle(title);
5271
5586
  }
5587
+ setRenderer(renderer) {
5588
+ this.panel.setRenderer(renderer);
5589
+ }
5272
5590
  close() {
5273
5591
  this.group.model.closePanel(this.panel);
5274
5592
  }
5593
+ maximize() {
5594
+ this.group.api.maximize();
5595
+ }
5596
+ isMaximized() {
5597
+ return this.group.api.isMaximized();
5598
+ }
5599
+ exitMaximized() {
5600
+ this.group.api.exitMaximized();
5601
+ }
5275
5602
  }
5276
5603
 
5277
5604
  class DockviewPanel extends CompositeDisposable {
@@ -5284,11 +5611,17 @@ class DockviewPanel extends CompositeDisposable {
5284
5611
  get group() {
5285
5612
  return this._group;
5286
5613
  }
5287
- constructor(id, accessor, containerApi, group, view) {
5614
+ get renderer() {
5615
+ var _a;
5616
+ return (_a = this._renderer) !== null && _a !== void 0 ? _a : this.accessor.renderer;
5617
+ }
5618
+ constructor(id, accessor, containerApi, group, view, options) {
5288
5619
  super();
5289
5620
  this.id = id;
5621
+ this.accessor = accessor;
5290
5622
  this.containerApi = containerApi;
5291
5623
  this.view = view;
5624
+ this._renderer = options.renderer;
5292
5625
  this._group = group;
5293
5626
  this.api = new DockviewPanelApiImpl(this, this._group, accessor);
5294
5627
  this.addDisposables(this.api.onActiveChange(() => {
@@ -5297,6 +5630,8 @@ class DockviewPanel extends CompositeDisposable {
5297
5630
  // forward the resize event to the group since if you want to resize a panel
5298
5631
  // you are actually just resizing the panels parent which is the group
5299
5632
  this.group.api.setSize(event);
5633
+ }), this.api.onDidRendererChange((event) => {
5634
+ this.group.model.rerender(this);
5300
5635
  }));
5301
5636
  }
5302
5637
  init(params) {
@@ -5316,6 +5651,7 @@ class DockviewPanel extends CompositeDisposable {
5316
5651
  ? this._params
5317
5652
  : undefined,
5318
5653
  title: this.title,
5654
+ renderer: this._renderer,
5319
5655
  };
5320
5656
  }
5321
5657
  setTitle(title) {
@@ -5331,6 +5667,15 @@ class DockviewPanel extends CompositeDisposable {
5331
5667
  this.api._onDidTitleChange.fire({ title });
5332
5668
  }
5333
5669
  }
5670
+ setRenderer(renderer) {
5671
+ const didChange = renderer !== this.renderer;
5672
+ if (didChange) {
5673
+ this._renderer = renderer;
5674
+ this.api._onDidRendererChange.fire({
5675
+ renderer: renderer,
5676
+ });
5677
+ }
5678
+ }
5334
5679
  update(event) {
5335
5680
  var _a;
5336
5681
  // merge the new parameters with the existing parameters
@@ -5549,8 +5894,8 @@ class DockviewPanelModel {
5549
5894
  }
5550
5895
 
5551
5896
  class DefaultDockviewDeserialzier {
5552
- constructor(layout) {
5553
- this.layout = layout;
5897
+ constructor(accessor) {
5898
+ this.accessor = accessor;
5554
5899
  }
5555
5900
  fromJSON(panelData, group) {
5556
5901
  var _a, _b;
@@ -5564,8 +5909,10 @@ class DefaultDockviewDeserialzier {
5564
5909
  const tabComponent = viewData
5565
5910
  ? (_b = viewData.tab) === null || _b === void 0 ? void 0 : _b.id
5566
5911
  : panelData.tabComponent;
5567
- const view = new DockviewPanelModel(this.layout, panelId, contentComponent, tabComponent);
5568
- const panel = new DockviewPanel(panelId, this.layout, new DockviewApi(this.layout), group, view);
5912
+ const view = new DockviewPanelModel(this.accessor, panelId, contentComponent, tabComponent);
5913
+ const panel = new DockviewPanel(panelId, this.accessor, new DockviewApi(this.accessor), group, view, {
5914
+ renderer: panelData.renderer,
5915
+ });
5569
5916
  panel.init({
5570
5917
  title: title !== null && title !== void 0 ? title : panelId,
5571
5918
  params: params !== null && params !== void 0 ? params : {},
@@ -5945,7 +6292,261 @@ class DockviewFloatingGroupPanel extends CompositeDisposable {
5945
6292
  }
5946
6293
  }
5947
6294
 
6295
+ class PopoutWindow extends CompositeDisposable {
6296
+ constructor(id, className, options) {
6297
+ super();
6298
+ this.id = id;
6299
+ this.className = className;
6300
+ this.options = options;
6301
+ this._onDidClose = new Emitter();
6302
+ this.onDidClose = this._onDidClose.event;
6303
+ this._window = null;
6304
+ this.addDisposables(this._onDidClose, {
6305
+ dispose: () => {
6306
+ this.close();
6307
+ },
6308
+ });
6309
+ }
6310
+ dimensions() {
6311
+ if (!this._window) {
6312
+ return null;
6313
+ }
6314
+ const left = this._window.value.screenX;
6315
+ const top = this._window.value.screenY;
6316
+ const width = this._window.value.innerWidth;
6317
+ const height = this._window.value.innerHeight;
6318
+ return { top, left, width, height };
6319
+ }
6320
+ close() {
6321
+ if (this._window) {
6322
+ this._window.disposable.dispose();
6323
+ this._window.value.close();
6324
+ this._window = null;
6325
+ }
6326
+ }
6327
+ open(content) {
6328
+ if (this._window) {
6329
+ throw new Error('instance of popout window is already open');
6330
+ }
6331
+ const url = `${this.options.url}`;
6332
+ const features = Object.entries({
6333
+ top: this.options.top,
6334
+ left: this.options.left,
6335
+ width: this.options.width,
6336
+ height: this.options.height,
6337
+ })
6338
+ .map(([key, value]) => `${key}=${value}`)
6339
+ .join(',');
6340
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/open
6341
+ const externalWindow = window.open(url, this.id, features);
6342
+ if (!externalWindow) {
6343
+ return;
6344
+ }
6345
+ const disposable = new CompositeDisposable();
6346
+ this._window = { value: externalWindow, disposable };
6347
+ const cleanUp = () => {
6348
+ this._onDidClose.fire();
6349
+ this._window = null;
6350
+ };
6351
+ // prevent any default content from loading
6352
+ // externalWindow.document.body.replaceWith(document.createElement('div'));
6353
+ disposable.addDisposables(addDisposableWindowListener(window, 'beforeunload', () => {
6354
+ cleanUp();
6355
+ this.close();
6356
+ }));
6357
+ externalWindow.addEventListener('load', () => {
6358
+ const externalDocument = externalWindow.document;
6359
+ externalDocument.title = document.title;
6360
+ const div = document.createElement('div');
6361
+ div.classList.add('dv-popout-window');
6362
+ div.style.position = 'absolute';
6363
+ div.style.width = '100%';
6364
+ div.style.height = '100%';
6365
+ div.style.top = '0px';
6366
+ div.style.left = '0px';
6367
+ div.classList.add(this.className);
6368
+ div.appendChild(content);
6369
+ externalDocument.body.replaceChildren(div);
6370
+ externalDocument.body.classList.add(this.className);
6371
+ addStyles(externalDocument, window.document.styleSheets);
6372
+ externalWindow.addEventListener('beforeunload', () => {
6373
+ // TODO: indicate external window is closing
6374
+ cleanUp();
6375
+ });
6376
+ });
6377
+ }
6378
+ }
6379
+
6380
+ class DockviewPopoutGroupPanel extends CompositeDisposable {
6381
+ constructor(id, group, options) {
6382
+ var _a;
6383
+ super();
6384
+ this.id = id;
6385
+ this.group = group;
6386
+ this.options = options;
6387
+ this.window = new PopoutWindow(id, (_a = options.className) !== null && _a !== void 0 ? _a : '', {
6388
+ url: this.options.popoutUrl,
6389
+ left: this.options.box.left,
6390
+ top: this.options.box.top,
6391
+ width: this.options.box.width,
6392
+ height: this.options.box.height,
6393
+ });
6394
+ group.model.location = 'popout';
6395
+ this.addDisposables(this.window, {
6396
+ dispose: () => {
6397
+ group.model.location = 'grid';
6398
+ },
6399
+ }, this.window.onDidClose(() => {
6400
+ this.dispose();
6401
+ }));
6402
+ this.window.open(group.element);
6403
+ }
6404
+ }
6405
+
5948
6406
  const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
6407
+ const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100 };
6408
+
6409
+ function createFocusableElement() {
6410
+ const element = document.createElement('div');
6411
+ element.tabIndex = -1;
6412
+ return element;
6413
+ }
6414
+ class OverlayRenderContainer extends CompositeDisposable {
6415
+ constructor(element) {
6416
+ super();
6417
+ this.element = element;
6418
+ this.map = {};
6419
+ this.addDisposables(Disposable.from(() => {
6420
+ for (const value of Object.values(this.map)) {
6421
+ value.disposable.dispose();
6422
+ value.destroy.dispose();
6423
+ }
6424
+ }));
6425
+ }
6426
+ detatch(panel) {
6427
+ if (this.map[panel.api.id]) {
6428
+ const { disposable, destroy } = this.map[panel.api.id];
6429
+ disposable.dispose();
6430
+ destroy.dispose();
6431
+ delete this.map[panel.api.id];
6432
+ return true;
6433
+ }
6434
+ return false;
6435
+ }
6436
+ attach(options) {
6437
+ const { panel, referenceContainer } = options;
6438
+ if (!this.map[panel.api.id]) {
6439
+ const element = createFocusableElement();
6440
+ element.className = 'dv-render-overlay';
6441
+ this.map[panel.api.id] = {
6442
+ panel,
6443
+ disposable: Disposable.NONE,
6444
+ destroy: Disposable.NONE,
6445
+ element,
6446
+ };
6447
+ }
6448
+ const focusContainer = this.map[panel.api.id].element;
6449
+ if (panel.view.content.element.parentElement !== focusContainer) {
6450
+ focusContainer.appendChild(panel.view.content.element);
6451
+ }
6452
+ if (focusContainer.parentElement !== this.element) {
6453
+ this.element.appendChild(focusContainer);
6454
+ }
6455
+ const resize = () => {
6456
+ // TODO propagate position to avoid getDomNodePagePosition calls, possible performance bottleneck?
6457
+ const box = getDomNodePagePosition(referenceContainer.element);
6458
+ const box2 = getDomNodePagePosition(this.element);
6459
+ focusContainer.style.left = `${box.left - box2.left}px`;
6460
+ focusContainer.style.top = `${box.top - box2.top}px`;
6461
+ focusContainer.style.width = `${box.width}px`;
6462
+ focusContainer.style.height = `${box.height}px`;
6463
+ toggleClass(focusContainer, 'dv-render-overlay-float', panel.group.api.location === 'floating');
6464
+ };
6465
+ const visibilityChanged = () => {
6466
+ if (panel.api.isVisible) {
6467
+ resize();
6468
+ }
6469
+ focusContainer.style.display = panel.api.isVisible ? '' : 'none';
6470
+ };
6471
+ const disposable = new CompositeDisposable(
6472
+ /**
6473
+ * since container is positioned absoutely we must explicitly forward
6474
+ * the dnd events for the expect behaviours to continue to occur in terms of dnd
6475
+ *
6476
+ * the dnd observer does not need to be conditional on whether the panel is visible since
6477
+ * non-visible panels are 'display: none' and in such case the dnd observer will not fire.
6478
+ */
6479
+ new DragAndDropObserver(focusContainer, {
6480
+ onDragEnd: (e) => {
6481
+ referenceContainer.dropTarget.dnd.onDragEnd(e);
6482
+ },
6483
+ onDragEnter: (e) => {
6484
+ referenceContainer.dropTarget.dnd.onDragEnter(e);
6485
+ },
6486
+ onDragLeave: (e) => {
6487
+ referenceContainer.dropTarget.dnd.onDragLeave(e);
6488
+ },
6489
+ onDrop: (e) => {
6490
+ referenceContainer.dropTarget.dnd.onDrop(e);
6491
+ },
6492
+ onDragOver: (e) => {
6493
+ referenceContainer.dropTarget.dnd.onDragOver(e);
6494
+ },
6495
+ }), panel.api.onDidVisibilityChange((event) => {
6496
+ /**
6497
+ * Control the visibility of the content, however even when not visible (display: none)
6498
+ * the content is still maintained within the DOM hence DOM specific attributes
6499
+ * such as scroll position are maintained when next made visible.
6500
+ */
6501
+ visibilityChanged();
6502
+ }), panel.api.onDidDimensionsChange(() => {
6503
+ if (!panel.api.isVisible) {
6504
+ return;
6505
+ }
6506
+ resize();
6507
+ }));
6508
+ this.map[panel.api.id].destroy = Disposable.from(() => {
6509
+ focusContainer.removeChild(panel.view.content.element);
6510
+ this.element.removeChild(focusContainer);
6511
+ });
6512
+ queueMicrotask(() => {
6513
+ if (this.isDisposed) {
6514
+ return;
6515
+ }
6516
+ /**
6517
+ * wait until everything has finished in the current stack-frame call before
6518
+ * calling the first resize as other size-altering events may still occur before
6519
+ * the end of the stack-frame.
6520
+ */
6521
+ visibilityChanged();
6522
+ });
6523
+ // dispose of logic asoccciated with previous reference-container
6524
+ this.map[panel.api.id].disposable.dispose();
6525
+ // and reset the disposable to the active reference-container
6526
+ this.map[panel.api.id].disposable = disposable;
6527
+ return focusContainer;
6528
+ }
6529
+ }
6530
+
6531
+ function getTheme(element) {
6532
+ function toClassList(element) {
6533
+ const list = [];
6534
+ for (let i = 0; i < element.classList.length; i++) {
6535
+ list.push(element.classList.item(i));
6536
+ }
6537
+ return list;
6538
+ }
6539
+ let theme = undefined;
6540
+ let parent = element;
6541
+ while (parent !== null) {
6542
+ theme = toClassList(parent).find((cls) => cls.startsWith('dockview-theme-'));
6543
+ if (typeof theme === 'string') {
6544
+ break;
6545
+ }
6546
+ parent = parent.parentElement;
6547
+ }
6548
+ return theme;
6549
+ }
5949
6550
  class DockviewComponent extends BaseGrid {
5950
6551
  get orientation() {
5951
6552
  return this.gridview.orientation;
@@ -5966,6 +6567,10 @@ class DockviewComponent extends BaseGrid {
5966
6567
  }
5967
6568
  return activeGroup.activePanel;
5968
6569
  }
6570
+ get renderer() {
6571
+ var _a;
6572
+ return (_a = this.options.defaultRenderer) !== null && _a !== void 0 ? _a : 'onlyWhenVisibile';
6573
+ }
5969
6574
  constructor(options) {
5970
6575
  var _a;
5971
6576
  super({
@@ -5992,12 +6597,27 @@ class DockviewComponent extends BaseGrid {
5992
6597
  this.onDidLayoutFromJSON = this._onDidLayoutFromJSON.event;
5993
6598
  this._onDidActivePanelChange = new Emitter();
5994
6599
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
5995
- this.floatingGroups = [];
6600
+ this._floatingGroups = [];
6601
+ this._popoutGroups = [];
6602
+ const gready = document.createElement('div');
6603
+ gready.className = 'dv-overlay-render-container';
6604
+ this.gridview.element.appendChild(gready);
6605
+ this.overlayRenderContainer = new OverlayRenderContainer(gready);
5996
6606
  toggleClass(this.gridview.element, 'dv-dockview', true);
5997
- this.addDisposables(this._onWillDragPanel, this._onWillDragGroup, this._onDidActivePanelChange, this._onDidAddPanel, this._onDidRemovePanel, this._onDidLayoutFromJSON, this._onDidDrop, Event.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
6607
+ toggleClass(this.element, 'dv-debug', !!options.debug);
6608
+ this.addDisposables(this.overlayRenderContainer, this._onWillDragPanel, this._onWillDragGroup, this._onDidActivePanelChange, this._onDidAddPanel, this._onDidRemovePanel, this._onDidLayoutFromJSON, this._onDidDrop, Event.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
5998
6609
  this.updateWatermark();
5999
6610
  }), Event.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidActivePanelChange)(() => {
6000
6611
  this._bufferOnDidLayoutChange.fire();
6612
+ }), Disposable.from(() => {
6613
+ // iterate over a copy of the array since .dispose() mutates the original array
6614
+ for (const group of [...this._floatingGroups]) {
6615
+ group.dispose();
6616
+ }
6617
+ // iterate over a copy of the array since .dispose() mutates the original array
6618
+ for (const group of [...this._popoutGroups]) {
6619
+ group.dispose();
6620
+ }
6001
6621
  }));
6002
6622
  this._options = options;
6003
6623
  if (!this.options.components) {
@@ -6067,6 +6687,55 @@ class DockviewComponent extends BaseGrid {
6067
6687
  this._api = new DockviewApi(this);
6068
6688
  this.updateWatermark();
6069
6689
  }
6690
+ addPopoutGroup(item, options) {
6691
+ var _a;
6692
+ let group;
6693
+ let box = options === null || options === void 0 ? void 0 : options.position;
6694
+ if (item instanceof DockviewPanel) {
6695
+ group = this.createGroup();
6696
+ this.removePanel(item, {
6697
+ removeEmptyGroup: true,
6698
+ skipDispose: true,
6699
+ });
6700
+ group.model.openPanel(item);
6701
+ if (!box) {
6702
+ box = this.element.getBoundingClientRect();
6703
+ }
6704
+ }
6705
+ else {
6706
+ group = item;
6707
+ if (!box) {
6708
+ box = group.element.getBoundingClientRect();
6709
+ }
6710
+ const skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
6711
+ options.skipRemoveGroup;
6712
+ if (!skip) {
6713
+ this.doRemoveGroup(item, { skipDispose: true });
6714
+ }
6715
+ }
6716
+ const theme = getTheme(this.gridview.element);
6717
+ const popoutWindow = new DockviewPopoutGroupPanel(`${this.id}-${group.id}`, // globally unique within dockview
6718
+ group, {
6719
+ className: theme !== null && theme !== void 0 ? theme : '',
6720
+ popoutUrl: (_a = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _a !== void 0 ? _a : '/popout.html',
6721
+ box: {
6722
+ left: window.screenX + box.left,
6723
+ top: window.screenY + box.top,
6724
+ width: box.width,
6725
+ height: box.height,
6726
+ },
6727
+ });
6728
+ popoutWindow.addDisposables({
6729
+ dispose: () => {
6730
+ remove(this._popoutGroups, popoutWindow);
6731
+ this.updateWatermark();
6732
+ },
6733
+ }, popoutWindow.window.onDidClose(() => {
6734
+ this.doAddGroup(group, [0]);
6735
+ }));
6736
+ this._popoutGroups.push(popoutWindow);
6737
+ this.updateWatermark();
6738
+ }
6070
6739
  addFloatingGroup(item, coord, options) {
6071
6740
  var _a, _b, _c, _d, _e, _f;
6072
6741
  let group;
@@ -6086,9 +6755,13 @@ class DockviewComponent extends BaseGrid {
6086
6755
  this.doRemoveGroup(item, { skipDispose: true });
6087
6756
  }
6088
6757
  }
6089
- group.model.isFloating = true;
6090
- const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number' ? Math.max(coord.x, 0) : 100;
6091
- const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number' ? Math.max(coord.y, 0) : 100;
6758
+ group.model.location = 'floating';
6759
+ const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number'
6760
+ ? Math.max(coord.x, 0)
6761
+ : DEFAULT_FLOATING_GROUP_POSITION.left;
6762
+ const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number'
6763
+ ? Math.max(coord.y, 0)
6764
+ : DEFAULT_FLOATING_GROUP_POSITION.top;
6092
6765
  const overlay = new Overlay({
6093
6766
  container: this.gridview.element,
6094
6767
  content: group.element,
@@ -6132,12 +6805,12 @@ class DockviewComponent extends BaseGrid {
6132
6805
  }), {
6133
6806
  dispose: () => {
6134
6807
  disposable.dispose();
6135
- group.model.isFloating = false;
6136
- remove(this.floatingGroups, floatingGroupPanel);
6808
+ group.model.location = 'grid';
6809
+ remove(this._floatingGroups, floatingGroupPanel);
6137
6810
  this.updateWatermark();
6138
6811
  },
6139
6812
  });
6140
- this.floatingGroups.push(floatingGroupPanel);
6813
+ this._floatingGroups.push(floatingGroupPanel);
6141
6814
  this.updateWatermark();
6142
6815
  }
6143
6816
  orthogonalize(position) {
@@ -6182,7 +6855,7 @@ class DockviewComponent extends BaseGrid {
6182
6855
  this.gridview.orientation = options.orientation;
6183
6856
  }
6184
6857
  if (hasFloatingGroupOptionsChanged) {
6185
- for (const group of this.floatingGroups) {
6858
+ for (const group of this._floatingGroups) {
6186
6859
  switch (this.options.floatingGroupBounds) {
6187
6860
  case 'boundedWithinViewport':
6188
6861
  group.overlay.minimumInViewportHeight = undefined;
@@ -6207,8 +6880,8 @@ class DockviewComponent extends BaseGrid {
6207
6880
  }
6208
6881
  layout(width, height, forceResize) {
6209
6882
  super.layout(width, height, forceResize);
6210
- if (this.floatingGroups) {
6211
- for (const floating of this.floatingGroups) {
6883
+ if (this._floatingGroups) {
6884
+ for (const floating of this._floatingGroups) {
6212
6885
  // ensure floting groups stay within visible boundaries
6213
6886
  floating.overlay.setBounds();
6214
6887
  }
@@ -6276,10 +6949,16 @@ class DockviewComponent extends BaseGrid {
6276
6949
  collection[panel.id] = panel.toJSON();
6277
6950
  return collection;
6278
6951
  }, {});
6279
- const floats = this.floatingGroups.map((floatingGroup) => {
6952
+ const floats = this._floatingGroups.map((group) => {
6953
+ return {
6954
+ data: group.group.toJSON(),
6955
+ position: group.overlay.toJSON(),
6956
+ };
6957
+ });
6958
+ const popoutGroups = this._popoutGroups.map((group) => {
6280
6959
  return {
6281
- data: floatingGroup.group.toJSON(),
6282
- position: floatingGroup.overlay.toJSON(),
6960
+ data: group.group.toJSON(),
6961
+ position: group.window.dimensions(),
6283
6962
  };
6284
6963
  });
6285
6964
  const result = {
@@ -6290,10 +6969,13 @@ class DockviewComponent extends BaseGrid {
6290
6969
  if (floats.length > 0) {
6291
6970
  result.floatingGroups = floats;
6292
6971
  }
6972
+ if (popoutGroups.length > 0) {
6973
+ result.popoutGroups = popoutGroups;
6974
+ }
6293
6975
  return result;
6294
6976
  }
6295
6977
  fromJSON(data) {
6296
- var _a;
6978
+ var _a, _b;
6297
6979
  this.clear();
6298
6980
  if (typeof data !== 'object' || data === null) {
6299
6981
  throw new Error('serialized layout must be a non-null object');
@@ -6360,7 +7042,16 @@ class DockviewComponent extends BaseGrid {
6360
7042
  width: position.width,
6361
7043
  }, { skipRemoveGroup: true, inDragMode: false });
6362
7044
  }
6363
- for (const floatingGroup of this.floatingGroups) {
7045
+ const serializedPopoutGroups = (_b = data.popoutGroups) !== null && _b !== void 0 ? _b : [];
7046
+ for (const serializedPopoutGroup of serializedPopoutGroups) {
7047
+ const { data, position } = serializedPopoutGroup;
7048
+ const group = createGroupFromSerializedState(data);
7049
+ this.addPopoutGroup(group, {
7050
+ skipRemoveGroup: true,
7051
+ position: position !== null && position !== void 0 ? position : undefined,
7052
+ });
7053
+ }
7054
+ for (const floatingGroup of this._floatingGroups) {
6364
7055
  floatingGroup.overlay.setBounds();
6365
7056
  }
6366
7057
  if (typeof activeGroup === 'string') {
@@ -6392,7 +7083,7 @@ class DockviewComponent extends BaseGrid {
6392
7083
  this._onDidRemoveGroup.fire(group);
6393
7084
  }
6394
7085
  // iterate over a reassigned array since original array will be modified
6395
- for (const floatingGroup of [...this.floatingGroups]) {
7086
+ for (const floatingGroup of [...this._floatingGroups]) {
6396
7087
  floatingGroup.dispose();
6397
7088
  }
6398
7089
  // fires clean-up events and clears the underlying HTML gridview.
@@ -6484,7 +7175,8 @@ class DockviewComponent extends BaseGrid {
6484
7175
  group.model.openPanel(panel);
6485
7176
  this.doSetGroupAndPanelActive(group);
6486
7177
  }
6487
- else if (referenceGroup.api.isFloating || target === 'center') {
7178
+ else if (referenceGroup.api.location === 'floating' ||
7179
+ target === 'center') {
6488
7180
  panel = this.createPanel(options, referenceGroup);
6489
7181
  referenceGroup.model.openPanel(panel);
6490
7182
  }
@@ -6528,6 +7220,7 @@ class DockviewComponent extends BaseGrid {
6528
7220
  }
6529
7221
  group.model.removePanel(panel);
6530
7222
  if (!options.skipDispose) {
7223
+ this.overlayRenderContainer.detatch(panel);
6531
7224
  panel.dispose();
6532
7225
  }
6533
7226
  if (group.size === 0 && options.removeEmptyGroup) {
@@ -6544,7 +7237,7 @@ class DockviewComponent extends BaseGrid {
6544
7237
  }
6545
7238
  updateWatermark() {
6546
7239
  var _a, _b;
6547
- if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
7240
+ if (this.groups.filter((x) => x.api.location === 'grid').length === 0) {
6548
7241
  if (!this.watermark) {
6549
7242
  this.watermark = this.createWatermarkComponent();
6550
7243
  this.watermark.init({
@@ -6619,19 +7312,40 @@ class DockviewComponent extends BaseGrid {
6619
7312
  }
6620
7313
  }
6621
7314
  doRemoveGroup(group, options) {
6622
- const floatingGroup = this.floatingGroups.find((_) => _.group === group);
6623
- if (floatingGroup) {
6624
- if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6625
- floatingGroup.group.dispose();
6626
- this._groups.delete(group.id);
6627
- this._onDidRemoveGroup.fire(group);
7315
+ if (group.api.location === 'floating') {
7316
+ const floatingGroup = this._floatingGroups.find((_) => _.group === group);
7317
+ if (floatingGroup) {
7318
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7319
+ floatingGroup.group.dispose();
7320
+ this._groups.delete(group.id);
7321
+ this._onDidRemoveGroup.fire(group);
7322
+ }
7323
+ remove(this._floatingGroups, floatingGroup);
7324
+ floatingGroup.dispose();
7325
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7326
+ const groups = Array.from(this._groups.values());
7327
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7328
+ }
7329
+ return floatingGroup.group;
6628
7330
  }
6629
- floatingGroup.dispose();
6630
- if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
6631
- const groups = Array.from(this._groups.values());
6632
- this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7331
+ throw new Error('failed to find floating group');
7332
+ }
7333
+ if (group.api.location === 'popout') {
7334
+ const selectedGroup = this._popoutGroups.find((_) => _.group === group);
7335
+ if (selectedGroup) {
7336
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7337
+ selectedGroup.group.dispose();
7338
+ this._groups.delete(group.id);
7339
+ this._onDidRemoveGroup.fire(group);
7340
+ }
7341
+ selectedGroup.dispose();
7342
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7343
+ const groups = Array.from(this._groups.values());
7344
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7345
+ }
7346
+ return selectedGroup.group;
6633
7347
  }
6634
- return floatingGroup.group;
7348
+ throw new Error('failed to find popout group');
6635
7349
  }
6636
7350
  return super.doRemoveGroup(group, options);
6637
7351
  }
@@ -6663,8 +7377,7 @@ class DockviewComponent extends BaseGrid {
6663
7377
  const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
6664
7378
  if (sourceGroup && sourceGroup.size < 2) {
6665
7379
  const [targetParentLocation, to] = tail(targetLocation);
6666
- const isFloating = this.floatingGroups.find((x) => x.group === sourceGroup);
6667
- if (!isFloating) {
7380
+ if (sourceGroup.api.location === 'grid') {
6668
7381
  const sourceLocation = getGridLocation(sourceGroup.element);
6669
7382
  const [sourceParentLocation, from] = tail(sourceLocation);
6670
7383
  if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
@@ -6710,12 +7423,25 @@ class DockviewComponent extends BaseGrid {
6710
7423
  }
6711
7424
  }
6712
7425
  else {
6713
- const floatingGroup = this.floatingGroups.find((x) => x.group === sourceGroup);
6714
- if (floatingGroup) {
6715
- floatingGroup.dispose();
6716
- }
6717
- else {
6718
- this.gridview.removeView(getGridLocation(sourceGroup.element));
7426
+ switch (sourceGroup.api.location) {
7427
+ case 'grid':
7428
+ this.gridview.removeView(getGridLocation(sourceGroup.element));
7429
+ break;
7430
+ case 'floating': {
7431
+ const selectedFloatingGroup = this._floatingGroups.find((x) => x.group === sourceGroup);
7432
+ if (!selectedFloatingGroup) {
7433
+ throw new Error('failed to find floating group');
7434
+ }
7435
+ selectedFloatingGroup.dispose();
7436
+ break;
7437
+ }
7438
+ case 'popout': {
7439
+ const selectedPopoutGroup = this._popoutGroups.find((x) => x.group === sourceGroup);
7440
+ if (!selectedPopoutGroup) {
7441
+ throw new Error('failed to find popout group');
7442
+ }
7443
+ selectedPopoutGroup.dispose();
7444
+ }
6719
7445
  }
6720
7446
  const referenceLocation = getGridLocation(referenceGroup.element);
6721
7447
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, target);
@@ -6777,7 +7503,7 @@ class DockviewComponent extends BaseGrid {
6777
7503
  const contentComponent = options.component;
6778
7504
  const tabComponent = (_a = options.tabComponent) !== null && _a !== void 0 ? _a : this.options.defaultTabComponent;
6779
7505
  const view = new DockviewPanelModel(this, options.id, contentComponent, tabComponent);
6780
- const panel = new DockviewPanel(options.id, this, this._api, group, view);
7506
+ const panel = new DockviewPanel(options.id, this, this._api, group, view, { renderer: options.renderer });
6781
7507
  panel.init({
6782
7508
  title: (_b = options.title) !== null && _b !== void 0 ? _b : options.id,
6783
7509
  params: (_c = options === null || options === void 0 ? void 0 : options.params) !== null && _c !== void 0 ? _c : {},
@@ -8123,6 +8849,8 @@ const DockviewReact = React.forwardRef((props, ref) => {
8123
8849
  singleTabMode: props.singleTabMode,
8124
8850
  disableFloatingGroups: props.disableFloatingGroups,
8125
8851
  floatingGroupBounds: props.floatingGroupBounds,
8852
+ defaultRenderer: props.defaultRenderer,
8853
+ debug: props.debug,
8126
8854
  });
8127
8855
  const { clientWidth, clientHeight } = domRef.current;
8128
8856
  dockview.layout(clientWidth, clientHeight);