dockview-core 6.6.1 → 7.0.3

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 (203) hide show
  1. package/README.md +8 -1
  2. package/dist/cjs/api/component.api.d.ts +42 -21
  3. package/dist/cjs/api/component.api.js +111 -20
  4. package/dist/cjs/api/dockviewGroupPanelApi.d.ts +23 -8
  5. package/dist/cjs/api/dockviewGroupPanelApi.js +24 -1
  6. package/dist/cjs/api/dockviewPanelApi.d.ts +4 -3
  7. package/dist/cjs/api/dockviewPanelApi.js +8 -0
  8. package/dist/cjs/dnd/dropTargetAnchorContainer.js +1 -2
  9. package/dist/cjs/dnd/droptarget.d.ts +8 -0
  10. package/dist/cjs/dnd/droptarget.js +28 -0
  11. package/dist/cjs/dnd/pointer/longPress.js +1 -1
  12. package/dist/cjs/dnd/pointer/pointerDragController.js +9 -7
  13. package/dist/cjs/dnd/pointer/pointerDragSource.js +4 -2
  14. package/dist/cjs/dockview/accessibilityMessages.d.ts +32 -0
  15. package/dist/cjs/dockview/accessibilityMessages.js +51 -0
  16. package/dist/cjs/dockview/allModules.d.ts +8 -0
  17. package/dist/cjs/dockview/allModules.js +25 -0
  18. package/dist/cjs/dockview/components/panel/content.d.ts +2 -0
  19. package/dist/cjs/dockview/components/panel/content.js +41 -10
  20. package/dist/cjs/dockview/components/popupService.js +1 -1
  21. package/dist/cjs/dockview/components/tab/tab.js +35 -7
  22. package/dist/cjs/dockview/components/titlebar/floatingTitleBar.d.ts +34 -0
  23. package/dist/cjs/dockview/components/titlebar/floatingTitleBar.js +95 -0
  24. package/dist/cjs/dockview/components/titlebar/groupDragSource.d.ts +51 -0
  25. package/dist/cjs/dockview/components/titlebar/groupDragSource.js +218 -0
  26. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
  27. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +36 -30
  28. package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +27 -5
  29. package/dist/cjs/dockview/components/titlebar/tabGroups.js +104 -53
  30. package/dist/cjs/dockview/components/titlebar/tabs.d.ts +12 -0
  31. package/dist/cjs/dockview/components/titlebar/tabs.js +121 -25
  32. package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +4 -0
  33. package/dist/cjs/dockview/components/titlebar/tabsContainer.js +13 -3
  34. package/dist/cjs/dockview/components/titlebar/voidContainer.d.ts +1 -4
  35. package/dist/cjs/dockview/components/titlebar/voidContainer.js +32 -156
  36. package/dist/cjs/dockview/dndCapabilities.js +3 -3
  37. package/dist/cjs/dockview/dockviewComponent.d.ts +304 -49
  38. package/dist/cjs/dockview/dockviewComponent.js +1839 -1075
  39. package/dist/cjs/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
  40. package/dist/cjs/dockview/dockviewFloatingGroupPanel.js +39 -3
  41. package/dist/cjs/dockview/dockviewGroupPanel.d.ts +1 -2
  42. package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +36 -14
  43. package/dist/cjs/dockview/dockviewGroupPanelModel.js +151 -125
  44. package/dist/cjs/dockview/dockviewPanel.d.ts +2 -2
  45. package/dist/cjs/dockview/dockviewPanel.js +4 -5
  46. package/dist/cjs/dockview/dockviewShell.d.ts +29 -7
  47. package/dist/cjs/dockview/dockviewShell.js +94 -36
  48. package/dist/cjs/dockview/edgeGroupService.d.ts +38 -0
  49. package/dist/cjs/dockview/edgeGroupService.js +128 -0
  50. package/dist/cjs/dockview/floatingGroupService.d.ts +37 -0
  51. package/dist/cjs/dockview/floatingGroupService.js +231 -0
  52. package/dist/cjs/dockview/headerActionsService.d.ts +32 -0
  53. package/dist/cjs/dockview/headerActionsService.js +149 -0
  54. package/dist/cjs/dockview/liveRegionService.d.ts +53 -0
  55. package/dist/cjs/dockview/liveRegionService.js +185 -0
  56. package/dist/cjs/dockview/moduleContracts.d.ts +119 -0
  57. package/dist/cjs/dockview/moduleContracts.js +2 -0
  58. package/dist/cjs/dockview/modules.d.ts +110 -0
  59. package/dist/cjs/dockview/modules.js +304 -0
  60. package/dist/cjs/dockview/options.d.ts +159 -6
  61. package/dist/cjs/dockview/options.js +8 -1
  62. package/dist/cjs/dockview/popoutWindowService.d.ts +95 -0
  63. package/dist/cjs/dockview/popoutWindowService.js +261 -0
  64. package/dist/cjs/dockview/rootDropTargetService.d.ts +35 -0
  65. package/dist/cjs/dockview/rootDropTargetService.js +87 -0
  66. package/dist/cjs/dockview/strictEventsSequencing.js +6 -6
  67. package/dist/cjs/dockview/tabGroup.js +3 -3
  68. package/dist/cjs/dockview/tabGroupAccent.js +1 -3
  69. package/dist/cjs/dockview/watermarkService.d.ts +30 -0
  70. package/dist/cjs/dockview/watermarkService.js +61 -0
  71. package/dist/cjs/dom.js +1 -1
  72. package/dist/cjs/events.js +1 -1
  73. package/dist/cjs/gridview/baseComponentGridview.d.ts +1 -1
  74. package/dist/cjs/gridview/baseComponentGridview.js +6 -10
  75. package/dist/cjs/gridview/branchNode.js +13 -17
  76. package/dist/cjs/gridview/gridview.js +8 -8
  77. package/dist/cjs/gridview/gridviewComponent.d.ts +3 -3
  78. package/dist/cjs/gridview/gridviewComponent.js +1 -6
  79. package/dist/cjs/gridview/gridviewPanel.d.ts +1 -1
  80. package/dist/cjs/index.d.ts +11 -4
  81. package/dist/cjs/index.js +14 -1
  82. package/dist/cjs/overlay/overlay.d.ts +43 -1
  83. package/dist/cjs/overlay/overlay.js +82 -36
  84. package/dist/cjs/overlay/overlayRenderContainer.js +3 -4
  85. package/dist/cjs/paneview/draggablePaneviewPanel.d.ts +2 -2
  86. package/dist/cjs/paneview/draggablePaneviewPanel.js +5 -5
  87. package/dist/cjs/paneview/paneviewComponent.d.ts +3 -3
  88. package/dist/cjs/paneview/paneviewComponent.js +7 -11
  89. package/dist/cjs/popoutWindow.js +4 -4
  90. package/dist/cjs/scrollbar.d.ts +1 -1
  91. package/dist/cjs/scrollbar.js +7 -6
  92. package/dist/cjs/splitview/splitview.d.ts +1 -1
  93. package/dist/cjs/splitview/splitview.js +21 -20
  94. package/dist/cjs/splitview/viewItem.js +1 -1
  95. package/dist/dockview-core.js +3548 -1544
  96. package/dist/dockview-core.min.js +2 -2
  97. package/dist/dockview-core.min.js.map +1 -1
  98. package/dist/dockview-core.min.noStyle.js +2 -2
  99. package/dist/dockview-core.min.noStyle.js.map +1 -1
  100. package/dist/dockview-core.noStyle.js +3547 -1543
  101. package/dist/esm/api/component.api.d.ts +42 -21
  102. package/dist/esm/api/component.api.js +63 -18
  103. package/dist/esm/api/dockviewGroupPanelApi.d.ts +23 -8
  104. package/dist/esm/api/dockviewGroupPanelApi.js +20 -1
  105. package/dist/esm/api/dockviewPanelApi.d.ts +4 -3
  106. package/dist/esm/api/dockviewPanelApi.js +7 -0
  107. package/dist/esm/dnd/dropTargetAnchorContainer.js +1 -2
  108. package/dist/esm/dnd/droptarget.d.ts +8 -0
  109. package/dist/esm/dnd/droptarget.js +28 -0
  110. package/dist/esm/dnd/pointer/longPress.js +1 -1
  111. package/dist/esm/dnd/pointer/pointerDragController.js +9 -7
  112. package/dist/esm/dnd/pointer/pointerDragSource.js +4 -2
  113. package/dist/esm/dockview/accessibilityMessages.d.ts +32 -0
  114. package/dist/esm/dockview/accessibilityMessages.js +30 -0
  115. package/dist/esm/dockview/allModules.d.ts +8 -0
  116. package/dist/esm/dockview/allModules.js +22 -0
  117. package/dist/esm/dockview/components/panel/content.d.ts +2 -0
  118. package/dist/esm/dockview/components/panel/content.js +42 -11
  119. package/dist/esm/dockview/components/popupService.js +1 -1
  120. package/dist/esm/dockview/components/tab/tab.js +35 -7
  121. package/dist/esm/dockview/components/titlebar/floatingTitleBar.d.ts +34 -0
  122. package/dist/esm/dockview/components/titlebar/floatingTitleBar.js +65 -0
  123. package/dist/esm/dockview/components/titlebar/groupDragSource.d.ts +51 -0
  124. package/dist/esm/dockview/components/titlebar/groupDragSource.js +178 -0
  125. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
  126. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +36 -30
  127. package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +27 -5
  128. package/dist/esm/dockview/components/titlebar/tabGroups.js +91 -41
  129. package/dist/esm/dockview/components/titlebar/tabs.d.ts +12 -0
  130. package/dist/esm/dockview/components/titlebar/tabs.js +119 -26
  131. package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +4 -0
  132. package/dist/esm/dockview/components/titlebar/tabsContainer.js +8 -2
  133. package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +1 -4
  134. package/dist/esm/dockview/components/titlebar/voidContainer.js +34 -146
  135. package/dist/esm/dockview/dndCapabilities.js +3 -3
  136. package/dist/esm/dockview/dockviewComponent.d.ts +304 -49
  137. package/dist/esm/dockview/dockviewComponent.js +1459 -772
  138. package/dist/esm/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
  139. package/dist/esm/dockview/dockviewFloatingGroupPanel.js +35 -3
  140. package/dist/esm/dockview/dockviewGroupPanel.d.ts +1 -2
  141. package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +36 -14
  142. package/dist/esm/dockview/dockviewGroupPanelModel.js +127 -117
  143. package/dist/esm/dockview/dockviewPanel.d.ts +2 -2
  144. package/dist/esm/dockview/dockviewPanel.js +1 -2
  145. package/dist/esm/dockview/dockviewShell.d.ts +29 -7
  146. package/dist/esm/dockview/dockviewShell.js +89 -37
  147. package/dist/esm/dockview/edgeGroupService.d.ts +38 -0
  148. package/dist/esm/dockview/edgeGroupService.js +63 -0
  149. package/dist/esm/dockview/floatingGroupService.d.ts +37 -0
  150. package/dist/esm/dockview/floatingGroupService.js +150 -0
  151. package/dist/esm/dockview/headerActionsService.d.ts +32 -0
  152. package/dist/esm/dockview/headerActionsService.js +86 -0
  153. package/dist/esm/dockview/liveRegionService.d.ts +53 -0
  154. package/dist/esm/dockview/liveRegionService.js +159 -0
  155. package/dist/esm/dockview/moduleContracts.d.ts +119 -0
  156. package/dist/esm/dockview/moduleContracts.js +1 -0
  157. package/dist/esm/dockview/modules.d.ts +110 -0
  158. package/dist/esm/dockview/modules.js +170 -0
  159. package/dist/esm/dockview/options.d.ts +159 -6
  160. package/dist/esm/dockview/options.js +8 -1
  161. package/dist/esm/dockview/popoutWindowService.d.ts +95 -0
  162. package/dist/esm/dockview/popoutWindowService.js +175 -0
  163. package/dist/esm/dockview/rootDropTargetService.d.ts +35 -0
  164. package/dist/esm/dockview/rootDropTargetService.js +82 -0
  165. package/dist/esm/dockview/strictEventsSequencing.js +6 -6
  166. package/dist/esm/dockview/tabGroup.js +3 -3
  167. package/dist/esm/dockview/tabGroupAccent.js +1 -3
  168. package/dist/esm/dockview/watermarkService.d.ts +30 -0
  169. package/dist/esm/dockview/watermarkService.js +56 -0
  170. package/dist/esm/dom.js +1 -1
  171. package/dist/esm/events.js +1 -1
  172. package/dist/esm/gridview/baseComponentGridview.d.ts +1 -1
  173. package/dist/esm/gridview/baseComponentGridview.js +5 -10
  174. package/dist/esm/gridview/branchNode.js +13 -15
  175. package/dist/esm/gridview/gridview.js +8 -8
  176. package/dist/esm/gridview/gridviewComponent.d.ts +3 -3
  177. package/dist/esm/gridview/gridviewComponent.js +1 -6
  178. package/dist/esm/gridview/gridviewPanel.d.ts +1 -1
  179. package/dist/esm/index.d.ts +11 -4
  180. package/dist/esm/index.js +4 -0
  181. package/dist/esm/overlay/overlay.d.ts +43 -1
  182. package/dist/esm/overlay/overlay.js +78 -36
  183. package/dist/esm/overlay/overlayRenderContainer.js +3 -4
  184. package/dist/esm/paneview/draggablePaneviewPanel.d.ts +2 -2
  185. package/dist/esm/paneview/draggablePaneviewPanel.js +5 -5
  186. package/dist/esm/paneview/paneviewComponent.d.ts +3 -3
  187. package/dist/esm/paneview/paneviewComponent.js +7 -11
  188. package/dist/esm/popoutWindow.js +4 -4
  189. package/dist/esm/scrollbar.d.ts +1 -1
  190. package/dist/esm/scrollbar.js +7 -6
  191. package/dist/esm/splitview/splitview.d.ts +1 -1
  192. package/dist/esm/splitview/splitview.js +21 -20
  193. package/dist/esm/splitview/viewItem.js +1 -1
  194. package/dist/package/main.cjs.js +3550 -1546
  195. package/dist/package/main.cjs.min.js +2 -2
  196. package/dist/package/main.esm.min.mjs +2 -2
  197. package/dist/package/main.esm.mjs +3538 -1545
  198. package/dist/styles/dockview.css +283 -21
  199. package/package.json +10 -1
  200. package/dist/cjs/dockview/contextMenu.d.ts +0 -10
  201. package/dist/cjs/dockview/contextMenu.js +0 -313
  202. package/dist/esm/dockview/contextMenu.d.ts +0 -10
  203. package/dist/esm/dockview/contextMenu.js +0 -228
@@ -65,7 +65,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
65
65
  exports.DockviewComponent = void 0;
66
66
  var gridview_1 = require("../gridview/gridview");
67
67
  var droptarget_1 = require("../dnd/droptarget");
68
- var backend_1 = require("../dnd/backend");
69
68
  var array_1 = require("../array");
70
69
  var dockviewPanel_1 = require("./dockviewPanel");
71
70
  var lifecycle_1 = require("../lifecycle");
@@ -84,21 +83,18 @@ var dockviewPanelModel_1 = require("./dockviewPanelModel");
84
83
  var dataTransfer_1 = require("../dnd/dataTransfer");
85
84
  var overlay_1 = require("../overlay/overlay");
86
85
  var dom_1 = require("../dom");
87
- var dockviewFloatingGroupPanel_1 = require("./dockviewFloatingGroupPanel");
86
+ var floatingTitleBar_1 = require("./components/titlebar/floatingTitleBar");
87
+ var modules_1 = require("./modules");
88
+ var allModules_1 = require("./allModules");
88
89
  var constants_1 = require("../constants");
89
90
  var overlayRenderContainer_1 = require("../overlay/overlayRenderContainer");
90
91
  var popoutWindow_1 = require("../popoutWindow");
91
92
  var strictEventsSequencing_1 = require("./strictEventsSequencing");
92
93
  var popupService_1 = require("./components/popupService");
93
- var contextMenu_1 = require("./contextMenu");
94
94
  var dropTargetAnchorContainer_1 = require("../dnd/dropTargetAnchorContainer");
95
95
  var theme_1 = require("./theme");
96
96
  var dockviewShell_1 = require("./dockviewShell");
97
97
  var tabGroupAccent_1 = require("./tabGroupAccent");
98
- var DEFAULT_ROOT_OVERLAY_MODEL = {
99
- activationSize: { type: 'pixels', value: 10 },
100
- size: { type: 'pixels', value: 20 },
101
- };
102
98
  function buildTabGroupColorPalette(options) {
103
99
  var _a;
104
100
  var entries = (_a = options.tabGroupColors) !== null && _a !== void 0 ? _a : tabGroupAccent_1.DEFAULT_TAB_GROUP_COLORS;
@@ -119,10 +115,37 @@ function moveGroupWithoutDestroying(options) {
119
115
  });
120
116
  });
121
117
  }
