dockview-core 6.6.1 → 7.0.2
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 +8 -1
- package/dist/cjs/api/component.api.d.ts +42 -21
- package/dist/cjs/api/component.api.js +111 -20
- package/dist/cjs/api/dockviewGroupPanelApi.d.ts +23 -8
- package/dist/cjs/api/dockviewGroupPanelApi.js +23 -0
- package/dist/cjs/api/dockviewPanelApi.d.ts +4 -3
- package/dist/cjs/api/dockviewPanelApi.js +8 -0
- package/dist/cjs/dnd/droptarget.d.ts +8 -0
- package/dist/cjs/dnd/droptarget.js +28 -0
- package/dist/cjs/dockview/accessibilityMessages.d.ts +32 -0
- package/dist/cjs/dockview/accessibilityMessages.js +51 -0
- package/dist/cjs/dockview/allModules.d.ts +8 -0
- package/dist/cjs/dockview/allModules.js +25 -0
- package/dist/cjs/dockview/components/panel/content.d.ts +2 -0
- package/dist/cjs/dockview/components/panel/content.js +35 -4
- package/dist/cjs/dockview/components/tab/tab.js +33 -5
- package/dist/cjs/dockview/components/titlebar/floatingTitleBar.d.ts +35 -0
- package/dist/cjs/dockview/components/titlebar/floatingTitleBar.js +95 -0
- package/dist/cjs/dockview/components/titlebar/groupDragSource.d.ts +52 -0
- package/dist/cjs/dockview/components/titlebar/groupDragSource.js +218 -0
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
- package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +31 -24
- package/dist/cjs/dockview/components/titlebar/tabGroups.js +1 -0
- package/dist/cjs/dockview/components/titlebar/tabs.d.ts +12 -0
- package/dist/cjs/dockview/components/titlebar/tabs.js +105 -2
- package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +4 -0
- package/dist/cjs/dockview/components/titlebar/tabsContainer.js +13 -3
- package/dist/cjs/dockview/components/titlebar/voidContainer.d.ts +1 -4
- package/dist/cjs/dockview/components/titlebar/voidContainer.js +31 -155
- package/dist/cjs/dockview/dockviewComponent.d.ts +299 -44
- package/dist/cjs/dockview/dockviewComponent.js +1787 -1041
- package/dist/cjs/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
- package/dist/cjs/dockview/dockviewFloatingGroupPanel.js +39 -3
- package/dist/cjs/dockview/dockviewGroupPanel.d.ts +0 -1
- package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +36 -14
- package/dist/cjs/dockview/dockviewGroupPanelModel.js +133 -101
- package/dist/cjs/dockview/dockviewPanel.d.ts +2 -2
- package/dist/cjs/dockview/edgeGroupService.d.ts +38 -0
- package/dist/cjs/dockview/edgeGroupService.js +128 -0
- package/dist/cjs/dockview/floatingGroupService.d.ts +37 -0
- package/dist/cjs/dockview/floatingGroupService.js +231 -0
- package/dist/cjs/dockview/headerActionsService.d.ts +32 -0
- package/dist/cjs/dockview/headerActionsService.js +149 -0
- package/dist/cjs/dockview/liveRegionService.d.ts +53 -0
- package/dist/cjs/dockview/liveRegionService.js +185 -0
- package/dist/cjs/dockview/moduleContracts.d.ts +119 -0
- package/dist/cjs/dockview/moduleContracts.js +2 -0
- package/dist/cjs/dockview/modules.d.ts +110 -0
- package/dist/cjs/dockview/modules.js +304 -0
- package/dist/cjs/dockview/options.d.ts +159 -6
- package/dist/cjs/dockview/options.js +8 -1
- package/dist/cjs/dockview/popoutWindowService.d.ts +95 -0
- package/dist/cjs/dockview/popoutWindowService.js +261 -0
- package/dist/cjs/dockview/rootDropTargetService.d.ts +35 -0
- package/dist/cjs/dockview/rootDropTargetService.js +87 -0
- package/dist/cjs/dockview/watermarkService.d.ts +30 -0
- package/dist/cjs/dockview/watermarkService.js +61 -0
- package/dist/cjs/gridview/baseComponentGridview.d.ts +1 -1
- package/dist/cjs/gridview/baseComponentGridview.js +3 -2
- package/dist/cjs/gridview/gridviewComponent.d.ts +3 -3
- package/dist/cjs/gridview/gridviewPanel.d.ts +1 -1
- package/dist/cjs/index.d.ts +11 -4
- package/dist/cjs/index.js +14 -1
- package/dist/cjs/overlay/overlay.d.ts +43 -1
- package/dist/cjs/overlay/overlay.js +57 -8
- package/dist/cjs/paneview/draggablePaneviewPanel.d.ts +2 -2
- package/dist/cjs/paneview/draggablePaneviewPanel.js +4 -4
- package/dist/cjs/paneview/paneviewComponent.d.ts +3 -3
- package/dist/cjs/paneview/paneviewComponent.js +5 -5
- package/dist/dockview-core.js +3201 -1280
- 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 +3200 -1279
- package/dist/esm/api/component.api.d.ts +42 -21
- package/dist/esm/api/component.api.js +63 -18
- package/dist/esm/api/dockviewGroupPanelApi.d.ts +23 -8
- package/dist/esm/api/dockviewGroupPanelApi.js +19 -0
- package/dist/esm/api/dockviewPanelApi.d.ts +4 -3
- package/dist/esm/api/dockviewPanelApi.js +7 -0
- package/dist/esm/dnd/droptarget.d.ts +8 -0
- package/dist/esm/dnd/droptarget.js +28 -0
- package/dist/esm/dockview/accessibilityMessages.d.ts +32 -0
- package/dist/esm/dockview/accessibilityMessages.js +30 -0
- package/dist/esm/dockview/allModules.d.ts +8 -0
- package/dist/esm/dockview/allModules.js +22 -0
- package/dist/esm/dockview/components/panel/content.d.ts +2 -0
- package/dist/esm/dockview/components/panel/content.js +36 -5
- package/dist/esm/dockview/components/tab/tab.js +33 -5
- package/dist/esm/dockview/components/titlebar/floatingTitleBar.d.ts +35 -0
- package/dist/esm/dockview/components/titlebar/floatingTitleBar.js +65 -0
- package/dist/esm/dockview/components/titlebar/groupDragSource.d.ts +52 -0
- package/dist/esm/dockview/components/titlebar/groupDragSource.js +178 -0
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
- package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +31 -24
- package/dist/esm/dockview/components/titlebar/tabGroups.js +1 -0
- package/dist/esm/dockview/components/titlebar/tabs.d.ts +12 -0
- package/dist/esm/dockview/components/titlebar/tabs.js +102 -2
- package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +4 -0
- package/dist/esm/dockview/components/titlebar/tabsContainer.js +8 -2
- package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +1 -4
- package/dist/esm/dockview/components/titlebar/voidContainer.js +33 -145
- package/dist/esm/dockview/dockviewComponent.d.ts +299 -44
- package/dist/esm/dockview/dockviewComponent.js +1420 -743
- package/dist/esm/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
- package/dist/esm/dockview/dockviewFloatingGroupPanel.js +35 -3
- package/dist/esm/dockview/dockviewGroupPanel.d.ts +0 -1
- package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +36 -14
- package/dist/esm/dockview/dockviewGroupPanelModel.js +109 -93
- package/dist/esm/dockview/dockviewPanel.d.ts +2 -2
- package/dist/esm/dockview/edgeGroupService.d.ts +38 -0
- package/dist/esm/dockview/edgeGroupService.js +63 -0
- package/dist/esm/dockview/floatingGroupService.d.ts +37 -0
- package/dist/esm/dockview/floatingGroupService.js +150 -0
- package/dist/esm/dockview/headerActionsService.d.ts +32 -0
- package/dist/esm/dockview/headerActionsService.js +86 -0
- package/dist/esm/dockview/liveRegionService.d.ts +53 -0
- package/dist/esm/dockview/liveRegionService.js +159 -0
- package/dist/esm/dockview/moduleContracts.d.ts +119 -0
- package/dist/esm/dockview/moduleContracts.js +1 -0
- package/dist/esm/dockview/modules.d.ts +110 -0
- package/dist/esm/dockview/modules.js +170 -0
- package/dist/esm/dockview/options.d.ts +159 -6
- package/dist/esm/dockview/options.js +8 -1
- package/dist/esm/dockview/popoutWindowService.d.ts +95 -0
- package/dist/esm/dockview/popoutWindowService.js +175 -0
- package/dist/esm/dockview/rootDropTargetService.d.ts +35 -0
- package/dist/esm/dockview/rootDropTargetService.js +82 -0
- package/dist/esm/dockview/watermarkService.d.ts +30 -0
- package/dist/esm/dockview/watermarkService.js +56 -0
- package/dist/esm/gridview/baseComponentGridview.d.ts +1 -1
- package/dist/esm/gridview/baseComponentGridview.js +2 -2
- package/dist/esm/gridview/gridviewComponent.d.ts +3 -3
- package/dist/esm/gridview/gridviewPanel.d.ts +1 -1
- package/dist/esm/index.d.ts +11 -4
- package/dist/esm/index.js +4 -0
- package/dist/esm/overlay/overlay.d.ts +43 -1
- package/dist/esm/overlay/overlay.js +53 -8
- package/dist/esm/paneview/draggablePaneviewPanel.d.ts +2 -2
- package/dist/esm/paneview/draggablePaneviewPanel.js +4 -4
- package/dist/esm/paneview/paneviewComponent.d.ts +3 -3
- package/dist/esm/paneview/paneviewComponent.js +5 -5
- package/dist/package/main.cjs.js +3236 -1315
- package/dist/package/main.cjs.min.js +2 -2
- package/dist/package/main.esm.min.mjs +2 -2
- package/dist/package/main.esm.mjs +3191 -1281
- package/dist/styles/dockview.css +275 -13
- package/package.json +10 -1
- package/dist/cjs/dockview/contextMenu.d.ts +0 -10
- package/dist/cjs/dockview/contextMenu.js +0 -313
- package/dist/esm/dockview/contextMenu.d.ts +0 -10
- package/dist/esm/dockview/contextMenu.js +0 -228
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { defineModule } from './modules';
|
|
2
|
+
export class EdgeGroupService {
|
|
3
|
+
constructor() {
|
|
4
|
+
this._edgeGroups = new Map();
|
|
5
|
+
this._edgeGroupDisposables = new Map();
|
|
6
|
+
}
|
|
7
|
+
// No constructor needed — the host is currently unused. The
|
|
8
|
+
// IEdgeGroupServiceHost slot stays for symmetry with the other modules
|
|
9
|
+
// and to leave room for future host callbacks.
|
|
10
|
+
add(position, group, autoCollapseDisposable) {
|
|
11
|
+
this._edgeGroups.set(position, group);
|
|
12
|
+
this._edgeGroupDisposables.set(position, autoCollapseDisposable);
|
|
13
|
+
}
|
|
14
|
+
remove(position) {
|
|
15
|
+
var _a;
|
|
16
|
+
(_a = this._edgeGroupDisposables.get(position)) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
17
|
+
this._edgeGroupDisposables.delete(position);
|
|
18
|
+
this._edgeGroups.delete(position);
|
|
19
|
+
}
|
|
20
|
+
get(position) {
|
|
21
|
+
return this._edgeGroups.get(position);
|
|
22
|
+
}
|
|
23
|
+
has(position) {
|
|
24
|
+
return this._edgeGroups.has(position);
|
|
25
|
+
}
|
|
26
|
+
hasAny() {
|
|
27
|
+
return this._edgeGroups.size > 0;
|
|
28
|
+
}
|
|
29
|
+
entries() {
|
|
30
|
+
return this._edgeGroups.entries();
|
|
31
|
+
}
|
|
32
|
+
includes(group) {
|
|
33
|
+
for (const edgeGroup of this._edgeGroups.values()) {
|
|
34
|
+
if (edgeGroup === group) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
findPositionOf(group) {
|
|
41
|
+
for (const [position, edgeGroup] of this._edgeGroups) {
|
|
42
|
+
if (edgeGroup === group) {
|
|
43
|
+
return position;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
disposeAll() {
|
|
49
|
+
for (const disposable of this._edgeGroupDisposables.values()) {
|
|
50
|
+
disposable.dispose();
|
|
51
|
+
}
|
|
52
|
+
this._edgeGroupDisposables.clear();
|
|
53
|
+
this._edgeGroups.clear();
|
|
54
|
+
}
|
|
55
|
+
dispose() {
|
|
56
|
+
this.disposeAll();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export const EdgeGroupModule = defineModule({
|
|
60
|
+
name: 'EdgeGroup',
|
|
61
|
+
serviceKey: 'edgeGroupService',
|
|
62
|
+
create: () => new EdgeGroupService(),
|
|
63
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { IDisposable } from '../lifecycle';
|
|
2
|
+
import { Gridview } from '../gridview/gridview';
|
|
3
|
+
import { Overlay } from '../overlay/overlay';
|
|
4
|
+
import { DockviewFloatingGroupPanel } from './dockviewFloatingGroupPanel';
|
|
5
|
+
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
6
|
+
import { DockviewOptions } from './options';
|
|
7
|
+
import { SerializedFloatingGroup } from './dockviewComponent';
|
|
8
|
+
/**
|
|
9
|
+
* Narrow callback surface the FloatingGroupService needs from its host
|
|
10
|
+
* component. Keeps the service decoupled from DockviewComponent.
|
|
11
|
+
*/
|
|
12
|
+
export interface IFloatingGroupHost {
|
|
13
|
+
fireLayoutChange(): void;
|
|
14
|
+
}
|
|
15
|
+
export interface IFloatingGroupService extends IDisposable {
|
|
16
|
+
readonly floatingGroups: readonly DockviewFloatingGroupPanel[];
|
|
17
|
+
add(group: DockviewGroupPanel, overlay: Overlay, gridview: Gridview): DockviewFloatingGroupPanel;
|
|
18
|
+
findByGroup(group: DockviewGroupPanel): DockviewFloatingGroupPanel | undefined;
|
|
19
|
+
serialize(): SerializedFloatingGroup[];
|
|
20
|
+
constrainBounds(): void;
|
|
21
|
+
updateBounds(options: Partial<DockviewOptions>): void;
|
|
22
|
+
disposeAll(): void;
|
|
23
|
+
}
|
|
24
|
+
export declare class FloatingGroupService implements IFloatingGroupService {
|
|
25
|
+
private readonly _host;
|
|
26
|
+
private readonly _floatingGroups;
|
|
27
|
+
get floatingGroups(): readonly DockviewFloatingGroupPanel[];
|
|
28
|
+
constructor(host: IFloatingGroupHost);
|
|
29
|
+
add(group: DockviewGroupPanel, overlay: Overlay, gridview: Gridview): DockviewFloatingGroupPanel;
|
|
30
|
+
findByGroup(group: DockviewGroupPanel): DockviewFloatingGroupPanel | undefined;
|
|
31
|
+
serialize(): SerializedFloatingGroup[];
|
|
32
|
+
constrainBounds(): void;
|
|
33
|
+
updateBounds(options: Partial<DockviewOptions>): void;
|
|
34
|
+
disposeAll(): void;
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
37
|
+
export declare const FloatingGroupModule: import("./modules").DockviewModule<IFloatingGroupHost>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { CompositeDisposable } from '../lifecycle';
|
|
2
|
+
import { remove } from '../array';
|
|
3
|
+
import { watchElementResize } from '../dom';
|
|
4
|
+
import { DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE } from '../constants';
|
|
5
|
+
import { DockviewFloatingGroupPanel } from './dockviewFloatingGroupPanel';
|
|
6
|
+
import { defineModule } from './modules';
|
|
7
|
+
export class FloatingGroupService {
|
|
8
|
+
get floatingGroups() {
|
|
9
|
+
return this._floatingGroups;
|
|
10
|
+
}
|
|
11
|
+
constructor(host) {
|
|
12
|
+
this._floatingGroups = [];
|
|
13
|
+
this._host = host;
|
|
14
|
+
}
|
|
15
|
+
add(group, overlay, gridview) {
|
|
16
|
+
const floatingGroupPanel = new DockviewFloatingGroupPanel(group, overlay, gridview);
|
|
17
|
+
const disposable = new CompositeDisposable(group.api.onDidActiveChange((event) => {
|
|
18
|
+
if (event.isActive) {
|
|
19
|
+
overlay.bringToFront();
|
|
20
|
+
}
|
|
21
|
+
}), (() => {
|
|
22
|
+
// The floating window's nested gridview fills the overlay
|
|
23
|
+
// beneath the (optional) title bar; size it from its own
|
|
24
|
+
// measured box so it follows the overlay as the user drags
|
|
25
|
+
// / resizes the window.
|
|
26
|
+
let lastWidth = -1;
|
|
27
|
+
let lastHeight = -1;
|
|
28
|
+
return watchElementResize(gridview.element, (entry) => {
|
|
29
|
+
const width = Math.round(entry.contentRect.width);
|
|
30
|
+
const height = Math.round(entry.contentRect.height);
|
|
31
|
+
if (width === lastWidth && height === lastHeight) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
lastWidth = width;
|
|
35
|
+
lastHeight = height;
|
|
36
|
+
gridview.layout(width, height);
|
|
37
|
+
});
|
|
38
|
+
})());
|
|
39
|
+
// Floating windows are non-modal dialogs (role set in Overlay). Give
|
|
40
|
+
// the dialog an accessible name from the representative group's active
|
|
41
|
+
// panel, refreshed as the active panel changes. An untitled panel
|
|
42
|
+
// leaves the dialog unnamed rather than hard-coding a label string.
|
|
43
|
+
const updateDialogLabel = () => {
|
|
44
|
+
var _a;
|
|
45
|
+
const title = (_a = group.activePanel) === null || _a === void 0 ? void 0 : _a.title;
|
|
46
|
+
if (title) {
|
|
47
|
+
overlay.element.setAttribute('aria-label', title);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
overlay.element.removeAttribute('aria-label');
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
updateDialogLabel();
|
|
54
|
+
floatingGroupPanel.addDisposables(group.api.onDidActivePanelChange(() => updateDialogLabel()), overlay.onDidChange(() => {
|
|
55
|
+
gridview.layout(gridview.width, gridview.height);
|
|
56
|
+
}), overlay.onDidChangeEnd(() => {
|
|
57
|
+
this._host.fireLayoutChange();
|
|
58
|
+
}), group.onDidChange((event) => {
|
|
59
|
+
// `event.height` is the group's requested *content* height.
|
|
60
|
+
// When a dedicated title bar is present the overlay's outer
|
|
61
|
+
// box is taller by the header, so add it back to preserve the
|
|
62
|
+
// requested content size.
|
|
63
|
+
overlay.setBounds({
|
|
64
|
+
height: typeof (event === null || event === void 0 ? void 0 : event.height) === 'number'
|
|
65
|
+
? event.height + overlay.headerHeight
|
|
66
|
+
: event === null || event === void 0 ? void 0 : event.height,
|
|
67
|
+
width: event === null || event === void 0 ? void 0 : event.width,
|
|
68
|
+
});
|
|
69
|
+
}), {
|
|
70
|
+
dispose: () => {
|
|
71
|
+
disposable.dispose();
|
|
72
|
+
remove(this._floatingGroups, floatingGroupPanel);
|
|
73
|
+
group.model.location = { type: 'grid' };
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
this._floatingGroups.push(floatingGroupPanel);
|
|
77
|
+
return floatingGroupPanel;
|
|
78
|
+
}
|
|
79
|
+
findByGroup(group) {
|
|
80
|
+
// A floating window may host several groups in a nested gridview, so
|
|
81
|
+
// match by membership (DOM containment) rather than only the anchor
|
|
82
|
+
// group. `floating.group === group` covers the brief window before the
|
|
83
|
+
// anchor's element is attached to the gridview.
|
|
84
|
+
return this._floatingGroups.find((floating) => floating.group === group ||
|
|
85
|
+
floating.gridview.element.contains(group.element));
|
|
86
|
+
}
|
|
87
|
+
serialize() {
|
|
88
|
+
return this._floatingGroups.map((floating) => {
|
|
89
|
+
const grid = floating.gridview.serialize();
|
|
90
|
+
const position = floating.overlay.toJSON();
|
|
91
|
+
const root = grid.root;
|
|
92
|
+
// A single-group window keeps the legacy `data` shape so layouts
|
|
93
|
+
// round-trip byte-stably and older readers keep working; only
|
|
94
|
+
// genuine multi-group windows emit the nested `grid` form.
|
|
95
|
+
if (root.type === 'branch' &&
|
|
96
|
+
root.data.length === 1 &&
|
|
97
|
+
root.data[0].type === 'leaf') {
|
|
98
|
+
return {
|
|
99
|
+
data: root.data[0].data,
|
|
100
|
+
position,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return { grid, position };
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
constrainBounds() {
|
|
107
|
+
for (const floating of this._floatingGroups) {
|
|
108
|
+
floating.overlay.setBounds();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
updateBounds(options) {
|
|
112
|
+
var _a, _b;
|
|
113
|
+
if (!('floatingGroupBounds' in options)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
for (const group of this._floatingGroups) {
|
|
117
|
+
switch (options.floatingGroupBounds) {
|
|
118
|
+
case 'boundedWithinViewport':
|
|
119
|
+
group.overlay.minimumInViewportHeight = undefined;
|
|
120
|
+
group.overlay.minimumInViewportWidth = undefined;
|
|
121
|
+
break;
|
|
122
|
+
case undefined:
|
|
123
|
+
group.overlay.minimumInViewportHeight =
|
|
124
|
+
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
|
|
125
|
+
group.overlay.minimumInViewportWidth =
|
|
126
|
+
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE;
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
group.overlay.minimumInViewportHeight =
|
|
130
|
+
(_a = options.floatingGroupBounds) === null || _a === void 0 ? void 0 : _a.minimumHeightWithinViewport;
|
|
131
|
+
group.overlay.minimumInViewportWidth =
|
|
132
|
+
(_b = options.floatingGroupBounds) === null || _b === void 0 ? void 0 : _b.minimumWidthWithinViewport;
|
|
133
|
+
}
|
|
134
|
+
group.overlay.setBounds();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
disposeAll() {
|
|
138
|
+
for (const floating of [...this._floatingGroups]) {
|
|
139
|
+
floating.dispose();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
dispose() {
|
|
143
|
+
this.disposeAll();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export const FloatingGroupModule = defineModule({
|
|
147
|
+
name: 'FloatingGroup',
|
|
148
|
+
serviceKey: 'floatingGroupService',
|
|
149
|
+
create: (host) => new FloatingGroupService(host),
|
|
150
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { IDisposable } from '../lifecycle';
|
|
2
|
+
import { Event } from '../events';
|
|
3
|
+
import { DockviewComponentOptions } from './options';
|
|
4
|
+
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
5
|
+
import { DockviewApi } from '../api/component.api';
|
|
6
|
+
export interface IHeaderActionsHost {
|
|
7
|
+
readonly api: DockviewApi;
|
|
8
|
+
readonly options: DockviewComponentOptions;
|
|
9
|
+
readonly groups: DockviewGroupPanel[];
|
|
10
|
+
readonly onDidAddGroup: Event<DockviewGroupPanel>;
|
|
11
|
+
readonly onDidRemoveGroup: Event<DockviewGroupPanel>;
|
|
12
|
+
}
|
|
13
|
+
export interface IHeaderActionsService extends IDisposable {
|
|
14
|
+
/** Re-mount the three header action slots on a single group. */
|
|
15
|
+
refresh(group: DockviewGroupPanel): void;
|
|
16
|
+
/** Re-mount on every group; used when one of the three options changes. */
|
|
17
|
+
refreshAll(): void;
|
|
18
|
+
/** Tear down per-group renderer state. */
|
|
19
|
+
disposeGroup(group: DockviewGroupPanel): void;
|
|
20
|
+
}
|
|
21
|
+
export declare class HeaderActionsService implements IHeaderActionsService {
|
|
22
|
+
private readonly _host;
|
|
23
|
+
private readonly _perGroup;
|
|
24
|
+
constructor(host: IHeaderActionsHost);
|
|
25
|
+
refresh(group: DockviewGroupPanel): void;
|
|
26
|
+
refreshAll(): void;
|
|
27
|
+
disposeGroup(group: DockviewGroupPanel): void;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
private _ensureState;
|
|
30
|
+
private _refreshSlot;
|
|
31
|
+
}
|
|
32
|
+
export declare const HeaderActionsModule: import("./modules").DockviewModule<IHeaderActionsHost>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { CompositeDisposable, MutableDisposable, } from '../lifecycle';
|
|
2
|
+
import { defineModule } from './modules';
|
|
3
|
+
const SLOT_OPTION_KEY = {
|
|
4
|
+
left: 'createLeftHeaderActionComponent',
|
|
5
|
+
right: 'createRightHeaderActionComponent',
|
|
6
|
+
prefix: 'createPrefixHeaderActionComponent',
|
|
7
|
+
};
|
|
8
|
+
export class HeaderActionsService {
|
|
9
|
+
constructor(host) {
|
|
10
|
+
this._perGroup = new Map();
|
|
11
|
+
this._host = host;
|
|
12
|
+
}
|
|
13
|
+
refresh(group) {
|
|
14
|
+
// The headerPosition setter on DockviewGroupPanelModel fires inside
|
|
15
|
+
// the model's constructor — before the parent DockviewGroupPanel has
|
|
16
|
+
// assigned its `_model` field, and in tests where the parent panel
|
|
17
|
+
// may be null. Skip; DockviewGroupPanel.initialize() will refresh
|
|
18
|
+
// once construction completes for real groups.
|
|
19
|
+
if (!(group === null || group === void 0 ? void 0 : group.model)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const state = this._ensureState(group);
|
|
23
|
+
this._refreshSlot('left', group, state.left);
|
|
24
|
+
this._refreshSlot('right', group, state.right);
|
|
25
|
+
this._refreshSlot('prefix', group, state.prefix);
|
|
26
|
+
}
|
|
27
|
+
refreshAll() {
|
|
28
|
+
for (const group of this._host.groups) {
|
|
29
|
+
this.refresh(group);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
disposeGroup(group) {
|
|
33
|
+
const state = this._perGroup.get(group);
|
|
34
|
+
if (!state) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
state.left.dispose();
|
|
38
|
+
state.right.dispose();
|
|
39
|
+
state.prefix.dispose();
|
|
40
|
+
this._perGroup.delete(group);
|
|
41
|
+
}
|
|
42
|
+
dispose() {
|
|
43
|
+
for (const group of [...this._perGroup.keys()]) {
|
|
44
|
+
this.disposeGroup(group);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
_ensureState(group) {
|
|
48
|
+
let state = this._perGroup.get(group);
|
|
49
|
+
if (!state) {
|
|
50
|
+
state = {
|
|
51
|
+
left: new MutableDisposable(),
|
|
52
|
+
right: new MutableDisposable(),
|
|
53
|
+
prefix: new MutableDisposable(),
|
|
54
|
+
};
|
|
55
|
+
this._perGroup.set(group, state);
|
|
56
|
+
}
|
|
57
|
+
return state;
|
|
58
|
+
}
|
|
59
|
+
_refreshSlot(slot, group, disposable) {
|
|
60
|
+
const factory = this._host.options[SLOT_OPTION_KEY[slot]];
|
|
61
|
+
if (factory) {
|
|
62
|
+
const renderer = factory(group);
|
|
63
|
+
disposable.value = renderer;
|
|
64
|
+
renderer.init({
|
|
65
|
+
containerApi: this._host.api,
|
|
66
|
+
api: group.api,
|
|
67
|
+
group,
|
|
68
|
+
});
|
|
69
|
+
group.model.attachHeaderAction(slot, renderer.element);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
disposable.dispose();
|
|
73
|
+
group.model.attachHeaderAction(slot, undefined);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export const HeaderActionsModule = defineModule({
|
|
78
|
+
name: 'HeaderActions',
|
|
79
|
+
serviceKey: 'headerActionsService',
|
|
80
|
+
create: (host) => new HeaderActionsService(host),
|
|
81
|
+
init: (host, service) => {
|
|
82
|
+
return new CompositeDisposable(host.onDidRemoveGroup((group) => {
|
|
83
|
+
service.disposeGroup(group);
|
|
84
|
+
}));
|
|
85
|
+
},
|
|
86
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { CompositeDisposable, IDisposable } from '../lifecycle';
|
|
2
|
+
import { Event } from '../events';
|
|
3
|
+
import { IDockviewPanel } from './dockviewPanel';
|
|
4
|
+
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
|
5
|
+
import { DockviewLayoutMutationEvent, DockviewMaximizedGroupChangeEvent } from './dockviewComponent';
|
|
6
|
+
import { DockviewComponentOptions } from './options';
|
|
7
|
+
/**
|
|
8
|
+
* The narrow surface the {@link LiveRegionService} needs from the host
|
|
9
|
+
* (the `DockviewComponent`) — somewhere to mount the region and the layout
|
|
10
|
+
* events to narrate. `onWill/onDidMutateLayout` are used to suppress the
|
|
11
|
+
* bulk-load / clear burst (one transaction, not N panel announcements).
|
|
12
|
+
*/
|
|
13
|
+
export interface ILiveRegionHost {
|
|
14
|
+
readonly element: HTMLElement;
|
|
15
|
+
readonly options: DockviewComponentOptions;
|
|
16
|
+
readonly onDidAddPanel: Event<IDockviewPanel>;
|
|
17
|
+
readonly onDidRemovePanel: Event<IDockviewPanel>;
|
|
18
|
+
readonly onWillMutateLayout: Event<DockviewLayoutMutationEvent>;
|
|
19
|
+
readonly onDidMutateLayout: Event<DockviewLayoutMutationEvent>;
|
|
20
|
+
readonly onDidMaximizedGroupChange: Event<DockviewMaximizedGroupChangeEvent>;
|
|
21
|
+
readonly onDidAddGroup: Event<DockviewGroupPanel>;
|
|
22
|
+
readonly onDidRemoveGroup: Event<DockviewGroupPanel>;
|
|
23
|
+
}
|
|
24
|
+
export interface ILiveRegionService extends IDisposable {
|
|
25
|
+
/**
|
|
26
|
+
* Announce a message to assistive technology via the live region. The
|
|
27
|
+
* shared sink — the accessibility module writes keyboard-docking
|
|
28
|
+
* narration here too, so all announcements use one region.
|
|
29
|
+
*/
|
|
30
|
+
announce(message: string, politeness?: 'polite' | 'assertive'): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Narrates layout state changes to screen readers via visually-hidden
|
|
34
|
+
* `aria-live` regions. Free / core (WCAG 4.1.3). Announces panel open/close +
|
|
35
|
+
* the shared `announce()` sink (the accessibility module narrates docking here too).
|
|
36
|
+
* Two regions: a **polite** one for routine status and an **assertive** one
|
|
37
|
+
* for errors/cancellations. The bulk load/clear burst is suppressed via the
|
|
38
|
+
* mutation-transaction events, and an app can take over delivery entirely with
|
|
39
|
+
* the `announcer` option.
|
|
40
|
+
*/
|
|
41
|
+
export declare class LiveRegionService extends CompositeDisposable implements ILiveRegionService {
|
|
42
|
+
private readonly _host;
|
|
43
|
+
private readonly _polite;
|
|
44
|
+
private readonly _assertive;
|
|
45
|
+
private _suppressDepth;
|
|
46
|
+
private readonly _locationSubs;
|
|
47
|
+
constructor(host: ILiveRegionHost);
|
|
48
|
+
private _trackLocation;
|
|
49
|
+
announce(message: string, politeness?: 'polite' | 'assertive'): void;
|
|
50
|
+
private _announce;
|
|
51
|
+
private _defaultMessage;
|
|
52
|
+
}
|
|
53
|
+
export declare const LiveRegionModule: import("./modules").DockviewModule<ILiveRegionHost>;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { CompositeDisposable } from '../lifecycle';
|
|
2
|
+
import { resolveMessages } from './accessibilityMessages';
|
|
3
|
+
import { defineModule } from './modules';
|
|
4
|
+
/** Bulk transactions whose per-panel events should not each be announced. */
|
|
5
|
+
const isBulk = (kind) => kind === 'load' || kind === 'clear';
|
|
6
|
+
function createLiveRegion(politeness) {
|
|
7
|
+
const el = document.createElement('div');
|
|
8
|
+
el.className =
|
|
9
|
+
politeness === 'assertive'
|
|
10
|
+
? 'dv-live-region-assertive'
|
|
11
|
+
: 'dv-live-region';
|
|
12
|
+
// assertive interrupts the SR (errors / cancellations); polite waits for a
|
|
13
|
+
// pause (routine status). `alert` implies assertive, `status` implies polite.
|
|
14
|
+
el.setAttribute('role', politeness === 'assertive' ? 'alert' : 'status');
|
|
15
|
+
el.setAttribute('aria-live', politeness);
|
|
16
|
+
el.setAttribute('aria-atomic', 'true');
|
|
17
|
+
// Visually hidden but kept in the accessibility tree (never display:none /
|
|
18
|
+
// visibility:hidden, which would drop it from AT). Standard clip pattern.
|
|
19
|
+
Object.assign(el.style, {
|
|
20
|
+
position: 'absolute',
|
|
21
|
+
width: '1px',
|
|
22
|
+
height: '1px',
|
|
23
|
+
margin: '-1px',
|
|
24
|
+
padding: '0',
|
|
25
|
+
overflow: 'hidden',
|
|
26
|
+
clip: 'rect(0 0 0 0)',
|
|
27
|
+
clipPath: 'inset(50%)',
|
|
28
|
+
whiteSpace: 'nowrap',
|
|
29
|
+
border: '0',
|
|
30
|
+
});
|
|
31
|
+
return el;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Narrates layout state changes to screen readers via visually-hidden
|
|
35
|
+
* `aria-live` regions. Free / core (WCAG 4.1.3). Announces panel open/close +
|
|
36
|
+
* the shared `announce()` sink (the accessibility module narrates docking here too).
|
|
37
|
+
* Two regions: a **polite** one for routine status and an **assertive** one
|
|
38
|
+
* for errors/cancellations. The bulk load/clear burst is suppressed via the
|
|
39
|
+
* mutation-transaction events, and an app can take over delivery entirely with
|
|
40
|
+
* the `announcer` option.
|
|
41
|
+
*/
|
|
42
|
+
export class LiveRegionService extends CompositeDisposable {
|
|
43
|
+
constructor(host) {
|
|
44
|
+
super();
|
|
45
|
+
this._suppressDepth = 0;
|
|
46
|
+
this._locationSubs = new Map();
|
|
47
|
+
this._host = host;
|
|
48
|
+
this._polite = createLiveRegion('polite');
|
|
49
|
+
this._assertive = createLiveRegion('assertive');
|
|
50
|
+
host.element.appendChild(this._polite);
|
|
51
|
+
host.element.appendChild(this._assertive);
|
|
52
|
+
this.addDisposables({ dispose: () => this._polite.remove() }, { dispose: () => this._assertive.remove() }, host.onDidAddPanel((panel) => this._announce(panel, 'open')), host.onDidRemovePanel((panel) => this._announce(panel, 'close')),
|
|
53
|
+
// Bracket bulk transactions so a fromJSON / clear doesn't announce
|
|
54
|
+
// every nested add/remove.
|
|
55
|
+
host.onWillMutateLayout((e) => {
|
|
56
|
+
if (isBulk(e.kind)) {
|
|
57
|
+
this._suppressDepth++;
|
|
58
|
+
}
|
|
59
|
+
}), host.onDidMutateLayout((e) => {
|
|
60
|
+
if (isBulk(e.kind)) {
|
|
61
|
+
this._suppressDepth = Math.max(0, this._suppressDepth - 1);
|
|
62
|
+
}
|
|
63
|
+
}), host.onDidMaximizedGroupChange((e) => {
|
|
64
|
+
const panel = e.group.activePanel;
|
|
65
|
+
if (panel) {
|
|
66
|
+
this._announce(panel, e.isMaximized ? 'maximize' : 'restore');
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
// Narrate a group floating / docking back / popping out. A group is
|
|
70
|
+
// born in the grid then transitions, so track each group's previous
|
|
71
|
+
// location and ignore the no-op initial `-> grid`.
|
|
72
|
+
host.onDidAddGroup((group) => this._trackLocation(group)), host.onDidRemoveGroup((group) => {
|
|
73
|
+
var _a;
|
|
74
|
+
(_a = this._locationSubs.get(group.id)) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
75
|
+
this._locationSubs.delete(group.id);
|
|
76
|
+
}), {
|
|
77
|
+
dispose: () => {
|
|
78
|
+
this._locationSubs.forEach((sub) => sub.dispose());
|
|
79
|
+
this._locationSubs.clear();
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
_trackLocation(group) {
|
|
84
|
+
let prev = group.api.location.type;
|
|
85
|
+
const sub = group.api.onDidLocationChange((e) => {
|
|
86
|
+
const next = e.location.type;
|
|
87
|
+
if (next === prev) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
prev = next;
|
|
91
|
+
const panel = group.activePanel;
|
|
92
|
+
if (!panel) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const kind = next === 'floating'
|
|
96
|
+
? 'float'
|
|
97
|
+
: next === 'popout'
|
|
98
|
+
? 'popout'
|
|
99
|
+
: 'dock';
|
|
100
|
+
this._announce(panel, kind);
|
|
101
|
+
});
|
|
102
|
+
this._locationSubs.set(group.id, sub);
|
|
103
|
+
}
|
|
104
|
+
announce(message, politeness = 'polite') {
|
|
105
|
+
// Opt-out (read live so `updateOptions({ announcements })` applies).
|
|
106
|
+
if (this._host.options.announcements === false ||
|
|
107
|
+
this._suppressDepth > 0 ||
|
|
108
|
+
!message) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Apps can route announcements into their own SR system instead of the
|
|
112
|
+
// built-in regions (e.g. a shared app-wide live region).
|
|
113
|
+
const announcer = this._host.options.announcer;
|
|
114
|
+
if (announcer) {
|
|
115
|
+
announcer({ message, politeness });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Clearing first forces SRs to re-announce an identical message.
|
|
119
|
+
const region = politeness === 'assertive' ? this._assertive : this._polite;
|
|
120
|
+
region.textContent = '';
|
|
121
|
+
region.textContent = message;
|
|
122
|
+
}
|
|
123
|
+
_announce(panel, kind) {
|
|
124
|
+
var _a, _b;
|
|
125
|
+
// The app may localise/override the message, suppress it (null / ''),
|
|
126
|
+
// or fall through to the default (undefined).
|
|
127
|
+
const custom = (_b = (_a = this._host.options).getAnnouncement) === null || _b === void 0 ? void 0 : _b.call(_a, { kind, panel });
|
|
128
|
+
if (custom === null || custom === '') {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.announce(custom !== null && custom !== void 0 ? custom : this._defaultMessage(panel, kind));
|
|
132
|
+
}
|
|
133
|
+
_defaultMessage(panel, kind) {
|
|
134
|
+
var _a;
|
|
135
|
+
const m = resolveMessages(this._host.options.messages);
|
|
136
|
+
const name = (_a = panel.title) !== null && _a !== void 0 ? _a : panel.id;
|
|
137
|
+
switch (kind) {
|
|
138
|
+
case 'open':
|
|
139
|
+
return m.panelOpened(name);
|
|
140
|
+
case 'close':
|
|
141
|
+
return m.panelClosed(name);
|
|
142
|
+
case 'maximize':
|
|
143
|
+
return m.groupMaximized(name);
|
|
144
|
+
case 'restore':
|
|
145
|
+
return m.groupRestored(name);
|
|
146
|
+
case 'float':
|
|
147
|
+
return m.groupFloated(name);
|
|
148
|
+
case 'dock':
|
|
149
|
+
return m.groupDocked(name);
|
|
150
|
+
case 'popout':
|
|
151
|
+
return m.groupPoppedOut(name);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export const LiveRegionModule = defineModule({
|
|
156
|
+
name: 'LiveRegion',
|
|
157
|
+
serviceKey: 'liveRegionService',
|
|
158
|
+
create: (host) => new LiveRegionService(host),
|
|
159
|
+
});
|