quilt-vanilla 0.2.4 → 0.4.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 +35 -39
- package/dist/actions.d.ts +14 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +115 -0
- package/dist/actions.js.map +1 -0
- package/dist/chrome-size.d.ts +7 -0
- package/dist/chrome-size.d.ts.map +1 -0
- package/dist/chrome-size.js +86 -0
- package/dist/chrome-size.js.map +1 -0
- package/dist/close.d.ts.map +1 -1
- package/dist/close.js +3 -1
- package/dist/close.js.map +1 -1
- package/dist/corners.d.ts +2 -1
- package/dist/corners.d.ts.map +1 -1
- package/dist/corners.js +2 -2
- package/dist/corners.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/menu.d.ts +9 -3
- package/dist/menu.d.ts.map +1 -1
- package/dist/menu.js +110 -37
- package/dist/menu.js.map +1 -1
- package/dist/panes.d.ts.map +1 -1
- package/dist/panes.js +84 -52
- package/dist/panes.js.map +1 -1
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -3
- package/dist/registry.js.map +1 -1
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +128 -36
- package/dist/renderer.js.map +1 -1
- package/dist/resize.d.ts +2 -1
- package/dist/resize.d.ts.map +1 -1
- package/dist/resize.js +2 -2
- package/dist/resize.js.map +1 -1
- package/dist/shortcut-registration.d.ts +9 -0
- package/dist/shortcut-registration.d.ts.map +1 -0
- package/dist/shortcut-registration.js +95 -0
- package/dist/shortcut-registration.js.map +1 -0
- package/dist/shortcuts.d.ts +7 -6
- package/dist/shortcuts.d.ts.map +1 -1
- package/dist/shortcuts.js +28 -50
- package/dist/shortcuts.js.map +1 -1
- package/dist/styles.css +74 -9
- package/dist/tabs.d.ts.map +1 -1
- package/dist/tabs.js +10 -12
- package/dist/tabs.js.map +1 -1
- package/dist/types.d.ts +50 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/workspace-api.d.ts +186 -0
- package/dist/workspace-api.d.ts.map +1 -0
- package/dist/workspace-api.js +409 -0
- package/dist/workspace-api.js.map +1 -0
- package/package.json +2 -2
- package/src/actions.ts +125 -0
- package/src/chrome-size.ts +99 -0
- package/src/close.ts +6 -1
- package/src/corners.ts +2 -1
- package/src/index.ts +31 -4
- package/src/menu.ts +123 -43
- package/src/panes.ts +82 -55
- package/src/registry.ts +6 -4
- package/src/renderer.ts +181 -54
- package/src/resize.ts +2 -1
- package/src/shortcut-registration.ts +106 -0
- package/src/shortcuts.ts +38 -63
- package/src/styles.css +74 -9
- package/src/tabs.ts +9 -11
- package/src/types.ts +67 -14
- package/src/workspace-api.ts +583 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { Pane, Group, WindowPlacement, AutoCollapse, Axis, CommandOptions, JoinOptions, Capability, Layout } from 'quilt-core';
|
|
2
|
+
import { PaneRegistry } from './registry.js';
|
|
3
|
+
import type { PaneRegistration } from './registry.js';
|
|
4
|
+
import type { LayoutTheme } from './theme.js';
|
|
5
|
+
import type { PaneRenderer, TabBarOptions, WorkspaceSettings, WorkspaceAction, ActionContext, RegisteredShortcut } from './types.js';
|
|
6
|
+
export type PaneType<T> = Omit<PaneRegistration<T>, 'type' | 'view'> & {
|
|
7
|
+
render: T;
|
|
8
|
+
};
|
|
9
|
+
export type PaneTypes<T> = Record<string, PaneType<T>>;
|
|
10
|
+
export type WorkspaceOptions<State = unknown> = WorkspaceSettings<State> & import('./types.js').InitialConfiguration & {
|
|
11
|
+
container: HTMLElement;
|
|
12
|
+
store?: never;
|
|
13
|
+
} & (unknown extends State ? {} : {
|
|
14
|
+
getPaneState: (paneId: string) => State;
|
|
15
|
+
}) & ({
|
|
16
|
+
paneTypes: PaneTypes<PaneRenderer<State>>;
|
|
17
|
+
registry?: never;
|
|
18
|
+
renderers?: never;
|
|
19
|
+
tabs?: never;
|
|
20
|
+
} | {
|
|
21
|
+
paneTypes?: undefined;
|
|
22
|
+
registry: PaneRegistry<PaneRenderer<State>>;
|
|
23
|
+
renderers?: never;
|
|
24
|
+
tabs?: never;
|
|
25
|
+
} | {
|
|
26
|
+
paneTypes?: undefined;
|
|
27
|
+
registry?: undefined;
|
|
28
|
+
renderers?: Record<string, PaneRenderer<State>>;
|
|
29
|
+
tabs?: import('./registry.js').TabRegistry;
|
|
30
|
+
});
|
|
31
|
+
export type WorkspaceOptionUpdates<State = unknown> = {
|
|
32
|
+
[Key in keyof WorkspaceSettings<State>]?: WorkspaceSettings<State>[Key] | undefined;
|
|
33
|
+
} & ({
|
|
34
|
+
paneTypes?: PaneTypes<PaneRenderer<State>> | undefined;
|
|
35
|
+
registry?: undefined;
|
|
36
|
+
renderers?: undefined;
|
|
37
|
+
tabs?: undefined;
|
|
38
|
+
} | {
|
|
39
|
+
paneTypes?: undefined;
|
|
40
|
+
registry?: PaneRegistry<PaneRenderer<State>> | undefined;
|
|
41
|
+
renderers?: undefined;
|
|
42
|
+
tabs?: undefined;
|
|
43
|
+
} | {
|
|
44
|
+
paneTypes?: undefined;
|
|
45
|
+
registry?: undefined;
|
|
46
|
+
renderers?: Record<string, PaneRenderer<State>> | undefined;
|
|
47
|
+
tabs?: import('./registry.js').TabRegistry | undefined;
|
|
48
|
+
});
|
|
49
|
+
export interface WorkspaceChange {
|
|
50
|
+
action: string;
|
|
51
|
+
changes: readonly ('layout' | 'theme' | 'tabBar' | 'autoCollapse' | 'shortcuts')[];
|
|
52
|
+
}
|
|
53
|
+
export interface WorkspaceEvents {
|
|
54
|
+
change: WorkspaceChange;
|
|
55
|
+
error: unknown;
|
|
56
|
+
}
|
|
57
|
+
export type AddPaneOptions = Partial<Omit<Pane, 'type'>> & {
|
|
58
|
+
groupId?: string;
|
|
59
|
+
};
|
|
60
|
+
export interface CloseOptions {
|
|
61
|
+
force?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface PaneHandle {
|
|
64
|
+
readonly id: string;
|
|
65
|
+
readonly isDisposed: boolean;
|
|
66
|
+
getSnapshot(): Pane;
|
|
67
|
+
update(patch: Partial<Omit<Pane, 'id'>>): void;
|
|
68
|
+
setTitle(title: string): void;
|
|
69
|
+
activate(): void;
|
|
70
|
+
move(groupId: string, position?: 'tab' | 'left' | 'right' | 'top' | 'bottom', index?: number): void;
|
|
71
|
+
popout(placement?: WindowPlacement): Promise<boolean>;
|
|
72
|
+
return(): void;
|
|
73
|
+
retry(): void;
|
|
74
|
+
close(options?: CloseOptions): Promise<boolean>;
|
|
75
|
+
}
|
|
76
|
+
/** The mounted API. The model and its lifetime remain private to Quilt. */
|
|
77
|
+
export interface WorkspaceHandle<State = unknown> {
|
|
78
|
+
readonly isDisposed: boolean;
|
|
79
|
+
canExecuteAction(action: WorkspaceAction, context?: ActionContext): boolean;
|
|
80
|
+
executeAction(action: WorkspaceAction, context?: ActionContext): Promise<boolean>;
|
|
81
|
+
getShortcuts(): readonly RegisteredShortcut[];
|
|
82
|
+
/** Subscribe to configuration changes or errors. The returned function unsubscribes. */
|
|
83
|
+
on<K extends keyof WorkspaceEvents>(event: K, listener: (event: WorkspaceEvents[K]) => void): () => void;
|
|
84
|
+
/** Stable immutable arrangement snapshot, including live detached records. */
|
|
85
|
+
getLayout(): Layout;
|
|
86
|
+
/** Mutable arrangement copy. Use exportWorkspace for persistence with appearance. */
|
|
87
|
+
exportLayout(): Layout;
|
|
88
|
+
/** Validate and replace the arrangement; detached records restore docked. Invalidates old pane handles on success. */
|
|
89
|
+
loadLayout(input: unknown): void;
|
|
90
|
+
/** Restore the initial arrangement and appearance. */
|
|
91
|
+
reset(): void;
|
|
92
|
+
exportWorkspace(): import('./workspace.js').WorkspacePreset;
|
|
93
|
+
/** Apply a complete preset atomically; emit one consolidated change event. */
|
|
94
|
+
loadWorkspace(input: unknown): void;
|
|
95
|
+
updateOptions(options: WorkspaceOptionUpdates<State>): void;
|
|
96
|
+
setTheme(theme: LayoutTheme): void;
|
|
97
|
+
setTabBar(tabBar: TabBarOptions): void;
|
|
98
|
+
refreshTheme(): void;
|
|
99
|
+
getAutoCollapse(): AutoCollapse;
|
|
100
|
+
setAutoCollapse(mode: AutoCollapse): void;
|
|
101
|
+
getPane(id: string): PaneHandle | undefined;
|
|
102
|
+
getPanes(): PaneHandle[];
|
|
103
|
+
/** Create from a registered type; undefined means its factory cancelled. */
|
|
104
|
+
addPane(type: string, options?: AddPaneOptions): PaneHandle | undefined;
|
|
105
|
+
insertPane(pane: Pane, groupId: string, options?: CommandOptions): void;
|
|
106
|
+
updatePane(pane: Pane): void;
|
|
107
|
+
activatePane(id: string): void;
|
|
108
|
+
movePane(paneId: string, groupId: string, position?: 'tab' | 'left' | 'right' | 'top' | 'bottom', index?: number, options?: CommandOptions): void;
|
|
109
|
+
splitGroup(groupId: string, axis: Axis, pane?: Pane | null, options?: CommandOptions & {
|
|
110
|
+
before?: boolean;
|
|
111
|
+
ratio?: number;
|
|
112
|
+
}): string;
|
|
113
|
+
removeEmptyGroup(groupId: string): void;
|
|
114
|
+
joinGroup(groupId: string, options?: CommandOptions): void;
|
|
115
|
+
joinGroups(receiverId: string, otherId: string, options?: JoinOptions): void;
|
|
116
|
+
resize(splitId: string, ratio: number, options?: CommandOptions): void;
|
|
117
|
+
resizeMany(ratios: Record<string, number>, options?: CommandOptions): void;
|
|
118
|
+
maximize(groupId: string | null): void;
|
|
119
|
+
setTabDisplay(groupId: string, display: Group['tabDisplay']): void;
|
|
120
|
+
setTabPlacement(groupId: string, placement: Group['tabPlacement']): void;
|
|
121
|
+
can(paneId: string, capability: Capability): boolean;
|
|
122
|
+
canRestoreClosedPane(): boolean;
|
|
123
|
+
restoreClosedPane(): void;
|
|
124
|
+
/** Confirm and check permissions unless force is explicitly supplied. */
|
|
125
|
+
closePane(id: string, options?: CloseOptions): Promise<boolean>;
|
|
126
|
+
closeGroup(id: string, options?: CloseOptions): Promise<boolean>;
|
|
127
|
+
/** Call during a user gesture. Resolves after destination readiness or rollback. */
|
|
128
|
+
popout(id: string, placement?: WindowPlacement): Promise<boolean>;
|
|
129
|
+
returnPane(id: string): void;
|
|
130
|
+
retryPane(id: string): void;
|
|
131
|
+
/** Idempotently cancel pending work and release views, companions, and the private model. */
|
|
132
|
+
dispose(): void;
|
|
133
|
+
}
|
|
134
|
+
/** A mounted workspace. Call dispose once when its application container is removed. */
|
|
135
|
+
export declare class Workspace<State = unknown> implements WorkspaceHandle<State> {
|
|
136
|
+
#private;
|
|
137
|
+
constructor(options: WorkspaceOptions<State>);
|
|
138
|
+
get isDisposed(): boolean;
|
|
139
|
+
on<K extends keyof WorkspaceEvents>(event: K, listener: (event: WorkspaceEvents[K]) => void): () => void;
|
|
140
|
+
/** Stable immutable layout snapshot. */
|
|
141
|
+
getLayout: () => Layout;
|
|
142
|
+
exportLayout(): Layout;
|
|
143
|
+
loadLayout(input: unknown): void;
|
|
144
|
+
reset(): void;
|
|
145
|
+
exportWorkspace(): import("./workspace.js").WorkspacePreset;
|
|
146
|
+
loadWorkspace(input: unknown): void;
|
|
147
|
+
canExecuteAction(action: WorkspaceAction, context?: ActionContext): boolean;
|
|
148
|
+
executeAction(action: WorkspaceAction, context?: ActionContext): Promise<boolean>;
|
|
149
|
+
getShortcuts(): readonly RegisteredShortcut[];
|
|
150
|
+
updateOptions(next: WorkspaceOptionUpdates<State>): void;
|
|
151
|
+
setTheme(theme: LayoutTheme): void;
|
|
152
|
+
setTabBar(tabBar: TabBarOptions): void;
|
|
153
|
+
refreshTheme(): void;
|
|
154
|
+
getAutoCollapse(): AutoCollapse;
|
|
155
|
+
setAutoCollapse(mode: AutoCollapse): void;
|
|
156
|
+
getPane(id: string): PaneHandle | undefined;
|
|
157
|
+
getPanes(): PaneHandle[];
|
|
158
|
+
addPane(type: string, options?: AddPaneOptions): PaneHandle | undefined;
|
|
159
|
+
/** Insert a fully specified serializable record (advanced model integration). */
|
|
160
|
+
insertPane(pane: Pane, groupId: string, options?: CommandOptions): void;
|
|
161
|
+
updatePane(pane: Pane): void;
|
|
162
|
+
activatePane(id: string): void;
|
|
163
|
+
movePane(paneId: string, groupId: string, position?: 'tab' | 'left' | 'right' | 'top' | 'bottom', index?: number, options?: CommandOptions): void;
|
|
164
|
+
splitGroup(groupId: string, axis: Axis, pane?: Pane | null, options?: CommandOptions & {
|
|
165
|
+
before?: boolean;
|
|
166
|
+
ratio?: number;
|
|
167
|
+
}): string;
|
|
168
|
+
removeEmptyGroup(groupId: string): void;
|
|
169
|
+
joinGroup(groupId: string, options?: CommandOptions): void;
|
|
170
|
+
joinGroups(receiverId: string, otherId: string, options?: JoinOptions): void;
|
|
171
|
+
resize(splitId: string, ratio: number, options?: CommandOptions): void;
|
|
172
|
+
resizeMany(ratios: Record<string, number>, options?: CommandOptions): void;
|
|
173
|
+
maximize(groupId: string | null): void;
|
|
174
|
+
setTabDisplay(groupId: string, display: Group['tabDisplay']): void;
|
|
175
|
+
setTabPlacement(groupId: string, placement: Group['tabPlacement']): void;
|
|
176
|
+
can(paneId: string, capability: Capability): boolean;
|
|
177
|
+
canRestoreClosedPane(): boolean;
|
|
178
|
+
restoreClosedPane(): void;
|
|
179
|
+
closePane(id: string, options?: CloseOptions): Promise<boolean>;
|
|
180
|
+
closeGroup(id: string, options?: CloseOptions): Promise<boolean>;
|
|
181
|
+
popout(id: string, placement?: WindowPlacement): Promise<boolean>;
|
|
182
|
+
returnPane(id: string): void;
|
|
183
|
+
retryPane(id: string): void;
|
|
184
|
+
dispose(): void;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=workspace-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-api.d.ts","sourceRoot":"","sources":["../src/workspace-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { groups, findNode } from 'quilt-core';
|
|
2
|
+
import { mountLayout } from './renderer.js';
|
|
3
|
+
import { PaneRegistry, createPaneId } from './registry.js';
|
|
4
|
+
import { dockLayout } from './workspace.js';
|
|
5
|
+
/** A mounted workspace. Call dispose once when its application container is removed. */
|
|
6
|
+
export class Workspace {
|
|
7
|
+
#mounted;
|
|
8
|
+
#disposed = false;
|
|
9
|
+
#handles = new Map();
|
|
10
|
+
#listeners = {
|
|
11
|
+
change: new Set(),
|
|
12
|
+
error: new Set(),
|
|
13
|
+
};
|
|
14
|
+
#cleanups = [];
|
|
15
|
+
#options;
|
|
16
|
+
#activeGroup;
|
|
17
|
+
#batch = false;
|
|
18
|
+
#initial;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
if (!options?.container?.ownerDocument?.defaultView)
|
|
21
|
+
throw new Error('Workspace requires a container in a live document');
|
|
22
|
+
const { container, ...input } = options;
|
|
23
|
+
const { initialLayout: _layout, initialWorkspace: _workspace, ...updates } = input;
|
|
24
|
+
this.#options = { ...updates };
|
|
25
|
+
const adapted = this.#adapt(this.#options);
|
|
26
|
+
this.#mounted = mountLayout(container, {
|
|
27
|
+
...input,
|
|
28
|
+
...adapted,
|
|
29
|
+
onError: this.#report,
|
|
30
|
+
});
|
|
31
|
+
this.#initial = this.#mounted.exportWorkspace();
|
|
32
|
+
this.#cleanups.push(this.#model.subscribe((event) => {
|
|
33
|
+
if (event.action === 'load') {
|
|
34
|
+
this.#handles.clear();
|
|
35
|
+
this.#activeGroup = undefined;
|
|
36
|
+
}
|
|
37
|
+
else
|
|
38
|
+
for (const id of this.#handles.keys())
|
|
39
|
+
if (!Object.hasOwn(event.layout.panes, id))
|
|
40
|
+
this.#handles.delete(id);
|
|
41
|
+
if (!this.#batch)
|
|
42
|
+
this.#emit({ action: event.action, changes: ['layout'] });
|
|
43
|
+
}), this.#model.onError(this.#report));
|
|
44
|
+
const activate = (event) => {
|
|
45
|
+
const target = event.target;
|
|
46
|
+
const id = target?.closest?.('[data-node-id]')?.getAttribute('data-node-id');
|
|
47
|
+
if (id && findNode(this.getLayout().root, id)?.kind === 'group')
|
|
48
|
+
this.#activeGroup = id;
|
|
49
|
+
};
|
|
50
|
+
container.addEventListener('pointerdown', activate);
|
|
51
|
+
container.addEventListener('focusin', activate);
|
|
52
|
+
this.#cleanups.push(() => container.removeEventListener('pointerdown', activate), () => container.removeEventListener('focusin', activate));
|
|
53
|
+
}
|
|
54
|
+
get #model() {
|
|
55
|
+
return this.#mounted.store;
|
|
56
|
+
}
|
|
57
|
+
#alive() {
|
|
58
|
+
if (this.#disposed)
|
|
59
|
+
throw new Error('Workspace has been disposed');
|
|
60
|
+
}
|
|
61
|
+
#report = (error) => {
|
|
62
|
+
try {
|
|
63
|
+
this.#options.onError?.(error);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
/* Reporting must not interrupt cleanup. */
|
|
67
|
+
}
|
|
68
|
+
for (const listener of [...this.#listeners.error]) {
|
|
69
|
+
if (!this.#listeners.error.has(listener))
|
|
70
|
+
continue;
|
|
71
|
+
try {
|
|
72
|
+
listener(error);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* Isolate reporters. */
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
#emit(event) {
|
|
80
|
+
for (const listener of [...this.#listeners.change]) {
|
|
81
|
+
if (!this.#listeners.change.has(listener))
|
|
82
|
+
continue;
|
|
83
|
+
try {
|
|
84
|
+
listener(event);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
this.#report(error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
#adapt(options) {
|
|
92
|
+
const { paneTypes, ...rest } = options;
|
|
93
|
+
if (paneTypes !== undefined) {
|
|
94
|
+
if (rest.registry || rest.renderers || rest.tabs)
|
|
95
|
+
throw new Error('paneTypes cannot be combined with registry, renderers, or tabs');
|
|
96
|
+
return {
|
|
97
|
+
...rest,
|
|
98
|
+
registry: new PaneRegistry(Object.entries(paneTypes).map(([type, { render, ...entry }]) => ({
|
|
99
|
+
...entry,
|
|
100
|
+
type,
|
|
101
|
+
view: render,
|
|
102
|
+
}))),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return { ...rest, registry: rest.registry };
|
|
106
|
+
}
|
|
107
|
+
get isDisposed() {
|
|
108
|
+
return this.#disposed;
|
|
109
|
+
}
|
|
110
|
+
on(event, listener) {
|
|
111
|
+
this.#alive();
|
|
112
|
+
const listeners = this.#listeners[event];
|
|
113
|
+
listeners.add(listener);
|
|
114
|
+
return () => {
|
|
115
|
+
listeners.delete(listener);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Stable immutable layout snapshot. */
|
|
119
|
+
getLayout = () => {
|
|
120
|
+
this.#alive();
|
|
121
|
+
return this.#model.getSnapshot();
|
|
122
|
+
};
|
|
123
|
+
exportLayout() {
|
|
124
|
+
this.#alive();
|
|
125
|
+
return this.#model.export();
|
|
126
|
+
}
|
|
127
|
+
loadLayout(input) {
|
|
128
|
+
this.#alive();
|
|
129
|
+
this.#model.load(dockLayout(input));
|
|
130
|
+
}
|
|
131
|
+
reset() {
|
|
132
|
+
this.loadWorkspace(this.#initial);
|
|
133
|
+
}
|
|
134
|
+
exportWorkspace() {
|
|
135
|
+
this.#alive();
|
|
136
|
+
return this.#mounted.exportWorkspace();
|
|
137
|
+
}
|
|
138
|
+
loadWorkspace(input) {
|
|
139
|
+
this.#alive();
|
|
140
|
+
this.#batch = true;
|
|
141
|
+
try {
|
|
142
|
+
this.#mounted.loadWorkspace(input);
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
this.#batch = false;
|
|
146
|
+
}
|
|
147
|
+
this.#emit({ action: 'loadWorkspace', changes: ['layout', 'theme', 'tabBar', 'autoCollapse'] });
|
|
148
|
+
}
|
|
149
|
+
canExecuteAction(action, context) {
|
|
150
|
+
return !this.#disposed && this.#mounted.canExecuteAction(action, context);
|
|
151
|
+
}
|
|
152
|
+
executeAction(action, context) {
|
|
153
|
+
return this.#disposed ? Promise.resolve(false) : this.#mounted.executeAction(action, context);
|
|
154
|
+
}
|
|
155
|
+
getShortcuts() {
|
|
156
|
+
return this.#mounted.getShortcuts();
|
|
157
|
+
}
|
|
158
|
+
updateOptions(next) {
|
|
159
|
+
this.#alive();
|
|
160
|
+
if ('container' in next)
|
|
161
|
+
throw new Error('Workspace container cannot be updated');
|
|
162
|
+
const candidate = { ...this.#options, ...next };
|
|
163
|
+
const adapted = this.#adapt(candidate);
|
|
164
|
+
const changes = [];
|
|
165
|
+
const before = this.exportWorkspace();
|
|
166
|
+
const beforeShortcuts = JSON.stringify(this.getShortcuts());
|
|
167
|
+
const beforeFormatter = this.#options.formatShortcut;
|
|
168
|
+
// Initial appearance is mount-only: only explicitly updated appearance keys apply.
|
|
169
|
+
if (!('theme' in next))
|
|
170
|
+
delete adapted.theme;
|
|
171
|
+
if (!('tabBar' in next))
|
|
172
|
+
delete adapted.tabBar;
|
|
173
|
+
this.#mounted.updateOptions({ ...adapted, onError: this.#report });
|
|
174
|
+
this.#options = candidate;
|
|
175
|
+
const after = this.exportWorkspace();
|
|
176
|
+
if (JSON.stringify(before.theme) !== JSON.stringify(after.theme))
|
|
177
|
+
changes.push('theme');
|
|
178
|
+
if (JSON.stringify(before.tabBar) !== JSON.stringify(after.tabBar))
|
|
179
|
+
changes.push('tabBar');
|
|
180
|
+
if (beforeShortcuts !== JSON.stringify(this.getShortcuts()) ||
|
|
181
|
+
beforeFormatter !== candidate.formatShortcut)
|
|
182
|
+
changes.push('shortcuts');
|
|
183
|
+
if (changes.length)
|
|
184
|
+
this.#emit({ action: 'updateOptions', changes });
|
|
185
|
+
}
|
|
186
|
+
setTheme(theme) {
|
|
187
|
+
this.updateOptions({ theme });
|
|
188
|
+
}
|
|
189
|
+
setTabBar(tabBar) {
|
|
190
|
+
this.updateOptions({ tabBar });
|
|
191
|
+
}
|
|
192
|
+
refreshTheme() {
|
|
193
|
+
this.#alive();
|
|
194
|
+
this.#mounted.refreshTheme();
|
|
195
|
+
}
|
|
196
|
+
getAutoCollapse() {
|
|
197
|
+
this.#alive();
|
|
198
|
+
return this.#model.getAutoCollapse();
|
|
199
|
+
}
|
|
200
|
+
setAutoCollapse(mode) {
|
|
201
|
+
this.#alive();
|
|
202
|
+
const previous = this.#model.getAutoCollapse();
|
|
203
|
+
this.#model.setAutoCollapse(mode);
|
|
204
|
+
if (mode !== previous)
|
|
205
|
+
this.#emit({ action: 'setAutoCollapse', changes: ['autoCollapse'] });
|
|
206
|
+
}
|
|
207
|
+
getPane(id) {
|
|
208
|
+
this.#alive();
|
|
209
|
+
if (!Object.hasOwn(this.getLayout().panes, id))
|
|
210
|
+
return undefined;
|
|
211
|
+
let handle = this.#handles.get(id);
|
|
212
|
+
if (handle)
|
|
213
|
+
return handle;
|
|
214
|
+
const workspace = this;
|
|
215
|
+
const alive = () => {
|
|
216
|
+
workspace.#alive();
|
|
217
|
+
if (workspace.#handles.get(id) !== handle)
|
|
218
|
+
throw new Error(`Pane ${id} has been disposed`);
|
|
219
|
+
};
|
|
220
|
+
handle = {
|
|
221
|
+
id,
|
|
222
|
+
get isDisposed() {
|
|
223
|
+
return workspace.#disposed || workspace.#handles.get(id) !== handle;
|
|
224
|
+
},
|
|
225
|
+
getSnapshot() {
|
|
226
|
+
alive();
|
|
227
|
+
return workspace.getLayout().panes[id];
|
|
228
|
+
},
|
|
229
|
+
update(patch) {
|
|
230
|
+
alive();
|
|
231
|
+
workspace.updatePane({ ...workspace.getLayout().panes[id], ...patch, id });
|
|
232
|
+
},
|
|
233
|
+
setTitle(title) {
|
|
234
|
+
this.update({ title });
|
|
235
|
+
},
|
|
236
|
+
activate() {
|
|
237
|
+
alive();
|
|
238
|
+
workspace.activatePane(id);
|
|
239
|
+
},
|
|
240
|
+
move(groupId, position, index) {
|
|
241
|
+
alive();
|
|
242
|
+
workspace.movePane(id, groupId, position, index);
|
|
243
|
+
},
|
|
244
|
+
async popout(placement) {
|
|
245
|
+
alive();
|
|
246
|
+
return workspace.popout(id, placement);
|
|
247
|
+
},
|
|
248
|
+
return() {
|
|
249
|
+
alive();
|
|
250
|
+
workspace.returnPane(id);
|
|
251
|
+
},
|
|
252
|
+
retry() {
|
|
253
|
+
alive();
|
|
254
|
+
workspace.retryPane(id);
|
|
255
|
+
},
|
|
256
|
+
async close(options) {
|
|
257
|
+
alive();
|
|
258
|
+
return workspace.closePane(id, options);
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
Object.freeze(handle);
|
|
262
|
+
this.#handles.set(id, handle);
|
|
263
|
+
return handle;
|
|
264
|
+
}
|
|
265
|
+
getPanes() {
|
|
266
|
+
return Object.keys(this.getLayout().panes).map((id) => this.getPane(id));
|
|
267
|
+
}
|
|
268
|
+
addPane(type, options = {}) {
|
|
269
|
+
this.#alive();
|
|
270
|
+
const layout = this.getLayout();
|
|
271
|
+
const all = groups(layout.root);
|
|
272
|
+
const groupId = options.groupId ?? all.find((group) => group.id === this.#activeGroup)?.id ?? all[0].id;
|
|
273
|
+
const group = all.find((group) => group.id === groupId);
|
|
274
|
+
if (!group)
|
|
275
|
+
throw new Error(`Group not found: ${groupId}`);
|
|
276
|
+
const registry = this.#adapt(this.#options).registry;
|
|
277
|
+
const entry = registry?.list().find((entry) => entry.type === type);
|
|
278
|
+
if (!entry)
|
|
279
|
+
throw new Error(`Pane type is not registered: ${type}`);
|
|
280
|
+
const supplied = entry.create
|
|
281
|
+
? entry.create({ groupId, source: group.active ? layout.panes[group.active] : undefined })
|
|
282
|
+
: {};
|
|
283
|
+
if (supplied === undefined)
|
|
284
|
+
return undefined;
|
|
285
|
+
const { groupId: _groupId, ...patch } = options;
|
|
286
|
+
const pane = {
|
|
287
|
+
title: entry.title,
|
|
288
|
+
...(entry.icon === undefined ? {} : { icon: entry.icon }),
|
|
289
|
+
...supplied,
|
|
290
|
+
...patch,
|
|
291
|
+
type,
|
|
292
|
+
id: patch.id ?? supplied.id ?? createPaneId(),
|
|
293
|
+
};
|
|
294
|
+
this.insertPane(pane, groupId);
|
|
295
|
+
return this.getPane(pane.id);
|
|
296
|
+
}
|
|
297
|
+
/** Insert a fully specified serializable record (advanced model integration). */
|
|
298
|
+
insertPane(pane, groupId, options = {}) {
|
|
299
|
+
this.#alive();
|
|
300
|
+
this.#model.add(pane, groupId, options);
|
|
301
|
+
}
|
|
302
|
+
updatePane(pane) {
|
|
303
|
+
this.#alive();
|
|
304
|
+
this.#model.updatePane(pane);
|
|
305
|
+
}
|
|
306
|
+
activatePane(id) {
|
|
307
|
+
const group = groups(this.getLayout().root).find((group) => group.panes.includes(id));
|
|
308
|
+
if (!group)
|
|
309
|
+
throw new Error(`Pane is not docked: ${id}`);
|
|
310
|
+
this.#activeGroup = group.id;
|
|
311
|
+
this.#model.activate(group.id, id);
|
|
312
|
+
}
|
|
313
|
+
movePane(paneId, groupId, position = 'tab', index, options = {}) {
|
|
314
|
+
this.#alive();
|
|
315
|
+
this.#model.move(paneId, groupId, position, index, options);
|
|
316
|
+
}
|
|
317
|
+
splitGroup(groupId, axis, pane = null, options = {}) {
|
|
318
|
+
this.#alive();
|
|
319
|
+
return this.#model.split(groupId, axis, pane, options);
|
|
320
|
+
}
|
|
321
|
+
removeEmptyGroup(groupId) {
|
|
322
|
+
this.#alive();
|
|
323
|
+
this.#model.removeEmptyGroup(groupId);
|
|
324
|
+
}
|
|
325
|
+
joinGroup(groupId, options = {}) {
|
|
326
|
+
this.#alive();
|
|
327
|
+
this.#model.join(groupId, options);
|
|
328
|
+
}
|
|
329
|
+
joinGroups(receiverId, otherId, options = {}) {
|
|
330
|
+
this.#alive();
|
|
331
|
+
this.#model.joinRegions(receiverId, otherId, options);
|
|
332
|
+
}
|
|
333
|
+
resize(splitId, ratio, options = {}) {
|
|
334
|
+
this.#alive();
|
|
335
|
+
this.#model.resize(splitId, ratio, options);
|
|
336
|
+
}
|
|
337
|
+
resizeMany(ratios, options = {}) {
|
|
338
|
+
this.#alive();
|
|
339
|
+
this.#model.resizeMany(ratios, options);
|
|
340
|
+
}
|
|
341
|
+
maximize(groupId) {
|
|
342
|
+
this.#alive();
|
|
343
|
+
this.#model.maximize(groupId);
|
|
344
|
+
}
|
|
345
|
+
setTabDisplay(groupId, display) {
|
|
346
|
+
this.#alive();
|
|
347
|
+
this.#model.setTabDisplay(groupId, display);
|
|
348
|
+
}
|
|
349
|
+
setTabPlacement(groupId, placement) {
|
|
350
|
+
this.#alive();
|
|
351
|
+
this.#model.setTabPlacement(groupId, placement);
|
|
352
|
+
}
|
|
353
|
+
can(paneId, capability) {
|
|
354
|
+
this.#alive();
|
|
355
|
+
return this.#model.can(paneId, capability);
|
|
356
|
+
}
|
|
357
|
+
canRestoreClosedPane() {
|
|
358
|
+
this.#alive();
|
|
359
|
+
return this.#model.canRestoreClosedTab();
|
|
360
|
+
}
|
|
361
|
+
restoreClosedPane() {
|
|
362
|
+
this.#alive();
|
|
363
|
+
this.#model.restoreClosedTab();
|
|
364
|
+
}
|
|
365
|
+
async closePane(id, options = {}) {
|
|
366
|
+
this.#alive();
|
|
367
|
+
if (options.force) {
|
|
368
|
+
this.#model.close(id);
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
return this.#mounted.requestClose(id);
|
|
372
|
+
}
|
|
373
|
+
async closeGroup(id, options = {}) {
|
|
374
|
+
this.#alive();
|
|
375
|
+
if (options.force) {
|
|
376
|
+
this.#model.closeGroup(id);
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
return this.#mounted.requestClose(id, 'group');
|
|
380
|
+
}
|
|
381
|
+
async popout(id, placement) {
|
|
382
|
+
this.#alive();
|
|
383
|
+
return this.#mounted.popout(id, placement);
|
|
384
|
+
}
|
|
385
|
+
returnPane(id) {
|
|
386
|
+
this.#alive();
|
|
387
|
+
this.#mounted.returnPane(id);
|
|
388
|
+
}
|
|
389
|
+
retryPane(id) {
|
|
390
|
+
this.#alive();
|
|
391
|
+
this.#mounted.retryPane(id);
|
|
392
|
+
}
|
|
393
|
+
dispose() {
|
|
394
|
+
if (this.#disposed)
|
|
395
|
+
return;
|
|
396
|
+
this.#disposed = true;
|
|
397
|
+
this.#handles.clear();
|
|
398
|
+
for (const cleanup of this.#cleanups.splice(0))
|
|
399
|
+
cleanup();
|
|
400
|
+
try {
|
|
401
|
+
this.#mounted.dispose();
|
|
402
|
+
}
|
|
403
|
+
finally {
|
|
404
|
+
this.#listeners.change.clear();
|
|
405
|
+
this.#listeners.error.clear();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=workspace-api.js.map
|