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
  */
@@ -252,6 +252,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
252
252
  // noop
253
253
  },
254
254
  };
255
+ function from(func) {
256
+ return {
257
+ dispose: () => {
258
+ func();
259
+ },
260
+ };
261
+ }
262
+ Disposable.from = from;
255
263
  })(Disposable || (Disposable = {}));
256
264
  class CompositeDisposable {
257
265
  get isDisposed() {
@@ -436,6 +444,61 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
436
444
  function quasiDefaultPrevented(event) {
437
445
  return event[QUASI_PREVENT_DEFAULT_KEY];
438
446
  }
447
+ function addStyles(document, styleSheetList) {
448
+ const styleSheets = Array.from(styleSheetList);
449
+ for (const styleSheet of styleSheets) {
450
+ if (styleSheet.href) {
451
+ const link = document.createElement('link');
452
+ link.href = styleSheet.href;
453
+ link.type = styleSheet.type;
454
+ link.rel = 'stylesheet';
455
+ document.head.appendChild(link);
456
+ }
457
+ let cssTexts = [];
458
+ try {
459
+ if (styleSheet.cssRules) {
460
+ cssTexts = Array.from(styleSheet.cssRules).map((rule) => rule.cssText);
461
+ }
462
+ }
463
+ catch (err) {
464
+ // security errors (lack of permissions), ignore
465
+ }
466
+ for (const rule of cssTexts) {
467
+ const style = document.createElement('style');
468
+ style.appendChild(document.createTextNode(rule));
469
+ document.head.appendChild(style);
470
+ }
471
+ }
472
+ }
473
+ function getDomNodePagePosition(domNode) {
474
+ const { left, top, width, height } = domNode.getBoundingClientRect();
475
+ return {
476
+ left: left + window.scrollX,
477
+ top: top + window.scrollY,
478
+ width: width,
479
+ height: height,
480
+ };
481
+ }
482
+ /**
483
+ * Check whether an element is in the DOM (including the Shadow DOM)
484
+ * @see https://terodox.tech/how-to-tell-if-an-element-is-in-the-dom-including-the-shadow-dom/
485
+ */
486
+ function isInDocument(element) {
487
+ let currentElement = element;
488
+ while (currentElement === null || currentElement === void 0 ? void 0 : currentElement.parentNode) {
489
+ if (currentElement.parentNode === document) {
490
+ return true;
491
+ }
492
+ else if (currentElement.parentNode instanceof DocumentFragment) {
493
+ // handle shadow DOMs
494
+ currentElement = currentElement.parentNode.host;
495
+ }
496
+ else {
497
+ currentElement = currentElement.parentNode;
498
+ }
499
+ }
500
+ return false;
501
+ }
439
502
 
440
503
  function tail(arr) {
441
504
  if (arr.length === 0) {
@@ -633,6 +696,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
633
696
  Sizing.Invisible = Invisible;
634
697
  })(exports.Sizing || (exports.Sizing = {}));
635
698
  class Splitview {
699
+ get contentSize() {
700
+ return this._contentSize;
701
+ }
636
702
  get size() {
637
703
  return this._size;
638
704
  }
@@ -698,7 +764,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
698
764
  this.sashes = [];
699
765
  this._size = 0;
700
766
  this._orthogonalSize = 0;
701
- this.contentSize = 0;
767
+ this._contentSize = 0;
702
768
  this._proportions = undefined;
703
769
  this._startSnappingEnabled = true;
704
770
  this._endSnappingEnabled = true;
@@ -817,7 +883,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
817
883
  );
818
884
  });
819
885
  // Initialize content size and proportions for first layout
820
- this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
886
+ this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
821
887
  this.saveProportions();
822
888
  }
823
889
  }
@@ -1091,7 +1157,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1091
1157
  this.addView(view, sizing, to);
1092
1158
  }
1093
1159
  layout(size, orthogonalSize) {
1094
- const previousSize = Math.max(this.size, this.contentSize);
1160
+ const previousSize = Math.max(this.size, this._contentSize);
1095
1161
  this.size = size;
1096
1162
  this.orthogonalSize = orthogonalSize;
1097
1163
  if (!this.proportions) {
@@ -1101,9 +1167,23 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1101
1167
  this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);
1102
1168
  }
1103
1169
  else {
1170
+ let total = 0;
1171
+ for (let i = 0; i < this.viewItems.length; i++) {
1172
+ const item = this.viewItems[i];
1173
+ const proportion = this.proportions[i];
1174
+ if (typeof proportion === 'number') {
1175
+ total += proportion;
1176
+ }
1177
+ else {
1178
+ size -= item.size;
1179
+ }
1180
+ }
1104
1181
  for (let i = 0; i < this.viewItems.length; i++) {
1105
1182
  const item = this.viewItems[i];
1106
- item.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);
1183
+ const proportion = this.proportions[i];
1184
+ if (typeof proportion === 'number' && total > 0) {
1185
+ item.size = clamp(Math.round((proportion * size) / total), item.minimumSize, item.maximumSize);
1186
+ }
1107
1187
  }
1108
1188
  }
1109
1189
  this.distributeEmptySpace();
@@ -1140,12 +1220,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1140
1220
  }
1141
1221
  }
