dockview 1.8.5 → 1.9.1

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 +4 -1
  4. package/dist/cjs/dockview/dockview.d.ts.map +1 -1
  5. package/dist/cjs/dockview/dockview.js +11 -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 +976 -228
  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 +976 -228
  21. package/dist/dockview.amd.noStyle.js.map +1 -1
  22. package/dist/dockview.cjs.js +976 -228
  23. package/dist/dockview.cjs.js.map +1 -1
  24. package/dist/dockview.esm.js +976 -228
  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 +976 -228
  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 +976 -228
  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 +4 -1
  38. package/dist/esm/dockview/dockview.d.ts.map +1 -1
  39. package/dist/esm/dockview/dockview.js +11 -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.1
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;
1104
1171
  for (let i = 0; i < this.viewItems.length; i++) {
1105
1172
  const item = this.viewItems[i];
1106
- item.size = clamp(Math.round(this.proportions[i] * size), item.minimumSize, item.maximumSize);
1173
+ const proportion = this.proportions[i];
1174
+ if (typeof proportion === 'number') {
1175
+ total += proportion;
1176
+ }
1177
+ else {
1178
+ size -= item.size;
1179
+ }
1180
+ }
1181
+ for (let i = 0; i < this.viewItems.length; i++) {
1182
+ const item = this.viewItems[i];
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,36 +3056,48 @@ 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
  }
2887
3100
 
2888
- function numberOrFallback(maybeNumber, fallback) {
2889
- return typeof maybeNumber === 'number' ? maybeNumber : fallback;
2890
- }
2891
3101
  function directionToPosition(direction) {
2892
3102
  switch (direction) {
2893
3103
  case 'above':
@@ -2920,6 +3130,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2920
3130
  throw new Error(`invalid position '${position}'`);
2921
3131
  }
2922
3132
  }
3133
+ const DEFAULT_ACTIVATION_SIZE = {
3134
+ value: 20,
3135
+ type: 'percentage',
3136
+ };
3137
+ const DEFAULT_SIZE = {
3138
+ value: 50,
3139
+ type: 'percentage',
3140
+ };
3141
+ const SMALL_WIDTH_BOUNDARY = 100;
3142
+ const SMALL_HEIGHT_BOUNDARY = 100;
2923
3143
  class Droptarget extends CompositeDisposable {
2924
3144
  get state() {
2925
3145
  return this._state;
@@ -2932,7 +3152,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2932
3152
  this.onDrop = this._onDrop.event;
2933
3153
  // use a set to take advantage of #<set>.has
2934
3154
  this._acceptedTargetZonesSet = new Set(this.options.acceptedTargetZones);
2935
- this.addDisposables(this._onDrop, new DragAndDropObserver(this.element, {
3155
+ this.dnd = new DragAndDropObserver(this.element, {
2936
3156
  onDragEnter: () => undefined,
2937
3157
  onDragOver: (e) => {
2938
3158
  if (this._acceptedTargetZonesSet.size === 0) {
@@ -2980,7 +3200,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2980
3200
  this.element.append(this.targetElement);
2981
3201
  }
2982
3202
  this.toggleClasses(quadrant, width, height);
2983
- this.setState(quadrant);
3203
+ this._state = quadrant;
2984
3204
  },
2985
3205
  onDragLeave: () => {
2986
3206
  this.removeDropTarget();
@@ -2999,11 +3219,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2999
3219
  this._onDrop.fire({ position: state, nativeEvent: e });
3000
3220
  }
3001
3221
  },
3002
- }));
3222
+ });
3223
+ this.addDisposables(this._onDrop, this.dnd);
3003
3224
  }
3004
3225
  setTargetZones(acceptedTargetZones) {
3005
3226
  this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
3006
3227
  }
3228
+ setOverlayModel(model) {
3229
+ this.options.overlayModel = model;
3230
+ }
3007
3231
  dispose() {
3008
3232
  this.removeDropTarget();
3009
3233
  super.dispose();
@@ -3015,19 +3239,19 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3015
3239
  event[Droptarget.USED_EVENT_ID] = true;
3016
3240
  }
3017
3241
  /**
3018
- * Check is the event has already been used by another instance od DropTarget
3242
+ * Check is the event has already been used by another instance of DropTarget
3019
3243
  */
3020
3244
  isAlreadyUsed(event) {
3021
3245
  const value = event[Droptarget.USED_EVENT_ID];
3022
3246
  return typeof value === 'boolean' && value;
3023
3247
  }
