quilt-vanilla 0.2.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +35 -39
  2. package/dist/actions.d.ts +14 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +115 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/chrome-size.d.ts +7 -0
  7. package/dist/chrome-size.d.ts.map +1 -0
  8. package/dist/chrome-size.js +86 -0
  9. package/dist/chrome-size.js.map +1 -0
  10. package/dist/close.d.ts.map +1 -1
  11. package/dist/close.js +3 -1
  12. package/dist/close.js.map +1 -1
  13. package/dist/corners.d.ts +2 -1
  14. package/dist/corners.d.ts.map +1 -1
  15. package/dist/corners.js +2 -2
  16. package/dist/corners.js.map +1 -1
  17. package/dist/index.d.ts +6 -4
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/menu.d.ts +9 -3
  22. package/dist/menu.d.ts.map +1 -1
  23. package/dist/menu.js +110 -37
  24. package/dist/menu.js.map +1 -1
  25. package/dist/panes.d.ts.map +1 -1
  26. package/dist/panes.js +84 -52
  27. package/dist/panes.js.map +1 -1
  28. package/dist/registry.d.ts +1 -0
  29. package/dist/registry.d.ts.map +1 -1
  30. package/dist/registry.js +4 -3
  31. package/dist/registry.js.map +1 -1
  32. package/dist/renderer.d.ts.map +1 -1
  33. package/dist/renderer.js +128 -36
  34. package/dist/renderer.js.map +1 -1
  35. package/dist/resize.d.ts +2 -1
  36. package/dist/resize.d.ts.map +1 -1
  37. package/dist/resize.js +2 -2
  38. package/dist/resize.js.map +1 -1
  39. package/dist/shortcut-registration.d.ts +9 -0
  40. package/dist/shortcut-registration.d.ts.map +1 -0
  41. package/dist/shortcut-registration.js +95 -0
  42. package/dist/shortcut-registration.js.map +1 -0
  43. package/dist/shortcuts.d.ts +7 -6
  44. package/dist/shortcuts.d.ts.map +1 -1
  45. package/dist/shortcuts.js +28 -50
  46. package/dist/shortcuts.js.map +1 -1
  47. package/dist/styles.css +74 -9
  48. package/dist/tabs.d.ts.map +1 -1
  49. package/dist/tabs.js +10 -12
  50. package/dist/tabs.js.map +1 -1
  51. package/dist/types.d.ts +50 -13
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js.map +1 -1
  54. package/dist/workspace-api.d.ts +186 -0
  55. package/dist/workspace-api.d.ts.map +1 -0
  56. package/dist/workspace-api.js +409 -0
  57. package/dist/workspace-api.js.map +1 -0
  58. package/package.json +2 -2
  59. package/src/actions.ts +125 -0
  60. package/src/chrome-size.ts +99 -0
  61. package/src/close.ts +6 -1
  62. package/src/corners.ts +2 -1
  63. package/src/index.ts +31 -4
  64. package/src/menu.ts +123 -43
  65. package/src/panes.ts +82 -55
  66. package/src/registry.ts +6 -4
  67. package/src/renderer.ts +181 -54
  68. package/src/resize.ts +2 -1
  69. package/src/shortcut-registration.ts +106 -0
  70. package/src/shortcuts.ts +38 -63
  71. package/src/styles.css +74 -9
  72. package/src/tabs.ts +9 -11
  73. package/src/types.ts +67 -14
  74. package/src/workspace-api.ts +583 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-api.js","sourceRoot":"","sources":["../src/workspace-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { groups, findNode } from 'quilt-core';\nimport type {\n LayoutStore,\n Pane,\n Group,\n WindowPlacement,\n AutoCollapse,\n Axis,\n CommandOptions,\n JoinOptions,\n Capability,\n Layout,\n} from 'quilt-core';\nimport { mountLayout } from './renderer.js';\nimport { PaneRegistry, createPaneId } from './registry.js';\nimport type { PaneRegistration } from './registry.js';\nimport { dockLayout } from './workspace.js';\nimport type { LayoutTheme } from './theme.js';\nimport type {\n LayoutOptions,\n LayoutOptionUpdates,\n MountedLayout,\n PaneRenderer,\n TabBarOptions,\n WorkspaceSettings,\n WorkspaceAction,\n ActionContext,\n RegisteredShortcut,\n} from './types.js';\n\nexport type PaneType<T> = Omit<PaneRegistration<T>, 'type' | 'view'> & { render: T };\nexport type PaneTypes<T> = Record<string, PaneType<T>>;\nexport type WorkspaceOptions<State = unknown> = WorkspaceSettings<State> &\n import('./types.js').InitialConfiguration & {\n container: HTMLElement;\n store?: never;\n } & (unknown extends State ? {} : { getPaneState: (paneId: string) => State }) &\n (\n | {\n paneTypes: PaneTypes<PaneRenderer<State>>;\n registry?: never;\n renderers?: never;\n tabs?: never;\n }\n | {\n paneTypes?: undefined;\n registry: PaneRegistry<PaneRenderer<State>>;\n renderers?: never;\n tabs?: never;\n }\n | {\n paneTypes?: undefined;\n registry?: undefined;\n renderers?: Record<string, PaneRenderer<State>>;\n tabs?: import('./registry.js').TabRegistry;\n }\n );\nexport type WorkspaceOptionUpdates<State = unknown> = {\n [Key in keyof WorkspaceSettings<State>]?: WorkspaceSettings<State>[Key] | undefined;\n} & (\n | {\n paneTypes?: PaneTypes<PaneRenderer<State>> | undefined;\n registry?: undefined;\n renderers?: undefined;\n tabs?: undefined;\n }\n | {\n paneTypes?: undefined;\n registry?: PaneRegistry<PaneRenderer<State>> | undefined;\n renderers?: undefined;\n tabs?: undefined;\n }\n | {\n paneTypes?: undefined;\n registry?: undefined;\n renderers?: Record<string, PaneRenderer<State>> | undefined;\n tabs?: import('./registry.js').TabRegistry | undefined;\n }\n);\nexport interface WorkspaceChange {\n action: string;\n changes: readonly ('layout' | 'theme' | 'tabBar' | 'autoCollapse' | 'shortcuts')[];\n}\nexport interface WorkspaceEvents {\n change: WorkspaceChange;\n error: unknown;\n}\nexport type AddPaneOptions = Partial<Omit<Pane, 'type'>> & { groupId?: string };\nexport interface CloseOptions {\n force?: boolean;\n}\nexport interface PaneHandle {\n readonly id: string;\n readonly isDisposed: boolean;\n getSnapshot(): Pane;\n update(patch: Partial<Omit<Pane, 'id'>>): void;\n setTitle(title: string): void;\n activate(): void;\n move(\n groupId: string,\n position?: 'tab' | 'left' | 'right' | 'top' | 'bottom',\n index?: number,\n ): void;\n popout(placement?: WindowPlacement): Promise<boolean>;\n return(): void;\n retry(): void;\n close(options?: CloseOptions): Promise<boolean>;\n}\n/** The mounted API. The model and its lifetime remain private to Quilt. */\nexport interface WorkspaceHandle<State = unknown> {\n readonly isDisposed: boolean;\n canExecuteAction(action: WorkspaceAction, context?: ActionContext): boolean;\n executeAction(action: WorkspaceAction, context?: ActionContext): Promise<boolean>;\n getShortcuts(): readonly RegisteredShortcut[];\n /** Subscribe to configuration changes or errors. The returned function unsubscribes. */\n on<K extends keyof WorkspaceEvents>(\n event: K,\n listener: (event: WorkspaceEvents[K]) => void,\n ): () => void;\n /** Stable immutable arrangement snapshot, including live detached records. */\n getLayout(): Layout;\n /** Mutable arrangement copy. Use exportWorkspace for persistence with appearance. */\n exportLayout(): Layout;\n /** Validate and replace the arrangement; detached records restore docked. Invalidates old pane handles on success. */\n loadLayout(input: unknown): void;\n /** Restore the initial arrangement and appearance. */\n reset(): void;\n exportWorkspace(): import('./workspace.js').WorkspacePreset;\n /** Apply a complete preset atomically; emit one consolidated change event. */\n loadWorkspace(input: unknown): void;\n updateOptions(options: WorkspaceOptionUpdates<State>): void;\n setTheme(theme: LayoutTheme): void;\n setTabBar(tabBar: TabBarOptions): void;\n refreshTheme(): void;\n getAutoCollapse(): AutoCollapse;\n setAutoCollapse(mode: AutoCollapse): void;\n getPane(id: string): PaneHandle | undefined;\n getPanes(): PaneHandle[];\n /** Create from a registered type; undefined means its factory cancelled. */\n addPane(type: string, options?: AddPaneOptions): PaneHandle | undefined;\n insertPane(pane: Pane, groupId: string, options?: CommandOptions): void;\n updatePane(pane: Pane): void;\n activatePane(id: string): void;\n movePane(\n paneId: string,\n groupId: string,\n position?: 'tab' | 'left' | 'right' | 'top' | 'bottom',\n index?: number,\n options?: CommandOptions,\n ): void;\n splitGroup(\n groupId: string,\n axis: Axis,\n pane?: Pane | null,\n options?: CommandOptions & { before?: boolean; ratio?: number },\n ): string;\n removeEmptyGroup(groupId: string): void;\n joinGroup(groupId: string, options?: CommandOptions): void;\n joinGroups(receiverId: string, otherId: string, options?: JoinOptions): void;\n resize(splitId: string, ratio: number, options?: CommandOptions): void;\n resizeMany(ratios: Record<string, number>, options?: CommandOptions): void;\n maximize(groupId: string | null): void;\n setTabDisplay(groupId: string, display: Group['tabDisplay']): void;\n setTabPlacement(groupId: string, placement: Group['tabPlacement']): void;\n can(paneId: string, capability: Capability): boolean;\n canRestoreClosedPane(): boolean;\n restoreClosedPane(): void;\n /** Confirm and check permissions unless force is explicitly supplied. */\n closePane(id: string, options?: CloseOptions): Promise<boolean>;\n closeGroup(id: string, options?: CloseOptions): Promise<boolean>;\n /** Call during a user gesture. Resolves after destination readiness or rollback. */\n popout(id: string, placement?: WindowPlacement): Promise<boolean>;\n returnPane(id: string): void;\n retryPane(id: string): void;\n /** Idempotently cancel pending work and release views, companions, and the private model. */\n dispose(): void;\n}\n\ntype InternalOptions<State> = LayoutOptionUpdates<State> & {\n paneTypes?: PaneTypes<PaneRenderer<State>> | undefined;\n};\n\n/** A mounted workspace. Call dispose once when its application container is removed. */\nexport class Workspace<State = unknown> implements WorkspaceHandle<State> {\n #mounted: MountedLayout<State>;\n #disposed = false;\n #handles = new Map<string, PaneHandle>();\n #listeners = {\n change: new Set<(event: WorkspaceChange) => void>(),\n error: new Set<(event: unknown) => void>(),\n };\n #cleanups: (() => void)[] = [];\n #options: InternalOptions<State>;\n #activeGroup: string | undefined;\n #batch = false;\n #initial: ReturnType<MountedLayout['exportWorkspace']>;\n constructor(options: WorkspaceOptions<State>) {\n if (!options?.container?.ownerDocument?.defaultView)\n throw new Error('Workspace requires a container in a live document');\n const { container, ...input } = options;\n const { initialLayout: _layout, initialWorkspace: _workspace, ...updates } = input;\n this.#options = { ...updates };\n const adapted = this.#adapt(this.#options);\n this.#mounted = mountLayout(container, {\n ...input,\n ...adapted,\n onError: this.#report,\n } as unknown as LayoutOptions<State>);\n this.#initial = this.#mounted.exportWorkspace();\n this.#cleanups.push(\n this.#model.subscribe((event) => {\n if (event.action === 'load') {\n this.#handles.clear();\n this.#activeGroup = undefined;\n } else\n for (const id of this.#handles.keys())\n if (!Object.hasOwn(event.layout.panes, id)) this.#handles.delete(id);\n if (!this.#batch) this.#emit({ action: event.action, changes: ['layout'] });\n }),\n this.#model.onError(this.#report),\n );\n const activate = (event: Event) => {\n const target = event.target as Element | null;\n const id = target?.closest?.('[data-node-id]')?.getAttribute('data-node-id');\n if (id && findNode(this.getLayout().root, id)?.kind === 'group') this.#activeGroup = id;\n };\n container.addEventListener('pointerdown', activate);\n container.addEventListener('focusin', activate);\n this.#cleanups.push(\n () => container.removeEventListener('pointerdown', activate),\n () => container.removeEventListener('focusin', activate),\n );\n }\n get #model(): LayoutStore {\n return this.#mounted.store as LayoutStore;\n }\n #alive() {\n if (this.#disposed) throw new Error('Workspace has been disposed');\n }\n #report = (error: unknown) => {\n try {\n this.#options.onError?.(error);\n } catch {\n /* Reporting must not interrupt cleanup. */\n }\n for (const listener of [...this.#listeners.error]) {\n if (!this.#listeners.error.has(listener)) continue;\n try {\n listener(error);\n } catch {\n /* Isolate reporters. */\n }\n }\n };\n #emit(event: WorkspaceChange) {\n for (const listener of [...this.#listeners.change]) {\n if (!this.#listeners.change.has(listener)) continue;\n try {\n listener(event);\n } catch (error) {\n this.#report(error);\n }\n }\n }\n #adapt(options: InternalOptions<State>): LayoutOptionUpdates<State> {\n const { paneTypes, ...rest } = options;\n if (paneTypes !== undefined) {\n if (rest.registry || rest.renderers || rest.tabs)\n throw new Error('paneTypes cannot be combined with registry, renderers, or tabs');\n return {\n ...rest,\n registry: new PaneRegistry(\n Object.entries(paneTypes).map(([type, { render, ...entry }]) => ({\n ...entry,\n type,\n view: render,\n })),\n ),\n };\n }\n return { ...rest, registry: rest.registry };\n }\n get isDisposed() {\n return this.#disposed;\n }\n on<K extends keyof WorkspaceEvents>(\n event: K,\n listener: (event: WorkspaceEvents[K]) => void,\n ): () => void {\n this.#alive();\n const listeners = this.#listeners[event] as Set<(event: WorkspaceEvents[K]) => void>;\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n }\n /** Stable immutable layout snapshot. */\n getLayout = () => {\n this.#alive();\n return this.#model.getSnapshot();\n };\n exportLayout() {\n this.#alive();\n return this.#model.export();\n }\n loadLayout(input: unknown) {\n this.#alive();\n this.#model.load(dockLayout(input));\n }\n reset() {\n this.loadWorkspace(this.#initial);\n }\n exportWorkspace() {\n this.#alive();\n return this.#mounted.exportWorkspace();\n }\n loadWorkspace(input: unknown) {\n this.#alive();\n this.#batch = true;\n try {\n this.#mounted.loadWorkspace(input);\n } finally {\n this.#batch = false;\n }\n this.#emit({ action: 'loadWorkspace', changes: ['layout', 'theme', 'tabBar', 'autoCollapse'] });\n }\n canExecuteAction(action: WorkspaceAction, context?: ActionContext): boolean {\n return !this.#disposed && this.#mounted.canExecuteAction(action, context);\n }\n executeAction(action: WorkspaceAction, context?: ActionContext): Promise<boolean> {\n return this.#disposed ? Promise.resolve(false) : this.#mounted.executeAction(action, context);\n }\n getShortcuts(): readonly RegisteredShortcut[] {\n return this.#mounted.getShortcuts();\n }\n updateOptions(next: WorkspaceOptionUpdates<State>) {\n this.#alive();\n if ('container' in next) throw new Error('Workspace container cannot be updated');\n const candidate = { ...this.#options, ...next };\n const adapted = this.#adapt(candidate);\n const changes: WorkspaceChange['changes'][number][] = [];\n const before = this.exportWorkspace();\n const beforeShortcuts = JSON.stringify(this.getShortcuts());\n const beforeFormatter = this.#options.formatShortcut;\n // Initial appearance is mount-only: only explicitly updated appearance keys apply.\n if (!('theme' in next)) delete adapted.theme;\n if (!('tabBar' in next)) delete adapted.tabBar;\n this.#mounted.updateOptions({ ...adapted, onError: this.#report });\n this.#options = candidate;\n const after = this.exportWorkspace();\n if (JSON.stringify(before.theme) !== JSON.stringify(after.theme)) changes.push('theme');\n if (JSON.stringify(before.tabBar) !== JSON.stringify(after.tabBar)) changes.push('tabBar');\n if (\n beforeShortcuts !== JSON.stringify(this.getShortcuts()) ||\n beforeFormatter !== candidate.formatShortcut\n )\n changes.push('shortcuts');\n if (changes.length) this.#emit({ action: 'updateOptions', changes });\n }\n setTheme(theme: LayoutTheme) {\n this.updateOptions({ theme });\n }\n setTabBar(tabBar: TabBarOptions) {\n this.updateOptions({ tabBar });\n }\n refreshTheme() {\n this.#alive();\n this.#mounted.refreshTheme();\n }\n getAutoCollapse() {\n this.#alive();\n return this.#model.getAutoCollapse();\n }\n setAutoCollapse(mode: AutoCollapse) {\n this.#alive();\n const previous = this.#model.getAutoCollapse();\n this.#model.setAutoCollapse(mode);\n if (mode !== previous) this.#emit({ action: 'setAutoCollapse', changes: ['autoCollapse'] });\n }\n getPane(id: string): PaneHandle | undefined {\n this.#alive();\n if (!Object.hasOwn(this.getLayout().panes, id)) return undefined;\n let handle = this.#handles.get(id);\n if (handle) return handle;\n const workspace = this;\n const alive = () => {\n workspace.#alive();\n if (workspace.#handles.get(id) !== handle) throw new Error(`Pane ${id} has been disposed`);\n };\n handle = {\n id,\n get isDisposed() {\n return workspace.#disposed || workspace.#handles.get(id) !== handle;\n },\n getSnapshot() {\n alive();\n return workspace.getLayout().panes[id]!;\n },\n update(patch) {\n alive();\n workspace.updatePane({ ...workspace.getLayout().panes[id]!, ...patch, id });\n },\n setTitle(title) {\n this.update({ title });\n },\n activate() {\n alive();\n workspace.activatePane(id);\n },\n move(groupId, position, index) {\n alive();\n workspace.movePane(id, groupId, position, index);\n },\n async popout(placement) {\n alive();\n return workspace.popout(id, placement);\n },\n return() {\n alive();\n workspace.returnPane(id);\n },\n retry() {\n alive();\n workspace.retryPane(id);\n },\n async close(options) {\n alive();\n return workspace.closePane(id, options);\n },\n };\n Object.freeze(handle);\n this.#handles.set(id, handle);\n return handle;\n }\n getPanes(): PaneHandle[] {\n return Object.keys(this.getLayout().panes).map((id) => this.getPane(id)!);\n }\n addPane(type: string, options: AddPaneOptions = {}): PaneHandle | undefined {\n this.#alive();\n const layout = this.getLayout();\n const all = groups(layout.root);\n const groupId =\n options.groupId ?? all.find((group) => group.id === this.#activeGroup)?.id ?? all[0]!.id;\n const group = all.find((group) => group.id === groupId);\n if (!group) throw new Error(`Group not found: ${groupId}`);\n const registry = this.#adapt(this.#options).registry;\n const entry = registry?.list().find((entry) => entry.type === type);\n if (!entry) throw new Error(`Pane type is not registered: ${type}`);\n const supplied = entry.create\n ? entry.create({ groupId, source: group.active ? layout.panes[group.active] : undefined })\n : {};\n if (supplied === undefined) return undefined;\n const { groupId: _groupId, ...patch } = options;\n const pane = {\n title: entry.title,\n ...(entry.icon === undefined ? {} : { icon: entry.icon }),\n ...supplied,\n ...patch,\n type,\n id: patch.id ?? supplied.id ?? createPaneId(),\n };\n this.insertPane(pane, groupId);\n return this.getPane(pane.id);\n }\n /** Insert a fully specified serializable record (advanced model integration). */\n insertPane(pane: Pane, groupId: string, options: CommandOptions = {}) {\n this.#alive();\n this.#model.add(pane, groupId, options);\n }\n updatePane(pane: Pane) {\n this.#alive();\n this.#model.updatePane(pane);\n }\n activatePane(id: string) {\n const group = groups(this.getLayout().root).find((group) => group.panes.includes(id));\n if (!group) throw new Error(`Pane is not docked: ${id}`);\n this.#activeGroup = group.id;\n this.#model.activate(group.id, id);\n }\n movePane(\n paneId: string,\n groupId: string,\n position: 'tab' | 'left' | 'right' | 'top' | 'bottom' = 'tab',\n index?: number,\n options: CommandOptions = {},\n ) {\n this.#alive();\n this.#model.move(paneId, groupId, position, index, options);\n }\n splitGroup(\n groupId: string,\n axis: Axis,\n pane: Pane | null = null,\n options: CommandOptions & { before?: boolean; ratio?: number } = {},\n ) {\n this.#alive();\n return this.#model.split(groupId, axis, pane, options);\n }\n removeEmptyGroup(groupId: string) {\n this.#alive();\n this.#model.removeEmptyGroup(groupId);\n }\n joinGroup(groupId: string, options: CommandOptions = {}) {\n this.#alive();\n this.#model.join(groupId, options);\n }\n joinGroups(receiverId: string, otherId: string, options: JoinOptions = {}) {\n this.#alive();\n this.#model.joinRegions(receiverId, otherId, options);\n }\n resize(splitId: string, ratio: number, options: CommandOptions = {}) {\n this.#alive();\n this.#model.resize(splitId, ratio, options);\n }\n resizeMany(ratios: Record<string, number>, options: CommandOptions = {}) {\n this.#alive();\n this.#model.resizeMany(ratios, options);\n }\n maximize(groupId: string | null) {\n this.#alive();\n this.#model.maximize(groupId);\n }\n setTabDisplay(groupId: string, display: Group['tabDisplay']) {\n this.#alive();\n this.#model.setTabDisplay(groupId, display);\n }\n setTabPlacement(groupId: string, placement: Group['tabPlacement']) {\n this.#alive();\n this.#model.setTabPlacement(groupId, placement);\n }\n can(paneId: string, capability: Capability) {\n this.#alive();\n return this.#model.can(paneId, capability);\n }\n canRestoreClosedPane() {\n this.#alive();\n return this.#model.canRestoreClosedTab();\n }\n restoreClosedPane() {\n this.#alive();\n this.#model.restoreClosedTab();\n }\n async closePane(id: string, options: CloseOptions = {}): Promise<boolean> {\n this.#alive();\n if (options.force) {\n this.#model.close(id);\n return true;\n }\n return this.#mounted.requestClose(id);\n }\n async closeGroup(id: string, options: CloseOptions = {}): Promise<boolean> {\n this.#alive();\n if (options.force) {\n this.#model.closeGroup(id);\n return true;\n }\n return this.#mounted.requestClose(id, 'group');\n }\n async popout(id: string, placement?: WindowPlacement): Promise<boolean> {\n this.#alive();\n return this.#mounted.popout(id, placement);\n }\n returnPane(id: string) {\n this.#alive();\n this.#mounted.returnPane(id);\n }\n retryPane(id: string) {\n this.#alive();\n this.#mounted.retryPane(id);\n }\n dispose() {\n if (this.#disposed) return;\n this.#disposed = true;\n this.#handles.clear();\n for (const cleanup of this.#cleanups.splice(0)) cleanup();\n try {\n this.#mounted.dispose();\n } finally {\n this.#listeners.change.clear();\n this.#listeners.error.clear();\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quilt-vanilla",
3
- "version": "0.2.4",
3
+ "version": "0.4.0",
4
4
  "description": "Vanilla DOM split panes, tabs, themes, and same-origin window popouts",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "prepack": "node ../../scripts/build-package.mjs dom --dependencies"
31
31
  },
