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.
Files changed (50) hide show
  1. package/README.md +35 -39
  2. package/dist/chrome-size.d.ts +7 -0
  3. package/dist/chrome-size.d.ts.map +1 -0
  4. package/dist/chrome-size.js +86 -0
  5. package/dist/chrome-size.js.map +1 -0
  6. package/dist/close.d.ts.map +1 -1
  7. package/dist/close.js +3 -1
  8. package/dist/close.js.map +1 -1
  9. package/dist/corners.d.ts +2 -1
  10. package/dist/corners.d.ts.map +1 -1
  11. package/dist/corners.js +2 -2
  12. package/dist/corners.js.map +1 -1
  13. package/dist/index.d.ts +5 -4
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/panes.d.ts.map +1 -1
  18. package/dist/panes.js +84 -52
  19. package/dist/panes.js.map +1 -1
  20. package/dist/registry.d.ts +1 -0
  21. package/dist/registry.d.ts.map +1 -1
  22. package/dist/registry.js +4 -3
  23. package/dist/registry.js.map +1 -1
  24. package/dist/renderer.d.ts.map +1 -1
  25. package/dist/renderer.js +94 -29
  26. package/dist/renderer.js.map +1 -1
  27. package/dist/resize.d.ts +2 -1
  28. package/dist/resize.d.ts.map +1 -1
  29. package/dist/resize.js +2 -2
  30. package/dist/resize.js.map +1 -1
  31. package/dist/styles.css +49 -0
  32. package/dist/types.d.ts +29 -8
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/types.js.map +1 -1
  35. package/dist/workspace-api.d.ts +180 -0
  36. package/dist/workspace-api.d.ts.map +1 -0
  37. package/dist/workspace-api.js +395 -0
  38. package/dist/workspace-api.js.map +1 -0
  39. package/package.json +2 -2
  40. package/src/chrome-size.ts +99 -0
  41. package/src/close.ts +6 -1
  42. package/src/corners.ts +2 -1
  43. package/src/index.ts +25 -4
  44. package/src/panes.ts +82 -55
  45. package/src/registry.ts +6 -4
  46. package/src/renderer.ts +141 -48
  47. package/src/resize.ts +2 -1
  48. package/src/styles.css +49 -0
  49. package/src/types.ts +24 -9
  50. 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"]}