3024
3248
  toggleClasses(quadrant, width, height) {
3025
- var _a, _b, _c, _d;
3249
+ var _a, _b;
3026
3250
  if (!this.overlayElement) {
3027
3251
  return;
3028
3252
  }
3029
- const isSmallX = width < 100;
3030
- const isSmallY = height < 100;
3253
+ const isSmallX = width < SMALL_WIDTH_BOUNDARY;
3254
+ const isSmallY = height < SMALL_HEIGHT_BOUNDARY;
3031
3255
  const isLeft = quadrant === 'left';
3032
3256
  const isRight = quadrant === 'right';
3033
3257
  const isTop = quadrant === 'top';
@@ -3036,20 +3260,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3036
3260
  const leftClass = !isSmallX && isLeft;
3037
3261
  const topClass = !isSmallY && isTop;
3038
3262
  const bottomClass = !isSmallY && isBottom;
3039
- let size = 0.5;
3040
- if (((_b = (_a = this.options.overlayModel) === null || _a === void 0 ? void 0 : _a.size) === null || _b === void 0 ? void 0 : _b.type) === 'percentage') {
3041
- size = clamp(this.options.overlayModel.size.value, 0, 100) / 100;
3263
+ let size = 1;
3264
+ const sizeOptions = (_b = (_a = this.options.overlayModel) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : DEFAULT_SIZE;
3265
+ if (sizeOptions.type === 'percentage') {
3266
+ size = clamp(sizeOptions.value, 0, 100) / 100;
3042
3267
  }
3043
- if (((_d = (_c = this.options.overlayModel) === null || _c === void 0 ? void 0 : _c.size) === null || _d === void 0 ? void 0 : _d.type) === 'pixels') {
3268
+ else {
3044
3269
  if (rightClass || leftClass) {
3045
- size =
3046
- clamp(0, this.options.overlayModel.size.value, width) /
3047
- width;
3270
+ size = clamp(0, sizeOptions.value, width) / width;
3048
3271
  }
3049
3272
  if (topClass || bottomClass) {
3050
- size =
3051
- clamp(0, this.options.overlayModel.size.value, height) /
3052
- height;
3273
+ size = clamp(0, sizeOptions.value, height) / height;
3053
3274
  }
3054
3275
  }
3055
3276
  const translate = (1 - size) / 2;
@@ -3071,39 +3292,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3071
3292
  transform = '';
3072
3293
  }
3073
3294
  this.overlayElement.style.transform = transform;
3074
- toggleClass(this.overlayElement, 'small-right', isSmallX && isRight);
3075
- toggleClass(this.overlayElement, 'small-left', isSmallX && isLeft);
3076
- toggleClass(this.overlayElement, 'small-top', isSmallY && isTop);
3077
- toggleClass(this.overlayElement, 'small-bottom', isSmallY && isBottom);
3078
- }
3079
- setState(quadrant) {
3080
- switch (quadrant) {
3081
- case 'top':
3082
- this._state = 'top';
3083
- break;
3084
- case 'left':
3085
- this._state = 'left';
3086
- break;
3087
- case 'bottom':
3088
- this._state = 'bottom';
3089
- break;
3090
- case 'right':
3091
- this._state = 'right';
3092
- break;
3093
- case 'center':
3094
- this._state = 'center';
3095
- break;
3096
- }
3295
+ toggleClass(this.overlayElement, 'dv-drop-target-small-vertical', isSmallY);
3296
+ toggleClass(this.overlayElement, 'dv-drop-target-small-horizontal', isSmallX);
3297
+ toggleClass(this.overlayElement, 'dv-drop-target-left', isLeft);
3298
+ toggleClass(this.overlayElement, 'dv-drop-target-right', isRight);
3299
+ toggleClass(this.overlayElement, 'dv-drop-target-top', isTop);
3300
+ toggleClass(this.overlayElement, 'dv-drop-target-bottom', isBottom);
3301
+ toggleClass(this.overlayElement, 'dv-drop-target-center', quadrant === 'center');
3097
3302
  }
3098
3303
  calculateQuadrant(overlayType, x, y, width, height) {
3099
- var _a, _b, _c, _d, _e, _f;
3100
- const isPercentage = ((_a = this.options.overlayModel) === null || _a === void 0 ? void 0 : _a.activationSize) === undefined ||
3101
- ((_c = (_b = this.options.overlayModel) === null || _b === void 0 ? void 0 : _b.activationSize) === null || _c === void 0 ? void 0 : _c.type) === 'percentage';
3102
- const value = numberOrFallback((_f = (_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.overlayModel) === null || _e === void 0 ? void 0 : _e.activationSize) === null || _f === void 0 ? void 0 : _f.value, 20);
3304
+ var _a, _b;
3305
+ const activationSizeOptions = (_b = (_a = this.options.overlayModel) === null || _a === void 0 ? void 0 : _a.activationSize) !== null && _b !== void 0 ? _b : DEFAULT_ACTIVATION_SIZE;
3306
+ const isPercentage = activationSizeOptions.type === 'percentage';
3103
3307
  if (isPercentage) {
3104
- return calculateQuadrantAsPercentage(overlayType, x, y, width, height, value);
3308
+ return calculateQuadrantAsPercentage(overlayType, x, y, width, height, activationSizeOptions.value);
3105
3309
  }
3106
- return calculateQuadrantAsPixels(overlayType, x, y, width, height, value);
3310
+ return calculateQuadrantAsPixels(overlayType, x, y, width, height, activationSizeOptions.value);
3107
3311
  }
3108
3312
  removeDropTarget() {
3109
3313
  if (this.targetElement) {
@@ -3155,12 +3359,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3155
3359
  return 'center';
3156
3360
  }
3157
3361
 
3362
+ exports.DockviewDropTargets = void 0;
3363
+ (function (DockviewDropTargets) {
3364
+ DockviewDropTargets[DockviewDropTargets["Tab"] = 0] = "Tab";
3365
+ DockviewDropTargets[DockviewDropTargets["Panel"] = 1] = "Panel";
3366
+ DockviewDropTargets[DockviewDropTargets["TabContainer"] = 2] = "TabContainer";
3367
+ DockviewDropTargets[DockviewDropTargets["Edge"] = 3] = "Edge";
3368
+ })(exports.DockviewDropTargets || (exports.DockviewDropTargets = {}));
3369
+
3158
3370
  class ContentContainer extends CompositeDisposable {
3159
3371
  get element() {
3160
3372
  return this._element;
3161
3373
  }
3162
- constructor() {
3374
+ constructor(accessor, group) {
3163
3375
  super();
3376
+ this.accessor = accessor;
3377
+ this.group = group;
3164
3378
  this.disposable = new MutableDisposable();
3165
3379
  this._onDidFocus = new Emitter();
3166
3380
  this.onDidFocus = this._onDidFocus.event;
@@ -3170,11 +3384,38 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3170
3384
  this._element.className = 'content-container';
3171
3385
  this._element.tabIndex = -1;
3172
3386
  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)
3387
+ this.dropTarget = new Droptarget(this.element, {
3388
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
3389
+ canDisplayOverlay: (event, position) => {
3390
+ if (this.group.locked === 'no-drop-target' ||
3391
+ (this.group.locked && position === 'center')) {
3392
+ return false;
3393
+ }
3394
+ const data = getPanelData();
3395
+ if (!data &&
3396
+ event.shiftKey &&
3397
+ this.group.location !== 'floating') {
3398
+ return false;
3399
+ }
3400
+ if (data && data.viewId === this.accessor.id) {
3401
+ if (data.groupId === this.group.id) {
3402
+ if (position === 'center') {
3403
+ // don't allow to drop on self for center position
3404
+ return false;
3405
+ }
3406
+ if (data.panelId === null) {
3407
+ // don't allow group move to drop anywhere on self
3408
+ return false;
3409
+ }
3410
+ }
3411
+ const groupHasOnePanelAndIsActiveDragElement = this.group.panels.length === 1 &&
3412
+ data.groupId === this.group.id;
3413
+ return !groupHasOnePanelAndIsActiveDragElement;
3414
+ }
3415
+ return this.group.canDisplayOverlay(event, position, exports.DockviewDropTargets.Panel);
3416
+ },
3417
+ });
3418
+ this.addDisposables(this.dropTarget);
3178
3419
  }
3179
3420
  show() {
3180
3421
  this.element.style.display = '';
@@ -3182,23 +3423,43 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3182
3423
  hide() {
3183
3424
  this.element.style.display = 'none';
3184
3425
  }
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;
3426
+ renderPanel(panel, options = { asActive: true }) {
3427
+ const doRender = options.asActive ||
3428
+ (this.panel && this.group.isPanelActive(this.panel));
3429
+ if (this.panel &&
3430
+ this.panel.view.content.element.parentElement === this._element) {
3431
+ /**
3432
+ * If the currently attached panel is mounted directly to the content then remove it
3433
+ */
3434
+ this._element.removeChild(this.panel.view.content.element);
3195
3435
  }
3196
3436
  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);
3437
+ let container;
3438
+ switch (panel.api.renderer) {
3439
+ case 'onlyWhenVisibile':
3440
+ this.accessor.overlayRenderContainer.detatch(panel);
3441
+ if (this.panel) {
3442
+ if (doRender) {
3443
+ this._element.appendChild(this.panel.view.content.element);
3444
+ }
3445
+ }
3446
+ container = this._element;
3447
+ break;
3448
+ case 'always':
3449
+ if (panel.view.content.element.parentElement === this._element) {
3450
+ this._element.removeChild(panel.view.content.element);
3451
+ }
3452
+ container = this.accessor.overlayRenderContainer.attach({
3453
+ panel,
3454
+ referenceContainer: this,
3455
+ });
3456
+ break;
3457
+ }
3458
+ if (doRender) {
3459
+ const _onDidFocus = panel.view.content.onDidFocus;
3460
+ const _onDidBlur = panel.view.content.onDidBlur;
3461
+ const focusTracker = trackFocus(container);
3462
+ const disposable = new CompositeDisposable();
3202
3463
  disposable.addDisposables(focusTracker, focusTracker.onDidFocus(() => this._onDidFocus.fire()), focusTracker.onDidBlur(() => this._onDidBlur.fire()));
3203
3464
  if (_onDidFocus) {
3204
3465
  disposable.addDisposables(_onDidFocus(() => this._onDidFocus.fire()));
@@ -3206,17 +3467,23 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3206
3467
  if (_onDidBlur) {
3207
3468
  disposable.addDisposables(_onDidBlur(() => this._onDidBlur.fire()));
3208
3469
  }
3209
- this._element.appendChild(this.panel.view.content.element);
3470
+ this.disposable.value = disposable;
3210
3471
  }
3211
- this.disposable.value = disposable;
3472
+ }
3473
+ openPanel(panel) {
3474
+ if (this.panel === panel) {
3475
+ return;
3476
+ }
3477
+ this.renderPanel(panel);
3212
3478
  }
3213
3479
  layout(_width, _height) {
3214
3480
  // noop
3215
3481
  }
3216
3482
  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);
3483
+ if (this.panel) {
3484
+ if (this.accessor.options.defaultRenderer === 'onlyWhenVisibile') {
3485
+ this._element.removeChild(this.panel.view.content.element);
3486
+ }
3220
3487
  this.panel = undefined;
3221
3488
  }
3222
3489
  }
@@ -3226,14 +3493,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3226
3493
  }
3227
3494
  }
3228
3495
 
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
3496
  class DragHandler extends CompositeDisposable {
3238
3497
  constructor(el) {
3239
3498
  super();
@@ -3408,7 +3667,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3408
3667
  }, true));
