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