quilt-vanilla 0.2.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -39
- package/dist/actions.d.ts +14 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +115 -0
- package/dist/actions.js.map +1 -0
- package/dist/chrome-size.d.ts +7 -0
- package/dist/chrome-size.d.ts.map +1 -0
- package/dist/chrome-size.js +86 -0
- package/dist/chrome-size.js.map +1 -0
- package/dist/close.d.ts.map +1 -1
- package/dist/close.js +3 -1
- package/dist/close.js.map +1 -1
- package/dist/corners.d.ts +2 -1
- package/dist/corners.d.ts.map +1 -1
- package/dist/corners.js +2 -2
- package/dist/corners.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/menu.d.ts +9 -3
- package/dist/menu.d.ts.map +1 -1
- package/dist/menu.js +110 -37
- package/dist/menu.js.map +1 -1
- package/dist/panes.d.ts.map +1 -1
- package/dist/panes.js +84 -52
- package/dist/panes.js.map +1 -1
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +4 -3
- package/dist/registry.js.map +1 -1
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +128 -36
- package/dist/renderer.js.map +1 -1
- package/dist/resize.d.ts +2 -1
- package/dist/resize.d.ts.map +1 -1
- package/dist/resize.js +2 -2
- package/dist/resize.js.map +1 -1
- package/dist/shortcut-registration.d.ts +9 -0
- package/dist/shortcut-registration.d.ts.map +1 -0
- package/dist/shortcut-registration.js +95 -0
- package/dist/shortcut-registration.js.map +1 -0
- package/dist/shortcuts.d.ts +7 -6
- package/dist/shortcuts.d.ts.map +1 -1
- package/dist/shortcuts.js +28 -50
- package/dist/shortcuts.js.map +1 -1
- package/dist/styles.css +74 -9
- package/dist/tabs.d.ts.map +1 -1
- package/dist/tabs.js +10 -12
- package/dist/tabs.js.map +1 -1
- package/dist/types.d.ts +50 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/workspace-api.d.ts +186 -0
- package/dist/workspace-api.d.ts.map +1 -0
- package/dist/workspace-api.js +409 -0
- package/dist/workspace-api.js.map +1 -0
- package/package.json +2 -2
- package/src/actions.ts +125 -0
- package/src/chrome-size.ts +99 -0
- package/src/close.ts +6 -1
- package/src/corners.ts +2 -1
- package/src/index.ts +31 -4
- package/src/menu.ts +123 -43
- package/src/panes.ts +82 -55
- package/src/registry.ts +6 -4
- package/src/renderer.ts +181 -54
- package/src/resize.ts +2 -1
- package/src/shortcut-registration.ts +106 -0
- package/src/shortcuts.ts +38 -63
- package/src/styles.css +74 -9
- package/src/tabs.ts +9 -11
- package/src/types.ts +67 -14
- package/src/workspace-api.ts +583 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# quilt-vanilla
|
|
2
2
|
|
|
3
|
-
Vanilla DOM pane layouts, tabs, themes, resizing, and same-origin browser popouts.
|
|
3
|
+
Vanilla DOM pane layouts, tabs, themes, resizing, and same-origin browser popouts. Includes layout JSON helpers and does not install React. MIT licensed, ESM and TypeScript.
|
|
4
4
|
|
|
5
5
|
<!-- shared-overview:start -->
|
|
6
6
|
|
|
@@ -43,49 +43,45 @@ Core is installed automatically; React is not required. Use an ESM-capable bundl
|
|
|
43
43
|
Provide a host in your HTML: `<div id="workspace" style="width:100%;height:600px"></div>`.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
|
-
import {
|
|
46
|
+
import { Workspace, type PaneRenderer } from 'quilt-vanilla';
|
|
47
47
|
import 'quilt-vanilla/styles.css';
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
renderers: {
|
|
59
|
-
notes: ({ element, document: doc, state }) => {
|
|
60
|
-
const model = state as typeof data;
|
|
61
|
-
const input = doc.createElement('textarea');
|
|
62
|
-
input.value = model.text;
|
|
63
|
-
input.oninput = () => {
|
|
64
|
-
model.text = input.value;
|
|
65
|
-
};
|
|
66
|
-
element.append(input);
|
|
67
|
-
return {
|
|
68
|
-
dispose() {
|
|
69
|
-
input.oninput = null;
|
|
70
|
-
},
|
|
71
|
-
};
|
|
49
|
+
type NotesState = { text: string };
|
|
50
|
+
const data: NotesState = { text: 'Notes' };
|
|
51
|
+
const notes: PaneRenderer<NotesState> = ({ element, document: doc, state, signal }) => {
|
|
52
|
+
const input = doc.createElement('textarea');
|
|
53
|
+
input.value = state.text;
|
|
54
|
+
input.addEventListener(
|
|
55
|
+
'input',
|
|
56
|
+
() => {
|
|
57
|
+
state.text = input.value;
|
|
72
58
|
},
|
|
73
|
-
|
|
59
|
+
{ signal },
|
|
60
|
+
);
|
|
61
|
+
element.append(input);
|
|
62
|
+
};
|
|
63
|
+
const workspace = new Workspace({
|
|
64
|
+
container: document.getElementById('workspace')!,
|
|
65
|
+
getPaneState: () => data,
|
|
66
|
+
paneTypes: { notes: { title: 'Notes', render: notes } },
|
|
74
67
|
});
|
|
75
|
-
|
|
68
|
+
|
|
69
|
+
const pane = workspace.addPane('notes', { id: 'notes' })!;
|
|
70
|
+
pane.setTitle('My notes');
|
|
71
|
+
|
|
72
|
+
// Call when removing the workspace.
|
|
76
73
|
function disposeWorkspace() {
|
|
77
|
-
|
|
78
|
-
store.dispose();
|
|
74
|
+
workspace.dispose();
|
|
79
75
|
}
|
|
80
76
|
```
|
|
81
77
|
|
|
82
|
-
The host needs an explicit height. Use
|
|
78
|
+
The host needs an explicit height. Use `paneTypes` to supply creation metadata and renderers together; advanced `PaneRegistry` and `TabRegistry` integrations are also supported. Quilt generates omitted pane IDs and preserves explicit IDs. `themes`, `themeFamilies`, `LayoutTheme`, and `WorkspaceHandle` are public exports. The layout JSON type is `LayoutSnapshot` from this entry point.
|
|
83
79
|
|
|
84
|
-
Call `
|
|
80
|
+
Call `workspace.popout(id)` from a user action. Companions are same-origin and owned by the main session. Use the supplied document/window inside renderers and use `signal` and `onCleanup` to release view-owned resources. Keep app data outside view lifetimes.
|
|
85
81
|
|
|
86
82
|
See [API](https://github.com/niko-dellic/quilt/blob/main/docs/api.md), [lifecycle](https://github.com/niko-dellic/quilt/blob/main/docs/lifecycle.md), and [migration](https://github.com/niko-dellic/quilt/blob/main/docs/migration.md).
|
|
87
83
|
|
|
88
|
-
Use `
|
|
84
|
+
Use `workspace.exportWorkspace()` and `workspace.loadWorkspace(input)` to round-trip
|
|
89
85
|
layout and appearance as JSON. Popouts export docked copies without closing live
|
|
90
86
|
windows. `popout` returns `Promise<boolean>` and must be called from a user gesture.
|
|
91
87
|
See [web integration](https://github.com/niko-dellic/quilt/blob/main/docs/integration.md)
|
|
@@ -95,13 +91,13 @@ for unified registration, custom themes, close confirmation, and storage example
|
|
|
95
91
|
|
|
96
92
|
## Documentation
|
|
97
93
|
|
|
98
|
-
- [
|
|
99
|
-
- [
|
|
100
|
-
- [
|
|
101
|
-
- [
|
|
102
|
-
- [
|
|
103
|
-
- [
|
|
104
|
-
- [
|
|
94
|
+
- [Getting started](https://quilt-layouts.vercel.app/docs/)
|
|
95
|
+
- [API reference](https://quilt-layouts.vercel.app/docs/api-reference/)
|
|
96
|
+
- [Themes and tab bars](https://quilt-layouts.vercel.app/docs/theming)
|
|
97
|
+
- [Registration, React context, persistence, and confirmation](https://quilt-layouts.vercel.app/docs/integration)
|
|
98
|
+
- [Examples](https://quilt-layouts.vercel.app/docs/examples)
|
|
99
|
+
- [Troubleshooting](https://quilt-layouts.vercel.app/docs/troubleshooting)
|
|
100
|
+
- [Migration](https://quilt-layouts.vercel.app/docs/migration)
|
|
105
101
|
- [Changelog](https://github.com/niko-dellic/quilt/blob/main/CHANGELOG.md)
|
|
106
102
|
|
|
107
103
|
<!-- shared-docs:end -->
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Group, Pane } from 'quilt-core';
|
|
2
|
+
import type { ActionContext, ResolvedLayoutOptions, WorkspaceAction } from './types.js';
|
|
3
|
+
export declare function createActions(options: ResolvedLayoutOptions, dependencies: {
|
|
4
|
+
context(): ActionContext;
|
|
5
|
+
disposed(): boolean;
|
|
6
|
+
create(action: WorkspaceAction, group: Group, pane: Pane | undefined): void;
|
|
7
|
+
close(id: string, kind?: 'pane' | 'group'): Promise<boolean>;
|
|
8
|
+
popout(id: string): Promise<boolean>;
|
|
9
|
+
report(error: unknown): void;
|
|
10
|
+
}): {
|
|
11
|
+
canExecuteAction: (action: WorkspaceAction, context?: ActionContext) => boolean;
|
|
12
|
+
executeAction: (action: WorkspaceAction, context?: ActionContext) => Promise<boolean>;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGxF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,qBAAqB,EAC9B,YAAY,EAAE;IACZ,OAAO,IAAI,aAAa,CAAC;IACzB,QAAQ,IAAI,OAAO,CAAC;IACpB,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5E,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;+BAsBiC,eAAe,YAAY,aAAa,KAAG,OAAO;4BAgC/C,eAAe,YAAY,aAAa,KAAG,OAAO,CAAC,OAAO,CAAC;EAwDjG"}
|
package/dist/actions.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { findNode, findParent, groups, paneIds } from 'quilt-core';
|
|
2
|
+
import { actionOrder } from './shortcut-registration.js';
|
|
3
|
+
export function createActions(options, dependencies) {
|
|
4
|
+
function resolve(context) {
|
|
5
|
+
const layout = options.store.getSnapshot();
|
|
6
|
+
const target = context?.groupId !== undefined || context?.paneId !== undefined
|
|
7
|
+
? context
|
|
8
|
+
: dependencies.context();
|
|
9
|
+
const id = target.groupId ??
|
|
10
|
+
(target.paneId === undefined
|
|
11
|
+
? undefined
|
|
12
|
+
: groups(layout.root).find((group) => group.panes.includes(target.paneId))?.id);
|
|
13
|
+
const node = id === undefined ? undefined : findNode(layout.root, id);
|
|
14
|
+
const group = node?.kind === 'group' ? node : undefined;
|
|
15
|
+
const paneId = target.paneId ?? group?.active;
|
|
16
|
+
const pane = paneId ? layout.panes[paneId] : undefined;
|
|
17
|
+
const valid = !(target.groupId !== undefined && !group) &&
|
|
18
|
+
!(target.paneId !== undefined && (!pane || !group?.panes.includes(target.paneId)));
|
|
19
|
+
return { layout, group, pane, valid };
|
|
20
|
+
}
|
|
21
|
+
function canExecuteAction(action, context) {
|
|
22
|
+
if (dependencies.disposed() || !actionOrder.includes(action))
|
|
23
|
+
return false;
|
|
24
|
+
const { layout, group, pane, valid } = resolve(context);
|
|
25
|
+
if (!valid)
|
|
26
|
+
return false;
|
|
27
|
+
if (action === 'restoreClosedTab')
|
|
28
|
+
return options.store.canRestoreClosedTab();
|
|
29
|
+
if (!group)
|
|
30
|
+
return false;
|
|
31
|
+
const allowed = (cap) => group.panes.every((id) => options.store.can(id, cap));
|
|
32
|
+
switch (action) {
|
|
33
|
+
case 'addTab':
|
|
34
|
+
return !!options.tabs?.list().length && allowed('move');
|
|
35
|
+
case 'splitLeft':
|
|
36
|
+
case 'splitRight':
|
|
37
|
+
case 'splitUp':
|
|
38
|
+
case 'splitDown':
|
|
39
|
+
return (!group.panes.length || !!options.tabs?.list().length) && allowed('split');
|
|
40
|
+
case 'closeActiveTab':
|
|
41
|
+
return !!pane && options.store.can(pane.id, 'close');
|
|
42
|
+
case 'closePane':
|
|
43
|
+
return !!group.panes.length && allowed('close');
|
|
44
|
+
case 'closeEmptyPane':
|
|
45
|
+
return !group.panes.length && group.id !== layout.root.id;
|
|
46
|
+
case 'popout':
|
|
47
|
+
return options.popouts !== false && !!pane && options.store.can(pane.id, 'popout');
|
|
48
|
+
case 'joinSiblingRegion': {
|
|
49
|
+
const parent = findParent(layout.root, group.id);
|
|
50
|
+
return !!parent && paneIds(parent).every((id) => options.store.can(id, 'join'));
|
|
51
|
+
}
|
|
52
|
+
default:
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function executeAction(action, context) {
|
|
57
|
+
try {
|
|
58
|
+
if (!canExecuteAction(action, context))
|
|
59
|
+
return false;
|
|
60
|
+
const { layout, group, pane } = resolve(context);
|
|
61
|
+
switch (action) {
|
|
62
|
+
case 'restoreClosedTab':
|
|
63
|
+
options.store.restoreClosedTab();
|
|
64
|
+
break;
|
|
65
|
+
case 'maximize':
|
|
66
|
+
options.store.maximize(layout.maximized === group.id ? null : group.id);
|
|
67
|
+
break;
|
|
68
|
+
case 'addTab':
|
|
69
|
+
case 'splitLeft':
|
|
70
|
+
case 'splitRight':
|
|
71
|
+
case 'splitUp':
|
|
72
|
+
case 'splitDown':
|
|
73
|
+
dependencies.create(action, group, pane);
|
|
74
|
+
break;
|
|
75
|
+
case 'closeActiveTab':
|
|
76
|
+
return await dependencies.close(pane.id);
|
|
77
|
+
case 'closePane':
|
|
78
|
+
return await dependencies.close(group.id, 'group');
|
|
79
|
+
case 'closeEmptyPane':
|
|
80
|
+
options.store.removeEmptyGroup(group.id);
|
|
81
|
+
break;
|
|
82
|
+
case 'popout':
|
|
83
|
+
return await dependencies.popout(pane.id);
|
|
84
|
+
case 'joinSiblingRegion':
|
|
85
|
+
options.store.join(group.id, { source: 'user' });
|
|
86
|
+
break;
|
|
87
|
+
case 'tabOrientationDefault':
|
|
88
|
+
options.store.setTabPlacement(group.id, undefined);
|
|
89
|
+
break;
|
|
90
|
+
case 'tabOrientationHorizontal':
|
|
91
|
+
options.store.setTabPlacement(group.id, 'top');
|
|
92
|
+
break;
|
|
93
|
+
case 'tabOrientationVertical':
|
|
94
|
+
options.store.setTabPlacement(group.id, 'left');
|
|
95
|
+
break;
|
|
96
|
+
case 'tabDisplayDefault':
|
|
97
|
+
options.store.setTabDisplay(group.id, undefined);
|
|
98
|
+
break;
|
|
99
|
+
case 'tabDisplayAutomatic':
|
|
100
|
+
options.store.setTabDisplay(group.id, 'automatic');
|
|
101
|
+
break;
|
|
102
|
+
case 'tabDisplayCompact':
|
|
103
|
+
options.store.setTabDisplay(group.id, 'compact');
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
dependencies.report(error);
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { canExecuteAction, executeAction };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import { findNode, findParent, groups, paneIds } from 'quilt-core';\nimport type { Group, Pane } from 'quilt-core';\nimport type { ActionContext, ResolvedLayoutOptions, WorkspaceAction } from './types.js';\nimport { actionOrder } from './shortcut-registration.js';\n\nexport function createActions(\n options: ResolvedLayoutOptions,\n dependencies: {\n context(): ActionContext;\n disposed(): boolean;\n create(action: WorkspaceAction, group: Group, pane: Pane | undefined): void;\n close(id: string, kind?: 'pane' | 'group'): Promise<boolean>;\n popout(id: string): Promise<boolean>;\n report(error: unknown): void;\n },\n) {\n function resolve(context?: ActionContext) {\n const layout = options.store.getSnapshot();\n const target =\n context?.groupId !== undefined || context?.paneId !== undefined\n ? context\n : dependencies.context();\n const id =\n target.groupId ??\n (target.paneId === undefined\n ? undefined\n : groups(layout.root).find((group) => group.panes.includes(target.paneId!))?.id);\n const node = id === undefined ? undefined : findNode(layout.root, id);\n const group = node?.kind === 'group' ? node : undefined;\n const paneId = target.paneId ?? group?.active;\n const pane = paneId ? layout.panes[paneId] : undefined;\n const valid =\n !(target.groupId !== undefined && !group) &&\n !(target.paneId !== undefined && (!pane || !group?.panes.includes(target.paneId)));\n return { layout, group, pane, valid };\n }\n function canExecuteAction(action: WorkspaceAction, context?: ActionContext): boolean {\n if (dependencies.disposed() || !actionOrder.includes(action)) return false;\n const { layout, group, pane, valid } = resolve(context);\n if (!valid) return false;\n if (action === 'restoreClosedTab') return options.store.canRestoreClosedTab();\n if (!group) return false;\n const allowed = (cap: 'split' | 'move' | 'close') =>\n group.panes.every((id) => options.store.can(id, cap));\n switch (action) {\n case 'addTab':\n return !!options.tabs?.list().length && allowed('move');\n case 'splitLeft':\n case 'splitRight':\n case 'splitUp':\n case 'splitDown':\n return (!group.panes.length || !!options.tabs?.list().length) && allowed('split');\n case 'closeActiveTab':\n return !!pane && options.store.can(pane.id, 'close');\n case 'closePane':\n return !!group.panes.length && allowed('close');\n case 'closeEmptyPane':\n return !group.panes.length && group.id !== layout.root.id;\n case 'popout':\n return options.popouts !== false && !!pane && options.store.can(pane.id, 'popout');\n case 'joinSiblingRegion': {\n const parent = findParent(layout.root, group.id);\n return !!parent && paneIds(parent).every((id) => options.store.can(id, 'join'));\n }\n default:\n return true;\n }\n }\n async function executeAction(action: WorkspaceAction, context?: ActionContext): Promise<boolean> {\n try {\n if (!canExecuteAction(action, context)) return false;\n const { layout, group, pane } = resolve(context);\n switch (action) {\n case 'restoreClosedTab':\n options.store.restoreClosedTab();\n break;\n case 'maximize':\n options.store.maximize(layout.maximized === group!.id ? null : group!.id);\n break;\n case 'addTab':\n case 'splitLeft':\n case 'splitRight':\n case 'splitUp':\n case 'splitDown':\n dependencies.create(action, group!, pane);\n break;\n case 'closeActiveTab':\n return await dependencies.close(pane!.id);\n case 'closePane':\n return await dependencies.close(group!.id, 'group');\n case 'closeEmptyPane':\n options.store.removeEmptyGroup(group!.id);\n break;\n case 'popout':\n return await dependencies.popout(pane!.id);\n case 'joinSiblingRegion':\n options.store.join(group!.id, { source: 'user' });\n break;\n case 'tabOrientationDefault':\n options.store.setTabPlacement(group!.id, undefined);\n break;\n case 'tabOrientationHorizontal':\n options.store.setTabPlacement(group!.id, 'top');\n break;\n case 'tabOrientationVertical':\n options.store.setTabPlacement(group!.id, 'left');\n break;\n case 'tabDisplayDefault':\n options.store.setTabDisplay(group!.id, undefined);\n break;\n case 'tabDisplayAutomatic':\n options.store.setTabDisplay(group!.id, 'automatic');\n break;\n case 'tabDisplayCompact':\n options.store.setTabDisplay(group!.id, 'compact');\n break;\n }\n return true;\n } catch (error) {\n dependencies.report(error);\n return false;\n }\n }\n return { canExecuteAction, executeAction };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TabBarStyle } from './types.js';
|
|
2
|
+
/** Measure only chrome, at its smallest presentation, without touching live views. */
|
|
3
|
+
export declare function chromeMinimum(region: HTMLElement, header: HTMLElement, style: TabBarStyle): {
|
|
4
|
+
minWidth: number;
|
|
5
|
+
minHeight: number;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=chrome-size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-size.d.ts","sourceRoot":"","sources":["../src/chrome-size.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,sFAAsF;AACtF,wBAAgB,aAAa,CAC3B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,WAAW,GACjB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CA0FzC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { themePixels } from './theme.js';
|
|
2
|
+
/** Measure only chrome, at its smallest presentation, without touching live views. */
|
|
3
|
+
export function chromeMinimum(region, header, style) {
|
|
4
|
+
if (header.hidden)
|
|
5
|
+
return { minWidth: 0, minHeight: 0 };
|
|
6
|
+
const doc = region.ownerDocument;
|
|
7
|
+
const win = doc.defaultView;
|
|
8
|
+
const left = style.placement === 'left';
|
|
9
|
+
const compact = style.display === 'compact';
|
|
10
|
+
const probe = region.cloneNode(false);
|
|
11
|
+
probe.removeAttribute('id');
|
|
12
|
+
probe.removeAttribute('data-node-id');
|
|
13
|
+
probe.dataset.tabPlacement = left ? 'left' : 'top';
|
|
14
|
+
probe.dataset.tabDisplay = compact ? 'compact' : 'automatic';
|
|
15
|
+
probe.dataset.tabAttachment = 'anchored';
|
|
16
|
+
probe.dataset.tabBar = 'full';
|
|
17
|
+
probe.dataset.tabBarFilled = 'true';
|
|
18
|
+
probe.setAttribute('aria-hidden', 'true');
|
|
19
|
+
probe.inert = true;
|
|
20
|
+
probe.style.cssText =
|
|
21
|
+
'position:fixed;left:-10000px;top:0;width:10000px;height:10000px;visibility:hidden;pointer-events:none';
|
|
22
|
+
const bar = header.cloneNode(true);
|
|
23
|
+
bar.removeAttribute('style');
|
|
24
|
+
bar.dataset.tabDisplay = probe.dataset.tabDisplay;
|
|
25
|
+
bar.querySelectorAll('[id]').forEach((element) => element.removeAttribute('id'));
|
|
26
|
+
bar
|
|
27
|
+
.querySelectorAll('.layouts-tab-cap,.layouts-tab-outline')
|
|
28
|
+
.forEach((element) => element.remove());
|
|
29
|
+
probe.append(bar);
|
|
30
|
+
region.parentElement.append(probe);
|
|
31
|
+
try {
|
|
32
|
+
const css = (element) => win.getComputedStyle(element);
|
|
33
|
+
const px = (value) => parseFloat(value) || 0; // Computed CSS dimensions are pixels.
|
|
34
|
+
const outer = (element, vertical) => {
|
|
35
|
+
const c = css(element);
|
|
36
|
+
return ((vertical
|
|
37
|
+
? element.getBoundingClientRect().height
|
|
38
|
+
: element.getBoundingClientRect().width) +
|
|
39
|
+
px(vertical ? c.marginTop : c.marginLeft) +
|
|
40
|
+
px(vertical ? c.marginBottom : c.marginRight));
|
|
41
|
+
};
|
|
42
|
+
const items = [...bar.querySelectorAll('.layouts-tab-item')];
|
|
43
|
+
const icon = themePixels(region, '--layouts-icon-size', 16);
|
|
44
|
+
for (const item of items) {
|
|
45
|
+
item.querySelector('.layouts-tab-label').style.display = 'none';
|
|
46
|
+
if (!left) {
|
|
47
|
+
const close = item.querySelector('.layouts-tab-close');
|
|
48
|
+
const showClose = !compact && item.dataset.active === 'true' && !!close;
|
|
49
|
+
if (close)
|
|
50
|
+
close.style.display = showClose ? 'block' : 'none';
|
|
51
|
+
const minimum = Math.max(px(css(item).minWidth), icon + (compact ? 16 : 8) + (showClose ? outer(close, false) : 0));
|
|
52
|
+
item.style.flex = '0 0 ' + minimum + 'px';
|
|
53
|
+
item.style.width = minimum + 'px';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const list = bar.querySelector('.layouts-tabs');
|
|
57
|
+
const controls = [...bar.children].filter((child) => child instanceof win.HTMLElement && child.classList.contains('layouts-button'));
|
|
58
|
+
const c = css(bar);
|
|
59
|
+
const listCss = css(list);
|
|
60
|
+
const tabs = items.reduce((sum, item) => sum + outer(item, left), 0) +
|
|
61
|
+
Math.max(0, items.length - 1) * px(left ? listCss.rowGap : listCss.columnGap);
|
|
62
|
+
const main = tabs +
|
|
63
|
+
controls.reduce((sum, control) => sum + outer(control, left), 0) +
|
|
64
|
+
Math.max(0, controls.length + (items.length ? 1 : 0) - 1) *
|
|
65
|
+
px(left ? c.rowGap : c.columnGap) +
|
|
66
|
+
px(left ? c.paddingTop : c.paddingLeft) +
|
|
67
|
+
px(left ? c.paddingBottom : c.paddingRight) +
|
|
68
|
+
px(left ? c.borderTopWidth : c.borderLeftWidth) +
|
|
69
|
+
px(left ? c.borderBottomWidth : c.borderRightWidth);
|
|
70
|
+
const cross = left ? bar.getBoundingClientRect().width : bar.getBoundingClientRect().height;
|
|
71
|
+
// Reserve the possible content scrollbar gutter for floating chrome. This also
|
|
72
|
+
// prevents the minimum from oscillating as content begins/stops scrolling.
|
|
73
|
+
const inset = style.attachment === 'floating'
|
|
74
|
+
? 2 * Math.max(0, themePixels(region, '--layouts-panel-padding', 8)) +
|
|
75
|
+
Math.max(0, themePixels(region, '--layouts-scrollbar-size', 6))
|
|
76
|
+
: 0;
|
|
77
|
+
return {
|
|
78
|
+
minWidth: Math.ceil((left ? cross : main) + inset),
|
|
79
|
+
minHeight: Math.ceil((left ? main : cross) + inset),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
probe.remove();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=chrome-size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-size.js","sourceRoot":"","sources":["../src/chrome-size.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAC3B,MAAmB,EACnB,MAAmB,EACnB,KAAkB;IAElB,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC;IACjC,MAAM,GAAG,GAAG,GAAG,CAAC,WAAY,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAgB,CAAC;IACrD,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC5B,KAAK,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;IACtC,KAAK,CAAC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACnD,KAAK,CAAC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7D,KAAK,CAAC,OAAO,CAAC,aAAa,GAAG,UAAU,CAAC;IACzC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAC9B,KAAK,CAAC,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC;IACpC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC1C,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,KAAK,CAAC,KAAK,CAAC,OAAO;QACjB,uGAAuG,CAAC;IAC1G,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAgB,CAAC;IAClD,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAC7B,GAAG,CAAC,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;IAClD,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IACjF,GAAG;SACA,gBAAgB,CAAC,uCAAuC,CAAC;SACzD,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAClB,MAAM,CAAC,aAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,sCAAsC;QAC5F,MAAM,KAAK,GAAG,CAAC,OAAoB,EAAE,QAAiB,EAAE,EAAE;YACxD,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,CACL,CAAC,QAAQ;gBACP,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,MAAM;gBACxC,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC;gBAC1C,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;gBACzC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAC9C,CAAC;QACJ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,gBAAgB,CAAc,mBAAmB,CAAC,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,aAAa,CAAc,oBAAoB,CAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;YAC9E,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAc,oBAAoB,CAAC,CAAC;gBACpE,MAAM,SAAS,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC;gBACxE,IAAI,KAAK;oBAAE,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CACtB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EACtB,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnE,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;gBAC1C,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC;YACpC,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAc,eAAe,CAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CACvC,CAAC,KAAK,EAAwB,EAAE,CAC9B,KAAK,YAAY,GAAG,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CACjF,CAAC;QACF,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,IAAI,GACR,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YACvD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChF,MAAM,IAAI,GACR,IAAI;YACJ,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBACvD,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACnC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;YACvC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YAC3C,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;YAC/C,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC;QAC5F,+EAA+E;QAC/E,2EAA2E;QAC3E,MAAM,KAAK,GACT,KAAK,CAAC,UAAU,KAAK,UAAU;YAC7B,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC;gBAClE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC,CAAC;QACR,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YAClD,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;SACpD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,MAAM,EAAE,CAAC;IACjB,CAAC;AACH,CAAC","sourcesContent":["import type { TabBarStyle } from './types.js';\nimport { themePixels } from './theme.js';\n\n/** Measure only chrome, at its smallest presentation, without touching live views. */\nexport function chromeMinimum(\n region: HTMLElement,\n header: HTMLElement,\n style: TabBarStyle,\n): { minWidth: number; minHeight: number } {\n if (header.hidden) return { minWidth: 0, minHeight: 0 };\n const doc = region.ownerDocument;\n const win = doc.defaultView!;\n const left = style.placement === 'left';\n const compact = style.display === 'compact';\n const probe = region.cloneNode(false) as HTMLElement;\n probe.removeAttribute('id');\n probe.removeAttribute('data-node-id');\n probe.dataset.tabPlacement = left ? 'left' : 'top';\n probe.dataset.tabDisplay = compact ? 'compact' : 'automatic';\n probe.dataset.tabAttachment = 'anchored';\n probe.dataset.tabBar = 'full';\n probe.dataset.tabBarFilled = 'true';\n probe.setAttribute('aria-hidden', 'true');\n probe.inert = true;\n probe.style.cssText =\n 'position:fixed;left:-10000px;top:0;width:10000px;height:10000px;visibility:hidden;pointer-events:none';\n const bar = header.cloneNode(true) as HTMLElement;\n bar.removeAttribute('style');\n bar.dataset.tabDisplay = probe.dataset.tabDisplay;\n bar.querySelectorAll('[id]').forEach((element) => element.removeAttribute('id'));\n bar\n .querySelectorAll('.layouts-tab-cap,.layouts-tab-outline')\n .forEach((element) => element.remove());\n probe.append(bar);\n region.parentElement!.append(probe);\n try {\n const css = (element: Element) => win.getComputedStyle(element);\n const px = (value: string) => parseFloat(value) || 0; // Computed CSS dimensions are pixels.\n const outer = (element: HTMLElement, vertical: boolean) => {\n const c = css(element);\n return (\n (vertical\n ? element.getBoundingClientRect().height\n : element.getBoundingClientRect().width) +\n px(vertical ? c.marginTop : c.marginLeft) +\n px(vertical ? c.marginBottom : c.marginRight)\n );\n };\n const items = [...bar.querySelectorAll<HTMLElement>('.layouts-tab-item')];\n const icon = themePixels(region, '--layouts-icon-size', 16);\n for (const item of items) {\n item.querySelector<HTMLElement>('.layouts-tab-label')!.style.display = 'none';\n if (!left) {\n const close = item.querySelector<HTMLElement>('.layouts-tab-close');\n const showClose = !compact && item.dataset.active === 'true' && !!close;\n if (close) close.style.display = showClose ? 'block' : 'none';\n const minimum = Math.max(\n px(css(item).minWidth),\n icon + (compact ? 16 : 8) + (showClose ? outer(close!, false) : 0),\n );\n item.style.flex = '0 0 ' + minimum + 'px';\n item.style.width = minimum + 'px';\n }\n }\n const list = bar.querySelector<HTMLElement>('.layouts-tabs')!;\n const controls = [...bar.children].filter(\n (child): child is HTMLElement =>\n child instanceof win.HTMLElement && child.classList.contains('layouts-button'),\n );\n const c = css(bar);\n const listCss = css(list);\n const tabs =\n items.reduce((sum, item) => sum + outer(item, left), 0) +\n Math.max(0, items.length - 1) * px(left ? listCss.rowGap : listCss.columnGap);\n const main =\n tabs +\n controls.reduce((sum, control) => sum + outer(control, left), 0) +\n Math.max(0, controls.length + (items.length ? 1 : 0) - 1) *\n px(left ? c.rowGap : c.columnGap) +\n px(left ? c.paddingTop : c.paddingLeft) +\n px(left ? c.paddingBottom : c.paddingRight) +\n px(left ? c.borderTopWidth : c.borderLeftWidth) +\n px(left ? c.borderBottomWidth : c.borderRightWidth);\n const cross = left ? bar.getBoundingClientRect().width : bar.getBoundingClientRect().height;\n // Reserve the possible content scrollbar gutter for floating chrome. This also\n // prevents the minimum from oscillating as content begins/stops scrolling.\n const inset =\n style.attachment === 'floating'\n ? 2 * Math.max(0, themePixels(region, '--layouts-panel-padding', 8)) +\n Math.max(0, themePixels(region, '--layouts-scrollbar-size', 6))\n : 0;\n return {\n minWidth: Math.ceil((left ? cross : main) + inset),\n minHeight: Math.ceil((left ? main : cross) + inset),\n };\n } finally {\n probe.remove();\n }\n}\n"]}
|
package/dist/close.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../src/close.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAM,KAAK,EAAE,MAAM,eAAe,CAAC;AAE1C,wBAAgB,aAAa,CAC3B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,QASd,MAAM,SAAQ,MAAM,GAAG,OAAO,KAAY,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"close.d.ts","sourceRoot":"","sources":["../src/close.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAM,KAAK,EAAE,MAAM,eAAe,CAAC;AAE1C,wBAAgB,aAAa,CAC3B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,QASd,MAAM,SAAQ,MAAM,GAAG,OAAO,KAAY,OAAO,CAAC,OAAO,CAAC,CA0G7E"}
|
package/dist/close.js
CHANGED
|
@@ -32,7 +32,9 @@ export function closeRequests(root, options, scope, report) {
|
|
|
32
32
|
};
|
|
33
33
|
let cleanup = () => { };
|
|
34
34
|
try {
|
|
35
|
-
|
|
35
|
+
const target = kind === 'group' ? findNode(options.store.getSnapshot().root, id) : undefined;
|
|
36
|
+
if ((!panes.length && target?.kind !== 'group') ||
|
|
37
|
+
panes.some((pane) => !options.store.can(pane.id, 'close')))
|
|
36
38
|
return false;
|
|
37
39
|
if (requiringConfirmation.length) {
|
|
38
40
|
const decision = options.confirmClose
|
package/dist/close.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"close.js","sourceRoot":"","sources":["../src/close.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,MAAM,UAAU,aAAa,CAC3B,IAAiB,EACjB,OAA8B,EAC9B,KAAY,EACZ,MAAgC;IAEhC,IAAI,OAAoC,CAAC;IACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;QACb,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACpE,OAAO,KAAK,EAAE,EAAU,EAAE,IAAI,GAAqB,MAAM,EAAoB,EAAE;QAC7E,IAAI,OAAO,IAAI,QAAQ;YAAE,OAAO,KAAK,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,OAAO,GAAG,UAAU,CAAC;QACrB,MAAM,OAAO,GAAG,GAAW,EAAE;YAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACxE,MAAM,GAAG,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACjF,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtF,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;QACxB,MAAM,qBAAqB,GAAG,KAAK,CAAC,MAAM,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,CAAC,YAAY;YACjB,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,YAAY;YAChF,KAAK,CACR,CAAC;QACF,MAAM,OAAO,GAAiB;YAC5B,KAAK;YACL,qBAAqB;YACrB,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7C,CAAC;QACF,IAAI,OAAO,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;QACvB,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"close.js","sourceRoot":"","sources":["../src/close.ts"],"names":[],"mappings":"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","sourcesContent":["import { findNode } from 'quilt-core';\nimport type { Pane } from 'quilt-core';\nimport type { CloseRequest, ResolvedLayoutOptions } from './types.js';\nimport { el, Scope } from './lifetime.js';\nimport { message } from './messages.js';\nexport function closeRequests(\n root: HTMLElement,\n options: ResolvedLayoutOptions,\n scope: Scope,\n report: (error: unknown) => void,\n) {\n let pending: AbortController | undefined;\n let disposed = false;\n scope.add(() => {\n disposed = true;\n pending?.abort();\n });\n const signature = (panes: readonly Pane[]) => JSON.stringify(panes);\n return async (id: string, kind: 'pane' | 'group' = 'pane'): Promise<boolean> => {\n if (pending || disposed) return false;\n const controller = new AbortController();\n pending = controller;\n const collect = (): Pane[] => {\n const snapshot = options.store.getSnapshot();\n const node = kind === 'group' ? findNode(snapshot.root, id) : undefined;\n const ids = kind === 'group' ? (node?.kind === 'group' ? node.panes : []) : [id];\n return ids.map((key) => snapshot.panes[key]).filter((pane): pane is Pane => !!pane);\n };\n const panes = collect();\n const requiringConfirmation = panes.filter(\n (pane) =>\n pane.confirmClose ??\n options.registry?.list().find((entry) => entry.type === pane.type)?.confirmClose ??\n false,\n );\n const request: CloseRequest = {\n panes,\n requiringConfirmation,\n signal: controller.signal,\n ...(kind === 'group' ? { groupId: id } : {}),\n };\n let cleanup = () => {};\n try {\n const target = kind === 'group' ? findNode(options.store.getSnapshot().root, id) : undefined;\n if (\n (!panes.length && target?.kind !== 'group') ||\n panes.some((pane) => !options.store.can(pane.id, 'close'))\n )\n return false;\n if (requiringConfirmation.length) {\n const decision = options.confirmClose\n ? Promise.resolve(options.confirmClose(request))\n : new Promise<boolean>((resolve) => {\n const dialog = el(root.ownerDocument, 'dialog', 'layouts-menu layouts-confirm');\n dialog.setAttribute('aria-label', message(options, 'Close selected panes?'));\n const title = el(\n root.ownerDocument,\n 'h2',\n '',\n message(options, 'Close selected panes?'),\n );\n const list = el(\n root.ownerDocument,\n 'p',\n '',\n requiringConfirmation.map((pane) => pane.title).join(', '),\n );\n const cancel = el(\n root.ownerDocument,\n 'button',\n 'layouts-button',\n message(options, 'Cancel'),\n );\n const close = el(\n root.ownerDocument,\n 'button',\n 'layouts-button',\n message(options, 'Close'),\n );\n cancel.type = close.type = 'button';\n cancel.onclick = () => resolve(false);\n close.onclick = () => resolve(true);\n dialog.oncancel = (event) => {\n event.preventDefault();\n resolve(false);\n };\n dialog.append(title, list, cancel, close);\n root.append(dialog);\n cleanup = () => dialog.remove();\n dialog.showModal();\n cancel.focus();\n });\n const aborted = new Promise<boolean>((resolve) =>\n controller.signal.addEventListener('abort', () => resolve(false), { once: true }),\n );\n const unsubscribe = options.store.subscribe((event) => {\n if (event.action === 'load' || signature(collect()) !== signature(panes))\n controller.abort();\n });\n const previousCleanup = cleanup;\n cleanup = () => {\n unsubscribe();\n previousCleanup();\n };\n if (!(await Promise.race([decision, aborted]))) return false;\n }\n if (\n controller.signal.aborted ||\n signature(collect()) !== signature(panes) ||\n panes.some((pane) => !options.store.can(pane.id, 'close'))\n )\n return false;\n if (kind === 'group') options.store.closeGroup(id, { source: 'user' });\n else options.store.close(id, { source: 'user' });\n return true;\n } catch (error) {\n report(error);\n return false;\n } finally {\n cleanup();\n controller.abort();\n if (pending === controller) pending = undefined;\n }\n };\n}\n"]}
|
package/dist/corners.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { bounds } from 'quilt-core';
|
|
1
2
|
import type { Group, Pane } from 'quilt-core';
|
|
2
3
|
import type { ResolvedLayoutOptions } from './types.js';
|
|
3
4
|
import { Scope } from './lifetime.js';
|
|
4
5
|
type Direction = 'left' | 'right' | 'top' | 'bottom';
|
|
5
6
|
/** Commit once on release; cancellation never changes the layout or pane ownership. */
|
|
6
|
-
export declare function bindCorners(host: HTMLElement, id: string, options: ResolvedLayoutOptions, scope: Scope, split: (pane: Pane | undefined, group: Group, direction: Direction, ratio: number) => void, report: (error: unknown) => void): void;
|
|
7
|
+
export declare function bindCorners(host: HTMLElement, id: string, options: ResolvedLayoutOptions, scope: Scope, split: (pane: Pane | undefined, group: Group, direction: Direction, ratio: number) => void, report: (error: unknown) => void, measureBounds?: typeof bounds): void;
|
|
7
8
|
export {};
|
|
8
9
|
//# sourceMappingURL=corners.d.ts.map
|
package/dist/corners.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"corners.d.ts","sourceRoot":"","sources":["../src/corners.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"corners.d.ts","sourceRoot":"","sources":["../src/corners.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,MAAM,EAAgC,MAAM,YAAY,CAAC;AAC5E,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAM,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1C,KAAK,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AACrD,uFAAuF;AACvF,wBAAgB,WAAW,CACzB,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,EAC1F,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAChC,aAAa,GAAE,OAAO,MAAe,QAwQtC"}
|
package/dist/corners.js
CHANGED
|
@@ -2,7 +2,7 @@ import { message } from './messages.js';
|
|
|
2
2
|
import { allocate, bounds, DIVIDER, findNode, joinRange } from 'quilt-core';
|
|
3
3
|
import { el, Scope } from './lifetime.js';
|
|
4
4
|
/** Commit once on release; cancellation never changes the layout or pane ownership. */
|
|
5
|
-
export function bindCorners(host, id, options, scope, split, report) {
|
|
5
|
+
export function bindCorners(host, id, options, scope, split, report, measureBounds = bounds) {
|
|
6
6
|
const doc = host.ownerDocument;
|
|
7
7
|
let drag;
|
|
8
8
|
scope.add(() => drag?.dispose());
|
|
@@ -90,7 +90,7 @@ export function bindCorners(host, id, options, scope, split, report) {
|
|
|
90
90
|
const current = findNode(layout.root, id);
|
|
91
91
|
if (!current)
|
|
92
92
|
return;
|
|
93
|
-
const constraints =
|
|
93
|
+
const constraints = measureBounds(current, layout);
|
|
94
94
|
const min = horizontal ? constraints.minWidth : constraints.minHeight;
|
|
95
95
|
const max = horizontal ? constraints.maxWidth : constraints.maxHeight;
|
|
96
96
|
const total = horizontal ? rect.width : rect.height;
|
package/dist/corners.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"corners.js","sourceRoot":"","sources":["../src/corners.ts"],"names":[],"mappings":"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","sourcesContent":["import { message } from './messages.js';\nimport { allocate, bounds, DIVIDER, findNode, joinRange } from 'quilt-core';\nimport type { Group, Pane } from 'quilt-core';\nimport type { ResolvedLayoutOptions } from './types.js';\nimport { el, Scope } from './lifetime.js';\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n/** Commit once on release; cancellation never changes the layout or pane ownership. */\nexport function bindCorners(\n host: HTMLElement,\n id: string,\n options: ResolvedLayoutOptions,\n scope: Scope,\n split: (pane: Pane | undefined, group: Group, direction: Direction, ratio: number) => void,\n report: (error: unknown) => void,\n) {\n const doc = host.ownerDocument;\n let drag: Scope | undefined;\n scope.add(() => drag?.dispose());\n const initial = findNode(options.store.getSnapshot().root, id);\n if (initial?.kind !== 'group' || !initial.panes.every((p) => options.store.can(p, 'split')))\n return;\n for (const corner of ['tl', 'tr', 'bl', 'br']) {\n const handle = el(doc, 'button', 'layouts-corner');\n handle.dataset.corner = corner;\n handle.title = message(\n options,\n 'Drag inward to split; drag across adjacent regions to join. Escape cancels.',\n );\n handle.setAttribute(\n 'aria-label',\n message(options, 'Split or join region from {corner} corner', { corner }),\n );\n handle.tabIndex = -1; // Equivalent keyboard operations live in the pane menu.\n host.append(handle);\n scope.add(() => handle.remove());\n scope.listen(handle, 'pointerdown', (event) => {\n const start = event as PointerEvent;\n if (start.button !== 0) return;\n const node = findNode(options.store.getSnapshot().root, id);\n if (node?.kind !== 'group' || !node.panes.every((p) => options.store.can(p, 'split'))) return;\n event.preventDefault();\n event.stopPropagation();\n drag?.dispose();\n const local = new Scope();\n drag = local;\n local.add(options.store.subscribe(() => local.dispose()));\n handle.setPointerCapture(start.pointerId);\n let target:\n | { kind: 'split'; direction: Direction; ratio: number }\n | { kind: 'join'; id: string; extents: Record<string, number> }\n | undefined;\n const overlay = el(doc, 'div', 'layouts-corner-overlay');\n overlay.setAttribute('aria-hidden', 'true');\n host.closest('.layouts')!.append(overlay);\n local.add(() => overlay.remove());\n const mark = (\n rect: { left: number; top: number; width: number; height: number },\n kind: string,\n label: string,\n ) => {\n const box = el(doc, 'div', 'layouts-corner-preview');\n box.dataset.cornerPreview = kind;\n Object.assign(box.style, {\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n box.append(el(doc, 'span', 'layouts-corner-label', label));\n overlay.append(box);\n };\n const clear = () => {\n overlay.replaceChildren();\n target = undefined;\n };\n local.add(() => {\n clear();\n try {\n handle.releasePointerCapture(start.pointerId);\n } catch {}\n });\n local.listen(handle, 'pointermove', (e) => {\n const move = e as PointerEvent;\n clear();\n if (Math.hypot(move.clientX - start.clientX, move.clientY - start.clientY) < 24) return;\n const rect = host.getBoundingClientRect();\n const inside =\n move.clientX > rect.left &&\n move.clientX < rect.right &&\n move.clientY > rect.top &&\n move.clientY < rect.bottom;\n if (inside) {\n const horizontal =\n Math.abs(move.clientX - start.clientX) > Math.abs(move.clientY - start.clientY);\n const direction: Direction = horizontal\n ? corner.endsWith('l')\n ? 'left'\n : 'right'\n : corner.startsWith('t')\n ? 'top'\n : 'bottom';\n target = {\n kind: 'split',\n direction,\n ratio: Math.max(\n 0.1,\n Math.min(\n 0.9,\n horizontal\n ? (move.clientX - rect.left) / rect.width\n : (move.clientY - rect.top) / rect.height,\n ),\n ),\n };\n const before = direction === 'left' || direction === 'top';\n const layout = options.store.getSnapshot();\n const current = findNode(layout.root, id);\n if (!current) return;\n const constraints = bounds(current, layout);\n const min = horizontal ? constraints.minWidth : constraints.minHeight;\n const max = horizontal ? constraints.maxWidth : constraints.maxHeight;\n const total = horizontal ? rect.width : rect.height;\n const disabled =\n current.kind === 'group' &&\n (!current.panes.every((p) => options.store.can(p, 'resize')) || min === max);\n const configuredGap = parseFloat(\n doc\n .defaultView!.getComputedStyle(host.closest('.layouts')!)\n .getPropertyValue(\n disabled\n ? '--layouts-disabled-resize-handle-width'\n : '--layouts-resize-handle-width',\n ),\n );\n const gap =\n Number.isFinite(configuredGap) && configuredGap >= 0\n ? configuredGap\n : disabled\n ? 0\n : DIVIDER;\n const [first, second] = allocate(\n total,\n target.ratio,\n before ? 0 : min,\n before ? Infinity : max,\n before ? min : 0,\n before ? max : Infinity,\n gap,\n );\n // Store uses content extents (excluding the divider), matching this preview exactly.\n const newRect = horizontal\n ? {\n left: rect.left + (before ? 0 : first + gap),\n top: rect.top,\n width: before ? first : second,\n height: rect.height,\n }\n : {\n left: rect.left,\n top: rect.top + (before ? 0 : first + gap),\n width: rect.width,\n height: before ? first : second,\n };\n mark(newRect, 'split', message(options, 'New pane'));\n } else {\n const layout = options.store.getSnapshot();\n const elements = Array.from(\n host.closest('.layouts')!.querySelectorAll<HTMLElement>('[data-node-id]'),\n ).filter((element) => element.closest('.layouts') === host.closest('.layouts'));\n const boxes = new Map(\n elements.map((element) => [element.dataset.nodeId!, element.getBoundingClientRect()]),\n );\n const hovered = elements.find((element) => {\n const candidate = findNode(layout.root, element.dataset.nodeId!);\n const box = boxes.get(element.dataset.nodeId!)!;\n return (\n candidate?.kind === 'group' &&\n move.clientX >= box.left &&\n move.clientX <= box.right &&\n move.clientY >= box.top &&\n move.clientY <= box.bottom\n );\n });\n if (!hovered) return;\n const receiverId = hovered.dataset.nodeId!;\n const range = joinRange(layout.root, id, receiverId);\n if (\n !range ||\n !range.selected.every((g) => g.panes.every((p) => options.store.can(p, 'join')))\n )\n return;\n const receiver = findNode(layout.root, receiverId);\n if (receiver?.kind !== 'group') return;\n const selectedBoxes = range.selected.map((g) => boxes.get(g.id));\n if (selectedBoxes.some((box) => !box)) return;\n // Require full-edge alignment in the rendered layout too (constraints can leave slack).\n const horizontal = range.row.axis === 'horizontal';\n if (\n selectedBoxes.some((box) =>\n horizontal\n ? Math.abs(box!.top - rect.top) > 1 || Math.abs(box!.bottom - rect.bottom) > 1\n : Math.abs(box!.left - rect.left) > 1 || Math.abs(box!.right - rect.right) > 1,\n )\n )\n return;\n const extents = Object.fromEntries(\n [...boxes].map(([nodeId, box]) => [nodeId, horizontal ? box.width : box.height]),\n );\n target = { kind: 'join', id: receiverId, extents };\n const targetTitle =\n layout.panes[receiver.active ?? '']?.title ?? message(options, 'Empty region');\n const sources = range.selected.filter((g) => g.id !== receiverId);\n const sourceLabel = sources.every((g) => g.panes.length === 0)\n ? message(\n options,\n sources.length === 1 ? '{count} empty region' : '{count} empty regions',\n { count: sources.length },\n )\n : sources\n .map((g) => layout.panes[g.active ?? '']?.title ?? message(options, 'Empty region'))\n .join(', ');\n for (const group of range.selected) {\n const receiving = group.id === receiverId;\n mark(\n boxes.get(group.id)!,\n receiving ? 'join-target' : 'join-source',\n receiving\n ? message(options, '{target} absorbs {source}', {\n target: targetTitle,\n source: sourceLabel,\n })\n : message(options, 'Joins {target}', { target: targetTitle }),\n );\n }\n const left = Math.min(...selectedBoxes.map((box) => box!.left));\n const top = Math.min(...selectedBoxes.map((box) => box!.top));\n mark(\n {\n left,\n top,\n width: Math.max(...selectedBoxes.map((box) => box!.right)) - left,\n height: Math.max(...selectedBoxes.map((box) => box!.bottom)) - top,\n },\n 'join',\n '',\n );\n }\n });\n local.listen(handle, 'pointerup', () => {\n const action = target;\n local.dispose();\n if (!action) return;\n try {\n if (action.kind === 'join')\n options.store.joinRegions(action.id, id, { source: 'user', extents: action.extents });\n else {\n const layout = options.store.getSnapshot(),\n group = findNode(layout.root, id);\n if (group?.kind === 'group')\n split(\n group.active ? layout.panes[group.active] : undefined,\n group,\n action.direction,\n action.ratio,\n );\n }\n } catch (error) {\n report(error);\n }\n });\n local.listen(handle, 'pointercancel', () => local.dispose());\n local.listen(handle, 'lostpointercapture', () => local.dispose());\n local.listen(doc, 'keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') local.dispose();\n });\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"corners.js","sourceRoot":"","sources":["../src/corners.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE1C,uFAAuF;AACvF,MAAM,UAAU,WAAW,CACzB,IAAiB,EACjB,EAAU,EACV,OAA8B,EAC9B,KAAY,EACZ,KAA0F,EAC1F,MAAgC,EAChC,aAAa,GAAkB,MAAM;IAErC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;IAC/B,IAAI,IAAuB,CAAC;IAC5B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,OAAO,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACzF,OAAO;IACT,KAAK,MAAM,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;QAC/B,MAAM,CAAC,KAAK,GAAG,OAAO,CACpB,OAAO,EACP,6EAA6E,CAC9E,CAAC;QACF,MAAM,CAAC,YAAY,CACjB,YAAY,EACZ,OAAO,CAAC,OAAO,EAAE,2CAA2C,EAAE,EAAE,MAAM,EAAE,CAAC,CAC1E,CAAC;QACF,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,wDAAwD;QAC9E,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;YAC5C,MAAM,KAAK,GAAG,KAAqB,CAAC;YACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5D,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;gBAAE,OAAO;YAC9F,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,IAAI,EAAE,OAAO,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,GAAG,KAAK,CAAC;YACb,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC1C,IAAI,MAGS,CAAC;YACd,MAAM,OAAO,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,wBAAwB,CAAC,CAAC;YACzD,OAAO,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,CACX,IAAkE,EAClE,IAAY,EACZ,KAAa,EACb,EAAE;gBACF,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,wBAAwB,CAAC,CAAC;gBACrD,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;gBACjC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE;oBACvB,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI;oBACtB,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;oBACpB,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI;oBACxB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI;iBAC3B,CAAC,CAAC;gBACH,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC3D,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtB,CAAC,CAAC;YACF,MAAM,KAAK,GAAG,GAAG,EAAE;gBACjB,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC1B,MAAM,GAAG,SAAS,CAAC;YACrB,CAAC,CAAC;YACF,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;gBACb,KAAK,EAAE,CAAC;gBACR,IAAI,CAAC;oBACH,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAChD,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACZ,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;gBACxC,MAAM,IAAI,GAAG,CAAiB,CAAC;gBAC/B,KAAK,EAAE,CAAC;gBACR,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;oBAAE,OAAO;gBACxF,MAAM,IAAI,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC1C,MAAM,MAAM,GACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI;oBACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK;oBACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG;oBACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC7B,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,UAAU,GACd,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;oBAClF,MAAM,SAAS,GAAc,UAAU;wBACrC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;4BACpB,CAAC,CAAC,MAAM;4BACR,CAAC,CAAC,OAAO;wBACX,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;4BACtB,CAAC,CAAC,KAAK;4BACP,CAAC,CAAC,QAAQ,CAAC;oBACf,MAAM,GAAG;wBACP,IAAI,EAAE,OAAO;wBACb,SAAS;wBACT,KAAK,EAAE,IAAI,CAAC,GAAG,CACb,GAAG,EACH,IAAI,CAAC,GAAG,CACN,GAAG,EACH,UAAU;4BACR,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK;4BACzC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAC5C,CACF;qBACF,CAAC;oBACF,MAAM,MAAM,GAAG,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,KAAK,CAAC;oBAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;oBAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAC1C,IAAI,CAAC,OAAO;wBAAE,OAAO;oBACrB,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBACnD,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC;oBACtE,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC;oBACtE,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;oBACpD,MAAM,QAAQ,GACZ,OAAO,CAAC,IAAI,KAAK,OAAO;wBACxB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;oBAC/E,MAAM,aAAa,GAAG,UAAU,CAC9B,GAAG;yBACA,WAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAE,CAAC;yBACxD,gBAAgB,CACf,QAAQ;wBACN,CAAC,CAAC,wCAAwC;wBAC1C,CAAC,CAAC,+BAA+B,CACpC,CACJ,CAAC;oBACF,MAAM,GAAG,GACP,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,IAAI,CAAC;wBAClD,CAAC,CAAC,aAAa;wBACf,CAAC,CAAC,QAAQ;4BACR,CAAC,CAAC,CAAC;4BACH,CAAC,CAAC,OAAO,CAAC;oBAChB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,QAAQ,CAC9B,KAAK,EACL,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAChB,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,EACvB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAChB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EACvB,GAAG,CACJ,CAAC;oBACF,qFAAqF;oBACrF,MAAM,OAAO,GAAG,UAAU;wBACxB,CAAC,CAAC;4BACE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC;4BAC5C,GAAG,EAAE,IAAI,CAAC,GAAG;4BACb,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;4BAC9B,MAAM,EAAE,IAAI,CAAC,MAAM;yBACpB;wBACH,CAAC,CAAC;4BACE,IAAI,EAAE,IAAI,CAAC,IAAI;4BACf,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC;4BAC1C,KAAK,EAAE,IAAI,CAAC,KAAK;4BACjB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;yBAChC,CAAC;oBACN,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;gBACvD,CAAC;qBAAM,CAAC;oBACN,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;oBAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAE,CAAC,gBAAgB,CAAc,gBAAgB,CAAC,CAC1E,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;oBAChF,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAO,EAAE,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,CACtF,CAAC;oBACF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;wBACxC,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,MAAO,CAAC,CAAC;wBACjE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAO,CAAE,CAAC;wBAChD,OAAO,CACL,SAAS,EAAE,IAAI,KAAK,OAAO;4BAC3B,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI;4BACxB,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK;4BACzB,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,GAAG;4BACvB,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,CAC3B,CAAC;oBACJ,CAAC,CAAC,CAAC;oBACH,IAAI,CAAC,OAAO;wBAAE,OAAO;oBACrB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAO,CAAC;oBAC3C,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;oBACrD,IACE,CAAC,KAAK;wBACN,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;wBAEhF,OAAO;oBACT,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;oBACnD,IAAI,QAAQ,EAAE,IAAI,KAAK,OAAO;wBAAE,OAAO;oBACvC,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oBACjE,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC;wBAAE,OAAO;oBAC9C,wFAAwF;oBACxF,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC;oBACnD,IACE,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CACzB,UAAU;wBACR,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;wBAC9E,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CACjF;wBAED,OAAO;oBACT,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAChC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CACjF,CAAC;oBACF,MAAM,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;oBACnD,MAAM,WAAW,GACf,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;oBACjF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;oBAClE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;wBAC5D,CAAC,CAAC,OAAO,CACL,OAAO,EACP,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,uBAAuB,EACvE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAC1B;wBACH,CAAC,CAAC,OAAO;6BACJ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;6BACnF,IAAI,CAAC,IAAI,CAAC,CAAC;oBAClB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;wBACnC,MAAM,SAAS,GAAG,KAAK,CAAC,EAAE,KAAK,UAAU,CAAC;wBAC1C,IAAI,CACF,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAE,EACpB,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EACzC,SAAS;4BACP,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,2BAA2B,EAAE;gCAC5C,MAAM,EAAE,WAAW;gCACnB,MAAM,EAAE,WAAW;6BACpB,CAAC;4BACJ,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAChE,CAAC;oBACJ,CAAC;oBACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBAChE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAI,CAAC,GAAG,CAAC,CAAC,CAAC;oBAC9D,IAAI,CACF;wBACE,IAAI;wBACJ,GAAG;wBACH,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI;wBACjE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAI,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG;qBACnE,EACD,MAAM,EACN,EAAE,CACH,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE;gBACrC,MAAM,MAAM,GAAG,MAAM,CAAC;gBACtB,KAAK,CAAC,OAAO,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM;oBAAE,OAAO;gBACpB,IAAI,CAAC;oBACH,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;wBACxB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;yBACnF,CAAC;wBACJ,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,EACxC,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;wBACpC,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO;4BACzB,KAAK,CACH,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,EACrD,KAAK,EACL,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,KAAK,CACb,CAAC;oBACN,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7D,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAClE,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gBACjC,IAAK,CAAmB,CAAC,GAAG,KAAK,QAAQ;oBAAE,KAAK,CAAC,OAAO,EAAE,CAAC;YAC7D,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["import { message } from './messages.js';\nimport { allocate, bounds, DIVIDER, findNode, joinRange } from 'quilt-core';\nimport type { Group, Pane } from 'quilt-core';\nimport type { ResolvedLayoutOptions } from './types.js';\nimport { el, Scope } from './lifetime.js';\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n/** Commit once on release; cancellation never changes the layout or pane ownership. */\nexport function bindCorners(\n host: HTMLElement,\n id: string,\n options: ResolvedLayoutOptions,\n scope: Scope,\n split: (pane: Pane | undefined, group: Group, direction: Direction, ratio: number) => void,\n report: (error: unknown) => void,\n measureBounds: typeof bounds = bounds,\n) {\n const doc = host.ownerDocument;\n let drag: Scope | undefined;\n scope.add(() => drag?.dispose());\n const initial = findNode(options.store.getSnapshot().root, id);\n if (initial?.kind !== 'group' || !initial.panes.every((p) => options.store.can(p, 'split')))\n return;\n for (const corner of ['tl', 'tr', 'bl', 'br']) {\n const handle = el(doc, 'button', 'layouts-corner');\n handle.dataset.corner = corner;\n handle.title = message(\n options,\n 'Drag inward to split; drag across adjacent regions to join. Escape cancels.',\n );\n handle.setAttribute(\n 'aria-label',\n message(options, 'Split or join region from {corner} corner', { corner }),\n );\n handle.tabIndex = -1; // Equivalent keyboard operations live in the pane menu.\n host.append(handle);\n scope.add(() => handle.remove());\n scope.listen(handle, 'pointerdown', (event) => {\n const start = event as PointerEvent;\n if (start.button !== 0) return;\n const node = findNode(options.store.getSnapshot().root, id);\n if (node?.kind !== 'group' || !node.panes.every((p) => options.store.can(p, 'split'))) return;\n event.preventDefault();\n event.stopPropagation();\n drag?.dispose();\n const local = new Scope();\n drag = local;\n local.add(options.store.subscribe(() => local.dispose()));\n handle.setPointerCapture(start.pointerId);\n let target:\n | { kind: 'split'; direction: Direction; ratio: number }\n | { kind: 'join'; id: string; extents: Record<string, number> }\n | undefined;\n const overlay = el(doc, 'div', 'layouts-corner-overlay');\n overlay.setAttribute('aria-hidden', 'true');\n host.closest('.layouts')!.append(overlay);\n local.add(() => overlay.remove());\n const mark = (\n rect: { left: number; top: number; width: number; height: number },\n kind: string,\n label: string,\n ) => {\n const box = el(doc, 'div', 'layouts-corner-preview');\n box.dataset.cornerPreview = kind;\n Object.assign(box.style, {\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n box.append(el(doc, 'span', 'layouts-corner-label', label));\n overlay.append(box);\n };\n const clear = () => {\n overlay.replaceChildren();\n target = undefined;\n };\n local.add(() => {\n clear();\n try {\n handle.releasePointerCapture(start.pointerId);\n } catch {}\n });\n local.listen(handle, 'pointermove', (e) => {\n const move = e as PointerEvent;\n clear();\n if (Math.hypot(move.clientX - start.clientX, move.clientY - start.clientY) < 24) return;\n const rect = host.getBoundingClientRect();\n const inside =\n move.clientX > rect.left &&\n move.clientX < rect.right &&\n move.clientY > rect.top &&\n move.clientY < rect.bottom;\n if (inside) {\n const horizontal =\n Math.abs(move.clientX - start.clientX) > Math.abs(move.clientY - start.clientY);\n const direction: Direction = horizontal\n ? corner.endsWith('l')\n ? 'left'\n : 'right'\n : corner.startsWith('t')\n ? 'top'\n : 'bottom';\n target = {\n kind: 'split',\n direction,\n ratio: Math.max(\n 0.1,\n Math.min(\n 0.9,\n horizontal\n ? (move.clientX - rect.left) / rect.width\n : (move.clientY - rect.top) / rect.height,\n ),\n ),\n };\n const before = direction === 'left' || direction === 'top';\n const layout = options.store.getSnapshot();\n const current = findNode(layout.root, id);\n if (!current) return;\n const constraints = measureBounds(current, layout);\n const min = horizontal ? constraints.minWidth : constraints.minHeight;\n const max = horizontal ? constraints.maxWidth : constraints.maxHeight;\n const total = horizontal ? rect.width : rect.height;\n const disabled =\n current.kind === 'group' &&\n (!current.panes.every((p) => options.store.can(p, 'resize')) || min === max);\n const configuredGap = parseFloat(\n doc\n .defaultView!.getComputedStyle(host.closest('.layouts')!)\n .getPropertyValue(\n disabled\n ? '--layouts-disabled-resize-handle-width'\n : '--layouts-resize-handle-width',\n ),\n );\n const gap =\n Number.isFinite(configuredGap) && configuredGap >= 0\n ? configuredGap\n : disabled\n ? 0\n : DIVIDER;\n const [first, second] = allocate(\n total,\n target.ratio,\n before ? 0 : min,\n before ? Infinity : max,\n before ? min : 0,\n before ? max : Infinity,\n gap,\n );\n // Store uses content extents (excluding the divider), matching this preview exactly.\n const newRect = horizontal\n ? {\n left: rect.left + (before ? 0 : first + gap),\n top: rect.top,\n width: before ? first : second,\n height: rect.height,\n }\n : {\n left: rect.left,\n top: rect.top + (before ? 0 : first + gap),\n width: rect.width,\n height: before ? first : second,\n };\n mark(newRect, 'split', message(options, 'New pane'));\n } else {\n const layout = options.store.getSnapshot();\n const elements = Array.from(\n host.closest('.layouts')!.querySelectorAll<HTMLElement>('[data-node-id]'),\n ).filter((element) => element.closest('.layouts') === host.closest('.layouts'));\n const boxes = new Map(\n elements.map((element) => [element.dataset.nodeId!, element.getBoundingClientRect()]),\n );\n const hovered = elements.find((element) => {\n const candidate = findNode(layout.root, element.dataset.nodeId!);\n const box = boxes.get(element.dataset.nodeId!)!;\n return (\n candidate?.kind === 'group' &&\n move.clientX >= box.left &&\n move.clientX <= box.right &&\n move.clientY >= box.top &&\n move.clientY <= box.bottom\n );\n });\n if (!hovered) return;\n const receiverId = hovered.dataset.nodeId!;\n const range = joinRange(layout.root, id, receiverId);\n if (\n !range ||\n !range.selected.every((g) => g.panes.every((p) => options.store.can(p, 'join')))\n )\n return;\n const receiver = findNode(layout.root, receiverId);\n if (receiver?.kind !== 'group') return;\n const selectedBoxes = range.selected.map((g) => boxes.get(g.id));\n if (selectedBoxes.some((box) => !box)) return;\n // Require full-edge alignment in the rendered layout too (constraints can leave slack).\n const horizontal = range.row.axis === 'horizontal';\n if (\n selectedBoxes.some((box) =>\n horizontal\n ? Math.abs(box!.top - rect.top) > 1 || Math.abs(box!.bottom - rect.bottom) > 1\n : Math.abs(box!.left - rect.left) > 1 || Math.abs(box!.right - rect.right) > 1,\n )\n )\n return;\n const extents = Object.fromEntries(\n [...boxes].map(([nodeId, box]) => [nodeId, horizontal ? box.width : box.height]),\n );\n target = { kind: 'join', id: receiverId, extents };\n const targetTitle =\n layout.panes[receiver.active ?? '']?.title ?? message(options, 'Empty region');\n const sources = range.selected.filter((g) => g.id !== receiverId);\n const sourceLabel = sources.every((g) => g.panes.length === 0)\n ? message(\n options,\n sources.length === 1 ? '{count} empty region' : '{count} empty regions',\n { count: sources.length },\n )\n : sources\n .map((g) => layout.panes[g.active ?? '']?.title ?? message(options, 'Empty region'))\n .join(', ');\n for (const group of range.selected) {\n const receiving = group.id === receiverId;\n mark(\n boxes.get(group.id)!,\n receiving ? 'join-target' : 'join-source',\n receiving\n ? message(options, '{target} absorbs {source}', {\n target: targetTitle,\n source: sourceLabel,\n })\n : message(options, 'Joins {target}', { target: targetTitle }),\n );\n }\n const left = Math.min(...selectedBoxes.map((box) => box!.left));\n const top = Math.min(...selectedBoxes.map((box) => box!.top));\n mark(\n {\n left,\n top,\n width: Math.max(...selectedBoxes.map((box) => box!.right)) - left,\n height: Math.max(...selectedBoxes.map((box) => box!.bottom)) - top,\n },\n 'join',\n '',\n );\n }\n });\n local.listen(handle, 'pointerup', () => {\n const action = target;\n local.dispose();\n if (!action) return;\n try {\n if (action.kind === 'join')\n options.store.joinRegions(action.id, id, { source: 'user', extents: action.extents });\n else {\n const layout = options.store.getSnapshot(),\n group = findNode(layout.root, id);\n if (group?.kind === 'group')\n split(\n group.active ? layout.panes[group.active] : undefined,\n group,\n action.direction,\n action.ratio,\n );\n }\n } catch (error) {\n report(error);\n }\n });\n local.listen(handle, 'pointercancel', () => local.dispose());\n local.listen(handle, 'lostpointercapture', () => local.dispose());\n local.listen(doc, 'keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Escape') local.dispose();\n });\n });\n }\n}\n"]}
|