32
32
  "dependencies": {
33
- "quilt-core": "0.2.4"
33
+ "quilt-core": "0.4.0"
34
34
  },
35
35
  "sideEffects": [
36
36
  "**/*.css"
package/src/actions.ts ADDED
@@ -0,0 +1,125 @@
1
+ import { findNode, findParent, groups, paneIds } from 'quilt-core';
2
+ import type { Group, Pane } from 'quilt-core';
3
+ import type { ActionContext, ResolvedLayoutOptions, WorkspaceAction } from './types.js';
4
+ import { actionOrder } from './shortcut-registration.js';
5
+
6
+ export function createActions(
7
+ options: ResolvedLayoutOptions,
8
+ dependencies: {
9
+ context(): ActionContext;
10
+ disposed(): boolean;
11
+ create(action: WorkspaceAction, group: Group, pane: Pane | undefined): void;
12
+ close(id: string, kind?: 'pane' | 'group'): Promise<boolean>;
13
+ popout(id: string): Promise<boolean>;
14
+ report(error: unknown): void;
15
+ },
16
+ ) {
17
+ function resolve(context?: ActionContext) {
18
+ const layout = options.store.getSnapshot();
19
+ const target =
20
+ context?.groupId !== undefined || context?.paneId !== undefined
21
+ ? context
22
+ : dependencies.context();
23
+ const id =
24
+ target.groupId ??
25
+ (target.paneId === undefined
26
+ ? undefined
27
+ : groups(layout.root).find((group) => group.panes.includes(target.paneId!))?.id);
28
+ const node = id === undefined ? undefined : findNode(layout.root, id);
29
+ const group = node?.kind === 'group' ? node : undefined;
30
+ const paneId = target.paneId ?? group?.active;
31
+ const pane = paneId ? layout.panes[paneId] : undefined;
32
+ const valid =
33
+ !(target.groupId !== undefined && !group) &&
34
+ !(target.paneId !== undefined && (!pane || !group?.panes.includes(target.paneId)));
35
+ return { layout, group, pane, valid };
36
+ }
37
+ function canExecuteAction(action: WorkspaceAction, context?: ActionContext): boolean {
38
+ if (dependencies.disposed() || !actionOrder.includes(action)) return false;
39
+ const { layout, group, pane, valid } = resolve(context);
40
+ if (!valid) return false;
41
+ if (action === 'restoreClosedTab') return options.store.canRestoreClosedTab();
42
+ if (!group) return false;
43
+ const allowed = (cap: 'split' | 'move' | 'close') =>
44
+ group.panes.every((id) => options.store.can(id, cap));
45
+ switch (action) {
46
+ case 'addTab':
47
+ return !!options.tabs?.list().length && allowed('move');
48
+ case 'splitLeft':
49
+ case 'splitRight':
50
+ case 'splitUp':
51
+ case 'splitDown':
52
+ return (!group.panes.length || !!options.tabs?.list().length) && allowed('split');
53
+ case 'closeActiveTab':
54
+ return !!pane && options.store.can(pane.id, 'close');
55
+ case 'closePane':
56
+ return !!group.panes.length && allowed('close');
57
+ case 'closeEmptyPane':
58
+ return !group.panes.length && group.id !== layout.root.id;
59
+ case 'popout':
60
+ return options.popouts !== false && !!pane && options.store.can(pane.id, 'popout');
61
+ case 'joinSiblingRegion': {
62
+ const parent = findParent(layout.root, group.id);
63
+ return !!parent && paneIds(parent).every((id) => options.store.can(id, 'join'));
64
+ }
65
+ default:
66
+ return true;
67
+ }
68
+ }
69
+ async function executeAction(action: WorkspaceAction, context?: ActionContext): Promise<boolean> {
70
+ try {
71
+ if (!canExecuteAction(action, context)) return false;
72
+ const { layout, group, pane } = resolve(context);
73
+ switch (action) {
74
+ case 'restoreClosedTab':
75
+ options.store.restoreClosedTab();
76
+ break;
77
+ case 'maximize':
78
+ options.store.maximize(layout.maximized === group!.id ? null : group!.id);
79
+ break;
80
+ case 'addTab':
81
+ case 'splitLeft':
82
+ case 'splitRight':
83
+ case 'splitUp':
84
+ case 'splitDown':
85
+ dependencies.create(action, group!, pane);
86
+ break;
87
+ case 'closeActiveTab':
88
+ return await dependencies.close(pane!.id);
89
+ case 'closePane':
90
+ return await dependencies.close(group!.id, 'group');
91
+ case 'closeEmptyPane':
92
+ options.store.removeEmptyGroup(group!.id);
93
+ break;
94
+ case 'popout':
95
+ return await dependencies.popout(pane!.id);
96
+ case 'joinSiblingRegion':
97
+ options.store.join(group!.id, { source: 'user' });
98
+ break;
99
+ case 'tabOrientationDefault':
100
+ options.store.setTabPlacement(group!.id, undefined);
101
+ break;
102
+ case 'tabOrientationHorizontal':
103
+ options.store.setTabPlacement(group!.id, 'top');
104
+ break;
105
+ case 'tabOrientationVertical':
106
+ options.store.setTabPlacement(group!.id, 'left');
107
+ break;
108
+ case 'tabDisplayDefault':
109
+ options.store.setTabDisplay(group!.id, undefined);
110
+ break;
111
+ case 'tabDisplayAutomatic':
112
+ options.store.setTabDisplay(group!.id, 'automatic');
113
+ break;
114
+ case 'tabDisplayCompact':
115
+ options.store.setTabDisplay(group!.id, 'compact');
116
+ break;
117
+ }
118
+ return true;
119
+ } catch (error) {
120
+ dependencies.report(error);
121
+ return false;
122
+ }
123
+ }
124
+ return { canExecuteAction, executeAction };
125
+ }
@@ -0,0 +1,99 @@
1
+ import type { TabBarStyle } from './types.js';
2
+ import { themePixels } from './theme.js';
3
+
4
+ /** Measure only chrome, at its smallest presentation, without touching live views. */
5
+ export function chromeMinimum(
6
+ region: HTMLElement,
7
+ header: HTMLElement,
8
+ style: TabBarStyle,
9
+ ): { minWidth: number; minHeight: number } {
10
+ if (header.hidden) return { minWidth: 0, minHeight: 0 };
11
+ const doc = region.ownerDocument;
12
+ const win = doc.defaultView!;
13
+ const left = style.placement === 'left';
14
+ const compact = style.display === 'compact';
15
+ const probe = region.cloneNode(false) as HTMLElement;
16
+ probe.removeAttribute('id');
17
+ probe.removeAttribute('data-node-id');
18
+ probe.dataset.tabPlacement = left ? 'left' : 'top';
19
+ probe.dataset.tabDisplay = compact ? 'compact' : 'automatic';
20
+ probe.dataset.tabAttachment = 'anchored';
21
+ probe.dataset.tabBar = 'full';
22
+ probe.dataset.tabBarFilled = 'true';
23
+ probe.setAttribute('aria-hidden', 'true');
24
+ probe.inert = true;
25
+ probe.style.cssText =
26
+ 'position:fixed;left:-10000px;top:0;width:10000px;height:10000px;visibility:hidden;pointer-events:none';
27
+ const bar = header.cloneNode(true) as HTMLElement;
28
+ bar.removeAttribute('style');
29
+ bar.dataset.tabDisplay = probe.dataset.tabDisplay;
30
+ bar.querySelectorAll('[id]').forEach((element) => element.removeAttribute('id'));
31
+ bar
32
+ .querySelectorAll('.layouts-tab-cap,.layouts-tab-outline')
33
+ .forEach((element) => element.remove());
34
+ probe.append(bar);
35
+ region.parentElement!.append(probe);
36
+ try {
37
+ const css = (element: Element) => win.getComputedStyle(element);
38
+ const px = (value: string) => parseFloat(value) || 0; // Computed CSS dimensions are pixels.
39
+ const outer = (element: HTMLElement, vertical: boolean) => {
40
+ const c = css(element);
41
+ return (
42
+ (vertical
43
+ ? element.getBoundingClientRect().height
44
+ : element.getBoundingClientRect().width) +
45
+ px(vertical ? c.marginTop : c.marginLeft) +
46
+ px(vertical ? c.marginBottom : c.marginRight)
47
+ );
48
+ };
49
+ const items = [...bar.querySelectorAll<HTMLElement>('.layouts-tab-item')];
50
+ const icon = themePixels(region, '--layouts-icon-size', 16);
51
+ for (const item of items) {
52
+ item.querySelector<HTMLElement>('.layouts-tab-label')!.style.display = 'none';
53
+ if (!left) {
54
+ const close = item.querySelector<HTMLElement>('.layouts-tab-close');
55
+ const showClose = !compact && item.dataset.active === 'true' && !!close;
56
+ if (close) close.style.display = showClose ? 'block' : 'none';
57
+ const minimum = Math.max(
58
+ px(css(item).minWidth),
59
+ icon + (compact ? 16 : 8) + (showClose ? outer(close!, false) : 0),
60
+ );
61
+ item.style.flex = '0 0 ' + minimum + 'px';
62
+ item.style.width = minimum + 'px';
63
+ }
64
+ }
65
+ const list = bar.querySelector<HTMLElement>('.layouts-tabs')!;
66
+ const controls = [...bar.children].filter(
67
+ (child): child is HTMLElement =>
68
+ child instanceof win.HTMLElement && child.classList.contains('layouts-button'),
69
+ );
70
+ const c = css(bar);
71
+ const listCss = css(list);
72
+ const tabs =
73
+ items.reduce((sum, item) => sum + outer(item, left), 0) +
74
+ Math.max(0, items.length - 1) * px(left ? listCss.rowGap : listCss.columnGap);
75
+ const main =
76
+ tabs +
77
+ controls.reduce((sum, control) => sum + outer(control, left), 0) +
78
+ Math.max(0, controls.length + (items.length ? 1 : 0) - 1) *
79
+ px(left ? c.rowGap : c.columnGap) +
80
+ px(left ? c.paddingTop : c.paddingLeft) +
81
+ px(left ? c.paddingBottom : c.paddingRight) +
82
+ px(left ? c.borderTopWidth : c.borderLeftWidth) +
83
+ px(left ? c.borderBottomWidth : c.borderRightWidth);
84
+ const cross = left ? bar.getBoundingClientRect().width : bar.getBoundingClientRect().height;
85
+ // Reserve the possible content scrollbar gutter for floating chrome. This also
86
+ // prevents the minimum from oscillating as content begins/stops scrolling.
87
+ const inset =
88
+ style.attachment === 'floating'
89
+ ? 2 * Math.max(0, themePixels(region, '--layouts-panel-padding', 8)) +
90
+ Math.max(0, themePixels(region, '--layouts-scrollbar-size', 6))
91
+ : 0;
92
+ return {
93
+ minWidth: Math.ceil((left ? cross : main) + inset),
94
+ minHeight: Math.ceil((left ? main : cross) + inset),
95
+ };
96
+ } finally {
97
+ probe.remove();
98
+ }
99
+ }
package/src/close.ts CHANGED
@@ -41,7 +41,12 @@ export function closeRequests(
41
41
  };
42
42
  let cleanup = () => {};
43
43
  try {
44
- if (!panes.length || panes.some((pane) => !options.store.can(pane.id, 'close'))) return false;
44
+ const target = kind === 'group' ? findNode(options.store.getSnapshot().root, id) : undefined;
45
+ if (
46
+ (!panes.length && target?.kind !== 'group') ||
47
+ panes.some((pane) => !options.store.can(pane.id, 'close'))
48
+ )
49
+ return false;
45
50
  if (requiringConfirmation.length) {
46
51
  const decision = options.confirmClose
47
52
  ? Promise.resolve(options.confirmClose(request))
package/src/corners.ts CHANGED
@@ -12,6 +12,7 @@ export function bindCorners(
12
12
  scope: Scope,
13
13
  split: (pane: Pane | undefined, group: Group, direction: Direction, ratio: number) => void,
14
14
  report: (error: unknown) => void,
15
+ measureBounds: typeof bounds = bounds,
15
16
  ) {
16
17
  const doc = host.ownerDocument;
17
18
  let drag: Scope | undefined;
@@ -116,7 +117,7 @@ export function bindCorners(
116
117
  const layout = options.store.getSnapshot();
117
118
  const current = findNode(layout.root, id);
118
119
  if (!current) return;
119
- const constraints = bounds(current, layout);
120
+ const constraints = measureBounds(current, layout);
120
121
  const min = horizontal ? constraints.minWidth : constraints.minHeight;
121
122
  const max = horizontal ? constraints.maxWidth : constraints.maxHeight;
122
123
  const total = horizontal ? rect.width : rect.height;
package/src/index.ts CHANGED
@@ -1,14 +1,39 @@
1
- export { mountLayout } from './renderer.js';
2
- export type * from './types.js';
1
+ export { Workspace } from './workspace-api.js';
2
+ export type {
3
+ WorkspaceHandle,
4
+ WorkspaceOptions,
5
+ WorkspaceOptionUpdates,
6
+ WorkspaceEvents,
7
+ WorkspaceChange,
8
+ PaneHandle,
9
+ PaneType,
10
+ PaneTypes,
11
+ AddPaneOptions,
12
+ CloseOptions,
13
+ } from './workspace-api.js';
14
+ export type {
15
+ PaneContext,
16
+ PaneView,
17
+ PaneRenderer,
18
+ TabBarStyle,
19
+ TabBarOptions,
20
+ InitialConfiguration,
21
+ WorkspaceSettings,
22
+ KeyBinding,
23
+ WorkspaceAction,
24
+ ActionContext,
25
+ RegisteredShortcut,
26
+ ShortcutRegistration,
27
+ CloseRequest,
28
+ } from './types.js';
3
29
 
4
30
  export { TabRegistry } from './registry.js';
5
31
  export type { TabRegistration } from './registry.js';
6
32
  export { themes, themeFamilies } from './theme.js';
7
33
  export type { LayoutTheme } from './theme.js';
8
- export { LayoutStore, LayoutError, createLayout, parseLayout, validate } from 'quilt-core';
34
+ export { LayoutError, createLayout, parseLayout, validate } from 'quilt-core';
9
35
  export type {
10
36
  AutoCollapse,
11
- LayoutStoreOptions,
12
37
  Json,
13
38
  Capability,
14
39
  Axis,
@@ -32,3 +57,5 @@ export type { WorkspacePreset } from './workspace.js';
32
57
  export { themeProperties } from './theme.js';
33
58
  export { defaultMessages } from './messages.js';
34
59
  export type { Messages } from './messages.js';
60
+
61
+ export { formatShortcut } from './shortcut-registration.js';