quilt-core 0.5.0 → 0.7.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.
@@ -1,4 +1,4 @@
1
- import type { AutoCollapse, LayoutStoreOptions, JoinOptions, Axis, Capability, Change, CommandOptions, Group, Layout, Pane, WindowPlacement } from './types.js';
1
+ import type { AutoCollapse, LayoutStoreOptions, JoinOptions, Axis, Capability, CapabilityPolicy, Change, CommandOptions, Group, Layout, Pane, WindowPlacement } from './types.js';
2
2
  export declare class LayoutStore {
3
3
  private state;
4
4
  private initial;
@@ -10,6 +10,7 @@ export declare class LayoutStore {
10
10
  private notifying;
11
11
  private pending;
12
12
  private autoCollapse;
13
+ private capabilities;
13
14
  constructor(input: unknown, options?: LayoutStoreOptions);
14
15
  /** Stable immutable snapshot, suitable for useSyncExternalStore. */
15
16
  getSnapshot: () => Layout;
@@ -28,7 +29,14 @@ export declare class LayoutStore {
28
29
  getAutoCollapse(): AutoCollapse;
29
30
  setAutoCollapse(mode: AutoCollapse): void;
30
31
  private tidy;
32
+ /** Replace session policy; layout export/load never serializes or resets it. */
33
+ setCapabilities(policy?: CapabilityPolicy): void;
34
+ private canPane;
31
35
  can(paneId: string, capability: Capability): boolean;
36
+ private canNodeIn;
37
+ /** Test every affected tab, including policy on empty regions. */
38
+ canNode(nodeId: string, capability: Capability): boolean;
39
+ private permitNode;
32
40
  load(input: unknown): void;
33
41
  reset(): void;
34
42
  setTabDisplay(groupId: string, display: Group['tabDisplay']): void;
@@ -37,7 +45,7 @@ export declare class LayoutStore {
37
45
  resize(splitId: string, ratio: number, options?: CommandOptions): void;
38
46
  /** Atomically update coupled split ratios without intermediate layouts. */
39
47
  resizeMany(ratios: Record<string, number>, options?: CommandOptions): void;
40
- maximize(groupId: string | null): void;
48
+ maximize(groupId: string | null, options?: CommandOptions): void;
41
49
  add(pane: Pane, groupId: string, options?: CommandOptions): void;
42
50
  updatePane(pane: Pane): void;
43
51
  split(groupId: string, axis: Axis, pane: Pane | null, options?: CommandOptions & {
@@ -45,7 +53,7 @@ export declare class LayoutStore {
45
53
  ratio?: number;
46
54
  }): string;
47
55
  /** Cancel only an unfilled region; never roll back edits made elsewhere. */
48
- removeEmptyGroup(groupId: string): void;
56
+ removeEmptyGroup(groupId: string, options?: CommandOptions): void;
49
57
  /** Move to a tab group or to a new split at an edge. */
50
58
  move(paneId: string, groupId: string, position?: 'tab' | 'left' | 'right' | 'top' | 'bottom', index?: number, options?: CommandOptions): void;
51
59
  /** Join the sibling region at this split, retaining its content as tabs. */
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -22,7 +22,9 @@ export class LayoutStore {
22
22
  notifying = false;
23
23
  pending = [];
24
24
  autoCollapse = 'disabled';
25
+ capabilities = {};
25
26
  constructor(input, options = {}) {
27
+ this.setCapabilities(options.capabilities);
26
28
  this.setAutoCollapse(options.autoCollapse ?? 'disabled');
27
29
  this.state = freeze(parseLayout(input));
28
30
  this.initial = this.export();
@@ -128,7 +130,7 @@ export class LayoutStore {
128
130
  }
129
131
  permit(draft, ids, cap, options) {
130
132
  for (const id of ids)
131
- if (options.source === 'user' && this.pane(draft, id).capabilities?.[cap] === false)
133
+ if (options.source === 'user' && !this.canPane(draft, id, cap))
132
134
  problem(`${cap} is disabled for ${id}`);
133
135
  }
134
136
  id(draft) {
@@ -176,9 +178,80 @@ export class LayoutStore {
176
178
  if (draft.maximized && !findNode(draft.root, draft.maximized))
177
179
  draft.maximized = null;
178
180
  }
181
+ /** Replace session policy; layout export/load never serializes or resets it. */
182
+ setCapabilities(policy = {}) {
183
+ this.alive();
184
+ const flags = (value) => {
185
+ if (!value || typeof value !== 'object' || Array.isArray(value))
186
+ problem('Invalid capabilities');
187
+ for (const [key, flag] of Object.entries(value))
188
+ if (![
189
+ 'resize',
190
+ 'move',
191
+ 'reorder',
192
+ 'addTab',
193
+ 'maximize',
194
+ 'split',
195
+ 'join',
196
+ 'close',
197
+ 'popout',
198
+ ].includes(key) ||
199
+ typeof flag !== 'boolean')
200
+ problem('Invalid capability: ' + key);
201
+ };
202
+ if (!policy || typeof policy !== 'object' || Array.isArray(policy))
203
+ problem('Invalid capability policy');
204
+ for (const [key, value] of Object.entries(policy)) {
205
+ if (value === undefined)
206
+ continue;
207
+ if (key === 'defaults')
208
+ flags(value);
209
+ else if (key === 'groups' || key === 'panes') {
210
+ if (!value || typeof value !== 'object' || Array.isArray(value))
211
+ problem('Invalid capability overrides');
212
+ Object.values(value).forEach(flags);
213
+ }
214
+ else
215
+ problem('Unknown capability scope: ' + key);
216
+ }
217
+ this.capabilities = structuredClone(policy);
218
+ }
219
+ canPane(layout, paneId, capability) {
220
+ const pane = layout.panes[paneId];
221
+ if (!pane)
222
+ return false;
223
+ const groupId = groups(layout.root).find((g) => g.panes.includes(paneId))?.id ??
224
+ layout.popouts.find((p) => p.paneId === paneId)?.groupId;
225
+ return (this.capabilities.panes?.[paneId]?.[capability] ??
226
+ pane.capabilities?.[capability] ??
227
+ (groupId ? this.capabilities.groups?.[groupId]?.[capability] : undefined) ??
228
+ this.capabilities.defaults?.[capability] ??
229
+ (capability === 'addTab' || capability === 'reorder'
230
+ ? this.canPane(layout, paneId, 'move')
231
+ : true));
232
+ }
179
233
  can(paneId, capability) {
180
- return (Boolean(this.state.panes[paneId]) &&
181
- this.state.panes[paneId].capabilities?.[capability] !== false);
234
+ return this.canPane(this.state, paneId, capability);
235
+ }
236
+ canNodeIn(layout, node, capability) {
237
+ if (node.kind === 'split')
238
+ return node.children.every((child) => this.canNodeIn(layout, child, capability));
239
+ return node.panes.length
240
+ ? node.panes.every((id) => this.canPane(layout, id, capability))
241
+ : (this.capabilities.groups?.[node.id]?.[capability] ??
242
+ this.capabilities.defaults?.[capability] ??
243
+ (capability === 'addTab' || capability === 'reorder'
244
+ ? this.canNodeIn(layout, node, 'move')
245
+ : true));
246
+ }
247
+ /** Test every affected tab, including policy on empty regions. */
248
+ canNode(nodeId, capability) {
249
+ const node = findNode(this.state.root, nodeId);
250
+ return !!node && this.canNodeIn(this.state, node, capability);
251
+ }
252
+ permitNode(layout, node, capability, options) {
253
+ if (options.source === 'user' && !this.canNodeIn(layout, node, capability))
254
+ problem(`${capability} is disabled for ${node.id}`);
182
255
  }
183
256
  load(input) {
184
257
  this.commit('load', (draft) => {
@@ -226,7 +299,7 @@ export class LayoutStore {
226
299
  const n = findNode(d.root, splitId);
227
300
  if (n?.kind !== 'split')
228
301
  problem('Split not found');
229
- this.permit(d, paneIds(n), 'resize', options);
302
+ this.permitNode(d, n, 'resize', options);
230
303
  n.ratio = ratio;
231
304
  });
232
305
  }
@@ -237,22 +310,22 @@ export class LayoutStore {
237
310
  const node = findNode(d.root, id);
238
311
  if (node?.kind !== 'split')
239
312
  problem('Split not found');
240
- this.permit(d, paneIds(node), 'resize', options);
313
+ this.permitNode(d, node, 'resize', options);
241
314
  node.ratio = ratio;
242
315
  }
243
316
  });
244
317
  }
245
- maximize(groupId) {
318
+ maximize(groupId, options = {}) {
246
319
  this.commit('maximize', (d) => {
247
320
  if (groupId)
248
- this.group(d, groupId);
321
+ this.permitNode(d, this.group(d, groupId), 'maximize', options);
249
322
  d.maximized = groupId;
250
323
  });
251
324
  }
252
325
  add(pane, groupId, options = {}) {
253
326
  this.commit('add', (d) => {
254
327
  const g = this.group(d, groupId);
255
- this.permit(d, g.panes, 'move', options);
328
+ this.permitNode(d, g, 'addTab', options);
256
329
  if (Object.hasOwn(d.panes, pane.id))
257
330
  problem('Pane id already exists');
258
331
  Object.defineProperty(d.panes, pane.id, {
@@ -275,7 +348,7 @@ export class LayoutStore {
275
348
  let created = '';
276
349
  this.commit('split', (d) => {
277
350
  const g = this.group(d, groupId);
278
- this.permit(d, g.panes, 'split', options);
351
+ this.permitNode(d, g, 'split', options);
279
352
  if (pane) {
280
353
  if (Object.hasOwn(d.panes, pane.id))
281
354
  problem('Pane id already exists');
@@ -304,13 +377,14 @@ export class LayoutStore {
304
377
  return created;
305
378
  }
306
379
  /** Cancel only an unfilled region; never roll back edits made elsewhere. */
307
- removeEmptyGroup(groupId) {
380
+ removeEmptyGroup(groupId, options = {}) {
308
381
  const existing = findNode(this.state.root, groupId);
309
382
  if (existing?.kind !== 'group' ||
310
383
  existing.panes.length ||
311
384
  !findParent(this.state.root, groupId))
312
385
  return;
313
386
  this.commit('removeEmptyGroup', (d) => {
387
+ this.permitNode(d, this.group(d, groupId), 'close', options);
314
388
  if (d.maximized === groupId)
315
389
  d.maximized = null;
316
390
  const parent = findParent(d.root, groupId);
@@ -324,9 +398,11 @@ export class LayoutStore {
324
398
  const source = groups(d.root).find((g) => g.panes.includes(paneId));
325
399
  if (!source)
326
400
  problem('Return a popped-out pane before moving it');
327
- this.permit(d, [paneId, ...target.panes], 'move', options);
401
+ const capability = source === target && position === 'tab' ? 'reorder' : 'move';
402
+ this.permit(d, [paneId], capability, options);
403
+ this.permitNode(d, target, capability, options);
328
404
  if (position !== 'tab')
329
- this.permit(d, target.panes, 'split', options);
405
+ this.permitNode(d, target, 'split', options);
330
406
  if (source === target && target.panes.length === 1)
331
407
  return;
332
408
  this.detach(d, paneId);
@@ -354,7 +430,7 @@ export class LayoutStore {
354
430
  const g = this.group(d, groupId), parent = findParent(d.root, groupId);
355
431
  if (!parent)
356
432
  return;
357
- this.permit(d, paneIds(parent), 'join', options);
433
+ this.permitNode(d, parent, 'join', options);
358
434
  g.panes = paneIds(parent);
359
435
  g.active ??= g.panes[0] ?? null;
360
436
  this.replace(d, parent, g);
@@ -365,7 +441,7 @@ export class LayoutStore {
365
441
  closeGroup(groupId, options = {}) {
366
442
  this.commit('closeGroup', (d) => {
367
443
  const group = this.group(d, groupId);
368
- this.permit(d, group.panes, 'close', options);
444
+ this.permitNode(d, group, 'close', options);
369
445
  for (const id of group.panes)
370
446
  delete d.panes[id];
371
447
  group.panes = [];
@@ -386,7 +462,7 @@ export class LayoutStore {
386
462
  problem('Join requires contiguous regions in one row or column');
387
463
  const { row, regions, boundaries, start, end, selected } = range;
388
464
  const panes = selected.flatMap((g) => g.panes);
389
- this.permit(d, panes, 'join', options);
465
+ selected.forEach((group) => this.permitNode(d, group, 'join', options));
390
466
  let sizes = range.weights;
391
467
  let gaps = boundaries.map(() => 0);
392
468
  if (options.extents) {
@@ -1 +1 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { joinRange } from './join.js';\nimport { findNode, findParent, groups, paneIds, parseLayout, validate } from './model.js';\nimport { LayoutError } from './types.js';\nimport type {\n AutoCollapse,\n LayoutStoreOptions,\n JoinOptions,\n Axis,\n Capability,\n Change,\n CommandOptions,\n Group,\n Layout,\n Node,\n Pane,\n WindowPlacement,\n} from './types.js';\nconst freeze = <T>(value: T): T => {\n if (value && typeof value === 'object') {\n Object.freeze(value);\n Object.values(value).forEach(freeze);\n }\n return value;\n};\nfunction problem(message: string): never {\n throw new LayoutError([{ path: 'command', message }]);\n}\nexport class LayoutStore {\n private state: Layout;\n private initial: Layout;\n private listeners = new Set<(event: Change) => void>();\n private errors = new Set<(error: unknown) => void>();\n private disposed = false;\n private serial = 0;\n private closedTabs: { pane: Pane; groupId: string; index: number }[] = [];\n private notifying = false;\n private pending: Change[] = [];\n private autoCollapse: AutoCollapse = 'disabled';\n constructor(input: unknown, options: LayoutStoreOptions = {}) {\n this.setAutoCollapse(options.autoCollapse ?? 'disabled');\n this.state = freeze(parseLayout(input));\n this.initial = this.export();\n }\n /** Stable immutable snapshot, suitable for useSyncExternalStore. */\n getSnapshot = (): Layout => this.state;\n export(): Layout {\n return structuredClone(this.state);\n }\n subscribe = (listener: (event: Change) => void): (() => void) => {\n this.alive();\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n onError(listener: (error: unknown) => void): () => void {\n this.errors.add(listener);\n return () => {\n this.errors.delete(listener);\n };\n }\n private alive() {\n if (this.disposed) problem('Store has been disposed');\n }\n private report(error: unknown) {\n for (const listener of this.errors) {\n try {\n listener(error);\n } catch {\n /* A reporting callback cannot invalidate a committed layout. */\n }\n }\n }\n private commit(action: string, mutate: (draft: Layout) => void) {\n this.alive();\n let next: Layout;\n try {\n next = this.export();\n mutate(next);\n next = parseLayout(next);\n } catch (error) {\n this.report(error);\n throw error;\n }\n // Update session history only after validation, before notifying subscribers.\n if (action === 'load') this.closedTabs = [];\n if (action === 'close' || action === 'closeGroup') {\n for (const pane of Object.values(this.state.panes)) {\n if (Object.hasOwn(next.panes, pane.id)) continue;\n const group = groups(this.state.root).find((g) => g.panes.includes(pane.id));\n const detached = this.state.popouts.find((p) => p.paneId === pane.id);\n this.closedTabs.push({\n pane: structuredClone(pane),\n groupId: group?.id ?? detached!.groupId,\n index: group ? group.panes.indexOf(pane.id) : detached!.index,\n });\n }\n this.closedTabs = this.closedTabs.slice(-50);\n }\n if (action === 'restoreClosedTab') {\n this.closedTabs = this.closedTabs.filter(\n (entry) => !Object.hasOwn(next.panes, entry.pane.id),\n );\n }\n this.state = freeze(next);\n this.pending.push({ action, layout: this.state });\n if (this.notifying) return;\n this.notifying = true;\n try {\n while (this.pending.length) {\n const event = this.pending.shift()!;\n for (const listener of [...this.listeners]) {\n if (!this.listeners.has(listener)) continue;\n try {\n listener(event);\n } catch (error) {\n this.report(error);\n }\n }\n }\n } finally {\n this.notifying = false;\n }\n }\n\n private group(draft: Layout, id: string): Group {\n const n = findNode(draft.root, id);\n if (n?.kind !== 'group') problem('Group not found: ' + id);\n return n;\n }\n private pane(draft: Layout, id: string): Pane {\n if (!Object.hasOwn(draft.panes, id)) problem('Pane not found: ' + id);\n return draft.panes[id]!;\n }\n private permit(draft: Layout, ids: string[], cap: Capability, options: CommandOptions) {\n for (const id of ids)\n if (options.source === 'user' && this.pane(draft, id).capabilities?.[cap] === false)\n problem(`${cap} is disabled for ${id}`);\n }\n private id(draft: Layout): string {\n let id: string;\n do {\n id = `layout-${++this.serial}`;\n } while (findNode(draft.root, id));\n return id;\n }\n private replace(draft: Layout, old: Node, next: Node) {\n const parent = findParent(draft.root, old.id);\n if (parent) parent.children[parent.children[0].id === old.id ? 0 : 1] = next;\n else draft.root = next;\n }\n private detach(draft: Layout, id: string): Group {\n const g = groups(draft.root).find((n) => n.panes.includes(id));\n if (!g) problem('Pane is not docked: ' + id);\n const at = g.panes.indexOf(id);\n g.panes.splice(at, 1);\n if (g.active === id) g.active = g.panes[Math.min(at, g.panes.length - 1)] ?? null;\n return g;\n }\n getAutoCollapse(): AutoCollapse {\n return this.autoCollapse;\n }\n setAutoCollapse(mode: AutoCollapse): void {\n this.alive();\n if (!['enabled', 'protected', 'disabled'].includes(mode)) problem('Invalid autoCollapse mode');\n this.autoCollapse = mode;\n }\n private tidy(draft: Layout, source?: Group, popout = false) {\n if (\n source &&\n !source.panes.length &&\n this.autoCollapse !== 'disabled' &&\n (!popout || this.autoCollapse === 'enabled')\n ) {\n const parent = findParent(draft.root, source.id);\n if (parent)\n this.replace(draft, parent, parent.children[parent.children[0].id === source.id ? 1 : 0]);\n }\n if (draft.maximized && !findNode(draft.root, draft.maximized)) draft.maximized = null;\n }\n can(paneId: string, capability: Capability): boolean {\n return (\n Boolean(this.state.panes[paneId]) &&\n this.state.panes[paneId]!.capabilities?.[capability] !== false\n );\n }\n load(input: unknown) {\n this.commit('load', (draft) => {\n const next = parseLayout(input);\n for (const key of Object.keys(draft)) Reflect.deleteProperty(draft, key);\n Object.assign(draft, next);\n });\n }\n reset() {\n this.load(this.initial);\n }\n setTabDisplay(groupId: string, display: Group['tabDisplay']) {\n this.commit('setTabDisplay', (draft) => {\n const group = findNode(draft.root, groupId);\n if (!group || group.kind !== 'group') problem('Expected a group id');\n if (display === undefined) delete group.tabDisplay;\n else group.tabDisplay = display;\n });\n }\n setTabPlacement(groupId: string, placement: Group['tabPlacement']) {\n this.commit('setTabPlacement', (draft) => {\n const group = findNode(draft.root, groupId);\n if (!group || group.kind !== 'group') problem('Expected a group id');\n if (placement === undefined) delete group.tabPlacement;\n else group.tabPlacement = placement;\n });\n }\n activate(groupId: string, paneId: string) {\n this.commit('activate', (d) => {\n const g = this.group(d, groupId);\n if (!g.panes.includes(paneId)) problem('Tab does not belong to group');\n g.active = paneId;\n });\n }\n resize(splitId: string, ratio: number, options: CommandOptions = {}) {\n this.commit('resize', (d) => {\n const n = findNode(d.root, splitId);\n if (n?.kind !== 'split') problem('Split not found');\n this.permit(d, paneIds(n), 'resize', options);\n n.ratio = ratio;\n });\n }\n /** Atomically update coupled split ratios without intermediate layouts. */\n resizeMany(ratios: Record<string, number>, options: CommandOptions = {}) {\n this.commit('resize', (d) => {\n for (const [id, ratio] of Object.entries(ratios)) {\n const node = findNode(d.root, id);\n if (node?.kind !== 'split') problem('Split not found');\n this.permit(d, paneIds(node), 'resize', options);\n node.ratio = ratio;\n }\n });\n }\n maximize(groupId: string | null) {\n this.commit('maximize', (d) => {\n if (groupId) this.group(d, groupId);\n d.maximized = groupId;\n });\n }\n add(pane: Pane, groupId: string, options: CommandOptions = {}) {\n this.commit('add', (d) => {\n const g = this.group(d, groupId);\n this.permit(d, g.panes, 'move', options);\n if (Object.hasOwn(d.panes, pane.id)) problem('Pane id already exists');\n Object.defineProperty(d.panes, pane.id, {\n value: structuredClone(pane),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n g.panes.push(pane.id);\n g.active = pane.id;\n });\n }\n updatePane(pane: Pane) {\n this.commit('updatePane', (d) => {\n this.pane(d, pane.id);\n d.panes[pane.id] = structuredClone(pane);\n });\n }\n split(\n groupId: string,\n axis: Axis,\n pane: Pane | null,\n options: CommandOptions & { before?: boolean; ratio?: number } = {},\n ) {\n let created = '';\n this.commit('split', (d) => {\n const g = this.group(d, groupId);\n this.permit(d, g.panes, 'split', options);\n if (pane) {\n if (Object.hasOwn(d.panes, pane.id)) problem('Pane id already exists');\n Object.defineProperty(d.panes, pane.id, {\n value: structuredClone(pane),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n const group: Group = {\n kind: 'group',\n id: this.id(d),\n panes: pane ? [pane.id] : [],\n active: pane?.id ?? null,\n };\n created = group.id;\n this.replace(d, g, {\n kind: 'split',\n id: this.id(d),\n axis,\n ratio: options.ratio ?? 0.5,\n children: options.before ? [group, g] : [g, group],\n });\n });\n return created;\n }\n /** Cancel only an unfilled region; never roll back edits made elsewhere. */\n removeEmptyGroup(groupId: string) {\n const existing = findNode(this.state.root, groupId);\n if (\n existing?.kind !== 'group' ||\n existing.panes.length ||\n !findParent(this.state.root, groupId)\n )\n return;\n this.commit('removeEmptyGroup', (d) => {\n if (d.maximized === groupId) d.maximized = null;\n const parent = findParent(d.root, groupId)!;\n this.replace(d, parent, parent.children[parent.children[0].id === groupId ? 1 : 0]);\n });\n }\n /** Move to a tab group or to a new split at an edge. */\n move(\n paneId: string,\n groupId: string,\n position: 'tab' | 'left' | 'right' | 'top' | 'bottom' = 'tab',\n index?: number,\n options: CommandOptions = {},\n ) {\n this.commit('move', (d) => {\n const target = this.group(d, groupId);\n const source = groups(d.root).find((g) => g.panes.includes(paneId));\n if (!source) problem('Return a popped-out pane before moving it');\n this.permit(d, [paneId, ...target.panes], 'move', options);\n if (position !== 'tab') this.permit(d, target.panes, 'split', options);\n if (source === target && target.panes.length === 1) return;\n this.detach(d, paneId);\n if (position === 'tab') {\n target.panes.splice(\n Math.max(0, Math.min(index ?? target.panes.length, target.panes.length)),\n 0,\n paneId,\n );\n target.active = paneId;\n } else {\n const g: Group = { kind: 'group', id: this.id(d), panes: [paneId], active: paneId };\n const before = position === 'left' || position === 'top';\n this.replace(d, target, {\n kind: 'split',\n id: this.id(d),\n axis: position === 'left' || position === 'right' ? 'horizontal' : 'vertical',\n ratio: 0.5,\n children: before ? [g, target] : [target, g],\n });\n }\n this.tidy(d, source);\n });\n }\n /** Join the sibling region at this split, retaining its content as tabs. */\n join(groupId: string, options: CommandOptions = {}) {\n this.commit('join', (d) => {\n const g = this.group(d, groupId),\n parent = findParent(d.root, groupId);\n if (!parent) return;\n this.permit(d, paneIds(parent), 'join', options);\n g.panes = paneIds(parent);\n g.active ??= g.panes[0] ?? null;\n this.replace(d, parent, g);\n this.tidy(d);\n });\n }\n /** Close all docked tabs and remove their region in one atomic command. */\n closeGroup(groupId: string, options: CommandOptions = {}) {\n this.commit('closeGroup', (d) => {\n const group = this.group(d, groupId);\n this.permit(d, group.panes, 'close', options);\n for (const id of group.panes) delete d.panes[id];\n group.panes = [];\n group.active = null;\n if (d.maximized === groupId) d.maximized = null;\n const parent = findParent(d.root, groupId);\n if (parent)\n this.replace(d, parent, parent.children[parent.children[0].id === groupId ? 1 : 0]);\n });\n }\n /** Join a contiguous row/column range into the receiver, including both endpoints. */\n joinRegions(receiverId: string, otherId: string, options: JoinOptions = {}) {\n this.commit('join', (d) => {\n const receiver = this.group(d, receiverId);\n const range = joinRange(d.root, receiverId, otherId);\n if (!range) problem('Join requires contiguous regions in one row or column');\n const { row, regions, boundaries, start, end, selected } = range;\n const panes = selected.flatMap((g) => g.panes);\n this.permit(d, panes, 'join', options);\n let sizes = range.weights;\n let gaps = boundaries.map(() => 0);\n if (options.extents) {\n const extent = (node: Node): number => {\n const value = options.extents![node.id];\n if (value === undefined || !Number.isFinite(value) || value <= 0)\n problem('Join extents must include a positive finite size for every node in the row');\n return value;\n };\n sizes = regions.map(extent);\n gaps = boundaries.map((split) => {\n const gap = extent(split) - extent(split.children[0]) - extent(split.children[1]);\n if (gap < -0.5) problem('Join extents must describe a non-overlapping row');\n return Math.max(0, gap);\n });\n }\n receiver.panes = panes;\n receiver.active ??= panes[0] ?? null;\n const combined =\n sizes.slice(start, end + 1).reduce((a, b) => a + b, 0) +\n gaps.slice(start, end).reduce((a, b) => a + b, 0);\n const remaining = [...regions.slice(0, start), receiver, ...regions.slice(end + 1)];\n const lengths = [...sizes.slice(0, start), combined, ...sizes.slice(end + 1)];\n const dividers = [...boundaries.slice(0, start), ...boundaries.slice(end)];\n const remainingGaps = [...gaps.slice(0, start), ...gaps.slice(end)];\n // Reuse the surviving boundary IDs and their settings. Removed boundaries alone disappear.\n let replacement = remaining[remaining.length - 1]!;\n let length = lengths[lengths.length - 1]!;\n for (let i = remaining.length - 2; i >= 0; i--) {\n const first = lengths[i]!;\n replacement = {\n ...dividers[i]!,\n ratio: first / (first + length),\n children: [remaining[i]!, replacement],\n };\n length += first + remainingGaps[i]!;\n }\n this.replace(d, row, replacement);\n if (selected.some((g) => g.id === d.maximized)) d.maximized = receiver.id;\n this.tidy(d);\n });\n }\n close(paneId: string, options: CommandOptions = {}) {\n this.commit('close', (d) => {\n this.permit(d, [paneId], 'close', options);\n this.pane(d, paneId);\n let source: Group | undefined;\n if (d.popouts.some((p) => p.paneId === paneId))\n d.popouts = d.popouts.filter((p) => p.paneId !== paneId);\n else source = this.detach(d, paneId);\n delete d.panes[paneId];\n this.tidy(d, source);\n });\n }\n canRestoreClosedTab(): boolean {\n return this.closedTabs.some((entry) => !Object.hasOwn(this.state.panes, entry.pane.id));\n }\n /** Restore the latest closed tab without undoing unrelated layout changes. */\n restoreClosedTab(): void {\n this.alive();\n const entry = [...this.closedTabs]\n .reverse()\n .find((item) => !Object.hasOwn(this.state.panes, item.pane.id));\n if (!entry) return;\n this.commit('restoreClosedTab', (d) => {\n Object.defineProperty(d.panes, entry.pane.id, {\n value: structuredClone(entry.pane),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n this.dockPane(d, entry.pane.id, entry.groupId, entry.index);\n });\n }\n private dockPane(d: Layout, paneId: string, groupId: string, index: number) {\n const preferred = findNode(d.root, groupId);\n d.maximized = null;\n const candidates = [\n ...(preferred?.kind === 'group' ? [preferred] : []),\n ...groups(d.root).filter(\n (g) => g.id !== groupId && g.panes.every((id) => d.panes[id]!.header !== false),\n ),\n ];\n for (const target of candidates) {\n const previousActive = target.active;\n target.panes.splice(Math.min(index, target.panes.length), 0, paneId);\n target.active = paneId;\n if (!validate(d).length) return;\n target.panes.splice(target.panes.indexOf(paneId), 1);\n target.active = previousActive;\n }\n const g: Group = { kind: 'group', id: this.id(d), panes: [paneId], active: paneId };\n d.root = {\n kind: 'split',\n id: this.id(d),\n axis: 'horizontal',\n ratio: 0.7,\n children: [d.root, g],\n };\n }\n popout(paneId: string, placement?: WindowPlacement, options: CommandOptions = {}) {\n this.commit('popout', (d) => {\n this.permit(d, [paneId], 'popout', options);\n const group = groups(d.root).find((g) => g.panes.includes(paneId));\n if (!group) problem('Pane is not docked');\n const entry = {\n paneId,\n groupId: group.id,\n index: group.panes.indexOf(paneId),\n ...(placement ? { placement } : {}),\n };\n this.detach(d, paneId);\n d.popouts.push(entry);\n this.tidy(d, group, true);\n });\n }\n returnPane(paneId: string) {\n this.commit('return', (d) => {\n const entry = d.popouts.find((p) => p.paneId === paneId);\n if (!entry) return;\n d.popouts = d.popouts.filter((p) => p.paneId !== paneId);\n this.dockPane(d, paneId, entry.groupId, entry.index);\n });\n }\n dispose() {\n this.closedTabs = [];\n this.listeners.clear();\n this.errors.clear();\n this.pending = [];\n this.disposed = true;\n }\n}\n"]}
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { joinRange } from './join.js';\nimport { findNode, findParent, groups, paneIds, parseLayout, validate } from './model.js';\nimport { LayoutError } from './types.js';\nimport type {\n AutoCollapse,\n LayoutStoreOptions,\n JoinOptions,\n Axis,\n Capability,\n CapabilityPolicy,\n Change,\n CommandOptions,\n Group,\n Layout,\n Node,\n Pane,\n WindowPlacement,\n} from './types.js';\nconst freeze = <T>(value: T): T => {\n if (value && typeof value === 'object') {\n Object.freeze(value);\n Object.values(value).forEach(freeze);\n }\n return value;\n};\nfunction problem(message: string): never {\n throw new LayoutError([{ path: 'command', message }]);\n}\nexport class LayoutStore {\n private state: Layout;\n private initial: Layout;\n private listeners = new Set<(event: Change) => void>();\n private errors = new Set<(error: unknown) => void>();\n private disposed = false;\n private serial = 0;\n private closedTabs: { pane: Pane; groupId: string; index: number }[] = [];\n private notifying = false;\n private pending: Change[] = [];\n private autoCollapse: AutoCollapse = 'disabled';\n private capabilities: CapabilityPolicy = {};\n constructor(input: unknown, options: LayoutStoreOptions = {}) {\n this.setCapabilities(options.capabilities);\n this.setAutoCollapse(options.autoCollapse ?? 'disabled');\n this.state = freeze(parseLayout(input));\n this.initial = this.export();\n }\n /** Stable immutable snapshot, suitable for useSyncExternalStore. */\n getSnapshot = (): Layout => this.state;\n export(): Layout {\n return structuredClone(this.state);\n }\n subscribe = (listener: (event: Change) => void): (() => void) => {\n this.alive();\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n onError(listener: (error: unknown) => void): () => void {\n this.errors.add(listener);\n return () => {\n this.errors.delete(listener);\n };\n }\n private alive() {\n if (this.disposed) problem('Store has been disposed');\n }\n private report(error: unknown) {\n for (const listener of this.errors) {\n try {\n listener(error);\n } catch {\n /* A reporting callback cannot invalidate a committed layout. */\n }\n }\n }\n private commit(action: string, mutate: (draft: Layout) => void) {\n this.alive();\n let next: Layout;\n try {\n next = this.export();\n mutate(next);\n next = parseLayout(next);\n } catch (error) {\n this.report(error);\n throw error;\n }\n // Update session history only after validation, before notifying subscribers.\n if (action === 'load') this.closedTabs = [];\n if (action === 'close' || action === 'closeGroup') {\n for (const pane of Object.values(this.state.panes)) {\n if (Object.hasOwn(next.panes, pane.id)) continue;\n const group = groups(this.state.root).find((g) => g.panes.includes(pane.id));\n const detached = this.state.popouts.find((p) => p.paneId === pane.id);\n this.closedTabs.push({\n pane: structuredClone(pane),\n groupId: group?.id ?? detached!.groupId,\n index: group ? group.panes.indexOf(pane.id) : detached!.index,\n });\n }\n this.closedTabs = this.closedTabs.slice(-50);\n }\n if (action === 'restoreClosedTab') {\n this.closedTabs = this.closedTabs.filter(\n (entry) => !Object.hasOwn(next.panes, entry.pane.id),\n );\n }\n this.state = freeze(next);\n this.pending.push({ action, layout: this.state });\n if (this.notifying) return;\n this.notifying = true;\n try {\n while (this.pending.length) {\n const event = this.pending.shift()!;\n for (const listener of [...this.listeners]) {\n if (!this.listeners.has(listener)) continue;\n try {\n listener(event);\n } catch (error) {\n this.report(error);\n }\n }\n }\n } finally {\n this.notifying = false;\n }\n }\n\n private group(draft: Layout, id: string): Group {\n const n = findNode(draft.root, id);\n if (n?.kind !== 'group') problem('Group not found: ' + id);\n return n;\n }\n private pane(draft: Layout, id: string): Pane {\n if (!Object.hasOwn(draft.panes, id)) problem('Pane not found: ' + id);\n return draft.panes[id]!;\n }\n private permit(draft: Layout, ids: string[], cap: Capability, options: CommandOptions) {\n for (const id of ids)\n if (options.source === 'user' && !this.canPane(draft, id, cap))\n problem(`${cap} is disabled for ${id}`);\n }\n private id(draft: Layout): string {\n let id: string;\n do {\n id = `layout-${++this.serial}`;\n } while (findNode(draft.root, id));\n return id;\n }\n private replace(draft: Layout, old: Node, next: Node) {\n const parent = findParent(draft.root, old.id);\n if (parent) parent.children[parent.children[0].id === old.id ? 0 : 1] = next;\n else draft.root = next;\n }\n private detach(draft: Layout, id: string): Group {\n const g = groups(draft.root).find((n) => n.panes.includes(id));\n if (!g) problem('Pane is not docked: ' + id);\n const at = g.panes.indexOf(id);\n g.panes.splice(at, 1);\n if (g.active === id) g.active = g.panes[Math.min(at, g.panes.length - 1)] ?? null;\n return g;\n }\n getAutoCollapse(): AutoCollapse {\n return this.autoCollapse;\n }\n setAutoCollapse(mode: AutoCollapse): void {\n this.alive();\n if (!['enabled', 'protected', 'disabled'].includes(mode)) problem('Invalid autoCollapse mode');\n this.autoCollapse = mode;\n }\n private tidy(draft: Layout, source?: Group, popout = false) {\n if (\n source &&\n !source.panes.length &&\n this.autoCollapse !== 'disabled' &&\n (!popout || this.autoCollapse === 'enabled')\n ) {\n const parent = findParent(draft.root, source.id);\n if (parent)\n this.replace(draft, parent, parent.children[parent.children[0].id === source.id ? 1 : 0]);\n }\n if (draft.maximized && !findNode(draft.root, draft.maximized)) draft.maximized = null;\n }\n /** Replace session policy; layout export/load never serializes or resets it. */\n setCapabilities(policy: CapabilityPolicy = {}): void {\n this.alive();\n const flags = (value: unknown) => {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n problem('Invalid capabilities');\n for (const [key, flag] of Object.entries(value!))\n if (\n ![\n 'resize',\n 'move',\n 'reorder',\n 'addTab',\n 'maximize',\n 'split',\n 'join',\n 'close',\n 'popout',\n ].includes(key) ||\n typeof flag !== 'boolean'\n )\n problem('Invalid capability: ' + key);\n };\n if (!policy || typeof policy !== 'object' || Array.isArray(policy))\n problem('Invalid capability policy');\n for (const [key, value] of Object.entries(policy)) {\n if (value === undefined) continue;\n if (key === 'defaults') flags(value);\n else if (key === 'groups' || key === 'panes') {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n problem('Invalid capability overrides');\n Object.values(value).forEach(flags);\n } else problem('Unknown capability scope: ' + key);\n }\n this.capabilities = structuredClone(policy);\n }\n private canPane(layout: Layout, paneId: string, capability: Capability): boolean {\n const pane = layout.panes[paneId];\n if (!pane) return false;\n const groupId =\n groups(layout.root).find((g) => g.panes.includes(paneId))?.id ??\n layout.popouts.find((p) => p.paneId === paneId)?.groupId;\n return (\n this.capabilities.panes?.[paneId]?.[capability] ??\n pane.capabilities?.[capability] ??\n (groupId ? this.capabilities.groups?.[groupId]?.[capability] : undefined) ??\n this.capabilities.defaults?.[capability] ??\n (capability === 'addTab' || capability === 'reorder'\n ? this.canPane(layout, paneId, 'move')\n : true)\n );\n }\n can(paneId: string, capability: Capability): boolean {\n return this.canPane(this.state, paneId, capability);\n }\n private canNodeIn(layout: Layout, node: Node, capability: Capability): boolean {\n if (node.kind === 'split')\n return node.children.every((child) => this.canNodeIn(layout, child, capability));\n return node.panes.length\n ? node.panes.every((id) => this.canPane(layout, id, capability))\n : (this.capabilities.groups?.[node.id]?.[capability] ??\n this.capabilities.defaults?.[capability] ??\n (capability === 'addTab' || capability === 'reorder'\n ? this.canNodeIn(layout, node, 'move')\n : true));\n }\n /** Test every affected tab, including policy on empty regions. */\n canNode(nodeId: string, capability: Capability): boolean {\n const node = findNode(this.state.root, nodeId);\n return !!node && this.canNodeIn(this.state, node, capability);\n }\n private permitNode(layout: Layout, node: Node, capability: Capability, options: CommandOptions) {\n if (options.source === 'user' && !this.canNodeIn(layout, node, capability))\n problem(`${capability} is disabled for ${node.id}`);\n }\n load(input: unknown) {\n this.commit('load', (draft) => {\n const next = parseLayout(input);\n for (const key of Object.keys(draft)) Reflect.deleteProperty(draft, key);\n Object.assign(draft, next);\n });\n }\n reset() {\n this.load(this.initial);\n }\n setTabDisplay(groupId: string, display: Group['tabDisplay']) {\n this.commit('setTabDisplay', (draft) => {\n const group = findNode(draft.root, groupId);\n if (!group || group.kind !== 'group') problem('Expected a group id');\n if (display === undefined) delete group.tabDisplay;\n else group.tabDisplay = display;\n });\n }\n setTabPlacement(groupId: string, placement: Group['tabPlacement']) {\n this.commit('setTabPlacement', (draft) => {\n const group = findNode(draft.root, groupId);\n if (!group || group.kind !== 'group') problem('Expected a group id');\n if (placement === undefined) delete group.tabPlacement;\n else group.tabPlacement = placement;\n });\n }\n activate(groupId: string, paneId: string) {\n this.commit('activate', (d) => {\n const g = this.group(d, groupId);\n if (!g.panes.includes(paneId)) problem('Tab does not belong to group');\n g.active = paneId;\n });\n }\n resize(splitId: string, ratio: number, options: CommandOptions = {}) {\n this.commit('resize', (d) => {\n const n = findNode(d.root, splitId);\n if (n?.kind !== 'split') problem('Split not found');\n this.permitNode(d, n, 'resize', options);\n n.ratio = ratio;\n });\n }\n /** Atomically update coupled split ratios without intermediate layouts. */\n resizeMany(ratios: Record<string, number>, options: CommandOptions = {}) {\n this.commit('resize', (d) => {\n for (const [id, ratio] of Object.entries(ratios)) {\n const node = findNode(d.root, id);\n if (node?.kind !== 'split') problem('Split not found');\n this.permitNode(d, node, 'resize', options);\n node.ratio = ratio;\n }\n });\n }\n maximize(groupId: string | null, options: CommandOptions = {}) {\n this.commit('maximize', (d) => {\n if (groupId) this.permitNode(d, this.group(d, groupId), 'maximize', options);\n d.maximized = groupId;\n });\n }\n add(pane: Pane, groupId: string, options: CommandOptions = {}) {\n this.commit('add', (d) => {\n const g = this.group(d, groupId);\n this.permitNode(d, g, 'addTab', options);\n if (Object.hasOwn(d.panes, pane.id)) problem('Pane id already exists');\n Object.defineProperty(d.panes, pane.id, {\n value: structuredClone(pane),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n g.panes.push(pane.id);\n g.active = pane.id;\n });\n }\n updatePane(pane: Pane) {\n this.commit('updatePane', (d) => {\n this.pane(d, pane.id);\n d.panes[pane.id] = structuredClone(pane);\n });\n }\n split(\n groupId: string,\n axis: Axis,\n pane: Pane | null,\n options: CommandOptions & { before?: boolean; ratio?: number } = {},\n ) {\n let created = '';\n this.commit('split', (d) => {\n const g = this.group(d, groupId);\n this.permitNode(d, g, 'split', options);\n if (pane) {\n if (Object.hasOwn(d.panes, pane.id)) problem('Pane id already exists');\n Object.defineProperty(d.panes, pane.id, {\n value: structuredClone(pane),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n const group: Group = {\n kind: 'group',\n id: this.id(d),\n panes: pane ? [pane.id] : [],\n active: pane?.id ?? null,\n };\n created = group.id;\n this.replace(d, g, {\n kind: 'split',\n id: this.id(d),\n axis,\n ratio: options.ratio ?? 0.5,\n children: options.before ? [group, g] : [g, group],\n });\n });\n return created;\n }\n /** Cancel only an unfilled region; never roll back edits made elsewhere. */\n removeEmptyGroup(groupId: string, options: CommandOptions = {}) {\n const existing = findNode(this.state.root, groupId);\n if (\n existing?.kind !== 'group' ||\n existing.panes.length ||\n !findParent(this.state.root, groupId)\n )\n return;\n this.commit('removeEmptyGroup', (d) => {\n this.permitNode(d, this.group(d, groupId), 'close', options);\n if (d.maximized === groupId) d.maximized = null;\n const parent = findParent(d.root, groupId)!;\n this.replace(d, parent, parent.children[parent.children[0].id === groupId ? 1 : 0]);\n });\n }\n /** Move to a tab group or to a new split at an edge. */\n move(\n paneId: string,\n groupId: string,\n position: 'tab' | 'left' | 'right' | 'top' | 'bottom' = 'tab',\n index?: number,\n options: CommandOptions = {},\n ) {\n this.commit('move', (d) => {\n const target = this.group(d, groupId);\n const source = groups(d.root).find((g) => g.panes.includes(paneId));\n if (!source) problem('Return a popped-out pane before moving it');\n const capability = source === target && position === 'tab' ? 'reorder' : 'move';\n this.permit(d, [paneId], capability, options);\n this.permitNode(d, target, capability, options);\n if (position !== 'tab') this.permitNode(d, target, 'split', options);\n if (source === target && target.panes.length === 1) return;\n this.detach(d, paneId);\n if (position === 'tab') {\n target.panes.splice(\n Math.max(0, Math.min(index ?? target.panes.length, target.panes.length)),\n 0,\n paneId,\n );\n target.active = paneId;\n } else {\n const g: Group = { kind: 'group', id: this.id(d), panes: [paneId], active: paneId };\n const before = position === 'left' || position === 'top';\n this.replace(d, target, {\n kind: 'split',\n id: this.id(d),\n axis: position === 'left' || position === 'right' ? 'horizontal' : 'vertical',\n ratio: 0.5,\n children: before ? [g, target] : [target, g],\n });\n }\n this.tidy(d, source);\n });\n }\n /** Join the sibling region at this split, retaining its content as tabs. */\n join(groupId: string, options: CommandOptions = {}) {\n this.commit('join', (d) => {\n const g = this.group(d, groupId),\n parent = findParent(d.root, groupId);\n if (!parent) return;\n this.permitNode(d, parent, 'join', options);\n g.panes = paneIds(parent);\n g.active ??= g.panes[0] ?? null;\n this.replace(d, parent, g);\n this.tidy(d);\n });\n }\n /** Close all docked tabs and remove their region in one atomic command. */\n closeGroup(groupId: string, options: CommandOptions = {}) {\n this.commit('closeGroup', (d) => {\n const group = this.group(d, groupId);\n this.permitNode(d, group, 'close', options);\n for (const id of group.panes) delete d.panes[id];\n group.panes = [];\n group.active = null;\n if (d.maximized === groupId) d.maximized = null;\n const parent = findParent(d.root, groupId);\n if (parent)\n this.replace(d, parent, parent.children[parent.children[0].id === groupId ? 1 : 0]);\n });\n }\n /** Join a contiguous row/column range into the receiver, including both endpoints. */\n joinRegions(receiverId: string, otherId: string, options: JoinOptions = {}) {\n this.commit('join', (d) => {\n const receiver = this.group(d, receiverId);\n const range = joinRange(d.root, receiverId, otherId);\n if (!range) problem('Join requires contiguous regions in one row or column');\n const { row, regions, boundaries, start, end, selected } = range;\n const panes = selected.flatMap((g) => g.panes);\n selected.forEach((group) => this.permitNode(d, group, 'join', options));\n let sizes = range.weights;\n let gaps = boundaries.map(() => 0);\n if (options.extents) {\n const extent = (node: Node): number => {\n const value = options.extents![node.id];\n if (value === undefined || !Number.isFinite(value) || value <= 0)\n problem('Join extents must include a positive finite size for every node in the row');\n return value;\n };\n sizes = regions.map(extent);\n gaps = boundaries.map((split) => {\n const gap = extent(split) - extent(split.children[0]) - extent(split.children[1]);\n if (gap < -0.5) problem('Join extents must describe a non-overlapping row');\n return Math.max(0, gap);\n });\n }\n receiver.panes = panes;\n receiver.active ??= panes[0] ?? null;\n const combined =\n sizes.slice(start, end + 1).reduce((a, b) => a + b, 0) +\n gaps.slice(start, end).reduce((a, b) => a + b, 0);\n const remaining = [...regions.slice(0, start), receiver, ...regions.slice(end + 1)];\n const lengths = [...sizes.slice(0, start), combined, ...sizes.slice(end + 1)];\n const dividers = [...boundaries.slice(0, start), ...boundaries.slice(end)];\n const remainingGaps = [...gaps.slice(0, start), ...gaps.slice(end)];\n // Reuse the surviving boundary IDs and their settings. Removed boundaries alone disappear.\n let replacement = remaining[remaining.length - 1]!;\n let length = lengths[lengths.length - 1]!;\n for (let i = remaining.length - 2; i >= 0; i--) {\n const first = lengths[i]!;\n replacement = {\n ...dividers[i]!,\n ratio: first / (first + length),\n children: [remaining[i]!, replacement],\n };\n length += first + remainingGaps[i]!;\n }\n this.replace(d, row, replacement);\n if (selected.some((g) => g.id === d.maximized)) d.maximized = receiver.id;\n this.tidy(d);\n });\n }\n close(paneId: string, options: CommandOptions = {}) {\n this.commit('close', (d) => {\n this.permit(d, [paneId], 'close', options);\n this.pane(d, paneId);\n let source: Group | undefined;\n if (d.popouts.some((p) => p.paneId === paneId))\n d.popouts = d.popouts.filter((p) => p.paneId !== paneId);\n else source = this.detach(d, paneId);\n delete d.panes[paneId];\n this.tidy(d, source);\n });\n }\n canRestoreClosedTab(): boolean {\n return this.closedTabs.some((entry) => !Object.hasOwn(this.state.panes, entry.pane.id));\n }\n /** Restore the latest closed tab without undoing unrelated layout changes. */\n restoreClosedTab(): void {\n this.alive();\n const entry = [...this.closedTabs]\n .reverse()\n .find((item) => !Object.hasOwn(this.state.panes, item.pane.id));\n if (!entry) return;\n this.commit('restoreClosedTab', (d) => {\n Object.defineProperty(d.panes, entry.pane.id, {\n value: structuredClone(entry.pane),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n this.dockPane(d, entry.pane.id, entry.groupId, entry.index);\n });\n }\n private dockPane(d: Layout, paneId: string, groupId: string, index: number) {\n const preferred = findNode(d.root, groupId);\n d.maximized = null;\n const candidates = [\n ...(preferred?.kind === 'group' ? [preferred] : []),\n ...groups(d.root).filter(\n (g) => g.id !== groupId && g.panes.every((id) => d.panes[id]!.header !== false),\n ),\n ];\n for (const target of candidates) {\n const previousActive = target.active;\n target.panes.splice(Math.min(index, target.panes.length), 0, paneId);\n target.active = paneId;\n if (!validate(d).length) return;\n target.panes.splice(target.panes.indexOf(paneId), 1);\n target.active = previousActive;\n }\n const g: Group = { kind: 'group', id: this.id(d), panes: [paneId], active: paneId };\n d.root = {\n kind: 'split',\n id: this.id(d),\n axis: 'horizontal',\n ratio: 0.7,\n children: [d.root, g],\n };\n }\n popout(paneId: string, placement?: WindowPlacement, options: CommandOptions = {}) {\n this.commit('popout', (d) => {\n this.permit(d, [paneId], 'popout', options);\n const group = groups(d.root).find((g) => g.panes.includes(paneId));\n if (!group) problem('Pane is not docked');\n const entry = {\n paneId,\n groupId: group.id,\n index: group.panes.indexOf(paneId),\n ...(placement ? { placement } : {}),\n };\n this.detach(d, paneId);\n d.popouts.push(entry);\n this.tidy(d, group, true);\n });\n }\n returnPane(paneId: string) {\n this.commit('return', (d) => {\n const entry = d.popouts.find((p) => p.paneId === paneId);\n if (!entry) return;\n d.popouts = d.popouts.filter((p) => p.paneId !== paneId);\n this.dockPane(d, paneId, entry.groupId, entry.index);\n });\n }\n dispose() {\n this.closedTabs = [];\n this.listeners.clear();\n this.errors.clear();\n this.pending = [];\n this.disposed = true;\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { AutoCollapse, LayoutStoreOptions, Json, Capability, Axis, Pane, Group, Split, Node, WindowPlacement, Popout, Layout, Issue, CommandOptions, Change, Bounds, JoinOptions, } from './types.js';
1
+ export type { AutoCollapse, LayoutStoreOptions, Json, Capability, CapabilityPolicy, Axis, Pane, Group, Split, Node, WindowPlacement, Popout, Layout, Issue, CommandOptions, Change, Bounds, JoinOptions, } from './types.js';
2
2
  export { LayoutError } from './types.js';
3
3
  export { LayoutStore } from './controller.js';
4
4
  export { createLayout, validate, parseLayout, findNode, findParent, groups, paneIds, DIVIDER, bounds, allocate, } from './model.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAI,EACJ,eAAe,EACf,MAAM,EACN,MAAM,EACN,KAAK,EACL,cAAc,EACd,MAAM,EACN,MAAM,EACN,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,IAAI,EACJ,UAAU,EACV,gBAAgB,EAChB,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAI,EACJ,eAAe,EACf,MAAM,EACN,MAAM,EACN,KAAK,EACL,cAAc,EACd,MAAM,EACN,MAAM,EACN,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export type {\n AutoCollapse,\n LayoutStoreOptions,\n Json,\n Capability,\n Axis,\n Pane,\n Group,\n Split,\n Node,\n WindowPlacement,\n Popout,\n Layout,\n Issue,\n CommandOptions,\n Change,\n Bounds,\n JoinOptions,\n} from './types.js';\nexport { LayoutError } from './types.js';\nexport { LayoutStore } from './controller.js';\nexport {\n createLayout,\n validate,\n parseLayout,\n findNode,\n findParent,\n groups,\n paneIds,\n DIVIDER,\n bounds,\n allocate,\n} from './model.js';\nexport { joinRange } from './join.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export type {\n AutoCollapse,\n LayoutStoreOptions,\n Json,\n Capability,\n CapabilityPolicy,\n Axis,\n Pane,\n Group,\n Split,\n Node,\n WindowPlacement,\n Popout,\n Layout,\n Issue,\n CommandOptions,\n Change,\n Bounds,\n JoinOptions,\n} from './types.js';\nexport { LayoutError } from './types.js';\nexport { LayoutStore } from './controller.js';\nexport {\n createLayout,\n validate,\n parseLayout,\n findNode,\n findParent,\n groups,\n paneIds,\n DIVIDER,\n bounds,\n allocate,\n} from './model.js';\nexport { joinRange } from './join.js';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAQ,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAoBjF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,CAwJhD;AACD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIlD;AACD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAMjE;AACD,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,YAAY,EAAE,KAAK,GAAG,SAAS,CAKzF;AACD,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,EAAE,CAE1C;AACD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAE5C;AASD,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,iGAAiG;AACjG,wBAAgB,MAAM,CACpB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,MAAM,GAC3D,MAAM,CA0BR;AACD,+FAA+F;AAC/F,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,SAAU,GACZ,CAAC,MAAM,EAAE,MAAM,CAAC,CAOlB;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CASpF"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAQ,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAoBjF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,CAkKhD;AACD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIlD;AACD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAMjE;AACD,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,YAAY,EAAE,KAAK,GAAG,SAAS,CAKzF;AACD,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,EAAE,CAE1C;AACD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAE5C;AASD,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,iGAAiG;AACjG,wBAAgB,MAAM,CACpB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,MAAM,GAC3D,MAAM,CA0BR;AACD,+FAA+F;AAC/F,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,SAAU,GACZ,CAAC,MAAM,EAAE,MAAM,CAAC,CAOlB;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CASpF"}
package/dist/model.js CHANGED
@@ -52,7 +52,17 @@ export function validate(input) {
52
52
  fail(`panes.${id}.capabilities`, 'Expected object');
53
53
  else
54
54
  for (const [key, value] of Object.entries(pane.capabilities))
55
- if (!['resize', 'move', 'split', 'join', 'close', 'popout'].includes(key) ||
55
+ if (![
56
+ 'resize',
57
+ 'move',
58
+ 'reorder',
59
+ 'addTab',
60
+ 'maximize',
61
+ 'split',
62
+ 'join',
63
+ 'close',
64
+ 'popout',
65
+ ].includes(key) ||
56
66
  typeof value !== 'boolean')
57
67
  fail(`panes.${id}.capabilities.${key}`, 'Unknown capability or non-boolean flag');
58
68
  }
package/dist/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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","sourcesContent":["import { LayoutError } from './types.js';\nimport type { Bounds, Group, Issue, Json, Layout, Node, Pane } from './types.js';\nconst record = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\nconst finite = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);\nfunction isJson(v: unknown, seen = new Set<unknown>(), depth = 0): v is Json {\n if (depth > 256) return false;\n if (v === null || typeof v === 'string' || typeof v === 'boolean') return true;\n if (typeof v === 'number') return Number.isFinite(v);\n if (typeof v !== 'object' || seen.has(v)) return false;\n if (\n !Array.isArray(v) &&\n Object.getPrototypeOf(v) !== Object.prototype &&\n Object.getPrototypeOf(v) !== null\n )\n return false;\n seen.add(v);\n const result = Object.values(v).every((x) => isJson(x, seen, depth + 1));\n seen.delete(v);\n return result;\n}\nexport function validate(input: unknown): Issue[] {\n const errors: Issue[] = [];\n const fail = (path: string, message: string) => {\n errors.push({ path, message });\n };\n if (!record(input) || !isJson(input))\n return [{ path: '$', message: 'Expected a finite, acyclic JSON object' }];\n if (input.version !== 1) fail('version', 'Expected version 1');\n if (!record(input.panes))\n return [...errors, { path: 'panes', message: 'Expected pane dictionary' }];\n const panes = input.panes;\n for (const [id, pane] of Object.entries(panes)) {\n if (\n !record(pane) ||\n pane.id !== id ||\n !id ||\n typeof pane.type !== 'string' ||\n !pane.type ||\n typeof pane.title !== 'string'\n ) {\n fail(`panes.${id}`, 'Expected matching id, type, and title');\n continue;\n }\n if (pane.confirmClose !== undefined && typeof pane.confirmClose !== 'boolean')\n fail(`panes.${id}.confirmClose`, 'Expected boolean');\n if (pane.icon !== undefined && typeof pane.icon !== 'string')\n fail(`panes.${id}.icon`, 'Expected string');\n if (pane.header !== undefined && typeof pane.header !== 'boolean')\n fail(`panes.${id}.header`, 'Expected boolean');\n if (pane.capabilities !== undefined) {\n if (!record(pane.capabilities)) fail(`panes.${id}.capabilities`, 'Expected object');\n else\n for (const [key, value] of Object.entries(pane.capabilities))\n if (\n !['resize', 'move', 'split', 'join', 'close', 'popout'].includes(key) ||\n typeof value !== 'boolean'\n )\n fail(`panes.${id}.capabilities.${key}`, 'Unknown capability or non-boolean flag');\n }\n if (pane.size !== undefined) {\n if (!record(pane.size)) fail(`panes.${id}.size`, 'Expected object');\n else {\n for (const [key, value] of Object.entries(pane.size))\n if (\n !['minWidth', 'maxWidth', 'minHeight', 'maxHeight'].includes(key) ||\n !finite(value) ||\n value < 0\n )\n fail(`panes.${id}.size.${key}`, 'Expected nonnegative finite size');\n for (const axis of ['Width', 'Height'])\n if (\n finite(pane.size['min' + axis]) &&\n finite(pane.size['max' + axis]) &&\n Number(pane.size['min' + axis]) > Number(pane.size['max' + axis])\n )\n fail(`panes.${id}.size`, 'Minimum exceeds maximum');\n }\n }\n }\n const ids = new Set<string>();\n const assigned = new Set<string>();\n const groups = new Set<string>();\n const use = (id: unknown, path: string) => {\n if (typeof id !== 'string' || !Object.hasOwn(panes, id)) fail(path, 'Unknown pane');\n else if (assigned.has(id)) fail(path, 'Pane is placed more than once');\n else assigned.add(id);\n };\n function walk(node: unknown, path: string, depth: number) {\n if (depth > 64) {\n fail(path, 'Maximum split depth is 64');\n return;\n }\n if (!record(node) || typeof node.id !== 'string' || !node.id) {\n fail(path, 'Expected node with id');\n return;\n }\n if (ids.has(node.id)) fail(path, 'Duplicate node id');\n ids.add(node.id);\n if (node.kind === 'group') {\n groups.add(node.id);\n if (\n node.tabDisplay !== undefined &&\n node.tabDisplay !== 'automatic' &&\n node.tabDisplay !== 'compact'\n )\n fail(path + '.tabDisplay', 'Expected automatic or compact');\n if (\n node.tabPlacement !== undefined &&\n node.tabPlacement !== 'top' &&\n node.tabPlacement !== 'left'\n )\n fail(path + '.tabPlacement', 'Expected top or left');\n if (!Array.isArray(node.panes)) {\n fail(path, 'Expected pane array');\n return;\n }\n node.panes.forEach((p, i) => use(p, `${path}.panes[${i}]`));\n if (node.panes.length ? !node.panes.includes(node.active) : node.active !== null)\n fail(path + '.active', 'Active tab must belong to group (or be null for empty group)');\n } else if (node.kind === 'split') {\n if (node.gap !== undefined && (!finite(node.gap) || node.gap < 0))\n fail(path + '.gap', 'Expected nonnegative divider space');\n if (!['horizontal', 'vertical'].includes(String(node.axis)))\n fail(path + '.axis', 'Expected horizontal or vertical');\n if (!finite(node.ratio) || node.ratio <= 0 || node.ratio >= 1)\n fail(path + '.ratio', 'Expected ratio between 0 and 1');\n if (!Array.isArray(node.children) || node.children.length !== 2)\n fail(path + '.children', 'Expected two children');\n else node.children.forEach((n, i) => walk(n, `${path}.children[${i}]`, depth + 1));\n } else fail(path + '.kind', 'Expected group or split');\n }\n walk(input.root, 'root', 0);\n if (!Array.isArray(input.popouts)) fail('popouts', 'Expected array');\n else\n input.popouts.forEach((p, i) => {\n const path = `popouts[${i}]`;\n if (!record(p)) {\n fail(path, 'Expected popout object');\n return;\n }\n use(p.paneId, path + '.paneId');\n if (typeof p.groupId !== 'string' || !Number.isInteger(p.index) || Number(p.index) < 0)\n fail(path, 'Expected return group id and nonnegative index');\n if (p.placement !== undefined) {\n if (!record(p.placement)) fail(path + '.placement', 'Expected placement object');\n else\n for (const [key, value] of Object.entries(p.placement))\n if (\n !['width', 'height', 'left', 'top'].includes(key) ||\n !finite(value) ||\n (['width', 'height'].includes(key) && value <= 0)\n )\n fail(path + '.placement.' + key, 'Invalid window placement');\n }\n });\n for (const id of Object.keys(panes))\n if (!assigned.has(id)) fail(`panes.${id}`, 'Pane has no placement');\n if (\n input.maximized !== null &&\n (typeof input.maximized !== 'string' || !groups.has(input.maximized))\n )\n fail('maximized', 'Expected a group id or null');\n if (!errors.length) {\n const check = (n: Node) => {\n const b = bounds(n, input as unknown as Layout);\n if (b.minWidth > b.maxWidth || b.minHeight > b.maxHeight)\n fail(n.id, 'Pane constraints cannot coexist in this region');\n if (n.kind === 'split') n.children.forEach(check);\n };\n check(input.root as unknown as Node);\n }\n return errors;\n}\nexport function parseLayout(input: unknown): Layout {\n const issues = validate(input);\n if (issues.length) throw new LayoutError(issues);\n return structuredClone(input) as Layout;\n}\nexport function findNode(root: Node, id: string): Node | undefined {\n return root.id === id\n ? root\n : root.kind === 'split'\n ? (findNode(root.children[0], id) ?? findNode(root.children[1], id))\n : undefined;\n}\nexport function findParent(root: Node, id: string): import('./types.js').Split | undefined {\n if (root.kind === 'group') return undefined;\n return root.children.some((n) => n.id === id)\n ? root\n : (findParent(root.children[0], id) ?? findParent(root.children[1], id));\n}\nexport function groups(root: Node): Group[] {\n return root.kind === 'group' ? [root] : root.children.flatMap(groups);\n}\nexport function paneIds(root: Node): string[] {\n return groups(root).flatMap((g) => g.panes);\n}\nfunction paneBounds(p: Pane): Bounds {\n return {\n minWidth: p.size?.minWidth ?? 0,\n maxWidth: p.size?.maxWidth ?? Infinity,\n minHeight: p.size?.minHeight ?? 0,\n maxHeight: p.size?.maxHeight ?? Infinity,\n };\n}\nexport const DIVIDER = 4;\n/** Aggregate model constraints, optionally resolving each group's bounds for a host renderer. */\nexport function bounds(\n node: Node,\n layout: Layout,\n resolveGroup?: (group: Group, constraints: Bounds) => Bounds,\n): Bounds {\n if (node.kind === 'group') {\n const values = node.panes.map((id) => paneBounds(layout.panes[id]!));\n const constraints = {\n minWidth: Math.max(0, ...values.map((b) => b.minWidth)),\n maxWidth: Math.min(Infinity, ...values.map((b) => b.maxWidth)),\n minHeight: Math.max(0, ...values.map((b) => b.minHeight)),\n maxHeight: Math.min(Infinity, ...values.map((b) => b.maxHeight)),\n };\n return resolveGroup ? resolveGroup(node, constraints) : constraints;\n }\n const a = bounds(node.children[0], layout, resolveGroup),\n b = bounds(node.children[1], layout, resolveGroup);\n return node.axis === 'horizontal'\n ? {\n minWidth: a.minWidth + b.minWidth + (node.gap ?? DIVIDER),\n maxWidth: a.maxWidth + b.maxWidth + (node.gap ?? DIVIDER),\n minHeight: Math.max(a.minHeight, b.minHeight),\n maxHeight: Math.max(a.maxHeight, b.maxHeight),\n }\n : {\n minHeight: a.minHeight + b.minHeight + (node.gap ?? DIVIDER),\n maxHeight: a.maxHeight + b.maxHeight + (node.gap ?? DIVIDER),\n minWidth: Math.max(a.minWidth, b.minWidth),\n maxWidth: Math.max(a.maxWidth, b.maxWidth),\n };\n}\n/** Returns content extents; overflow retains minimums, surplus beyond maximums stays empty. */\nexport function allocate(\n total: number,\n ratio: number,\n minA: number,\n maxA: number,\n minB: number,\n maxB: number,\n gap = DIVIDER,\n): [number, number] {\n const available = Math.max(total - gap, minA + minB);\n const used = Math.min(available, maxA + maxB);\n const low = Math.max(minA, used - maxB),\n high = Math.min(maxA, used - minB);\n const a = Math.max(low, Math.min(high, used * ratio));\n return [a, used - a];\n}\n\n/** Create independent, validated JSON for an empty or single-pane workspace. */\nexport function createLayout(options: { pane?: Pane; groupId?: string } = {}): Layout {\n const { pane, groupId = 'main' } = options;\n return parseLayout({\n version: 1,\n root: { kind: 'group', id: groupId, panes: pane ? [pane.id] : [], active: pane?.id ?? null },\n panes: pane ? { [pane.id]: pane } : {},\n popouts: [],\n maximized: null,\n });\n}\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,GAAG,CAAC,CAAU,EAAgC,EAAE,CAC1D,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3D,MAAM,MAAM,GAAG,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxF,SAAS,MAAM,CAAC,CAAU,EAAE,IAAI,GAAG,IAAI,GAAG,EAAW,EAAE,KAAK,GAAG,CAAC;IAC9D,IAAI,KAAK,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC/E,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACvD,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QACjB,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS;QAC7C,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI;QAEjC,OAAO,KAAK,CAAC;IACf,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACZ,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACzE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACf,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,EAAE;QAC7C,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAClC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC,CAAC;IAC5E,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC;QAAE,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QACtB,OAAO,CAAC,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAC7E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IACE,CAAC,MAAM,CAAC,IAAI,CAAC;YACb,IAAI,CAAC,EAAE,KAAK,EAAE;YACd,CAAC,EAAE;YACH,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC7B,CAAC,IAAI,CAAC,IAAI;YACV,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAC9B,CAAC;YACD,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,uCAAuC,CAAC,CAAC;YAC7D,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,SAAS;YAC3E,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,kBAAkB,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC1D,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS;YAC/D,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;gBAAE,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;;gBAElF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;oBAC1D,IACE,CAAC;wBACC,QAAQ;wBACR,MAAM;wBACN,SAAS;wBACT,QAAQ;wBACR,UAAU;wBACV,OAAO;wBACP,MAAM;wBACN,OAAO;wBACP,QAAQ;qBACT,CAAC,QAAQ,CAAC,GAAG,CAAC;wBACf,OAAO,KAAK,KAAK,SAAS;wBAE1B,IAAI,CAAC,SAAS,EAAE,iBAAiB,GAAG,EAAE,EAAE,wCAAwC,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;iBAC/D,CAAC;gBACJ,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;oBAClD,IACE,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;wBACjE,CAAC,MAAM,CAAC,KAAK,CAAC;wBACd,KAAK,GAAG,CAAC;wBAET,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,EAAE,kCAAkC,CAAC,CAAC;gBACxE,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;oBACpC,IACE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;wBAC/B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;wBAC/B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;wBAEjE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,yBAAyB,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,GAAG,GAAG,CAAC,EAAW,EAAE,IAAY,EAAE,EAAE;QACxC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;aAC/E,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;;YAClE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC;IACF,SAAS,IAAI,CAAC,IAAa,EAAE,IAAY,EAAE,KAAa;QACtD,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YAC7D,IAAI,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QACtD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpB,IACE,IAAI,CAAC,UAAU,KAAK,SAAS;gBAC7B,IAAI,CAAC,UAAU,KAAK,WAAW;gBAC/B,IAAI,CAAC,UAAU,KAAK,SAAS;gBAE7B,IAAI,CAAC,IAAI,GAAG,aAAa,EAAE,+BAA+B,CAAC,CAAC;YAC9D,IACE,IAAI,CAAC,YAAY,KAAK,SAAS;gBAC/B,IAAI,CAAC,YAAY,KAAK,KAAK;gBAC3B,IAAI,CAAC,YAAY,KAAK,MAAM;gBAE5B,IAAI,CAAC,IAAI,GAAG,eAAe,EAAE,sBAAsB,CAAC,CAAC;YACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,IAAI,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5D,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI;gBAC9E,IAAI,CAAC,IAAI,GAAG,SAAS,EAAE,8DAA8D,CAAC,CAAC;QAC3F,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;gBAC/D,IAAI,CAAC,IAAI,GAAG,MAAM,EAAE,oCAAoC,CAAC,CAAC;YAC5D,IAAI,CAAC,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzD,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,iCAAiC,CAAC,CAAC;YAC1D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC;gBAC3D,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,gCAAgC,CAAC,CAAC;YAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAC7D,IAAI,CAAC,IAAI,GAAG,WAAW,EAAE,uBAAuB,CAAC,CAAC;;gBAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QACrF,CAAC;;YAAM,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,yBAAyB,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;;QAEnE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;gBACrC,OAAO;YACT,CAAC;YACD,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC;YAChC,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;gBACpF,IAAI,CAAC,IAAI,EAAE,gDAAgD,CAAC,CAAC;YAC/D,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC9B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;oBAAE,IAAI,CAAC,IAAI,GAAG,YAAY,EAAE,2BAA2B,CAAC,CAAC;;oBAE/E,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;wBACpD,IACE,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;4BACjD,CAAC,MAAM,CAAC,KAAK,CAAC;4BACd,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;4BAEjD,IAAI,CAAC,IAAI,GAAG,aAAa,GAAG,GAAG,EAAE,0BAA0B,CAAC,CAAC;YACrE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACjC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,uBAAuB,CAAC,CAAC;IACtE,IACE,KAAK,CAAC,SAAS,KAAK,IAAI;QACxB,CAAC,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAErE,IAAI,CAAC,WAAW,EAAE,6BAA6B,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,CAAC,CAAO,EAAE,EAAE;YACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAA0B,CAAC,CAAC;YAChD,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;gBACtD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,gDAAgD,CAAC,CAAC;YAC/D,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;gBAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC;QACF,KAAK,CAAC,KAAK,CAAC,IAAuB,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD,OAAO,eAAe,CAAC,KAAK,CAAW,CAAC;AAC1C,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,IAAU,EAAE,EAAU;IAC7C,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE;QACnB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO;YACrB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpE,CAAC,CAAC,SAAS,CAAC;AAClB,CAAC;AACD,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,EAAU;IAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QAC3C,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7E,CAAC;AACD,MAAM,UAAU,MAAM,CAAC,IAAU;IAC/B,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACxE,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,IAAU;IAChC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC9C,CAAC;AACD,SAAS,UAAU,CAAC,CAAO;IACzB,OAAO;QACL,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,IAAI,CAAC;QAC/B,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,IAAI,QAAQ;QACtC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,IAAI,CAAC;QACjC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,IAAI,QAAQ;KACzC,CAAC;AACJ,CAAC;AACD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,iGAAiG;AACjG,MAAM,UAAU,MAAM,CACpB,IAAU,EACV,MAAc,EACd,YAA4D;IAE5D,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAE,CAAC,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG;YAClB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACvD,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC9D,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACzD,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;SACjE,CAAC;QACF,OAAO,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IACtE,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EACtD,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,IAAI,KAAK,YAAY;QAC/B,CAAC,CAAC;YACE,QAAQ,EAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC;YACzD,QAAQ,EAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC;YACzD,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC;YAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC;SAC9C;QACH,CAAC,CAAC;YACE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC;YAC5D,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC;YAC5D,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;YAC1C,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;SAC3C,CAAC;AACR,CAAC;AACD,+FAA+F;AAC/F,MAAM,UAAU,QAAQ,CACtB,KAAa,EACb,KAAa,EACb,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,IAAY,EACZ,GAAG,GAAG,OAAO;IAEb,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,EACrC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;AACvB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,OAAO,GAAsC,EAAE;IAC1E,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3C,OAAO,WAAW,CAAC;QACjB,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE;QAC5F,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;QACtC,OAAO,EAAE,EAAE;QACX,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { LayoutError } from './types.js';\nimport type { Bounds, Group, Issue, Json, Layout, Node, Pane } from './types.js';\nconst record = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\nconst finite = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);\nfunction isJson(v: unknown, seen = new Set<unknown>(), depth = 0): v is Json {\n if (depth > 256) return false;\n if (v === null || typeof v === 'string' || typeof v === 'boolean') return true;\n if (typeof v === 'number') return Number.isFinite(v);\n if (typeof v !== 'object' || seen.has(v)) return false;\n if (\n !Array.isArray(v) &&\n Object.getPrototypeOf(v) !== Object.prototype &&\n Object.getPrototypeOf(v) !== null\n )\n return false;\n seen.add(v);\n const result = Object.values(v).every((x) => isJson(x, seen, depth + 1));\n seen.delete(v);\n return result;\n}\nexport function validate(input: unknown): Issue[] {\n const errors: Issue[] = [];\n const fail = (path: string, message: string) => {\n errors.push({ path, message });\n };\n if (!record(input) || !isJson(input))\n return [{ path: '$', message: 'Expected a finite, acyclic JSON object' }];\n if (input.version !== 1) fail('version', 'Expected version 1');\n if (!record(input.panes))\n return [...errors, { path: 'panes', message: 'Expected pane dictionary' }];\n const panes = input.panes;\n for (const [id, pane] of Object.entries(panes)) {\n if (\n !record(pane) ||\n pane.id !== id ||\n !id ||\n typeof pane.type !== 'string' ||\n !pane.type ||\n typeof pane.title !== 'string'\n ) {\n fail(`panes.${id}`, 'Expected matching id, type, and title');\n continue;\n }\n if (pane.confirmClose !== undefined && typeof pane.confirmClose !== 'boolean')\n fail(`panes.${id}.confirmClose`, 'Expected boolean');\n if (pane.icon !== undefined && typeof pane.icon !== 'string')\n fail(`panes.${id}.icon`, 'Expected string');\n if (pane.header !== undefined && typeof pane.header !== 'boolean')\n fail(`panes.${id}.header`, 'Expected boolean');\n if (pane.capabilities !== undefined) {\n if (!record(pane.capabilities)) fail(`panes.${id}.capabilities`, 'Expected object');\n else\n for (const [key, value] of Object.entries(pane.capabilities))\n if (\n ![\n 'resize',\n 'move',\n 'reorder',\n 'addTab',\n 'maximize',\n 'split',\n 'join',\n 'close',\n 'popout',\n ].includes(key) ||\n typeof value !== 'boolean'\n )\n fail(`panes.${id}.capabilities.${key}`, 'Unknown capability or non-boolean flag');\n }\n if (pane.size !== undefined) {\n if (!record(pane.size)) fail(`panes.${id}.size`, 'Expected object');\n else {\n for (const [key, value] of Object.entries(pane.size))\n if (\n !['minWidth', 'maxWidth', 'minHeight', 'maxHeight'].includes(key) ||\n !finite(value) ||\n value < 0\n )\n fail(`panes.${id}.size.${key}`, 'Expected nonnegative finite size');\n for (const axis of ['Width', 'Height'])\n if (\n finite(pane.size['min' + axis]) &&\n finite(pane.size['max' + axis]) &&\n Number(pane.size['min' + axis]) > Number(pane.size['max' + axis])\n )\n fail(`panes.${id}.size`, 'Minimum exceeds maximum');\n }\n }\n }\n const ids = new Set<string>();\n const assigned = new Set<string>();\n const groups = new Set<string>();\n const use = (id: unknown, path: string) => {\n if (typeof id !== 'string' || !Object.hasOwn(panes, id)) fail(path, 'Unknown pane');\n else if (assigned.has(id)) fail(path, 'Pane is placed more than once');\n else assigned.add(id);\n };\n function walk(node: unknown, path: string, depth: number) {\n if (depth > 64) {\n fail(path, 'Maximum split depth is 64');\n return;\n }\n if (!record(node) || typeof node.id !== 'string' || !node.id) {\n fail(path, 'Expected node with id');\n return;\n }\n if (ids.has(node.id)) fail(path, 'Duplicate node id');\n ids.add(node.id);\n if (node.kind === 'group') {\n groups.add(node.id);\n if (\n node.tabDisplay !== undefined &&\n node.tabDisplay !== 'automatic' &&\n node.tabDisplay !== 'compact'\n )\n fail(path + '.tabDisplay', 'Expected automatic or compact');\n if (\n node.tabPlacement !== undefined &&\n node.tabPlacement !== 'top' &&\n node.tabPlacement !== 'left'\n )\n fail(path + '.tabPlacement', 'Expected top or left');\n if (!Array.isArray(node.panes)) {\n fail(path, 'Expected pane array');\n return;\n }\n node.panes.forEach((p, i) => use(p, `${path}.panes[${i}]`));\n if (node.panes.length ? !node.panes.includes(node.active) : node.active !== null)\n fail(path + '.active', 'Active tab must belong to group (or be null for empty group)');\n } else if (node.kind === 'split') {\n if (node.gap !== undefined && (!finite(node.gap) || node.gap < 0))\n fail(path + '.gap', 'Expected nonnegative divider space');\n if (!['horizontal', 'vertical'].includes(String(node.axis)))\n fail(path + '.axis', 'Expected horizontal or vertical');\n if (!finite(node.ratio) || node.ratio <= 0 || node.ratio >= 1)\n fail(path + '.ratio', 'Expected ratio between 0 and 1');\n if (!Array.isArray(node.children) || node.children.length !== 2)\n fail(path + '.children', 'Expected two children');\n else node.children.forEach((n, i) => walk(n, `${path}.children[${i}]`, depth + 1));\n } else fail(path + '.kind', 'Expected group or split');\n }\n walk(input.root, 'root', 0);\n if (!Array.isArray(input.popouts)) fail('popouts', 'Expected array');\n else\n input.popouts.forEach((p, i) => {\n const path = `popouts[${i}]`;\n if (!record(p)) {\n fail(path, 'Expected popout object');\n return;\n }\n use(p.paneId, path + '.paneId');\n if (typeof p.groupId !== 'string' || !Number.isInteger(p.index) || Number(p.index) < 0)\n fail(path, 'Expected return group id and nonnegative index');\n if (p.placement !== undefined) {\n if (!record(p.placement)) fail(path + '.placement', 'Expected placement object');\n else\n for (const [key, value] of Object.entries(p.placement))\n if (\n !['width', 'height', 'left', 'top'].includes(key) ||\n !finite(value) ||\n (['width', 'height'].includes(key) && value <= 0)\n )\n fail(path + '.placement.' + key, 'Invalid window placement');\n }\n });\n for (const id of Object.keys(panes))\n if (!assigned.has(id)) fail(`panes.${id}`, 'Pane has no placement');\n if (\n input.maximized !== null &&\n (typeof input.maximized !== 'string' || !groups.has(input.maximized))\n )\n fail('maximized', 'Expected a group id or null');\n if (!errors.length) {\n const check = (n: Node) => {\n const b = bounds(n, input as unknown as Layout);\n if (b.minWidth > b.maxWidth || b.minHeight > b.maxHeight)\n fail(n.id, 'Pane constraints cannot coexist in this region');\n if (n.kind === 'split') n.children.forEach(check);\n };\n check(input.root as unknown as Node);\n }\n return errors;\n}\nexport function parseLayout(input: unknown): Layout {\n const issues = validate(input);\n if (issues.length) throw new LayoutError(issues);\n return structuredClone(input) as Layout;\n}\nexport function findNode(root: Node, id: string): Node | undefined {\n return root.id === id\n ? root\n : root.kind === 'split'\n ? (findNode(root.children[0], id) ?? findNode(root.children[1], id))\n : undefined;\n}\nexport function findParent(root: Node, id: string): import('./types.js').Split | undefined {\n if (root.kind === 'group') return undefined;\n return root.children.some((n) => n.id === id)\n ? root\n : (findParent(root.children[0], id) ?? findParent(root.children[1], id));\n}\nexport function groups(root: Node): Group[] {\n return root.kind === 'group' ? [root] : root.children.flatMap(groups);\n}\nexport function paneIds(root: Node): string[] {\n return groups(root).flatMap((g) => g.panes);\n}\nfunction paneBounds(p: Pane): Bounds {\n return {\n minWidth: p.size?.minWidth ?? 0,\n maxWidth: p.size?.maxWidth ?? Infinity,\n minHeight: p.size?.minHeight ?? 0,\n maxHeight: p.size?.maxHeight ?? Infinity,\n };\n}\nexport const DIVIDER = 4;\n/** Aggregate model constraints, optionally resolving each group's bounds for a host renderer. */\nexport function bounds(\n node: Node,\n layout: Layout,\n resolveGroup?: (group: Group, constraints: Bounds) => Bounds,\n): Bounds {\n if (node.kind === 'group') {\n const values = node.panes.map((id) => paneBounds(layout.panes[id]!));\n const constraints = {\n minWidth: Math.max(0, ...values.map((b) => b.minWidth)),\n maxWidth: Math.min(Infinity, ...values.map((b) => b.maxWidth)),\n minHeight: Math.max(0, ...values.map((b) => b.minHeight)),\n maxHeight: Math.min(Infinity, ...values.map((b) => b.maxHeight)),\n };\n return resolveGroup ? resolveGroup(node, constraints) : constraints;\n }\n const a = bounds(node.children[0], layout, resolveGroup),\n b = bounds(node.children[1], layout, resolveGroup);\n return node.axis === 'horizontal'\n ? {\n minWidth: a.minWidth + b.minWidth + (node.gap ?? DIVIDER),\n maxWidth: a.maxWidth + b.maxWidth + (node.gap ?? DIVIDER),\n minHeight: Math.max(a.minHeight, b.minHeight),\n maxHeight: Math.max(a.maxHeight, b.maxHeight),\n }\n : {\n minHeight: a.minHeight + b.minHeight + (node.gap ?? DIVIDER),\n maxHeight: a.maxHeight + b.maxHeight + (node.gap ?? DIVIDER),\n minWidth: Math.max(a.minWidth, b.minWidth),\n maxWidth: Math.max(a.maxWidth, b.maxWidth),\n };\n}\n/** Returns content extents; overflow retains minimums, surplus beyond maximums stays empty. */\nexport function allocate(\n total: number,\n ratio: number,\n minA: number,\n maxA: number,\n minB: number,\n maxB: number,\n gap = DIVIDER,\n): [number, number] {\n const available = Math.max(total - gap, minA + minB);\n const used = Math.min(available, maxA + maxB);\n const low = Math.max(minA, used - maxB),\n high = Math.min(maxA, used - minB);\n const a = Math.max(low, Math.min(high, used * ratio));\n return [a, used - a];\n}\n\n/** Create independent, validated JSON for an empty or single-pane workspace. */\nexport function createLayout(options: { pane?: Pane; groupId?: string } = {}): Layout {\n const { pane, groupId = 'main' } = options;\n return parseLayout({\n version: 1,\n root: { kind: 'group', id: groupId, panes: pane ? [pane.id] : [], active: pane?.id ?? null },\n panes: pane ? { [pane.id]: pane } : {},\n popouts: [],\n maximized: null,\n });\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -1,12 +1,21 @@
1
1
  export type AutoCollapse = 'enabled' | 'protected' | 'disabled';
2
+ /** User interaction policy. More specific values override workspace defaults. */
3
+ export interface CapabilityPolicy {
4
+ defaults?: Partial<Record<Capability, boolean>>;
5
+ /** Region overrides, keyed by Group.id. */
6
+ groups?: Record<string, Partial<Record<Capability, boolean>>>;
7
+ /** Tab overrides, keyed by Pane.id; take precedence over saved pane capabilities. */
8
+ panes?: Record<string, Partial<Record<Capability, boolean>>>;
9
+ }
2
10
  export interface LayoutStoreOptions {
11
+ capabilities?: CapabilityPolicy;
3
12
  /** Session policy; omitted defaults to disabled. Not serialized in Layout JSON. */
4
13
  autoCollapse?: AutoCollapse;
5
14
  }
6
15
  export type Json = null | boolean | number | string | Json[] | {
7
16
  [key: string]: Json;
8
17
  };
9
- export type Capability = 'resize' | 'move' | 'split' | 'join' | 'close' | 'popout';
18
+ export type Capability = 'resize' | 'move' | 'reorder' | 'addTab' | 'maximize' | 'split' | 'join' | 'close' | 'popout';
10
19
  export type Axis = 'horizontal' | 'vertical';
11
20
  export interface Pane {
12
21
  /** Override the pane-type close confirmation default. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAiEA,MAAM,OAAO,WAAY,SAAQ,KAAK;IACR,MAAM;IAAlC,YAA4B,MAAe;QACzC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;sBADrC,MAAM;QAEhC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF","sourcesContent":["export type AutoCollapse = 'enabled' | 'protected' | 'disabled';\nexport interface LayoutStoreOptions {\n /** Session policy; omitted defaults to disabled. Not serialized in Layout JSON. */\n autoCollapse?: AutoCollapse;\n}\nexport type Json = null | boolean | number | string | Json[] | { [key: string]: Json };\nexport type Capability = 'resize' | 'move' | 'split' | 'join' | 'close' | 'popout';\nexport type Axis = 'horizontal' | 'vertical';\nexport interface Pane {\n /** Override the pane-type close confirmation default. */\n confirmClose?: boolean;\n id: string;\n type: string;\n title: string;\n /** Application-defined icon key, resolved by the view adapter. */\n icon?: string;\n params?: Json;\n capabilities?: Partial<Record<Capability, boolean>>;\n size?: { minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number };\n /** Hide chrome only for a one-tab group. Host commands can still operate on it. */\n header?: boolean;\n}\nexport interface Group {\n kind: 'group';\n id: string;\n panes: string[];\n active: string | null;\n /** Persisted tab orientation for this region; omitted inherits renderer settings. */\n tabPlacement?: 'top' | 'left';\n /** Omitted inherits the workspace tab display setting. */\n tabDisplay?: 'automatic' | 'compact';\n}\nexport interface Split {\n kind: 'split';\n id: string;\n axis: Axis;\n ratio: number;\n /** Divider space in pixels; zero removes fixed-bar gaps. Default 4. */\n gap?: number;\n children: [Node, Node];\n}\nexport type Node = Group | Split;\nexport interface WindowPlacement {\n width?: number;\n height?: number;\n left?: number;\n top?: number;\n}\nexport interface Popout {\n paneId: string;\n groupId: string;\n index: number;\n placement?: WindowPlacement;\n}\nexport interface Layout {\n version: 1;\n root: Node;\n panes: Record<string, Pane>;\n popouts: Popout[];\n maximized: string | null;\n}\nexport interface Issue {\n path: string;\n message: string;\n}\nexport class LayoutError extends Error {\n constructor(public readonly issues: Issue[]) {\n super(issues.map((i) => `${i.path}: ${i.message}`).join('; '));\n this.name = 'LayoutError';\n }\n}\nexport interface CommandOptions {\n /** Treat capability flags as user-interaction restrictions. */ source?: 'user' | 'api';\n}\nexport interface Change {\n action: string;\n layout: Layout;\n}\nexport interface Bounds {\n minWidth: number;\n maxWidth: number;\n minHeight: number;\n maxHeight: number;\n}\n\nexport interface JoinOptions extends CommandOptions {\n /** Optional rendered extents along the join axis, keyed by node ID, including splits.\n * Supply the complete row to retain actual sizes under constraints and custom dividers.\n * Without measurements, joins retain proportional shares of the row/column.\n */\n extents?: Record<string, number>;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2EA,MAAM,OAAO,WAAY,SAAQ,KAAK;IACR,MAAM;IAAlC,YAA4B,MAAe;QACzC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;sBADrC,MAAM;QAEhC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF","sourcesContent":["export type AutoCollapse = 'enabled' | 'protected' | 'disabled';\n/** User interaction policy. More specific values override workspace defaults. */\nexport interface CapabilityPolicy {\n defaults?: Partial<Record<Capability, boolean>>;\n /** Region overrides, keyed by Group.id. */\n groups?: Record<string, Partial<Record<Capability, boolean>>>;\n /** Tab overrides, keyed by Pane.id; take precedence over saved pane capabilities. */\n panes?: Record<string, Partial<Record<Capability, boolean>>>;\n}\nexport interface LayoutStoreOptions {\n capabilities?: CapabilityPolicy;\n /** Session policy; omitted defaults to disabled. Not serialized in Layout JSON. */\n autoCollapse?: AutoCollapse;\n}\nexport type Json = null | boolean | number | string | Json[] | { [key: string]: Json };\nexport type Capability =\n 'resize' | 'move' | 'reorder' | 'addTab' | 'maximize' | 'split' | 'join' | 'close' | 'popout';\nexport type Axis = 'horizontal' | 'vertical';\nexport interface Pane {\n /** Override the pane-type close confirmation default. */\n confirmClose?: boolean;\n id: string;\n type: string;\n title: string;\n /** Application-defined icon key, resolved by the view adapter. */\n icon?: string;\n params?: Json;\n capabilities?: Partial<Record<Capability, boolean>>;\n size?: { minWidth?: number; maxWidth?: number; minHeight?: number; maxHeight?: number };\n /** Hide chrome only for a one-tab group. Host commands can still operate on it. */\n header?: boolean;\n}\nexport interface Group {\n kind: 'group';\n id: string;\n panes: string[];\n active: string | null;\n /** Persisted tab orientation for this region; omitted inherits renderer settings. */\n tabPlacement?: 'top' | 'left';\n /** Omitted inherits the workspace tab display setting. */\n tabDisplay?: 'automatic' | 'compact';\n}\nexport interface Split {\n kind: 'split';\n id: string;\n axis: Axis;\n ratio: number;\n /** Divider space in pixels; zero removes fixed-bar gaps. Default 4. */\n gap?: number;\n children: [Node, Node];\n}\nexport type Node = Group | Split;\nexport interface WindowPlacement {\n width?: number;\n height?: number;\n left?: number;\n top?: number;\n}\nexport interface Popout {\n paneId: string;\n groupId: string;\n index: number;\n placement?: WindowPlacement;\n}\nexport interface Layout {\n version: 1;\n root: Node;\n panes: Record<string, Pane>;\n popouts: Popout[];\n maximized: string | null;\n}\nexport interface Issue {\n path: string;\n message: string;\n}\nexport class LayoutError extends Error {\n constructor(public readonly issues: Issue[]) {\n super(issues.map((i) => `${i.path}: ${i.message}`).join('; '));\n this.name = 'LayoutError';\n }\n}\nexport interface CommandOptions {\n /** Treat capability flags as user-interaction restrictions. */ source?: 'user' | 'api';\n}\nexport interface Change {\n action: string;\n layout: Layout;\n}\nexport interface Bounds {\n minWidth: number;\n maxWidth: number;\n minHeight: number;\n maxHeight: number;\n}\n\nexport interface JoinOptions extends CommandOptions {\n /** Optional rendered extents along the join axis, keyed by node ID, including splits.\n * Supply the complete row to retain actual sizes under constraints and custom dividers.\n * Without measurements, joins retain proportional shares of the row/column.\n */\n extents?: Record<string, number>;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quilt-core",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Framework-independent pane layout model, validation, commands, and subscriptions",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/controller.ts CHANGED
@@ -7,6 +7,7 @@ import type {
7
7
  JoinOptions,
8
8
  Axis,
9
9
  Capability,
10
+ CapabilityPolicy,
10
11
  Change,
11
12
  CommandOptions,
12
13
  Group,
@@ -36,7 +37,9 @@ export class LayoutStore {
36
37
  private notifying = false;
37
38
  private pending: Change[] = [];
38
39
  private autoCollapse: AutoCollapse = 'disabled';
40
+ private capabilities: CapabilityPolicy = {};
39
41
  constructor(input: unknown, options: LayoutStoreOptions = {}) {
42
+ this.setCapabilities(options.capabilities);
40
43
  this.setAutoCollapse(options.autoCollapse ?? 'disabled');
41
44
  this.state = freeze(parseLayout(input));
42
45
  this.initial = this.export();
@@ -134,7 +137,7 @@ export class LayoutStore {
134
137
  }
135
138
  private permit(draft: Layout, ids: string[], cap: Capability, options: CommandOptions) {
136
139
  for (const id of ids)
137
- if (options.source === 'user' && this.pane(draft, id).capabilities?.[cap] === false)
140
+ if (options.source === 'user' && !this.canPane(draft, id, cap))
138
141
  problem(`${cap} is disabled for ${id}`);
139
142
  }
140
143
  private id(draft: Layout): string {
@@ -178,12 +181,81 @@ export class LayoutStore {
178
181
  }
179
182
  if (draft.maximized && !findNode(draft.root, draft.maximized)) draft.maximized = null;
180
183
  }
181
- can(paneId: string, capability: Capability): boolean {
184
+ /** Replace session policy; layout export/load never serializes or resets it. */
185
+ setCapabilities(policy: CapabilityPolicy = {}): void {
186
+ this.alive();
187
+ const flags = (value: unknown) => {
188
+ if (!value || typeof value !== 'object' || Array.isArray(value))
189
+ problem('Invalid capabilities');
190
+ for (const [key, flag] of Object.entries(value!))
191
+ if (
192
+ ![
193
+ 'resize',
194
+ 'move',
195
+ 'reorder',
196
+ 'addTab',
197
+ 'maximize',
198
+ 'split',
199
+ 'join',
200
+ 'close',
201
+ 'popout',
202
+ ].includes(key) ||
203
+ typeof flag !== 'boolean'
204
+ )
205
+ problem('Invalid capability: ' + key);
206
+ };
207
+ if (!policy || typeof policy !== 'object' || Array.isArray(policy))
208
+ problem('Invalid capability policy');
209
+ for (const [key, value] of Object.entries(policy)) {
210
+ if (value === undefined) continue;
211
+ if (key === 'defaults') flags(value);
212
+ else if (key === 'groups' || key === 'panes') {
213
+ if (!value || typeof value !== 'object' || Array.isArray(value))
214
+ problem('Invalid capability overrides');
215
+ Object.values(value).forEach(flags);
216
+ } else problem('Unknown capability scope: ' + key);
217
+ }
218
+ this.capabilities = structuredClone(policy);
219
+ }
220
+ private canPane(layout: Layout, paneId: string, capability: Capability): boolean {
221
+ const pane = layout.panes[paneId];
222
+ if (!pane) return false;
223
+ const groupId =
224
+ groups(layout.root).find((g) => g.panes.includes(paneId))?.id ??
225
+ layout.popouts.find((p) => p.paneId === paneId)?.groupId;
182
226
  return (
183
- Boolean(this.state.panes[paneId]) &&
184
- this.state.panes[paneId]!.capabilities?.[capability] !== false
227
+ this.capabilities.panes?.[paneId]?.[capability] ??
228
+ pane.capabilities?.[capability] ??
229
+ (groupId ? this.capabilities.groups?.[groupId]?.[capability] : undefined) ??
230
+ this.capabilities.defaults?.[capability] ??
231
+ (capability === 'addTab' || capability === 'reorder'
232
+ ? this.canPane(layout, paneId, 'move')
233
+ : true)
185
234
  );
186
235
  }
236
+ can(paneId: string, capability: Capability): boolean {
237
+ return this.canPane(this.state, paneId, capability);
238
+ }
239
+ private canNodeIn(layout: Layout, node: Node, capability: Capability): boolean {
240
+ if (node.kind === 'split')
241
+ return node.children.every((child) => this.canNodeIn(layout, child, capability));
242
+ return node.panes.length
243
+ ? node.panes.every((id) => this.canPane(layout, id, capability))
244
+ : (this.capabilities.groups?.[node.id]?.[capability] ??
245
+ this.capabilities.defaults?.[capability] ??
246
+ (capability === 'addTab' || capability === 'reorder'
247
+ ? this.canNodeIn(layout, node, 'move')
248
+ : true));
249
+ }
250
+ /** Test every affected tab, including policy on empty regions. */
251
+ canNode(nodeId: string, capability: Capability): boolean {
252
+ const node = findNode(this.state.root, nodeId);
253
+ return !!node && this.canNodeIn(this.state, node, capability);
254
+ }
255
+ private permitNode(layout: Layout, node: Node, capability: Capability, options: CommandOptions) {
256
+ if (options.source === 'user' && !this.canNodeIn(layout, node, capability))
257
+ problem(`${capability} is disabled for ${node.id}`);
258
+ }
187
259
  load(input: unknown) {
188
260
  this.commit('load', (draft) => {
189
261
  const next = parseLayout(input);
@@ -221,7 +293,7 @@ export class LayoutStore {
221
293
  this.commit('resize', (d) => {
222
294
  const n = findNode(d.root, splitId);
223
295
  if (n?.kind !== 'split') problem('Split not found');
224
- this.permit(d, paneIds(n), 'resize', options);
296
+ this.permitNode(d, n, 'resize', options);
225
297
  n.ratio = ratio;
226
298
  });
227
299
  }
@@ -231,21 +303,21 @@ export class LayoutStore {
231
303
  for (const [id, ratio] of Object.entries(ratios)) {
232
304
  const node = findNode(d.root, id);
233
305
  if (node?.kind !== 'split') problem('Split not found');
234
- this.permit(d, paneIds(node), 'resize', options);
306
+ this.permitNode(d, node, 'resize', options);
235
307
  node.ratio = ratio;
236
308
  }
237
309
  });
238
310
  }
239
- maximize(groupId: string | null) {
311
+ maximize(groupId: string | null, options: CommandOptions = {}) {
240
312
  this.commit('maximize', (d) => {
241
- if (groupId) this.group(d, groupId);
313
+ if (groupId) this.permitNode(d, this.group(d, groupId), 'maximize', options);
242
314
  d.maximized = groupId;
243
315
  });
244
316
  }
245
317
  add(pane: Pane, groupId: string, options: CommandOptions = {}) {
246
318
  this.commit('add', (d) => {
247
319
  const g = this.group(d, groupId);
248
- this.permit(d, g.panes, 'move', options);
320
+ this.permitNode(d, g, 'addTab', options);
249
321
  if (Object.hasOwn(d.panes, pane.id)) problem('Pane id already exists');
250
322
  Object.defineProperty(d.panes, pane.id, {
251
323
  value: structuredClone(pane),
@@ -272,7 +344,7 @@ export class LayoutStore {
272
344
  let created = '';
273
345
  this.commit('split', (d) => {
274
346
  const g = this.group(d, groupId);
275
- this.permit(d, g.panes, 'split', options);
347
+ this.permitNode(d, g, 'split', options);
276
348
  if (pane) {
277
349
  if (Object.hasOwn(d.panes, pane.id)) problem('Pane id already exists');
278
350
  Object.defineProperty(d.panes, pane.id, {
@@ -300,7 +372,7 @@ export class LayoutStore {
300
372
  return created;
301
373
  }
302
374
  /** Cancel only an unfilled region; never roll back edits made elsewhere. */
303
- removeEmptyGroup(groupId: string) {
375
+ removeEmptyGroup(groupId: string, options: CommandOptions = {}) {
304
376
  const existing = findNode(this.state.root, groupId);
305
377
  if (
306
378
  existing?.kind !== 'group' ||
@@ -309,6 +381,7 @@ export class LayoutStore {
309
381
  )
310
382
  return;
311
383
  this.commit('removeEmptyGroup', (d) => {
384
+ this.permitNode(d, this.group(d, groupId), 'close', options);
312
385
  if (d.maximized === groupId) d.maximized = null;
313
386
  const parent = findParent(d.root, groupId)!;
314
387
  this.replace(d, parent, parent.children[parent.children[0].id === groupId ? 1 : 0]);
@@ -326,8 +399,10 @@ export class LayoutStore {
326
399
  const target = this.group(d, groupId);
327
400
  const source = groups(d.root).find((g) => g.panes.includes(paneId));
328
401
  if (!source) problem('Return a popped-out pane before moving it');
329
- this.permit(d, [paneId, ...target.panes], 'move', options);
330
- if (position !== 'tab') this.permit(d, target.panes, 'split', options);
402
+ const capability = source === target && position === 'tab' ? 'reorder' : 'move';
403
+ this.permit(d, [paneId], capability, options);
404
+ this.permitNode(d, target, capability, options);
405
+ if (position !== 'tab') this.permitNode(d, target, 'split', options);
331
406
  if (source === target && target.panes.length === 1) return;
332
407
  this.detach(d, paneId);
333
408
  if (position === 'tab') {
@@ -357,7 +432,7 @@ export class LayoutStore {
357
432
  const g = this.group(d, groupId),
358
433
  parent = findParent(d.root, groupId);
359
434
  if (!parent) return;
360
- this.permit(d, paneIds(parent), 'join', options);
435
+ this.permitNode(d, parent, 'join', options);
361
436
  g.panes = paneIds(parent);
362
437
  g.active ??= g.panes[0] ?? null;
363
438
  this.replace(d, parent, g);
@@ -368,7 +443,7 @@ export class LayoutStore {
368
443
  closeGroup(groupId: string, options: CommandOptions = {}) {
369
444
  this.commit('closeGroup', (d) => {
370
445
  const group = this.group(d, groupId);
371
- this.permit(d, group.panes, 'close', options);
446
+ this.permitNode(d, group, 'close', options);
372
447
  for (const id of group.panes) delete d.panes[id];
373
448
  group.panes = [];
374
449
  group.active = null;
@@ -386,7 +461,7 @@ export class LayoutStore {
386
461
  if (!range) problem('Join requires contiguous regions in one row or column');
387
462
  const { row, regions, boundaries, start, end, selected } = range;
388
463
  const panes = selected.flatMap((g) => g.panes);
389
- this.permit(d, panes, 'join', options);
464
+ selected.forEach((group) => this.permitNode(d, group, 'join', options));
390
465
  let sizes = range.weights;
391
466
  let gaps = boundaries.map(() => 0);
392
467
  if (options.extents) {
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export type {
3
3
  LayoutStoreOptions,
4
4
  Json,
5
5
  Capability,
6
+ CapabilityPolicy,
6
7
  Axis,
7
8
  Pane,
8
9
  Group,
package/src/model.ts CHANGED
@@ -53,7 +53,17 @@ export function validate(input: unknown): Issue[] {
53
53
  else
54
54
  for (const [key, value] of Object.entries(pane.capabilities))
55
55
  if (
56
- !['resize', 'move', 'split', 'join', 'close', 'popout'].includes(key) ||
56
+ ![
57
+ 'resize',
58
+ 'move',
59
+ 'reorder',
60
+ 'addTab',
61
+ 'maximize',
62
+ 'split',
63
+ 'join',
64
+ 'close',
65
+ 'popout',
66
+ ].includes(key) ||
57
67
  typeof value !== 'boolean'
58
68
  )
59
69
  fail(`panes.${id}.capabilities.${key}`, 'Unknown capability or non-boolean flag');
package/src/types.ts CHANGED
@@ -1,10 +1,20 @@
1
1
  export type AutoCollapse = 'enabled' | 'protected' | 'disabled';
2
+ /** User interaction policy. More specific values override workspace defaults. */
3
+ export interface CapabilityPolicy {
4
+ defaults?: Partial<Record<Capability, boolean>>;
5
+ /** Region overrides, keyed by Group.id. */
6
+ groups?: Record<string, Partial<Record<Capability, boolean>>>;
7
+ /** Tab overrides, keyed by Pane.id; take precedence over saved pane capabilities. */
8
+ panes?: Record<string, Partial<Record<Capability, boolean>>>;
9
+ }
2
10
  export interface LayoutStoreOptions {
11
+ capabilities?: CapabilityPolicy;
3
12
  /** Session policy; omitted defaults to disabled. Not serialized in Layout JSON. */
4
13
  autoCollapse?: AutoCollapse;
5
14
  }
6
15
  export type Json = null | boolean | number | string | Json[] | { [key: string]: Json };
7
- export type Capability = 'resize' | 'move' | 'split' | 'join' | 'close' | 'popout';
16
+ export type Capability =
17
+ 'resize' | 'move' | 'reorder' | 'addTab' | 'maximize' | 'split' | 'join' | 'close' | 'popout';
8
18
  export type Axis = 'horizontal' | 'vertical';
9
19
  export interface Pane {
10
20
  /** Override the pane-type close confirmation default. */