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
  */
@@ -282,6 +282,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
282
282
  // noop
283
283
  },
284
284
  };
285
+ function from(func) {
286
+ return {
287
+ dispose: () => {
288
+ func();
289
+ },
290
+ };
291
+ }
292
+ Disposable.from = from;
285
293
  })(Disposable || (Disposable = {}));
286
294
  class CompositeDisposable {
287
295
  get isDisposed() {
@@ -466,6 +474,61 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
466
474
  function quasiDefaultPrevented(event) {
467
475
  return event[QUASI_PREVENT_DEFAULT_KEY];
468
476
  }
477
+ function addStyles(document, styleSheetList) {
478
+ const styleSheets = Array.from(styleSheetList);
479
+ for (const styleSheet of styleSheets) {
480
+ if (styleSheet.href) {
481
+ const link = document.createElement('link');
482
+ link.href = styleSheet.href;
483
+ link.type = styleSheet.type;
484
+ link.rel = 'stylesheet';
485
+ document.head.appendChild(link);
486
+ }
487
+ let cssTexts = [];
488
+ try {
489
+ if (styleSheet.cssRules) {
490
+ cssTexts = Array.from(styleSheet.cssRules).map((rule) => rule.cssText);
491
+ }
492
+ }
493
+ catch (err) {
494
+ // security errors (lack of permissions), ignore
495
+ }
496
+ for (const rule of cssTexts) {
497
+ const style = document.createElement('style');
498
+ style.appendChild(document.createTextNode(rule));
499
+ document.head.appendChild(style);
500
+ }
501
+ }
502
+ }
503
+ function getDomNodePagePosition(domNode) {
504
+ const { left, top, width, height } = domNode.getBoundingClientRect();
505
+ return {
506
+ left: left + window.scrollX,
507
+ top: top + window.scrollY,
508
+ width: width,
509
+ height: height,
510
+ };
511
+ }
512
+ /**
513
+ * Check whether an element is in the DOM (including the Shadow DOM)
514
+ * @see https://terodox.tech/how-to-tell-if-an-element-is-in-the-dom-including-the-shadow-dom/
515
+ */
516
+ function isInDocument(element) {
517
+ let currentElement = element;
518
+ while (currentElement === null || currentElement === void 0 ? void 0 : currentElement.parentNode) {
519
+ if (currentElement.parentNode === document) {
520
+ return true;
521
+ }
522
+ else if (currentElement.parentNode instanceof DocumentFragment) {
523
+ // handle shadow DOMs
524
+ currentElement = currentElement.parentNode.host;
525
+ }
526
+ else {
527
+ currentElement = currentElement.parentNode;
528
+ }
529
+ }
530
+ return false;
531
+ }
469
532
 
470
533
  function tail(arr) {
471
534
  if (arr.length === 0) {
@@ -663,6 +726,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
663
726
  Sizing.Invisible = Invisible;
664
727
  })(exports.Sizing || (exports.Sizing = {}));
665
728
  class Splitview {
729
+ get contentSize() {
730
+ return this._contentSize;
731
+ }
666
732
  get size() {
667
733
  return this._size;
668
734
  }
@@ -728,7 +794,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
728
794
  this.sashes = [];
729
795
  this._size = 0;
730
796
  this._orthogonalSize = 0;
731
- this.contentSize = 0;
797
+ this._contentSize = 0;
732
798
  this._proportions = undefined;
733
799
  this._startSnappingEnabled = true;
734
800
  this._endSnappingEnabled = true;
@@ -847,7 +913,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
847
913
  );
848
914
  });
849
915
  // Initialize content size and proportions for first layout
850
- this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
916
+ this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
851
917
  this.saveProportions();
852
918
  }
853
919
  }
@@ -1121,7 +1187,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1121
1187
  this.addView(view, sizing, to);
1122
1188
  }
1123
1189
  layout(size, orthogonalSize) {
1124
- const previousSize = Math.max(this.size, this.contentSize);
1190
+ const previousSize = Math.max(this.size, this._contentSize);
1125
1191
  this.size = size;
1126
1192
  this.orthogonalSize = orthogonalSize;
1127
1193
  if (!this.proportions) {
@@ -1131,9 +1197,23 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1131
1197
  this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);
1132
1198
  }
1133
1199
  else {
1200
+ let total = 0;
1201
+ for (let i = 0; i < this.viewItems.length; i++) {
1202
+ const item = this.viewItems[i];
1203
+ const proportion = this.proportions[i];
1204
+ if (typeof proportion === 'number') {
1205
+ total += proportion;
1206
+ }
1207
+ else {
1208
+ size -= item.size;
1209
+ }
1210
+ }
1134
1211
  for (let i = 0; i < this.viewItems.length; i++) {
1135
1212
  const item = this.viewItems[i];
1136
- item.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);
1213
+ const proportion = this.proportions[i];
1214
+ if (typeof proportion === 'number' && total > 0) {
1215
+ item.size = clamp(Math.round((proportion * size) / total), item.minimumSize, item.maximumSize);
1216
+ }
1137
1217
  }
1138
1218
  }
1139
1219
  this.distributeEmptySpace();
@@ -1170,12 +1250,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1170
1250
  }
1171
1251
  }
