dockview-core 5.2.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/cjs/api/component.api.d.ts +93 -1
- package/dist/cjs/api/component.api.js +146 -0
- package/dist/cjs/api/dockviewGroupPanelApi.d.ts +26 -0
- package/dist/cjs/api/dockviewGroupPanelApi.js +21 -1
- package/dist/cjs/api/entryPoints.js +4 -5
- package/dist/cjs/array.js +7 -8
- package/dist/cjs/dnd/dataTransfer.d.ts +2 -1
- package/dist/cjs/dnd/dataTransfer.js +5 -4
- package/dist/cjs/dnd/droptarget.d.ts +12 -0
- package/dist/cjs/dnd/droptarget.js +38 -10
- package/dist/cjs/dnd/ghost.js +1 -2
- package/dist/cjs/dockview/components/panel/content.js +5 -1
- package/dist/cjs/dockview/components/popupService.d.ts +9 -2
- package/dist/cjs/dockview/components/popupService.js +24 -9
- package/dist/cjs/dockview/components/tab/tab.d.ts +6 -1
- package/dist/cjs/dockview/components/tab/tab.js +81 -9
- package/dist/cjs/dockview/components/titlebar/tabGroupChip.d.ts +30 -0
- package/dist/cjs/dockview/components/titlebar/tabGroupChip.js +95 -0
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.d.ts +71 -0
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +471 -0
- package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +57 -0
- package/dist/cjs/dockview/components/titlebar/tabGroups.js +612 -0
- package/dist/cjs/dockview/components/titlebar/tabOverflowControl.js +1 -2
- package/dist/cjs/dockview/components/titlebar/tabs.d.ts +59 -0
- package/dist/cjs/dockview/components/titlebar/tabs.js +1227 -144
- package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +6 -0
- package/dist/cjs/dockview/components/titlebar/tabsContainer.js +132 -14
- package/dist/cjs/dockview/contextMenu.d.ts +10 -0
- package/dist/cjs/dockview/contextMenu.js +298 -0
- package/dist/cjs/dockview/dockviewComponent.d.ts +60 -3
- package/dist/cjs/dockview/dockviewComponent.js +712 -126
- package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +83 -0
- package/dist/cjs/dockview/dockviewGroupPanelModel.js +619 -27
- package/dist/cjs/dockview/dockviewShell.d.ts +128 -0
- package/dist/cjs/dockview/dockviewShell.js +681 -0
- package/dist/cjs/dockview/events.d.ts +9 -0
- package/dist/cjs/dockview/framework.d.ts +14 -0
- package/dist/cjs/dockview/options.d.ts +92 -10
- package/dist/cjs/dockview/options.js +10 -7
- package/dist/cjs/dockview/tabGroup.d.ts +99 -0
- package/dist/cjs/dockview/tabGroup.js +219 -0
- package/dist/cjs/dockview/tabGroupAccent.d.ts +65 -0
- package/dist/cjs/dockview/tabGroupAccent.js +128 -0
- package/dist/cjs/dockview/theme.d.ts +56 -1
- package/dist/cjs/dockview/theme.js +103 -6
- package/dist/cjs/dockview/types.d.ts +2 -0
- package/dist/cjs/dom.js +19 -19
- package/dist/cjs/events.js +2 -2
- package/dist/cjs/gridview/baseComponentGridview.d.ts +1 -0
- package/dist/cjs/gridview/baseComponentGridview.js +6 -3
- package/dist/cjs/gridview/gridview.js +7 -7
- package/dist/cjs/index.d.ts +8 -5
- package/dist/cjs/index.js +6 -1
- package/dist/cjs/popoutWindow.js +3 -3
- package/dist/cjs/splitview/splitviewPanel.d.ts +1 -1
- package/dist/dockview-core.js +6942 -2777
- package/dist/dockview-core.min.js +2 -2
- package/dist/dockview-core.min.js.map +1 -1
- package/dist/dockview-core.min.noStyle.js +2 -2
- package/dist/dockview-core.min.noStyle.js.map +1 -1
- package/dist/dockview-core.noStyle.js +6940 -2775
- package/dist/esm/api/component.api.d.ts +93 -1
- package/dist/esm/api/component.api.js +118 -0
- package/dist/esm/api/dockviewGroupPanelApi.d.ts +26 -0
- package/dist/esm/api/dockviewGroupPanelApi.js +21 -1
- package/dist/esm/dnd/dataTransfer.d.ts +2 -1
- package/dist/esm/dnd/dataTransfer.js +2 -1
- package/dist/esm/dnd/droptarget.d.ts +12 -0
- package/dist/esm/dnd/droptarget.js +33 -5
- package/dist/esm/dockview/components/panel/content.js +5 -1
- package/dist/esm/dockview/components/popupService.d.ts +9 -2
- package/dist/esm/dockview/components/popupService.js +23 -9
- package/dist/esm/dockview/components/tab/tab.d.ts +6 -1
- package/dist/esm/dockview/components/tab/tab.js +83 -9
- package/dist/esm/dockview/components/titlebar/tabGroupChip.d.ts +30 -0
- package/dist/esm/dockview/components/titlebar/tabGroupChip.js +68 -0
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.d.ts +71 -0
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +354 -0
- package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +57 -0
- package/dist/esm/dockview/components/titlebar/tabGroups.js +406 -0
- package/dist/esm/dockview/components/titlebar/tabs.d.ts +59 -0
- package/dist/esm/dockview/components/titlebar/tabs.js +1011 -99
- package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +6 -0
- package/dist/esm/dockview/components/titlebar/tabsContainer.js +105 -7
- package/dist/esm/dockview/contextMenu.d.ts +10 -0
- package/dist/esm/dockview/contextMenu.js +213 -0
- package/dist/esm/dockview/dockviewComponent.d.ts +60 -3
- package/dist/esm/dockview/dockviewComponent.js +460 -35
- package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +83 -0
- package/dist/esm/dockview/dockviewGroupPanelModel.js +460 -4
- package/dist/esm/dockview/dockviewShell.d.ts +128 -0
- package/dist/esm/dockview/dockviewShell.js +621 -0
- package/dist/esm/dockview/events.d.ts +9 -0
- package/dist/esm/dockview/framework.d.ts +14 -0
- package/dist/esm/dockview/options.d.ts +92 -10
- package/dist/esm/dockview/options.js +5 -2
- package/dist/esm/dockview/tabGroup.d.ts +99 -0
- package/dist/esm/dockview/tabGroup.js +144 -0
- package/dist/esm/dockview/tabGroupAccent.d.ts +65 -0
- package/dist/esm/dockview/tabGroupAccent.js +116 -0
- package/dist/esm/dockview/theme.d.ts +56 -1
- package/dist/esm/dockview/theme.js +102 -5
- package/dist/esm/dockview/types.d.ts +2 -0
- package/dist/esm/dom.js +1 -1
- package/dist/esm/gridview/baseComponentGridview.d.ts +1 -0
- package/dist/esm/gridview/baseComponentGridview.js +4 -1
- package/dist/esm/index.d.ts +8 -5
- package/dist/esm/index.js +2 -1
- package/dist/esm/popoutWindow.js +1 -1
- package/dist/esm/splitview/splitviewPanel.d.ts +1 -1
- package/dist/package/main.cjs.js +6936 -2801
- package/dist/package/main.cjs.min.js +2 -2
- package/dist/package/main.esm.min.mjs +2 -2
- package/dist/package/main.esm.mjs +6922 -2800
- package/dist/styles/dockview.css +1945 -196
- package/package.json +5 -1
|
@@ -9,6 +9,7 @@ import { DockviewHeaderDirection } from '../../options';
|
|
|
9
9
|
export interface TabDropIndexEvent {
|
|
10
10
|
readonly event: DragEvent;
|
|
11
11
|
readonly index: number;
|
|
12
|
+
readonly targetTabGroupId?: string | null;
|
|
12
13
|
}
|
|
13
14
|
export interface TabDragEvent {
|
|
14
15
|
readonly nativeEvent: DragEvent;
|
|
@@ -41,6 +42,8 @@ export interface ITabsContainer extends IDisposable {
|
|
|
41
42
|
show(): void;
|
|
42
43
|
hide(): void;
|
|
43
44
|
updateDragAndDropState(): void;
|
|
45
|
+
updateTabGroups(): void;
|
|
46
|
+
refreshTabGroupAccent(): void;
|
|
44
47
|
}
|
|
45
48
|
export declare class TabsContainer extends CompositeDisposable implements ITabsContainer {
|
|
46
49
|
private readonly accessor;
|
|
@@ -58,6 +61,7 @@ export declare class TabsContainer extends CompositeDisposable implements ITabsC
|
|
|
58
61
|
private _direction;
|
|
59
62
|
private dropdownPart;
|
|
60
63
|
private _overflowTabs;
|
|
64
|
+
private _overflowTabGroups;
|
|
61
65
|
private readonly _dropdownDisposable;
|
|
62
66
|
private readonly _onDrop;
|
|
63
67
|
readonly onDrop: Event<TabDropIndexEvent>;
|
|
@@ -89,4 +93,6 @@ export declare class TabsContainer extends CompositeDisposable implements ITabsC
|
|
|
89
93
|
private updateClassnames;
|
|
90
94
|
private toggleDropdown;
|
|
91
95
|
updateDragAndDropState(): void;
|
|
96
|
+
updateTabGroups(): void;
|
|
97
|
+
refreshTabGroupAccent(): void;
|
|
92
98
|
}
|
|
@@ -6,6 +6,7 @@ import { DockviewWillShowOverlayLocationEvent } from '../../events';
|
|
|
6
6
|
import { getPanelData } from '../../../dnd/dataTransfer';
|
|
7
7
|
import { Tabs } from './tabs';
|
|
8
8
|
import { createDropdownElementHandle, } from './tabOverflowControl';
|
|
9
|
+
import { applyTabGroupAccent } from '../../tabGroupAccent';
|
|
9
10
|
export class TabsContainer extends CompositeDisposable {
|
|
10
11
|
get onTabDragStart() {
|
|
11
12
|
return this.tabs.onTabDragStart;
|
|
@@ -50,6 +51,7 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
50
51
|
this._direction = 'horizontal';
|
|
51
52
|
this.dropdownPart = null;
|
|
52
53
|
this._overflowTabs = [];
|
|
54
|
+
this._overflowTabGroups = [];
|
|
53
55
|
this._dropdownDisposable = new MutableDisposable();
|
|
54
56
|
this._onDrop = new Emitter();
|
|
55
57
|
this.onDrop = this._onDrop.event;
|
|
@@ -70,11 +72,13 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
70
72
|
showTabsOverflowControl: !accessor.options.disableTabsOverflowList,
|
|
71
73
|
});
|
|
72
74
|
this.voidContainer = new VoidContainer(this.accessor, this.group);
|
|
75
|
+
this.tabs.voidContainer = this.voidContainer.element;
|
|
73
76
|
this._element.appendChild(this.preActionsContainer);
|
|
74
77
|
this._element.appendChild(this.tabs.element);
|
|
75
78
|
this._element.appendChild(this.leftActionsContainer);
|
|
76
79
|
this._element.appendChild(this.voidContainer.element);
|
|
77
80
|
this._element.appendChild(this.rightActionsContainer);
|
|
81
|
+
this.tabs.setExtendedDropZone(this._element);
|
|
78
82
|
this.addDisposables(this.tabs.onDrop((e) => this._onDrop.fire(e)), this.tabs.onWillShowOverlay((e) => this._onWillShowOverlay.fire(e)), accessor.onDidOptionsChange(() => {
|
|
79
83
|
this.tabs.showTabsOverflowControl =
|
|
80
84
|
!accessor.options.disableTabsOverflowList;
|
|
@@ -86,6 +90,10 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
86
90
|
group: this.group,
|
|
87
91
|
});
|
|
88
92
|
}), this.voidContainer.onDrop((event) => {
|
|
93
|
+
// If an active group drag is in progress, let Tabs handle it
|
|
94
|
+
if (this.tabs.handleVoidDrop()) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
89
97
|
this._onDrop.fire({
|
|
90
98
|
event: event.nativeEvent,
|
|
91
99
|
index: this.tabs.size,
|
|
@@ -98,6 +106,25 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
98
106
|
group: this.group,
|
|
99
107
|
getData: getPanelData,
|
|
100
108
|
}));
|
|
109
|
+
}), addDisposableListener(this.leftActionsContainer, 'dragleave', (event) => {
|
|
110
|
+
const related = event.relatedTarget;
|
|
111
|
+
if (!this.leftActionsContainer.contains(related) &&
|
|
112
|
+
!this._element.contains(related)) {
|
|
113
|
+
// Left the header entirely
|
|
114
|
+
this.tabs.clearExternalAnimState();
|
|
115
|
+
}
|
|
116
|
+
}), addDisposableListener(this.voidContainer.element, 'dragleave', (event) => {
|
|
117
|
+
const related = event.relatedTarget;
|
|
118
|
+
if (!this.voidContainer.element.contains(related)) {
|
|
119
|
+
if (this._element.contains(related)) {
|
|
120
|
+
// Moved to another part of the header — keep state
|
|
121
|
+
this.tabs.setExternalInsertionIndex(null);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Left the header entirely
|
|
125
|
+
this.tabs.clearExternalAnimState();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
101
128
|
}), addDisposableListener(this.voidContainer.element, 'pointerdown', (event) => {
|
|
102
129
|
if (event.defaultPrevented) {
|
|
103
130
|
return;
|
|
@@ -105,7 +132,8 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
105
132
|
const isFloatingGroupsEnabled = !this.accessor.options.disableFloatingGroups;
|
|
106
133
|
if (isFloatingGroupsEnabled &&
|
|
107
134
|
event.shiftKey &&
|
|
108
|
-
this.group.api.location.type !== 'floating'
|
|
135
|
+
this.group.api.location.type !== 'floating' &&
|
|
136
|
+
this.group.api.location.type !== 'edge') {
|
|
109
137
|
event.preventDefault();
|
|
110
138
|
const { top, left } = this.element.getBoundingClientRect();
|
|
111
139
|
const { top: rootTop, left: rootLeft } = this.accessor.element.getBoundingClientRect();
|
|
@@ -192,19 +220,22 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
192
220
|
}
|
|
193
221
|
toggleDropdown(options) {
|
|
194
222
|
const tabs = options.reset ? [] : options.tabs;
|
|
223
|
+
const tabGroups = options.reset ? [] : options.tabGroups;
|
|
195
224
|
this._overflowTabs = tabs;
|
|
196
|
-
|
|
197
|
-
|
|
225
|
+
this._overflowTabGroups = tabGroups;
|
|
226
|
+
const totalCount = this._overflowTabs.length;
|
|
227
|
+
if (totalCount > 0 && this.dropdownPart) {
|
|
228
|
+
this.dropdownPart.update({ tabs: totalCount });
|
|
198
229
|
return;
|
|
199
230
|
}
|
|
200
|
-
if (
|
|
231
|
+
if (totalCount === 0) {
|
|
201
232
|
this._dropdownDisposable.dispose();
|
|
202
233
|
return;
|
|
203
234
|
}
|
|
204
235
|
const root = document.createElement('div');
|
|
205
236
|
root.className = 'dv-tabs-overflow-dropdown-root';
|
|
206
237
|
const part = createDropdownElementHandle();
|
|
207
|
-
part.update({ tabs:
|
|
238
|
+
part.update({ tabs: totalCount });
|
|
208
239
|
this.dropdownPart = part;
|
|
209
240
|
root.appendChild(part.element);
|
|
210
241
|
this.rightActionsContainer.prepend(root);
|
|
@@ -219,7 +250,58 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
219
250
|
const el = document.createElement('div');
|
|
220
251
|
el.style.overflow = 'auto';
|
|
221
252
|
el.className = 'dv-tabs-overflow-container';
|
|
253
|
+
// Build lookup: panelId → tabGroup for overflow groups
|
|
254
|
+
const overflowGroupSet = new Set(this._overflowTabGroups);
|
|
255
|
+
const allTabGroups = this.group.model.getTabGroups();
|
|
256
|
+
const panelToGroup = new Map();
|
|
257
|
+
for (const tg of allTabGroups) {
|
|
258
|
+
if (overflowGroupSet.has(tg.id)) {
|
|
259
|
+
for (const pid of tg.panelIds) {
|
|
260
|
+
panelToGroup.set(pid, tg);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Track which groups have already been rendered
|
|
265
|
+
const renderedGroups = new Set();
|
|
222
266
|
for (const tab of this.tabs.tabs.filter((tab) => this._overflowTabs.includes(tab.panel.id))) {
|
|
267
|
+
const tg = panelToGroup.get(tab.panel.id);
|
|
268
|
+
// If this tab belongs to an overflow group, render the
|
|
269
|
+
// group header before its first member tab.
|
|
270
|
+
if (tg && !renderedGroups.has(tg.id)) {
|
|
271
|
+
renderedGroups.add(tg.id);
|
|
272
|
+
const groupHeader = document.createElement('div');
|
|
273
|
+
groupHeader.className = 'dv-tabs-overflow-group-header';
|
|
274
|
+
const colorDot = document.createElement('span');
|
|
275
|
+
colorDot.className = 'dv-tabs-overflow-group-color';
|
|
276
|
+
applyTabGroupAccent(colorDot, tg.color, this.accessor.tabGroupColorPalette);
|
|
277
|
+
groupHeader.appendChild(colorDot);
|
|
278
|
+
const labelSpan = document.createElement('span');
|
|
279
|
+
labelSpan.className = 'dv-tabs-overflow-group-label';
|
|
280
|
+
labelSpan.textContent = tg.label || tg.id;
|
|
281
|
+
groupHeader.appendChild(labelSpan);
|
|
282
|
+
if (tg.collapsed) {
|
|
283
|
+
const badge = document.createElement('span');
|
|
284
|
+
badge.className =
|
|
285
|
+
'dv-tabs-overflow-group-collapsed-badge';
|
|
286
|
+
badge.textContent = `${tg.panelIds.length}`;
|
|
287
|
+
groupHeader.appendChild(badge);
|
|
288
|
+
}
|
|
289
|
+
groupHeader.addEventListener('click', () => {
|
|
290
|
+
this.accessor
|
|
291
|
+
.getPopupServiceForGroup(this.group)
|
|
292
|
+
.close();
|
|
293
|
+
if (tg.collapsed) {
|
|
294
|
+
tg.expand();
|
|
295
|
+
}
|
|
296
|
+
// Activate the first panel in the group
|
|
297
|
+
const firstPanelId = tg.panelIds[0];
|
|
298
|
+
if (firstPanelId) {
|
|
299
|
+
const panel = this.group.panels.find((p) => p.id === firstPanelId);
|
|
300
|
+
panel === null || panel === void 0 ? void 0 : panel.api.setActive();
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
el.appendChild(groupHeader);
|
|
304
|
+
}
|
|
223
305
|
const panelObject = this.group.panels.find((panel) => panel === tab.panel);
|
|
224
306
|
const tabComponent = panelObject.view.createTabRenderer('headerOverflow');
|
|
225
307
|
const child = tabComponent.element;
|
|
@@ -227,11 +309,19 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
227
309
|
toggleClass(wrapper, 'dv-tab', true);
|
|
228
310
|
toggleClass(wrapper, 'dv-active-tab', panelObject.api.isActive);
|
|
229
311
|
toggleClass(wrapper, 'dv-inactive-tab', !panelObject.api.isActive);
|
|
312
|
+
if (tg) {
|
|
313
|
+
toggleClass(wrapper, 'dv-tab--grouped', true);
|
|
314
|
+
}
|
|
230
315
|
wrapper.addEventListener('click', (event) => {
|
|
231
|
-
this.accessor
|
|
316
|
+
this.accessor
|
|
317
|
+
.getPopupServiceForGroup(this.group)
|
|
318
|
+
.close();
|
|
232
319
|
if (event.defaultPrevented) {
|
|
233
320
|
return;
|
|
234
321
|
}
|
|
322
|
+
if (tg === null || tg === void 0 ? void 0 : tg.collapsed) {
|
|
323
|
+
tg.expand();
|
|
324
|
+
}
|
|
235
325
|
tab.element.scrollIntoView();
|
|
236
326
|
tab.panel.api.setActive();
|
|
237
327
|
});
|
|
@@ -239,7 +329,9 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
239
329
|
el.appendChild(wrapper);
|
|
240
330
|
}
|
|
241
331
|
const relativeParent = findRelativeZIndexParent(root);
|
|
242
|
-
this.accessor
|
|
332
|
+
this.accessor
|
|
333
|
+
.getPopupServiceForGroup(this.group)
|
|
334
|
+
.openPopover(el, {
|
|
243
335
|
x: event.clientX,
|
|
244
336
|
y: event.clientY,
|
|
245
337
|
zIndex: (relativeParent === null || relativeParent === void 0 ? void 0 : relativeParent.style.zIndex)
|
|
@@ -252,4 +344,10 @@ export class TabsContainer extends CompositeDisposable {
|
|
|
252
344
|
this.tabs.updateDragAndDropState();
|
|
253
345
|
this.voidContainer.updateDragAndDropState();
|
|
254
346
|
}
|
|
347
|
+
updateTabGroups() {
|
|
348
|
+
this.tabs.updateTabGroups();
|
|
349
|
+
}
|
|
350
|
+
refreshTabGroupAccent() {
|
|
351
|
+
this.tabs.refreshTabGroupAccent();
|
|
352
|
+
}
|
|
255
353
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DockviewComponent } from './dockviewComponent';
|
|
2
|
+
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
3
|
+
import { IDockviewPanel } from './dockviewPanel';
|
|
4
|
+
import { ITabGroup } from './tabGroup';
|
|
5
|
+
export declare class ContextMenuController {
|
|
6
|
+
private readonly accessor;
|
|
7
|
+
constructor(accessor: DockviewComponent);
|
|
8
|
+
show(panel: IDockviewPanel, group: DockviewGroupPanel, event: MouseEvent): void;
|
|
9
|
+
showForChip(tabGroup: ITabGroup, group: DockviewGroupPanel, event: MouseEvent): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { findRelativeZIndexParent } from '../dom';
|
|
2
|
+
function popoverZIndexFor(target) {
|
|
3
|
+
if (!(target instanceof HTMLElement)) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
// Floating overlays live in the shell as siblings of the popover anchor
|
|
7
|
+
// and the AriaLevelTracker sets their inline z-index. Without this, a
|
|
8
|
+
// popover opened from inside a floating group would render behind it
|
|
9
|
+
// because they share the shell stacking context.
|
|
10
|
+
const relativeParent = findRelativeZIndexParent(target);
|
|
11
|
+
return (relativeParent === null || relativeParent === void 0 ? void 0 : relativeParent.style.zIndex)
|
|
12
|
+
? `calc(${relativeParent.style.zIndex} * 2)`
|
|
13
|
+
: undefined;
|
|
14
|
+
}
|
|
15
|
+
let _nextId = 0;
|
|
16
|
+
const nextContextMenuItemId = () => `dv-ctx-menu-item-${_nextId++}`;
|
|
17
|
+
function isItemConfig(item) {
|
|
18
|
+
return typeof item === 'object';
|
|
19
|
+
}
|
|
20
|
+
function buildItem(label, close, action, disabled) {
|
|
21
|
+
const el = document.createElement('div');
|
|
22
|
+
el.className = 'dv-context-menu-item';
|
|
23
|
+
el.setAttribute('role', 'menuitem');
|
|
24
|
+
if (disabled) {
|
|
25
|
+
el.classList.add('dv-context-menu-item--disabled');
|
|
26
|
+
el.setAttribute('aria-disabled', 'true');
|
|
27
|
+
}
|
|
28
|
+
el.textContent = label;
|
|
29
|
+
if (!disabled) {
|
|
30
|
+
el.addEventListener('click', () => {
|
|
31
|
+
action();
|
|
32
|
+
close();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return el;
|
|
36
|
+
}
|
|
37
|
+
function buildSeparator() {
|
|
38
|
+
const el = document.createElement('div');
|
|
39
|
+
el.className = 'dv-context-menu-separator';
|
|
40
|
+
el.setAttribute('role', 'separator');
|
|
41
|
+
return el;
|
|
42
|
+
}
|
|
43
|
+
function buildRenameInput(tabGroup) {
|
|
44
|
+
const wrapper = document.createElement('div');
|
|
45
|
+
wrapper.className = 'dv-context-menu-rename';
|
|
46
|
+
const input = document.createElement('input');
|
|
47
|
+
input.className = 'dv-context-menu-rename-input';
|
|
48
|
+
input.type = 'text';
|
|
49
|
+
input.placeholder = 'Name This Group';
|
|
50
|
+
input.value = tabGroup.label;
|
|
51
|
+
input.addEventListener('input', () => {
|
|
52
|
+
tabGroup.setLabel(input.value);
|
|
53
|
+
});
|
|
54
|
+
input.addEventListener('keydown', (e) => {
|
|
55
|
+
if (e.key !== 'Escape' && e.key !== 'Enter') {
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
input.addEventListener('click', (e) => {
|
|
60
|
+
e.stopPropagation();
|
|
61
|
+
});
|
|
62
|
+
wrapper.appendChild(input);
|
|
63
|
+
requestAnimationFrame(() => {
|
|
64
|
+
input.focus();
|
|
65
|
+
input.select();
|
|
66
|
+
});
|
|
67
|
+
return wrapper;
|
|
68
|
+
}
|
|
69
|
+
function buildColorPicker(tabGroup, palette) {
|
|
70
|
+
const wrapper = document.createElement('div');
|
|
71
|
+
wrapper.className = 'dv-context-menu-color-picker';
|
|
72
|
+
if (!palette.enabled) {
|
|
73
|
+
// Opt-out: render no swatches. Returning a wrapper rather than null
|
|
74
|
+
// keeps the call site simple; the wrapper is empty and visually inert.
|
|
75
|
+
return wrapper;
|
|
76
|
+
}
|
|
77
|
+
for (const entry of palette.entries()) {
|
|
78
|
+
const swatch = document.createElement('div');
|
|
79
|
+
swatch.className = 'dv-context-menu-color-swatch';
|
|
80
|
+
// Use a CSS custom property rather than setting `backgroundColor`
|
|
81
|
+
// directly: the IDL setter validates the value against a color
|
|
82
|
+
// grammar and rejects `var(...)` references in some environments
|
|
83
|
+
// (notably jsdom; some browsers have historically had similar
|
|
84
|
+
// quirks). The matching SCSS rule reads the var at use time.
|
|
85
|
+
swatch.style.setProperty('--dv-tab-group-color', entry.value);
|
|
86
|
+
if (entry.label) {
|
|
87
|
+
swatch.title = entry.label;
|
|
88
|
+
}
|
|
89
|
+
if (tabGroup.color === entry.id) {
|
|
90
|
+
swatch.classList.add('dv-context-menu-color-swatch--selected');
|
|
91
|
+
}
|
|
92
|
+
swatch.addEventListener('click', () => {
|
|
93
|
+
tabGroup.setColor(entry.id);
|
|
94
|
+
});
|
|
95
|
+
wrapper.appendChild(swatch);
|
|
96
|
+
}
|
|
97
|
+
return wrapper;
|
|
98
|
+
}
|
|
99
|
+
export class ContextMenuController {
|
|
100
|
+
constructor(accessor) {
|
|
101
|
+
this.accessor = accessor;
|
|
102
|
+
}
|
|
103
|
+
show(panel, group, event) {
|
|
104
|
+
var _a, _b;
|
|
105
|
+
if (!this.accessor.options.getTabContextMenuItems) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const items = this.accessor.options.getTabContextMenuItems({
|
|
109
|
+
panel,
|
|
110
|
+
group,
|
|
111
|
+
api: this.accessor.api,
|
|
112
|
+
event,
|
|
113
|
+
});
|
|
114
|
+
if (items.length === 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
const popupService = this.accessor.getPopupServiceForGroup(group);
|
|
119
|
+
const close = () => popupService.close();
|
|
120
|
+
const menuEl = document.createElement('div');
|
|
121
|
+
menuEl.className = 'dv-context-menu';
|
|
122
|
+
menuEl.setAttribute('role', 'menu');
|
|
123
|
+
for (const item of items) {
|
|
124
|
+
if (item === 'separator') {
|
|
125
|
+
menuEl.appendChild(buildSeparator());
|
|
126
|
+
}
|
|
127
|
+
else if (item === 'close') {
|
|
128
|
+
menuEl.appendChild(buildItem('Close', close, () => panel.api.close()));
|
|
129
|
+
}
|
|
130
|
+
else if (item === 'closeOthers') {
|
|
131
|
+
menuEl.appendChild(buildItem('Close Others', close, () => {
|
|
132
|
+
group.panels
|
|
133
|
+
.filter((p) => p !== panel)
|
|
134
|
+
.forEach((p) => p.api.close());
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
else if (item === 'closeAll') {
|
|
138
|
+
menuEl.appendChild(buildItem('Close All', close, () => {
|
|
139
|
+
[...group.panels].forEach((p) => p.api.close());
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
else if (isItemConfig(item) && item.element) {
|
|
143
|
+
menuEl.appendChild(item.element);
|
|
144
|
+
}
|
|
145
|
+
else if (isItemConfig(item) && item.component) {
|
|
146
|
+
const renderer = (_b = (_a = this.accessor.options).createContextMenuItemComponent) === null || _b === void 0 ? void 0 : _b.call(_a, {
|
|
147
|
+
id: nextContextMenuItemId(),
|
|
148
|
+
component: item.component,
|
|
149
|
+
});
|
|
150
|
+
if (renderer) {
|
|
151
|
+
renderer.init({
|
|
152
|
+
panel,
|
|
153
|
+
group,
|
|
154
|
+
api: this.accessor.api,
|
|
155
|
+
close,
|
|
156
|
+
componentProps: item.componentProps,
|
|
157
|
+
});
|
|
158
|
+
menuEl.appendChild(renderer.element);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (isItemConfig(item) && item.label) {
|
|
162
|
+
menuEl.appendChild(buildItem(item.label, close, () => { var _a; return (_a = item.action) === null || _a === void 0 ? void 0 : _a.call(item); }, item.disabled));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
popupService.openPopover(menuEl, {
|
|
166
|
+
x: event.clientX,
|
|
167
|
+
y: event.clientY,
|
|
168
|
+
zIndex: popoverZIndexFor(event.target),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
showForChip(tabGroup, group, event) {
|
|
172
|
+
if (!this.accessor.options.getTabGroupChipContextMenuItems) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const items = this.accessor.options.getTabGroupChipContextMenuItems({
|
|
176
|
+
tabGroup,
|
|
177
|
+
group,
|
|
178
|
+
api: this.accessor.api,
|
|
179
|
+
event,
|
|
180
|
+
});
|
|
181
|
+
if (items.length === 0) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
event.preventDefault();
|
|
185
|
+
const popupService = this.accessor.getPopupServiceForGroup(group);
|
|
186
|
+
const close = () => popupService.close();
|
|
187
|
+
const menuEl = document.createElement('div');
|
|
188
|
+
menuEl.className = 'dv-context-menu';
|
|
189
|
+
menuEl.setAttribute('role', 'menu');
|
|
190
|
+
for (const item of items) {
|
|
191
|
+
if (item === 'separator') {
|
|
192
|
+
menuEl.appendChild(buildSeparator());
|
|
193
|
+
}
|
|
194
|
+
else if (item === 'rename') {
|
|
195
|
+
menuEl.appendChild(buildRenameInput(tabGroup));
|
|
196
|
+
}
|
|
197
|
+
else if (item === 'colorPicker') {
|
|
198
|
+
menuEl.appendChild(buildColorPicker(tabGroup, this.accessor.tabGroupColorPalette));
|
|
199
|
+
}
|
|
200
|
+
else if (isItemConfig(item) && item.element) {
|
|
201
|
+
menuEl.appendChild(item.element);
|
|
202
|
+
}
|
|
203
|
+
else if (isItemConfig(item) && item.label) {
|
|
204
|
+
menuEl.appendChild(buildItem(item.label, close, () => { var _a; return (_a = item.action) === null || _a === void 0 ? void 0 : _a.call(item); }, item.disabled));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
popupService.openPopover(menuEl, {
|
|
208
|
+
x: event.clientX,
|
|
209
|
+
y: event.clientY,
|
|
210
|
+
zIndex: popoverZIndexFor(event.target),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -8,7 +8,7 @@ import { BaseGrid, IBaseGrid } from '../gridview/baseComponentGridview';
|
|
|
8
8
|
import { DockviewApi } from '../api/component.api';
|
|
9
9
|
import { Orientation } from '../splitview/splitview';
|
|
10
10
|
import { GroupOptions, GroupPanelViewState, DockviewDidDropEvent, DockviewWillDropEvent } from './dockviewGroupPanelModel';
|
|
11
|
-
import { DockviewWillShowOverlayLocationEvent } from './events';
|
|
11
|
+
import { DockviewWillShowOverlayLocationEvent, DockviewTabGroupChangeEvent, DockviewTabGroupCollapsedChangeEvent, DockviewTabGroupPanelChangeEvent } from './events';
|
|
12
12
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
13
13
|
import { Parameters } from '../panel/types';
|
|
14
14
|
import { DockviewFloatingGroupPanel } from './dockviewFloatingGroupPanel';
|
|
@@ -16,7 +16,11 @@ import { GroupDragEvent, TabDragEvent } from './components/titlebar/tabsContaine
|
|
|
16
16
|
import { AnchoredBox, AnchorPosition, Box } from '../types';
|
|
17
17
|
import { DockviewPanelRenderer, OverlayRenderContainer } from '../overlay/overlayRenderContainer';
|
|
18
18
|
import { PopupService } from './components/popupService';
|
|
19
|
+
import { ContextMenuController } from './contextMenu';
|
|
19
20
|
import { DropTargetAnchorContainer } from '../dnd/dropTargetAnchorContainer';
|
|
21
|
+
import { EdgeGroupPosition, EdgeGroupOptions, SerializedEdgeGroups } from './dockviewShell';
|
|
22
|
+
import { DockviewGroupPanelApi } from '../api/dockviewGroupPanelApi';
|
|
23
|
+
import { TabGroupColorPalette } from './tabGroupAccent';
|
|
20
24
|
export interface DockviewPopoutGroupOptions {
|
|
21
25
|
/**
|
|
22
26
|
* The position of the popout group
|
|
@@ -68,6 +72,7 @@ export interface SerializedDockview {
|
|
|
68
72
|
activeGroup?: string;
|
|
69
73
|
floatingGroups?: SerializedFloatingGroup[];
|
|
70
74
|
popoutGroups?: SerializedPopoutGroup[];
|
|
75
|
+
edgeGroups?: SerializedEdgeGroups;
|
|
71
76
|
}
|
|
72
77
|
export interface MovePanelEvent {
|
|
73
78
|
panel: IDockviewPanel;
|
|
@@ -87,6 +92,7 @@ type MoveGroupOrPanelOptions = {
|
|
|
87
92
|
from: {
|
|
88
93
|
groupId: string;
|
|
89
94
|
panelId?: string;
|
|
95
|
+
tabGroupId?: string;
|
|
90
96
|
};
|
|
91
97
|
to: {
|
|
92
98
|
group: DockviewGroupPanel;
|
|
@@ -103,7 +109,7 @@ export interface FloatingGroupOptions {
|
|
|
103
109
|
width?: number;
|
|
104
110
|
position?: AnchorPosition;
|
|
105
111
|
}
|
|
106
|
-
|
|
112
|
+
interface FloatingGroupOptionsInternal extends FloatingGroupOptions {
|
|
107
113
|
skipRemoveGroup?: boolean;
|
|
108
114
|
inDragMode?: boolean;
|
|
109
115
|
skipActiveGroup?: boolean;
|
|
@@ -145,7 +151,14 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|
|
145
151
|
readonly onDidPopoutGroupSizeChange: Event<PopoutGroupChangeSizeEvent>;
|
|
146
152
|
readonly onDidPopoutGroupPositionChange: Event<PopoutGroupChangePositionEvent>;
|
|
147
153
|
readonly onDidOpenPopoutWindowFail: Event<void>;
|
|
154
|
+
readonly onDidCreateTabGroup: Event<DockviewTabGroupChangeEvent>;
|
|
155
|
+
readonly onDidDestroyTabGroup: Event<DockviewTabGroupChangeEvent>;
|
|
156
|
+
readonly onDidAddPanelToTabGroup: Event<DockviewTabGroupPanelChangeEvent>;
|
|
157
|
+
readonly onDidRemovePanelFromTabGroup: Event<DockviewTabGroupPanelChangeEvent>;
|
|
158
|
+
readonly onDidTabGroupChange: Event<DockviewTabGroupChangeEvent>;
|
|
159
|
+
readonly onDidTabGroupCollapsedChange: Event<DockviewTabGroupCollapsedChangeEvent>;
|
|
148
160
|
readonly options: DockviewComponentOptions;
|
|
161
|
+
readonly tabGroupColorPalette: TabGroupColorPalette;
|
|
149
162
|
updateOptions(options: DockviewOptions): void;
|
|
150
163
|
moveGroupOrPanel(options: MoveGroupOrPanelOptions): void;
|
|
151
164
|
moveGroup(options: MoveGroupOptions): void;
|
|
@@ -179,16 +192,24 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|
|
179
192
|
fromJSON(data: any, options?: {
|
|
180
193
|
reuseExistingPanels: boolean;
|
|
181
194
|
}): void;
|
|
195
|
+
addEdgeGroup(position: EdgeGroupPosition, options: EdgeGroupOptions): DockviewGroupPanelApi;
|
|
196
|
+
getEdgeGroup(position: EdgeGroupPosition): DockviewGroupPanelApi | undefined;
|
|
197
|
+
setEdgeGroupVisible(position: EdgeGroupPosition, visible: boolean): void;
|
|
198
|
+
isEdgeGroupVisible(position: EdgeGroupPosition): boolean;
|
|
199
|
+
removeEdgeGroup(position: EdgeGroupPosition): void;
|
|
182
200
|
}
|
|
183
201
|
export declare class DockviewComponent extends BaseGrid<DockviewGroupPanel> implements IDockviewComponent {
|
|
184
202
|
private readonly nextGroupId;
|
|
185
203
|
private readonly _deserializer;
|
|
186
204
|
private readonly _api;
|
|
187
205
|
private _options;
|
|
206
|
+
private _tabGroupColorPalette;
|
|
188
207
|
private _watermark;
|
|
189
|
-
private
|
|
208
|
+
private _shellThemeClassnames;
|
|
190
209
|
readonly overlayRenderContainer: OverlayRenderContainer;
|
|
191
210
|
readonly popupService: PopupService;
|
|
211
|
+
private readonly _popoutPopupServices;
|
|
212
|
+
readonly contextMenuController: ContextMenuController;
|
|
192
213
|
readonly rootDropTargetContainer: DropTargetAnchorContainer;
|
|
193
214
|
private readonly _onWillDragPanel;
|
|
194
215
|
readonly onWillDragPanel: Event<TabDragEvent>;
|
|
@@ -218,8 +239,25 @@ export declare class DockviewComponent extends BaseGrid<DockviewGroupPanel> impl
|
|
|
218
239
|
readonly onDidActivePanelChange: Event<IDockviewPanel | undefined>;
|
|
219
240
|
private readonly _onDidMovePanel;
|
|
220
241
|
readonly onDidMovePanel: Event<MovePanelEvent>;
|
|
242
|
+
private readonly _onDidCreateTabGroup;
|
|
243
|
+
readonly onDidCreateTabGroup: Event<DockviewTabGroupChangeEvent>;
|
|
244
|
+
private readonly _onDidDestroyTabGroup;
|
|
245
|
+
readonly onDidDestroyTabGroup: Event<DockviewTabGroupChangeEvent>;
|
|
246
|
+
private readonly _onDidAddPanelToTabGroup;
|
|
247
|
+
readonly onDidAddPanelToTabGroup: Event<DockviewTabGroupPanelChangeEvent>;
|
|
248
|
+
private readonly _onDidRemovePanelFromTabGroup;
|
|
249
|
+
readonly onDidRemovePanelFromTabGroup: Event<DockviewTabGroupPanelChangeEvent>;
|
|
250
|
+
private readonly _onDidTabGroupChange;
|
|
251
|
+
readonly onDidTabGroupChange: Event<DockviewTabGroupChangeEvent>;
|
|
252
|
+
private readonly _onDidTabGroupCollapsedChange;
|
|
253
|
+
readonly onDidTabGroupCollapsedChange: Event<DockviewTabGroupChangeEvent>;
|
|
221
254
|
private readonly _onDidMaximizedGroupChange;
|
|
222
255
|
readonly onDidMaximizedGroupChange: Event<DockviewMaximizedGroupChanged>;
|
|
256
|
+
private _shellManager;
|
|
257
|
+
private _floatingOverlayHost;
|
|
258
|
+
private _inShellLayout;
|
|
259
|
+
private readonly _edgeGroups;
|
|
260
|
+
private readonly _edgeGroupDisposables;
|
|
223
261
|
private readonly _floatingGroups;
|
|
224
262
|
private readonly _popoutGroups;
|
|
225
263
|
private readonly _rootDropTarget;
|
|
@@ -236,6 +274,7 @@ export declare class DockviewComponent extends BaseGrid<DockviewGroupPanel> impl
|
|
|
236
274
|
get totalPanels(): number;
|
|
237
275
|
get panels(): IDockviewPanel[];
|
|
238
276
|
get options(): DockviewComponentOptions;
|
|
277
|
+
get tabGroupColorPalette(): TabGroupColorPalette;
|
|
239
278
|
get activePanel(): IDockviewPanel | undefined;
|
|
240
279
|
get renderer(): DockviewPanelRenderer;
|
|
241
280
|
get defaultHeaderPosition(): DockviewHeaderPosition;
|
|
@@ -248,11 +287,28 @@ export declare class DockviewComponent extends BaseGrid<DockviewGroupPanel> impl
|
|
|
248
287
|
get popoutRestorationPromise(): Promise<void>;
|
|
249
288
|
constructor(container: HTMLElement, options: DockviewComponentOptions);
|
|
250
289
|
setVisible(panel: DockviewGroupPanel, visible: boolean): void;
|
|
290
|
+
/**
|
|
291
|
+
* Returns the {@link PopupService} that should host popovers (context
|
|
292
|
+
* menus, tab overflow menus) for the given group. Popout groups have their
|
|
293
|
+
* own service rooted in their popout window so the popover renders there
|
|
294
|
+
* and dismisses on events from that window.
|
|
295
|
+
*/
|
|
296
|
+
getPopupServiceForGroup(group: DockviewGroupPanel): PopupService;
|
|
251
297
|
addPopoutGroup(itemToPopout: DockviewPanel | DockviewGroupPanel, options?: DockviewPopoutGroupOptions): Promise<boolean>;
|
|
252
298
|
addFloatingGroup(item: DockviewPanel | DockviewGroupPanel, options?: FloatingGroupOptionsInternal): void;
|
|
253
299
|
private orthogonalize;
|
|
254
300
|
updateOptions(options: Partial<DockviewComponentOptions>): void;
|
|
255
301
|
layout(width: number, height: number, forceResize?: boolean | undefined): void;
|
|
302
|
+
private _syncFloatingOverlayHost;
|
|
303
|
+
private _layoutFromShell;
|
|
304
|
+
protected forceRelayout(): void;
|
|
305
|
+
addEdgeGroup(position: EdgeGroupPosition, options: EdgeGroupOptions): DockviewGroupPanelApi;
|
|
306
|
+
getEdgeGroup(position: EdgeGroupPosition): DockviewGroupPanelApi | undefined;
|
|
307
|
+
setEdgeGroupVisible(position: EdgeGroupPosition, visible: boolean): void;
|
|
308
|
+
isEdgeGroupVisible(position: EdgeGroupPosition): boolean;
|
|
309
|
+
removeEdgeGroup(position: EdgeGroupPosition): void;
|
|
310
|
+
setEdgeGroupCollapsed(group: DockviewGroupPanel, collapsed: boolean): void;
|
|
311
|
+
isEdgeGroupCollapsed(group: DockviewGroupPanel): boolean;
|
|
256
312
|
private updateDragAndDropState;
|
|
257
313
|
focus(): void;
|
|
258
314
|
getGroupPanel(id: string): IDockviewPanel | undefined;
|
|
@@ -297,6 +353,7 @@ export declare class DockviewComponent extends BaseGrid<DockviewGroupPanel> impl
|
|
|
297
353
|
private debouncedUpdateAllPositions;
|
|
298
354
|
movingLock<T>(func: () => T): T;
|
|
299
355
|
moveGroupOrPanel(options: MoveGroupOrPanelOptions): void;
|
|
356
|
+
private moveTabGroupToGroup;
|
|
300
357
|
moveGroup(options: MoveGroupOptions): void;
|
|
301
358
|
doSetGroupActive(group: DockviewGroupPanel | undefined): void;
|
|
302
359
|
doSetGroupAndPanelActive(group: DockviewGroupPanel | undefined): void;
|