3409
3668
  }
3410
3669
  isCancelled(_event) {
3411
- if (this.group.api.isFloating && !_event.shiftKey) {
3670
+ if (this.group.api.location === 'floating' && !_event.shiftKey) {
3412
3671
  return true;
3413
3672
  }
3414
3673
  return false;
@@ -3610,7 +3869,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3610
3869
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3611
3870
  if (isFloatingGroupsEnabled &&
3612
3871
  event.shiftKey &&
3613
- !this.group.api.isFloating) {
3872
+ this.group.api.location !== 'floating') {
3614
3873
  event.preventDefault();
3615
3874
  const { top, left } = this.element.getBoundingClientRect();
3616
3875
  const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
@@ -3675,7 +3934,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3675
3934
  }), tab.onChanged((event) => {
3676
3935
  var _a;
3677
3936
  const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
3678
- const isFloatingWithOnePanel = this.group.api.isFloating && this.size === 1;
3937
+ const isFloatingWithOnePanel = this.group.api.location === 'floating' && this.size === 1;
3679
3938
  if (isFloatingGroupsEnabled &&
3680
3939
  !isFloatingWithOnePanel &&
3681
3940
  event.shiftKey) {
@@ -3758,15 +4017,37 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3758
4017
  }
3759
4018
  return isAncestor(document.activeElement, this.contentContainer.element);
3760
4019
  }
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,
4020
+ get location() {
4021
+ return this._location;
4022
+ }
4023
+ set location(value) {
4024
+ this._location = value;
4025
+ toggleClass(this.container, 'dv-groupview-floating', false);
4026
+ toggleClass(this.container, 'dv-groupview-popout', false);
4027
+ switch (value) {
4028
+ case 'grid':
4029
+ this.contentContainer.dropTarget.setTargetZones([
4030
+ 'top',
4031
+ 'bottom',
4032
+ 'left',
4033
+ 'right',
4034
+ 'center',
4035
+ ]);
4036
+ break;
4037
+ case 'floating':
4038
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4039
+ this.contentContainer.dropTarget.setTargetZones(value
4040
+ ? ['center']
4041
+ : ['top', 'bottom', 'left', 'right', 'center']);
4042
+ toggleClass(this.container, 'dv-groupview-floating', true);
4043
+ break;
4044
+ case 'popout':
4045
+ this.contentContainer.dropTarget.setTargetZones(['center']);
4046
+ toggleClass(this.container, 'dv-groupview-popout', true);
4047
+ break;
4048
+ }
4049
+ this.groupPanel.api._onDidLocationChange.fire({
4050
+ location: this.location,
3770
4051
  });
3771
4052
  }
3772
4053
  constructor(container, accessor, id, options, groupPanel) {
@@ -3779,7 +4060,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3779
4060
  this.groupPanel = groupPanel;
3780
4061
  this._isGroupActive = false;
3781
4062
  this._locked = false;
3782
- this._isFloating = false;
4063
+ this._location = 'grid';
3783
4064
  this.mostRecentlyUsed = [];
3784
4065
  this._onDidChange = new Emitter();
3785
4066
  this.onDidChange = this._onDidChange.event;
@@ -3802,35 +4083,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3802
4083
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
3803
4084
  toggleClass(this.container, 'groupview', true);
3804
4085
  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
- });
4086
+ this.contentContainer = new ContentContainer(this.accessor, this);
3834
4087
  container.append(this.tabsContainer.element, this.contentContainer.element);
3835
4088
  this.header.hidden = !!options.hideHeader;
3836
4089
  this.locked = (_a = options.locked) !== null && _a !== void 0 ? _a : false;
@@ -3844,7 +4097,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3844
4097
  this.accessor.doSetGroupActive(this.groupPanel, true);
3845
4098
  }), this.contentContainer.onDidBlur(() => {
3846
4099
  // noop
3847
- }), this.dropTarget.onDrop((event) => {
4100
+ }), this.contentContainer.dropTarget.onDrop((event) => {
3848
4101
  this.handleDropEvent(event.nativeEvent, event.position);
3849
4102
  }), this._onMove, this._onDidChange, this._onDidDrop, this._onDidAddPanel, this._onDidRemovePanel, this._onDidActivePanelChange);
3850
4103
  }
@@ -3893,6 +4146,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3893
4146
  this.tabsContainer.setPrefixActionsElement(this._prefixHeaderActions.element);
3894
4147
  }
3895
4148
  }
4149
+ rerender(panel) {
4150
+ this.contentContainer.renderPanel(panel, { asActive: false });
4151
+ }
3896
4152
  indexOf(panel) {
3897
4153
  return this.tabsContainer.indexOf(panel.id);
3898
4154
  }