1172
1252
  saveProportions() {
1173
- if (this.proportionalLayout && this.contentSize > 0) {
1174
- this._proportions = this.viewItems.map((i) => i.size / this.contentSize);
1253
+ if (this.proportionalLayout && this._contentSize > 0) {
1254
+ this._proportions = this.viewItems.map((i) => i.visible ? i.size / this._contentSize : undefined);
1175
1255
  }
1176
1256
  }
1177
1257
  layoutViews() {
1178
- this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1258
+ this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1179
1259
  let sum = 0;
1180
1260
  const x = [];
1181
1261
  this.updateSashEnablement();
@@ -1269,7 +1349,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1269
1349
  }
1270
1350
  else if (snappedAfter &&
1271
1351
  collapsesDown[index] &&
1272
- (position < this.contentSize || this.endSnappingEnabled)) {
1352
+ (position < this._contentSize || this.endSnappingEnabled)) {
1273
1353
  this.updateSash(sash, exports.SashState.MAXIMUM);
1274
1354
  }
1275
1355
  else {
@@ -1558,7 +1638,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1558
1638
  setVisible(visible) {
1559
1639
  if (this.view.setVisible) {
1560
1640
  this.view.setVisible(visible);
1561
- this._onDidChange.fire({});
1562
1641
  }
1563
1642
  }
1564
1643
  layout(size, orthogonalSize) {
@@ -1590,10 +1669,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1590
1669
  get minimumSize() {
1591
1670
  return this.children.length === 0
1592
1671
  ? 0
1593
- : Math.max(...this.children.map((c) => c.minimumOrthogonalSize));
1672
+ : Math.max(...this.children.map((c, index) => this.splitview.isViewVisible(index)
1673
+ ? c.minimumOrthogonalSize
1674
+ : 0));
1594
1675
  }
1595
1676
  get maximumSize() {
1596
- return Math.min(...this.children.map((c) => c.maximumOrthogonalSize));
1677
+ return Math.min(...this.children.map((c, index) => this.splitview.isViewVisible(index)
1678
+ ? c.maximumOrthogonalSize
1679
+ : Number.POSITIVE_INFINITY));
1597
1680
  }
1598
1681
  get minimumOrthogonalSize() {
1599
1682
  return this.splitview.minimumSize;
@@ -1651,6 +1734,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1651
1734
  this.children = [];
1652
1735
  this._onDidChange = new Emitter();
1653
1736
  this.onDidChange = this._onDidChange.event;
1737
+ this._onDidVisibilityChange = new Emitter();
1738
+ this.onDidVisibilityChange = this._onDidVisibilityChange.event;
1654
1739
  this._orthogonalSize = orthogonalSize;
1655
1740
  this._size = size;
1656
1741
  this.element = document.createElement('div');
@@ -1685,7 +1770,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1685
1770
  styles,
1686
1771
  });
1687
1772
  }
1688
- this.addDisposables(this._onDidChange, this.splitview.onDidSashEnd(() => {
1773
+ this.addDisposables(this._onDidChange, this._onDidVisibilityChange, this.splitview.onDidSashEnd(() => {
1689
1774
  this._onDidChange.fire({});
1690
1775
  }));
1691
1776
  this.setupChildrenEvents();
@@ -1708,7 +1793,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1708
1793
  if (this.splitview.isViewVisible(index) === visible) {
1709
1794
  return;
1710
1795
  }
1796
+ const wereAllChildrenHidden = this.splitview.contentSize === 0;
1711
1797
  this.splitview.setViewVisible(index, visible);
1798
+ const areAllChildrenHidden = this.splitview.contentSize === 0;
1799
+ // If all children are hidden then the parent should hide the entire splitview
1800
+ // If the entire splitview is hidden then the parent should show the splitview when a child is shown
1801
+ if ((visible && wereAllChildrenHidden) ||
1802
+ (!visible && areAllChildrenHidden)) {
1803
+ this._onDidVisibilityChange.fire(visible);
1804
+ }
1712
1805
  }
1713
1806
  moveChild(from, to) {
1714
1807
  if (from === to) {
@@ -1772,13 +1865,20 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1772
1865
  }
1773
1866
  setupChildrenEvents() {
1774
1867
  this._childrenDisposable.dispose();
1775
- this._childrenDisposable = exports.DockviewEvent.any(...this.children.map((c) => c.onDidChange))((e) => {
1868
+ this._childrenDisposable = new CompositeDisposable(exports.DockviewEvent.any(...this.children.map((c) => c.onDidChange))((e) => {
1776
1869
  /**
1777
1870
  * indicate a change has occured to allows any re-rendering but don't bubble
1778
1871
  * event because that was specific to this branch
1779
1872
  */
1780
1873
  this._onDidChange.fire({ size: e.orthogonalSize });
1781
- });
1874
+ }), ...this.children.map((c, i) => {
1875
+ if (c instanceof BranchNode) {
1876
+ return c.onDidVisibilityChange((visible) => {
1877
+ this.setChildVisible(i, visible);
1878
+ });
1879
+ }
1880
+ return Disposable.NONE;
1881
+ }));
1782
1882
  }
1783
1883
  dispose() {
1784
1884
  this._childrenDisposable.dispose();
@@ -1939,7 +2039,69 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1939
2039
  get maximumHeight() {
1940
2040
  return this.root.maximumHeight;
1941
2041
  }
2042
+ maximizedView() {
2043
+ var _a;
2044
+ return (_a = this._maximizedNode) === null || _a === void 0 ? void 0 : _a.view;
2045
+ }
2046
+ hasMaximizedView() {
2047
+ return this._maximizedNode !== undefined;
2048
+ }
2049
+ maximizeView(view) {
2050
+ const location = getGridLocation(view.element);
2051
+ const [_, node] = this.getNode(location);
2052
+ if (!(node instanceof LeafNode)) {
2053
+ return;
2054
+ }
2055
+ if (this._maximizedNode === node) {
2056
+ return;
2057
+ }
2058
+ if (this.hasMaximizedView()) {
2059
+ this.exitMaximizedView();
2060
+ }
2061
+ function hideAllViewsBut(parent, exclude) {
2062
+ for (let i = 0; i < parent.children.length; i++) {
2063
+ const child = parent.children[i];
2064
+ if (child instanceof LeafNode) {
2065
+ if (child !== exclude) {
2066
+ parent.setChildVisible(i, false);
2067
+ }
2068
+ }
2069
+ else {
2070
+ hideAllViewsBut(child, exclude);
2071
+ }
2072
+ }
2073
+ }
2074
+ hideAllViewsBut(this.root, node);
2075
+ this._maximizedNode = node;
2076
+ this._onDidMaxmizedNodeChange.fire();
2077
+ }
2078
+ exitMaximizedView() {
2079
+ if (!this._maximizedNode) {
2080
+ return;
2081
+ }
2082
+ function showViewsInReverseOrder(parent) {
2083
+ for (let index = parent.children.length - 1; index >= 0; index--) {
2084
+ const child = parent.children[index];
2085
+ if (child instanceof LeafNode) {
2086
+ parent.setChildVisible(index, true);
2087
+ }
2088
+ else {
2089
+ showViewsInReverseOrder(child);
2090
+ }
2091
+ }
2092
+ }
2093
+ showViewsInReverseOrder(this.root);
2094
+ this._maximizedNode = undefined;
2095
+ this._onDidMaxmizedNodeChange.fire();
2096
+ }
1942
2097
  serialize() {
2098
+ if (this.hasMaximizedView()) {
2099
+ /**
2100
+ * do not persist maximized view state but we must first exit any maximized views
2101
+ * before serialization to ensure the correct dimensions are persisted
2102
+ */
2103
+ this.exitMaximizedView();
2104
+ }
1943
2105
  const root = serializeBranchNode(this.getView(), this.orientation);
1944
2106
  return {
1945
2107
  root,
@@ -1951,7 +2113,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1951
2113
  dispose() {
1952
2114
  this.disposable.dispose();
1953
2115
  this._onDidChange.dispose();
2116
+ this._onDidMaxmizedNodeChange.dispose();
1954
2117
  this.root.dispose();
2118
+ this._maximizedNode = undefined;
1955
2119
  this.element.remove();
1956
2120
  }
1957
2121
  clear() {
@@ -1992,6 +2156,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1992
2156
  const oldRoot = this._root;
1993
2157
  if (oldRoot) {
1994
2158
  oldRoot.dispose();
2159
+ this._maximizedNode = undefined;
1995
2160
  this.element.removeChild(oldRoot.element);
1996
2161
  }
1997
2162
  this._root = root;
@@ -2078,9 +2243,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2078
2243
  constructor(proportionalLayout, styles, orientation) {
2079
2244
  this.proportionalLayout = proportionalLayout;
2080
2245
  this.styles = styles;
2246
+ this._maximizedNode = undefined;
2081
2247
  this.disposable = new MutableDisposable();
2082
2248
  this._onDidChange = new Emitter();
2083
2249
  this.onDidChange = this._onDidChange.event;
2250
+ this._onDidMaxmizedNodeChange = new Emitter();
2251
+ this.onDidMaxmizedNodeChange = this._onDidMaxmizedNodeChange.event;
2084
2252
  this.element = document.createElement('div');
2085
2253
  this.element.className = 'grid-view';
2086
2254
  this.root = new BranchNode(orientation, proportionalLayout, styles, 0, 0);
@@ -2094,6 +2262,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2094
2262
  return parent.isChildVisible(index);
2095
2263
  }
2096
2264
  setViewVisible(location, visible) {
2265
+ if (this.hasMaximizedView()) {
2266
+ this.exitMaximizedView();
2267
+ }
2097
2268
  const [rest, index] = tail(location);
2098
2269
  const [, parent] = this.getNode(rest);
2099
2270
  if (!(parent instanceof BranchNode)) {
@@ -2102,6 +2273,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2102
2273
  parent.setChildVisible(index, visible);
2103
2274
  }
2104
2275
  moveView(parentLocation, from, to) {
2276
+ if (this.hasMaximizedView()) {
2277
+ this.exitMaximizedView();
2278
+ }
2105
2279
  const [, parent] = this.getNode(parentLocation);
2106
2280
  if (!(parent instanceof BranchNode)) {
2107
2281
  throw new Error('Invalid location');
@@ -2109,6 +2283,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2109
2283
  parent.moveChild(from, to);
2110
2284
  }
2111
2285
  addView(view, size, location) {
2286
+ if (this.hasMaximizedView()) {
2287
+ this.exitMaximizedView();
2288
+ }
2112
2289
  const [rest, index] = tail(location);
2113
2290
  const [pathToParent, parent] = this.getNode(rest);
2114
2291
  if (parent instanceof BranchNode) {
@@ -2141,6 +2318,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2141
2318
  return this.removeView(location, sizing);
2142
2319
  }
2143
2320
  removeView(location, sizing) {
2321
+ if (this.hasMaximizedView()) {
2322
+ this.exitMaximizedView();
2323
+ }
2144
2324
  const [rest, index] = tail(location);
2145
2325
  const [pathToParent, parent] = this.getNode(rest);
2146
2326
  if (!(parent instanceof BranchNode)) {
@@ -2878,6 +3058,24 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2878
3058
  moveToPrevious(options) {
2879
3059
  this.component.moveToPrevious(options);
2880
3060
  }
3061
+ maximizeGroup(panel) {
3062
+ this.component.maximizeGroup(panel.group);
3063
+ }
3064
+ hasMaximizedGroup() {
3065
+ return this.component.hasMaximizedGroup();
3066
+ }
3067
+ exitMaxmizedGroup() {
3068
+ this.component.exitMaximizedGroup();
3069
+ }
3070
+ get onDidMaxmizedGroupChange() {
3071
+ return this.component.onDidMaxmizedGroupChange;
3072
+ }
3073
+ /**
3074
+ * Add a popout group in a new Window
3075
+ */
3076
+ addPopoutGroup(item, options) {
3077
+ this.component.addPopoutGroup(item, options);
3078
+ }
2881
3079
  }
2882
3080
 
2883
3081
  class DragAndDropObserver extends CompositeDisposable {
@@ -2888,29 +3086,44 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2888
3086
  this.target = null;
2889
3087
  this.registerListeners();
2890
3088
  }
3089
+ onDragEnter(e) {
3090
+ this.target = e.target;
3091
+ this.callbacks.onDragEnter(e);
3092
+ }
3093
+ onDragOver(e) {
3094
+ e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
3095
+ if (this.callbacks.onDragOver) {
3096
+ this.callbacks.onDragOver(e);
3097
+ }
3098
+ }
3099
+ onDragLeave(e) {
3100
+ if (this.target === e.target) {
3101
+ this.target = null;
3102
+ this.callbacks.onDragLeave(e);
3103
+ }
3104
+ }
3105
+ onDragEnd(e) {
3106
+ this.target = null;
3107
+ this.callbacks.onDragEnd(e);
3108
+ }
3109
+ onDrop(e) {
3110
+ this.callbacks.onDrop(e);
3111
+ }
2891
3112
  registerListeners() {
2892
3113
  this.addDisposables(addDisposableListener(this.element, 'dragenter', (e) => {
2893
- this.target = e.target;
2894
- this.callbacks.onDragEnter(e);
3114
+ this.onDragEnter(e);
2895
3115
  }, true));
2896
3116
  this.addDisposables(addDisposableListener(this.element, 'dragover', (e) => {
2897
- e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
2898
- if (this.callbacks.onDragOver) {
2899
- this.callbacks.onDragOver(e);
2900
- }
3117
+ this.onDragOver(e);
2901
3118
  }, true));
2902
3119
  this.addDisposables(addDisposableListener(this.element, 'dragleave', (e) => {
2903
- if (this.target === e.target) {
2904
- this.target = null;
2905
- this.callbacks.onDragLeave(e);
2906
- }
3120
+ this.onDragLeave(e);
2907
3121
  }));
2908
3122
  this.addDisposables(addDisposableListener(this.element, 'dragend', (e) => {
2909
- this.target = null;
2910
- this.callbacks.onDragEnd(e);
3123
+ this.onDragEnd(e);
2911
3124
  }));
2912
3125
  this.addDisposables(addDisposableListener(this.element, 'drop', (e) => {
2913
- this.callbacks.onDrop(e);
3126
+ this.onDrop(e);
2914
3127
  }));
2915
3128
  }
2916
3129
  }
@@ -2962,7 +3175,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2962
3175
  this.onDrop = this._onDrop.event;
2963
3176
  // use a set to take advantage of #<set>.has
2964
3177
  this._acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2965
- this.addDisposables(this._onDrop, new DragAndDropObserver(this.element, {
3178
+ this.dnd = new DragAndDropObserver(this.element, {
2966
3179
  onDragEnter: () => undefined,
2967
3180
  onDragOver: (e) => {
2968
3181
  if (this._acceptedTargetZonesSet.size === 0) {
@@ -3029,7 +3242,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3029
3242
  this._onDrop.fire({ position: state, nativeEvent: e });
3030
3243
  }
3031
3244
  },
3032
- }));
3245
+ });
3246
+ this.addDisposables(this._onDrop, this.dnd);
3033
3247
  }
3034
3248
  setTargetZones(acceptedTargetZones) {
3035
3249
  this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
@@ -3185,12 +3399,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3185
3399
  return 'center';
3186
3400
  }
3187
3401
 
3402
+ exports.DockviewDropTargets = void 0;
3403
+ (function (DockviewDropTargets) {
3404
+ DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3405
+ DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3406
+ DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3407
+ DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3408
+ })(exports.DockviewDropTargets || (exports.DockviewDropTargets = {}));
3409
+
3188
3410
  class ContentContainer extends CompositeDisposable {
3189
3411
  get element() {
3190
3412
  return this._element;
3191
3413
  }
3192
- constructor() {
3414
+ constructor(accessor, group) {
3193
3415
  super();
3416
+ this.accessor = accessor;
3417
+ this.group = group;
3194
3418
  this.disposable = new MutableDisposable();
3195
3419
  this._onDidFocus = new Emitter();
3196
3420
  this.onDidFocus = this._onDidFocus.event;
@@ -3200,11 +3424,38 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3200
3424
  this._element.className = 'content-container';
3201
3425
  this._element.tabIndex = -1;
3202
3426
  this.addDisposables(this._onDidFocus, this._onDidBlur);
3203
- // for hosted containers
3204
- // 1) register a drop target on the host
3205
- // 2) register window dragStart events to disable pointer events
3206
- // 3) register dragEnd events
3207
- // 4) register mouseMove events (if no buttons are present we take this as a dragEnd event)
3427
+ this.dropTarget = new Droptarget(this.element, {
3428
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3429
+ canDisplayOverlay: (event, position) => {
3430
+ if (this.group.locked === 'no-drop-target' ||
3431
+ (this.group.locked && position === 'center')) {
3432
+ return false;
3433
+ }
3434
+ const data = getPanelData();
3435
+ if (!data &&
3436
+ event.shiftKey &&
3437
+ this.group.location !== 'floating') {
3438
+ return false;
3439
+ }
3440
+ if (data && data.viewId === this.accessor.id) {
3441
+ if (data.groupId === this.group.id) {
3442
+ if (position === 'center') {
3443
+ // don't allow to drop on self for center position
3444
+ return false;
3445
+ }
3446
+ if (data.panelId === null) {
3447
+ // don't allow group move to drop anywhere on self
3448
+ return false;
3449
+ }
3450
+ }
3451
+ const groupHasOnePanelAndIsActiveDragElement = this.group.panels.length === 1 &&
3452
+ data.groupId === this.group.id;
3453
+ return !groupHasOnePanelAndIsActiveDragElement;
3454
+ }
3455
+ return this.group.canDisplayOverlay(event, position, exports.DockviewDropTargets.Panel);
3456
+ },
3457
+ });
3458
+ this.addDisposables(this.dropTarget);
3208
3459
  }
3209
3460
  show() {
3210
3461
  this.element.style.display = '';
@@ -3212,23 +3463,43 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3212
3463
  hide() {
3213
3464
  this.element.style.display = 'none';
3214
3465
  }
3215
- openPanel(panel) {
3216
- var _a;
3217
- if (this.panel === panel) {
3218
- return;
3219
- }
3220
- if (this.panel) {
3221
- if ((_a = this.panel.view) === null || _a === void 0 ? void 0 : _a.content) {
3222
- this._element.removeChild(this.panel.view.content.element);
3223
- }
3224
- this.panel = undefined;
3466
+ renderPanel(panel, options = { asActive: true }) {
3467
+ const doRender = options.asActive ||
3468
+ (this.panel && this.group.isPanelActive(this.panel));
3469
+ if (this.panel &&
3470
+ this.panel.view.content.element.parentElement === this._element) {
3471
+ /**
3472
+ * If the currently attached panel is mounted directly to the content then remove it
3473
+ */
3474
+ this._element.removeChild(this.panel.view.content.element);
3225
3475
  }
3226
3476
  this.panel = panel;
3227
- const disposable = new CompositeDisposable();
3228
- if (this.panel.view) {
3229
- const _onDidFocus = this.panel.view.content.onDidFocus;
3230
- const _onDidBlur = this.panel.view.content.onDidBlur;
3231
- const focusTracker = trackFocus(this._element);
3477
+ let container;
3478
+ switch (panel.api.renderer) {
3479
+ case 'onlyWhenVisibile':
3480
+ this.accessor.overlayRenderContainer.detatch(panel);
3481
+ if (this.panel) {
3482
+ if (doRender) {
3483
+ this._element.appendChild(this.panel.view.content.element);
3484
+ }
3485
+ }
3486
+ container = this._element;
3487
+ break;
3488
+ case 'always':
3489
+ if (panel.view.content.element.parentElement === this._element) {
3490
+ this._element.removeChild(panel.view.content.element);
3491
+ }
3492
+ container = this.accessor.overlayRenderContainer.attach({
3493
+ panel,
3494
+ referenceContainer: this,
3495
+ });
3496
+ break;
3497
+ }
3498
+ if (doRender) {
3499
+ const _onDidFocus = panel.view.content.onDidFocus;
3500
+ const _onDidBlur = panel.view.content.onDidBlur;
3501
+ const focusTracker = trackFocus(container);
3502
+ const disposable = new CompositeDisposable();
3232
3503
  disposable.addDisposables(focusTracker, focusTracker.onDidFocus(() => this._onDidFocus.fire()), focusTracker.onDidBlur(() => this._onDidBlur.fire()));
3233
3504
  if (_onDidFocus) {
3234
3505
  disposable.addDisposables(_onDidFocus(() => this._onDidFocus.fire()));
@@ -3236,17 +3507,23 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3236
3507
  if (_onDidBlur) {
3237
3508
  disposable.addDisposables(_onDidBlur(() => this._onDidBlur.fire()));
3238
3509
  }
3239
- this._element.appendChild(this.panel.view.content.element);
3510
+ this.disposable.value = disposable;
3240
3511
  }
3241
- this.disposable.value = disposable;
3512
+ }
3513
+ openPanel(panel) {
3514
+ if (this.panel === panel) {
3515
+ return;
3516
+ }
3517
+ this.renderPanel(panel);
3242
3518
  }
3243
3519
  layout(_width, _height) {
3244
3520
  // noop
3245
3521
  }
3246
3522
  closePanel() {
3247
- var _a, _b, _c;
3248
- 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) {
3249
- this._element.removeChild(this.panel.view.content.element);
3523
+ if (this.panel) {
3524
+ if (this.accessor.options.defaultRenderer === 'onlyWhenVisibile') {
3525
+ this._element.removeChild(this.panel.view.content.element);
3526
+ }
3250
3527
  this.panel = undefined;
3251
3528
  }
3252
3529
  }
@@ -3256,14 +3533,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3256
3533
  }
3257
3534
  }
3258
3535
 
3259
- exports.DockviewDropTargets = void 0;
3260
- (function (DockviewDropTargets) {
3261
- DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3262
- DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3263
- DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3264
- DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3265
- })(exports.DockviewDropTargets || (exports.DockviewDropTargets = {}));
3266
-
3267
3536
  class DragHandler extends CompositeDisposable {
3268
3537
  constructor(el) {
3269
3538
  super();
@@ -3438,7 +3707,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3438
3707
  }, true));
3439
3708
  }
3440
3709
  isCancelled(_event) {
3441
- if (this.group.api.isFloating && !_event.shiftKey) {
3710
+ if (this.group.api.location === 'floating' && !_event.shiftKey) {
3442
3711
  return true;
3443
3712
  }
3444
3713
  return false;
@@ -3640,7 +3909,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3640
3909
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3641
3910
  if (isFloatingGroupsEnabled &&
3642
3911
  event.shiftKey &&
3643
- !this.group.api.isFloating) {
3912
+ this.group.api.location !== 'floating') {
3644
3913
  event.preventDefault();
3645
3914
  const { top, left } = this.element.getBoundingClientRect();
3646
3915
  const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
@@ -3705,7 +3974,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3705
3974
  }), tab.onChanged((event) => {
3706
3975
  var _a;
3707
3976
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3708
- const isFloatingWithOnePanel = this.group.api.isFloating && this.size === 1;
3977
+ const isFloatingWithOnePanel = this.group.api.location === 'floating' && this.size === 1;
3709
3978
  if (isFloatingGroupsEnabled &&
3710
3979
  !isFloatingWithOnePanel &&
3711
3980
  event.shiftKey) {
@@ -3788,15 +4057,37 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3788
4057
  }
3789
4058
  return isAncestor(document.activeElement, this.contentContainer.element);
3790
4059
  }
3791
- get isFloating() {
3792
- return this._isFloating;
3793
- }
3794
- set isFloating(value) {
3795
- this._isFloating = value;
3796
- this.dropTarget.setTargetZones(value ? ['center'] : ['top', 'bottom', 'left', 'right', 'center']);
3797
- toggleClass(this.container, 'dv-groupview-floating', value);
3798
- this.groupPanel.api._onDidFloatingStateChange.fire({
3799
- isFloating: this.isFloating,
4060
+ get location() {
4061
+ return this._location;
4062
+ }
4063
+ set location(value) {
4064
+ this._location = value;
4065
+ toggleClass(this.container, 'dv-groupview-floating', false);
4066
+ toggleClass(this.container, 'dv-groupview-popout', false);
4067
+ switch (value) {
4068
+ case 'grid':
4069
+ this.contentContainer.dropTarget.setTargetZones([
4070
+ 'top',
4071
+ 'bottom',
4072
+ 'left',
4073
+ 'right',
4074
+ 'center',
4075
+ ]);
4076
+ break;
4077
+ case 'floating':
4078
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4079
+ this.contentContainer.dropTarget.setTargetZones(value
4080
+ ? ['center']
4081
+ : ['top', 'bottom', 'left', 'right', 'center']);
4082
+ toggleClass(this.container, 'dv-groupview-floating', true);
4083
+ break;
4084
+ case 'popout':
4085
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4086
+ toggleClass(this.container, 'dv-groupview-popout', true);
4087
+ break;
4088
+ }
4089
+ this.groupPanel.api._onDidLocationChange.fire({
4090
+ location: this.location,
3800
4091
  });
3801
4092
  }
3802
4093
  constructor(container, accessor, id, options, groupPanel) {
@@ -3809,7 +4100,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3809
4100
  this.groupPanel = groupPanel;
3810
4101
  this._isGroupActive = false;
3811
4102
  this._locked = false;
3812
- this._isFloating = false;
4103
+ this._location = 'grid';
3813
4104
  this.mostRecentlyUsed = [];
3814
4105
  this._onDidChange = new Emitter();
3815
4106
  this.onDidChange = this._onDidChange.event;
@@ -3832,35 +4123,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3832
4123
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
3833
4124
  toggleClass(this.container, 'groupview', true);
3834
4125
  this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
3835
- this.contentContainer = new ContentContainer();
3836
- this.dropTarget = new Droptarget(this.contentContainer.element, {
3837
- acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3838
- canDisplayOverlay: (event, position) => {
3839
- if (this.locked === 'no-drop-target' ||
3840
- (this.locked && position === 'center')) {
3841
- return false;
3842
- }
3843
- const data = getPanelData();
3844
- if (!data && event.shiftKey && !this.isFloating) {
3845
- return false;
3846
- }
3847
- if (data && data.viewId === this.accessor.id) {
3848
- if (data.groupId === this.id) {
3849
- if (position === 'center') {
3850
- // don't allow to drop on self for center position
3851
- return false;
3852
- }
3853
- if (data.panelId === null) {
3854
- // don't allow group move to drop anywhere on self
3855
- return false;
3856
- }
3857
- }
3858
- const groupHasOnePanelAndIsActiveDragElement = this._panels.length === 1 && data.groupId === this.id;
3859
- return !groupHasOnePanelAndIsActiveDragElement;
3860
- }
3861
- return this.canDisplayOverlay(event, position, exports.DockviewDropTargets.Panel);
3862
- },
3863
- });
4126
+ this.contentContainer = new ContentContainer(this.accessor, this);
3864
4127
  container.append(this.tabsContainer.element, this.contentContainer.element);
3865
4128
  this.header.hidden = !!options.hideHeader;
3866
4129
  this.locked = (_a = options.locked) !== null && _a !== void 0 ? _a : false;
@@ -3874,7 +4137,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3874
4137
  this.accessor.doSetGroupActive(this.groupPanel, true);
3875
4138
  }), this.contentContainer.onDidBlur(() => {
3876
4139
  // noop
3877
- }), this.dropTarget.onDrop((event) => {
4140
+ }), this.contentContainer.dropTarget.onDrop((event) => {
3878
4141
  this.handleDropEvent(event.nativeEvent, event.position);
3879
4142
  }), this._onMove, this._onDidChange, this._onDidDrop, this._onDidAddPanel, this._onDidRemovePanel, this._onDidActivePanelChange);
3880
4143
  }
@@ -3923,6 +4186,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3923
4186
  this.tabsContainer.setPrefixActionsElement(this._prefixHeaderActions.element);
3924
4187
  }
3925
4188
  }
4189
+ rerender(panel) {
4190
+ this.contentContainer.renderPanel(panel, { asActive: false });
4191
+ }
3926
4192
  indexOf(panel) {
3927
4193
  return this.tabsContainer.indexOf(panel.id);
3928
4194
  }
@@ -4114,12 +4380,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4114
4380
  doAddPanel(panel, index = this.panels.length, skipSetActive = false) {
4115
4381
  const existingPanel = this._panels.indexOf(panel);
4116
4382
  const hasExistingPanel = existingPanel > -1;
4383
+ this.tabsContainer.show();
4384
+ this.contentContainer.show();
4117
4385
  this.tabsContainer.openPanel(panel, index);
4118
4386
  if (!skipSetActive) {
4119
4387
  this.contentContainer.openPanel(panel);
4120
4388
  }
4121
- this.tabsContainer.show();
4122
- this.contentContainer.show();
4123
4389
  if (hasExistingPanel) {
4124
4390
  // TODO - need to ensure ordering hasn't changed and if it has need to re-order this.panels
4125
4391
  return;
@@ -4235,7 +4501,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4235
4501
  for (const panel of this.panels) {
4236
4502
  panel.dispose();
4237
4503
  }
4238
- this.dropTarget.dispose();
4239
4504
  this.tabsContainer.dispose();
4240
4505
  this.contentContainer.dispose();
4241
4506
  }
@@ -4274,7 +4539,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4274
4539
  if (this.disableResizing) {
4275
4540
  return;
4276
4541
  }
4277
- if (!document.body.contains(this._element)) {
4542
+ if (!isInDocument(this._element)) {
4278
4543
  /**
4279
4544
  * since the event is dispatched through requestAnimationFrame there is a small chance
4280
4545
  * the component is no longer attached to the DOM, if that is the case the dimensions
@@ -4366,6 +4631,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4366
4631
  isVisible(panel) {
4367
4632
  return this.gridview.isViewVisible(getGridLocation(panel.element));
4368
4633
  }
4634
+ maximizeGroup(panel) {
4635
+ this.gridview.maximizeView(panel);
4636
+ }
4637
+ isMaximizedGroup(panel) {
4638
+ return this.gridview.maximizedView() === panel;
4639
+ }
4640
+ exitMaximizedGroup() {
4641
+ this.gridview.exitMaximizedView();
4642
+ }
4643
+ hasMaximizedGroup() {
4644
+ return this.gridview.hasMaximizedView();
4645
+ }
4646
+ get onDidMaxmizedGroupChange() {
4647
+ return this.gridview.onDidMaxmizedNodeChange;
4648
+ }
4369
4649
  doAddGroup(group, location = [0], size) {
4370
4650
  this.gridview.addView(group, size !== null && size !== void 0 ? size : exports.Sizing.Distribute, location);
4371
4651
  this._onDidAddGroup.fire(group);
@@ -5142,32 +5422,63 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5142
5422
  }
5143
5423
  }
5144
5424
 
5425
+ // TODO find a better way to initialize and avoid needing null checks
5426
+ const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
5145
5427
  class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
5146
- get isFloating() {
5428
+ get location() {
5147
5429
  if (!this._group) {
5148
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5430
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5149
5431
  }
5150
- return this._group.model.isFloating;
5432
+ return this._group.model.location;
5151
5433
  }
5152
5434
  constructor(id, accessor) {
5153
5435
  super(id);
5154
5436
  this.accessor = accessor;
5155
- this._onDidFloatingStateChange = new Emitter();
5156
- this.onDidFloatingStateChange = this._onDidFloatingStateChange.event;
5157
- this.addDisposables(this._onDidFloatingStateChange);
5437
+ this._onDidLocationChange = new Emitter();
5438
+ this.onDidLocationChange = this._onDidLocationChange.event;
5439
+ this.addDisposables(this._onDidLocationChange);
5158
5440
  }
5159
5441
  moveTo(options) {
5160
- var _a;
5442
+ var _a, _b, _c;
5443
+ if (!this._group) {
5444
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5445
+ }
5446
+ const group = (_a = options.group) !== null && _a !== void 0 ? _a : this.accessor.addGroup({
5447
+ direction: positionToDirection((_b = options.position) !== null && _b !== void 0 ? _b : 'right'),
5448
+ });
5449
+ this.accessor.moveGroupOrPanel(group, this._group.id, undefined, options.group ? (_c = options.position) !== null && _c !== void 0 ? _c : 'center' : 'center');
5450
+ }
5451
+ maximize() {
5452
+ if (!this._group) {
5453
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5454
+ }
5455
+ if (this.location !== 'grid') {
5456
+ // only grid groups can be maximized
5457
+ return;
5458
+ }
5459
+ this.accessor.maximizeGroup(this._group);
5460
+ }
5461
+ isMaximized() {
5161
5462
  if (!this._group) {
5162
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5463
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5464
+ }
5465
+ return this.accessor.isMaximizedGroup(this._group);
5466
+ }
5467
+ exitMaximized() {
5468
+ if (!this._group) {
5469
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5470
+ }
5471
+ if (this.isMaximized()) {
5472
+ this.accessor.exitMaximizedGroup();
5163
5473
  }
5164
- this.accessor.moveGroupOrPanel(options.group, this._group.id, undefined, (_a = options.position) !== null && _a !== void 0 ? _a : 'center');
5165
5474
  }
5166
5475
  initialize(group) {
5167
5476
  this._group = group;
5168
5477
  }
5169
5478
  }
5170
5479
 
5480
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH = 100;
5481
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT = 100;
5171
5482
  class DockviewGroupPanel extends GridviewPanel {
5172
5483
  get panels() {
5173
5484
  return this._model.panels;
@@ -5192,8 +5503,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5192
5503
  }
5193
5504
  constructor(accessor, id, options) {
5194
5505
  super(id, 'groupview_default', {
5195
- minimumHeight: 100,
5196
- minimumWidth: 100,
5506
+ minimumHeight: MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT,
5507
+ minimumWidth: MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH,
5197
5508
  }, new DockviewGroupPanelApiImpl(id, accessor));
5198
5509
  this.api.initialize(this); // cannot use 'this' after after 'super' call
5199
5510
  this._model = new DockviewGroupPanelModel(this.element, accessor, id, options, this);
@@ -5247,8 +5558,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5247
5558
  return this.panel.title;
5248
5559
  }
5249
5560
  get isGroupActive() {
5250
- var _a;
5251
- return !!((_a = this.group) === null || _a === void 0 ? void 0 : _a.isActive);
5561
+ return this.group.isActive;
5562
+ }
5563
+ get renderer() {
5564
+ return this.panel.renderer;
5252
5565
  }
5253
5566
  set group(value) {
5254
5567
  const isOldGroupActive = this.isGroupActive;
@@ -5276,10 +5589,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5276
5589
  this.onDidActiveGroupChange = this._onDidActiveGroupChange.event;
5277
5590
  this._onDidGroupChange = new Emitter();
5278
5591
  this.onDidGroupChange = this._onDidGroupChange.event;
5592
+ this._onDidRendererChange = new Emitter();
5593
+ this.onDidRendererChange = this._onDidRendererChange.event;
5279
5594
  this.disposable = new MutableDisposable();
5280
5595
  this.initialize(panel);
5281
5596
  this._group = group;
5282
- this.addDisposables(this.disposable, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5597
+ this.addDisposables(this.disposable, this._onDidRendererChange, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5283
5598
  }
5284
5599
  moveTo(options) {
5285
5600
  var _a;
@@ -5288,9 +5603,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5288
5603
  setTitle(title) {
5289
5604
  this.panel.setTitle(title);
5290
5605
  }
5606
+ setRenderer(renderer) {
5607
+ this.panel.setRenderer(renderer);
5608
+ }
5291
5609
  close() {
5292
5610
  this.group.model.closePanel(this.panel);
5293
5611
  }
5612
+ maximize() {
5613
+ this.group.api.maximize();
5614
+ }
5615
+ isMaximized() {
5616
+ return this.group.api.isMaximized();
5617
+ }
5618
+ exitMaximized() {
5619
+ this.group.api.exitMaximized();
5620
+ }
5294
5621
  }
5295
5622
 
5296
5623
  class DockviewPanel extends CompositeDisposable {
@@ -5303,11 +5630,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5303
5630
  get group() {
5304
5631
  return this._group;
5305
5632
  }
5306
- constructor(id, accessor, containerApi, group, view) {
5633
+ get renderer() {
5634
+ var _a;
5635
+ return (_a = this._renderer) !== null && _a !== void 0 ? _a : this.accessor.renderer;
5636
+ }
5637
+ constructor(id, accessor, containerApi, group, view, options) {
5307
5638
  super();
5308
5639
  this.id = id;
5640
+ this.accessor = accessor;
5309
5641
  this.containerApi = containerApi;
5310
5642
  this.view = view;
5643
+ this._renderer = options.renderer;
5311
5644
  this._group = group;
5312
5645
  this.api = new DockviewPanelApiImpl(this, this._group, accessor);
5313
5646
  this.addDisposables(this.api.onActiveChange(() => {
@@ -5316,6 +5649,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5316
5649
  // forward the resize event to the group since if you want to resize a panel
5317
5650
  // you are actually just resizing the panels parent which is the group
5318
5651
  this.group.api.setSize(event);
5652
+ }), this.api.onDidRendererChange((event) => {
5653
+ this.group.model.rerender(this);
5319
5654
  }));
5320
5655
  }
5321
5656
  init(params) {
@@ -5335,6 +5670,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5335
5670
  ? this._params
5336
5671
  : undefined,
5337
5672
  title: this.title,
5673
+ renderer: this._renderer,
5338
5674
  };
5339
5675
  }
5340
5676
  setTitle(title) {
@@ -5350,6 +5686,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5350
5686
  this.api._onDidTitleChange.fire({ title });
5351
5687
  }
5352
5688
  }
5689
+ setRenderer(renderer) {
5690
+ const didChange = renderer !== this.renderer;
5691
+ if (didChange) {
5692
+ this._renderer = renderer;
5693
+ this.api._onDidRendererChange.fire({
5694
+ renderer: renderer,
5695
+ });
5696
+ }
5697
+ }
5353
5698
  update(event) {
5354
5699
  var _a;
5355
5700
  // merge the new parameters with the existing parameters
@@ -5568,8 +5913,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5568
5913
  }
5569
5914
 
5570
5915
  class DefaultDockviewDeserialzier {
5571
- constructor(layout) {
5572
- this.layout = layout;
5916
+ constructor(accessor) {
5917
+ this.accessor = accessor;
5573
5918
  }
5574
5919
  fromJSON(panelData, group) {
5575
5920
  var _a, _b;
@@ -5583,8 +5928,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5583
5928
  const tabComponent = viewData
5584
5929
  ? (_b = viewData.tab) === null || _b === void 0 ? void 0 : _b.id
5585
5930
  : panelData.tabComponent;
5586
- const view = new DockviewPanelModel(this.layout, panelId, contentComponent, tabComponent);
5587
- const panel = new DockviewPanel(panelId, this.layout, new DockviewApi(this.layout), group, view);
5931
+ const view = new DockviewPanelModel(this.accessor, panelId, contentComponent, tabComponent);
5932
+ const panel = new DockviewPanel(panelId, this.accessor, new DockviewApi(this.accessor), group, view, {
5933
+ renderer: panelData.renderer,
5934
+ });
5588
5935
  panel.init({
5589
5936
  title: title !== null && title !== void 0 ? title : panelId,
5590
5937
  params: params !== null && params !== void 0 ? params : {},
@@ -5964,7 +6311,261 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5964
6311
  }
5965
6312
  }
5966
6313
 
6314
+ class PopoutWindow extends CompositeDisposable {
6315
+ constructor(id, className, options) {
6316
+ super();
6317
+ this.id = id;
6318
+ this.className = className;
6319
+ this.options = options;
6320
+ this._onDidClose = new Emitter();
6321
+ this.onDidClose = this._onDidClose.event;
6322
+ this._window = null;
6323
+ this.addDisposables(this._onDidClose, {
6324
+ dispose: () => {
6325
+ this.close();
6326
+ },
6327
+ });
6328
+ }
6329
+ dimensions() {
6330
+ if (!this._window) {
6331
+ return null;
6332
+ }
6333
+ const left = this._window.value.screenX;
6334
+ const top = this._window.value.screenY;
6335
+ const width = this._window.value.innerWidth;
6336
+ const height = this._window.value.innerHeight;
6337
+ return { top, left, width, height };
6338
+ }
6339
+ close() {
6340
+ if (this._window) {
6341
+ this._window.disposable.dispose();
6342
+ this._window.value.close();
6343
+ this._window = null;
6344
+ }
6345
+ }
6346
+ open(content) {
6347
+ if (this._window) {
6348
+ throw new Error('instance of popout window is already open');
6349
+ }
6350
+ const url = `${this.options.url}`;
6351
+ const features = Object.entries({
6352
+ top: this.options.top,
6353
+ left: this.options.left,
6354
+ width: this.options.width,
6355
+ height: this.options.height,
6356
+ })
6357
+ .map(([key, value]) => `${key}=${value}`)
6358
+ .join(',');
6359
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/open
6360
+ const externalWindow = window.open(url, this.id, features);
6361
+ if (!externalWindow) {
6362
+ return;
6363
+ }
6364
+ const disposable = new CompositeDisposable();
6365
+ this._window = { value: externalWindow, disposable };
6366
+ const cleanUp = () => {
6367
+ this._onDidClose.fire();
6368
+ this._window = null;
6369
+ };
6370
+ // prevent any default content from loading
6371
+ // externalWindow.document.body.replaceWith(document.createElement('div'));
6372
+ disposable.addDisposables(addDisposableWindowListener(window, 'beforeunload', () => {
6373
+ cleanUp();
6374
+ this.close();
6375
+ }));
6376
+ externalWindow.addEventListener('load', () => {
6377
+ const externalDocument = externalWindow.document;
6378
+ externalDocument.title = document.title;
6379
+ const div = document.createElement('div');
6380
+ div.classList.add('dv-popout-window');
6381
+ div.style.position = 'absolute';
6382
+ div.style.width = '100%';
6383
+ div.style.height = '100%';
6384
+ div.style.top = '0px';
6385
+ div.style.left = '0px';
6386
+ div.classList.add(this.className);
6387
+ div.appendChild(content);
6388
+ externalDocument.body.replaceChildren(div);
6389
+ externalDocument.body.classList.add(this.className);
6390
+ addStyles(externalDocument, window.document.styleSheets);
6391
+ externalWindow.addEventListener('beforeunload', () => {
6392
+ // TODO: indicate external window is closing
6393
+ cleanUp();
6394
+ });
6395
+ });
6396
+ }
6397
+ }
6398
+
6399
+ class DockviewPopoutGroupPanel extends CompositeDisposable {
6400
+ constructor(id, group, options) {
6401
+ var _a;
6402
+ super();
6403
+ this.id = id;
6404
+ this.group = group;
6405
+ this.options = options;
6406
+ this.window = new PopoutWindow(id, (_a = options.className) !== null && _a !== void 0 ? _a : '', {
6407
+ url: this.options.popoutUrl,
6408
+ left: this.options.box.left,
6409
+ top: this.options.box.top,
6410
+ width: this.options.box.width,
6411
+ height: this.options.box.height,
6412
+ });
6413
+ group.model.location = 'popout';
6414
+ this.addDisposables(this.window, {
6415
+ dispose: () => {
6416
+ group.model.location = 'grid';
6417
+ },
6418
+ }, this.window.onDidClose(() => {
6419
+ this.dispose();
6420
+ }));
6421
+ this.window.open(group.element);
6422
+ }
6423
+ }
6424
+
5967
6425
  const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
6426
+ const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100 };
6427
+
6428
+ function createFocusableElement() {
6429
+ const element = document.createElement('div');
6430
+ element.tabIndex = -1;
6431
+ return element;
6432
+ }
6433
+ class OverlayRenderContainer extends CompositeDisposable {
6434
+ constructor(element) {
6435
+ super();
6436
+ this.element = element;
6437
+ this.map = {};
6438
+ this.addDisposables(Disposable.from(() => {
6439
+ for (const value of Object.values(this.map)) {
6440
+ value.disposable.dispose();
6441
+ value.destroy.dispose();
6442
+ }
6443
+ }));
6444
+ }
6445
+ detatch(panel) {
6446
+ if (this.map[panel.api.id]) {
6447
+ const { disposable, destroy } = this.map[panel.api.id];
6448
+ disposable.dispose();
6449
+ destroy.dispose();
6450
+ delete this.map[panel.api.id];
6451
+ return true;
6452
+ }
6453
+ return false;
6454
+ }
6455
+ attach(options) {
6456
+ const { panel, referenceContainer } = options;
6457
+ if (!this.map[panel.api.id]) {
6458
+ const element = createFocusableElement();
6459
+ element.className = 'dv-render-overlay';
6460
+ this.map[panel.api.id] = {
6461
+ panel,
6462
+ disposable: Disposable.NONE,
6463
+ destroy: Disposable.NONE,
6464
+ element,
6465
+ };
6466
+ }
6467
+ const focusContainer = this.map[panel.api.id].element;
6468
+ if (panel.view.content.element.parentElement !== focusContainer) {
6469
+ focusContainer.appendChild(panel.view.content.element);
6470
+ }
6471
+ if (focusContainer.parentElement !== this.element) {
6472
+ this.element.appendChild(focusContainer);
6473
+ }
6474
+ const resize = () => {
6475
+ // TODO propagate position to avoid getDomNodePagePosition calls, possible performance bottleneck?
6476
+ const box = getDomNodePagePosition(referenceContainer.element);
6477
+ const box2 = getDomNodePagePosition(this.element);
6478
+ focusContainer.style.left = `${box.left - box2.left}px`;
6479
+ focusContainer.style.top = `${box.top - box2.top}px`;
6480
+ focusContainer.style.width = `${box.width}px`;
6481
+ focusContainer.style.height = `${box.height}px`;
6482
+ toggleClass(focusContainer, 'dv-render-overlay-float', panel.group.api.location === 'floating');
6483
+ };
6484
+ const visibilityChanged = () => {
6485
+ if (panel.api.isVisible) {
6486
+ resize();
6487
+ }
6488
+ focusContainer.style.display = panel.api.isVisible ? '' : 'none';
6489
+ };
6490
+ const disposable = new CompositeDisposable(
6491
+ /**
6492
+ * since container is positioned absoutely we must explicitly forward
6493
+ * the dnd events for the expect behaviours to continue to occur in terms of dnd
6494
+ *
6495
+ * the dnd observer does not need to be conditional on whether the panel is visible since
6496
+ * non-visible panels are 'display: none' and in such case the dnd observer will not fire.
6497
+ */
6498
+ new DragAndDropObserver(focusContainer, {
6499
+ onDragEnd: (e) => {
6500
+ referenceContainer.dropTarget.dnd.onDragEnd(e);
6501
+ },
6502
+ onDragEnter: (e) => {
6503
+ referenceContainer.dropTarget.dnd.onDragEnter(e);
6504
+ },
6505
+ onDragLeave: (e) => {
6506
+ referenceContainer.dropTarget.dnd.onDragLeave(e);
6507
+ },
6508
+ onDrop: (e) => {
6509
+ referenceContainer.dropTarget.dnd.onDrop(e);
6510
+ },
6511
+ onDragOver: (e) => {
6512
+ referenceContainer.dropTarget.dnd.onDragOver(e);
6513
+ },
6514
+ }), panel.api.onDidVisibilityChange((event) => {
6515
+ /**
6516
+ * Control the visibility of the content, however even when not visible (display: none)
6517
+ * the content is still maintained within the DOM hence DOM specific attributes
6518
+ * such as scroll position are maintained when next made visible.
6519
+ */
6520
+ visibilityChanged();
6521
+ }), panel.api.onDidDimensionsChange(() => {
6522
+ if (!panel.api.isVisible) {
6523
+ return;
6524
+ }
6525
+ resize();
6526
+ }));
6527
+ this.map[panel.api.id].destroy = Disposable.from(() => {
6528
+ focusContainer.removeChild(panel.view.content.element);
6529
+ this.element.removeChild(focusContainer);
6530
+ });
6531
+ queueMicrotask(() => {
6532
+ if (this.isDisposed) {
6533
+ return;
6534
+ }
6535
+ /**
6536
+ * wait until everything has finished in the current stack-frame call before
6537
+ * calling the first resize as other size-altering events may still occur before
6538
+ * the end of the stack-frame.
6539
+ */
6540
+ visibilityChanged();
6541
+ });
6542
+ // dispose of logic asoccciated with previous reference-container
6543
+ this.map[panel.api.id].disposable.dispose();
6544
+ // and reset the disposable to the active reference-container
6545
+ this.map[panel.api.id].disposable = disposable;
6546
+ return focusContainer;
6547
+ }
6548
+ }
6549
+
6550
+ function getTheme(element) {
6551
+ function toClassList(element) {
6552
+ const list = [];
6553
+ for (let i = 0; i < element.classList.length; i++) {
6554
+ list.push(element.classList.item(i));
6555
+ }
6556
+ return list;
6557
+ }
6558
+ let theme = undefined;
6559
+ let parent = element;
6560
+ while (parent !== null) {
6561
+ theme = toClassList(parent).find((cls) => cls.startsWith('dockview-theme-'));
6562
+ if (typeof theme === 'string') {
6563
+ break;
6564
+ }
6565
+ parent = parent.parentElement;
6566
+ }
6567
+ return theme;
6568
+ }
5968
6569
  class DockviewComponent extends BaseGrid {
5969
6570
  get orientation() {
5970
6571
  return this.gridview.orientation;
@@ -5985,6 +6586,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5985
6586
  }
5986
6587
  return activeGroup.activePanel;
5987
6588
  }
6589
+ get renderer() {
6590
+ var _a;
6591
+ return (_a = this.options.defaultRenderer) !== null && _a !== void 0 ? _a : 'onlyWhenVisibile';
6592
+ }
5988
6593
  constructor(options) {
5989
6594
  var _a;
5990
6595
  super({
@@ -6011,12 +6616,27 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6011
6616
  this.onDidLayoutFromJSON = this._onDidLayoutFromJSON.event;
6012
6617
  this._onDidActivePanelChange = new Emitter();
6013
6618
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
6014
- this.floatingGroups = [];
6619
+ this._floatingGroups = [];
6620
+ this._popoutGroups = [];
6621
+ const gready = document.createElement('div');
6622
+ gready.className = 'dv-overlay-render-container';
6623
+ this.gridview.element.appendChild(gready);
6624
+ this.overlayRenderContainer = new OverlayRenderContainer(gready);
6015
6625
  toggleClass(this.gridview.element, 'dv-dockview', true);
6016
- this.addDisposables(this._onWillDragPanel, this._onWillDragGroup, this._onDidActivePanelChange, this._onDidAddPanel, this._onDidRemovePanel, this._onDidLayoutFromJSON, this._onDidDrop, exports.DockviewEvent.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
6626
+ toggleClass(this.element, 'dv-debug', !!options.debug);
6627
+ this.addDisposables(this.overlayRenderContainer, this._onWillDragPanel, this._onWillDragGroup, this._onDidActivePanelChange, this._onDidAddPanel, this._onDidRemovePanel, this._onDidLayoutFromJSON, this._onDidDrop, exports.DockviewEvent.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
6017
6628
  this.updateWatermark();
6018
6629
  }), exports.DockviewEvent.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidActivePanelChange)(() => {
6019
6630
  this._bufferOnDidLayoutChange.fire();
6631
+ }), Disposable.from(() => {
6632
+ // iterate over a copy of the array since .dispose() mutates the original array
6633
+ for (const group of [...this._floatingGroups]) {
6634
+ group.dispose();
6635
+ }
6636
+ // iterate over a copy of the array since .dispose() mutates the original array
6637
+ for (const group of [...this._popoutGroups]) {
6638
+ group.dispose();
6639
+ }
6020
6640
  }));
6021
6641
  this._options = options;
6022
6642
  if (!this.options.components) {
@@ -6086,6 +6706,55 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6086
6706
  this._api = new DockviewApi(this);
6087
6707
  this.updateWatermark();
6088
6708
  }
6709
+ addPopoutGroup(item, options) {
6710
+ var _a;
6711
+ let group;
6712
+ let box = options === null || options === void 0 ? void 0 : options.position;
6713
+ if (item instanceof DockviewPanel) {
6714
+ group = this.createGroup();
6715
+ this.removePanel(item, {
6716
+ removeEmptyGroup: true,
6717
+ skipDispose: true,
6718
+ });
6719
+ group.model.openPanel(item);
6720
+ if (!box) {
6721
+ box = this.element.getBoundingClientRect();
6722
+ }
6723
+ }
6724
+ else {
6725
+ group = item;
6726
+ if (!box) {
6727
+ box = group.element.getBoundingClientRect();
6728
+ }
6729
+ const skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
6730
+ options.skipRemoveGroup;
6731
+ if (!skip) {
6732
+ this.doRemoveGroup(item, { skipDispose: true });
6733
+ }
6734
+ }
6735
+ const theme = getTheme(this.gridview.element);
6736
+ const popoutWindow = new DockviewPopoutGroupPanel(`${this.id}-${group.id}`, // globally unique within dockview
6737
+ group, {
6738
+ className: theme !== null && theme !== void 0 ? theme : '',
6739
+ popoutUrl: (_a = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _a !== void 0 ? _a : '/popout.html',
6740
+ box: {
6741
+ left: window.screenX + box.left,
6742
+ top: window.screenY + box.top,
6743
+ width: box.width,
6744
+ height: box.height,
6745
+ },
6746
+ });
6747
+ popoutWindow.addDisposables({
6748
+ dispose: () => {
6749
+ remove(this._popoutGroups, popoutWindow);
6750
+ this.updateWatermark();
6751
+ },
6752
+ }, popoutWindow.window.onDidClose(() => {
6753
+ this.doAddGroup(group, [0]);
6754
+ }));
6755
+ this._popoutGroups.push(popoutWindow);
6756
+ this.updateWatermark();
6757
+ }
6089
6758
  addFloatingGroup(item, coord, options) {
6090
6759
  var _a, _b, _c, _d, _e, _f;
6091
6760
  let group;
@@ -6105,9 +6774,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6105
6774
  this.doRemoveGroup(item, { skipDispose: true });
6106
6775
  }
6107
6776
  }
6108
- group.model.isFloating = true;
6109
- const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number' ? Math.max(coord.x, 0) : 100;
6110
- const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number' ? Math.max(coord.y, 0) : 100;
6777
+ group.model.location = 'floating';
6778
+ const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number'
6779
+ ? Math.max(coord.x, 0)
6780
+ : DEFAULT_FLOATING_GROUP_POSITION.left;
6781
+ const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number'
6782
+ ? Math.max(coord.y, 0)
6783
+ : DEFAULT_FLOATING_GROUP_POSITION.top;
6111
6784
  const overlay = new Overlay({
6112
6785
  container: this.gridview.element,
6113
6786
  content: group.element,
@@ -6151,12 +6824,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6151
6824
  }), {
6152
6825
  dispose: () => {
6153
6826
  disposable.dispose();
6154
- group.model.isFloating = false;
6155
- remove(this.floatingGroups, floatingGroupPanel);
6827
+ group.model.location = 'grid';
6828
+ remove(this._floatingGroups, floatingGroupPanel);
6156
6829
  this.updateWatermark();
6157
6830
  },
6158
6831
  });
6159
- this.floatingGroups.push(floatingGroupPanel);
6832
+ this._floatingGroups.push(floatingGroupPanel);
6160
6833
  this.updateWatermark();
6161
6834
  }
6162
6835
  orthogonalize(position) {
@@ -6201,7 +6874,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6201
6874
  this.gridview.orientation = options.orientation;
6202
6875
  }
6203
6876
  if (hasFloatingGroupOptionsChanged) {
6204
- for (const group of this.floatingGroups) {
6877
+ for (const group of this._floatingGroups) {
6205
6878
  switch (this.options.floatingGroupBounds) {
6206
6879
  case 'boundedWithinViewport':
6207
6880
  group.overlay.minimumInViewportHeight = undefined;
@@ -6226,8 +6899,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6226
6899
  }
6227
6900
  layout(width, height, forceResize) {
6228
6901
  super.layout(width, height, forceResize);
6229
- if (this.floatingGroups) {
6230
- for (const floating of this.floatingGroups) {
6902
+ if (this._floatingGroups) {
6903
+ for (const floating of this._floatingGroups) {
6231
6904
  // ensure floting groups stay within visible boundaries
6232
6905
  floating.overlay.setBounds();
6233
6906
  }
@@ -6295,10 +6968,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6295
6968
  collection[panel.id] = panel.toJSON();
6296
6969
  return collection;
6297
6970
  }, {});
6298
- const floats = this.floatingGroups.map((floatingGroup) => {
6971
+ const floats = this._floatingGroups.map((group) => {
6972
+ return {
6973
+ data: group.group.toJSON(),
6974
+ position: group.overlay.toJSON(),
6975
+ };
6976
+ });
6977
+ const popoutGroups = this._popoutGroups.map((group) => {
6299
6978
  return {
6300
- data: floatingGroup.group.toJSON(),
6301
- position: floatingGroup.overlay.toJSON(),
6979
+ data: group.group.toJSON(),
6980
+ position: group.window.dimensions(),
6302
6981
  };
6303
6982
  });
6304
6983
  const result = {
@@ -6309,10 +6988,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6309
6988
  if (floats.length > 0) {
6310
6989
  result.floatingGroups = floats;
6311
6990
  }
6991
+ if (popoutGroups.length > 0) {
6992
+ result.popoutGroups = popoutGroups;
6993
+ }
6312
6994
  return result;
6313
6995
  }
6314
6996
  fromJSON(data) {
6315
- var _a;
6997
+ var _a, _b;
6316
6998
  this.clear();
6317
6999
  if (typeof data !== 'object' || data === null) {
6318
7000
  throw new Error('serialized layout must be a non-null object');
@@ -6379,7 +7061,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6379
7061
  width: position.width,
6380
7062
  }, { skipRemoveGroup: true, inDragMode: false });
6381
7063
  }
6382
- for (const floatingGroup of this.floatingGroups) {
7064
+ const serializedPopoutGroups = (_b = data.popoutGroups) !== null && _b !== void 0 ? _b : [];
7065
+ for (const serializedPopoutGroup of serializedPopoutGroups) {
7066
+ const { data, position } = serializedPopoutGroup;
7067
+ const group = createGroupFromSerializedState(data);
7068
+ this.addPopoutGroup(group, {
7069
+ skipRemoveGroup: true,
7070
+ position: position !== null && position !== void 0 ? position : undefined,
7071
+ });
7072
+ }
7073
+ for (const floatingGroup of this._floatingGroups) {
6383
7074
  floatingGroup.overlay.setBounds();
6384
7075
  }
6385
7076
  if (typeof activeGroup === 'string') {
@@ -6411,7 +7102,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6411
7102
  this._onDidRemoveGroup.fire(group);
6412
7103
  }
6413
7104
  // iterate over a reassigned array since original array will be modified
6414
- for (const floatingGroup of [...this.floatingGroups]) {
7105
+ for (const floatingGroup of [...this._floatingGroups]) {
6415
7106
  floatingGroup.dispose();
6416
7107
  }
6417
7108
  // fires clean-up events and clears the underlying HTML gridview.
@@ -6503,7 +7194,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6503
7194
  group.model.openPanel(panel);
6504
7195
  this.doSetGroupAndPanelActive(group);
6505
7196
  }
6506
- else if (referenceGroup.api.isFloating || target === 'center') {
7197
+ else if (referenceGroup.api.location === 'floating' ||
7198
+ target === 'center') {
6507
7199
  panel = this.createPanel(options, referenceGroup);
6508
7200
  referenceGroup.model.openPanel(panel);
6509
7201
  }
@@ -6547,6 +7239,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6547
7239
  }
6548
7240
  group.model.removePanel(panel);
6549
7241
  if (!options.skipDispose) {
7242
+ this.overlayRenderContainer.detatch(panel);
6550
7243
  panel.dispose();
6551
7244
  }
6552
7245
  if (group.size === 0 && options.removeEmptyGroup) {
@@ -6563,7 +7256,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6563
7256
  }
6564
7257
  updateWatermark() {
6565
7258
  var _a, _b;
6566
- if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
7259
+ if (this.groups.filter((x) => x.api.location === 'grid').length === 0) {
6567
7260
  if (!this.watermark) {
6568
7261
  this.watermark = this.createWatermarkComponent();
6569
7262
  this.watermark.init({
@@ -6638,19 +7331,40 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6638
7331
  }
6639
7332
  }
6640
7333
  doRemoveGroup(group, options) {
6641
- const floatingGroup = this.floatingGroups.find((_) => _.group === group);
6642
- if (floatingGroup) {
6643
- if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6644
- floatingGroup.group.dispose();
6645
- this._groups.delete(group.id);
6646
- this._onDidRemoveGroup.fire(group);
7334
+ if (group.api.location === 'floating') {
7335
+ const floatingGroup = this._floatingGroups.find((_) => _.group === group);
7336
+ if (floatingGroup) {
7337
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7338
+ floatingGroup.group.dispose();
7339
+ this._groups.delete(group.id);
7340
+ this._onDidRemoveGroup.fire(group);
7341
+ }
7342
+ remove(this._floatingGroups, floatingGroup);
7343
+ floatingGroup.dispose();
7344
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7345
+ const groups = Array.from(this._groups.values());
7346
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7347
+ }
7348
+ return floatingGroup.group;
6647
7349
  }
6648
- floatingGroup.dispose();
6649
- if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
6650
- const groups = Array.from(this._groups.values());
6651
- this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7350
+ throw new Error('failed to find floating group');
7351
+ }
7352
+ if (group.api.location === 'popout') {
7353
+ const selectedGroup = this._popoutGroups.find((_) => _.group === group);
7354
+ if (selectedGroup) {
7355
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7356
+ selectedGroup.group.dispose();
7357
+ this._groups.delete(group.id);
7358
+ this._onDidRemoveGroup.fire(group);
7359
+ }
7360
+ selectedGroup.dispose();
7361
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7362
+ const groups = Array.from(this._groups.values());
7363
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7364
+ }
7365
+ return selectedGroup.group;
6652
7366
  }
6653
- return floatingGroup.group;
7367
+ throw new Error('failed to find popout group');
6654
7368
  }
6655
7369
  return super.doRemoveGroup(group, options);
6656
7370
  }
@@ -6682,8 +7396,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6682
7396
  const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
6683
7397
  if (sourceGroup && sourceGroup.size < 2) {
6684
7398
  const [targetParentLocation, to] = tail(targetLocation);
6685
- const isFloating = this.floatingGroups.find((x) => x.group === sourceGroup);
6686
- if (!isFloating) {
7399
+ if (sourceGroup.api.location === 'grid') {
6687
7400
  const sourceLocation = getGridLocation(sourceGroup.element);
6688
7401
  const [sourceParentLocation, from] = tail(sourceLocation);
6689
7402
  if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
@@ -6729,12 +7442,25 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6729
7442
  }
6730
7443
  }
6731
7444
  else {
6732
- const floatingGroup = this.floatingGroups.find((x) => x.group === sourceGroup);
6733
- if (floatingGroup) {
6734
- floatingGroup.dispose();
6735
- }
6736
- else {
6737
- this.gridview.removeView(getGridLocation(sourceGroup.element));
7445
+ switch (sourceGroup.api.location) {
7446
+ case 'grid':
7447
+ this.gridview.removeView(getGridLocation(sourceGroup.element));
7448
+ break;
7449
+ case 'floating': {
7450
+ const selectedFloatingGroup = this._floatingGroups.find((x) => x.group === sourceGroup);
7451
+ if (!selectedFloatingGroup) {
7452
+ throw new Error('failed to find floating group');
7453
+ }
7454
+ selectedFloatingGroup.dispose();
7455
+ break;
7456
+ }
7457
+ case 'popout': {
7458
+ const selectedPopoutGroup = this._popoutGroups.find((x) => x.group === sourceGroup);
7459
+ if (!selectedPopoutGroup) {
7460
+ throw new Error('failed to find popout group');
7461
+ }
7462
+ selectedPopoutGroup.dispose();
7463
+ }
6738
7464
  }
6739
7465
  const referenceLocation = getGridLocation(referenceGroup.element);
6740
7466
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, target);
@@ -6796,7 +7522,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6796
7522
  const contentComponent = options.component;
6797
7523
  const tabComponent = (_a = options.tabComponent) !== null && _a !== void 0 ? _a : this.options.defaultTabComponent;
6798
7524
  const view = new DockviewPanelModel(this, options.id, contentComponent, tabComponent);
6799
- const panel = new DockviewPanel(options.id, this, this._api, group, view);
7525
+ const panel = new DockviewPanel(options.id, this, this._api, group, view, { renderer: options.renderer });
6800
7526
  panel.init({
6801
7527
  title: (_b = options.title) !== null && _b !== void 0 ? _b : options.id,
6802
7528
  params: (_c = options === null || options === void 0 ? void 0 : options.params) !== null && _c !== void 0 ? _c : {},
@@ -8142,6 +8868,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
8142
8868
  singleTabMode: props.singleTabMode,
8143
8869
  disableFloatingGroups: props.disableFloatingGroups,
8144
8870
  floatingGroupBounds: props.floatingGroupBounds,
8871
+ defaultRenderer: props.defaultRenderer,
8872
+ debug: props.debug,
8145
8873
  });
8146
8874
  const { clientWidth, clientHeight } = domRef.current;
8147
8875
  dockview.layout(clientWidth, clientHeight);