1142
1222
  saveProportions() {
1143
- if (this.proportionalLayout && this.contentSize > 0) {
1144
- this._proportions = this.viewItems.map((i) => i.size / this.contentSize);
1223
+ if (this.proportionalLayout && this._contentSize > 0) {
1224
+ this._proportions = this.viewItems.map((i) => i.visible ? i.size / this._contentSize : undefined);
1145
1225
  }
1146
1226
  }
1147
1227
  layoutViews() {
1148
- this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1228
+ this._contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
1149
1229
  let sum = 0;
1150
1230
  const x = [];
1151
1231
  this.updateSashEnablement();
@@ -1239,7 +1319,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1239
1319
  }
1240
1320
  else if (snappedAfter &&
1241
1321
  collapsesDown[index] &&
1242
- (position < this.contentSize || this.endSnappingEnabled)) {
1322
+ (position < this._contentSize || this.endSnappingEnabled)) {
1243
1323
  this.updateSash(sash, exports.SashState.MAXIMUM);
1244
1324
  }
1245
1325
  else {
@@ -1528,7 +1608,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1528
1608
  setVisible(visible) {
1529
1609
  if (this.view.setVisible) {
1530
1610
  this.view.setVisible(visible);
1531
- this._onDidChange.fire({});
1532
1611
  }
1533
1612
  }
1534
1613
  layout(size, orthogonalSize) {
@@ -1560,10 +1639,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1560
1639
  get minimumSize() {
1561
1640
  return this.children.length === 0
1562
1641
  ? 0
1563
- : Math.max(...this.children.map((c) => c.minimumOrthogonalSize));
1642
+ : Math.max(...this.children.map((c, index) => this.splitview.isViewVisible(index)
1643
+ ? c.minimumOrthogonalSize
1644
+ : 0));
1564
1645
  }
1565
1646
  get maximumSize() {
1566
- return Math.min(...this.children.map((c) => c.maximumOrthogonalSize));
1647
+ return Math.min(...this.children.map((c, index) => this.splitview.isViewVisible(index)
1648
+ ? c.maximumOrthogonalSize
1649
+ : Number.POSITIVE_INFINITY));
1567
1650
  }
1568
1651
  get minimumOrthogonalSize() {
1569
1652
  return this.splitview.minimumSize;
@@ -1621,6 +1704,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1621
1704
  this.children = [];
1622
1705
  this._onDidChange = new Emitter();
1623
1706
  this.onDidChange = this._onDidChange.event;
1707
+ this._onDidVisibilityChange = new Emitter();
1708
+ this.onDidVisibilityChange = this._onDidVisibilityChange.event;
1624
1709
  this._orthogonalSize = orthogonalSize;
1625
1710
  this._size = size;
1626
1711
  this.element = document.createElement('div');
@@ -1655,7 +1740,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1655
1740
  styles,
1656
1741
  });
1657
1742
  }
1658
- this.addDisposables(this._onDidChange, this.splitview.onDidSashEnd(() => {
1743
+ this.addDisposables(this._onDidChange, this._onDidVisibilityChange, this.splitview.onDidSashEnd(() => {
1659
1744
  this._onDidChange.fire({});
1660
1745
  }));
1661
1746
  this.setupChildrenEvents();
@@ -1678,7 +1763,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1678
1763
  if (this.splitview.isViewVisible(index) === visible) {
1679
1764
  return;
1680
1765
  }
1766
+ const wereAllChildrenHidden = this.splitview.contentSize === 0;
1681
1767
  this.splitview.setViewVisible(index, visible);
1768
+ const areAllChildrenHidden = this.splitview.contentSize === 0;
1769
+ // If all children are hidden then the parent should hide the entire splitview
1770
+ // If the entire splitview is hidden then the parent should show the splitview when a child is shown
1771
+ if ((visible && wereAllChildrenHidden) ||
1772
+ (!visible && areAllChildrenHidden)) {
1773
+ this._onDidVisibilityChange.fire(visible);
1774
+ }
1682
1775
  }
1683
1776
  moveChild(from, to) {
1684
1777
  if (from === to) {
@@ -1742,13 +1835,20 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1742
1835
  }
1743
1836
  setupChildrenEvents() {
1744
1837
  this._childrenDisposable.dispose();
1745
- this._childrenDisposable = exports.DockviewEvent.any(...this.children.map((c) => c.onDidChange))((e) => {
1838
+ this._childrenDisposable = new CompositeDisposable(exports.DockviewEvent.any(...this.children.map((c) => c.onDidChange))((e) => {
1746
1839
  /**
1747
1840
  * indicate a change has occured to allows any re-rendering but don't bubble
1748
1841
  * event because that was specific to this branch
1749
1842
  */
1750
1843
  this._onDidChange.fire({ size: e.orthogonalSize });
1751
- });
1844
+ }), ...this.children.map((c, i) => {
1845
+ if (c instanceof BranchNode) {
1846
+ return c.onDidVisibilityChange((visible) => {
1847
+ this.setChildVisible(i, visible);
1848
+ });
1849
+ }
1850
+ return Disposable.NONE;
1851
+ }));
1752
1852
  }
1753
1853
  dispose() {
1754
1854
  this._childrenDisposable.dispose();
@@ -1909,7 +2009,69 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1909
2009
  get maximumHeight() {
1910
2010
  return this.root.maximumHeight;
1911
2011
  }
2012
+ maximizedView() {
2013
+ var _a;
2014
+ return (_a = this._maximizedNode) === null || _a === void 0 ? void 0 : _a.view;
2015
+ }
2016
+ hasMaximizedView() {
2017
+ return this._maximizedNode !== undefined;
2018
+ }
2019
+ maximizeView(view) {
2020
+ const location = getGridLocation(view.element);
2021
+ const [_, node] = this.getNode(location);
2022
+ if (!(node instanceof LeafNode)) {
2023
+ return;
2024
+ }
2025
+ if (this._maximizedNode === node) {
2026
+ return;
2027
+ }
2028
+ if (this.hasMaximizedView()) {
2029
+ this.exitMaximizedView();
2030
+ }
2031
+ function hideAllViewsBut(parent, exclude) {
2032
+ for (let i = 0; i < parent.children.length; i++) {
2033
+ const child = parent.children[i];
2034
+ if (child instanceof LeafNode) {
2035
+ if (child !== exclude) {
2036
+ parent.setChildVisible(i, false);
2037
+ }
2038
+ }
2039
+ else {
2040
+ hideAllViewsBut(child, exclude);
2041
+ }
2042
+ }
2043
+ }
2044
+ hideAllViewsBut(this.root, node);
2045
+ this._maximizedNode = node;
2046
+ this._onDidMaxmizedNodeChange.fire();
2047
+ }
2048
+ exitMaximizedView() {
2049
+ if (!this._maximizedNode) {
2050
+ return;
2051
+ }
2052
+ function showViewsInReverseOrder(parent) {
2053
+ for (let index = parent.children.length - 1; index >= 0; index--) {
2054
+ const child = parent.children[index];
2055
+ if (child instanceof LeafNode) {
2056
+ parent.setChildVisible(index, true);
2057
+ }
2058
+ else {
2059
+ showViewsInReverseOrder(child);
2060
+ }
2061
+ }
2062
+ }
2063
+ showViewsInReverseOrder(this.root);
2064
+ this._maximizedNode = undefined;
2065
+ this._onDidMaxmizedNodeChange.fire();
2066
+ }
1912
2067
  serialize() {
2068
+ if (this.hasMaximizedView()) {
2069
+ /**
2070
+ * do not persist maximized view state but we must first exit any maximized views
2071
+ * before serialization to ensure the correct dimensions are persisted
2072
+ */
2073
+ this.exitMaximizedView();
2074
+ }
1913
2075
  const root = serializeBranchNode(this.getView(), this.orientation);
1914
2076
  return {
1915
2077
  root,
@@ -1921,7 +2083,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1921
2083
  dispose() {
1922
2084
  this.disposable.dispose();
1923
2085
  this._onDidChange.dispose();
2086
+ this._onDidMaxmizedNodeChange.dispose();
1924
2087
  this.root.dispose();
2088
+ this._maximizedNode = undefined;
1925
2089
  this.element.remove();
1926
2090
  }
1927
2091
  clear() {
@@ -1962,6 +2126,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1962
2126
  const oldRoot = this._root;
1963
2127
  if (oldRoot) {
1964
2128
  oldRoot.dispose();
2129
+ this._maximizedNode = undefined;
1965
2130
  this.element.removeChild(oldRoot.element);
1966
2131
  }
1967
2132
  this._root = root;
@@ -2048,9 +2213,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2048
2213
  constructor(proportionalLayout, styles, orientation) {
2049
2214
  this.proportionalLayout = proportionalLayout;
2050
2215
  this.styles = styles;
2216
+ this._maximizedNode = undefined;
2051
2217
  this.disposable = new MutableDisposable();
2052
2218
  this._onDidChange = new Emitter();
2053
2219
  this.onDidChange = this._onDidChange.event;
2220
+ this._onDidMaxmizedNodeChange = new Emitter();
2221
+ this.onDidMaxmizedNodeChange = this._onDidMaxmizedNodeChange.event;
2054
2222
  this.element = document.createElement('div');
2055
2223
  this.element.className = 'grid-view';
2056
2224
  this.root = new BranchNode(orientation, proportionalLayout, styles, 0, 0);
@@ -2064,6 +2232,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2064
2232
  return parent.isChildVisible(index);
2065
2233
  }
2066
2234
  setViewVisible(location, visible) {
2235
+ if (this.hasMaximizedView()) {
2236
+ this.exitMaximizedView();
2237
+ }
2067
2238
  const [rest, index] = tail(location);
2068
2239
  const [, parent] = this.getNode(rest);
2069
2240
  if (!(parent instanceof BranchNode)) {
@@ -2072,6 +2243,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2072
2243
  parent.setChildVisible(index, visible);
2073
2244
  }
2074
2245
  moveView(parentLocation, from, to) {
2246
+ if (this.hasMaximizedView()) {
2247
+ this.exitMaximizedView();
2248
+ }
2075
2249
  const [, parent] = this.getNode(parentLocation);
2076
2250
  if (!(parent instanceof BranchNode)) {
2077
2251
  throw new Error('Invalid location');
@@ -2079,6 +2253,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2079
2253
  parent.moveChild(from, to);
2080
2254
  }
2081
2255
  addView(view, size, location) {
2256
+ if (this.hasMaximizedView()) {
2257
+ this.exitMaximizedView();
2258
+ }
2082
2259
  const [rest, index] = tail(location);
2083
2260
  const [pathToParent, parent] = this.getNode(rest);
2084
2261
  if (parent instanceof BranchNode) {
@@ -2111,6 +2288,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2111
2288
  return this.removeView(location, sizing);
2112
2289
  }
2113
2290
  removeView(location, sizing) {
2291
+ if (this.hasMaximizedView()) {
2292
+ this.exitMaximizedView();
2293
+ }
2114
2294
  const [rest, index] = tail(location);
2115
2295
  const [pathToParent, parent] = this.getNode(rest);
2116
2296
  if (!(parent instanceof BranchNode)) {
@@ -2848,6 +3028,24 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2848
3028
  moveToPrevious(options) {
2849
3029
  this.component.moveToPrevious(options);
2850
3030
  }
3031
+ maximizeGroup(panel) {
3032
+ this.component.maximizeGroup(panel.group);
3033
+ }
3034
+ hasMaximizedGroup() {
3035
+ return this.component.hasMaximizedGroup();
3036
+ }
3037
+ exitMaxmizedGroup() {
3038
+ this.component.exitMaximizedGroup();
3039
+ }
3040
+ get onDidMaxmizedGroupChange() {
3041
+ return this.component.onDidMaxmizedGroupChange;
3042
+ }
3043
+ /**
3044
+ * Add a popout group in a new Window
3045
+ */
3046
+ addPopoutGroup(item, options) {
3047
+ this.component.addPopoutGroup(item, options);
3048
+ }
2851
3049
  }
2852
3050
 
2853
3051
  class DragAndDropObserver extends CompositeDisposable {
@@ -2858,29 +3056,44 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2858
3056
  this.target = null;
2859
3057
  this.registerListeners();
2860
3058
  }
3059
+ onDragEnter(e) {
3060
+ this.target = e.target;
3061
+ this.callbacks.onDragEnter(e);
3062
+ }
3063
+ onDragOver(e) {
3064
+ e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
3065
+ if (this.callbacks.onDragOver) {
3066
+ this.callbacks.onDragOver(e);
3067
+ }
3068
+ }
3069
+ onDragLeave(e) {
3070
+ if (this.target === e.target) {
3071
+ this.target = null;
3072
+ this.callbacks.onDragLeave(e);
3073
+ }
3074
+ }
3075
+ onDragEnd(e) {
3076
+ this.target = null;
3077
+ this.callbacks.onDragEnd(e);
3078
+ }
3079
+ onDrop(e) {
3080
+ this.callbacks.onDrop(e);
3081
+ }
2861
3082
  registerListeners() {
2862
3083
  this.addDisposables(addDisposableListener(this.element, 'dragenter', (e) => {
2863
- this.target = e.target;
2864
- this.callbacks.onDragEnter(e);
3084
+ this.onDragEnter(e);
2865
3085
  }, true));
2866
3086
  this.addDisposables(addDisposableListener(this.element, 'dragover', (e) => {
2867
- e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
2868
- if (this.callbacks.onDragOver) {
2869
- this.callbacks.onDragOver(e);
2870
- }
3087
+ this.onDragOver(e);
2871
3088
  }, true));
2872
3089
  this.addDisposables(addDisposableListener(this.element, 'dragleave', (e) => {
2873
- if (this.target === e.target) {
2874
- this.target = null;
2875
- this.callbacks.onDragLeave(e);
2876
- }
3090
+ this.onDragLeave(e);
2877
3091
  }));
2878
3092
  this.addDisposables(addDisposableListener(this.element, 'dragend', (e) => {
2879
- this.target = null;
2880
- this.callbacks.onDragEnd(e);
3093
+ this.onDragEnd(e);
2881
3094
  }));
2882
3095
  this.addDisposables(addDisposableListener(this.element, 'drop', (e) => {
2883
- this.callbacks.onDrop(e);
3096
+ this.onDrop(e);
2884
3097
  }));
2885
3098
  }
2886
3099
  }
@@ -2932,7 +3145,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2932
3145
  this.onDrop = this._onDrop.event;
2933
3146
  // use a set to take advantage of #<set>.has
2934
3147
  this._acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2935
- this.addDisposables(this._onDrop, new DragAndDropObserver(this.element, {
3148
+ this.dnd = new DragAndDropObserver(this.element, {
2936
3149
  onDragEnter: () => undefined,
2937
3150
  onDragOver: (e) => {
2938
3151
  if (this._acceptedTargetZonesSet.size === 0) {
@@ -2999,7 +3212,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2999
3212
  this._onDrop.fire({ position: state, nativeEvent: e });
3000
3213
  }
3001
3214
  },
3002
- }));
3215
+ });
3216
+ this.addDisposables(this._onDrop, this.dnd);
3003
3217
  }
3004
3218
  setTargetZones(acceptedTargetZones) {
3005
3219
  this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
@@ -3155,12 +3369,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3155
3369
  return 'center';
3156
3370
  }
3157
3371
 
3372
+ exports.DockviewDropTargets = void 0;
3373
+ (function (DockviewDropTargets) {
3374
+ DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3375
+ DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3376
+ DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3377
+ DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3378
+ })(exports.DockviewDropTargets || (exports.DockviewDropTargets = {}));
3379
+
3158
3380
  class ContentContainer extends CompositeDisposable {
3159
3381
  get element() {
3160
3382
  return this._element;
3161
3383
  }
3162
- constructor() {
3384
+ constructor(accessor, group) {
3163
3385
  super();
3386
+ this.accessor = accessor;
3387
+ this.group = group;
3164
3388
  this.disposable = new MutableDisposable();
3165
3389
  this._onDidFocus = new Emitter();
3166
3390
  this.onDidFocus = this._onDidFocus.event;
@@ -3170,11 +3394,38 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3170
3394
  this._element.className = 'content-container';
3171
3395
  this._element.tabIndex = -1;
3172
3396
  this.addDisposables(this._onDidFocus, this._onDidBlur);
3173
- // for hosted containers
3174
- // 1) register a drop target on the host
3175
- // 2) register window dragStart events to disable pointer events
3176
- // 3) register dragEnd events
3177
- // 4) register mouseMove events (if no buttons are present we take this as a dragEnd event)
3397
+ this.dropTarget = new Droptarget(this.element, {
3398
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3399
+ canDisplayOverlay: (event, position) => {
3400
+ if (this.group.locked === 'no-drop-target' ||
3401
+ (this.group.locked && position === 'center')) {
3402
+ return false;
3403
+ }
3404
+ const data = getPanelData();
3405
+ if (!data &&
3406
+ event.shiftKey &&
3407
+ this.group.location !== 'floating') {
3408
+ return false;
3409
+ }
3410
+ if (data && data.viewId === this.accessor.id) {
3411
+ if (data.groupId === this.group.id) {
3412
+ if (position === 'center') {
3413
+ // don't allow to drop on self for center position
3414
+ return false;
3415
+ }
3416
+ if (data.panelId === null) {
3417
+ // don't allow group move to drop anywhere on self
3418
+ return false;
3419
+ }
3420
+ }
3421
+ const groupHasOnePanelAndIsActiveDragElement = this.group.panels.length === 1 &&
3422
+ data.groupId === this.group.id;
3423
+ return !groupHasOnePanelAndIsActiveDragElement;
3424
+ }
3425
+ return this.group.canDisplayOverlay(event, position, exports.DockviewDropTargets.Panel);
3426
+ },
3427
+ });
3428
+ this.addDisposables(this.dropTarget);
3178
3429
  }
3179
3430
  show() {
3180
3431
  this.element.style.display = '';
@@ -3182,23 +3433,43 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3182
3433
  hide() {
3183
3434
  this.element.style.display = 'none';
3184
3435
  }
3185
- openPanel(panel) {
3186
- var _a;
3187
- if (this.panel === panel) {
3188
- return;
3189
- }
3190
- if (this.panel) {
3191
- if ((_a = this.panel.view) === null || _a === void 0 ? void 0 : _a.content) {
3192
- this._element.removeChild(this.panel.view.content.element);
3193
- }
3194
- this.panel = undefined;
3436
+ renderPanel(panel, options = { asActive: true }) {
3437
+ const doRender = options.asActive ||
3438
+ (this.panel && this.group.isPanelActive(this.panel));
3439
+ if (this.panel &&
3440
+ this.panel.view.content.element.parentElement === this._element) {
3441
+ /**
3442
+ * If the currently attached panel is mounted directly to the content then remove it
3443
+ */
3444
+ this._element.removeChild(this.panel.view.content.element);
3195
3445
  }
3196
3446
  this.panel = panel;
3197
- const disposable = new CompositeDisposable();
3198
- if (this.panel.view) {
3199
- const _onDidFocus = this.panel.view.content.onDidFocus;
3200
- const _onDidBlur = this.panel.view.content.onDidBlur;
3201
- const focusTracker = trackFocus(this._element);
3447
+ let container;
3448
+ switch (panel.api.renderer) {
3449
+ case 'onlyWhenVisibile':
3450
+ this.accessor.overlayRenderContainer.detatch(panel);
3451
+ if (this.panel) {
3452
+ if (doRender) {
3453
+ this._element.appendChild(this.panel.view.content.element);
3454
+ }
3455
+ }
3456
+ container = this._element;
3457
+ break;
3458
+ case 'always':
3459
+ if (panel.view.content.element.parentElement === this._element) {
3460
+ this._element.removeChild(panel.view.content.element);
3461
+ }
3462
+ container = this.accessor.overlayRenderContainer.attach({
3463
+ panel,
3464
+ referenceContainer: this,
3465
+ });
3466
+ break;
3467
+ }
3468
+ if (doRender) {
3469
+ const _onDidFocus = panel.view.content.onDidFocus;
3470
+ const _onDidBlur = panel.view.content.onDidBlur;
3471
+ const focusTracker = trackFocus(container);
3472
+ const disposable = new CompositeDisposable();
3202
3473
  disposable.addDisposables(focusTracker, focusTracker.onDidFocus(() => this._onDidFocus.fire()), focusTracker.onDidBlur(() => this._onDidBlur.fire()));
3203
3474
  if (_onDidFocus) {
3204
3475
  disposable.addDisposables(_onDidFocus(() => this._onDidFocus.fire()));
@@ -3206,17 +3477,23 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3206
3477
  if (_onDidBlur) {
3207
3478
  disposable.addDisposables(_onDidBlur(() => this._onDidBlur.fire()));
3208
3479
  }
3209
- this._element.appendChild(this.panel.view.content.element);
3480
+ this.disposable.value = disposable;
3210
3481
  }
3211
- this.disposable.value = disposable;
3482
+ }
3483
+ openPanel(panel) {
3484
+ if (this.panel === panel) {
3485
+ return;
3486
+ }
3487
+ this.renderPanel(panel);
3212
3488
  }
3213
3489
  layout(_width, _height) {
3214
3490
  // noop
3215
3491
  }
3216
3492
  closePanel() {
3217
- var _a, _b, _c;
3218
- 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) {
3219
- this._element.removeChild(this.panel.view.content.element);
3493
+ if (this.panel) {
3494
+ if (this.accessor.options.defaultRenderer === 'onlyWhenVisibile') {
3495
+ this._element.removeChild(this.panel.view.content.element);
3496
+ }
3220
3497
  this.panel = undefined;
3221
3498
  }
3222
3499
  }
@@ -3226,14 +3503,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3226
3503
  }
3227
3504
  }
3228
3505
 
3229
- exports.DockviewDropTargets = void 0;
3230
- (function (DockviewDropTargets) {
3231
- DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3232
- DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3233
- DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3234
- DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3235
- })(exports.DockviewDropTargets || (exports.DockviewDropTargets = {}));
3236
-
3237
3506
  class DragHandler extends CompositeDisposable {
3238
3507
  constructor(el) {
3239
3508
  super();
@@ -3408,7 +3677,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3408
3677
  }, true));
3409
3678
  }
3410
3679
  isCancelled(_event) {
3411
- if (this.group.api.isFloating && !_event.shiftKey) {
3680
+ if (this.group.api.location === 'floating' && !_event.shiftKey) {
3412
3681
  return true;
3413
3682
  }
3414
3683
  return false;
@@ -3610,7 +3879,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3610
3879
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3611
3880
  if (isFloatingGroupsEnabled &&
3612
3881
  event.shiftKey &&
3613
- !this.group.api.isFloating) {
3882
+ this.group.api.location !== 'floating') {
3614
3883
  event.preventDefault();
3615
3884
  const { top, left } = this.element.getBoundingClientRect();
3616
3885
  const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
@@ -3675,7 +3944,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3675
3944
  }), tab.onChanged((event) => {
3676
3945
  var _a;
3677
3946
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3678
- const isFloatingWithOnePanel = this.group.api.isFloating && this.size === 1;
3947
+ const isFloatingWithOnePanel = this.group.api.location === 'floating' && this.size === 1;
3679
3948
  if (isFloatingGroupsEnabled &&
3680
3949
  !isFloatingWithOnePanel &&
3681
3950
  event.shiftKey) {
@@ -3758,15 +4027,37 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3758
4027
  }
3759
4028
  return isAncestor(document.activeElement, this.contentContainer.element);
3760
4029
  }
3761
- get isFloating() {
3762
- return this._isFloating;
3763
- }
3764
- set isFloating(value) {
3765
- this._isFloating = value;
3766
- this.dropTarget.setTargetZones(value ? ['center'] : ['top', 'bottom', 'left', 'right', 'center']);
3767
- toggleClass(this.container, 'dv-groupview-floating', value);
3768
- this.groupPanel.api._onDidFloatingStateChange.fire({
3769
- isFloating: this.isFloating,
4030
+ get location() {
4031
+ return this._location;
4032
+ }
4033
+ set location(value) {
4034
+ this._location = value;
4035
+ toggleClass(this.container, 'dv-groupview-floating', false);
4036
+ toggleClass(this.container, 'dv-groupview-popout', false);
4037
+ switch (value) {
4038
+ case 'grid':
4039
+ this.contentContainer.dropTarget.setTargetZones([
4040
+ 'top',
4041
+ 'bottom',
4042
+ 'left',
4043
+ 'right',
4044
+ 'center',
4045
+ ]);
4046
+ break;
4047
+ case 'floating':
4048
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4049
+ this.contentContainer.dropTarget.setTargetZones(value
4050
+ ? ['center']
4051
+ : ['top', 'bottom', 'left', 'right', 'center']);
4052
+ toggleClass(this.container, 'dv-groupview-floating', true);
4053
+ break;
4054
+ case 'popout':
4055
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4056
+ toggleClass(this.container, 'dv-groupview-popout', true);
4057
+ break;
4058
+ }
4059
+ this.groupPanel.api._onDidLocationChange.fire({
4060
+ location: this.location,
3770
4061
  });
3771
4062
  }
3772
4063
  constructor(container, accessor, id, options, groupPanel) {
@@ -3779,7 +4070,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3779
4070
  this.groupPanel = groupPanel;
3780
4071
  this._isGroupActive = false;
3781
4072
  this._locked = false;
3782
- this._isFloating = false;
4073
+ this._location = 'grid';
3783
4074
  this.mostRecentlyUsed = [];
3784
4075
  this._onDidChange = new Emitter();
3785
4076
  this.onDidChange = this._onDidChange.event;
@@ -3802,35 +4093,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3802
4093
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
3803
4094
  toggleClass(this.container, 'groupview', true);
3804
4095
  this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel);
3805
- this.contentContainer = new ContentContainer();
3806
- this.dropTarget = new Droptarget(this.contentContainer.element, {
3807
- acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3808
- canDisplayOverlay: (event, position) => {
3809
- if (this.locked === 'no-drop-target' ||
3810
- (this.locked && position === 'center')) {
3811
- return false;
3812
- }
3813
- const data = getPanelData();
3814
- if (!data && event.shiftKey && !this.isFloating) {
3815
- return false;
3816
- }
3817
- if (data && data.viewId === this.accessor.id) {
3818
- if (data.groupId === this.id) {
3819
- if (position === 'center') {
3820
- // don't allow to drop on self for center position
3821
- return false;
3822
- }
3823
- if (data.panelId === null) {
3824
- // don't allow group move to drop anywhere on self
3825
- return false;
3826
- }
3827
- }
3828
- const groupHasOnePanelAndIsActiveDragElement = this._panels.length === 1 && data.groupId === this.id;
3829
- return !groupHasOnePanelAndIsActiveDragElement;
3830
- }
3831
- return this.canDisplayOverlay(event, position, exports.DockviewDropTargets.Panel);
3832
- },
3833
- });
4096
+ this.contentContainer = new ContentContainer(this.accessor, this);
3834
4097
  container.append(this.tabsContainer.element, this.contentContainer.element);
3835
4098
  this.header.hidden = !!options.hideHeader;
3836
4099
  this.locked = (_a = options.locked) !== null && _a !== void 0 ? _a : false;
@@ -3844,7 +4107,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3844
4107
  this.accessor.doSetGroupActive(this.groupPanel, true);
3845
4108
  }), this.contentContainer.onDidBlur(() => {
3846
4109
  // noop
3847
- }), this.dropTarget.onDrop((event) => {
4110
+ }), this.contentContainer.dropTarget.onDrop((event) => {
3848
4111
  this.handleDropEvent(event.nativeEvent, event.position);
3849
4112
  }), this._onMove, this._onDidChange, this._onDidDrop, this._onDidAddPanel, this._onDidRemovePanel, this._onDidActivePanelChange);
3850
4113
  }
@@ -3893,6 +4156,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3893
4156
  this.tabsContainer.setPrefixActionsElement(this._prefixHeaderActions.element);
3894
4157
  }
3895
4158
  }
4159
+ rerender(panel) {
4160
+ this.contentContainer.renderPanel(panel, { asActive: false });
4161
+ }
3896
4162
  indexOf(panel) {
3897
4163
  return this.tabsContainer.indexOf(panel.id);
3898
4164
  }
@@ -4084,12 +4350,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4084
4350
  doAddPanel(panel, index = this.panels.length, skipSetActive = false) {
4085
4351
  const existingPanel = this._panels.indexOf(panel);
4086
4352
  const hasExistingPanel = existingPanel > -1;
4353
+ this.tabsContainer.show();
4354
+ this.contentContainer.show();
4087
4355
  this.tabsContainer.openPanel(panel, index);
4088
4356
  if (!skipSetActive) {
4089
4357
  this.contentContainer.openPanel(panel);
4090
4358
  }
4091
- this.tabsContainer.show();
4092
- this.contentContainer.show();
4093
4359
  if (hasExistingPanel) {
4094
4360
  // TODO - need to ensure ordering hasn't changed and if it has need to re-order this.panels
4095
4361
  return;
@@ -4205,7 +4471,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4205
4471
  for (const panel of this.panels) {
4206
4472
  panel.dispose();
4207
4473
  }
4208
- this.dropTarget.dispose();
4209
4474
  this.tabsContainer.dispose();
4210
4475
  this.contentContainer.dispose();
4211
4476
  }
@@ -4244,7 +4509,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4244
4509
  if (this.disableResizing) {
4245
4510
  return;
4246
4511
  }
4247
- if (!document.body.contains(this._element)) {
4512
+ if (!isInDocument(this._element)) {
4248
4513
  /**
4249
4514
  * since the event is dispatched through requestAnimationFrame there is a small chance
4250
4515
  * the component is no longer attached to the DOM, if that is the case the dimensions
@@ -4336,6 +4601,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4336
4601
  isVisible(panel) {
4337
4602
  return this.gridview.isViewVisible(getGridLocation(panel.element));
4338
4603
  }
4604
+ maximizeGroup(panel) {
4605
+ this.gridview.maximizeView(panel);
4606
+ }
4607
+ isMaximizedGroup(panel) {
4608
+ return this.gridview.maximizedView() === panel;
4609
+ }
4610
+ exitMaximizedGroup() {
4611
+ this.gridview.exitMaximizedView();
4612
+ }
4613
+ hasMaximizedGroup() {
4614
+ return this.gridview.hasMaximizedView();
4615
+ }
4616
+ get onDidMaxmizedGroupChange() {
4617
+ return this.gridview.onDidMaxmizedNodeChange;
4618
+ }
4339
4619
  doAddGroup(group, location = [0], size) {
4340
4620
  this.gridview.addView(group, size !== null && size !== void 0 ? size : exports.Sizing.Distribute, location);
4341
4621
  this._onDidAddGroup.fire(group);
@@ -5112,32 +5392,63 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5112
5392
  }
5113
5393
  }
5114
5394
 
5395
+ // TODO find a better way to initialize and avoid needing null checks
5396
+ const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
5115
5397
  class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
5116
- get isFloating() {
5398
+ get location() {
5117
5399
  if (!this._group) {
5118
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5400
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5119
5401
  }
5120
- return this._group.model.isFloating;
5402
+ return this._group.model.location;
5121
5403
  }
5122
5404
  constructor(id, accessor) {
5123
5405
  super(id);
5124
5406
  this.accessor = accessor;
5125
- this._onDidFloatingStateChange = new Emitter();
5126
- this.onDidFloatingStateChange = this._onDidFloatingStateChange.event;
5127
- this.addDisposables(this._onDidFloatingStateChange);
5407
+ this._onDidLocationChange = new Emitter();
5408
+ this.onDidLocationChange = this._onDidLocationChange.event;
5409
+ this.addDisposables(this._onDidLocationChange);
5128
5410
  }
5129
5411
  moveTo(options) {
5130
- var _a;
5412
+ var _a, _b, _c;
5413
+ if (!this._group) {
5414
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5415
+ }
5416
+ const group = (_a = options.group) !== null && _a !== void 0 ? _a : this.accessor.addGroup({
5417
+ direction: positionToDirection((_b = options.position) !== null && _b !== void 0 ? _b : 'right'),
5418
+ });
5419
+ this.accessor.moveGroupOrPanel(group, this._group.id, undefined, options.group ? (_c = options.position) !== null && _c !== void 0 ? _c : 'center' : 'center');
5420
+ }
5421
+ maximize() {
5422
+ if (!this._group) {
5423
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5424
+ }
5425
+ if (this.location !== 'grid') {
5426
+ // only grid groups can be maximized
5427
+ return;
5428
+ }
5429
+ this.accessor.maximizeGroup(this._group);
5430
+ }
5431
+ isMaximized() {
5131
5432
  if (!this._group) {
5132
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5433
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5434
+ }
5435
+ return this.accessor.isMaximizedGroup(this._group);
5436
+ }
5437
+ exitMaximized() {
5438
+ if (!this._group) {
5439
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5440
+ }
5441
+ if (this.isMaximized()) {
5442
+ this.accessor.exitMaximizedGroup();
5133
5443
  }
5134
- this.accessor.moveGroupOrPanel(options.group, this._group.id, undefined, (_a = options.position) !== null && _a !== void 0 ? _a : 'center');
5135
5444
  }
5136
5445
  initialize(group) {
5137
5446
  this._group = group;
5138
5447
  }
5139
5448
  }
5140
5449
 
5450
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH = 100;
5451
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT = 100;
5141
5452
  class DockviewGroupPanel extends GridviewPanel {
5142
5453
  get panels() {
5143
5454
  return this._model.panels;
@@ -5162,8 +5473,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5162
5473
  }
5163
5474
  constructor(accessor, id, options) {
5164
5475
  super(id, 'groupview_default', {
5165
- minimumHeight: 100,
5166
- minimumWidth: 100,
5476
+ minimumHeight: MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT,
5477
+ minimumWidth: MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH,
5167
5478
  }, new DockviewGroupPanelApiImpl(id, accessor));
5168
5479
  this.api.initialize(this); // cannot use 'this' after after 'super' call
5169
5480
  this._model = new DockviewGroupPanelModel(this.element, accessor, id, options, this);
@@ -5217,8 +5528,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5217
5528
  return this.panel.title;
5218
5529
  }
5219
5530
  get isGroupActive() {
5220
- var _a;
5221
- return !!((_a = this.group) === null || _a === void 0 ? void 0 : _a.isActive);
5531
+ return this.group.isActive;
5532
+ }
5533
+ get renderer() {
5534
+ return this.panel.renderer;
5222
5535
  }
5223
5536
  set group(value) {
5224
5537
  const isOldGroupActive = this.isGroupActive;
@@ -5246,10 +5559,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5246
5559
  this.onDidActiveGroupChange = this._onDidActiveGroupChange.event;
5247
5560
  this._onDidGroupChange = new Emitter();
5248
5561
  this.onDidGroupChange = this._onDidGroupChange.event;
5562
+ this._onDidRendererChange = new Emitter();
5563
+ this.onDidRendererChange = this._onDidRendererChange.event;
5249
5564
  this.disposable = new MutableDisposable();
5250
5565
  this.initialize(panel);
5251
5566
  this._group = group;
5252
- this.addDisposables(this.disposable, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5567
+ this.addDisposables(this.disposable, this._onDidRendererChange, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5253
5568
  }
5254
5569
  moveTo(options) {
5255
5570
  var _a;
@@ -5258,9 +5573,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5258
5573
  setTitle(title) {
5259
5574
  this.panel.setTitle(title);
5260
5575
  }
5576
+ setRenderer(renderer) {
5577
+ this.panel.setRenderer(renderer);
5578
+ }
5261
5579
  close() {
5262
5580
  this.group.model.closePanel(this.panel);
5263
5581
  }
5582
+ maximize() {
5583
+ this.group.api.maximize();
5584
+ }
5585
+ isMaximized() {
5586
+ return this.group.api.isMaximized();
5587
+ }
5588
+ exitMaximized() {
5589
+ this.group.api.exitMaximized();
5590
+ }
5264
5591
  }
5265
5592
 
5266
5593
  class DockviewPanel extends CompositeDisposable {
@@ -5273,11 +5600,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5273
5600
  get group() {
5274
5601
  return this._group;
5275
5602
  }
5276
- constructor(id, accessor, containerApi, group, view) {
5603
+ get renderer() {
5604
+ var _a;
5605
+ return (_a = this._renderer) !== null && _a !== void 0 ? _a : this.accessor.renderer;
5606
+ }
5607
+ constructor(id, accessor, containerApi, group, view, options) {
5277
5608
  super();
5278
5609
  this.id = id;
5610
+ this.accessor = accessor;
5279
5611
  this.containerApi = containerApi;
5280
5612
  this.view = view;
5613
+ this._renderer = options.renderer;
5281
5614
  this._group = group;
5282
5615
  this.api = new DockviewPanelApiImpl(this, this._group, accessor);
5283
5616
  this.addDisposables(this.api.onActiveChange(() => {
@@ -5286,6 +5619,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5286
5619
  // forward the resize event to the group since if you want to resize a panel
5287
5620
  // you are actually just resizing the panels parent which is the group
5288
5621
  this.group.api.setSize(event);
5622
+ }), this.api.onDidRendererChange((event) => {
5623
+ this.group.model.rerender(this);
5289
5624
  }));
5290
5625
  }
5291
5626
  init(params) {
@@ -5305,6 +5640,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5305
5640
  ? this._params
5306
5641
  : undefined,
5307
5642
  title: this.title,
5643
+ renderer: this._renderer,
5308
5644
  };
5309
5645
  }
5310
5646
  setTitle(title) {
@@ -5320,6 +5656,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5320
5656
  this.api._onDidTitleChange.fire({ title });
5321
5657
  }
5322
5658
  }
5659
+ setRenderer(renderer) {
5660
+ const didChange = renderer !== this.renderer;
5661
+ if (didChange) {
5662
+ this._renderer = renderer;
5663
+ this.api._onDidRendererChange.fire({
5664
+ renderer: renderer,
5665
+ });
5666
+ }
5667
+ }
5323
5668
  update(event) {
5324
5669
  var _a;
5325
5670
  // merge the new parameters with the existing parameters
@@ -5538,8 +5883,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5538
5883
  }
5539
5884
 
5540
5885
  class DefaultDockviewDeserialzier {
5541
- constructor(layout) {
5542
- this.layout = layout;
5886
+ constructor(accessor) {
5887
+ this.accessor = accessor;
5543
5888
  }
5544
5889
  fromJSON(panelData, group) {
5545
5890
  var _a, _b;
@@ -5553,8 +5898,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5553
5898
  const tabComponent = viewData
5554
5899
  ? (_b = viewData.tab) === null || _b === void 0 ? void 0 : _b.id
5555
5900
  : panelData.tabComponent;
5556
- const view = new DockviewPanelModel(this.layout, panelId, contentComponent, tabComponent);
5557
- const panel = new DockviewPanel(panelId, this.layout, new DockviewApi(this.layout), group, view);
5901
+ const view = new DockviewPanelModel(this.accessor, panelId, contentComponent, tabComponent);
5902
+ const panel = new DockviewPanel(panelId, this.accessor, new DockviewApi(this.accessor), group, view, {
5903
+ renderer: panelData.renderer,
5904
+ });
5558
5905
  panel.init({
5559
5906
  title: title !== null && title !== void 0 ? title : panelId,
5560
5907
  params: params !== null && params !== void 0 ? params : {},
@@ -5934,7 +6281,261 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5934
6281
  }
5935
6282
  }
5936
6283
 
6284
+ class PopoutWindow extends CompositeDisposable {
6285
+ constructor(id, className, options) {
6286
+ super();
6287
+ this.id = id;
6288
+ this.className = className;
6289
+ this.options = options;
6290
+ this._onDidClose = new Emitter();
6291
+ this.onDidClose = this._onDidClose.event;
6292
+ this._window = null;
6293
+ this.addDisposables(this._onDidClose, {
6294
+ dispose: () => {
6295
+ this.close();
6296
+ },
6297
+ });
6298
+ }
6299
+ dimensions() {
6300
+ if (!this._window) {
6301
+ return null;
6302
+ }
6303
+ const left = this._window.value.screenX;
6304
+ const top = this._window.value.screenY;
6305
+ const width = this._window.value.innerWidth;
6306
+ const height = this._window.value.innerHeight;
6307
+ return { top, left, width, height };
6308
+ }
6309
+ close() {
6310
+ if (this._window) {
6311
+ this._window.disposable.dispose();
6312
+ this._window.value.close();
6313
+ this._window = null;
6314
+ }
6315
+ }
6316
+ open(content) {
6317
+ if (this._window) {
6318
+ throw new Error('instance of popout window is already open');
6319
+ }
6320
+ const url = `${this.options.url}`;
6321
+ const features = Object.entries({
6322
+ top: this.options.top,
6323
+ left: this.options.left,
6324
+ width: this.options.width,
6325
+ height: this.options.height,
6326
+ })
6327
+ .map(([key, value]) => `${key}=${value}`)
6328
+ .join(',');
6329
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/open
6330
+ const externalWindow = window.open(url, this.id, features);
6331
+ if (!externalWindow) {
6332
+ return;
6333
+ }
6334
+ const disposable = new CompositeDisposable();
6335
+ this._window = { value: externalWindow, disposable };
6336
+ const cleanUp = () => {
6337
+ this._onDidClose.fire();
6338
+ this._window = null;
6339
+ };
6340
+ // prevent any default content from loading
6341
+ // externalWindow.document.body.replaceWith(document.createElement('div'));
6342
+ disposable.addDisposables(addDisposableWindowListener(window, 'beforeunload', () => {
6343
+ cleanUp();
6344
+ this.close();
6345
+ }));
6346
+ externalWindow.addEventListener('load', () => {
6347
+ const externalDocument = externalWindow.document;
6348
+ externalDocument.title = document.title;
6349
+ const div = document.createElement('div');
6350
+ div.classList.add('dv-popout-window');
6351
+ div.style.position = 'absolute';
6352
+ div.style.width = '100%';
6353
+ div.style.height = '100%';
6354
+ div.style.top = '0px';
6355
+ div.style.left = '0px';
6356
+ div.classList.add(this.className);
6357
+ div.appendChild(content);
6358
+ externalDocument.body.replaceChildren(div);
6359
+ externalDocument.body.classList.add(this.className);
6360
+ addStyles(externalDocument, window.document.styleSheets);
6361
+ externalWindow.addEventListener('beforeunload', () => {
6362
+ // TODO: indicate external window is closing
6363
+ cleanUp();
6364
+ });
6365
+ });
6366
+ }
6367
+ }
6368
+
6369
+ class DockviewPopoutGroupPanel extends CompositeDisposable {
6370
+ constructor(id, group, options) {
6371
+ var _a;
6372
+ super();
6373
+ this.id = id;
6374
+ this.group = group;
6375
+ this.options = options;
6376
+ this.window = new PopoutWindow(id, (_a = options.className) !== null && _a !== void 0 ? _a : '', {
6377
+ url: this.options.popoutUrl,
6378
+ left: this.options.box.left,
6379
+ top: this.options.box.top,
6380
+ width: this.options.box.width,
6381
+ height: this.options.box.height,
6382
+ });
6383
+ group.model.location = 'popout';
6384
+ this.addDisposables(this.window, {
6385
+ dispose: () => {
6386
+ group.model.location = 'grid';
6387
+ },
6388
+ }, this.window.onDidClose(() => {
6389
+ this.dispose();
6390
+ }));
6391
+ this.window.open(group.element);
6392
+ }
6393
+ }
6394
+
5937
6395
  const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
6396
+ const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100 };
6397
+
6398
+ function createFocusableElement() {
6399
+ const element = document.createElement('div');
6400
+ element.tabIndex = -1;
6401
+ return element;
6402
+ }
6403
+ class OverlayRenderContainer extends CompositeDisposable {
6404
+ constructor(element) {
6405
+ super();
6406
+ this.element = element;
6407
+ this.map = {};
6408
+ this.addDisposables(Disposable.from(() => {
6409
+ for (const value of Object.values(this.map)) {
6410
+ value.disposable.dispose();
6411
+ value.destroy.dispose();
6412
+ }
6413
+ }));
6414
+ }
6415
+ detatch(panel) {
6416
+ if (this.map[panel.api.id]) {
6417
+ const { disposable, destroy } = this.map[panel.api.id];
6418
+ disposable.dispose();
6419
+ destroy.dispose();
6420
+ delete this.map[panel.api.id];
6421
+ return true;
6422
+ }
6423
+ return false;
6424
+ }
6425
+ attach(options) {
6426
+ const { panel, referenceContainer } = options;
6427
+ if (!this.map[panel.api.id]) {
6428
+ const element = createFocusableElement();
6429
+ element.className = 'dv-render-overlay';
6430
+ this.map[panel.api.id] = {
6431
+ panel,
6432
+ disposable: Disposable.NONE,
6433
+ destroy: Disposable.NONE,
6434
+ element,
6435
+ };
6436
+ }
6437
+ const focusContainer = this.map[panel.api.id].element;
6438
+ if (panel.view.content.element.parentElement !== focusContainer) {
6439
+ focusContainer.appendChild(panel.view.content.element);
6440
+ }
6441
+ if (focusContainer.parentElement !== this.element) {
6442
+ this.element.appendChild(focusContainer);
6443
+ }
6444
+ const resize = () => {
6445
+ // TODO propagate position to avoid getDomNodePagePosition calls, possible performance bottleneck?
6446
+ const box = getDomNodePagePosition(referenceContainer.element);
6447
+ const box2 = getDomNodePagePosition(this.element);
6448
+ focusContainer.style.left = `${box.left - box2.left}px`;
6449
+ focusContainer.style.top = `${box.top - box2.top}px`;
6450
+ focusContainer.style.width = `${box.width}px`;
6451
+ focusContainer.style.height = `${box.height}px`;
6452
+ toggleClass(focusContainer, 'dv-render-overlay-float', panel.group.api.location === 'floating');
6453
+ };
6454
+ const visibilityChanged = () => {
6455
+ if (panel.api.isVisible) {
6456
+ resize();
6457
+ }
6458
+ focusContainer.style.display = panel.api.isVisible ? '' : 'none';
6459
+ };
6460
+ const disposable = new CompositeDisposable(
6461
+ /**
6462
+ * since container is positioned absoutely we must explicitly forward
6463
+ * the dnd events for the expect behaviours to continue to occur in terms of dnd
6464
+ *
6465
+ * the dnd observer does not need to be conditional on whether the panel is visible since
6466
+ * non-visible panels are 'display: none' and in such case the dnd observer will not fire.
6467
+ */
6468
+ new DragAndDropObserver(focusContainer, {
6469
+ onDragEnd: (e) => {
6470
+ referenceContainer.dropTarget.dnd.onDragEnd(e);
6471
+ },
6472
+ onDragEnter: (e) => {
6473
+ referenceContainer.dropTarget.dnd.onDragEnter(e);
6474
+ },
6475
+ onDragLeave: (e) => {
6476
+ referenceContainer.dropTarget.dnd.onDragLeave(e);
6477
+ },
6478
+ onDrop: (e) => {
6479
+ referenceContainer.dropTarget.dnd.onDrop(e);
6480
+ },
6481
+ onDragOver: (e) => {
6482
+ referenceContainer.dropTarget.dnd.onDragOver(e);
6483
+ },
6484
+ }), panel.api.onDidVisibilityChange((event) => {
6485
+ /**
6486
+ * Control the visibility of the content, however even when not visible (display: none)
6487
+ * the content is still maintained within the DOM hence DOM specific attributes
6488
+ * such as scroll position are maintained when next made visible.
6489
+ */
6490
+ visibilityChanged();
6491
+ }), panel.api.onDidDimensionsChange(() => {
6492
+ if (!panel.api.isVisible) {
6493
+ return;
6494
+ }
6495
+ resize();
6496
+ }));
6497
+ this.map[panel.api.id].destroy = Disposable.from(() => {
6498
+ focusContainer.removeChild(panel.view.content.element);
6499
+ this.element.removeChild(focusContainer);
6500
+ });
6501
+ queueMicrotask(() => {
6502
+ if (this.isDisposed) {
6503
+ return;
6504
+ }
6505
+ /**
6506
+ * wait until everything has finished in the current stack-frame call before
6507
+ * calling the first resize as other size-altering events may still occur before
6508
+ * the end of the stack-frame.
6509
+ */
6510
+ visibilityChanged();
6511
+ });
6512
+ // dispose of logic asoccciated with previous reference-container
6513
+ this.map[panel.api.id].disposable.dispose();
6514
+ // and reset the disposable to the active reference-container
6515
+ this.map[panel.api.id].disposable = disposable;
6516
+ return focusContainer;
6517
+ }
6518
+ }
6519
+
6520
+ function getTheme(element) {
6521
+ function toClassList(element) {
6522
+ const list = [];
6523
+ for (let i = 0; i < element.classList.length; i++) {
6524
+ list.push(element.classList.item(i));
6525
+ }
6526
+ return list;
6527
+ }
6528
+ let theme = undefined;
6529
+ let parent = element;
6530
+ while (parent !== null) {
6531
+ theme = toClassList(parent).find((cls) => cls.startsWith('dockview-theme-'));
6532
+ if (typeof theme === 'string') {
6533
+ break;
6534
+ }
6535
+ parent = parent.parentElement;
6536
+ }
6537
+ return theme;
6538
+ }
5938
6539
  class DockviewComponent extends BaseGrid {
5939
6540
  get orientation() {
5940
6541
  return this.gridview.orientation;
@@ -5955,6 +6556,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5955
6556
  }
5956
6557
  return activeGroup.activePanel;
5957
6558
  }
6559
+ get renderer() {
6560
+ var _a;
6561
+ return (_a = this.options.defaultRenderer) !== null && _a !== void 0 ? _a : 'onlyWhenVisibile';
6562
+ }
5958
6563
  constructor(options) {
5959
6564
  var _a;
5960
6565
  super({
@@ -5981,12 +6586,27 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5981
6586
  this.onDidLayoutFromJSON = this._onDidLayoutFromJSON.event;
5982
6587
  this._onDidActivePanelChange = new Emitter();
5983
6588
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
5984
- this.floatingGroups = [];
6589
+ this._floatingGroups = [];
6590
+ this._popoutGroups = [];
6591
+ const gready = document.createElement('div');
6592
+ gready.className = 'dv-overlay-render-container';
6593
+ this.gridview.element.appendChild(gready);
6594
+ this.overlayRenderContainer = new OverlayRenderContainer(gready);
5985
6595
  toggleClass(this.gridview.element, 'dv-dockview', true);
5986
- this.addDisposables(this._onWillDragPanel, this._onWillDragGroup, this._onDidActivePanelChange, this._onDidAddPanel, this._onDidRemovePanel, this._onDidLayoutFromJSON, this._onDidDrop, exports.DockviewEvent.any(this.onDidAddGroup, this.onDidRemoveGroup)(() => {
6596
+ toggleClass(this.element, 'dv-debug', !!options.debug);
6597
+ 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)(() => {
5987
6598
  this.updateWatermark();
5988
6599
  }), exports.DockviewEvent.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidActivePanelChange)(() => {
5989
6600
  this._bufferOnDidLayoutChange.fire();
6601
+ }), Disposable.from(() => {
6602
+ // iterate over a copy of the array since .dispose() mutates the original array
6603
+ for (const group of [...this._floatingGroups]) {
6604
+ group.dispose();
6605
+ }
6606
+ // iterate over a copy of the array since .dispose() mutates the original array
6607
+ for (const group of [...this._popoutGroups]) {
6608
+ group.dispose();
6609
+ }
5990
6610
  }));
5991
6611
  this._options = options;
5992
6612
  if (!this.options.components) {
@@ -6056,6 +6676,55 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6056
6676
  this._api = new DockviewApi(this);
6057
6677
  this.updateWatermark();
6058
6678
  }
6679
+ addPopoutGroup(item, options) {
6680
+ var _a;
6681
+ let group;
6682
+ let box = options === null || options === void 0 ? void 0 : options.position;
6683
+ if (item instanceof DockviewPanel) {
6684
+ group = this.createGroup();
6685
+ this.removePanel(item, {
6686
+ removeEmptyGroup: true,
6687
+ skipDispose: true,
6688
+ });
6689
+ group.model.openPanel(item);
6690
+ if (!box) {
6691
+ box = this.element.getBoundingClientRect();
6692
+ }
6693
+ }
6694
+ else {
6695
+ group = item;
6696
+ if (!box) {
6697
+ box = group.element.getBoundingClientRect();
6698
+ }
6699
+ const skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
6700
+ options.skipRemoveGroup;
6701
+ if (!skip) {
6702
+ this.doRemoveGroup(item, { skipDispose: true });
6703
+ }
6704
+ }
6705
+ const theme = getTheme(this.gridview.element);
6706
+ const popoutWindow = new DockviewPopoutGroupPanel(`${this.id}-${group.id}`, // globally unique within dockview
6707
+ group, {
6708
+ className: theme !== null && theme !== void 0 ? theme : '',
6709
+ popoutUrl: (_a = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _a !== void 0 ? _a : '/popout.html',
6710
+ box: {
6711
+ left: window.screenX + box.left,
6712
+ top: window.screenY + box.top,
6713
+ width: box.width,
6714
+ height: box.height,
6715
+ },
6716
+ });
6717
+ popoutWindow.addDisposables({
6718
+ dispose: () => {
6719
+ remove(this._popoutGroups, popoutWindow);
6720
+ this.updateWatermark();
6721
+ },
6722
+ }, popoutWindow.window.onDidClose(() => {
6723
+ this.doAddGroup(group, [0]);
6724
+ }));
6725
+ this._popoutGroups.push(popoutWindow);
6726
+ this.updateWatermark();
6727
+ }
6059
6728
  addFloatingGroup(item, coord, options) {
6060
6729
  var _a, _b, _c, _d, _e, _f;
6061
6730
  let group;
@@ -6075,9 +6744,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6075
6744
  this.doRemoveGroup(item, { skipDispose: true });
6076
6745
  }
6077
6746
  }
6078
- group.model.isFloating = true;
6079
- const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number' ? Math.max(coord.x, 0) : 100;
6080
- const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number' ? Math.max(coord.y, 0) : 100;
6747
+ group.model.location = 'floating';
6748
+ const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number'
6749
+ ? Math.max(coord.x, 0)
6750
+ : DEFAULT_FLOATING_GROUP_POSITION.left;
6751
+ const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number'
6752
+ ? Math.max(coord.y, 0)
6753
+ : DEFAULT_FLOATING_GROUP_POSITION.top;
6081
6754
  const overlay = new Overlay({
6082
6755
  container: this.gridview.element,
6083
6756
  content: group.element,
@@ -6121,12 +6794,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6121
6794
  }), {
6122
6795
  dispose: () => {
6123
6796
  disposable.dispose();
6124
- group.model.isFloating = false;
6125
- remove(this.floatingGroups, floatingGroupPanel);
6797
+ group.model.location = 'grid';
6798
+ remove(this._floatingGroups, floatingGroupPanel);
6126
6799
  this.updateWatermark();
6127
6800
  },
6128
6801
  });
6129
- this.floatingGroups.push(floatingGroupPanel);
6802
+ this._floatingGroups.push(floatingGroupPanel);
6130
6803
  this.updateWatermark();
6131
6804
  }
6132
6805
  orthogonalize(position) {
@@ -6171,7 +6844,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6171
6844
  this.gridview.orientation = options.orientation;
6172
6845
  }
6173
6846
  if (hasFloatingGroupOptionsChanged) {
6174
- for (const group of this.floatingGroups) {
6847
+ for (const group of this._floatingGroups) {
6175
6848
  switch (this.options.floatingGroupBounds) {
6176
6849
  case 'boundedWithinViewport':
6177
6850
  group.overlay.minimumInViewportHeight = undefined;
@@ -6196,8 +6869,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6196
6869
  }
6197
6870
  layout(width, height, forceResize) {
6198
6871
  super.layout(width, height, forceResize);
6199
- if (this.floatingGroups) {
6200
- for (const floating of this.floatingGroups) {
6872
+ if (this._floatingGroups) {
6873
+ for (const floating of this._floatingGroups) {
6201
6874
  // ensure floting groups stay within visible boundaries
6202
6875
  floating.overlay.setBounds();
6203
6876
  }
@@ -6265,10 +6938,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6265
6938
  collection[panel.id] = panel.toJSON();
6266
6939
  return collection;
6267
6940
  }, {});
6268
- const floats = this.floatingGroups.map((floatingGroup) => {
6941
+ const floats = this._floatingGroups.map((group) => {
6942
+ return {
6943
+ data: group.group.toJSON(),
6944
+ position: group.overlay.toJSON(),
6945
+ };
6946
+ });
6947
+ const popoutGroups = this._popoutGroups.map((group) => {
6269
6948
  return {
6270
- data: floatingGroup.group.toJSON(),
6271
- position: floatingGroup.overlay.toJSON(),
6949
+ data: group.group.toJSON(),
6950
+ position: group.window.dimensions(),
6272
6951
  };
6273
6952
  });
6274
6953
  const result = {
@@ -6279,10 +6958,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6279
6958
  if (floats.length > 0) {
6280
6959
  result.floatingGroups = floats;
6281
6960
  }
6961
+ if (popoutGroups.length > 0) {
6962
+ result.popoutGroups = popoutGroups;
6963
+ }
6282
6964
  return result;
6283
6965
  }
6284
6966
  fromJSON(data) {
6285
- var _a;
6967
+ var _a, _b;
6286
6968
  this.clear();
6287
6969
  if (typeof data !== 'object' || data === null) {
6288
6970
  throw new Error('serialized layout must be a non-null object');
@@ -6349,7 +7031,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6349
7031
  width: position.width,
6350
7032
  }, { skipRemoveGroup: true, inDragMode: false });
6351
7033
  }
6352
- for (const floatingGroup of this.floatingGroups) {
7034
+ const serializedPopoutGroups = (_b = data.popoutGroups) !== null && _b !== void 0 ? _b : [];
7035
+ for (const serializedPopoutGroup of serializedPopoutGroups) {
7036
+ const { data, position } = serializedPopoutGroup;
7037
+ const group = createGroupFromSerializedState(data);
7038
+ this.addPopoutGroup(group, {
7039
+ skipRemoveGroup: true,
7040
+ position: position !== null && position !== void 0 ? position : undefined,
7041
+ });
7042
+ }
7043
+ for (const floatingGroup of this._floatingGroups) {
6353
7044
  floatingGroup.overlay.setBounds();
6354
7045
  }
6355
7046
  if (typeof activeGroup === 'string') {
@@ -6381,7 +7072,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6381
7072
  this._onDidRemoveGroup.fire(group);
6382
7073
  }
6383
7074
  // iterate over a reassigned array since original array will be modified
6384
- for (const floatingGroup of [...this.floatingGroups]) {
7075
+ for (const floatingGroup of [...this._floatingGroups]) {
6385
7076
  floatingGroup.dispose();
6386
7077
  }
6387
7078
  // fires clean-up events and clears the underlying HTML gridview.
@@ -6473,7 +7164,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6473
7164
  group.model.openPanel(panel);
6474
7165
  this.doSetGroupAndPanelActive(group);
6475
7166
  }
6476
- else if (referenceGroup.api.isFloating || target === 'center') {
7167
+ else if (referenceGroup.api.location === 'floating' ||
7168
+ target === 'center') {
6477
7169
  panel = this.createPanel(options, referenceGroup);
6478
7170
  referenceGroup.model.openPanel(panel);
6479
7171
  }
@@ -6517,6 +7209,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6517
7209
  }
6518
7210
  group.model.removePanel(panel);
6519
7211
  if (!options.skipDispose) {
7212
+ this.overlayRenderContainer.detatch(panel);
6520
7213
  panel.dispose();
6521
7214
  }
6522
7215
  if (group.size === 0 && options.removeEmptyGroup) {
@@ -6533,7 +7226,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6533
7226
  }
6534
7227
  updateWatermark() {
6535
7228
  var _a, _b;
6536
- if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
7229
+ if (this.groups.filter((x) => x.api.location === 'grid').length === 0) {
6537
7230
  if (!this.watermark) {
6538
7231
  this.watermark = this.createWatermarkComponent();
6539
7232
  this.watermark.init({
@@ -6608,19 +7301,40 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6608
7301
  }
6609
7302
  }
6610
7303
  doRemoveGroup(group, options) {
6611
- const floatingGroup = this.floatingGroups.find((_) => _.group === group);
6612
- if (floatingGroup) {
6613
- if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6614
- floatingGroup.group.dispose();
6615
- this._groups.delete(group.id);
6616
- this._onDidRemoveGroup.fire(group);
7304
+ if (group.api.location === 'floating') {
7305
+ const floatingGroup = this._floatingGroups.find((_) => _.group === group);
7306
+ if (floatingGroup) {
7307
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7308
+ floatingGroup.group.dispose();
7309
+ this._groups.delete(group.id);
7310
+ this._onDidRemoveGroup.fire(group);
7311
+ }
7312
+ remove(this._floatingGroups, floatingGroup);
7313
+ floatingGroup.dispose();
7314
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7315
+ const groups = Array.from(this._groups.values());
7316
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7317
+ }
7318
+ return floatingGroup.group;
6617
7319
  }
6618
- floatingGroup.dispose();
6619
- if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
6620
- const groups = Array.from(this._groups.values());
6621
- this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7320
+ throw new Error('failed to find floating group');
7321
+ }
7322
+ if (group.api.location === 'popout') {
7323
+ const selectedGroup = this._popoutGroups.find((_) => _.group === group);
7324
+ if (selectedGroup) {
7325
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7326
+ selectedGroup.group.dispose();
7327
+ this._groups.delete(group.id);
7328
+ this._onDidRemoveGroup.fire(group);
7329
+ }
7330
+ selectedGroup.dispose();
7331
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7332
+ const groups = Array.from(this._groups.values());
7333
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7334
+ }
7335
+ return selectedGroup.group;
6622
7336
  }
6623
- return floatingGroup.group;
7337
+ throw new Error('failed to find popout group');
6624
7338
  }
6625
7339
  return super.doRemoveGroup(group, options);
6626
7340
  }
@@ -6652,8 +7366,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6652
7366
  const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
6653
7367
  if (sourceGroup && sourceGroup.size < 2) {
6654
7368
  const [targetParentLocation, to] = tail(targetLocation);
6655
- const isFloating = this.floatingGroups.find((x) => x.group === sourceGroup);
6656
- if (!isFloating) {
7369
+ if (sourceGroup.api.location === 'grid') {
6657
7370
  const sourceLocation = getGridLocation(sourceGroup.element);
6658
7371
  const [sourceParentLocation, from] = tail(sourceLocation);
6659
7372
  if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
@@ -6699,12 +7412,25 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6699
7412
  }
6700
7413
  }
6701
7414
  else {
6702
- const floatingGroup = this.floatingGroups.find((x) => x.group === sourceGroup);
6703
- if (floatingGroup) {
6704
- floatingGroup.dispose();
6705
- }
6706
- else {
6707
- this.gridview.removeView(getGridLocation(sourceGroup.element));
7415
+ switch (sourceGroup.api.location) {
7416
+ case 'grid':
7417
+ this.gridview.removeView(getGridLocation(sourceGroup.element));
7418
+ break;
7419
+ case 'floating': {
7420
+ const selectedFloatingGroup = this._floatingGroups.find((x) => x.group === sourceGroup);
7421
+ if (!selectedFloatingGroup) {
7422
+ throw new Error('failed to find floating group');
7423
+ }
7424
+ selectedFloatingGroup.dispose();
7425
+ break;
7426
+ }
7427
+ case 'popout': {
7428
+ const selectedPopoutGroup = this._popoutGroups.find((x) => x.group === sourceGroup);
7429
+ if (!selectedPopoutGroup) {
7430
+ throw new Error('failed to find popout group');
7431
+ }
7432
+ selectedPopoutGroup.dispose();
7433
+ }
6708
7434
  }
6709
7435
  const referenceLocation = getGridLocation(referenceGroup.element);
6710
7436
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, target);
@@ -6766,7 +7492,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6766
7492
  const contentComponent = options.component;
6767
7493
  const tabComponent = (_a = options.tabComponent) !== null && _a !== void 0 ? _a : this.options.defaultTabComponent;
6768
7494
  const view = new DockviewPanelModel(this, options.id, contentComponent, tabComponent);
6769
- const panel = new DockviewPanel(options.id, this, this._api, group, view);
7495
+ const panel = new DockviewPanel(options.id, this, this._api, group, view, { renderer: options.renderer });
6770
7496
  panel.init({
6771
7497
  title: (_b = options.title) !== null && _b !== void 0 ? _b : options.id,
6772
7498
  params: (_c = options === null || options === void 0 ? void 0 : options.params) !== null && _c !== void 0 ? _c : {},
@@ -8112,6 +8838,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
8112
8838
  singleTabMode: props.singleTabMode,
8113
8839
  disableFloatingGroups: props.disableFloatingGroups,
8114
8840
  floatingGroupBounds: props.floatingGroupBounds,
8841
+ defaultRenderer: props.defaultRenderer,
8842
+ debug: props.debug,
8115
8843
  });
8116
8844
  const { clientWidth, clientHeight } = domRef.current;
8117
8845
  dockview.layout(clientWidth, clientHeight);