@@ -4084,12 +4340,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4084
4340
  doAddPanel(panel, index = this.panels.length, skipSetActive = false) {
4085
4341
  const existingPanel = this._panels.indexOf(panel);
4086
4342
  const hasExistingPanel = existingPanel > -1;
4343
+ this.tabsContainer.show();
4344
+ this.contentContainer.show();
4087
4345
  this.tabsContainer.openPanel(panel, index);
4088
4346
  if (!skipSetActive) {
4089
4347
  this.contentContainer.openPanel(panel);
4090
4348
  }
4091
- this.tabsContainer.show();
4092
- this.contentContainer.show();
4093
4349
  if (hasExistingPanel) {
4094
4350
  // TODO - need to ensure ordering hasn't changed and if it has need to re-order this.panels
4095
4351
  return;
@@ -4205,7 +4461,6 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4205
4461
  for (const panel of this.panels) {
4206
4462
  panel.dispose();
4207
4463
  }
4208
- this.dropTarget.dispose();
4209
4464
  this.tabsContainer.dispose();
4210
4465
  this.contentContainer.dispose();
4211
4466
  }
@@ -4244,7 +4499,22 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4244
4499
  if (this.disableResizing) {
4245
4500
  return;
4246
4501
  }
4247
- if (!document.body.contains(this._element)) {
4502
+ if (!this._element.offsetParent) {
4503
+ /**
4504
+ * offsetParent === null is equivalent to display: none being set on the element or one
4505
+ * of it's parents. In the display: none case the size will become (0, 0) which we do
4506
+ * not want to propagate.
4507
+ *
4508
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent
4509
+ *
4510
+ * You could use checkVisibility() but at the time of writing it's not supported across
4511
+ * all Browsers
4512
+ *
4513
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility
4514
+ */
4515
+ return;
4516
+ }
4517
+ if (!isInDocument(this._element)) {
4248
4518
  /**
4249
4519
  * since the event is dispatched through requestAnimationFrame there is a small chance
4250
4520
  * the component is no longer attached to the DOM, if that is the case the dimensions
@@ -4336,6 +4606,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
4336
4606
  isVisible(panel) {
4337
4607
  return this.gridview.isViewVisible(getGridLocation(panel.element));
4338
4608
  }
4609
+ maximizeGroup(panel) {
4610
+ this.gridview.maximizeView(panel);
4611
+ }
4612
+ isMaximizedGroup(panel) {
4613
+ return this.gridview.maximizedView() === panel;
4614
+ }
4615
+ exitMaximizedGroup() {
4616
+ this.gridview.exitMaximizedView();
4617
+ }
4618
+ hasMaximizedGroup() {
4619
+ return this.gridview.hasMaximizedView();
4620
+ }
4621
+ get onDidMaxmizedGroupChange() {
4622
+ return this.gridview.onDidMaxmizedNodeChange;
4623
+ }
4339
4624
  doAddGroup(group, location = [0], size) {
4340
4625
  this.gridview.addView(group, size !== null && size !== void 0 ? size : exports.Sizing.Distribute, location);
4341
4626
  this._onDidAddGroup.fire(group);
@@ -5112,32 +5397,63 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5112
5397
  }
5113
5398
  }
5114
5399
 
5400
+ // TODO find a better way to initialize and avoid needing null checks
5401
+ const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
5115
5402
  class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
5116
- get isFloating() {
5403
+ get location() {
5117
5404
  if (!this._group) {
5118
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5405
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5119
5406
  }
5120
- return this._group.model.isFloating;
5407
+ return this._group.model.location;
5121
5408
  }
5122
5409
  constructor(id, accessor) {
5123
5410
  super(id);
5124
5411
  this.accessor = accessor;
5125
- this._onDidFloatingStateChange = new Emitter();
5126
- this.onDidFloatingStateChange = this._onDidFloatingStateChange.event;
5127
- this.addDisposables(this._onDidFloatingStateChange);
5412
+ this._onDidLocationChange = new Emitter();
5413
+ this.onDidLocationChange = this._onDidLocationChange.event;
5414
+ this.addDisposables(this._onDidLocationChange);
5128
5415
  }
5129
5416
  moveTo(options) {
5130
- var _a;
5417
+ var _a, _b, _c;
5418
+ if (!this._group) {
5419
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5420
+ }
5421
+ const group = (_a = options.group) !== null && _a !== void 0 ? _a : this.accessor.addGroup({
5422
+ direction: positionToDirection((_b = options.position) !== null && _b !== void 0 ? _b : 'right'),
5423
+ });
5424
+ this.accessor.moveGroupOrPanel(group, this._group.id, undefined, options.group ? (_c = options.position) !== null && _c !== void 0 ? _c : 'center' : 'center');
5425
+ }
5426
+ maximize() {
5427
+ if (!this._group) {
5428
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5429
+ }
5430
+ if (this.location !== 'grid') {
5431
+ // only grid groups can be maximized
5432
+ return;
5433
+ }
5434
+ this.accessor.maximizeGroup(this._group);
5435
+ }
5436
+ isMaximized() {
5131
5437
  if (!this._group) {
5132
- throw new Error(`DockviewGroupPanelApiImpl not initialized`);
5438
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5439
+ }
5440
+ return this.accessor.isMaximizedGroup(this._group);
5441
+ }
5442
+ exitMaximized() {
5443
+ if (!this._group) {
5444
+ throw new Error(NOT_INITIALIZED_MESSAGE);
5445
+ }
5446
+ if (this.isMaximized()) {
5447
+ this.accessor.exitMaximizedGroup();
5133
5448
  }
5134
- this.accessor.moveGroupOrPanel(options.group, this._group.id, undefined, (_a = options.position) !== null && _a !== void 0 ? _a : 'center');
5135
5449
  }
5136
5450
  initialize(group) {
5137
5451
  this._group = group;
5138
5452
  }
5139
5453
  }
5140
5454
 
5455
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH = 100;
5456
+ const MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT = 100;
5141
5457
  class DockviewGroupPanel extends GridviewPanel {
5142
5458
  get panels() {
5143
5459
  return this._model.panels;
@@ -5162,8 +5478,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5162
5478
  }
5163
5479
  constructor(accessor, id, options) {
5164
5480
  super(id, 'groupview_default', {
5165
- minimumHeight: 100,
5166
- minimumWidth: 100,
5481
+ minimumHeight: MINIMUM_DOCKVIEW_GROUP_PANEL_HEIGHT,
5482
+ minimumWidth: MINIMUM_DOCKVIEW_GROUP_PANEL_WIDTH,
5167
5483
  }, new DockviewGroupPanelApiImpl(id, accessor));
5168
5484
  this.api.initialize(this); // cannot use 'this' after after 'super' call
5169
5485
  this._model = new DockviewGroupPanelModel(this.element, accessor, id, options, this);
@@ -5217,8 +5533,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5217
5533
  return this.panel.title;
5218
5534
  }
5219
5535
  get isGroupActive() {
5220
- var _a;
5221
- return !!((_a = this.group) === null || _a === void 0 ? void 0 : _a.isActive);
5536
+ return this.group.isActive;
5537
+ }
5538
+ get renderer() {
5539
+ return this.panel.renderer;
5222
5540
  }
5223
5541
  set group(value) {
5224
5542
  const isOldGroupActive = this.isGroupActive;
@@ -5246,10 +5564,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5246
5564
  this.onDidActiveGroupChange = this._onDidActiveGroupChange.event;
5247
5565
  this._onDidGroupChange = new Emitter();
5248
5566
  this.onDidGroupChange = this._onDidGroupChange.event;
5567
+ this._onDidRendererChange = new Emitter();
5568
+ this.onDidRendererChange = this._onDidRendererChange.event;
5249
5569
  this.disposable = new MutableDisposable();
5250
5570
  this.initialize(panel);
5251
5571
  this._group = group;
5252
- this.addDisposables(this.disposable, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5572
+ this.addDisposables(this.disposable, this._onDidRendererChange, this._onDidTitleChange, this._onDidGroupChange, this._onDidActiveGroupChange);
5253
5573
  }
5254
5574
  moveTo(options) {
5255
5575
  var _a;
@@ -5258,9 +5578,21 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5258
5578
  setTitle(title) {
5259
5579
  this.panel.setTitle(title);
5260
5580
  }
5581
+ setRenderer(renderer) {
5582
+ this.panel.setRenderer(renderer);
5583
+ }
5261
5584
  close() {
5262
5585
  this.group.model.closePanel(this.panel);
5263
5586
  }
5587
+ maximize() {
5588
+ this.group.api.maximize();
5589
+ }
5590
+ isMaximized() {
5591
+ return this.group.api.isMaximized();
5592
+ }
5593
+ exitMaximized() {
5594
+ this.group.api.exitMaximized();
5595
+ }
5264
5596
  }
5265
5597
 
5266
5598
  class DockviewPanel extends CompositeDisposable {
@@ -5273,11 +5605,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5273
5605
  get group() {
5274
5606
  return this._group;
5275
5607
  }
5276
- constructor(id, accessor, containerApi, group, view) {
5608
+ get renderer() {
5609
+ var _a;
5610
+ return (_a = this._renderer) !== null && _a !== void 0 ? _a : this.accessor.renderer;
5611
+ }
5612
+ constructor(id, accessor, containerApi, group, view, options) {
5277
5613
  super();
5278
5614
  this.id = id;
5615
+ this.accessor = accessor;
5279
5616
  this.containerApi = containerApi;
5280
5617
  this.view = view;
5618
+ this._renderer = options.renderer;
5281
5619
  this._group = group;
5282
5620
  this.api = new DockviewPanelApiImpl(this, this._group, accessor);
5283
5621
  this.addDisposables(this.api.onActiveChange(() => {
@@ -5286,6 +5624,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5286
5624
  // forward the resize event to the group since if you want to resize a panel
5287
5625
  // you are actually just resizing the panels parent which is the group
5288
5626
  this.group.api.setSize(event);
5627
+ }), this.api.onDidRendererChange((event) => {
5628
+ this.group.model.rerender(this);
5289
5629
  }));
5290
5630
  }
5291
5631
  init(params) {
@@ -5305,6 +5645,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5305
5645
  ? this._params
5306
5646
  : undefined,
5307
5647
  title: this.title,
5648
+ renderer: this._renderer,
5308
5649
  };
5309
5650
  }
5310
5651
  setTitle(title) {
@@ -5320,6 +5661,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5320
5661
  this.api._onDidTitleChange.fire({ title });
5321
5662
  }
5322
5663
  }
5664
+ setRenderer(renderer) {
5665
+ const didChange = renderer !== this.renderer;
5666
+ if (didChange) {
5667
+ this._renderer = renderer;
5668
+ this.api._onDidRendererChange.fire({
5669
+ renderer: renderer,
5670
+ });
5671
+ }
5672
+ }
5323
5673
  update(event) {
5324
5674
  var _a;
5325
5675
  // merge the new parameters with the existing parameters
@@ -5538,8 +5888,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5538
5888
  }
5539
5889
 
5540
5890
  class DefaultDockviewDeserialzier {
5541
- constructor(layout) {
5542
- this.layout = layout;
5891
+ constructor(accessor) {
5892
+ this.accessor = accessor;
5543
5893
  }
5544
5894
  fromJSON(panelData, group) {
5545
5895
  var _a, _b;
@@ -5553,8 +5903,10 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5553
5903
  const tabComponent = viewData
5554
5904
  ? (_b = viewData.tab) === null || _b === void 0 ? void 0 : _b.id
5555
5905
  : 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);
5906
+ const view = new DockviewPanelModel(this.accessor, panelId, contentComponent, tabComponent);
5907
+ const panel = new DockviewPanel(panelId, this.accessor, new DockviewApi(this.accessor), group, view, {
5908
+ renderer: panelData.renderer,
5909
+ });
5558
5910
  panel.init({
5559
5911
  title: title !== null && title !== void 0 ? title : panelId,
5560
5912
  params: params !== null && params !== void 0 ? params : {},
@@ -5934,7 +6286,265 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5934
6286
  }
5935
6287
  }
5936
6288
 
6289
+ class PopoutWindow extends CompositeDisposable {
6290
+ constructor(id, className, options) {
6291
+ super();
6292
+ this.id = id;
6293
+ this.className = className;
6294
+ this.options = options;
6295
+ this._onDidClose = new Emitter();
6296
+ this.onDidClose = this._onDidClose.event;
6297
+ this._window = null;
6298
+ this.addDisposables(this._onDidClose, {
6299
+ dispose: () => {
6300
+ this.close();
6301
+ },
6302
+ });
6303
+ }
6304
+ dimensions() {
6305
+ if (!this._window) {
6306
+ return null;
6307
+ }
6308
+ const left = this._window.value.screenX;
6309
+ const top = this._window.value.screenY;
6310
+ const width = this._window.value.innerWidth;
6311
+ const height = this._window.value.innerHeight;
6312
+ return { top, left, width, height };
6313
+ }
6314
+ close() {
6315
+ if (this._window) {
6316
+ this._window.disposable.dispose();
6317
+ this._window.value.close();
6318
+ this._window = null;
6319
+ }
6320
+ }
6321
+ open(content) {
6322
+ if (this._window) {
6323
+ throw new Error('instance of popout window is already open');
6324
+ }
6325
+ const url = `${this.options.url}`;
6326
+ const features = Object.entries({
6327
+ top: this.options.top,
6328
+ left: this.options.left,
6329
+ width: this.options.width,
6330
+ height: this.options.height,
6331
+ })
6332
+ .map(([key, value]) => `${key}=${value}`)
6333
+ .join(',');
6334
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/open
6335
+ const externalWindow = window.open(url, this.id, features);
6336
+ if (!externalWindow) {
6337
+ return;
6338
+ }
6339
+ const disposable = new CompositeDisposable();
6340
+ this._window = { value: externalWindow, disposable };
6341
+ const cleanUp = () => {
6342
+ this._onDidClose.fire();
6343
+ this._window = null;
6344
+ };
6345
+ // prevent any default content from loading
6346
+ // externalWindow.document.body.replaceWith(document.createElement('div'));
6347
+ disposable.addDisposables(addDisposableWindowListener(window, 'beforeunload', () => {
6348
+ cleanUp();
6349
+ this.close();
6350
+ }));
6351
+ externalWindow.addEventListener('load', () => {
6352
+ const externalDocument = externalWindow.document;
6353
+ externalDocument.title = document.title;
6354
+ const div = document.createElement('div');
6355
+ div.classList.add('dv-popout-window');
6356
+ div.style.position = 'absolute';
6357
+ div.style.width = '100%';
6358
+ div.style.height = '100%';
6359
+ div.style.top = '0px';
6360
+ div.style.left = '0px';
6361
+ div.classList.add(this.className);
6362
+ div.appendChild(content);
6363
+ externalDocument.body.replaceChildren(div);
6364
+ externalDocument.body.classList.add(this.className);
6365
+ addStyles(externalDocument, window.document.styleSheets);
6366
+ externalWindow.addEventListener('beforeunload', () => {
6367
+ // TODO: indicate external window is closing
6368
+ cleanUp();
6369
+ });
6370
+ });
6371
+ }
6372
+ }
6373
+
6374
+ class DockviewPopoutGroupPanel extends CompositeDisposable {
6375
+ constructor(id, group, options) {
6376
+ var _a;
6377
+ super();
6378
+ this.id = id;
6379
+ this.group = group;
6380
+ this.options = options;
6381
+ this.window = new PopoutWindow(id, (_a = options.className) !== null && _a !== void 0 ? _a : '', {
6382
+ url: this.options.popoutUrl,
6383
+ left: this.options.box.left,
6384
+ top: this.options.box.top,
6385
+ width: this.options.box.width,
6386
+ height: this.options.box.height,
6387
+ });
6388
+ group.model.location = 'popout';
6389
+ this.addDisposables(this.window, {
6390
+ dispose: () => {
6391
+ group.model.location = 'grid';
6392
+ },
6393
+ }, this.window.onDidClose(() => {
6394
+ this.dispose();
6395
+ }));
6396
+ this.window.open(group.element);
6397
+ }
6398
+ }
6399
+
5937
6400
  const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100;
6401
+ const DEFAULT_FLOATING_GROUP_POSITION = { left: 100, top: 100 };
6402
+
6403
+ function createFocusableElement() {
6404
+ const element = document.createElement('div');
6405
+ element.tabIndex = -1;
6406
+ return element;
6407
+ }
6408
+ class OverlayRenderContainer extends CompositeDisposable {
6409
+ constructor(element) {
6410
+ super();
6411
+ this.element = element;
6412
+ this.map = {};
6413
+ this.addDisposables(Disposable.from(() => {
6414
+ for (const value of Object.values(this.map)) {
6415
+ value.disposable.dispose();
6416
+ value.destroy.dispose();
6417
+ }
6418
+ }));
6419
+ }
6420
+ detatch(panel) {
6421
+ if (this.map[panel.api.id]) {
6422
+ const { disposable, destroy } = this.map[panel.api.id];
6423
+ disposable.dispose();
6424
+ destroy.dispose();
6425
+ delete this.map[panel.api.id];
6426
+ return true;
6427
+ }
6428
+ return false;
6429
+ }
6430
+ attach(options) {
6431
+ const { panel, referenceContainer } = options;
6432
+ if (!this.map[panel.api.id]) {
6433
+ const element = createFocusableElement();
6434
+ element.className = 'dv-render-overlay';
6435
+ this.map[panel.api.id] = {
6436
+ panel,
6437
+ disposable: Disposable.NONE,
6438
+ destroy: Disposable.NONE,
6439
+ element,
6440
+ };
6441
+ }
6442
+ const focusContainer = this.map[panel.api.id].element;
6443
+ if (panel.view.content.element.parentElement !== focusContainer) {
6444
+ focusContainer.appendChild(panel.view.content.element);
6445
+ }
6446
+ if (focusContainer.parentElement !== this.element) {
6447
+ this.element.appendChild(focusContainer);
6448
+ }
6449
+ const resize = () => {
6450
+ // TODO propagate position to avoid getDomNodePagePosition calls, possible performance bottleneck?
6451
+ const box = getDomNodePagePosition(referenceContainer.element);
6452
+ const box2 = getDomNodePagePosition(this.element);
6453
+ focusContainer.style.left = `${box.left - box2.left}px`;
6454
+ focusContainer.style.top = `${box.top - box2.top}px`;
6455
+ focusContainer.style.width = `${box.width}px`;
6456
+ focusContainer.style.height = `${box.height}px`;
6457
+ toggleClass(focusContainer, 'dv-render-overlay-float', panel.group.api.location === 'floating');
6458
+ };
6459
+ const visibilityChanged = () => {
6460
+ if (panel.api.isVisible) {
6461
+ resize();
6462
+ }
6463
+ focusContainer.style.display = panel.api.isVisible ? '' : 'none';
6464
+ };
6465
+ const disposable = new CompositeDisposable(
6466
+ /**
6467
+ * since container is positioned absoutely we must explicitly forward
6468
+ * the dnd events for the expect behaviours to continue to occur in terms of dnd
6469
+ *
6470
+ * the dnd observer does not need to be conditional on whether the panel is visible since
6471
+ * non-visible panels are 'display: none' and in such case the dnd observer will not fire.
6472
+ */
6473
+ new DragAndDropObserver(focusContainer, {
6474
+ onDragEnd: (e) => {
6475
+ referenceContainer.dropTarget.dnd.onDragEnd(e);
6476
+ },
6477
+ onDragEnter: (e) => {
6478
+ referenceContainer.dropTarget.dnd.onDragEnter(e);
6479
+ },
6480
+ onDragLeave: (e) => {
6481
+ referenceContainer.dropTarget.dnd.onDragLeave(e);
6482
+ },
6483
+ onDrop: (e) => {
6484
+ referenceContainer.dropTarget.dnd.onDrop(e);
6485
+ },
6486
+ onDragOver: (e) => {
6487
+ referenceContainer.dropTarget.dnd.onDragOver(e);
6488
+ },
6489
+ }), panel.api.onDidVisibilityChange((event) => {
6490
+ /**
6491
+ * Control the visibility of the content, however even when not visible (display: none)
6492
+ * the content is still maintained within the DOM hence DOM specific attributes
6493
+ * such as scroll position are maintained when next made visible.
6494
+ */
6495
+ visibilityChanged();
6496
+ }), panel.api.onDidDimensionsChange(() => {
6497
+ if (!panel.api.isVisible) {
6498
+ return;
6499
+ }
6500
+ resize();
6501
+ }));
6502
+ this.map[panel.api.id].destroy = Disposable.from(() => {
6503
+ focusContainer.removeChild(panel.view.content.element);
6504
+ this.element.removeChild(focusContainer);
6505
+ });
6506
+ queueMicrotask(() => {
6507
+ if (this.isDisposed) {
6508
+ return;
6509
+ }
6510
+ /**
6511
+ * wait until everything has finished in the current stack-frame call before
6512
+ * calling the first resize as other size-altering events may still occur before
6513
+ * the end of the stack-frame.
6514
+ */
6515
+ visibilityChanged();
6516
+ });
6517
+ // dispose of logic asoccciated with previous reference-container
6518
+ this.map[panel.api.id].disposable.dispose();
6519
+ // and reset the disposable to the active reference-container
6520
+ this.map[panel.api.id].disposable = disposable;
6521
+ return focusContainer;
6522
+ }
6523
+ }
6524
+
6525
+ const DEFAULT_ROOT_OVERLAY_MODEL = {
6526
+ activationSize: { type: 'pixels', value: 10 },
6527
+ size: { type: 'pixels', value: 20 },
6528
+ };
6529
+ function getTheme(element) {
6530
+ function toClassList(element) {
6531
+ const list = [];
6532
+ for (let i = 0; i < element.classList.length; i++) {
6533
+ list.push(element.classList.item(i));
6534
+ }
6535
+ return list;
6536
+ }
6537
+ let theme = undefined;
6538
+ let parent = element;
6539
+ while (parent !== null) {
6540
+ theme = toClassList(parent).find((cls) => cls.startsWith('dockview-theme-'));
6541
+ if (typeof theme === 'string') {
6542
+ break;
6543
+ }
6544
+ parent = parent.parentElement;
6545
+ }
6546
+ return theme;
6547
+ }
5938
6548
  class DockviewComponent extends BaseGrid {
5939
6549
  get orientation() {
5940
6550
  return this.gridview.orientation;
@@ -5955,8 +6565,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5955
6565
  }
5956
6566
  return activeGroup.activePanel;
5957
6567
  }