118
+ var _hasWarnedUsingCoreDirectly = false;
119
+ /**
120
+ * `dockview-core` is an internal package. The public `dockview` package calls
121
+ * `markDockviewPackageLoaded()` on import; if that marker is absent the consumer
122
+ * is using `dockview-core` directly, so emit a one-time console warning
123
+ * steering them to `dockview`.
124
+ *
125
+ * Suppressed in production builds: it is a development-time nudge and most
126
+ * bundlers inline `process.env.NODE_ENV` so the branch is dropped entirely. The
127
+ * `typeof process` guard keeps this safe in plain browser/UMD contexts where
128
+ * `process` is undefined.
129
+ */
130
+ function warnIfUsingCoreDirectly() {
131
+ var _a;
132
+ if (typeof process !== 'undefined' &&
133
+ ((_a = process.env) === null || _a === void 0 ? void 0 : _a.NODE_ENV) === 'production') {
134
+ return;
135
+ }
136
+ if (_hasWarnedUsingCoreDirectly || (0, modules_1.isDockviewPackageLoaded)()) {
137
+ return;
138
+ }
139
+ _hasWarnedUsingCoreDirectly = true;
140
+ console.warn('dockview: do not use "dockview-core" directly — it is an internal ' +
141
+ 'package. Use the "dockview" package, the JavaScript version of ' +
142
+ 'dockview, instead. This notice is shown once.');
143
+ }
122
144
  var DockviewComponent = /** @class */ (function (_super) {
123
145
  __extends(DockviewComponent, _super);
124
146
  function DockviewComponent(container, options) {
125
- var _a, _b, _c, _d, _e, _f, _g;
147
+ var e_1, _a;
148
+ var _b, _c, _d, _e, _f;
126
149
  var _this = _super.call(this, container, {
127
150
  proportionalLayout: true,
128
151
  orientation: splitview_1.Orientation.HORIZONTAL,
@@ -131,13 +154,12 @@ var DockviewComponent = /** @class */ (function (_super) {
131
154
  : undefined,
132
155
  disableAutoResizing: options.disableAutoResizing,
133
156
  locked: options.locked,
134
- margin: (_b = (_a = options.theme) === null || _a === void 0 ? void 0 : _a.gap) !== null && _b !== void 0 ? _b : 0,
157
+ margin: (_c = (_b = options.theme) === null || _b === void 0 ? void 0 : _b.gap) !== null && _c !== void 0 ? _c : 0,
135
158
  className: options.className,
136
159
  }) || this;
137
160
  _this.nextGroupId = (0, math_1.sequentialNumberGenerator)();
138
161
  _this._deserializer = new deserializer_1.DefaultDockviewDeserialzier(_this);
139
- _this._watermark = null;
140
- _this._popoutPopupServices = new Map();
162
+ _this._moduleRegistry = new modules_1.ModuleRegistry();
141
163
  _this._onWillDragPanel = new events_1.Emitter();
142
164
  _this.onWillDragPanel = _this._onWillDragPanel.event;
143
165
  _this._onWillDragGroup = new events_1.Emitter();
@@ -146,10 +168,25 @@ var DockviewComponent = /** @class */ (function (_super) {
146
168
  _this.onDidDrop = _this._onDidDrop.event;
147
169
  _this._onWillDrop = new events_1.Emitter();
148
170
  _this.onWillDrop = _this._onWillDrop.event;
171
+ // Transaction boundary bracketing each top-level structural mutation.
172
+ // Compound operations (e.g. a drag that relocates a panel) nest via the
173
+ // depth counter and bracket as a single transaction. See `mutation()`.
174
+ _this._mutationDepth = 0;
175
+ // Current operation origin. Defaults to `'user'`; the DockviewApi boundary
176
+ // flips it to `'api'` for the duration of a programmatic call via
177
+ // `withOrigin`. Nested operations inherit the outermost origin (tracked by
178
+ // `_originDepth`, independent of mutation bracketing so it also covers
179
+ // active-panel changes that are not structural mutations).
180
+ _this._origin = 'user';
181
+ _this._originDepth = 0;
182
+ _this._onWillMutateLayout = new events_1.Emitter();
183
+ _this.onWillMutateLayout = _this._onWillMutateLayout.event;
184
+ _this._onDidMutateLayout = new events_1.Emitter();
185
+ _this.onDidMutateLayout = _this._onDidMutateLayout.event;
149
186
  _this._onWillShowOverlay = new events_1.Emitter();
150
187
  _this.onWillShowOverlay = _this._onWillShowOverlay.event;
151
- _this._onUnhandledDragOverEvent = new events_1.Emitter();
152
- _this.onUnhandledDragOverEvent = _this._onUnhandledDragOverEvent.event;
188
+ _this._onUnhandledDragOver = new events_1.Emitter();
189
+ _this.onUnhandledDragOver = _this._onUnhandledDragOver.event;
153
190
  _this._onDidRemovePanel = new events_1.Emitter();
154
191
  _this.onDidRemovePanel = _this._onDidRemovePanel.event;
155
192
  _this._onDidAddPanel = new events_1.Emitter();
@@ -158,6 +195,10 @@ var DockviewComponent = /** @class */ (function (_super) {
158
195
  _this.onDidPopoutGroupSizeChange = _this._onDidPopoutGroupSizeChange.event;
159
196
  _this._onDidPopoutGroupPositionChange = new events_1.Emitter();
160
197
  _this.onDidPopoutGroupPositionChange = _this._onDidPopoutGroupPositionChange.event;
198
+ _this._onDidAddPopoutGroup = new events_1.Emitter();
199
+ _this.onDidAddPopoutGroup = _this._onDidAddPopoutGroup.event;
200
+ _this._onDidRemovePopoutGroup = new events_1.Emitter();
201
+ _this.onDidRemovePopoutGroup = _this._onDidRemovePopoutGroup.event;
161
202
  _this._onDidOpenPopoutWindowFail = new events_1.Emitter();
162
203
  _this.onDidOpenPopoutWindowFail = _this._onDidOpenPopoutWindowFail.event;
163
204
  _this._onDidLayoutFromJSON = new events_1.Emitter();
@@ -181,12 +222,6 @@ var DockviewComponent = /** @class */ (function (_super) {
181
222
  _this._onDidMaximizedGroupChange = new events_1.Emitter();
182
223
  _this.onDidMaximizedGroupChange = _this._onDidMaximizedGroupChange.event;
183
224
  _this._inShellLayout = false;
184
- _this._edgeGroups = new Map();
185
- _this._edgeGroupDisposables = new Map();
186
- _this._floatingGroups = [];
187
- _this._popoutGroups = [];
188
- _this._popoutRestorationPromise = Promise.resolve();
189
- _this._popoutRestorationCleanups = new Set();
190
225
  _this._onDidRemoveGroup = new events_1.Emitter();
191
226
  _this.onDidRemoveGroup = _this._onDidRemoveGroup.event;
192
227
  _this._onDidAddGroup = new events_1.Emitter();
@@ -198,14 +233,51 @@ var DockviewComponent = /** @class */ (function (_super) {
198
233
  _this._moving = false;
199
234
  _this._options = options;
200
235
  _this._tabGroupColorPalette = buildTabGroupColorPalette(options);
236
+ // Internal seam: defaults to the full set, but tests can supply a
237
+ // subset to assert every module is independently removable (and the
238
+ // opt-in module API will build on this later). Not part of the public
239
+ // options surface.
240
+ var explicitModules = options
241
+ .modules;
242
+ var modules = explicitModules !== null && explicitModules !== void 0 ? explicitModules : __spreadArray(__spreadArray([], __read(allModules_1.AllModules), false), __read((0, modules_1.getRegisteredModules)()), false);
243
+ try {
244
+ for (var modules_2 = __values(modules), modules_2_1 = modules_2.next(); !modules_2_1.done; modules_2_1 = modules_2.next()) {
245
+ var module_1 = modules_2_1.value;
246
+ _this._moduleRegistry.register(module_1);
247
+ }
248
+ }
249
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
250
+ finally {
251
+ try {
252
+ if (modules_2_1 && !modules_2_1.done && (_a = modules_2.return)) _a.call(modules_2);
253
+ }
254
+ finally { if (e_1) throw e_1.error; }
255
+ }
256
+ _this._moduleRegistry.initialize(_this);
257
+ // Surface popout removal symmetrically with `onDidAddPopoutGroup`. The
258
+ // service is the single point every removal path funnels through — a
259
+ // genuine window close and an explicit removal alike — and it suppresses
260
+ // the event during component teardown.
261
+ var popoutWindowService = _this._popoutWindowService;
262
+ if (popoutWindowService) {
263
+ _this.addDisposables(popoutWindowService.onDidRemove(function (entry) {
264
+ _this._onDidRemovePopoutGroup.fire({
265
+ id: entry.popoutGroup.id,
266
+ group: entry.popoutGroup,
267
+ window: entry.getWindow(),
268
+ });
269
+ }));
270
+ }
271
+ // Purely a developer warning (no functional effect): nudge anyone using
272
+ // the internal `dockview-core` package directly towards `dockview`.
273
+ warnIfUsingCoreDirectly();
201
274
  _this.popupService = new popupService_1.PopupService(_this.element);
202
- _this.contextMenuController = new contextMenu_1.ContextMenuController(_this);
203
275
  _this._api = new component_api_1.DockviewApi(_this);
204
276
  // The shell always wraps the dockview element so edge groups can be
205
277
  // added at any time via addEdgeGroup() without re-parenting the DOM.
206
278
  _this.disableResizing = true;
207
- container.removeChild(_this.element);
208
- _this._shellManager = new dockviewShell_1.ShellManager(container, _this.element, function (w, h) { return _this._layoutFromShell(w, h); }, (_d = (_c = options.theme) === null || _c === void 0 ? void 0 : _c.gap) !== null && _d !== void 0 ? _d : 0, (_e = options.theme) === null || _e === void 0 ? void 0 : _e.edgeGroupCollapsedSize);
279
+ _this.element.remove();
280
+ _this._shellManager = new dockviewShell_1.ShellManager(container, _this.element, function (w, h) { return _this._layoutFromShell(w, h); }, (_e = (_d = options.theme) === null || _d === void 0 ? void 0 : _d.gap) !== null && _e !== void 0 ? _e : 0, (_f = options.theme) === null || _f === void 0 ? void 0 : _f.edgeGroupCollapsedSize);
209
281
  // The shell wraps the dockview element, so move the popup anchor
210
282
  // into the shell so overflow dropdowns in edge groups position correctly
211
283
  _this.popupService.updateRoot(_this._shellManager.element);
@@ -221,69 +293,23 @@ var DockviewComponent = /** @class */ (function (_super) {
221
293
  _this._floatingOverlayHost = document.createElement('div');
222
294
  _this._floatingOverlayHost.className = 'dv-floating-overlay-host';
223
295
  _this._shellManager.element.appendChild(_this._floatingOverlayHost);
224
- var rootCanDisplayOverlay = function (event, position) {
225
- var data = (0, dataTransfer_1.getPanelData)();
226
- if (data) {
227
- if (data.viewId !== _this.id) {
228
- return false;
229
- }
230
- if (position === 'center') {
231
- // center drop target is only allowed if there are no panels in the grid
232
- // floating panels are allowed
233
- return _this.gridview.length === 0;
234
- }
235
- return true;
236
- }
237
- if (position === 'center' && _this.gridview.length !== 0) {
238
- /**
239
- * for external events only show the four-corner drag overlays, disable
240
- * the center position so that external drag events can fall through to the group
241
- * and panel drop target handlers
242
- */
243
- return false;
244
- }
245
- var firedEvent = new options_1.DockviewUnhandledDragOverEvent(event, 'edge', position, dataTransfer_1.getPanelData);
246
- _this._onUnhandledDragOverEvent.fire(firedEvent);
247
- return firedEvent.isAccepted;
248
- };
249
- _this._rootDropTarget = backend_1.html5Backend.createDropTarget(_this.element, {
250
- className: 'dv-drop-target-edge',
251
- canDisplayOverlay: rootCanDisplayOverlay,
252
- acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
253
- overlayModel: (_f = options.rootOverlayModel) !== null && _f !== void 0 ? _f : DEFAULT_ROOT_OVERLAY_MODEL,
254
- getOverrideTarget: function () { var _a; return (_a = _this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model; },
255
- });
256
- _this._rootPointerDropTarget = backend_1.pointerBackend.createDropTarget(_this.element, {
257
- className: 'dv-drop-target-edge',
258
- canDisplayOverlay: rootCanDisplayOverlay,
259
- acceptedTargetZones: [
260
- 'top',
261
- 'bottom',
262
- 'left',
263
- 'right',
264
- 'center',
265
- ],
266
- overlayModel: (_g = options.rootOverlayModel) !== null && _g !== void 0 ? _g : DEFAULT_ROOT_OVERLAY_MODEL,
267
- getOverrideTarget: function () { var _a; return (_a = _this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model; },
268
- });
269
- _this.updateDropTargetModel(options);
270
296
  (0, dom_1.toggleClass)(_this.gridview.element, 'dv-dockview', true);
271
297
  (0, dom_1.toggleClass)(_this.element, 'dv-debug', !!options.debug);
272
298
  _this.updateTheme();
273
- _this.updateWatermark();
274
299
  if (options.debug) {
275
300
  _this.addDisposables(new strictEventsSequencing_1.StrictEventsSequencing(_this));
276
301
  }
277
- _this.addDisposables(_this.rootDropTargetContainer, _this.overlayRenderContainer, _this._onWillDragPanel, _this._onWillDragGroup, _this._onWillShowOverlay, _this._onDidActivePanelChange, _this._onDidAddPanel, _this._onDidRemovePanel, _this._onDidLayoutFromJSON, _this._onDidDrop, _this._onWillDrop, _this._onDidMovePanel, _this._onDidMovePanel.event(function () {
302
+ _this.addDisposables(_this.rootDropTargetContainer, _this.overlayRenderContainer, _this._onWillDragPanel, _this._onWillDragGroup, _this._onWillShowOverlay, _this._onDidActivePanelChange, _this._onDidAddPanel, _this._onDidRemovePanel, _this._onDidLayoutFromJSON, _this._onDidDrop, _this._onWillDrop, _this._onWillMutateLayout, _this._onDidMutateLayout, _this._onDidMovePanel, _this._onDidMovePanel.event(function () {
278
303
  /**
279
304
  * Update overlay positions after DOM layout completes to prevent 0×0 dimensions.
280
305
  * With defaultRenderer="always" this results in panel content not showing after move operations.
281
306
  * Debounced to avoid multiple calls when moving groups with multiple panels.
282
307
  */
283
308
  _this.debouncedUpdateAllPositions();
284
- }), _this._onDidAddGroup, _this._onDidRemoveGroup, _this._onDidActiveGroupChange, _this._onUnhandledDragOverEvent, _this._onDidMaximizedGroupChange, _this._onDidOptionsChange, _this._onDidPopoutGroupSizeChange, _this._onDidPopoutGroupPositionChange, _this._onDidOpenPopoutWindowFail, _this._onDidCreateTabGroup, _this._onDidDestroyTabGroup, _this._onDidAddPanelToTabGroup, _this._onDidRemovePanelFromTabGroup, _this._onDidTabGroupChange, _this._onDidTabGroupCollapsedChange, _this.onDidViewVisibilityChangeMicroTaskQueue(function () {
285
- _this.updateWatermark();
286
- }), _this.onDidAdd(function (event) {
309
+ }), _this._onDidAddGroup, _this._onDidRemoveGroup, _this._onDidActiveGroupChange, _this._onUnhandledDragOver, _this._onDidMaximizedGroupChange, _this._onDidPopoutGroupSizeChange, _this._onDidPopoutGroupPositionChange, _this._onDidAddPopoutGroup, _this._onDidRemovePopoutGroup, _this._onDidOpenPopoutWindowFail, _this._onDidCreateTabGroup, _this._onDidDestroyTabGroup, _this._onDidAddPanelToTabGroup, _this._onDidRemovePanelFromTabGroup, _this._onDidTabGroupChange, _this._onDidTabGroupCollapsedChange, events_1.Event.any(_this.onDidPopoutGroupSizeChange, _this.onDidPopoutGroupPositionChange, _this.onDidCreateTabGroup, _this.onDidDestroyTabGroup, _this.onDidAddPanelToTabGroup, _this.onDidRemovePanelFromTabGroup, _this.onDidTabGroupChange, _this.onDidTabGroupCollapsedChange)(function () {
310
+ // Popout size/position and tab-group mutations persist as layout changes.
311
+ _this.fireLayoutChange();
312
+ }), _this._onDidOptionsChange, _this.onDidAdd(function (event) {
287
313
  if (!_this._moving) {
288
314
  _this._onDidAddGroup.fire(event);
289
315
  }
@@ -300,127 +326,100 @@ var DockviewComponent = /** @class */ (function (_super) {
300
326
  group: event.panel,
301
327
  isMaximized: event.isMaximized,
302
328
  });
303
- }), events_1.Event.any(_this.onDidAdd, _this.onDidRemove)(function () {
304
- _this.updateWatermark();
305
- }), events_1.Event.any(_this.onDidAddPanel, _this.onDidRemovePanel, _this.onDidAddGroup, _this.onDidRemove, _this.onDidRemoveGroup, _this.onDidMovePanel, _this.onDidActivePanelChange, _this.onDidPopoutGroupPositionChange, _this.onDidPopoutGroupSizeChange, _this.onDidCreateTabGroup, _this.onDidDestroyTabGroup, _this.onDidAddPanelToTabGroup, _this.onDidRemovePanelFromTabGroup, _this.onDidTabGroupChange, _this.onDidTabGroupCollapsedChange)(function () {
329
+ }), events_1.Event.any(_this.onDidAddPanel, _this.onDidRemovePanel, _this.onDidAddGroup, _this.onDidRemove, _this.onDidRemoveGroup, _this.onDidMovePanel, _this.onDidActivePanelChange)(function () {
306
330
  _this._bufferOnDidLayoutChange.fire();
307
331
  }), lifecycle_1.Disposable.from(function () {
308
- var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
309
- var _e;
310
- try {
311
- // Cancel any pending popout-restoration timers scheduled by
312
- // fromJSON so they don't open new browser windows after
313
- // dispose, and resolve their promises so callers awaiting
314
- // popoutRestorationPromise don't hang. See issue #851.
315
- for (var _f = __values(__spreadArray([], __read(_this._popoutRestorationCleanups), false)), _g = _f.next(); !_g.done; _g = _f.next()) {
316
- var cleanup = _g.value;
317
- cleanup();
318
- }
319
- }
320
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
321
- finally {
322
- try {
323
- if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
324
- }
325
- finally { if (e_1) throw e_1.error; }
326
- }
327
- _this._popoutRestorationCleanups.clear();
328
- try {
329
- // iterate over a copy of the array since .dispose() mutates the original array
330
- for (var _h = __values(__spreadArray([], __read(_this._floatingGroups), false)), _j = _h.next(); !_j.done; _j = _h.next()) {
331
- var group = _j.value;
332
- group.dispose();
333
- }
334
- }
335
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
336
- finally {
337
- try {
338
- if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
339
- }
340
- finally { if (e_2) throw e_2.error; }
341
- }
342
- try {
343
- // iterate over a copy of the array since .dispose() mutates the original array
344
- for (var _k = __values(__spreadArray([], __read(_this._popoutGroups), false)), _l = _k.next(); !_l.done; _l = _k.next()) {
345
- var group = _l.value;
346
- group.disposable.dispose();
347
- }
348
- }
349
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
350
- finally {
351
- try {
352
- if (_l && !_l.done && (_c = _k.return)) _c.call(_k);
353
- }
354
- finally { if (e_3) throw e_3.error; }
355
- }
356
- (_e = _this._shellManager) === null || _e === void 0 ? void 0 : _e.dispose();
357
- try {
358
- for (var _m = __values(_this._edgeGroupDisposables.values()), _o = _m.next(); !_o.done; _o = _m.next()) {
359
- var d = _o.value;
360
- d.dispose();
361
- }
362
- }
363
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
364
- finally {
365
- try {
366
- if (_o && !_o.done && (_d = _m.return)) _d.call(_m);
367
- }
368
- finally { if (e_4) throw e_4.error; }
369
- }
370
- _this._edgeGroupDisposables.clear();
371
- }), _this._rootDropTarget, _this._rootPointerDropTarget, events_1.Event.any(_this._rootDropTarget.onWillShowOverlay, _this._rootPointerDropTarget.onWillShowOverlay)(function (event) {
372
- if (_this.gridview.length > 0 && event.position === 'center') {
373
- // option only available when no panels in primary grid
374
- return;
375
- }
376
- _this._onWillShowOverlay.fire(new events_2.DockviewWillShowOverlayLocationEvent(event, {
377
- kind: 'edge',
378
- panel: undefined,
379
- api: _this._api,
380
- group: undefined,
381
- getData: dataTransfer_1.getPanelData,
382
- }));
383
- }), events_1.Event.any(_this._rootDropTarget.onDrop, _this._rootPointerDropTarget.onDrop)(function (event) {
384
332
  var _a;
385
- var willDropEvent = new dockviewGroupPanelModel_1.DockviewWillDropEvent({
386
- nativeEvent: event.nativeEvent,
387
- position: event.position,
388
- panel: undefined,
389
- api: _this._api,
390
- group: undefined,
391
- getData: dataTransfer_1.getPanelData,
392
- kind: 'edge',
393
- });
394
- _this._onWillDrop.fire(willDropEvent);
395
- if (willDropEvent.defaultPrevented) {
396
- return;
397
- }
398
- var data = (0, dataTransfer_1.getPanelData)();
399
- if (data) {
400
- _this.moveGroupOrPanel({
401
- from: {
402
- groupId: data.groupId,
403
- panelId: (_a = data.panelId) !== null && _a !== void 0 ? _a : undefined,
404
- },
405
- to: {
406
- group: _this.orthogonalize(event.position),
407
- position: 'center',
408
- },
409
- });
410
- }
411
- else {
412
- _this._onDidDrop.fire(new dockviewGroupPanelModel_1.DockviewDidDropEvent({
333
+ // Registry disposes init() subscriptions then every module
334
+ // service that implements IDisposable. The order matters so
335
+ // init handlers stop firing into services about to be torn
336
+ // down. Includes popout-restoration timer cancellation that
337
+ // resolves promises so awaiters of popoutRestorationPromise
338
+ // don't hang. See issue #851.
339
+ _this._moduleRegistry.dispose();
340
+ (_a = _this._shellManager) === null || _a === void 0 ? void 0 : _a.dispose();
341
+ }));
342
+ // Root edge-drop wiring lives with its (optional) module — guard it so
343
+ // the module is independently removable.
344
+ var rootDropTarget = _this._rootDropTargetService;
345
+ if (rootDropTarget) {
346
+ _this.addDisposables(rootDropTarget.onWillShowOverlay(function (event) {
347
+ if (_this.gridview.length > 0 &&
348
+ event.position === 'center') {
349
+ // option only available when no panels in primary grid
350
+ return;
351
+ }
352
+ _this._onWillShowOverlay.fire(new events_2.DockviewWillShowOverlayLocationEvent(event, {
353
+ kind: 'edge',
354
+ panel: undefined,
355
+ api: _this._api,
356
+ group: undefined,
357
+ getData: dataTransfer_1.getPanelData,
358
+ }));
359
+ }), rootDropTarget.onDrop(function (event) {
360
+ var _a;
361
+ var willDropEvent = new dockviewGroupPanelModel_1.DockviewWillDropEvent({
413
362
  nativeEvent: event.nativeEvent,
414
363
  position: event.position,
415
364
  panel: undefined,
416
365
  api: _this._api,
417
366
  group: undefined,
418
367
  getData: dataTransfer_1.getPanelData,
419
- }));
420
- }
421
- }));
368
+ kind: 'edge',
369
+ });
370
+ _this._onWillDrop.fire(willDropEvent);
371
+ if (willDropEvent.defaultPrevented) {
372
+ return;
373
+ }
374
+ var data = (0, dataTransfer_1.getPanelData)();
375
+ if (data) {
376
+ _this.moveGroupOrPanel({
377
+ from: {
378
+ groupId: data.groupId,
379
+ panelId: (_a = data.panelId) !== null && _a !== void 0 ? _a : undefined,
380
+ },
381
+ to: {
382
+ group: _this.orthogonalize(event.position),
383
+ position: 'center',
384
+ },
385
+ });
386
+ }
387
+ else {
388
+ _this._onDidDrop.fire(new dockviewGroupPanelModel_1.DockviewDidDropEvent({
389
+ nativeEvent: event.nativeEvent,
390
+ position: event.position,
391
+ panel: undefined,
392
+ api: _this._api,
393
+ group: undefined,
394
+ getData: dataTransfer_1.getPanelData,
395
+ }));
396
+ }
397
+ }));
398
+ }
399
+ // Final module wiring: runs after the host is fully constructed.
400
+ // Modules subscribe to host events here so the component doesn't
401
+ // need to manually invoke them at scattered call sites.
402
+ _this._moduleRegistry.postConstruct(_this);
422
403
  return _this;
423
404
  }
405
+ DockviewComponent.prototype.fireDidCreateTabGroup = function (event) {
406
+ this._onDidCreateTabGroup.fire(event);
407
+ };
408
+ DockviewComponent.prototype.fireDidDestroyTabGroup = function (event) {
409
+ this._onDidDestroyTabGroup.fire(event);
410
+ };
411
+ DockviewComponent.prototype.fireDidAddPanelToTabGroup = function (event) {
412
+ this._onDidAddPanelToTabGroup.fire(event);
413
+ };
414
+ DockviewComponent.prototype.fireDidRemovePanelFromTabGroup = function (event) {
415
+ this._onDidRemovePanelFromTabGroup.fire(event);
416
+ };
417
+ DockviewComponent.prototype.fireDidTabGroupChange = function (event) {
418
+ this._onDidTabGroupChange.fire(event);
419
+ };
420
+ DockviewComponent.prototype.fireDidTabGroupCollapsedChange = function (event) {
421
+ this._onDidTabGroupCollapsedChange.fire(event);
422
+ };
424
423
  Object.defineProperty(DockviewComponent.prototype, "orientation", {
425
424
  get: function () {
426
425
  return this.gridview.orientation;
@@ -492,18 +491,262 @@ var DockviewComponent = /** @class */ (function (_super) {
492
491
  });
493
492
  Object.defineProperty(DockviewComponent.prototype, "floatingGroups", {
494
493
  get: function () {
495
- return this._floatingGroups;
494
+ var _a, _b, _c;
495
+ return ((_c = (_b = (_a = this._moduleRegistry) === null || _a === void 0 ? void 0 : _a.services.floatingGroupService) === null || _b === void 0 ? void 0 : _b.floatingGroups) !== null && _c !== void 0 ? _c : []);
496
+ },
497
+ enumerable: false,
498
+ configurable: true
499
+ });
500
+ /**
501
+ * Boxes of the floating groups other than `exclude`, in coordinates
502
+ * relative to the floating overlay container. Supplied to a
503
+ * `transformFloatingGroupDrag` callback as `context.others` so it can
504
+ * align the dragged float against its siblings.
505
+ */
506
+ DockviewComponent.prototype._gatherFloatingGroupBoxes = function (exclude) {
507
+ var _a;
508
+ var container = (_a = this._floatingOverlayHost) !== null && _a !== void 0 ? _a : this.gridview.element;
509
+ var containerRect = container.getBoundingClientRect();
510
+ return this.floatingGroups
511
+ .filter(function (floating) { return floating.group !== exclude; })
512
+ .map(function (floating) {
513
+ var rect = floating.overlay.element.getBoundingClientRect();
514
+ return {
515
+ left: rect.left - containerRect.left,
516
+ top: rect.top - containerRect.top,
517
+ width: rect.width,
518
+ height: rect.height,
519
+ };
520
+ });
521
+ };
522
+ Object.defineProperty(DockviewComponent.prototype, "_floatingGroupService", {
523
+ get: function () {
524
+ return this._moduleRegistry.services.floatingGroupService;
525
+ },
526
+ enumerable: false,
527
+ configurable: true
528
+ });
529
+ Object.defineProperty(DockviewComponent.prototype, "_popoutWindowService", {
530
+ get: function () {
531
+ return this._moduleRegistry.services.popoutWindowService;
532
+ },
533
+ enumerable: false,
534
+ configurable: true
535
+ });
536
+ Object.defineProperty(DockviewComponent.prototype, "_watermarkService", {
537
+ get: function () {
538
+ // Tier 1 module — optional. Callers must `?.`-guard so the module
539
+ // can be removed from AllModules without crashing the component.
540
+ return this._moduleRegistry.services.watermarkService;
541
+ },
542
+ enumerable: false,
543
+ configurable: true
544
+ });
545
+ Object.defineProperty(DockviewComponent.prototype, "_edgeGroupService", {
546
+ get: function () {
547
+ return this._moduleRegistry.services.edgeGroupService;
548
+ },
549
+ enumerable: false,
550
+ configurable: true
551
+ });
552
+ Object.defineProperty(DockviewComponent.prototype, "_rootDropTargetService", {
553
+ get: function () {
554
+ // Optional like every other module service — RootDropTargetModule can be
555
+ // removed from the registered set without crashing the component.
556
+ return this._moduleRegistry.services.rootDropTargetService;
557
+ },
558
+ enumerable: false,
559
+ configurable: true
560
+ });
561
+ Object.defineProperty(DockviewComponent.prototype, "_advancedDnDService", {
562
+ get: function () {
563
+ // Optional — callers `?.`-guard so the module can be removed from
564
+ // AllModules. Absent ⇒ the onWill* hooks simply don't fire (≡ no
565
+ // subscriber), which is invisible to apps not customising DnD.
566
+ return this._moduleRegistry.services.advancedDnDService;
567
+ },
568
+ enumerable: false,
569
+ configurable: true
570
+ });
571
+ Object.defineProperty(DockviewComponent.prototype, "headerActionsService", {
572
+ get: function () {
573
+ return this._moduleRegistry.services.headerActionsService;
574
+ },
575
+ enumerable: false,
576
+ configurable: true
577
+ });
578
+ DockviewComponent.prototype.isGridEmpty = function () {
579
+ return this.gridview.length === 0;
580
+ };
581
+ DockviewComponent.prototype.rootDropTargetOverrideTarget = function () {
582
+ var _a;
583
+ return (_a = this.rootDropTargetContainer) === null || _a === void 0 ? void 0 : _a.model;
584
+ };
585
+ DockviewComponent.prototype.dispatchUnhandledDragOver = function (nativeEvent, position) {
586
+ var event = new options_1.DockviewUnhandledDragOverEvent(nativeEvent, 'edge', position, dataTransfer_1.getPanelData);
587
+ this._onUnhandledDragOver.fire(event);
588
+ return event.isAccepted;
589
+ };
590
+ // IAdvancedDnDHost — the emitters stay here so the public onWill* event
591
+ // shape is unchanged; AdvancedDnDService routes the per-group fires
592
+ // through these. Engine guards (e.g. disableDnd) run on the component
593
+ // ahead of the dispatch.
594
+ DockviewComponent.prototype.fireWillDragPanel = function (event) {
595
+ this._onWillDragPanel.fire(event);
596
+ };
597
+ DockviewComponent.prototype.fireWillDragGroup = function (event) {
598
+ this._onWillDragGroup.fire(event);
599
+ };
600
+ DockviewComponent.prototype.fireWillDrop = function (event) {
601
+ this._onWillDrop.fire(event);
602
+ };
603
+ DockviewComponent.prototype.fireWillShowOverlay = function (event) {
604
+ this._onWillShowOverlay.fire(event);
605
+ };
606
+ /**
607
+ * Resolve the custom group drag ghost (via the AdvancedDnD module), or
608
+ * `undefined` to fall back to the default chip. Returns `undefined` when
609
+ * the module is absent — the default ghost then renders.
610
+ */
611
+ DockviewComponent.prototype.buildGroupDragGhost = function (group) {
612
+ var _a;
613
+ return (_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.buildGroupDragGhost(group);
614
+ };
615
+ /**
616
+ * Resolve the app-supplied drop overlay model (via the AdvancedDnD module)
617
+ * for a group drop target, or `undefined` to keep the target's default.
618
+ */
619
+ DockviewComponent.prototype.resolveDropOverlayModel = function (location, group) {
620
+ var _a;
621
+ return (_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.resolveOverlayModel(location, group);
622
+ };
623
+ Object.defineProperty(DockviewComponent.prototype, "rootElement", {
624
+ // IAccessibilityHost — keyboard docking reaches the AdvancedDnD preview +
625
+ // LiveRegion announcer through these so the service stays decoupled.
626
+ /** Outermost element — the shell (incl. edge groups) once built, else the gridview. */
627
+ get: function () {
628
+ var _a, _b;
629
+ return (_b = (_a = this._shellManager) === null || _a === void 0 ? void 0 : _a.element) !== null && _b !== void 0 ? _b : this.element;
630
+ },
631
+ enumerable: false,
632
+ configurable: true
633
+ });
634
+ /**
635
+ * The next / previous group in gridview (spatial) order, wrapping round.
636
+ * The keyboard accessibility module's focus navigation is built on this
637
+ * primitive — the only piece that needs the grid internals; the rest of
638
+ * the navigation logic lives in the AccessibilityService.
639
+ */
640
+ DockviewComponent.prototype.adjacentGroup = function (group, reverse) {
641
+ var _a;
642
+ // gridview traversal only covers grid groups; a floating/popout group
643
+ // isn't in the grid, so there's no adjacent grid group to step to.
644
+ if (group.api.location.type !== 'grid') {
645
+ return undefined;
646
+ }
647
+ var location = (0, gridview_1.getGridLocation)(group.element);
648
+ return ((_a = (reverse
649
+ ? this.gridview.previous(location)
650
+ : this.gridview.next(location))) === null || _a === void 0 ? void 0 : _a.view);
651
+ };
652
+ /**
653
+ * The nearest grid group in a spatial direction from `group`, by
654
+ * comparing group centre points. Floating and popout groups sit outside
655
+ * the grid's geometry and are ignored. Returns `undefined` when there is
656
+ * no group in that direction.
657
+ */
658
+ DockviewComponent.prototype.adjacentGroupInDirection = function (group, direction) {
659
+ var e_2, _a;
660
+ if (group.api.location.type !== 'grid') {
661
+ return undefined;
662
+ }
663
+ var from = group.element.getBoundingClientRect();
664
+ var fromX = from.left + from.width / 2;
665
+ var fromY = from.top + from.height / 2;
666
+ var best;
667
+ var bestDistance = Number.POSITIVE_INFINITY;
668
+ try {
669
+ for (var _b = __values(this.groups), _c = _b.next(); !_c.done; _c = _b.next()) {
670
+ var candidate = _c.value;
671
+ if (candidate === group || candidate.api.location.type !== 'grid') {
672
+ continue;
673
+ }
674
+ var rect = candidate.element.getBoundingClientRect();
675
+ var dx = rect.left + rect.width / 2 - fromX;
676
+ var dy = rect.top + rect.height / 2 - fromY;
677
+ // Require the candidate to sit predominantly in the asked-for
678
+ // direction (dominant axis), so 'left' ignores a group that's
679
+ // mostly above/below.
680
+ var inDirection = direction === 'left'
681
+ ? dx < 0 && Math.abs(dx) >= Math.abs(dy)
682
+ : direction === 'right'
683
+ ? dx > 0 && Math.abs(dx) >= Math.abs(dy)
684
+ : direction === 'up'
685
+ ? dy < 0 && Math.abs(dy) >= Math.abs(dx)
686
+ : dy > 0 && Math.abs(dy) >= Math.abs(dx);
687
+ if (!inDirection) {
688
+ continue;
689
+ }
690
+ var distance = dx * dx + dy * dy;
691
+ if (distance < bestDistance) {
692
+ bestDistance = distance;
693
+ best = candidate;
694
+ }
695
+ }
696
+ }
697
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
698
+ finally {
699
+ try {
700
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
701
+ }
702
+ finally { if (e_2) throw e_2.error; }
703
+ }
704
+ return best;
705
+ };
706
+ DockviewComponent.prototype.showDropPreview = function (group, position) {
707
+ var _a, _b;
708
+ return ((_b = (_a = this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.showPreviewOverlay(group, position)) !== null && _b !== void 0 ? _b : lifecycle_1.Disposable.NONE);
709
+ };
710
+ DockviewComponent.prototype.announce = function (message) {
711
+ var _a;
712
+ (_a = this._moduleRegistry.services.liveRegionService) === null || _a === void 0 ? void 0 : _a.announce(message);
713
+ };
714
+ DockviewComponent.prototype.dockPanel = function (panel, group, position) {
715
+ this.moveGroupOrPanel({
716
+ from: { groupId: panel.group.id, panelId: panel.id },
717
+ to: { group: group, position: position },
718
+ });
719
+ };
720
+ Object.defineProperty(DockviewComponent.prototype, "contextMenuService", {
721
+ get: function () {
722
+ // Owned by ContextMenuModule — undefined when the module is not
723
+ // registered, so callers must `?.`-guard.
724
+ return this._moduleRegistry.services.contextMenuService;
725
+ },
726
+ enumerable: false,
727
+ configurable: true
728
+ });
729
+ Object.defineProperty(DockviewComponent.prototype, "mountElement", {
730
+ get: function () {
731
+ return this.gridview.element;
496
732
  },
497
733
  enumerable: false,
498
734
  configurable: true
499
735
  });
736
+ DockviewComponent.prototype.hasVisibleGridGroup = function () {
737
+ return this.groups.some(function (group) { return group.api.location.type === 'grid' && group.api.isVisible; });
738
+ };
739
+ DockviewComponent.prototype.fireLayoutChange = function () {
740
+ this._bufferOnDidLayoutChange.fire();
741
+ };
500
742
  Object.defineProperty(DockviewComponent.prototype, "popoutRestorationPromise", {
501
743
  /**
502
744
  * Promise that resolves when all popout groups from the last fromJSON call are restored.
503
745
  * Useful for tests that need to wait for delayed popout creation.
504
746
  */
505
747
  get: function () {
506
- return this._popoutRestorationPromise;
748
+ var _a, _b;
749
+ return ((_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.restorationPromise) !== null && _b !== void 0 ? _b : Promise.resolve());
507
750
  },
508
751
  enumerable: false,
509
752
  configurable: true
@@ -538,12 +781,33 @@ var DockviewComponent = /** @class */ (function (_super) {
538
781
  * and dismisses on events from that window.
539
782
  */
540
783
  DockviewComponent.prototype.getPopupServiceForGroup = function (group) {
541
- var _a;
542
- return (_a = this._popoutPopupServices.get(group.id)) !== null && _a !== void 0 ? _a : this.popupService;
784
+ var _a, _b;
785
+ return ((_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.getPopupService(group.id)) !== null && _b !== void 0 ? _b : this.popupService);
543
786
  };
544
787
  DockviewComponent.prototype.addPopoutGroup = function (itemToPopout, options) {
545
788
  var _this = this;
546
- var _a, _b, _c, _d, _e, _f;
789
+ // The transaction brackets the synchronous structural change; the
790
+ // popout window opens asynchronously after it resolves.
791
+ return this.mutation('popout', function () {
792
+ return _this._doAddPopoutGroup(itemToPopout, options);
793
+ });
794
+ };
795
+ /** Enumerate the popout groups currently open in their own windows. */
796
+ DockviewComponent.prototype.getPopouts = function () {
797
+ var _a, _b;
798
+ return ((_b = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.entries.map(function (entry) { return ({
799
+ id: entry.popoutGroup.id,
800
+ group: entry.popoutGroup,
801
+ window: entry.getWindow(),
802
+ }); })) !== null && _b !== void 0 ? _b : []);
803
+ };
804
+ DockviewComponent.prototype._doAddPopoutGroup = function (itemToPopout, options) {
805
+ var _this = this;
806
+ var _a, _b, _c, _d, _e;
807
+ var service = (0, modules_1.assertModule)(this._popoutWindowService, 'PopoutWindow', 'api.addPopoutGroup');
808
+ if (!service) {
809
+ return Promise.resolve(false);
810
+ }
547
811
  if (itemToPopout instanceof dockviewGroupPanel_1.DockviewGroupPanel &&
548
812
  itemToPopout.model.location.type === 'edge') {
549
813
  // edge groups are permanent structural elements and cannot be popped out
@@ -569,16 +833,21 @@ var DockviewComponent = /** @class */ (function (_super) {
569
833
  }
570
834
  var box = getBox();
571
835
  var groupId = (_b = (_a = options === null || options === void 0 ? void 0 : options.overridePopoutGroup) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : this.getNextGroupId();
836
+ // Resolve the configured popout URL once (per-call override → global
837
+ // option). Recorded on the entry / group locations so it survives
838
+ // serialization; the '/popout.html' default is applied only when
839
+ // actually opening the window, not baked into saved layouts.
840
+ var resolvedPopoutUrl = (_c = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _c !== void 0 ? _c : (_d = this.options) === null || _d === void 0 ? void 0 : _d.popoutUrl;
572
841
  var _window = new popoutWindow_1.PopoutWindow("".concat(this.id, "-").concat(groupId), // unique id
573
842
  theme !== null && theme !== void 0 ? theme : '', {
574
- url: (_e = (_c = options === null || options === void 0 ? void 0 : options.popoutUrl) !== null && _c !== void 0 ? _c : (_d = this.options) === null || _d === void 0 ? void 0 : _d.popoutUrl) !== null && _e !== void 0 ? _e : '/popout.html',
843
+ url: resolvedPopoutUrl !== null && resolvedPopoutUrl !== void 0 ? resolvedPopoutUrl : '/popout.html',
575
844
  left: window.screenX + box.left,
576
845
  top: window.screenY + box.top,
577
846
  width: box.width,
578
847
  height: box.height,
579
848
  onDidOpen: options === null || options === void 0 ? void 0 : options.onDidOpen,
580
849
  onWillClose: options === null || options === void 0 ? void 0 : options.onWillClose,
581
- nonce: (_f = this.options) === null || _f === void 0 ? void 0 : _f.nonce,
850
+ nonce: (_e = this.options) === null || _e === void 0 ? void 0 : _e.nonce,
582
851
  });
583
852
  var popoutWindowDisposable = new lifecycle_1.CompositeDisposable(_window, _window.onDidClose(function () {
584
853
  popoutWindowDisposable.dispose();
@@ -586,15 +855,14 @@ var DockviewComponent = /** @class */ (function (_super) {
586
855
  return _window
587
856
  .open()
588
857
  .then(function (popoutContainer) {
589
- var _a;
858
+ var e_3, _a;
859
+ var _b, _c, _d, _e;
590
860
  if (_window.isDisposed) {
591
861
  return false;
592
862
  }
593
- var referenceGroup = (options === null || options === void 0 ? void 0 : options.referenceGroup)
594
- ? options.referenceGroup
595
- : itemToPopout instanceof dockviewPanel_1.DockviewPanel
596
- ? itemToPopout.group
597
- : itemToPopout;
863
+ var referenceGroup = (_b = options === null || options === void 0 ? void 0 : options.referenceGroup) !== null && _b !== void 0 ? _b : (itemToPopout instanceof dockviewPanel_1.DockviewPanel
864
+ ? itemToPopout.group
865
+ : itemToPopout);
598
866
  var referenceLocation = itemToPopout.api.location.type;
599
867
  /**
600
868
  * The group that is being added doesn't already exist within the DOM, the most likely occurrence
@@ -602,7 +870,12 @@ var DockviewComponent = /** @class */ (function (_super) {
602
870
  */
603
871
  var isGroupAddedToDom = referenceGroup.element.parentElement !== null;
604
872
  var group;
605
- if (!isGroupAddedToDom) {
873
+ if (options === null || options === void 0 ? void 0 : options.overridePopoutGridview) {
874
+ // Restoring a multi-group window: the anchor group is
875
+ // already built inside the supplied gridview.
876
+ group = (_c = options.overridePopoutGroup) !== null && _c !== void 0 ? _c : referenceGroup;
877
+ }
878
+ else if (!isGroupAddedToDom) {
606
879
  group = referenceGroup;
607
880
  }
608
881
  else if (options === null || options === void 0 ? void 0 : options.overridePopoutGroup) {
@@ -615,29 +888,46 @@ var DockviewComponent = /** @class */ (function (_super) {
615
888
  }
616
889
  }
617
890
  if (popoutContainer === null) {
618
- console.error('dockview: failed to create popout. perhaps you need to allow pop-ups for this website');
619
- popoutWindowDisposable.dispose();
620
- _this._onDidOpenPopoutWindowFail.fire();
621
- // if the popout window was blocked, we need to move the group back to the reference group
622
- // and set it to visible
623
- _this.movingLock(function () {
624
- return moveGroupWithoutDestroying({
625
- from: group,
626
- to: referenceGroup,
627
- });
891
+ _this.handleBlockedPopout({
892
+ group: group,
893
+ referenceGroup: referenceGroup,
894
+ options: options,
895
+ popoutWindowDisposable: popoutWindowDisposable,
628
896
  });
629
- if (!referenceGroup.api.isVisible) {
630
- referenceGroup.api.setVisible(true);
631
- }
632
897
  return false;
633
898
  }
634
899
  var gready = document.createElement('div');
635
900
  gready.className = 'dv-overlay-render-container';
636
901
  var overlayRenderContainer = new overlayRenderContainer_1.OverlayRenderContainer(gready, _this);
637
902
  group.model.renderContainer = overlayRenderContainer;
638
- group.layout(_window.window.innerWidth, _window.window.innerHeight);
903
+ // The popout window hosts its own gridview so it can grow into
904
+ // a nested splitview layout. The window starts with the single
905
+ // anchor group; further groups arrive via drag-and-drop. On
906
+ // restore a pre-populated gridview is supplied instead.
907
+ var popoutGridview = (_d = options === null || options === void 0 ? void 0 : options.overridePopoutGridview) !== null && _d !== void 0 ? _d : _this.createNestedGridview();
908
+ if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGridview)) {
909
+ popoutGridview.addView(group, splitview_1.Sizing.Distribute, [0]);
910
+ }
911
+ // Fill the popout window. Unlike the main grid (explicit px) and
912
+ // floating windows (CSS inside .dv-resize-container), the popout
913
+ // gridview has no sizing context, so without this it collapses
914
+ // to 0 height and nothing renders.
915
+ popoutGridview.element.style.width = '100%';
916
+ popoutGridview.element.style.height = '100%';
917
+ popoutGridview.layout(_window.window.innerWidth, _window.window.innerHeight);
918
+ // Guarded so the teardown's re-entrant paths (window close
919
+ // re-enters via the anchor's doRemoveGroup) never double-dispose.
920
+ var popoutGridviewDisposed = false;
921
+ var disposePopoutGridview = function () {
922
+ if (!popoutGridviewDisposed) {
923
+ popoutGridviewDisposed = true;
924
+ popoutGridview.dispose();
925
+ }
926
+ };
639
927
  var floatingBox;
640
- if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) && isGroupAddedToDom) {
928
+ if (!(options === null || options === void 0 ? void 0 : options.overridePopoutGroup) &&
929
+ !(options === null || options === void 0 ? void 0 : options.overridePopoutGridview) &&
930
+ isGroupAddedToDom) {
641
931
  if (itemToPopout instanceof dockviewPanel_1.DockviewPanel) {
642
932
  _this.movingLock(function () {
643
933
  var panel = referenceGroup.model.removePanel(itemToPopout);
@@ -657,11 +947,11 @@ var DockviewComponent = /** @class */ (function (_super) {
657
947
  break;
658
948
  case 'floating':
659
949
  case 'popout':
660
- floatingBox = (_a = _this._floatingGroups
950
+ floatingBox = (_e = _this.floatingGroups
661
951
  .find(function (value) {
662
952
  return value.group.api.id ===
663
953
  itemToPopout.api.id;
664
- })) === null || _a === void 0 ? void 0 : _a.overlay.toJSON();
954
+ })) === null || _e === void 0 ? void 0 : _e.overlay.toJSON();
665
955
  _this.removeGroup(referenceGroup);
666
956
  break;
667
957
  }
@@ -670,7 +960,7 @@ var DockviewComponent = /** @class */ (function (_super) {
670
960
  popoutContainer.classList.add('dv-dockview');
671
961
  popoutContainer.style.overflow = 'hidden';
672
962
  popoutContainer.appendChild(gready);
673
- popoutContainer.appendChild(group.element);
963
+ popoutContainer.appendChild(popoutGridview.element);
674
964
  var anchor = document.createElement('div');
675
965
  var dropTargetContainer = new dropTargetAnchorContainer_1.DropTargetAnchorContainer(anchor, { disabled: _this.rootDropTargetContainer.disabled });
676
966
  popoutContainer.appendChild(anchor);
@@ -681,20 +971,54 @@ var DockviewComponent = /** @class */ (function (_super) {
681
971
  // their pointerdown/keydown listeners fire on the right
682
972
  // window for outside-click and Escape dismissal.
683
973
  var popoutPopupService = new popupService_1.PopupService(popoutContainer, _window.window);
684
- _this._popoutPopupServices.set(group.id, popoutPopupService);
974
+ service.setPopupService(group.id, popoutPopupService);
685
975
  popoutWindowDisposable.addDisposables(popoutPopupService, lifecycle_1.Disposable.from(function () {
686
- _this._popoutPopupServices.delete(group.id);
976
+ service.deletePopupService(group.id);
687
977
  }));
688
978
  group.model.location = {
689
979
  type: 'popout',
690
980
  getWindow: function () { return _window.window; },
691
- popoutUrl: options === null || options === void 0 ? void 0 : options.popoutUrl,
981
+ popoutUrl: resolvedPopoutUrl,
692
982
  };
983
+ if (options === null || options === void 0 ? void 0 : options.overridePopoutGridview) {
984
+ // Restored multi-group window. Wire every member (including
985
+ // the anchor) to this window's containers and popout
986
+ // location now that the gridview is attached and laid out —
987
+ // re-setting renderContainer forces a re-render at the right
988
+ // time so 'always'-rendered content positions in this
989
+ // window rather than where it was first created.
990
+ var members = _this.groups.filter(function (candidate) {
991
+ return popoutGridview.element.contains(candidate.element);
992
+ });
993
+ try {
994
+ for (var members_1 = __values(members), members_1_1 = members_1.next(); !members_1_1.done; members_1_1 = members_1.next()) {
995
+ var member = members_1_1.value;
996
+ member.model.renderContainer = overlayRenderContainer;
997
+ member.model.dropTargetContainer = dropTargetContainer;
998
+ member.model.location = {
999
+ type: 'popout',
1000
+ getWindow: function () { return _window.window; },
1001
+ popoutUrl: resolvedPopoutUrl,
1002
+ };
1003
+ }
1004
+ }
1005
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
1006
+ finally {
1007
+ try {
1008
+ if (members_1_1 && !members_1_1.done && (_a = members_1.return)) _a.call(members_1);
1009
+ }
1010
+ finally { if (e_3) throw e_3.error; }
1011
+ }
1012
+ }
693
1013
  if (isGroupAddedToDom &&
694
1014
  itemToPopout.api.location.type === 'grid') {
695
1015
  itemToPopout.api.setVisible(false);
696
1016
  }
697
1017
  _this.doSetGroupAndPanelActive(group);
1018
+ var resizeObserverDisposable = service.observeGridviewSize(_window, popoutGridview, overlayRenderContainer);
1019
+ if (resizeObserverDisposable) {
1020
+ popoutWindowDisposable.addDisposables(resizeObserverDisposable);
1021
+ }
698
1022
  popoutWindowDisposable.addDisposables(group.api.onDidActiveChange(function (event) {
699
1023
  var _a;
700
1024
  if (event.isActive) {
@@ -704,20 +1028,28 @@ var DockviewComponent = /** @class */ (function (_super) {
704
1028
  var _a;
705
1029
  (_a = _window.window) === null || _a === void 0 ? void 0 : _a.focus();
706
1030
  }));
707
- var returnedGroup;
1031
+ // Holder so the close teardown (extracted below) can publish
1032
+ // the group that was returned to the main grid back to the
1033
+ // entry's `dispose()` contract.
1034
+ var closeResult = {};
708
1035
  var isValidReferenceGroup = isGroupAddedToDom &&
709
1036
  referenceGroup &&
710
1037
  _this.getPanel(referenceGroup.id);
711
1038
  var value = {
712
1039
  window: _window,
713
1040
  popoutGroup: group,
1041
+ gridview: popoutGridview,
1042
+ overlayRenderContainer: overlayRenderContainer,
1043
+ dropTargetContainer: dropTargetContainer,
1044
+ getWindow: function () { return _window.window; },
1045
+ popoutUrl: resolvedPopoutUrl,
714
1046
  referenceGroup: isValidReferenceGroup
715
1047
  ? referenceGroup.id
716
1048
  : undefined,
717
1049
  disposable: {
718
1050
  dispose: function () {
719
1051
  popoutWindowDisposable.dispose();
720
- return returnedGroup;
1052
+ return closeResult.returnedGroup;
721
1053
  },
722
1054
  },
723
1055
  };
@@ -734,85 +1066,257 @@ var DockviewComponent = /** @class */ (function (_super) {
734
1066
  screenY: _window.window.screenX,
735
1067
  group: group,
736
1068
  });
737
- }),
738
- /**
739
- * ResizeObserver seems slow here, I do not know why but we don't need it
740
- * since we can reply on the window resize event as we will occupy the full
741
- * window dimensions
742
- */
743
- (0, events_1.addDisposableListener)(_window.window, 'resize', function () {
744
- group.layout(_window.window.innerWidth, _window.window.innerHeight);
1069
+ }), (0, events_1.addDisposableListener)(_window.window, 'resize', function () {
1070
+ popoutGridview.layout(_window.window.innerWidth, _window.window.innerHeight);
745
1071
  }), overlayRenderContainer, lifecycle_1.Disposable.from(function () {
746
- if (_this.isDisposed) {
747
- return; // cleanup may run after instance is disposed
1072
+ return _this.disposePopoutWindow({
1073
+ group: group,
1074
+ referenceGroup: referenceGroup,
1075
+ popoutGridview: popoutGridview,
1076
+ isGroupAddedToDom: isGroupAddedToDom,
1077
+ floatingBox: floatingBox,
1078
+ disposePopoutGridview: disposePopoutGridview,
1079
+ closeResult: closeResult,
1080
+ });
1081
+ }));
1082
+ service.add(value);
1083
+ _this._onDidAddPopoutGroup.fire({
1084
+ id: value.popoutGroup.id,
1085
+ group: value.popoutGroup,
1086
+ window: value.getWindow(),
1087
+ });
1088
+ return true;
1089
+ })
1090
+ .catch(function (err) {
1091
+ console.error('dockview: failed to create popout.', err);
1092
+ return false;
1093
+ });
1094
+ };
1095
+ /**
1096
+ * The popout window was blocked (e.g. by the browser's popup blocker —
1097
+ * common when restoring popouts on load). Fall back gracefully so the
1098
+ * group(s) end up valid and visible in the main grid rather than as
1099
+ * orphans that later crash clear()/remove().
1100
+ */
1101
+ DockviewComponent.prototype.handleBlockedPopout = function (params) {
1102
+ var e_4, _a;
1103
+ var _this = this;
1104
+ var group = params.group, referenceGroup = params.referenceGroup, options = params.options, popoutWindowDisposable = params.popoutWindowDisposable;
1105
+ console.error('dockview: failed to create popout. perhaps you need to allow pop-ups for this website');
1106
+ popoutWindowDisposable.dispose();
1107
+ this._onDidOpenPopoutWindowFail.fire();
1108
+ if (options === null || options === void 0 ? void 0 : options.overridePopoutGridview) {
1109
+ // Restoring a multi-group popout window: its nested gridview was
1110
+ // built up-front but never attached to a window. Dock every member
1111
+ // into the main grid so no group is lost, then discard the
1112
+ // detached gridview.
1113
+ var blockedGridview_1 = options.overridePopoutGridview;
1114
+ var members = this.groups.filter(function (candidate) {
1115
+ return blockedGridview_1.element.contains(candidate.element);
1116
+ });
1117
+ var _loop_1 = function (member) {
1118
+ this_1.movingLock(function () {
1119
+ blockedGridview_1.remove(member);
1120
+ _this.redockGroupToMainGrid(member);
1121
+ });
1122
+ };
1123
+ var this_1 = this;
1124
+ try {
1125
+ for (var members_2 = __values(members), members_2_1 = members_2.next(); !members_2_1.done; members_2_1 = members_2.next()) {
1126
+ var member = members_2_1.value;
1127
+ _loop_1(member);
748
1128
  }
749
- if (isGroupAddedToDom &&
750
- _this.getPanel(referenceGroup.id)) {
751
- _this.movingLock(function () {
752
- return moveGroupWithoutDestroying({
753
- from: group,
754
- to: referenceGroup,
755
- });
1129
+ }
1130
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
1131
+ finally {
1132
+ try {
1133
+ if (members_2_1 && !members_2_1.done && (_a = members_2.return)) _a.call(members_2);
1134
+ }
1135
+ finally { if (e_4) throw e_4.error; }
1136
+ }
1137
+ blockedGridview_1.dispose();
1138
+ if (referenceGroup && !referenceGroup.api.isVisible) {
1139
+ referenceGroup.api.setVisible(true);
1140
+ }
1141
+ return;
1142
+ }
1143
+ if (group === referenceGroup) {
1144
+ // No separate grid group to return to (e.g. restoring a popout
1145
+ // straight from JSON) — dock this group into the main grid.
1146
+ if (!this.gridview.element.contains(group.element)) {
1147
+ this.movingLock(function () { return _this.doAddGroup(group, [0]); });
1148
+ group.model.location = { type: 'grid' };
1149
+ }
1150
+ }
1151
+ else {
1152
+ // A fresh group was created for the popout — return its panels to
1153
+ // the reference group and discard the now-empty popout group so it
1154
+ // doesn't linger as an orphan.
1155
+ this.movingLock(function () {
1156
+ return moveGroupWithoutDestroying({
1157
+ from: group,
1158
+ to: referenceGroup,
1159
+ });
1160
+ });
1161
+ if (group.model.size === 0 && this._groups.has(group.id)) {
1162
+ group.dispose();
1163
+ this._groups.delete(group.id);
1164
+ this._onDidRemoveGroup.fire(group);
1165
+ }
1166
+ }
1167
+ if (!referenceGroup.api.isVisible) {
1168
+ referenceGroup.api.setVisible(true);
1169
+ }
1170
+ };
1171
+ /**
1172
+ * Wire a group that has been displaced from a floating / popout window back
1173
+ * to the main grid's render & drop-target containers and dock it at the
1174
+ * root. The caller is responsible for first detaching it from its old
1175
+ * gridview — the detach strategy differs between the window-teardown path
1176
+ * (`doRemoveGroup`) and the blocked-window path (`gridview.remove`).
1177
+ */
1178
+ DockviewComponent.prototype.redockGroupToMainGrid = function (group) {
1179
+ group.model.renderContainer = this.overlayRenderContainer;
1180
+ group.model.dropTargetContainer = this.rootDropTargetContainer;
1181
+ group.model.location = { type: 'grid' };
1182
+ this.doAddGroup(group, [0]);
1183
+ };
1184
+ /**
1185
+ * Teardown for a popout window's `popoutWindowDisposable`. Runs when the
1186
+ * window closes (by user, by `removeGroup`, or by component disposal):
1187
+ * relocates every member group back to the main grid (or to a floating
1188
+ * window when the anchor came from one), then disposes the nested gridview.
1189
+ * `closeResult.returnedGroup` is read by the entry's `dispose()` contract.
1190
+ */
1191
+ DockviewComponent.prototype.disposePopoutWindow = function (params) {
1192
+ var e_5, _a;
1193
+ var _this = this;
1194
+ var _b;
1195
+ var group = params.group, referenceGroup = params.referenceGroup, popoutGridview = params.popoutGridview, isGroupAddedToDom = params.isGroupAddedToDom, floatingBox = params.floatingBox, disposePopoutGridview = params.disposePopoutGridview, closeResult = params.closeResult;
1196
+ if (this.isDisposed) {
1197
+ // cleanup may run after instance is disposed; just tear down the
1198
+ // nested gridview.
1199
+ disposePopoutGridview();
1200
+ return;
1201
+ }
1202
+ // Distinguish a genuine window close from an explicit `removeGroup`:
1203
+ // the explicit-removal paths remove the service entry *before* this
1204
+ // disposable runs. Key off the stable `popoutGridview` rather than the
1205
+ // captured `group`, which may no longer be the window's anchor (it can
1206
+ // have been dragged out, promoting another member to anchor).
1207
+ var genuineClose = !!((_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.entries.find(function (entry) { return entry.gridview === popoutGridview; }));
1208
+ // The groups still living in this window, resolved from the gridview so
1209
+ // a reassigned anchor doesn't hide surviving members.
1210
+ var members = this.groups.filter(function (candidate) {
1211
+ return popoutGridview.element.contains(candidate.element);
1212
+ });
1213
+ var anchorPresent = members.includes(group);
1214
+ var anchorIsSoleMember = anchorPresent && members.length === 1;
1215
+ // On a genuine close, relocate every member that ISN'T the captured
1216
+ // anchor back to the main grid. The captured anchor (if still here) gets
1217
+ // the reference-return / re-float treatment below. Explicit removal
1218
+ // relocates via its own path, so the loop is skipped for it.
1219
+ if (genuineClose) {
1220
+ var _loop_2 = function (member) {
1221
+ if (member === group) {
1222
+ return "continue";
1223
+ }
1224
+ this_2.movingLock(function () {
1225
+ _this.doRemoveGroup(member, {
1226
+ skipDispose: true,
1227
+ skipActive: true,
1228
+ skipPopoutReturn: true,
756
1229
  });
757
- if (!referenceGroup.api.isVisible) {
758
- referenceGroup.api.setVisible(true);
759
- }
760
- if (_this.getPanel(group.id)) {
761
- _this.doRemoveGroup(group, {
762
- skipPopoutAssociated: true,
763
- });
764
- }
1230
+ _this.redockGroupToMainGrid(member);
1231
+ });
1232
+ };
1233
+ var this_2 = this;
1234
+ try {
1235
+ for (var members_3 = __values(members), members_3_1 = members_3.next(); !members_3_1.done; members_3_1 = members_3.next()) {
1236
+ var member = members_3_1.value;
1237
+ _loop_2(member);
765
1238
  }
766
- else if (_this.getPanel(group.id)) {
767
- group.model.renderContainer =
768
- _this.overlayRenderContainer;
769
- group.model.dropTargetContainer =
770
- _this.rootDropTargetContainer;
771
- returnedGroup = group;
772
- var alreadyRemoved = !_this._popoutGroups.find(function (p) { return p.popoutGroup === group; });
773
- if (alreadyRemoved) {
774
- /**
775
- * If this popout group was explicitly removed then we shouldn't run the additional
776
- * steps. To tell if the running of this disposable is the result of this popout group
777
- * being explicitly removed we can check if this popout group is still referenced in
778
- * the `this._popoutGroups` list.
779
- */
780
- return;
781
- }
782
- if (floatingBox) {
783
- _this.addFloatingGroup(group, {
784
- height: floatingBox.height,
785
- width: floatingBox.width,
786
- position: floatingBox,
787
- });
788
- }
789
- else {
790
- _this.doRemoveGroup(group, {
791
- skipDispose: true,
792
- skipActive: true,
793
- skipPopoutReturn: true,
794
- });
795
- group.model.location = { type: 'grid' };
796
- _this.movingLock(function () {
797
- // suppress group add events since the group already exists
798
- _this.doAddGroup(group, [0]);
799
- });
800
- }
801
- _this.doSetGroupAndPanelActive(group);
1239
+ }
1240
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
1241
+ finally {
1242
+ try {
1243
+ if (members_3_1 && !members_3_1.done && (_a = members_3.return)) _a.call(members_3);
802
1244
  }
803
- }));
804
- _this._popoutGroups.push(value);
805
- _this.updateWatermark();
806
- return true;
807
- })
808
- .catch(function (err) {
809
- console.error('dockview: failed to create popout.', err);
810
- return false;
811
- });
1245
+ finally { if (e_5) throw e_5.error; }
1246
+ }
1247
+ }
1248
+ if (anchorPresent &&
1249
+ isGroupAddedToDom &&
1250
+ this.getPanel(referenceGroup.id)) {
1251
+ this.movingLock(function () {
1252
+ return moveGroupWithoutDestroying({
1253
+ from: group,
1254
+ to: referenceGroup,
1255
+ });
1256
+ });
1257
+ if (!referenceGroup.api.isVisible) {
1258
+ referenceGroup.api.setVisible(true);
1259
+ }
1260
+ if (this.getPanel(group.id)) {
1261
+ this.doRemoveGroup(group, {
1262
+ skipPopoutAssociated: true,
1263
+ });
1264
+ }
1265
+ }
1266
+ else if (anchorPresent && this.getPanel(group.id)) {
1267
+ group.model.renderContainer = this.overlayRenderContainer;
1268
+ group.model.dropTargetContainer = this.rootDropTargetContainer;
1269
+ closeResult.returnedGroup = group;
1270
+ if (!genuineClose) {
1271
+ /**
1272
+ * If this popout group was explicitly removed then we shouldn't run the additional
1273
+ * steps. The explicit remover re-docks the returned group itself; here we only hand
1274
+ * it back (above) and tear down the nested gridview.
1275
+ */
1276
+ disposePopoutGridview();
1277
+ return;
1278
+ }
1279
+ // Re-float only restores the pre-popout state of a SINGLE popped-out
1280
+ // group. A multi-group window must not be split (anchor re-floats
1281
+ // while the rest dock to the grid), so dock the anchor to the grid
1282
+ // alongside the other members once they're no longer alone.
1283
+ if (floatingBox && anchorIsSoleMember) {
1284
+ this.addFloatingGroup(group, {
1285
+ height: floatingBox.height,
1286
+ width: floatingBox.width,
1287
+ position: floatingBox,
1288
+ });
1289
+ }
1290
+ else {
1291
+ this.doRemoveGroup(group, {
1292
+ skipDispose: true,
1293
+ skipActive: true,
1294
+ skipPopoutReturn: true,
1295
+ });
1296
+ group.model.location = { type: 'grid' };
1297
+ this.movingLock(function () {
1298
+ // suppress group add events since the group already exists
1299
+ _this.doAddGroup(group, [0]);
1300
+ });
1301
+ }
1302
+ this.doSetGroupAndPanelActive(group);
1303
+ }
1304
+ // All members have been relocated out; tear down the window's nested
1305
+ // gridview (does not dispose the leaf views — their lifecycle stays
1306
+ // with `_groups`).
1307
+ disposePopoutGridview();
812
1308
  };
813
1309
  DockviewComponent.prototype.addFloatingGroup = function (item, options) {
814
1310
  var _this = this;
815
- var _a, _b, _c, _d, _e, _f;
1311
+ this.mutation('float', function () { return _this._doAddFloatingGroup(item, options); });
1312
+ };
1313
+ DockviewComponent.prototype._doAddFloatingGroup = function (item, options) {
1314
+ var _this = this;
1315
+ var _a;
1316
+ var service = (0, modules_1.assertModule)(this._floatingGroupService, 'FloatingGroup', 'api.addFloatingGroup');
1317
+ if (!service) {
1318
+ return;
1319
+ }
816
1320
  if (item instanceof dockviewGroupPanel_1.DockviewGroupPanel &&
817
1321
  item.model.location.type === 'edge') {
818
1322
  // edge groups are permanent structural elements and cannot be floated
@@ -835,7 +1339,7 @@ var DockviewComponent = /** @class */ (function (_super) {
835
1339
  }
836
1340
  else {
837
1341
  group = item;
838
- var popoutReferenceGroupId = (_a = this._popoutGroups.find(function (_) { return _.popoutGroup === group; })) === null || _a === void 0 ? void 0 : _a.referenceGroup;
1342
+ var popoutReferenceGroupId = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.findReferenceGroupId(group);
839
1343
  var popoutReferenceGroup_1 = popoutReferenceGroupId
840
1344
  ? this.getPanel(popoutReferenceGroupId)
841
1345
  : undefined;
@@ -918,65 +1422,104 @@ var DockviewComponent = /** @class */ (function (_super) {
918
1422
  };
919
1423
  }
920
1424
  var anchoredBox = getAnchoredBox();
921
- var overlay = new overlay_1.Overlay(__assign(__assign({ container: (_b = this._floatingOverlayHost) !== null && _b !== void 0 ? _b : this.gridview.element, content: group.element }, anchoredBox), { minimumInViewportWidth: this.options.floatingGroupBounds === 'boundedWithinViewport'
1425
+ // The floating window hosts its own gridview so it can grow into a
1426
+ // nested splitview layout. The window starts with the single anchor
1427
+ // group; further groups are added via drag-and-drop.
1428
+ var floatingGridview = this.createNestedGridview();
1429
+ floatingGridview.addView(group, splitview_1.Sizing.Distribute, [0]);
1430
+ this.mountFloatingWindow(floatingGridview, group, [group], anchoredBox, {
1431
+ dragHandle: options === null || options === void 0 ? void 0 : options.dragHandle,
1432
+ inDragMode: options === null || options === void 0 ? void 0 : options.inDragMode,
1433
+ skipActiveGroup: options === null || options === void 0 ? void 0 : options.skipActiveGroup,
1434
+ });
1435
+ };
1436
+ /**
1437
+ * Build an empty gridview configured to match the main grid's styling, for
1438
+ * hosting a nested layout inside a floating or popout window.
1439
+ */
1440
+ DockviewComponent.prototype.createNestedGridview = function (orientation) {
1441
+ var _a, _b;
1442
+ if (orientation === void 0) { orientation = splitview_1.Orientation.HORIZONTAL; }
1443
+ return new gridview_1.Gridview(true, this.options.hideBorders
1444
+ ? { separatorBorder: 'transparent' }
1445
+ : undefined, orientation, false, (_b = (_a = this.options.theme) === null || _a === void 0 ? void 0 : _a.gap) !== null && _b !== void 0 ? _b : 0);
1446
+ };
1447
+ /**
1448
+ * Wrap a (populated) floating gridview in an overlay window: title bar /
1449
+ * move handle, drag wiring, the floating-group service entry and the
1450
+ * `floating` location tag for every member group.
1451
+ */
1452
+ DockviewComponent.prototype.mountFloatingWindow = function (floatingGridview, anchorGroup, members, anchoredBox, options) {
1453
+ var e_6, _a;
1454
+ var _this = this;
1455
+ var _b, _c, _d, _e, _f, _g, _h, _j;
1456
+ var service = (0, modules_1.assertModule)(this._floatingGroupService, 'FloatingGroup', 'api.addFloatingGroup');
1457
+ if (!service) {
1458
+ return;
1459
+ }
1460
+ var dragHandleMode = (_c = (_b = options === null || options === void 0 ? void 0 : options.dragHandle) !== null && _b !== void 0 ? _b : this.options.floatingGroupDragHandle) !== null && _c !== void 0 ? _c : 'titlebar';
1461
+ // `'titlebar'` renders a dedicated grab bar above the tab bar and uses
1462
+ // it as the move handle; `'tabbar'` falls back to moving via the
1463
+ // tab-bar void container.
1464
+ var titleBar = dragHandleMode === 'titlebar'
1465
+ ? new floatingTitleBar_1.FloatingTitleBar(this, anchorGroup)
1466
+ : undefined;
1467
+ var overlay = new overlay_1.Overlay(__assign(__assign({ container: (_d = this._floatingOverlayHost) !== null && _d !== void 0 ? _d : this.gridview.element, content: floatingGridview.element, header: titleBar === null || titleBar === void 0 ? void 0 : titleBar.element }, anchoredBox), { minimumInViewportWidth: this.options.floatingGroupBounds === 'boundedWithinViewport'
922
1468
  ? undefined
923
- : ((_d = (_c = this.options.floatingGroupBounds) === null || _c === void 0 ? void 0 : _c.minimumWidthWithinViewport) !== null && _d !== void 0 ? _d : constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE), minimumInViewportHeight: this.options.floatingGroupBounds === 'boundedWithinViewport'
1469
+ : ((_f = (_e = this.options.floatingGroupBounds) === null || _e === void 0 ? void 0 : _e.minimumWidthWithinViewport) !== null && _f !== void 0 ? _f : constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE), minimumInViewportHeight: this.options.floatingGroupBounds === 'boundedWithinViewport'
924
1470
  ? undefined
925
- : ((_f = (_e = this.options.floatingGroupBounds) === null || _e === void 0 ? void 0 : _e.minimumHeightWithinViewport) !== null && _f !== void 0 ? _f : constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE) }));
926
- var el = group.element.querySelector('.dv-void-container');
927
- if (!el) {
1471
+ : ((_h = (_g = this.options.floatingGroupBounds) === null || _g === void 0 ? void 0 : _g.minimumHeightWithinViewport) !== null && _h !== void 0 ? _h : constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE), transformDragPosition: this.options.transformFloatingGroupDrag
1472
+ ? function (context) {
1473
+ return _this.options.transformFloatingGroupDrag({
1474
+ group: anchorGroup,
1475
+ proposed: context.proposed,
1476
+ container: context.container,
1477
+ others: context.others,
1478
+ });
1479
+ }
1480
+ : undefined, getSiblingBoxes: function () { return _this._gatherFloatingGroupBoxes(anchorGroup); } }));
1481
+ var dragHandle = (_j = titleBar === null || titleBar === void 0 ? void 0 : titleBar.element) !== null && _j !== void 0 ? _j : anchorGroup.element.querySelector('.dv-void-container');
1482
+ if (!dragHandle) {
928
1483
  throw new Error('dockview: failed to find drag handle');
929
1484
  }
930
- overlay.setupDrag(el, {
1485
+ overlay.setupDrag(dragHandle, {
931
1486
  inDragMode: typeof (options === null || options === void 0 ? void 0 : options.inDragMode) === 'boolean'
932
1487
  ? options.inDragMode
933
1488
  : false,
934
1489
  });
935
- var floatingGroupPanel = new dockviewFloatingGroupPanel_1.DockviewFloatingGroupPanel(group, overlay);
936
- var disposable = new lifecycle_1.CompositeDisposable(group.api.onDidActiveChange(function (event) {
937
- if (event.isActive) {
938
- overlay.bringToFront();
939
- }
940
- }), (function () {
941
- var lastWidth = -1;
942
- var lastHeight = -1;
943
- return (0, dom_1.watchElementResize)(group.element, function (entry) {
944
- var width = Math.round(entry.contentRect.width);
945
- var height = Math.round(entry.contentRect.height);
946
- if (width === lastWidth && height === lastHeight) {
947
- return;
948
- }
949
- lastWidth = width;
950
- lastHeight = height;
951
- group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
952
- });
953
- })());
954
- floatingGroupPanel.addDisposables(overlay.onDidChange(function () {
955
- // this is either a resize or a move
956
- // to inform the panels .layout(...) the group with it's current size
957
- // don't care about resize since the above watcher handles that
958
- group.layout(group.width, group.height);
959
- }), overlay.onDidChangeEnd(function () {
960
- _this._bufferOnDidLayoutChange.fire();
961
- }), group.onDidChange(function (event) {
962
- overlay.setBounds({
963
- height: event === null || event === void 0 ? void 0 : event.height,
964
- width: event === null || event === void 0 ? void 0 : event.width,
965
- });
966
- }), {
967
- dispose: function () {
968
- disposable.dispose();
969
- (0, array_1.remove)(_this._floatingGroups, floatingGroupPanel);
970
- group.model.location = { type: 'grid' };
971
- _this.updateWatermark();
972
- },
973
- });
974
- this._floatingGroups.push(floatingGroupPanel);
975
- group.model.location = { type: 'floating' };
1490
+ var floatingGroupPanel = service.add(anchorGroup, overlay, floatingGridview);
1491
+ if (titleBar) {
1492
+ // Tie the title bar's lifetime to the floating window and surface
1493
+ // its redock drag through the same public `onWillDragGroup` event
1494
+ // the tab-bar handle uses. Register it so anchor reassignment (when
1495
+ // the original anchor leaves a multi-group window) retargets the
1496
+ // bar at a group that still lives here.
1497
+ floatingGroupPanel.setTitleBar(titleBar);
1498
+ floatingGroupPanel.addDisposables(titleBar, lifecycle_1.Disposable.from(function () {
1499
+ return floatingGroupPanel.setTitleBar(undefined);
1500
+ }), titleBar.onDragStart(function (event) {
1501
+ _this._onWillDragGroup.fire({
1502
+ nativeEvent: event,
1503
+ group: floatingGroupPanel.group,
1504
+ });
1505
+ }));
1506
+ }
1507
+ try {
1508
+ for (var members_4 = __values(members), members_4_1 = members_4.next(); !members_4_1.done; members_4_1 = members_4.next()) {
1509
+ var member = members_4_1.value;
1510
+ member.model.location = { type: 'floating' };
1511
+ }
1512
+ }
1513
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
1514
+ finally {
1515
+ try {
1516
+ if (members_4_1 && !members_4_1.done && (_a = members_4.return)) _a.call(members_4);
1517
+ }
1518
+ finally { if (e_6) throw e_6.error; }
1519
+ }
976
1520
  if (!(options === null || options === void 0 ? void 0 : options.skipActiveGroup)) {
977
- this.doSetGroupAndPanelActive(group);
1521
+ this.doSetGroupAndPanelActive(anchorGroup);
978
1522
  }
979
- this.updateWatermark();
980
1523
  };
981
1524
  DockviewComponent.prototype.orthogonalize = function (position, options) {
982
1525
  this.gridview.normalize();
@@ -1013,42 +1556,11 @@ var DockviewComponent = /** @class */ (function (_super) {
1013
1556
  }
1014
1557
  };
1015
1558
  DockviewComponent.prototype.updateOptions = function (options) {
1016
- var e_5, _a, e_6, _b, e_7, _c, e_8, _d;
1017
- var _e, _f, _g, _h, _j;
1559
+ var e_7, _a, e_8, _b;
1560
+ var _c, _d, _e, _f, _g;
1018
1561
  _super.prototype.updateOptions.call(this, options);
1019
- if ('floatingGroupBounds' in options) {
1020
- try {
1021
- for (var _k = __values(this._floatingGroups), _l = _k.next(); !_l.done; _l = _k.next()) {
1022
- var group = _l.value;
1023
- switch (options.floatingGroupBounds) {
1024
- case 'boundedWithinViewport':
1025
- group.overlay.minimumInViewportHeight = undefined;
1026
- group.overlay.minimumInViewportWidth = undefined;
1027
- break;
1028
- case undefined:
1029
- group.overlay.minimumInViewportHeight =
1030
- constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
1031
- group.overlay.minimumInViewportWidth =
1032
- constants_1.DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
1033
- break;
1034
- default:
1035
- group.overlay.minimumInViewportHeight =
1036
- (_e = options.floatingGroupBounds) === null || _e === void 0 ? void 0 : _e.minimumHeightWithinViewport;
1037
- group.overlay.minimumInViewportWidth =
1038
- (_f = options.floatingGroupBounds) === null || _f === void 0 ? void 0 : _f.minimumWidthWithinViewport;
1039
- }
1040
- group.overlay.setBounds();
1041
- }
1042
- }
1043
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
1044
- finally {
1045
- try {
1046
- if (_l && !_l.done && (_a = _k.return)) _a.call(_k);
1047
- }
1048
- finally { if (e_5) throw e_5.error; }
1049
- }
1050
- }
1051
- this.updateDropTargetModel(options);
1562
+ (_c = this._floatingGroupService) === null || _c === void 0 ? void 0 : _c.updateBounds(options);
1563
+ (_d = this._rootDropTargetService) === null || _d === void 0 ? void 0 : _d.setOptions(options);
1052
1564
  var oldDisableDnd = this.options.disableDnd;
1053
1565
  var oldDndStrategy = this.options.dndStrategy;
1054
1566
  this._options = __assign(__assign({}, this.options), options);
@@ -1064,55 +1576,38 @@ var DockviewComponent = /** @class */ (function (_super) {
1064
1576
  if ('createRightHeaderActionComponent' in options ||
1065
1577
  'createLeftHeaderActionComponent' in options ||
1066
1578
  'createPrefixHeaderActionComponent' in options) {
1067
- try {
1068
- for (var _m = __values(this.groups), _o = _m.next(); !_o.done; _o = _m.next()) {
1069
- var group = _o.value;
1070
- group.model.updateHeaderActions();
1071
- }
1072
- }
1073
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
1074
- finally {
1075
- try {
1076
- if (_o && !_o.done && (_b = _m.return)) _b.call(_m);
1077
- }
1078
- finally { if (e_6) throw e_6.error; }
1079
- }
1579
+ (_e = this.headerActionsService) === null || _e === void 0 ? void 0 : _e.refreshAll();
1080
1580
  }
1081
1581
  if ('createWatermarkComponent' in options) {
1082
- if (this._watermark) {
1083
- this._watermark.element.parentElement.remove();
1084
- (_h = (_g = this._watermark).dispose) === null || _h === void 0 ? void 0 : _h.call(_g);
1085
- this._watermark = null;
1086
- }
1087
- this.updateWatermark();
1582
+ (_f = this._watermarkService) === null || _f === void 0 ? void 0 : _f.refresh();
1088
1583
  try {
1089
- for (var _p = __values(this.groups), _q = _p.next(); !_q.done; _q = _p.next()) {
1090
- var group = _q.value;
1584
+ for (var _h = __values(this.groups), _j = _h.next(); !_j.done; _j = _h.next()) {
1585
+ var group = _j.value;
1091
1586
  group.model.refreshWatermark();
1092
1587
  }
1093
1588
  }
1094
1589
  catch (e_7_1) { e_7 = { error: e_7_1 }; }
1095
1590
  finally {
1096
1591
  try {
1097
- if (_q && !_q.done && (_c = _p.return)) _c.call(_p);
1592
+ if (_j && !_j.done && (_a = _h.return)) _a.call(_h);
1098
1593
  }
1099
1594
  finally { if (e_7) throw e_7.error; }
1100
1595
  }
1101
1596
  }
1102
1597
  if ('tabGroupColors' in options || 'tabGroupAccent' in options) {
1103
- this._tabGroupColorPalette.setEntries((_j = this._options.tabGroupColors) !== null && _j !== void 0 ? _j : tabGroupAccent_1.DEFAULT_TAB_GROUP_COLORS);
1598
+ this._tabGroupColorPalette.setEntries((_g = this._options.tabGroupColors) !== null && _g !== void 0 ? _g : tabGroupAccent_1.DEFAULT_TAB_GROUP_COLORS);
1104
1599
  this._tabGroupColorPalette.enabled =
1105
1600
  this._options.tabGroupAccent !== 'off';
1106
1601
  try {
1107
- for (var _r = __values(this.groups), _s = _r.next(); !_s.done; _s = _r.next()) {
1108
- var group = _s.value;
1602
+ for (var _k = __values(this.groups), _l = _k.next(); !_l.done; _l = _k.next()) {
1603
+ var group = _l.value;
1109
1604
  group.model.refreshTabGroupAccent();
1110
1605
  }
1111
1606
  }
1112
1607
  catch (e_8_1) { e_8 = { error: e_8_1 }; }
1113
1608
  finally {
1114
1609
  try {
1115
- if (_s && !_s.done && (_d = _r.return)) _d.call(_r);
1610
+ if (_l && !_l.done && (_b = _k.return)) _b.call(_k);
1116
1611
  }
1117
1612
  finally { if (e_8) throw e_8.error; }
1118
1613
  }
@@ -1121,7 +1616,7 @@ var DockviewComponent = /** @class */ (function (_super) {
1121
1616
  this._layoutFromShell(this.gridview.width, this.gridview.height);
1122
1617
  };
1123
1618
  DockviewComponent.prototype.layout = function (width, height, forceResize) {
1124
- var e_9, _a;
1619
+ var _a, _b;
1125
1620
  if (this._shellManager && !this._inShellLayout) {
1126
1621
  this._shellManager.layout(width, height);
1127
1622
  }
@@ -1129,22 +1624,9 @@ var DockviewComponent = /** @class */ (function (_super) {
1129
1624
  _super.prototype.layout.call(this, width, height, forceResize);
1130
1625
  }
1131
1626
  this._syncFloatingOverlayHost();
1132
- if (this._floatingGroups) {
1133
- try {
1134
- for (var _b = __values(this._floatingGroups), _c = _b.next(); !_c.done; _c = _b.next()) {
1135
- var floating = _c.value;
1136
- // ensure floting groups stay within visible boundaries
1137
- floating.overlay.setBounds();
1138
- }
1139
- }
1140
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
1141
- finally {
1142
- try {
1143
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1144
- }
1145
- finally { if (e_9) throw e_9.error; }
1146
- }
1147
- }
1627
+ // floatingGroupService may be undefined during super() (BaseGrid calls
1628
+ // layout(0, 0) before subclass field initialisers run).
1629
+ (_b = (_a = this._moduleRegistry) === null || _a === void 0 ? void 0 : _a.services.floatingGroupService) === null || _b === void 0 ? void 0 : _b.constrainBounds();
1148
1630
  };
1149
1631
  DockviewComponent.prototype._syncFloatingOverlayHost = function () {
1150
1632
  if (!this._floatingOverlayHost || !this._shellManager) {
@@ -1173,27 +1655,32 @@ var DockviewComponent = /** @class */ (function (_super) {
1173
1655
  };
1174
1656
  DockviewComponent.prototype.addEdgeGroup = function (position, options) {
1175
1657
  var _this = this;
1176
- if (this._edgeGroups.has(position)) {
1658
+ var service = (0, modules_1.assertModule)(this._edgeGroupService, 'EdgeGroup', 'api.addEdgeGroup');
1659
+ if (!service) {
1660
+ throw new Error("dockview: EdgeGroup module is not registered");
1661
+ }
1662
+ if (service.has(position)) {
1177
1663
  throw new Error("dockview: edge group already exists at position '".concat(position, "'"));
1178
1664
  }
1179
- var group = this.createGroup({ id: options.id });
1180
- group.model.location = { type: 'edge', position: position };
1181
- group.model.headerPosition = position;
1182
- this._edgeGroups.set(position, group);
1183
- this._onDidAddGroup.fire(group);
1184
- // Collapse when the group becomes empty
1185
- var autoCollapseDisposable = group.model.onDidRemovePanel(function () {
1186
- if (group.model.isEmpty) {
1187
- _this.setEdgeGroupCollapsed(group, true);
1188
- }
1665
+ return this.mutation('add', function () {
1666
+ var group = _this.createGroup({ id: options.id });
1667
+ group.model.location = { type: 'edge', position: position };
1668
+ group.model.headerPosition = position;
1669
+ // Collapse when the group becomes empty
1670
+ var autoCollapseDisposable = group.model.onDidRemovePanel(function () {
1671
+ if (group.model.isEmpty) {
1672
+ _this.setEdgeGroupCollapsed(group, true);
1673
+ }
1674
+ });
1675
+ service.add(position, group, autoCollapseDisposable);
1676
+ _this._onDidAddGroup.fire(group);
1677
+ _this._shellManager.addEdgeView(position, options, group);
1678
+ return group.api;
1189
1679
  });
1190
- this._edgeGroupDisposables.set(position, autoCollapseDisposable);
1191
- this._shellManager.addEdgeView(position, options, group);
1192
- return group.api;
1193
1680
  };
1194
1681
  DockviewComponent.prototype.getEdgeGroup = function (position) {
1195
- var _a;
1196
- return (_a = this._edgeGroups.get(position)) === null || _a === void 0 ? void 0 : _a.api;
1682
+ var _a, _b;
1683
+ return (_b = (_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.get(position)) === null || _b === void 0 ? void 0 : _b.api;
1197
1684
  };
1198
1685
  DockviewComponent.prototype.setEdgeGroupVisible = function (position, visible) {
1199
1686
  this._shellManager.setEdgeGroupVisible(position, visible);
@@ -1202,90 +1689,69 @@ var DockviewComponent = /** @class */ (function (_super) {
1202
1689
  return this._shellManager.isEdgeGroupVisible(position);
1203
1690
  };
1204
1691
  DockviewComponent.prototype.removeEdgeGroup = function (position) {
1205
- var e_10, _a;
1206
- var _b;
1207
- var group = this._edgeGroups.get(position);
1692
+ var _this = this;
1693
+ var service = (0, modules_1.assertModule)(this._edgeGroupService, 'EdgeGroup', 'api.removeEdgeGroup');
1694
+ if (!service) {
1695
+ return;
1696
+ }
1697
+ var group = service.get(position);
1208
1698
  if (!group) {
1209
1699
  throw new Error("dockview: no edge group exists at position '".concat(position, "'"));
1210
1700
  }
1211
- try {
1212
- // Remove panels inside the group first
1213
- for (var _c = __values(__spreadArray([], __read(group.panels), false)), _d = _c.next(); !_d.done; _d = _c.next()) {
1214
- var panel = _d.value;
1215
- this.removePanel(panel, {
1216
- removeEmptyGroup: false,
1217
- skipDispose: false,
1218
- });
1219
- }
1220
- }
1221
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
1222
- finally {
1701
+ // One transaction — the per-panel removals below nest via the depth
1702
+ // counter, so consumers see a single edge-group removal.
1703
+ this.mutation('remove', function () {
1704
+ var e_9, _a;
1223
1705
  try {
1224
- if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
1225
- }
1226
- finally { if (e_10) throw e_10.error; }
1227
- }
1228
- // Dispose the auto-collapse listener
1229
- (_b = this._edgeGroupDisposables.get(position)) === null || _b === void 0 ? void 0 : _b.dispose();
1230
- this._edgeGroupDisposables.delete(position);
1231
- // Remove from the shell splitview
1232
- this._shellManager.removeEdgeView(position);
1233
- // Clean up group state
1234
- this._edgeGroups.delete(position);
1235
- group.dispose();
1236
- this._groups.delete(group.id);
1237
- this._onDidRemoveGroup.fire(group);
1238
- };
1239
- DockviewComponent.prototype.setEdgeGroupCollapsed = function (group, collapsed) {
1240
- var e_11, _a;
1241
- try {
1242
- for (var _b = __values(this._edgeGroups), _c = _b.next(); !_c.done; _c = _b.next()) {
1243
- var _d = __read(_c.value, 2), position = _d[0], edgeGroup = _d[1];
1244
- if (edgeGroup === group) {
1245
- if (this._shellManager.isEdgeGroupCollapsed(position) ===
1246
- collapsed) {
1247
- // Skip the splitview resize on a no-op: with non-zero
1248
- // theme gap, redundant resizeView calls accumulate
1249
- // rounding drift that gradually shrinks the group.
1250
- return;
1251
- }
1252
- this._shellManager.setEdgeGroupCollapsed(position, collapsed);
1253
- edgeGroup.api._onDidCollapsedChange.fire({
1254
- isCollapsed: collapsed,
1706
+ // Remove panels inside the group first
1707
+ for (var _b = __values(__spreadArray([], __read(group.panels), false)), _c = _b.next(); !_c.done; _c = _b.next()) {
1708
+ var panel = _c.value;
1709
+ _this.removePanel(panel, {
1710
+ removeEmptyGroup: false,
1711
+ skipDispose: false,
1255
1712
  });
1256
- return;
1257
1713
  }
1258
1714
  }
1259
- }
1260
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
1261
- finally {
1262
- try {
1263
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1264
- }
1265
- finally { if (e_11) throw e_11.error; }
1266
- }
1267
- };
1268
- DockviewComponent.prototype.isEdgeGroupCollapsed = function (group) {
1269
- var e_12, _a;
1270
- try {
1271
- for (var _b = __values(this._edgeGroups), _c = _b.next(); !_c.done; _c = _b.next()) {
1272
- var _d = __read(_c.value, 2), position = _d[0], edgeGroup = _d[1];
1273
- if (edgeGroup === group) {
1274
- return this._shellManager.isEdgeGroupCollapsed(position);
1715
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
1716
+ finally {
1717
+ try {
1718
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1275
1719
  }
1720
+ finally { if (e_9) throw e_9.error; }
1276
1721
  }
1722
+ // Remove from the shell splitview
1723
+ _this._shellManager.removeEdgeView(position);
1724
+ // Clean up service-tracked state + group itself
1725
+ service.remove(position);
1726
+ group.dispose();
1727
+ _this._groups.delete(group.id);
1728
+ _this._onDidRemoveGroup.fire(group);
1729
+ });
1730
+ };
1731
+ DockviewComponent.prototype.setEdgeGroupCollapsed = function (group, collapsed) {
1732
+ var _a;
1733
+ var position = (_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.findPositionOf(group);
1734
+ if (!position) {
1735
+ return;
1277
1736
  }
1278
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
1279
- finally {
1280
- try {
1281
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1282
- }
1283
- finally { if (e_12) throw e_12.error; }
1737
+ if (this._shellManager.isEdgeGroupCollapsed(position) === collapsed) {
1738
+ // Skip the splitview resize on a no-op: with non-zero theme gap,
1739
+ // redundant resizeView calls accumulate rounding drift that
1740
+ // gradually shrinks the group.
1741
+ return;
1284
1742
  }
1285
- return false;
1743
+ this._shellManager.setEdgeGroupCollapsed(position, collapsed);
1744
+ group.api._onDidCollapsedChange.fire({ isCollapsed: collapsed });
1745
+ };
1746
+ DockviewComponent.prototype.isEdgeGroupCollapsed = function (group) {
1747
+ var _a;
1748
+ var position = (_a = this._edgeGroupService) === null || _a === void 0 ? void 0 : _a.findPositionOf(group);
1749
+ return position
1750
+ ? this._shellManager.isEdgeGroupCollapsed(position)
1751
+ : false;
1286
1752
  };
1287
1753
  DockviewComponent.prototype.updateDragAndDropState = function () {
1288
- var e_13, _a;
1754
+ var e_10, _a;
1289
1755
  try {
1290
1756
  // Update draggable state for all tabs and void containers
1291
1757
  for (var _b = __values(this.groups), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -1293,12 +1759,12 @@ var DockviewComponent = /** @class */ (function (_super) {
1293
1759
  group.model.updateDragAndDropState();
1294
1760
  }
1295
1761
  }
1296
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
1762
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
1297
1763
  finally {
1298
1764
  try {
1299
1765
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1300
1766
  }
1301
- finally { if (e_13) throw e_13.error; }
1767
+ finally { if (e_10) throw e_10.error; }
1302
1768
  }
1303
1769
  };
1304
1770
  DockviewComponent.prototype.focus = function () {
@@ -1359,33 +1825,19 @@ var DockviewComponent = /** @class */ (function (_super) {
1359
1825
  * @returns A JSON respresentation of the layout
1360
1826
  */
1361
1827
  DockviewComponent.prototype.toJSON = function () {
1362
- var e_14, _a;
1363
- var _b;
1828
+ var e_11, _a;
1829
+ var _b, _c, _d, _e, _f, _g, _h, _j;
1364
1830
  var data = this.gridview.serialize();
1365
1831
  var panels = this.panels.reduce(function (collection, panel) {
1366
1832
  collection[panel.id] = panel.toJSON();
1367
1833
  return collection;
1368
1834
  }, {});
1369
- var floats = this._floatingGroups.map(function (group) {
1370
- return {
1371
- data: group.group.toJSON(),
1372
- position: group.overlay.toJSON(),
1373
- };
1374
- });
1375
- var popoutGroups = this._popoutGroups.map(function (group) {
1376
- return {
1377
- data: group.popoutGroup.toJSON(),
1378
- gridReferenceGroup: group.referenceGroup,
1379
- position: group.window.dimensions(),
1380
- url: group.popoutGroup.api.location.type === 'popout'
1381
- ? group.popoutGroup.api.location.popoutUrl
1382
- : undefined,
1383
- };
1384
- });
1835
+ var floats = (_c = (_b = this._floatingGroupService) === null || _b === void 0 ? void 0 : _b.serialize()) !== null && _c !== void 0 ? _c : [];
1836
+ var popoutGroups = (_e = (_d = this._popoutWindowService) === null || _d === void 0 ? void 0 : _d.serialize()) !== null && _e !== void 0 ? _e : [];
1385
1837
  var result = {
1386
1838
  grid: data,
1387
1839
  panels: panels,
1388
- activeGroup: (_b = this.activeGroup) === null || _b === void 0 ? void 0 : _b.id,
1840
+ activeGroup: (_f = this.activeGroup) === null || _f === void 0 ? void 0 : _f.id,
1389
1841
  };
1390
1842
  if (floats.length > 0) {
1391
1843
  result.floatingGroups = floats;
@@ -1393,53 +1845,47 @@ var DockviewComponent = /** @class */ (function (_super) {
1393
1845
  if (popoutGroups.length > 0) {
1394
1846
  result.popoutGroups = popoutGroups;
1395
1847
  }
1396
- if (this._edgeGroups.size > 0) {
1848
+ var edgeEntries = (_h = (_g = this._edgeGroupService) === null || _g === void 0 ? void 0 : _g.entries()) !== null && _h !== void 0 ? _h : [];
1849
+ if ((_j = this._edgeGroupService) === null || _j === void 0 ? void 0 : _j.hasAny()) {
1397
1850
  var shellSerialized = this._shellManager.toJSON();
1398
1851
  try {
1399
1852
  // Augment each entry with the serialized group state
1400
- for (var _c = __values(this._edgeGroups), _d = _c.next(); !_d.done; _d = _c.next()) {
1401
- var _e = __read(_d.value, 2), position = _e[0], group = _e[1];
1853
+ for (var edgeEntries_1 = __values(edgeEntries), edgeEntries_1_1 = edgeEntries_1.next(); !edgeEntries_1_1.done; edgeEntries_1_1 = edgeEntries_1.next()) {
1854
+ var _k = __read(edgeEntries_1_1.value, 2), position = _k[0], group = _k[1];
1402
1855
  var entry = shellSerialized[position];
1403
1856
  if (entry) {
1404
1857
  entry.group = group.toJSON();
1405
1858
  }
1406
1859
  }
1407
1860
  }
1408
- catch (e_14_1) { e_14 = { error: e_14_1 }; }
1861
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
1409
1862
  finally {
1410
1863
  try {
1411
- if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
1864
+ if (edgeEntries_1_1 && !edgeEntries_1_1.done && (_a = edgeEntries_1.return)) _a.call(edgeEntries_1);
1412
1865
  }
1413
- finally { if (e_14) throw e_14.error; }
1866
+ finally { if (e_11) throw e_11.error; }
1414
1867
  }
1415
1868
  result.edgeGroups = shellSerialized;
1416
1869
  }
1417
1870
  return result;
1418
1871
  };
1419
1872
  DockviewComponent.prototype.fromJSON = function (data, options) {
1420
- var e_15, _a, e_16, _b, e_17, _c, e_18, _d, e_19, _e, e_20, _f, e_21, _g, e_22, _h, e_23, _j, e_24, _k, e_25, _l;
1421
1873
  var _this = this;
1422
- var _m, _o, _p;
1423
- try {
1424
- // Cancel any popout-restoration timers queued by a previous fromJSON
1425
- // that haven't fired yet. Each cleanup also disposes the orphan group
1426
- // that was registered in _groups synchronously but never parented
1427
- // into a popout window — otherwise the upcoming clear() would call
1428
- // gridview.remove() on an unparented element and throw
1429
- // "Invalid grid element". See issue #1304.
1430
- for (var _q = __values(__spreadArray([], __read(this._popoutRestorationCleanups), false)), _r = _q.next(); !_r.done; _r = _q.next()) {
1431
- var cleanup = _r.value;
1432
- cleanup();
1433
- }
1434
- }
1435
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
1436
- finally {
1437
- try {
1438
- if (_r && !_r.done && (_a = _q.return)) _a.call(_q);
1439
- }
1440
- finally { if (e_15) throw e_15.error; }
1441
- }
1442
- this._popoutRestorationCleanups.clear();
1874
+ // One 'load' transaction for the whole deserialization — the many
1875
+ // nested add/remove mutations join it via the depth counter.
1876
+ this.mutation('load', function () { return _this._doFromJSON(data, options); });
1877
+ };
1878
+ DockviewComponent.prototype._doFromJSON = function (data, options) {
1879
+ var e_12, _a, e_13, _b, e_14, _c, e_15, _d;
1880
+ var _this = this;
1881
+ var _e, _f, _g, _h, _j, _k, _l;
1882
+ // Cancel any popout-restoration timers queued by a previous fromJSON
1883
+ // that haven't fired yet. The cancel path also disposes orphan groups
1884
+ // registered in _groups synchronously but never parented into a popout
1885
+ // window — otherwise the upcoming clear() would call gridview.remove()
1886
+ // on an unparented element and throw "Invalid grid element". See
1887
+ // issue #1304.
1888
+ (_e = this._popoutWindowService) === null || _e === void 0 ? void 0 : _e.cancelPendingRestorations();
1443
1889
  var existingPanels = new Map();
1444
1890
  var tempGroup;
1445
1891
  if (options === null || options === void 0 ? void 0 : options.reuseExistingPanels) {
@@ -1453,19 +1899,19 @@ var DockviewComponent = /** @class */ (function (_super) {
1453
1899
  this._groups.delete(tempGroup.api.id);
1454
1900
  var newPanels = Object.keys(data.panels);
1455
1901
  try {
1456
- for (var _s = __values(this.panels), _t = _s.next(); !_t.done; _t = _s.next()) {
1457
- var panel = _t.value;
1902
+ for (var _m = __values(this.panels), _o = _m.next(); !_o.done; _o = _m.next()) {
1903
+ var panel = _o.value;
1458
1904
  if (newPanels.includes(panel.api.id)) {
1459
1905
  existingPanels.set(panel.api.id, panel);
1460
1906
  }
1461
1907
  }
1462
1908
  }
1463
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
1909
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
1464
1910
  finally {
1465
1911
  try {
1466
- if (_t && !_t.done && (_b = _s.return)) _b.call(_s);
1912
+ if (_o && !_o.done && (_a = _m.return)) _a.call(_m);
1467
1913
  }
1468
- finally { if (e_16) throw e_16.error; }
1914
+ finally { if (e_12) throw e_12.error; }
1469
1915
  }
1470
1916
  this.movingLock(function () {
1471
1917
  Array.from(existingPanels.values()).forEach(function (panel) {
@@ -1496,10 +1942,10 @@ var DockviewComponent = /** @class */ (function (_super) {
1496
1942
  var width = this.width;
1497
1943
  var height = this.height;
1498
1944
  var createGroupFromSerializedState_1 = function (data) {
1499
- var e_26, _a;
1945
+ var e_16, _a;
1500
1946
  var id = data.id, locked = data.locked, hideHeader = data.hideHeader, headerPosition = data.headerPosition, views = data.views, activeView = data.activeView;
1501
1947
  if (typeof id !== 'string') {
1502
- throw new Error('dockview: group id must be of type string');
1948
+ throw new TypeError('dockview: group id must be of type string');
1503
1949
  }
1504
1950
  var group = _this.createGroup({
1505
1951
  id: id,
@@ -1509,7 +1955,7 @@ var DockviewComponent = /** @class */ (function (_super) {
1509
1955
  });
1510
1956
  _this._onDidAddGroup.fire(group);
1511
1957
  var createdPanels = [];
1512
- var _loop_1 = function (child) {
1958
+ var _loop_3 = function (child) {
1513
1959
  /**
1514
1960
  * Run the deserializer step seperately since this may fail to due corrupted external state.
1515
1961
  * In running this section first we avoid firing lots of 'add' events in the event of a failure
@@ -1529,19 +1975,19 @@ var DockviewComponent = /** @class */ (function (_super) {
1529
1975
  }
1530
1976
  };
1531
1977
  try {
1532
- for (var views_2 = __values(views), views_2_1 = views_2.next(); !views_2_1.done; views_2_1 = views_2.next()) {
1533
- var child = views_2_1.value;
1534
- _loop_1(child);
1978
+ for (var views_1 = __values(views), views_1_1 = views_1.next(); !views_1_1.done; views_1_1 = views_1.next()) {
1979
+ var child = views_1_1.value;
1980
+ _loop_3(child);
1535
1981
  }
1536
1982
  }
1537
- catch (e_26_1) { e_26 = { error: e_26_1 }; }
1983
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
1538
1984
  finally {
1539
1985
  try {
1540
- if (views_2_1 && !views_2_1.done && (_a = views_2.return)) _a.call(views_2);
1986
+ if (views_1_1 && !views_1_1.done && (_a = views_1.return)) _a.call(views_1);
1541
1987
  }
1542
- finally { if (e_26) throw e_26.error; }
1988
+ finally { if (e_16) throw e_16.error; }
1543
1989
  }
1544
- var _loop_2 = function (i) {
1990
+ var _loop_4 = function (i) {
1545
1991
  var panel = createdPanels[i];
1546
1992
  var isActive = typeof activeView === 'string' &&
1547
1993
  activeView === panel.id;
@@ -1562,7 +2008,7 @@ var DockviewComponent = /** @class */ (function (_super) {
1562
2008
  }
1563
2009
  };
1564
2010
  for (var i = 0; i < views.length; i++) {
1565
- _loop_2(i);
2011
+ _loop_4(i);
1566
2012
  }
1567
2013
  // Restore tab groups before activating a fallback panel so
1568
2014
  // that collapsed groups can clear the active panel correctly.
@@ -1583,199 +2029,23 @@ var DockviewComponent = /** @class */ (function (_super) {
1583
2029
  });
1584
2030
  this._layoutFromShell(width, height);
1585
2031
  if (data.edgeGroups) {
1586
- try {
1587
- // Auto-create edge groups for positions in the serialized state
1588
- // that don't already have a group registered (e.g. when fromJSON
1589
- // is called before the user has called addEdgeGroup).
1590
- for (var _u = __values([
1591
- 'top',
1592
- 'bottom',
1593
- 'left',
1594
- 'right',
1595
- ]), _v = _u.next(); !_v.done; _v = _u.next()) {
1596
- var _position = _v.value;
1597
- var fixedData = data.edgeGroups[_position];
1598
- if (fixedData && !this._edgeGroups.has(_position)) {
1599
- var groupState = fixedData.group;
1600
- var id = (_m = groupState === null || groupState === void 0 ? void 0 : groupState.id) !== null && _m !== void 0 ? _m : "".concat(_position, "-group");
1601
- this.addEdgeGroup(_position, { id: id });
1602
- }
1603
- }
1604
- }
1605
- catch (e_17_1) { e_17 = { error: e_17_1 }; }
1606
- finally {
1607
- try {
1608
- if (_v && !_v.done && (_c = _u.return)) _c.call(_u);
1609
- }
1610
- finally { if (e_17) throw e_17.error; }
1611
- }
1612
- try {
1613
- // Restore panel contents of edge groups
1614
- for (var _w = __values(this._edgeGroups), _x = _w.next(); !_x.done; _x = _w.next()) {
1615
- var _y = __read(_x.value, 2), position = _y[0], edgeGroup = _y[1];
1616
- var edgeData = data.edgeGroups[position];
1617
- var groupState = edgeData === null || edgeData === void 0 ? void 0 : edgeData.group;
1618
- if (groupState) {
1619
- var views = groupState.views, activeView = groupState.activeView;
1620
- var createdPanels = [];
1621
- try {
1622
- for (var views_1 = (e_19 = void 0, __values(views)), views_1_1 = views_1.next(); !views_1_1.done; views_1_1 = views_1.next()) {
1623
- var panelId = views_1_1.value;
1624
- if (panels[panelId]) {
1625
- var panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
1626
- createdPanels.push(panel);
1627
- }
1628
- }
1629
- }
1630
- catch (e_19_1) { e_19 = { error: e_19_1 }; }
1631
- finally {
1632
- try {
1633
- if (views_1_1 && !views_1_1.done && (_e = views_1.return)) _e.call(views_1);
1634
- }
1635
- finally { if (e_19) throw e_19.error; }
1636
- }
1637
- for (var i = 0; i < createdPanels.length; i++) {
1638
- var panel = createdPanels[i];
1639
- var isActive = activeView === panel.id;
1640
- edgeGroup.model.openPanel(panel, {
1641
- skipSetActive: !isActive,
1642
- skipSetGroupActive: true,
1643
- });
1644
- }
1645
- // Restore tab groups before activating a fallback panel
1646
- if (groupState.tabGroups &&
1647
- groupState.tabGroups.length > 0) {
1648
- edgeGroup.model.restoreTabGroups(groupState.tabGroups);
1649
- }
1650
- if (!edgeGroup.activePanel &&
1651
- edgeGroup.panels.length > 0) {
1652
- edgeGroup.model.openPanel(edgeGroup.panels[edgeGroup.panels.length - 1], { skipSetGroupActive: true });
1653
- }
1654
- }
1655
- }
1656
- }
1657
- catch (e_18_1) { e_18 = { error: e_18_1 }; }
1658
- finally {
1659
- try {
1660
- if (_x && !_x.done && (_d = _w.return)) _d.call(_w);
1661
- }
1662
- finally { if (e_18) throw e_18.error; }
1663
- }
1664
- this._shellManager.fromJSON(data.edgeGroups);
1665
- }
1666
- var serializedFloatingGroups = (_o = data.floatingGroups) !== null && _o !== void 0 ? _o : [];
1667
- try {
1668
- for (var serializedFloatingGroups_1 = __values(serializedFloatingGroups), serializedFloatingGroups_1_1 = serializedFloatingGroups_1.next(); !serializedFloatingGroups_1_1.done; serializedFloatingGroups_1_1 = serializedFloatingGroups_1.next()) {
1669
- var serializedFloatingGroup = serializedFloatingGroups_1_1.value;
1670
- var data_1 = serializedFloatingGroup.data, position = serializedFloatingGroup.position;
1671
- var group = createGroupFromSerializedState_1(data_1);
1672
- this.addFloatingGroup(group, {
1673
- position: position,
1674
- width: position.width,
1675
- height: position.height,
1676
- skipRemoveGroup: true,
1677
- inDragMode: false,
1678
- });
1679
- }
1680
- }
1681
- catch (e_20_1) { e_20 = { error: e_20_1 }; }
1682
- finally {
1683
- try {
1684
- if (serializedFloatingGroups_1_1 && !serializedFloatingGroups_1_1.done && (_f = serializedFloatingGroups_1.return)) _f.call(serializedFloatingGroups_1);
1685
- }
1686
- finally { if (e_20) throw e_20.error; }
1687
- }
1688
- var serializedPopoutGroups = (_p = data.popoutGroups) !== null && _p !== void 0 ? _p : [];
1689
- // Create a promise that resolves when all popout groups are created
1690
- var popoutPromises_1 = [];
1691
- // Queue popup group creation with delays to avoid browser blocking
1692
- serializedPopoutGroups.forEach(function (serializedPopoutGroup, index) {
1693
- var data = serializedPopoutGroup.data, position = serializedPopoutGroup.position, gridReferenceGroup = serializedPopoutGroup.gridReferenceGroup, url = serializedPopoutGroup.url;
1694
- var group = createGroupFromSerializedState_1(data);
1695
- // Add a small delay for each popup after the first to avoid browser popup blocking
1696
- var popoutPromise = new Promise(function (resolve) {
1697
- var cleanup = function () {
1698
- var e_27, _a;
1699
- _this._popoutRestorationCleanups.delete(cleanup);
1700
- clearTimeout(handle);
1701
- // The group was registered in _groups synchronously
1702
- // but the timer that would parent it into the popout
1703
- // window never ran. Dispose the orphan here so the
1704
- // next clear() doesn't trip over an unparented
1705
- // element. See issue #1304.
1706
- if (!_this.isDisposed &&
1707
- _this._groups.has(group.id) &&
1708
- group.element.parentElement === null) {
1709
- try {
1710
- for (var _b = __values(__spreadArray([], __read(group.panels), false)), _c = _b.next(); !_c.done; _c = _b.next()) {
1711
- var panel = _c.value;
1712
- _this.removePanel(panel, {
1713
- removeEmptyGroup: false,
1714
- });
1715
- }
1716
- }
1717
- catch (e_27_1) { e_27 = { error: e_27_1 }; }
1718
- finally {
1719
- try {
1720
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1721
- }
1722
- finally { if (e_27) throw e_27.error; }
1723
- }
1724
- group.dispose();
1725
- _this._groups.delete(group.id);
1726
- _this._onDidRemoveGroup.fire(group);
1727
- }
1728
- resolve();
1729
- };
1730
- var handle = setTimeout(function () {
1731
- _this._popoutRestorationCleanups.delete(cleanup);
1732
- // Guard against the component being disposed before
1733
- // this timer fires. Under React StrictMode the
1734
- // component is mounted -> disposed -> remounted, and
1735
- // without this guard the first instance's queued
1736
- // restoration would open a second popout window.
1737
- // See issue #851.
1738
- if (_this.isDisposed) {
1739
- resolve();
1740
- return;
1741
- }
1742
- _this.addPopoutGroup(group, {
1743
- position: position !== null && position !== void 0 ? position : undefined,
1744
- overridePopoutGroup: gridReferenceGroup
1745
- ? group
1746
- : undefined,
1747
- referenceGroup: gridReferenceGroup
1748
- ? _this.getPanel(gridReferenceGroup)
1749
- : undefined,
1750
- popoutUrl: url,
1751
- });
1752
- resolve();
1753
- }, index * constants_1.DESERIALIZATION_POPOUT_DELAY_MS); // 100ms delay between each popup
1754
- _this._popoutRestorationCleanups.add(cleanup);
1755
- });
1756
- popoutPromises_1.push(popoutPromise);
1757
- });
1758
- // Store the promise for tests to wait on
1759
- this._popoutRestorationPromise = Promise.all(popoutPromises_1).then(function () { return void 0; });
1760
- try {
1761
- for (var _z = __values(this._floatingGroups), _0 = _z.next(); !_0.done; _0 = _z.next()) {
1762
- var floatingGroup = _0.value;
1763
- floatingGroup.overlay.setBounds();
1764
- }
1765
- }
1766
- catch (e_21_1) { e_21 = { error: e_21_1 }; }
1767
- finally {
1768
- try {
1769
- if (_0 && !_0.done && (_g = _z.return)) _g.call(_z);
1770
- }
1771
- finally { if (e_21) throw e_21.error; }
2032
+ this.deserializeEdgeGroups(data.edgeGroups, panels);
1772
2033
  }
2034
+ this.deserializeFloatingWindows((_f = data.floatingGroups) !== null && _f !== void 0 ? _f : [], createGroupFromSerializedState_1);
2035
+ var popoutPromises = this.deserializePopoutWindows((_g = data.popoutGroups) !== null && _g !== void 0 ? _g : [], createGroupFromSerializedState_1);
2036
+ (_h = this._popoutWindowService) === null || _h === void 0 ? void 0 : _h.finishRestoration(popoutPromises);
2037
+ (_j = this._floatingGroupService) === null || _j === void 0 ? void 0 : _j.constrainBounds();
1773
2038
  if (typeof activeGroup === 'string') {
1774
2039
  var panel = this.getPanel(activeGroup);
1775
2040
  if (panel) {
1776
2041
  this.doSetGroupAndPanelActive(panel);
1777
2042
  }
1778
2043
  }
2044
+ // `gridview.deserialize()` rebuilds the grid without firing the
2045
+ // BaseGrid add events the watermark module reacts to, so the
2046
+ // watermark mounted during `clear()` would otherwise persist over
2047
+ // the restored layout. Re-evaluate now the layout is in place.
2048
+ (_k = this._watermarkService) === null || _k === void 0 ? void 0 : _k.update();
1779
2049
  }
1780
2050
  catch (err) {
1781
2051
  console.error('dockview: failed to deserialize layout. Reverting changes', err);
@@ -1783,102 +2053,326 @@ var DockviewComponent = /** @class */ (function (_super) {
1783
2053
  /**
1784
2054
  * Takes all the successfully created groups and remove all of their panels.
1785
2055
  */
1786
- for (var _1 = __values(this.groups), _2 = _1.next(); !_2.done; _2 = _1.next()) {
1787
- var group = _2.value;
2056
+ for (var _p = __values(this.groups), _q = _p.next(); !_q.done; _q = _p.next()) {
2057
+ var group = _q.value;
1788
2058
  try {
1789
- for (var _3 = (e_23 = void 0, __values(group.panels)), _4 = _3.next(); !_4.done; _4 = _3.next()) {
1790
- var panel = _4.value;
2059
+ for (var _r = (e_14 = void 0, __values(group.panels)), _s = _r.next(); !_s.done; _s = _r.next()) {
2060
+ var panel = _s.value;
1791
2061
  this.removePanel(panel, {
1792
2062
  removeEmptyGroup: false,
1793
2063
  skipDispose: false,
1794
2064
  });
1795
2065
  }
1796
2066
  }
1797
- catch (e_23_1) { e_23 = { error: e_23_1 }; }
2067
+ catch (e_14_1) { e_14 = { error: e_14_1 }; }
1798
2068
  finally {
1799
2069
  try {
1800
- if (_4 && !_4.done && (_j = _3.return)) _j.call(_3);
2070
+ if (_s && !_s.done && (_c = _r.return)) _c.call(_r);
1801
2071
  }
1802
- finally { if (e_23) throw e_23.error; }
2072
+ finally { if (e_14) throw e_14.error; }
1803
2073
  }
1804
2074
  }
1805
2075
  }
1806
- catch (e_22_1) { e_22 = { error: e_22_1 }; }
2076
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
1807
2077
  finally {
1808
2078
  try {
1809
- if (_2 && !_2.done && (_h = _1.return)) _h.call(_1);
2079
+ if (_q && !_q.done && (_b = _p.return)) _b.call(_p);
1810
2080
  }
1811
- finally { if (e_22) throw e_22.error; }
2081
+ finally { if (e_13) throw e_13.error; }
1812
2082
  }
1813
2083
  try {
1814
2084
  /**
1815
2085
  * To remove a group we cannot call this.removeGroup(...) since this makes assumptions about
1816
2086
  * the underlying HTMLElement existing in the Gridview.
1817
2087
  */
1818
- for (var _5 = __values(this.groups), _6 = _5.next(); !_6.done; _6 = _5.next()) {
1819
- var group = _6.value;
2088
+ for (var _t = __values(this.groups), _u = _t.next(); !_u.done; _u = _t.next()) {
2089
+ var group = _u.value;
1820
2090
  group.dispose();
1821
2091
  this._groups.delete(group.id);
1822
2092
  this._onDidRemoveGroup.fire(group);
1823
2093
  }
1824
2094
  }
1825
- catch (e_24_1) { e_24 = { error: e_24_1 }; }
1826
- finally {
1827
- try {
1828
- if (_6 && !_6.done && (_k = _5.return)) _k.call(_5);
2095
+ catch (e_15_1) { e_15 = { error: e_15_1 }; }
2096
+ finally {
2097
+ try {
2098
+ if (_u && !_u.done && (_d = _t.return)) _d.call(_t);
2099
+ }
2100
+ finally { if (e_15) throw e_15.error; }
2101
+ }
2102
+ (_l = this._floatingGroupService) === null || _l === void 0 ? void 0 : _l.disposeAll();
2103
+ // fires clean-up events and clears the underlying HTML gridview.
2104
+ this.clear();
2105
+ /**
2106
+ * even though we have cleaned-up we still want to inform the caller of their error
2107
+ * and we'll do this through re-throwing the original error since afterall you would
2108
+ * expect trying to load a corrupted layout to result in an error and not silently fail...
2109
+ */
2110
+ throw err;
2111
+ }
2112
+ // Force position updates for always visible panels after DOM layout is complete
2113
+ this.debouncedUpdateAllPositions();
2114
+ this._onDidLayoutFromJSON.fire();
2115
+ };
2116
+ /**
2117
+ * Rebuild a floating / popout window's nested gridview from its serialized
2118
+ * tree, collecting the member groups (in deserialization order) so the
2119
+ * caller can mount or restore the window.
2120
+ */
2121
+ DockviewComponent.prototype.deserializeNestedGridview = function (grid, createGroup) {
2122
+ var gridview = this.createNestedGridview(grid.orientation);
2123
+ var members = [];
2124
+ gridview.deserialize(grid, {
2125
+ fromJSON: function (node) {
2126
+ var group = createGroup(node.data);
2127
+ members.push(group);
2128
+ return group;
2129
+ },
2130
+ });
2131
+ return { gridview: gridview, members: members };
2132
+ };
2133
+ DockviewComponent.prototype.deserializeEdgeGroups = function (edgeGroups, panels) {
2134
+ var e_17, _a, e_18, _b, e_19, _c, e_20, _d;
2135
+ var _e;
2136
+ var edgeService = (0, modules_1.assertModule)(this._edgeGroupService, 'EdgeGroup', 'fromJSON edge restoration');
2137
+ if (!edgeService) {
2138
+ return;
2139
+ }
2140
+ try {
2141
+ // Auto-create edge groups for positions in the serialized state that
2142
+ // don't already have a group registered (e.g. when fromJSON is called
2143
+ // before the user has called addEdgeGroup).
2144
+ for (var _f = __values([
2145
+ 'top',
2146
+ 'bottom',
2147
+ 'left',
2148
+ 'right',
2149
+ ]), _g = _f.next(); !_g.done; _g = _f.next()) {
2150
+ var _position = _g.value;
2151
+ var fixedData = edgeGroups[_position];
2152
+ if (fixedData && !edgeService.has(_position)) {
2153
+ var groupState = fixedData.group;
2154
+ var id = (_e = groupState === null || groupState === void 0 ? void 0 : groupState.id) !== null && _e !== void 0 ? _e : "".concat(_position, "-group");
2155
+ this.addEdgeGroup(_position, { id: id });
2156
+ }
2157
+ }
2158
+ }
2159
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
2160
+ finally {
2161
+ try {
2162
+ if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
2163
+ }
2164
+ finally { if (e_17) throw e_17.error; }
2165
+ }
2166
+ try {
2167
+ // Restore panel contents of edge groups
2168
+ for (var _h = __values(edgeService.entries()), _j = _h.next(); !_j.done; _j = _h.next()) {
2169
+ var _k = __read(_j.value, 2), position = _k[0], edgeGroup = _k[1];
2170
+ var edgeData = edgeGroups[position];
2171
+ var groupState = edgeData === null || edgeData === void 0 ? void 0 : edgeData.group;
2172
+ if (groupState) {
2173
+ var views = groupState.views, activeView = groupState.activeView;
2174
+ var createdPanels = [];
2175
+ try {
2176
+ for (var views_2 = (e_19 = void 0, __values(views)), views_2_1 = views_2.next(); !views_2_1.done; views_2_1 = views_2.next()) {
2177
+ var panelId = views_2_1.value;
2178
+ if (panels[panelId]) {
2179
+ var panel = this._deserializer.fromJSON(panels[panelId], edgeGroup);
2180
+ createdPanels.push(panel);
2181
+ }
2182
+ }
2183
+ }
2184
+ catch (e_19_1) { e_19 = { error: e_19_1 }; }
2185
+ finally {
2186
+ try {
2187
+ if (views_2_1 && !views_2_1.done && (_c = views_2.return)) _c.call(views_2);
2188
+ }
2189
+ finally { if (e_19) throw e_19.error; }
2190
+ }
2191
+ try {
2192
+ for (var createdPanels_1 = (e_20 = void 0, __values(createdPanels)), createdPanels_1_1 = createdPanels_1.next(); !createdPanels_1_1.done; createdPanels_1_1 = createdPanels_1.next()) {
2193
+ var panel = createdPanels_1_1.value;
2194
+ var isActive = activeView === panel.id;
2195
+ edgeGroup.model.openPanel(panel, {
2196
+ skipSetActive: !isActive,
2197
+ skipSetGroupActive: true,
2198
+ });
2199
+ }
2200
+ }
2201
+ catch (e_20_1) { e_20 = { error: e_20_1 }; }
2202
+ finally {
2203
+ try {
2204
+ if (createdPanels_1_1 && !createdPanels_1_1.done && (_d = createdPanels_1.return)) _d.call(createdPanels_1);
2205
+ }
2206
+ finally { if (e_20) throw e_20.error; }
2207
+ }
2208
+ // Restore tab groups before activating a fallback panel
2209
+ if (groupState.tabGroups && groupState.tabGroups.length > 0) {
2210
+ edgeGroup.model.restoreTabGroups(groupState.tabGroups);
2211
+ }
2212
+ if (!edgeGroup.activePanel && edgeGroup.panels.length > 0) {
2213
+ edgeGroup.model.openPanel(edgeGroup.panels[edgeGroup.panels.length - 1], { skipSetGroupActive: true });
2214
+ }
2215
+ }
2216
+ }
2217
+ }
2218
+ catch (e_18_1) { e_18 = { error: e_18_1 }; }
2219
+ finally {
2220
+ try {
2221
+ if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
2222
+ }
2223
+ finally { if (e_18) throw e_18.error; }
2224
+ }
2225
+ this._shellManager.fromJSON(edgeGroups);
2226
+ };
2227
+ DockviewComponent.prototype.deserializeFloatingWindows = function (serialized, createGroup) {
2228
+ var e_21, _a;
2229
+ try {
2230
+ for (var serialized_1 = __values(serialized), serialized_1_1 = serialized_1.next(); !serialized_1_1.done; serialized_1_1 = serialized_1.next()) {
2231
+ var serializedFloatingGroup = serialized_1_1.value;
2232
+ var data = serializedFloatingGroup.data, grid = serializedFloatingGroup.grid, position = serializedFloatingGroup.position;
2233
+ if (grid) {
2234
+ // Multi-group window: rebuild the window's nested gridview from
2235
+ // its serialized tree.
2236
+ var _b = this.deserializeNestedGridview(grid, createGroup), floatingGridview = _b.gridview, members = _b.members;
2237
+ if (members.length === 0) {
2238
+ continue;
2239
+ }
2240
+ this.mountFloatingWindow(floatingGridview, members[0], members, position, { inDragMode: false });
2241
+ }
2242
+ else if (data) {
2243
+ var group = createGroup(data);
2244
+ this.addFloatingGroup(group, {
2245
+ position: position,
2246
+ width: position.width,
2247
+ height: position.height,
2248
+ skipRemoveGroup: true,
2249
+ inDragMode: false,
2250
+ });
1829
2251
  }
1830
- finally { if (e_24) throw e_24.error; }
1831
2252
  }
2253
+ }
2254
+ catch (e_21_1) { e_21 = { error: e_21_1 }; }
2255
+ finally {
1832
2256
  try {
1833
- // iterate over a reassigned array since original array will be modified
1834
- for (var _7 = __values(__spreadArray([], __read(this._floatingGroups), false)), _8 = _7.next(); !_8.done; _8 = _7.next()) {
1835
- var floatingGroup = _8.value;
1836
- floatingGroup.dispose();
1837
- }
2257
+ if (serialized_1_1 && !serialized_1_1.done && (_a = serialized_1.return)) _a.call(serialized_1);
1838
2258
  }
1839
- catch (e_25_1) { e_25 = { error: e_25_1 }; }
1840
- finally {
2259
+ finally { if (e_21) throw e_21.error; }
2260
+ }
2261
+ };
2262
+ DockviewComponent.prototype.deserializePopoutWindows = function (serialized, createGroup) {
2263
+ var _this = this;
2264
+ var popoutService = serialized.length > 0
2265
+ ? (0, modules_1.assertModule)(this._popoutWindowService, 'PopoutWindow', 'fromJSON popout restoration')
2266
+ : this._popoutWindowService;
2267
+ if (!popoutService) {
2268
+ return [];
2269
+ }
2270
+ // Queue popup group creation with delays to avoid browser blocking
2271
+ return serialized.flatMap(function (serializedPopoutGroup, index) {
2272
+ var data = serializedPopoutGroup.data, grid = serializedPopoutGroup.grid, position = serializedPopoutGroup.position, gridReferenceGroup = serializedPopoutGroup.gridReferenceGroup, url = serializedPopoutGroup.url;
2273
+ // Multi-group popout windows rebuild their nested gridview from the
2274
+ // serialized tree; single-group windows use the legacy single-group
2275
+ // path.
2276
+ var overridePopoutGridview;
2277
+ var members = [];
2278
+ if (grid) {
2279
+ var built = _this.deserializeNestedGridview(grid, createGroup);
2280
+ overridePopoutGridview = built.gridview;
2281
+ members = built.members;
2282
+ if (members.length === 0) {
2283
+ // A serialized window with no groups: nothing to restore.
2284
+ // Mirror the floating path's guard and discard the empty
2285
+ // gridview rather than passing an undefined anchor to
2286
+ // addPopoutGroup.
2287
+ overridePopoutGridview.dispose();
2288
+ return [];
2289
+ }
2290
+ }
2291
+ var group = grid ? members[0] : createGroup(data);
2292
+ return popoutService.scheduleRestoration(index * constants_1.DESERIALIZATION_POPOUT_DELAY_MS, function () {
2293
+ _this.addPopoutGroup(group, {
2294
+ position: position !== null && position !== void 0 ? position : undefined,
2295
+ overridePopoutGroup: gridReferenceGroup
2296
+ ? group
2297
+ : undefined,
2298
+ overridePopoutGridview: overridePopoutGridview,
2299
+ referenceGroup: gridReferenceGroup
2300
+ ? _this.getPanel(gridReferenceGroup)
2301
+ : undefined,
2302
+ popoutUrl: url,
2303
+ });
2304
+ }, function () {
2305
+ var e_22, _a, e_23, _b;
1841
2306
  try {
1842
- if (_8 && !_8.done && (_l = _7.return)) _l.call(_7);
2307
+ // The group was registered in _groups synchronously but the
2308
+ // timer that would parent it into the popout window never
2309
+ // ran. Dispose the orphan here so the next clear() doesn't
2310
+ // trip over an unparented element. See issue #1304.
2311
+ for (var _c = __values(members.length > 0
2312
+ ? members
2313
+ : [group]), _d = _c.next(); !_d.done; _d = _c.next()) {
2314
+ var orphan = _d.value;
2315
+ if (!_this.isDisposed &&
2316
+ _this._groups.has(orphan.id) &&
2317
+ orphan.element.parentElement === null) {
2318
+ try {
2319
+ for (var _e = (e_23 = void 0, __values(__spreadArray([], __read(orphan.panels), false))), _f = _e.next(); !_f.done; _f = _e.next()) {
2320
+ var panel = _f.value;
2321
+ _this.removePanel(panel, {
2322
+ removeEmptyGroup: false,
2323
+ });
2324
+ }
2325
+ }
2326
+ catch (e_23_1) { e_23 = { error: e_23_1 }; }
2327
+ finally {
2328
+ try {
2329
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
2330
+ }
2331
+ finally { if (e_23) throw e_23.error; }
2332
+ }
2333
+ orphan.dispose();
2334
+ _this._groups.delete(orphan.id);
2335
+ _this._onDidRemoveGroup.fire(orphan);
2336
+ }
2337
+ }
1843
2338
  }
1844
- finally { if (e_25) throw e_25.error; }
1845
- }
1846
- // fires clean-up events and clears the underlying HTML gridview.
1847
- this.clear();
1848
- /**
1849
- * even though we have cleaned-up we still want to inform the caller of their error
1850
- * and we'll do this through re-throwing the original error since afterall you would
1851
- * expect trying to load a corrupted layout to result in an error and not silently fail...
1852
- */
1853
- throw err;
1854
- }
1855
- this.updateWatermark();
1856
- // Force position updates for always visible panels after DOM layout is complete
1857
- this.debouncedUpdateAllPositions();
1858
- this._onDidLayoutFromJSON.fire();
2339
+ catch (e_22_1) { e_22 = { error: e_22_1 }; }
2340
+ finally {
2341
+ try {
2342
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
2343
+ }
2344
+ finally { if (e_22) throw e_22.error; }
2345
+ }
2346
+ });
2347
+ });
1859
2348
  };
1860
2349
  DockviewComponent.prototype.clear = function () {
1861
- var e_28, _a, e_29, _b;
2350
+ var _this = this;
2351
+ this.mutation('clear', function () { return _this._doClear(); });
2352
+ };
2353
+ DockviewComponent.prototype._doClear = function () {
2354
+ var e_24, _a, e_25, _b;
2355
+ var _c;
1862
2356
  var groups = Array.from(this._groups.values()).map(function (_) { return _.value; });
1863
2357
  var hasActiveGroup = !!this.activeGroup;
1864
2358
  try {
1865
2359
  for (var groups_1 = __values(groups), groups_1_1 = groups_1.next(); !groups_1_1.done; groups_1_1 = groups_1.next()) {
1866
2360
  var group = groups_1_1.value;
1867
- if (__spreadArray([], __read(this._edgeGroups.values()), false).includes(group)) {
2361
+ if ((_c = this._edgeGroupService) === null || _c === void 0 ? void 0 : _c.includes(group)) {
1868
2362
  // Edge groups are structural - only clear their panels, not the group itself
1869
2363
  var panels = __spreadArray([], __read(group.panels), false);
1870
2364
  try {
1871
- for (var panels_1 = (e_29 = void 0, __values(panels)), panels_1_1 = panels_1.next(); !panels_1_1.done; panels_1_1 = panels_1.next()) {
2365
+ for (var panels_1 = (e_25 = void 0, __values(panels)), panels_1_1 = panels_1.next(); !panels_1_1.done; panels_1_1 = panels_1.next()) {
1872
2366
  var panel = panels_1_1.value;
1873
2367
  this.removePanel(panel, { removeEmptyGroup: false });
1874
2368
  }
1875
2369
  }
1876
- catch (e_29_1) { e_29 = { error: e_29_1 }; }
2370
+ catch (e_25_1) { e_25 = { error: e_25_1 }; }
1877
2371
  finally {
1878
2372
  try {
1879
2373
  if (panels_1_1 && !panels_1_1.done && (_b = panels_1.return)) _b.call(panels_1);
1880
2374
  }
1881
- finally { if (e_29) throw e_29.error; }
2375
+ finally { if (e_25) throw e_25.error; }
1882
2376
  }
1883
2377
  continue;
1884
2378
  }
@@ -1886,12 +2380,12 @@ var DockviewComponent = /** @class */ (function (_super) {
1886
2380
  this.removeGroup(group, { skipActive: true });
1887
2381
  }
1888
2382
  }
1889
- catch (e_28_1) { e_28 = { error: e_28_1 }; }
2383
+ catch (e_24_1) { e_24 = { error: e_24_1 }; }
1890
2384
  finally {
1891
2385
  try {
1892
2386
  if (groups_1_1 && !groups_1_1.done && (_a = groups_1.return)) _a.call(groups_1);
1893
2387
  }
1894
- finally { if (e_28) throw e_28.error; }
2388
+ finally { if (e_24) throw e_24.error; }
1895
2389
  }
1896
2390
  if (hasActiveGroup) {
1897
2391
  this.doSetGroupAndPanelActive(undefined);
@@ -1899,25 +2393,34 @@ var DockviewComponent = /** @class */ (function (_super) {
1899
2393
  this.gridview.clear();
1900
2394
  };
1901
2395
  DockviewComponent.prototype.closeAllGroups = function () {
1902
- var e_30, _a;
1903
- try {
1904
- for (var _b = __values(this._groups.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
1905
- var entry = _c.value;
1906
- var _d = __read(entry, 2), _ = _d[0], group = _d[1];
1907
- group.value.model.closeAllPanels();
1908
- }
1909
- }
1910
- catch (e_30_1) { e_30 = { error: e_30_1 }; }
1911
- finally {
2396
+ var _this = this;
2397
+ // One transaction — the per-panel removals inside nest via the depth
2398
+ // counter, so consumers (undo, announcements) see a single mutation.
2399
+ this.mutation('remove', function () {
2400
+ var e_26, _a;
1912
2401
  try {
1913
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2402
+ for (var _b = __values(_this._groups.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
2403
+ var entry = _c.value;
2404
+ var _d = __read(entry, 2), _ = _d[0], group = _d[1];
2405
+ group.value.model.closeAllPanels();
2406
+ }
1914
2407
  }
1915
- finally { if (e_30) throw e_30.error; }
1916
- }
2408
+ catch (e_26_1) { e_26 = { error: e_26_1 }; }
2409
+ finally {
2410
+ try {
2411
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2412
+ }
2413
+ finally { if (e_26) throw e_26.error; }
2414
+ }
2415
+ });
1917
2416
  };
1918
2417
  DockviewComponent.prototype.addPanel = function (options) {
1919
- var _a, _b;
1920
- if (this.panels.find(function (_) { return _.id === options.id; })) {
2418
+ var _this = this;
2419
+ return this.mutation('add', function () { return _this._doAddPanel(options); });
2420
+ };
2421
+ DockviewComponent.prototype._doAddPanel = function (options) {
2422
+ var _a, _b, _c, _d;
2423
+ if (this.panels.some(function (_) { return _.id === options.id; })) {
1921
2424
  throw new Error("dockview: panel with id ".concat(options.id, " already exists"));
1922
2425
  }
1923
2426
  var referenceGroup;
@@ -1936,18 +2439,24 @@ var DockviewComponent = /** @class */ (function (_super) {
1936
2439
  : options.position.referencePanel;
1937
2440
  index = options.position.index;
1938
2441
  if (!referencePanel) {
1939
- throw new Error("dockview: referencePanel '".concat(options.position.referencePanel, "' does not exist"));
2442
+ var referenceId = typeof options.position.referencePanel === 'string'
2443
+ ? options.position.referencePanel
2444
+ : (_a = options.position.referencePanel) === null || _a === void 0 ? void 0 : _a.id;
2445
+ throw new Error("dockview: referencePanel '".concat(referenceId, "' does not exist"));
1940
2446
  }
1941
2447
  referenceGroup = this.findGroup(referencePanel);
1942
2448
  }
1943
2449
  else if ((0, options_1.isPanelOptionsWithGroup)(options.position)) {
1944
2450
  referenceGroup =
1945
2451
  typeof options.position.referenceGroup === 'string'
1946
- ? (_a = this._groups.get(options.position.referenceGroup)) === null || _a === void 0 ? void 0 : _a.value
2452
+ ? (_b = this._groups.get(options.position.referenceGroup)) === null || _b === void 0 ? void 0 : _b.value
1947
2453
  : options.position.referenceGroup;
1948
2454
  index = options.position.index;
1949
2455
  if (!referenceGroup) {
1950
- throw new Error("dockview: referenceGroup '".concat(options.position.referenceGroup, "' does not exist"));
2456
+ var referenceId = typeof options.position.referenceGroup === 'string'
2457
+ ? options.position.referenceGroup
2458
+ : (_c = options.position.referenceGroup) === null || _c === void 0 ? void 0 : _c.id;
2459
+ throw new Error("dockview: referenceGroup '".concat(referenceId, "' does not exist"));
1951
2460
  }
1952
2461
  }
1953
2462
  else {
@@ -1973,7 +2482,7 @@ var DockviewComponent = /** @class */ (function (_super) {
1973
2482
  }
1974
2483
  var panel;
1975
2484
  if (referenceGroup) {
1976
- var target = (0, baseComponentGridview_1.toTarget)(((_b = options.position) === null || _b === void 0 ? void 0 : _b.direction) || 'within');
2485
+ var target = (0, baseComponentGridview_1.toTarget)(((_d = options.position) === null || _d === void 0 ? void 0 : _d.direction) || 'within');
1977
2486
  if (options.floating) {
1978
2487
  var group = this.createGroup();
1979
2488
  this._onDidAddGroup.fire(group);
@@ -2056,9 +2565,17 @@ var DockviewComponent = /** @class */ (function (_super) {
2056
2565
  return panel;
2057
2566
  };
2058
2567
  DockviewComponent.prototype.removePanel = function (panel, options) {
2059
- if (options === void 0) { options = {
2060
- removeEmptyGroup: true,
2061
- }; }
2568
+ var _this = this;
2569
+ this.mutation('remove', function () {
2570
+ var _a;
2571
+ return _this._doRemovePanel(panel, {
2572
+ removeEmptyGroup: (_a = options === null || options === void 0 ? void 0 : options.removeEmptyGroup) !== null && _a !== void 0 ? _a : true,
2573
+ skipDispose: options === null || options === void 0 ? void 0 : options.skipDispose,
2574
+ skipSetActiveGroup: options === null || options === void 0 ? void 0 : options.skipSetActiveGroup,
2575
+ });
2576
+ });
2577
+ };
2578
+ DockviewComponent.prototype._doRemovePanel = function (panel, options) {
2062
2579
  var group = panel.group;
2063
2580
  if (!group) {
2064
2581
  throw new Error("dockview: cannot remove panel ".concat(panel.id, ". it's missing a group."));
@@ -2080,50 +2597,39 @@ var DockviewComponent = /** @class */ (function (_super) {
2080
2597
  }
2081
2598
  return new watermark_1.Watermark();
2082
2599
  };
2083
- DockviewComponent.prototype.updateWatermark = function () {
2084
- var _a, _b;
2085
- if (this.groups.filter(function (x) { return x.api.location.type === 'grid' && x.api.isVisible; }).length === 0) {
2086
- if (!this._watermark) {
2087
- this._watermark = this.createWatermarkComponent();
2088
- this._watermark.init({
2089
- containerApi: new component_api_1.DockviewApi(this),
2090
- });
2091
- var watermarkContainer = document.createElement('div');
2092
- watermarkContainer.className = 'dv-watermark-container';
2093
- (0, dom_1.addTestId)(watermarkContainer, 'watermark-component');
2094
- watermarkContainer.appendChild(this._watermark.element);
2095
- this.gridview.element.appendChild(watermarkContainer);
2096
- }
2097
- }
2098
- else if (this._watermark) {
2099
- this._watermark.element.parentElement.remove();
2100
- (_b = (_a = this._watermark).dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
2101
- this._watermark = null;
2102
- }
2103
- };
2104
2600
  DockviewComponent.prototype.addGroup = function (options) {
2105
- var _a;
2601
+ var _this = this;
2602
+ return this.mutation('add', function () { return _this._doAddGroup(options); });
2603
+ };
2604
+ DockviewComponent.prototype._doAddGroup = function (options) {
2605
+ var _a, _b, _c;
2106
2606
  if (options) {
2107
2607
  var referenceGroup = void 0;
2108
2608
  if ((0, options_1.isGroupOptionsWithPanel)(options)) {
2109
2609
  var referencePanel = typeof options.referencePanel === 'string'
2110
2610
  ? this.panels.find(function (panel) { return panel.id === options.referencePanel; })
2111
2611
  : options.referencePanel;
2612
+ var referencePanelId = typeof options.referencePanel === 'string'
2613
+ ? options.referencePanel
2614
+ : (_a = options.referencePanel) === null || _a === void 0 ? void 0 : _a.id;
2112
2615
  if (!referencePanel) {
2113
- throw new Error("dockview: reference panel ".concat(options.referencePanel, " does not exist"));
2616
+ throw new Error("dockview: reference panel ".concat(referencePanelId, " does not exist"));
2114
2617
  }
2115
2618
  referenceGroup = this.findGroup(referencePanel);
2116
2619
  if (!referenceGroup) {
2117
- throw new Error("dockview: reference group for reference panel ".concat(options.referencePanel, " does not exist"));
2620
+ throw new Error("dockview: reference group for reference panel ".concat(referencePanelId, " does not exist"));
2118
2621
  }
2119
2622
  }
2120
2623
  else if ((0, options_1.isGroupOptionsWithGroup)(options)) {
2121
2624
  referenceGroup =
2122
2625
  typeof options.referenceGroup === 'string'
2123
- ? (_a = this._groups.get(options.referenceGroup)) === null || _a === void 0 ? void 0 : _a.value
2626
+ ? (_b = this._groups.get(options.referenceGroup)) === null || _b === void 0 ? void 0 : _b.value
2124
2627
  : options.referenceGroup;
2125
2628
  if (!referenceGroup) {
2126
- throw new Error("dockview: reference group ".concat(options.referenceGroup, " does not exist"));
2629
+ var referenceId = typeof options.referenceGroup === 'string'
2630
+ ? options.referenceGroup
2631
+ : (_c = options.referenceGroup) === null || _c === void 0 ? void 0 : _c.id;
2632
+ throw new Error("dockview: reference group ".concat(referenceId, " does not exist"));
2127
2633
  }
2128
2634
  }
2129
2635
  else {
@@ -2161,13 +2667,73 @@ var DockviewComponent = /** @class */ (function (_super) {
2161
2667
  : splitview_1.Orientation.VERTICAL;
2162
2668
  };
2163
2669
  DockviewComponent.prototype.removeGroup = function (group, options) {
2164
- this.doRemoveGroup(group, options);
2670
+ var _this = this;
2671
+ this.mutation('remove', function () { return _this.doRemoveGroup(group, options); });
2672
+ };
2673
+ /**
2674
+ * Detach a single group from the nested gridview of its floating / popout
2675
+ * window, keeping the window and its remaining members alive, and reassign
2676
+ * the window's anchor if the detached group was it.
2677
+ *
2678
+ * @returns `true` if the group was detached from a multi-member window;
2679
+ * `false` if `group` is not in a nested window, or is the window's only
2680
+ * member — in which case the caller is responsible for disposing the whole
2681
+ * window.
2682
+ */
2683
+ DockviewComponent.prototype.detachFromNestedWindow = function (group) {
2684
+ var _a, _b;
2685
+ var floating = (_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.findByGroup(group);
2686
+ if (floating) {
2687
+ var members = this.nestedWindowMembers(group);
2688
+ if (members.length <= 1) {
2689
+ return false;
2690
+ }
2691
+ floating.gridview.remove(group);
2692
+ if (floating.group === group) {
2693
+ // The anchor left; promote a remaining member.
2694
+ floating.setAnchorGroup(members.find(function (m) { return m !== group; }));
2695
+ }
2696
+ return true;
2697
+ }
2698
+ var popout = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(group);
2699
+ if (popout) {
2700
+ var members = this.nestedWindowMembers(group);
2701
+ if (members.length <= 1) {
2702
+ return false;
2703
+ }
2704
+ popout.gridview.remove(group);
2705
+ if (popout.popoutGroup === group) {
2706
+ // The anchor left; promote a remaining member.
2707
+ popout.popoutGroup = members.find(function (m) { return m !== group; });
2708
+ }
2709
+ return true;
2710
+ }
2711
+ return false;
2712
+ };
2713
+ /**
2714
+ * Dispose a group and forget it: remove it from `_groups` and fire the
2715
+ * removed event.
2716
+ */
2717
+ DockviewComponent.prototype.disposeGroupRecord = function (group) {
2718
+ group.dispose();
2719
+ this._groups.delete(group.id);
2720
+ this._onDidRemoveGroup.fire(group);
2721
+ };
2722
+ /**
2723
+ * When `removed` was the active group, fall the active selection back to
2724
+ * the first remaining group (or clear it when none remain).
2725
+ */
2726
+ DockviewComponent.prototype.activateFallbackGroupIfRemoved = function (removed, skipActive) {
2727
+ if (!skipActive && this._activeGroup === removed) {
2728
+ var groups = Array.from(this._groups.values());
2729
+ this.doSetGroupAndPanelActive(groups.length > 0 ? groups[0].value : undefined);
2730
+ }
2165
2731
  };
2166
2732
  DockviewComponent.prototype.doRemoveGroup = function (group, options) {
2167
- var e_31, _a;
2168
- var _b;
2733
+ var e_27, _a;
2734
+ var _b, _c, _d, _e, _f;
2169
2735
  // Edge groups are permanent structural elements - never remove them from the layout
2170
- if (__spreadArray([], __read(this._edgeGroups.values()), false).includes(group)) {
2736
+ if ((_b = this._edgeGroupService) === null || _b === void 0 ? void 0 : _b.includes(group)) {
2171
2737
  return group;
2172
2738
  }
2173
2739
  var panels = __spreadArray([], __read(group.panels), false); // reassign since group panels will mutate
@@ -2177,72 +2743,107 @@ var DockviewComponent = /** @class */ (function (_super) {
2177
2743
  var panel = panels_2_1.value;
2178
2744
  this.removePanel(panel, {
2179
2745
  removeEmptyGroup: false,
2180
- skipDispose: (_b = options === null || options === void 0 ? void 0 : options.skipDispose) !== null && _b !== void 0 ? _b : false,
2746
+ skipDispose: (_c = options === null || options === void 0 ? void 0 : options.skipDispose) !== null && _c !== void 0 ? _c : false,
2181
2747
  });
2182
2748
  }
2183
2749
  }
2184
- catch (e_31_1) { e_31 = { error: e_31_1 }; }
2750
+ catch (e_27_1) { e_27 = { error: e_27_1 }; }
2185
2751
  finally {
2186
2752
  try {
2187
2753
  if (panels_2_1 && !panels_2_1.done && (_a = panels_2.return)) _a.call(panels_2);
2188
2754
  }
2189
- finally { if (e_31) throw e_31.error; }
2755
+ finally { if (e_27) throw e_27.error; }
2190
2756
  }
2191
2757
  }
2192
2758
  var activePanel = this.activePanel;
2193
2759
  if (group.api.location.type === 'floating') {
2194
- var floatingGroup = this._floatingGroups.find(function (_) { return _.group === group; });
2195
- if (floatingGroup) {
2196
- if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
2197
- floatingGroup.group.dispose();
2198
- this._groups.delete(group.id);
2199
- this._onDidRemoveGroup.fire(group);
2760
+ var floatingGroup = (_d = this._floatingGroupService) === null || _d === void 0 ? void 0 : _d.findByGroup(group);
2761
+ if (!floatingGroup) {
2762
+ throw new Error('dockview: failed to find floating group');
2763
+ }
2764
+ if (this.detachFromNestedWindow(group)) {
2765
+ // The floating window hosts other groups and stays alive —
2766
+ // finalize just this group.
2767
+ if (options === null || options === void 0 ? void 0 : options.skipDispose) {
2768
+ // Relocation: reset location so the destination root can
2769
+ // re-tag it.
2770
+ group.model.location = { type: 'grid' };
2200
2771
  }
2201
- (0, array_1.remove)(this._floatingGroups, floatingGroup);
2202
- floatingGroup.dispose();
2203
- if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
2204
- var groups = Array.from(this._groups.values());
2205
- this.doSetGroupAndPanelActive(groups.length > 0 ? groups[0].value : undefined);
2772
+ else {
2773
+ this.disposeGroupRecord(group);
2206
2774
  }
2207
- return floatingGroup.group;
2775
+ this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
2776
+ return group;
2208
2777
  }
2209
- throw new Error('dockview: failed to find floating group');
2778
+ // Last group leaving — dispose the whole floating window.
2779
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
2780
+ this.disposeGroupRecord(group);
2781
+ }
2782
+ // floatingGroup.dispose() removes itself from the service array
2783
+ floatingGroup.dispose();
2784
+ this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
2785
+ return group;
2210
2786
  }
2211
2787
  if (group.api.location.type === 'popout') {
2212
- var selectedGroup = this._popoutGroups.find(function (_) { return _.popoutGroup === group; });
2213
- if (selectedGroup) {
2214
- if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
2215
- if (!(options === null || options === void 0 ? void 0 : options.skipPopoutAssociated)) {
2216
- var refGroup = selectedGroup.referenceGroup
2217
- ? this.getPanel(selectedGroup.referenceGroup)
2218
- : undefined;
2219
- if (refGroup && refGroup.panels.length === 0) {
2220
- this.removeGroup(refGroup);
2221
- }
2222
- }
2223
- selectedGroup.popoutGroup.dispose();
2224
- this._groups.delete(group.id);
2225
- this._onDidRemoveGroup.fire(group);
2788
+ var selectedGroup = (_e = this._popoutWindowService) === null || _e === void 0 ? void 0 : _e.findByGroup(group);
2789
+ if (!selectedGroup) {
2790
+ throw new Error('dockview: failed to find popout group');
2791
+ }
2792
+ if (this.detachFromNestedWindow(group)) {
2793
+ // The popout window hosts other groups and stays alive —
2794
+ // finalize just this group.
2795
+ if (options === null || options === void 0 ? void 0 : options.skipDispose) {
2796
+ // Relocation: reset location so the destination root can
2797
+ // re-tag it.
2798
+ group.model.location = { type: 'grid' };
2226
2799
  }
2227
- (0, array_1.remove)(this._popoutGroups, selectedGroup);
2228
- var removedGroup = selectedGroup.disposable.dispose();
2229
- if (!(options === null || options === void 0 ? void 0 : options.skipPopoutReturn) && removedGroup) {
2230
- this.doAddGroup(removedGroup, [0]);
2231
- this.doSetGroupAndPanelActive(removedGroup);
2232
- }
2233
- if (!(options === null || options === void 0 ? void 0 : options.skipActive) && this._activeGroup === group) {
2234
- var groups = Array.from(this._groups.values());
2235
- this.doSetGroupAndPanelActive(groups.length > 0 ? groups[0].value : undefined);
2800
+ else {
2801
+ this.disposeGroupRecord(group);
2236
2802
  }
2237
- this.updateWatermark();
2238
- return selectedGroup.popoutGroup;
2803
+ this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
2804
+ return group;
2239
2805
  }
2240
- throw new Error('dockview: failed to find popout group');
2806
+ // Last group leaving — tear the whole popout window down.
2807
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
2808
+ if (!(options === null || options === void 0 ? void 0 : options.skipPopoutAssociated)) {
2809
+ var refGroup = selectedGroup.referenceGroup
2810
+ ? this.getPanel(selectedGroup.referenceGroup)
2811
+ : undefined;
2812
+ if ((refGroup === null || refGroup === void 0 ? void 0 : refGroup.panels.length) === 0) {
2813
+ this.removeGroup(refGroup);
2814
+ }
2815
+ }
2816
+ selectedGroup.popoutGroup.dispose();
2817
+ this._groups.delete(group.id);
2818
+ this._onDidRemoveGroup.fire(group);
2819
+ }
2820
+ (_f = this._popoutWindowService) === null || _f === void 0 ? void 0 : _f.remove(selectedGroup);
2821
+ var removedGroup = selectedGroup.disposable.dispose();
2822
+ if (!(options === null || options === void 0 ? void 0 : options.skipPopoutReturn) && removedGroup) {
2823
+ this.doAddGroup(removedGroup, [0]);
2824
+ this.doSetGroupAndPanelActive(removedGroup);
2825
+ }
2826
+ this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
2827
+ return selectedGroup.popoutGroup;
2828
+ }
2829
+ // A `grid`-location group whose element isn't actually in the gridview
2830
+ // is an orphan — e.g. a popout-destined group created during fromJSON
2831
+ // whose window hasn't opened yet, swept up by clear()/a re-entrant
2832
+ // fromJSON. `gridview.remove()` would throw "Invalid grid element", so
2833
+ // dispose it directly.
2834
+ if (!this.gridview.element.contains(group.element)) {
2835
+ if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
2836
+ var item = this._groups.get(group.id);
2837
+ item === null || item === void 0 ? void 0 : item.disposable.dispose();
2838
+ this.disposeGroupRecord(group);
2839
+ }
2840
+ this.activateFallbackGroupIfRemoved(group, options === null || options === void 0 ? void 0 : options.skipActive);
2841
+ return group;
2241
2842
  }
2242
2843
  var re = _super.prototype.doRemoveGroup.call(this, group, options);
2243
2844
  if (!(options === null || options === void 0 ? void 0 : options.skipActive)) {
2244
2845
  if (this.activePanel !== activePanel) {
2245
- this._onDidActivePanelChange.fire(this.activePanel);
2846
+ this.fireActivePanelChange(this.activePanel);
2246
2847
  }
2247
2848
  }
2248
2849
  return re;
@@ -2253,8 +2854,26 @@ var DockviewComponent = /** @class */ (function (_super) {
2253
2854
  cancelAnimationFrame(this._updatePositionsFrameId);
2254
2855
  }
2255
2856
  this._updatePositionsFrameId = requestAnimationFrame(function () {
2857
+ var e_28, _a;
2858
+ var _b, _c;
2256
2859
  _this._updatePositionsFrameId = undefined;
2257
2860
  _this.overlayRenderContainer.updateAllPositions();
2861
+ try {
2862
+ // Popout windows have their own render containers; reposition those
2863
+ // too so panels moved/split within a popout are laid out (the main
2864
+ // container only covers grid + floating, which share it).
2865
+ for (var _d = __values((_c = (_b = _this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.entries) !== null && _c !== void 0 ? _c : []), _e = _d.next(); !_e.done; _e = _d.next()) {
2866
+ var entry = _e.value;
2867
+ entry.overlayRenderContainer.updateAllPositions();
2868
+ }
2869
+ }
2870
+ catch (e_28_1) { e_28 = { error: e_28_1 }; }
2871
+ finally {
2872
+ try {
2873
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
2874
+ }
2875
+ finally { if (e_28) throw e_28.error; }
2876
+ }
2258
2877
  });
2259
2878
  };
2260
2879
  DockviewComponent.prototype.movingLock = function (func) {
@@ -2267,9 +2886,76 @@ var DockviewComponent = /** @class */ (function (_super) {
2267
2886
  this._moving = isMoving;
2268
2887
  }
2269
2888
  };
2889
+ /**
2890
+ * Bracket a structural mutation with `onWillMutateLayout` /
2891
+ * `onDidMutateLayout`. Re-entrant: nested calls (a compound operation such
2892
+ * as a drag that relocates a panel) join the outermost transaction, so the
2893
+ * events fire exactly once around the whole operation. `kind` reflects the
2894
+ * outermost mutation.
2895
+ */
2896
+ DockviewComponent.prototype.mutation = function (kind, func) {
2897
+ var outer = this._mutationDepth === 0;
2898
+ var origin = this._origin;
2899
+ if (outer) {
2900
+ this._onWillMutateLayout.fire({ kind: kind, origin: origin });
2901
+ }
2902
+ this._mutationDepth++;
2903
+ try {
2904
+ return func();
2905
+ }
2906
+ finally {
2907
+ this._mutationDepth--;
2908
+ if (outer) {
2909
+ this._onDidMutateLayout.fire({ kind: kind, origin: origin });
2910
+ }
2911
+ }
2912
+ };
2913
+ /**
2914
+ * The origin of the operation currently in progress (`'user'` by default).
2915
+ * Read inside a `mutation()` or active-panel change to learn whether the
2916
+ * change was driven by application code (via the {@link DockviewApi}) or a
2917
+ * user gesture.
2918
+ */
2919
+ DockviewComponent.prototype.currentOrigin = function () {
2920
+ return this._origin;
2921
+ };
2922
+ /**
2923
+ * Run `func` with the operation origin set to `origin`, restoring the
2924
+ * previous value afterwards. Used by the DockviewApi boundary to tag
2925
+ * programmatic operations as `'api'`, and by user-gesture handlers to tag
2926
+ * `'user'`. Only the outermost caller sets the origin — a nested call (or a
2927
+ * call made while a mutation is already in flight) keeps whatever the
2928
+ * enclosing operation established, so the trigger always wins.
2929
+ */
2930
+ DockviewComponent.prototype.withOrigin = function (origin, func) {
2931
+ if (this._originDepth > 0 || this._mutationDepth > 0) {
2932
+ return func();
2933
+ }
2934
+ var previous = this._origin;
2935
+ this._origin = origin;
2936
+ this._originDepth++;
2937
+ try {
2938
+ return func();
2939
+ }
2940
+ finally {
2941
+ this._originDepth--;
2942
+ this._origin = previous;
2943
+ }
2944
+ };
2945
+ /**
2946
+ * Fire `onDidActivePanelChange` with the panel and the current operation
2947
+ * {@link DockviewOrigin}. Callers keep their own dedupe guards.
2948
+ */
2949
+ DockviewComponent.prototype.fireActivePanelChange = function (panel) {
2950
+ this._onDidActivePanelChange.fire({ panel: panel, origin: this._origin });
2951
+ };
2270
2952
  DockviewComponent.prototype.moveGroupOrPanel = function (options) {
2271
2953
  var _this = this;
2272
- var _a;
2954
+ this.mutation('move', function () { return _this._doMoveGroupOrPanel(options); });
2955
+ };
2956
+ DockviewComponent.prototype._doMoveGroupOrPanel = function (options) {
2957
+ var _this = this;
2958
+ var _a, _b;
2273
2959
  var destinationGroup = options.to.group;
2274
2960
  var sourceGroupId = options.from.groupId;
2275
2961
  var sourceItemId = options.from.panelId;
@@ -2352,17 +3038,22 @@ var DockviewComponent = /** @class */ (function (_super) {
2352
3038
  * Dropping a panel to the extremities of a group which will place that panel
2353
3039
  * into an adjacent group
2354
3040
  */
3041
+ // The destination group may live in the main grid or in a floating
3042
+ // window's nested gridview — resolve which root we are dropping
3043
+ // into so locations/orientation are computed against it.
3044
+ var destinationGridview_1 = this.getGridviewForGroup(destinationGroup);
2355
3045
  var referenceLocation = (0, gridview_1.getGridLocation)(destinationGroup.element);
2356
- var targetLocation = (0, gridview_1.getRelativeLocation)(this.gridview.orientation, referenceLocation, destinationTarget);
3046
+ var targetLocation = (0, gridview_1.getRelativeLocation)(destinationGridview_1.orientation, referenceLocation, destinationTarget);
2357
3047
  if (sourceGroup.size < 2) {
2358
3048
  /**
2359
3049
  * If we are moving from a group which only has one panel left we will consider
2360
3050
  * moving the group itself rather than moving the panel into a newly created group
2361
3051
  */
2362
- var _b = __read((0, array_1.tail)(targetLocation), 2), targetParentLocation = _b[0], to = _b[1];
2363
- if (sourceGroup.api.location.type === 'grid') {
3052
+ var _c = __read((0, array_1.tail)(targetLocation), 2), targetParentLocation = _c[0], to = _c[1];
3053
+ if (sourceGroup.api.location.type === 'grid' &&
3054
+ destinationGridview_1 === this.gridview) {
2364
3055
  var sourceLocation = (0, gridview_1.getGridLocation)(sourceGroup.element);
2365
- var _c = __read((0, array_1.tail)(sourceLocation), 2), sourceParentLocation = _c[0], from = _c[1];
3056
+ var _d = __read((0, array_1.tail)(sourceLocation), 2), sourceParentLocation = _d[0], from = _d[1];
2366
3057
  if ((0, array_1.sequenceEquals)(sourceParentLocation, targetParentLocation)) {
2367
3058
  // special case when 'swapping' two views within same grid location
2368
3059
  // if a group has one tab - we are essentially moving the 'group'
@@ -2375,9 +3066,11 @@ var DockviewComponent = /** @class */ (function (_super) {
2375
3066
  return;
2376
3067
  }
2377
3068
  }
2378
- if (sourceGroup.api.location.type === 'popout') {
3069
+ if (sourceGroup.api.location.type === 'popout' &&
3070
+ this.nestedWindowMembers(sourceGroup).length <= 1) {
2379
3071
  /**
2380
- * the source group is a popout group with a single panel
3072
+ * the source group is the only group in a popout window and
3073
+ * has a single panel
2381
3074
  *
2382
3075
  * 1. remove the panel from the group without triggering any events
2383
3076
  * 2. remove the popout group — this may cascade-remove the empty
@@ -2385,8 +3078,14 @@ var DockviewComponent = /** @class */ (function (_super) {
2385
3078
  * doRemoveGroup for popout groups), which can shift grid indices
2386
3079
  * 3. recompute the target location now that the grid is stable
2387
3080
  * 4. create a new group at the recomputed location and add that panel
3081
+ *
3082
+ * Multi-group popout windows fall through to the generic
3083
+ * detach-and-re-add path so the window stays alive.
2388
3084
  */
2389
- var popoutGroup_1 = this._popoutGroups.find(function (group) { return group.popoutGroup === sourceGroup; });
3085
+ var popoutGroup_1 = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(sourceGroup);
3086
+ if (!popoutGroup_1) {
3087
+ return;
3088
+ }
2390
3089
  var removedPanel_2 = this.movingLock(function () {
2391
3090
  return popoutGroup_1.popoutGroup.model.removePanel(popoutGroup_1.popoutGroup.panels[0], {
2392
3091
  skipSetActive: true,
@@ -2394,8 +3093,8 @@ var DockviewComponent = /** @class */ (function (_super) {
2394
3093
  });
2395
3094
  });
2396
3095
  this.doRemoveGroup(sourceGroup, { skipActive: true });
2397
- var updatedTargetLocation = (0, gridview_1.getRelativeLocation)(this.gridview.orientation, (0, gridview_1.getGridLocation)(destinationGroup.element), destinationTarget);
2398
- var newGroup_1 = this.createGroupAtLocation(updatedTargetLocation);
3096
+ var updatedTargetLocation = (0, gridview_1.getRelativeLocation)(destinationGridview_1.orientation, (0, gridview_1.getGridLocation)(destinationGroup.element), destinationTarget);
3097
+ var newGroup_1 = this.createGroupAtLocation(updatedTargetLocation, undefined, undefined, destinationGridview_1);
2399
3098
  this.movingLock(function () {
2400
3099
  return newGroup_1.model.openPanel(removedPanel_2, {
2401
3100
  skipSetActive: true,
@@ -2423,7 +3122,7 @@ var DockviewComponent = /** @class */ (function (_super) {
2423
3122
  if (!removedPanel_3) {
2424
3123
  throw new Error("dockview: No panel with id ".concat(sourceItemId));
2425
3124
  }
2426
- var newGroup_2 = this.createGroupAtLocation(targetLocation);
3125
+ var newGroup_2 = this.createGroupAtLocation(targetLocation, undefined, undefined, destinationGridview_1);
2427
3126
  this.movingLock(function () {
2428
3127
  return newGroup_2.model.openPanel(removedPanel_3, {
2429
3128
  skipSetGroupActive: true,
@@ -2445,8 +3144,11 @@ var DockviewComponent = /** @class */ (function (_super) {
2445
3144
  });
2446
3145
  // after deleting the group we need to re-evaulate the ref location
2447
3146
  var updatedReferenceLocation = (0, gridview_1.getGridLocation)(destinationGroup.element);
2448
- var location_3 = (0, gridview_1.getRelativeLocation)(this.gridview.orientation, updatedReferenceLocation, destinationTarget);
2449
- this.movingLock(function () { return _this.doAddGroup(targetGroup_1, location_3); });
3147
+ var location_3 = (0, gridview_1.getRelativeLocation)(destinationGridview_1.orientation, updatedReferenceLocation, destinationTarget);
3148
+ this.movingLock(function () {
3149
+ return _this.doAddGroup(targetGroup_1, location_3, undefined, destinationGridview_1);
3150
+ });
3151
+ this.setGroupLocationForRoot(targetGroup_1, destinationGridview_1);
2450
3152
  this.doSetGroupAndPanelActive(targetGroup_1);
2451
3153
  this._onDidMovePanel.fire({
2452
3154
  panel: this.getGroupPanel(sourceItemId),
@@ -2467,8 +3169,8 @@ var DockviewComponent = /** @class */ (function (_super) {
2467
3169
  if (!removedPanel_4) {
2468
3170
  throw new Error("dockview: No panel with id ".concat(sourceItemId));
2469
3171
  }
2470
- var dropLocation = (0, gridview_1.getRelativeLocation)(this.gridview.orientation, referenceLocation, destinationTarget);
2471
- var group_2 = this.createGroupAtLocation(dropLocation);
3172
+ var dropLocation = (0, gridview_1.getRelativeLocation)(destinationGridview_1.orientation, referenceLocation, destinationTarget);
3173
+ var group_2 = this.createGroupAtLocation(dropLocation, undefined, undefined, destinationGridview_1);
2472
3174
  this.movingLock(function () {
2473
3175
  return group_2.model.openPanel(removedPanel_4, {
2474
3176
  skipSetGroupActive: true,
@@ -2518,9 +3220,9 @@ var DockviewComponent = /** @class */ (function (_super) {
2518
3220
  return;
2519
3221
  }
2520
3222
  var addPanelsToGroup = function (targetGroup) {
2521
- var e_32, _a, e_33, _b;
3223
+ var e_29, _a, e_30, _b;
2522
3224
  _this.movingLock(function () {
2523
- var e_34, _a;
3225
+ var e_31, _a;
2524
3226
  try {
2525
3227
  for (var removedPanels_3 = __values(removedPanels), removedPanels_3_1 = removedPanels_3.next(); !removedPanels_3_1.done; removedPanels_3_1 = removedPanels_3.next()) {
2526
3228
  var panel = removedPanels_3_1.value;
@@ -2531,12 +3233,12 @@ var DockviewComponent = /** @class */ (function (_super) {
2531
3233
  });
2532
3234
  }
2533
3235
  }
2534
- catch (e_34_1) { e_34 = { error: e_34_1 }; }
3236
+ catch (e_31_1) { e_31 = { error: e_31_1 }; }
2535
3237
  finally {
2536
3238
  try {
2537
3239
  if (removedPanels_3_1 && !removedPanels_3_1.done && (_a = removedPanels_3.return)) _a.call(removedPanels_3);
2538
3240
  }
2539
- finally { if (e_34) throw e_34.error; }
3241
+ finally { if (e_31) throw e_31.error; }
2540
3242
  }
2541
3243
  });
2542
3244
  // Recreate the tab group in the destination
@@ -2552,12 +3254,12 @@ var DockviewComponent = /** @class */ (function (_super) {
2552
3254
  targetGroup.model.addPanelToTabGroup(newTabGroup.id, panel.id);
2553
3255
  }
2554
3256
  }
2555
- catch (e_32_1) { e_32 = { error: e_32_1 }; }
3257
+ catch (e_29_1) { e_29 = { error: e_29_1 }; }
2556
3258
  finally {
2557
3259
  try {
2558
3260
  if (removedPanels_1_1 && !removedPanels_1_1.done && (_a = removedPanels_1.return)) _a.call(removedPanels_1);
2559
3261
  }
2560
- finally { if (e_32) throw e_32.error; }
3262
+ finally { if (e_29) throw e_29.error; }
2561
3263
  }
2562
3264
  if (!options.skipSetActive) {
2563
3265
  _this.doSetGroupAndPanelActive(targetGroup);
@@ -2571,12 +3273,12 @@ var DockviewComponent = /** @class */ (function (_super) {
2571
3273
  });
2572
3274
  }
2573
3275
  }
2574
- catch (e_33_1) { e_33 = { error: e_33_1 }; }
3276
+ catch (e_30_1) { e_30 = { error: e_30_1 }; }
2575
3277
  finally {
2576
3278
  try {
2577
3279
  if (removedPanels_2_1 && !removedPanels_2_1.done && (_b = removedPanels_2.return)) _b.call(removedPanels_2);
2578
3280
  }
2579
- finally { if (e_33) throw e_33.error; }
3281
+ finally { if (e_30) throw e_30.error; }
2580
3282
  }
2581
3283
  };
2582
3284
  var targetGroup;
@@ -2602,8 +3304,26 @@ var DockviewComponent = /** @class */ (function (_super) {
2602
3304
  addPanelsToGroup(targetGroup);
2603
3305
  };
2604
3306
  DockviewComponent.prototype.moveGroup = function (options) {
2605
- var e_35, _a, e_36, _b, e_37, _c, e_38, _d;
2606
3307
  var _this = this;
3308
+ this.mutation('move', function () { return _this._doMoveGroup(options); });
3309
+ };
3310
+ // Bracket maximize/restore as a 'maximize' transaction. The maximized node
3311
+ // is serialized by the gridview (`SerializedGridview.maximizedNode`), so
3312
+ // the state round-trips through toJSON/fromJSON and is restorable on undo.
3313
+ // When the exit is a side-effect of another bracketed operation (e.g. a
3314
+ // move that activates a different group) the depth counter folds it in.
3315
+ DockviewComponent.prototype.maximizeGroup = function (panel) {
3316
+ var _this = this;
3317
+ this.mutation('maximize', function () { return _super.prototype.maximizeGroup.call(_this, panel); });
3318
+ };
3319
+ DockviewComponent.prototype.exitMaximizedGroup = function () {
3320
+ var _this = this;
3321
+ this.mutation('maximize', function () { return _super.prototype.exitMaximizedGroup.call(_this); });
3322
+ };
3323
+ DockviewComponent.prototype._doMoveGroup = function (options) {
3324
+ var e_32, _a, e_33, _b, e_34, _c, e_35, _d;
3325
+ var _this = this;
3326
+ var _e, _f, _g;
2607
3327
  var from = options.from.group;
2608
3328
  var to = options.to.group;
2609
3329
  var target = options.to.position;
@@ -2634,7 +3354,7 @@ var DockviewComponent = /** @class */ (function (_super) {
2634
3354
  this.doRemoveGroup(from, { skipActive: true });
2635
3355
  }
2636
3356
  this.movingLock(function () {
2637
- var e_39, _a;
3357
+ var e_36, _a;
2638
3358
  try {
2639
3359
  for (var panels_4 = __values(panels_3), panels_4_1 = panels_4.next(); !panels_4_1.done; panels_4_1 = panels_4.next()) {
2640
3360
  var panel = panels_4_1.value;
@@ -2644,12 +3364,12 @@ var DockviewComponent = /** @class */ (function (_super) {
2644
3364
  });
2645
3365
  }
2646
3366
  }
2647
- catch (e_39_1) { e_39 = { error: e_39_1 }; }
3367
+ catch (e_36_1) { e_36 = { error: e_36_1 }; }
2648
3368
  finally {
2649
3369
  try {
2650
3370
  if (panels_4_1 && !panels_4_1.done && (_a = panels_4.return)) _a.call(panels_4);
2651
3371
  }
2652
- finally { if (e_39) throw e_39.error; }
3372
+ finally { if (e_36) throw e_36.error; }
2653
3373
  }
2654
3374
  });
2655
3375
  try {
@@ -2662,26 +3382,26 @@ var DockviewComponent = /** @class */ (function (_super) {
2662
3382
  componentParams: snapshot.componentParams,
2663
3383
  });
2664
3384
  try {
2665
- for (var _e = (e_36 = void 0, __values(snapshot.panelIds)), _f = _e.next(); !_f.done; _f = _e.next()) {
2666
- var panelId = _f.value;
3385
+ for (var _h = (e_33 = void 0, __values(snapshot.panelIds)), _j = _h.next(); !_j.done; _j = _h.next()) {
3386
+ var panelId = _j.value;
2667
3387
  to.model.addPanelToTabGroup(newTabGroup.id, panelId);
2668
3388
  }
2669
3389
  }
2670
- catch (e_36_1) { e_36 = { error: e_36_1 }; }
3390
+ catch (e_33_1) { e_33 = { error: e_33_1 }; }
2671
3391
  finally {
2672
3392
  try {
2673
- if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
3393
+ if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
2674
3394
  }
2675
- finally { if (e_36) throw e_36.error; }
3395
+ finally { if (e_33) throw e_33.error; }
2676
3396
  }
2677
3397
  }
2678
3398
  }
2679
- catch (e_35_1) { e_35 = { error: e_35_1 }; }
3399
+ catch (e_32_1) { e_32 = { error: e_32_1 }; }
2680
3400
  finally {
2681
3401
  try {
2682
3402
  if (tabGroupSnapshots_1_1 && !tabGroupSnapshots_1_1.done && (_a = tabGroupSnapshots_1.return)) _a.call(tabGroupSnapshots_1);
2683
3403
  }
2684
- finally { if (e_35) throw e_35.error; }
3404
+ finally { if (e_32) throw e_32.error; }
2685
3405
  }
2686
3406
  // Ensure group becomes active after move
2687
3407
  if (options.skipSetActive !== true) {
@@ -2723,8 +3443,15 @@ var DockviewComponent = /** @class */ (function (_super) {
2723
3443
  });
2724
3444
  });
2725
3445
  source = this.createGroup();
3446
+ // The new source group enters the layout via gridview.addView
3447
+ // below, which bypasses doAddGroup and so doesn't fire
3448
+ // BaseGrid._onDidAdd. Modules (TabGroupChips, etc.) drive
3449
+ // per-group attachment off _onDidAddGroup, so we fire it
3450
+ // explicitly here — matches the pattern in addFloatingGroup
3451
+ // and addEdgeGroup.
3452
+ this._onDidAddGroup.fire(source);
2726
3453
  this.movingLock(function () {
2727
- var e_40, _a;
3454
+ var e_37, _a;
2728
3455
  try {
2729
3456
  for (var movedPanels_2 = __values(movedPanels_1), movedPanels_2_1 = movedPanels_2.next(); !movedPanels_2_1.done; movedPanels_2_1 = movedPanels_2.next()) {
2730
3457
  var panel = movedPanels_2_1.value;
@@ -2734,12 +3461,12 @@ var DockviewComponent = /** @class */ (function (_super) {
2734
3461
  });
2735
3462
  }
2736
3463
  }
2737
- catch (e_40_1) { e_40 = { error: e_40_1 }; }
3464
+ catch (e_37_1) { e_37 = { error: e_37_1 }; }
2738
3465
  finally {
2739
3466
  try {
2740
3467
  if (movedPanels_2_1 && !movedPanels_2_1.done && (_a = movedPanels_2.return)) _a.call(movedPanels_2);
2741
3468
  }
2742
- finally { if (e_40) throw e_40.error; }
3469
+ finally { if (e_37) throw e_37.error; }
2743
3470
  }
2744
3471
  });
2745
3472
  try {
@@ -2752,26 +3479,26 @@ var DockviewComponent = /** @class */ (function (_super) {
2752
3479
  componentParams: snapshot.componentParams,
2753
3480
  });
2754
3481
  try {
2755
- for (var _g = (e_38 = void 0, __values(snapshot.panelIds)), _h = _g.next(); !_h.done; _h = _g.next()) {
2756
- var panelId = _h.value;
3482
+ for (var _k = (e_35 = void 0, __values(snapshot.panelIds)), _l = _k.next(); !_l.done; _l = _k.next()) {
3483
+ var panelId = _l.value;
2757
3484
  source.model.addPanelToTabGroup(newTabGroup.id, panelId);
2758
3485
  }
2759
3486
  }
2760
- catch (e_38_1) { e_38 = { error: e_38_1 }; }
3487
+ catch (e_35_1) { e_35 = { error: e_35_1 }; }
2761
3488
  finally {
2762
3489
  try {
2763
- if (_h && !_h.done && (_d = _g.return)) _d.call(_g);
3490
+ if (_l && !_l.done && (_d = _k.return)) _d.call(_k);
2764
3491
  }
2765
- finally { if (e_38) throw e_38.error; }
3492
+ finally { if (e_35) throw e_35.error; }
2766
3493
  }
2767
3494
  }
2768
3495
  }
2769
- catch (e_37_1) { e_37 = { error: e_37_1 }; }
3496
+ catch (e_34_1) { e_34 = { error: e_34_1 }; }
2770
3497
  finally {
2771
3498
  try {
2772
3499
  if (tabGroupSnapshots_2_1 && !tabGroupSnapshots_2_1.done && (_c = tabGroupSnapshots_2.return)) _c.call(tabGroupSnapshots_2);
2773
3500
  }
2774
- finally { if (e_37) throw e_37.error; }
3501
+ finally { if (e_34) throw e_34.error; }
2775
3502
  }
2776
3503
  }
2777
3504
  else {
@@ -2780,23 +3507,34 @@ var DockviewComponent = /** @class */ (function (_super) {
2780
3507
  this.gridview.removeView((0, gridview_1.getGridLocation)(from.element));
2781
3508
  break;
2782
3509
  case 'floating': {
2783
- var selectedFloatingGroup = this._floatingGroups.find(function (x) { return x.group === from; });
3510
+ var selectedFloatingGroup = (_e = this._floatingGroupService) === null || _e === void 0 ? void 0 : _e.findByGroup(from);
2784
3511
  if (!selectedFloatingGroup) {
2785
3512
  throw new Error('dockview: failed to find floating group');
2786
3513
  }
2787
- selectedFloatingGroup.dispose();
3514
+ // Detach just this group from the floating window's
3515
+ // nested gridview, keeping the window (and its other
3516
+ // groups) alive. If it was the only member, dispose the
3517
+ // whole window.
3518
+ if (!this.detachFromNestedWindow(from)) {
3519
+ selectedFloatingGroup.dispose();
3520
+ }
2788
3521
  break;
2789
3522
  }
2790
3523
  case 'popout': {
2791
- var selectedPopoutGroup = this._popoutGroups.find(function (x) { return x.popoutGroup === from; });
3524
+ var selectedPopoutGroup = (_f = this._popoutWindowService) === null || _f === void 0 ? void 0 : _f.findByGroup(from);
2792
3525
  if (!selectedPopoutGroup) {
2793
3526
  throw new Error('dockview: failed to find popout group');
2794
3527
  }
2795
- // Remove from popout groups list to prevent automatic restoration
2796
- var index = this._popoutGroups.indexOf(selectedPopoutGroup);
2797
- if (index >= 0) {
2798
- this._popoutGroups.splice(index, 1);
3528
+ // Detach just this group from the popout window's
3529
+ // nested gridview, keeping the window + its other groups
3530
+ // alive. Destination containers/location are applied by
3531
+ // the placement block below.
3532
+ if (this.detachFromNestedWindow(from)) {
3533
+ break;
2799
3534
  }
3535
+ // Last group leaving — tear the window down. Remove from
3536
+ // the service first to prevent automatic restoration.
3537
+ (_g = this._popoutWindowService) === null || _g === void 0 ? void 0 : _g.remove(selectedPopoutGroup);
2800
3538
  // Clean up the reference group (ghost) if it exists and is hidden
2801
3539
  if (selectedPopoutGroup.referenceGroup) {
2802
3540
  var referenceGroup = this.getPanel(selectedPopoutGroup.referenceGroup);
@@ -2807,34 +3545,25 @@ var DockviewComponent = /** @class */ (function (_super) {
2807
3545
  });
2808
3546
  }
2809
3547
  }
2810
- // Manually dispose the window without triggering restoration
3548
+ // Dispose the window without triggering restoration. The
3549
+ // placement block below applies the destination
3550
+ // location and containers to `from`.
2811
3551
  selectedPopoutGroup.window.dispose();
2812
- // Update group's location and containers for target
2813
- if (to.api.location.type === 'grid') {
2814
- from.model.renderContainer =
2815
- this.overlayRenderContainer;
2816
- from.model.dropTargetContainer =
2817
- this.rootDropTargetContainer;
2818
- from.model.location = { type: 'grid' };
2819
- }
2820
- else if (to.api.location.type === 'floating') {
2821
- from.model.renderContainer =
2822
- this.overlayRenderContainer;
2823
- from.model.dropTargetContainer =
2824
- this.rootDropTargetContainer;
2825
- from.model.location = { type: 'floating' };
2826
- }
2827
3552
  break;
2828
3553
  }
2829
3554
  }
2830
3555
  }
2831
- // For moves to grid locations
2832
- if (to.api.location.type === 'grid') {
3556
+ // Place `source` next to `to`, in whichever gridview root `to`
3557
+ // lives in. When `to` is inside a floating / popout window this
3558
+ // splits that window's nested layout rather than spawning a new one.
3559
+ if (to.api.location.type === 'grid' ||
3560
+ to.api.location.type === 'floating' ||
3561
+ to.api.location.type === 'popout') {
3562
+ var destGridview = this.getGridviewForGroup(to);
2833
3563
  var referenceLocation = (0, gridview_1.getGridLocation)(to.element);
2834
- var dropLocation = (0, gridview_1.getRelativeLocation)(this.gridview.orientation, referenceLocation, target);
2835
- // Add to grid for all moves targeting grid location
3564
+ var dropLocation = (0, gridview_1.getRelativeLocation)(destGridview.orientation, referenceLocation, target);
2836
3565
  var size = void 0;
2837
- switch (this.gridview.orientation) {
3566
+ switch (destGridview.orientation) {
2838
3567
  case splitview_1.Orientation.VERTICAL:
2839
3568
  size =
2840
3569
  referenceLocation.length % 2 == 0
@@ -2848,43 +3577,8 @@ var DockviewComponent = /** @class */ (function (_super) {
2848
3577
  : from.api.width;
2849
3578
  break;
2850
3579
  }
2851
- this.gridview.addView(source, size, dropLocation);
2852
- }
2853
- else if (to.api.location.type === 'floating') {
2854
- // For moves to floating locations, add as floating group
2855
- // Get the position/size from the target floating group
2856
- var targetFloatingGroup = this._floatingGroups.find(function (x) { return x.group === to; });
2857
- if (targetFloatingGroup) {
2858
- var box = targetFloatingGroup.overlay.toJSON();
2859
- // Calculate position based on available properties
2860
- var left = void 0, top_1;
2861
- if ('left' in box) {
2862
- left = box.left + 50;
2863
- }
2864
- else if ('right' in box) {
2865
- left = Math.max(0, box.right - box.width - 50);
2866
- }
2867
- else {
2868
- left = 50; // Default fallback
2869
- }
2870
- if ('top' in box) {
2871
- top_1 = box.top + 50;
2872
- }
2873
- else if ('bottom' in box) {
2874
- top_1 = Math.max(0, box.bottom - box.height - 50);
2875
- }
2876
- else {
2877
- top_1 = 50; // Default fallback
2878
- }
2879
- this.addFloatingGroup(source, {
2880
- height: box.height,
2881
- width: box.width,
2882
- position: {
2883
- left: left,
2884
- top: top_1,
2885
- },
2886
- });
2887
- }
3580
+ destGridview.addView(source, size, dropLocation);
3581
+ this.setGroupLocationForRoot(source, destGridview);
2888
3582
  }
2889
3583
  }
2890
3584
  source.panels.forEach(function (panel) {
@@ -2905,14 +3599,16 @@ var DockviewComponent = /** @class */ (function (_super) {
2905
3599
  }
2906
3600
  };
2907
3601
  DockviewComponent.prototype.doSetGroupActive = function (group) {
3602
+ var _a;
2908
3603
  _super.prototype.doSetGroupActive.call(this, group);
2909
3604
  var activePanel = this.activePanel;
2910
3605
  if (!this._moving &&
2911
- activePanel !== this._onDidActivePanelChange.value) {
2912
- this._onDidActivePanelChange.fire(activePanel);
3606
+ activePanel !== ((_a = this._onDidActivePanelChange.value) === null || _a === void 0 ? void 0 : _a.panel)) {
3607
+ this.fireActivePanelChange(activePanel);
2913
3608
  }
2914
3609
  };
2915
3610
  DockviewComponent.prototype.doSetGroupAndPanelActive = function (group) {
3611
+ var _a;
2916
3612
  _super.prototype.doSetGroupActive.call(this, group);
2917
3613
  var activePanel = this.activePanel;
2918
3614
  if (group &&
@@ -2921,8 +3617,8 @@ var DockviewComponent = /** @class */ (function (_super) {
2921
3617
  this.exitMaximizedGroup();
2922
3618
  }
2923
3619
  if (!this._moving &&
2924
- activePanel !== this._onDidActivePanelChange.value) {
2925
- this._onDidActivePanelChange.fire(activePanel);
3620
+ activePanel !== ((_a = this._onDidActivePanelChange.value) === null || _a === void 0 ? void 0 : _a.panel)) {
3621
+ this.fireActivePanelChange(activePanel);
2926
3622
  }
2927
3623
  };
2928
3624
  DockviewComponent.prototype.getNextGroupId = function () {
@@ -2934,9 +3630,7 @@ var DockviewComponent = /** @class */ (function (_super) {
2934
3630
  };
2935
3631
  DockviewComponent.prototype.createGroup = function (options) {
2936
3632
  var _this = this;
2937
- if (!options) {
2938
- options = {};
2939
- }
3633
+ options !== null && options !== void 0 ? options : (options = {});
2940
3634
  var id = options === null || options === void 0 ? void 0 : options.id;
2941
3635
  if (id && this._groups.has(options.id)) {
2942
3636
  console.warn("dockview: Duplicate group id ".concat(options === null || options === void 0 ? void 0 : options.id, ". reassigning group id to avoid errors"));
@@ -2952,9 +3646,11 @@ var DockviewComponent = /** @class */ (function (_super) {
2952
3646
  view.init({ params: {}, accessor: this });
2953
3647
  if (!this._groups.has(view.id)) {
2954
3648
  var disposable = new lifecycle_1.CompositeDisposable(view.model.onTabDragStart(function (event) {
2955
- _this._onWillDragPanel.fire(event);
3649
+ var _a;
3650
+ (_a = _this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillDragPanel(event);
2956
3651
  }), view.model.onGroupDragStart(function (event) {
2957
- _this._onWillDragGroup.fire(event);
3652
+ var _a;
3653
+ (_a = _this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillDragGroup(event);
2958
3654
  }), view.model.onMove(function (event) {
2959
3655
  var groupId = event.groupId, itemId = event.itemId, target = event.target, index = event.index, tabGroupId = event.tabGroupId;
2960
3656
  _this.moveGroupOrPanel({
@@ -2972,15 +3668,19 @@ var DockviewComponent = /** @class */ (function (_super) {
2972
3668
  }), view.model.onDidDrop(function (event) {
2973
3669
  _this._onDidDrop.fire(event);
2974
3670
  }), view.model.onWillDrop(function (event) {
2975
- _this._onWillDrop.fire(event);
3671
+ var _a;
3672
+ (_a = _this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillDrop(event);
2976
3673
  }), view.model.onWillShowOverlay(function (event) {
3674
+ var _a;
2977
3675
  if (_this.options.disableDnd) {
3676
+ // Engine policy — stays in core, ahead of any
3677
+ // customisation dispatch.
2978
3678
  event.preventDefault();
2979
3679
  return;
2980
3680
  }
2981
- _this._onWillShowOverlay.fire(event);
2982
- }), view.model.onUnhandledDragOverEvent(function (event) {
2983
- _this._onUnhandledDragOverEvent.fire(event);
3681
+ (_a = _this._advancedDnDService) === null || _a === void 0 ? void 0 : _a.dispatchWillShowOverlay(event);
3682
+ }), view.model.onUnhandledDragOver(function (event) {
3683
+ _this._onUnhandledDragOver.fire(event);
2984
3684
  }), view.model.onDidAddPanel(function (event) {
2985
3685
  if (_this._moving) {
2986
3686
  return;
@@ -2992,27 +3692,17 @@ var DockviewComponent = /** @class */ (function (_super) {
2992
3692
  }
2993
3693
  _this._onDidRemovePanel.fire(event.panel);
2994
3694
  }), view.model.onDidActivePanelChange(function (event) {
3695
+ var _a;
2995
3696
  if (_this._moving) {
2996
3697
  return;
2997
3698
  }
2998
3699
  if (event.panel !== _this.activePanel) {
2999
3700
  return;
3000
3701
  }
3001
- if (_this._onDidActivePanelChange.value !== event.panel) {
3002
- _this._onDidActivePanelChange.fire(event.panel);
3003
- }
3004
- }), view.model.onDidCreateTabGroup(function (e) {
3005
- _this._onDidCreateTabGroup.fire(e);
3006
- }), view.model.onDidDestroyTabGroup(function (e) {
3007
- _this._onDidDestroyTabGroup.fire(e);
3008
- }), view.model.onDidAddPanelToTabGroup(function (e) {
3009
- _this._onDidAddPanelToTabGroup.fire(e);
3010
- }), view.model.onDidRemovePanelFromTabGroup(function (e) {
3011
- _this._onDidRemovePanelFromTabGroup.fire(e);
3012
- }), view.model.onDidTabGroupChange(function (e) {
3013
- _this._onDidTabGroupChange.fire(e);
3014
- }), view.model.onDidTabGroupCollapsedChange(function (e) {
3015
- _this._onDidTabGroupCollapsedChange.fire(e);
3702
+ if (((_a = _this._onDidActivePanelChange.value) === null || _a === void 0 ? void 0 : _a.panel) !==
3703
+ event.panel) {
3704
+ _this.fireActivePanelChange(event.panel);
3705
+ }
3016
3706
  }), events_1.Event.any(view.model.onDidPanelTitleChange, view.model.onDidPanelParametersChange)(function () {
3017
3707
  _this._bufferOnDidLayoutChange.fire();
3018
3708
  }));
@@ -3040,11 +3730,76 @@ var DockviewComponent = /** @class */ (function (_super) {
3040
3730
  });
3041
3731
  return panel;
3042
3732
  };
3043
- DockviewComponent.prototype.createGroupAtLocation = function (location, size, options) {
3733
+ DockviewComponent.prototype.createGroupAtLocation = function (location, size, options, gridview) {
3734
+ if (gridview === void 0) { gridview = this.gridview; }
3044
3735
  var group = this.createGroup(options);
3045
- this.doAddGroup(group, location, size);
3736
+ this.doAddGroup(group, location, size, gridview);
3737
+ this.setGroupLocationForRoot(group, gridview);
3046
3738
  return group;
3047
3739
  };
3740
+ /**
3741
+ * Tag a group with the location and render / drop-target containers
3742
+ * matching the gridview root it now lives in: the main grid, a floating
3743
+ * window (shares the main containers), or a popout window (uses its own
3744
+ * window-local containers).
3745
+ */
3746
+ DockviewComponent.prototype.setGroupLocationForRoot = function (group, gridview) {
3747
+ var _a;
3748
+ var popout = (_a = this._popoutWindowService) === null || _a === void 0 ? void 0 : _a.entries.find(function (entry) { return entry.gridview === gridview; });
3749
+ if (popout) {
3750
+ if (group.model.renderContainer !== popout.overlayRenderContainer) {
3751
+ group.model.renderContainer = popout.overlayRenderContainer;
3752
+ }
3753
+ group.model.dropTargetContainer = popout.dropTargetContainer;
3754
+ group.model.location = {
3755
+ type: 'popout',
3756
+ getWindow: popout.getWindow,
3757
+ popoutUrl: popout.popoutUrl,
3758
+ };
3759
+ return;
3760
+ }
3761
+ // grid / floating both render through the main containers
3762
+ if (group.model.renderContainer !== this.overlayRenderContainer) {
3763
+ group.model.renderContainer = this.overlayRenderContainer;
3764
+ }
3765
+ group.model.dropTargetContainer = this.rootDropTargetContainer;
3766
+ group.model.location =
3767
+ gridview === this.gridview
3768
+ ? { type: 'grid' }
3769
+ : { type: 'floating' };
3770
+ };
3771
+ /**
3772
+ * Resolve which gridview root currently owns a group: the main grid, or
3773
+ * the nested gridview of the floating / popout window it lives in.
3774
+ */
3775
+ DockviewComponent.prototype.getGridviewForGroup = function (group) {
3776
+ var _a, _b;
3777
+ var floating = (_a = this._floatingGroupService) === null || _a === void 0 ? void 0 : _a.findByGroup(group);
3778
+ if (floating) {
3779
+ return floating.gridview;
3780
+ }
3781
+ // Use findByGroup (anchor-identity OR containment) for symmetry with
3782
+ // the floating branch — it also resolves an anchor whose element is
3783
+ // briefly detached from the gridview during a move/restore.
3784
+ var popout = (_b = this._popoutWindowService) === null || _b === void 0 ? void 0 : _b.findByGroup(group);
3785
+ if (popout) {
3786
+ return popout.gridview;
3787
+ }
3788
+ return this.gridview;
3789
+ };
3790
+ /**
3791
+ * The groups that live within the same floating / popout window as `group`
3792
+ * (including `group` itself). Empty when `group` is in the main grid.
3793
+ */
3794
+ DockviewComponent.prototype.nestedWindowMembers = function (group) {
3795
+ var gridview = this.getGridviewForGroup(group);
3796
+ if (gridview === this.gridview) {
3797
+ return [];
3798
+ }
3799
+ return this.groups.filter(function (candidate) {
3800
+ return gridview.element.contains(candidate.element);
3801
+ });
3802
+ };
3048
3803
  DockviewComponent.prototype.findGroup = function (panel) {
3049
3804
  var _a;
3050
3805
  return (_a = Array.from(this._groups.values()).find(function (group) {
@@ -3057,44 +3812,53 @@ var DockviewComponent = /** @class */ (function (_super) {
3057
3812
  ? rootOrientation
3058
3813
  : (0, gridview_1.orthogonal)(rootOrientation);
3059
3814
  };
3060
- DockviewComponent.prototype.updateDropTargetModel = function (options) {
3061
- if ('dndEdges' in options) {
3062
- var disabled = typeof options.dndEdges === 'boolean' &&
3063
- options.dndEdges === false;
3064
- this._rootDropTarget.disabled = disabled;
3065
- this._rootPointerDropTarget.disabled = disabled;
3066
- if (typeof options.dndEdges === 'object' &&
3067
- options.dndEdges !== null) {
3068
- this._rootDropTarget.setOverlayModel(options.dndEdges);
3069
- this._rootPointerDropTarget.setOverlayModel(options.dndEdges);
3070
- }
3071
- else {
3072
- this._rootDropTarget.setOverlayModel(DEFAULT_ROOT_OVERLAY_MODEL);
3073
- this._rootPointerDropTarget.setOverlayModel(DEFAULT_ROOT_OVERLAY_MODEL);
3074
- }
3075
- }
3076
- if ('rootOverlayModel' in options) {
3077
- this.updateDropTargetModel({ dndEdges: options.dndEdges });
3078
- }
3079
- };
3080
3815
  DockviewComponent.prototype.updateTheme = function () {
3081
- var e_41, _a;
3082
- var _b, _c, _d, _e, _f, _g, _h, _j, _k;
3083
- var theme = (_b = this._options.theme) !== null && _b !== void 0 ? _b : theme_1.themeAbyss;
3816
+ var e_38, _a, e_39, _b, e_40, _c;
3817
+ var _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
3818
+ var theme = (_d = this._options.theme) !== null && _d !== void 0 ? _d : theme_1.themeAbyss;
3084
3819
  // Apply the theme class only to the shell so edge groups and the
3085
3820
  // main grid both inherit its CSS custom properties via the cascade.
3086
3821
  // Re-declaring it on `.dv-dockview` would block consumer overrides
3087
3822
  // set on the shell from reaching the dockview subtree.
3088
- (_c = this._shellThemeClassnames) === null || _c === void 0 ? void 0 : _c.setClassNames(theme.className);
3089
- this.gridview.margin = (_d = theme.gap) !== null && _d !== void 0 ? _d : 0;
3090
- (_e = this._shellManager) === null || _e === void 0 ? void 0 : _e.updateTheme((_f = theme.gap) !== null && _f !== void 0 ? _f : 0, (_g = theme.edgeGroupCollapsedSize) !== null && _g !== void 0 ? _g : 35);
3091
- if (theme.dndOverlayBorder !== undefined) {
3092
- this.element.style.setProperty('--dv-drag-over-border', theme.dndOverlayBorder);
3093
- (_h = this._shellManager) === null || _h === void 0 ? void 0 : _h.element.style.setProperty('--dv-drag-over-border', theme.dndOverlayBorder);
3823
+ (_e = this._shellThemeClassnames) === null || _e === void 0 ? void 0 : _e.setClassNames(theme.className);
3824
+ var gap = (_f = theme.gap) !== null && _f !== void 0 ? _f : 0;
3825
+ this.gridview.margin = gap;
3826
+ try {
3827
+ // Floating / popout windows host their own nested gridviews; keep their
3828
+ // gap in sync with the main grid when the theme changes at runtime.
3829
+ for (var _p = __values(this.floatingGroups), _q = _p.next(); !_q.done; _q = _p.next()) {
3830
+ var floating = _q.value;
3831
+ floating.gridview.margin = gap;
3832
+ }
3094
3833
  }
3095
- else {
3834
+ catch (e_38_1) { e_38 = { error: e_38_1 }; }
3835
+ finally {
3836
+ try {
3837
+ if (_q && !_q.done && (_a = _p.return)) _a.call(_p);
3838
+ }
3839
+ finally { if (e_38) throw e_38.error; }
3840
+ }
3841
+ try {
3842
+ for (var _r = __values((_h = (_g = this._popoutWindowService) === null || _g === void 0 ? void 0 : _g.entries) !== null && _h !== void 0 ? _h : []), _s = _r.next(); !_s.done; _s = _r.next()) {
3843
+ var entry = _s.value;
3844
+ entry.gridview.margin = gap;
3845
+ }
3846
+ }
3847
+ catch (e_39_1) { e_39 = { error: e_39_1 }; }
3848
+ finally {
3849
+ try {
3850
+ if (_s && !_s.done && (_b = _r.return)) _b.call(_r);
3851
+ }
3852
+ finally { if (e_39) throw e_39.error; }
3853
+ }
3854
+ (_j = this._shellManager) === null || _j === void 0 ? void 0 : _j.updateTheme(gap, (_k = theme.edgeGroupCollapsedSize) !== null && _k !== void 0 ? _k : 35);
3855
+ if (theme.dndOverlayBorder === undefined) {
3096
3856
  this.element.style.removeProperty('--dv-drag-over-border');
3097
- (_j = this._shellManager) === null || _j === void 0 ? void 0 : _j.element.style.removeProperty('--dv-drag-over-border');
3857
+ (_l = this._shellManager) === null || _l === void 0 ? void 0 : _l.element.style.removeProperty('--dv-drag-over-border');
3858
+ }
3859
+ else {
3860
+ this.element.style.setProperty('--dv-drag-over-border', theme.dndOverlayBorder);
3861
+ (_m = this._shellManager) === null || _m === void 0 ? void 0 : _m.element.style.setProperty('--dv-drag-over-border', theme.dndOverlayBorder);
3098
3862
  }
3099
3863
  switch (theme.dndOverlayMounting) {
3100
3864
  case 'absolute':
@@ -3107,24 +3871,24 @@ var DockviewComponent = /** @class */ (function (_super) {
3107
3871
  }
3108
3872
  // Toggle a CSS class so theme stylesheets can scope pure-CSS
3109
3873
  // tab group indicator rules to the 'none' mode only.
3110
- var indicatorNone = ((_k = theme.tabGroupIndicator) !== null && _k !== void 0 ? _k : 'wrap') === 'none';
3874
+ var indicatorNone = ((_o = theme.tabGroupIndicator) !== null && _o !== void 0 ? _o : 'wrap') === 'none';
3111
3875
  (0, dom_1.toggleClass)(this.element, 'dv-tab-group-indicator-none', indicatorNone);
3112
3876
  if (this._shellManager) {
3113
3877
  (0, dom_1.toggleClass)(this._shellManager.element, 'dv-tab-group-indicator-none', indicatorNone);
3114
3878
  }
3115
3879
  try {
3116
3880
  // Re-render tab group indicators so the new tabGroupIndicator mode takes effect
3117
- for (var _l = __values(this.groups), _m = _l.next(); !_m.done; _m = _l.next()) {
3118
- var group = _m.value;
3881
+ for (var _t = __values(this.groups), _u = _t.next(); !_u.done; _u = _t.next()) {
3882
+ var group = _u.value;
3119
3883
  group.model.updateTabGroups();
3120
3884
  }
3121
3885
  }
3122
- catch (e_41_1) { e_41 = { error: e_41_1 }; }
3886
+ catch (e_40_1) { e_40 = { error: e_40_1 }; }
3123
3887
  finally {
3124
3888
  try {
3125
- if (_m && !_m.done && (_a = _l.return)) _a.call(_l);
3889
+ if (_u && !_u.done && (_c = _t.return)) _c.call(_t);
3126
3890
  }
3127
- finally { if (e_41) throw e_41.error; }
3891
+ finally { if (e_40) throw e_40.error; }
3128
3892
  }
3129
3893
  };
3130
3894
  return DockviewComponent;