5958
- constructor(options) {
6568
+ get renderer() {
5959
6569
  var _a;
6570
+ return (_a = this.options.defaultRenderer) !== null && _a !== void 0 ? _a : 'onlyWhenVisibile';
6571
+ }
6572
+ constructor(options) {
6573
+ var _a, _b;
5960
6574
  super({
5961
6575
  proportionalLayout: true,
5962
6576
  orientation: (_a = options.orientation) !== null && _a !== void 0 ? _a : exports.Orientation.HORIZONTAL,
@@ -5981,12 +6595,27 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5981
6595
  this.onDidLayoutFromJSON = this._onDidLayoutFromJSON.event;
5982
6596
  this._onDidActivePanelChange = new Emitter();
5983
6597
  this.onDidActivePanelChange = this._onDidActivePanelChange.event;
5984
- this.floatingGroups = [];
6598
+ this._floatingGroups = [];
6599
+ this._popoutGroups = [];
6600
+ const gready = document.createElement('div');
6601
+ gready.className = 'dv-overlay-render-container';
6602
+ this.gridview.element.appendChild(gready);
6603
+ this.overlayRenderContainer = new OverlayRenderContainer(gready);
5985
6604
  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)(() => {
6605
+ toggleClass(this.element, 'dv-debug', !!options.debug);
6606
+ 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
6607
  this.updateWatermark();
5988
6608
  }), exports.DockviewEvent.any(this.onDidAddPanel, this.onDidRemovePanel, this.onDidActivePanelChange)(() => {
5989
6609
  this._bufferOnDidLayoutChange.fire();
6610
+ }), Disposable.from(() => {
6611
+ // iterate over a copy of the array since .dispose() mutates the original array
6612
+ for (const group of [...this._floatingGroups]) {
6613
+ group.dispose();
6614
+ }
6615
+ // iterate over a copy of the array since .dispose() mutates the original array
6616
+ for (const group of [...this._popoutGroups]) {
6617
+ group.dispose();
6618
+ }
5990
6619
  }));
5991
6620
  this._options = options;
5992
6621
  if (!this.options.components) {
@@ -6005,7 +6634,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6005
6634
  !this.options.watermarkFrameworkComponent) {
6006
6635
  this.options.watermarkComponent = Watermark;
6007
6636
  }
6008
- const dropTarget = new Droptarget(this.element, {
6637
+ this._rootDropTarget = new Droptarget(this.element, {
6009
6638
  canDisplayOverlay: (event, position) => {
6010
6639
  const data = getPanelData();
6011
6640
  if (data) {
@@ -6038,12 +6667,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6038
6667
  return false;
6039
6668
  },
6040
6669
  acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
6041
- overlayModel: {
6042
- activationSize: { type: 'pixels', value: 10 },
6043
- size: { type: 'pixels', value: 20 },
6044
- },
6670
+ overlayModel: (_b = this.options.rootOverlayModel) !== null && _b !== void 0 ? _b : DEFAULT_ROOT_OVERLAY_MODEL,
6045
6671
  });
6046
- this.addDisposables(dropTarget.onDrop((event) => {
6672
+ this.addDisposables(this._rootDropTarget.onDrop((event) => {
6047
6673
  var _a;
6048
6674
  const data = getPanelData();
6049
6675
  if (data) {
@@ -6052,10 +6678,59 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6052
6678
  else {
6053
6679
  this._onDidDrop.fire(Object.assign(Object.assign({}, event), { api: this._api, group: null, getData: getPanelData }));
6054
6680
  }
6055
- }), dropTarget);
6681
+ }), this._rootDropTarget);
6056
6682
  this._api = new DockviewApi(this);
6057
6683
  this.updateWatermark();
6058
6684
  }
6685
+ addPopoutGroup(item, options) {
6686
+ var _a;
6687
+ let group;
6688
+ let box = options === null || options === void 0 ? void 0 : options.position;
6689
+ if (item instanceof DockviewPanel) {
6690
+ group = this.createGroup();
6691
+ this.removePanel(item, {
6692
+ removeEmptyGroup: true,
6693
+ skipDispose: true,
6694
+ });
6695
+ group.model.openPanel(item);
6696
+ if (!box) {
6697
+ box = this.element.getBoundingClientRect();
6698
+ }
6699
+ }
6700
+ else {
6701
+ group = item;
6702
+ if (!box) {
6703
+ box = group.element.getBoundingClientRect();
6704
+ }
6705
+ const skip = typeof (options === null || options === void 0 ? void 0 : options.skipRemoveGroup) === 'boolean' &&
6706
+ options.skipRemoveGroup;
6707
+ if (!skip) {
6708
+ this.doRemoveGroup(item, { skipDispose: true });
6709
+ }
6710
+ }
6711
+ const theme = getTheme(this.gridview.element);
6712
+ const popoutWindow = new DockviewPopoutGroupPanel(`${this.id}-${group.id}`, // globally unique within dockview
6713
+ group, {
6714
+ className: theme !== null && theme !== void 0 ? theme : '',
6715
+ popoutUrl: (_a = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _a !== void 0 ? _a : '/popout.html',
6716
+ box: {
6717
+ left: window.screenX + box.left,
6718
+ top: window.screenY + box.top,
6719
+ width: box.width,
6720
+ height: box.height,
6721
+ },
6722
+ });
6723
+ popoutWindow.addDisposables({
6724
+ dispose: () => {
6725
+ remove(this._popoutGroups, popoutWindow);
6726
+ this.updateWatermark();
6727
+ },
6728
+ }, popoutWindow.window.onDidClose(() => {
6729
+ this.doAddGroup(group, [0]);
6730
+ }));
6731
+ this._popoutGroups.push(popoutWindow);
6732
+ this.updateWatermark();
6733
+ }
6059
6734
  addFloatingGroup(item, coord, options) {
6060
6735
  var _a, _b, _c, _d, _e, _f;
6061
6736
  let group;
@@ -6075,9 +6750,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6075
6750
  this.doRemoveGroup(item, { skipDispose: true });
6076
6751
  }
6077
6752
  }
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;
6753
+ group.model.location = 'floating';
6754
+ const overlayLeft = typeof (coord === null || coord === void 0 ? void 0 : coord.x) === 'number'
6755
+ ? Math.max(coord.x, 0)
6756
+ : DEFAULT_FLOATING_GROUP_POSITION.left;
6757
+ const overlayTop = typeof (coord === null || coord === void 0 ? void 0 : coord.y) === 'number'
6758
+ ? Math.max(coord.y, 0)
6759
+ : DEFAULT_FLOATING_GROUP_POSITION.top;
6081
6760
  const overlay = new Overlay({
6082
6761
  container: this.gridview.element,
6083
6762
  content: group.element,
@@ -6121,12 +6800,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6121
6800
  }), {
6122
6801
  dispose: () => {
6123
6802
  disposable.dispose();
6124
- group.model.isFloating = false;
6125
- remove(this.floatingGroups, floatingGroupPanel);
6803
+ group.model.location = 'grid';
6804
+ remove(this._floatingGroups, floatingGroupPanel);
6126
6805
  this.updateWatermark();
6127
6806
  },
6128
6807
  });
6129
- this.floatingGroups.push(floatingGroupPanel);
6808
+ this._floatingGroups.push(floatingGroupPanel);
6130
6809
  this.updateWatermark();
6131
6810
  }
6132
6811
  orthogonalize(position) {
@@ -6162,16 +6841,18 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6162
6841
  }
6163
6842
  updateOptions(options) {
6164
6843
  var _a, _b;
6165
- const hasOrientationChanged = typeof options.orientation === 'string' &&
6844
+ const changed_orientation = typeof options.orientation === 'string' &&
6166
6845
  this.gridview.orientation !== options.orientation;
6167
- const hasFloatingGroupOptionsChanged = options.floatingGroupBounds !== undefined &&
6846
+ const changed_floatingGroupBounds = options.floatingGroupBounds !== undefined &&
6168
6847
  options.floatingGroupBounds !== this.options.floatingGroupBounds;
6848
+ const changed_rootOverlayOptions = options.rootOverlayModel !== undefined &&
6849
+ options.rootOverlayModel !== this.options.rootOverlayModel;
6169
6850
  this._options = Object.assign(Object.assign({}, this.options), options);
6170
- if (hasOrientationChanged) {
6851
+ if (changed_orientation) {
6171
6852
  this.gridview.orientation = options.orientation;
6172
6853
  }
6173
- if (hasFloatingGroupOptionsChanged) {
6174
- for (const group of this.floatingGroups) {
6854
+ if (changed_floatingGroupBounds) {
6855
+ for (const group of this._floatingGroups) {
6175
6856
  switch (this.options.floatingGroupBounds) {
6176
6857
  case 'boundedWithinViewport':
6177
6858
  group.overlay.minimumInViewportHeight = undefined;
@@ -6192,12 +6873,15 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6192
6873
  group.overlay.setBounds({});
6193
6874
  }
6194
6875
  }
6876
+ if (changed_rootOverlayOptions) {
6877
+ this._rootDropTarget.setOverlayModel(options.rootOverlayModel);
6878
+ }
6195
6879
  this.layout(this.gridview.width, this.gridview.height, true);
6196
6880
  }
6197
6881
  layout(width, height, forceResize) {
6198
6882
  super.layout(width, height, forceResize);
6199
- if (this.floatingGroups) {
6200
- for (const floating of this.floatingGroups) {
6883
+ if (this._floatingGroups) {
6884
+ for (const floating of this._floatingGroups) {
6201
6885
  // ensure floting groups stay within visible boundaries
6202
6886
  floating.overlay.setBounds();
6203
6887
  }
@@ -6265,10 +6949,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6265
6949
  collection[panel.id] = panel.toJSON();
6266
6950
  return collection;
6267
6951
  }, {});
6268
- const floats = this.floatingGroups.map((floatingGroup) => {
6952
+ const floats = this._floatingGroups.map((group) => {
6269
6953
  return {
6270
- data: floatingGroup.group.toJSON(),
6271
- position: floatingGroup.overlay.toJSON(),
6954
+ data: group.group.toJSON(),
6955
+ position: group.overlay.toJSON(),
6956
+ };
6957
+ });
6958
+ const popoutGroups = this._popoutGroups.map((group) => {
6959
+ return {
6960
+ data: group.group.toJSON(),
6961
+ position: group.window.dimensions(),
6272
6962
  };
6273
6963
  });
6274
6964
  const result = {
@@ -6279,10 +6969,13 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6279
6969
  if (floats.length > 0) {
6280
6970
  result.floatingGroups = floats;
6281
6971
  }
6972
+ if (popoutGroups.length > 0) {
6973
+ result.popoutGroups = popoutGroups;
6974
+ }
6282
6975
  return result;
6283
6976
  }
6284
6977
  fromJSON(data) {
6285
- var _a;
6978
+ var _a, _b;
6286
6979
  this.clear();
6287
6980
  if (typeof data !== 'object' || data === null) {
6288
6981
  throw new Error('serialized layout must be a non-null object');
@@ -6349,7 +7042,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6349
7042
  width: position.width,
6350
7043
  }, { skipRemoveGroup: true, inDragMode: false });
6351
7044
  }
6352
- for (const floatingGroup of this.floatingGroups) {
7045
+ const serializedPopoutGroups = (_b = data.popoutGroups) !== null && _b !== void 0 ? _b : [];
7046
+ for (const serializedPopoutGroup of serializedPopoutGroups) {
7047
+ const { data, position } = serializedPopoutGroup;
7048
+ const group = createGroupFromSerializedState(data);
7049
+ this.addPopoutGroup(group, {
7050
+ skipRemoveGroup: true,
7051
+ position: position !== null && position !== void 0 ? position : undefined,
7052
+ });
7053
+ }
7054
+ for (const floatingGroup of this._floatingGroups) {
6353
7055
  floatingGroup.overlay.setBounds();
6354
7056
  }
6355
7057
  if (typeof activeGroup === 'string') {
@@ -6381,7 +7083,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6381
7083
  this._onDidRemoveGroup.fire(group);
6382
7084
  }
6383
7085
  // iterate over a reassigned array since original array will be modified
6384
- for (const floatingGroup of [...this.floatingGroups]) {
7086
+ for (const floatingGroup of [...this._floatingGroups]) {
6385
7087
  floatingGroup.dispose();
6386
7088
  }
6387
7089
  // fires clean-up events and clears the underlying HTML gridview.
@@ -6473,7 +7175,8 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6473
7175
  group.model.openPanel(panel);
6474
7176
  this.doSetGroupAndPanelActive(group);
6475
7177
  }
6476
- else if (referenceGroup.api.isFloating || target === 'center') {
7178
+ else if (referenceGroup.api.location === 'floating' ||
7179
+ target === 'center') {
6477
7180
  panel = this.createPanel(options, referenceGroup);
6478
7181
  referenceGroup.model.openPanel(panel);
6479
7182
  }
@@ -6517,6 +7220,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6517
7220
  }
6518
7221
  group.model.removePanel(panel);
6519
7222
  if (!options.skipDispose) {
7223
+ this.overlayRenderContainer.detatch(panel);
6520
7224
  panel.dispose();
6521
7225
  }
6522
7226
  if (group.size === 0 && options.removeEmptyGroup) {
@@ -6533,7 +7237,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6533
7237
  }
6534
7238
  updateWatermark() {
6535
7239
  var _a, _b;
6536
- if (this.groups.filter((x) => !x.api.isFloating).length === 0) {
7240
+ if (this.groups.filter((x) => x.api.location === 'grid').length === 0) {
6537
7241
  if (!this.watermark) {
6538
7242
  this.watermark = this.createWatermarkComponent();
6539
7243
  this.watermark.init({
@@ -6608,19 +7312,40 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6608
7312
  }
6609
7313
  }
6610
7314
  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);
7315
+ if (group.api.location === 'floating') {
7316
+ const floatingGroup = this._floatingGroups.find((_) => _.group === group);
7317
+ if (floatingGroup) {
7318
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7319
+ floatingGroup.group.dispose();
7320
+ this._groups.delete(group.id);
7321
+ this._onDidRemoveGroup.fire(group);
7322
+ }
7323
+ remove(this._floatingGroups, floatingGroup);
7324
+ floatingGroup.dispose();
7325
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7326
+ const groups = Array.from(this._groups.values());
7327
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7328
+ }
7329
+ return floatingGroup.group;
6617
7330
  }
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);
7331
+ throw new Error('failed to find floating group');
7332
+ }
7333
+ if (group.api.location === 'popout') {
7334
+ const selectedGroup = this._popoutGroups.find((_) => _.group === group);
7335
+ if (selectedGroup) {
7336
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
7337
+ selectedGroup.group.dispose();
7338
+ this._groups.delete(group.id);
7339
+ this._onDidRemoveGroup.fire(group);
7340
+ }
7341
+ selectedGroup.dispose();
7342
+ if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
7343
+ const groups = Array.from(this._groups.values());
7344
+ this.doSetGroupActive(groups.length > 0 ? groups[0].value : undefined);
7345
+ }
7346
+ return selectedGroup.group;
6622
7347
  }
6623
- return floatingGroup.group;
7348
+ throw new Error('failed to find popout group');
6624
7349
  }
6625
7350
  return super.doRemoveGroup(group, options);
6626
7351
  }
@@ -6652,8 +7377,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6652
7377
  const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, destinationTarget);
6653
7378
  if (sourceGroup && sourceGroup.size < 2) {
6654
7379
  const [targetParentLocation, to] = tail(targetLocation);
6655
- const isFloating = this.floatingGroups.find((x) => x.group === sourceGroup);
6656
- if (!isFloating) {
7380
+ if (sourceGroup.api.location === 'grid') {
6657
7381
  const sourceLocation = getGridLocation(sourceGroup.element);
6658
7382
  const [sourceParentLocation, from] = tail(sourceLocation);
6659
7383
  if (sequenceEquals(sourceParentLocation, targetParentLocation)) {
@@ -6699,12 +7423,25 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6699
7423
  }
6700
7424
  }
6701
7425
  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));
7426
+ switch (sourceGroup.api.location) {
7427
+ case 'grid':
7428
+ this.gridview.removeView(getGridLocation(sourceGroup.element));
7429
+ break;
7430
+ case 'floating': {
7431
+ const selectedFloatingGroup = this._floatingGroups.find((x) => x.group === sourceGroup);
7432
+ if (!selectedFloatingGroup) {
7433
+ throw new Error('failed to find floating group');
7434
+ }
7435
+ selectedFloatingGroup.dispose();
7436
+ break;
7437
+ }
7438
+ case 'popout': {
7439
+ const selectedPopoutGroup = this._popoutGroups.find((x) => x.group === sourceGroup);
7440
+ if (!selectedPopoutGroup) {
7441
+ throw new Error('failed to find popout group');
7442
+ }
7443
+ selectedPopoutGroup.dispose();
7444
+ }
6708
7445
  }
6709
7446
  const referenceLocation = getGridLocation(referenceGroup.element);
6710
7447
  const dropLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, target);
@@ -6766,7 +7503,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6766
7503
  const contentComponent = options.component;
6767
7504
  const tabComponent = (_a = options.tabComponent) !== null && _a !== void 0 ? _a : this.options.defaultTabComponent;
6768
7505
  const view = new DockviewPanelModel(this, options.id, contentComponent, tabComponent);
6769
- const panel = new DockviewPanel(options.id, this, this._api, group, view);
7506
+ const panel = new DockviewPanel(options.id, this, this._api, group, view, { renderer: options.renderer });
6770
7507
  panel.init({
6771
7508
  title: (_b = options.title) !== null && _b !== void 0 ? _b : options.id,
6772
7509
  params: (_c = options === null || options === void 0 ? void 0 : options.params) !== null && _c !== void 0 ? _c : {},
@@ -8112,6 +8849,9 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
8112
8849
  singleTabMode: props.singleTabMode,
8113
8850
  disableFloatingGroups: props.disableFloatingGroups,
8114
8851
  floatingGroupBounds: props.floatingGroupBounds,
8852
+ defaultRenderer: props.defaultRenderer,
8853
+ debug: props.debug,
8854
+ rootOverlayModel: props.rootOverlayModel,
8115
8855
  });
8116
8856
  const { clientWidth, clientHeight } = domRef.current;
8117
8857
  dockview.layout(clientWidth, clientHeight);
@@ -8219,6 +8959,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
8219
8959
  createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
8220
8960
  });
8221
8961
  }, [props.leftHeaderActionsComponent]);
8962
+ React__namespace.useEffect(() => {
8963
+ if (!dockviewRef.current) {
8964
+ return;
8965
+ }
8966
+ dockviewRef.current.updateOptions({
8967
+ rootOverlayModel: props.rootOverlayModel,
8968
+ });
8969
+ }, [props.rootOverlayModel]);
8222
8970
  React__namespace.useEffect(() => {
8223
8971
  if (!dockviewRef.current) {
8224
8972
  return;