@zenfg/inspector 0.1.0-beta.2 → 0.1.0-beta.4
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/GUIDE.md +182 -0
- package/README.md +60 -26
- package/THEMING.md +124 -0
- package/dist/FrameGraphInspector.d.ts +24 -8
- package/dist/FrameGraphInspector.d.ts.map +1 -1
- package/dist/FrameGraphInspector.js +151 -65
- package/dist/FrameGraphInspector.js.map +1 -1
- package/dist/capture.d.ts +5 -0
- package/dist/capture.d.ts.map +1 -0
- package/dist/capture.js +2 -0
- package/dist/capture.js.map +1 -0
- package/dist/debugCaptureModel.d.ts +28 -4
- package/dist/debugCaptureModel.d.ts.map +1 -1
- package/dist/debugCaptureModel.js +72 -16
- package/dist/debugCaptureModel.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/panelAliasAnalysis.d.ts +1 -0
- package/dist/panelAliasAnalysis.d.ts.map +1 -1
- package/dist/panelAliasAnalysis.js +23 -54
- package/dist/panelAliasAnalysis.js.map +1 -1
- package/dist/panelCytoscapeGraphRenderer.d.ts +18 -3
- package/dist/panelCytoscapeGraphRenderer.d.ts.map +1 -1
- package/dist/panelCytoscapeGraphRenderer.js +183 -41
- package/dist/panelCytoscapeGraphRenderer.js.map +1 -1
- package/dist/panelDetailLayout.d.ts +27 -0
- package/dist/panelDetailLayout.d.ts.map +1 -0
- package/dist/panelDetailLayout.js +174 -0
- package/dist/panelDetailLayout.js.map +1 -0
- package/dist/panelDetailStyles.d.ts +2 -0
- package/dist/panelDetailStyles.d.ts.map +1 -0
- package/dist/panelDetailStyles.js +57 -0
- package/dist/panelDetailStyles.js.map +1 -0
- package/dist/panelDiagnosticsView.d.ts +10 -1
- package/dist/panelDiagnosticsView.d.ts.map +1 -1
- package/dist/panelDiagnosticsView.js +167 -58
- package/dist/panelDiagnosticsView.js.map +1 -1
- package/dist/panelDomHelpers.d.ts.map +1 -1
- package/dist/panelDomHelpers.js +6 -5
- package/dist/panelDomHelpers.js.map +1 -1
- package/dist/panelGraphLayout.d.ts +3 -2
- package/dist/panelGraphLayout.d.ts.map +1 -1
- package/dist/panelGraphLayout.js +20 -5
- package/dist/panelGraphLayout.js.map +1 -1
- package/dist/panelGraphRenderer.d.ts +10 -0
- package/dist/panelGraphRenderer.d.ts.map +1 -1
- package/dist/panelGraphRenderer.js.map +1 -1
- package/dist/panelGraphScene.d.ts +15 -26
- package/dist/panelGraphScene.d.ts.map +1 -1
- package/dist/panelGraphScene.js +191 -208
- package/dist/panelGraphScene.js.map +1 -1
- package/dist/panelGraphSearch.d.ts +16 -0
- package/dist/panelGraphSearch.d.ts.map +1 -0
- package/dist/panelGraphSearch.js +93 -0
- package/dist/panelGraphSearch.js.map +1 -0
- package/dist/panelGraphView.d.ts +82 -0
- package/dist/panelGraphView.d.ts.map +1 -1
- package/dist/panelGraphView.js +42 -9
- package/dist/panelGraphView.js.map +1 -1
- package/dist/panelGraphVisuals.d.ts +18 -6
- package/dist/panelGraphVisuals.d.ts.map +1 -1
- package/dist/panelGraphVisuals.js +156 -116
- package/dist/panelGraphVisuals.js.map +1 -1
- package/dist/panelInspectorView.d.ts +13 -0
- package/dist/panelInspectorView.d.ts.map +1 -1
- package/dist/panelInspectorView.js +326 -46
- package/dist/panelInspectorView.js.map +1 -1
- package/dist/panelListStyles.d.ts +3 -0
- package/dist/panelListStyles.d.ts.map +1 -0
- package/dist/panelListStyles.js +155 -0
- package/dist/panelListStyles.js.map +1 -0
- package/dist/panelMemoryStyles.d.ts +3 -0
- package/dist/panelMemoryStyles.d.ts.map +1 -0
- package/dist/panelMemoryStyles.js +42 -0
- package/dist/panelMemoryStyles.js.map +1 -0
- package/dist/panelMemoryView.d.ts +13 -1
- package/dist/panelMemoryView.d.ts.map +1 -1
- package/dist/panelMemoryView.js +161 -41
- package/dist/panelMemoryView.js.map +1 -1
- package/dist/panelPassesView.d.ts +15 -0
- package/dist/panelPassesView.d.ts.map +1 -1
- package/dist/panelPassesView.js +202 -72
- package/dist/panelPassesView.js.map +1 -1
- package/dist/panelRawView.d.ts +15 -0
- package/dist/panelRawView.d.ts.map +1 -0
- package/dist/panelRawView.js +105 -0
- package/dist/panelRawView.js.map +1 -0
- package/dist/panelResourcesView.d.ts +8 -0
- package/dist/panelResourcesView.d.ts.map +1 -1
- package/dist/panelResourcesView.js +62 -31
- package/dist/panelResourcesView.js.map +1 -1
- package/dist/panelSelection.d.ts +9 -1
- package/dist/panelSelection.d.ts.map +1 -1
- package/dist/panelSelection.js +36 -6
- package/dist/panelSelection.js.map +1 -1
- package/dist/panelTheme.d.ts +13 -0
- package/dist/panelTheme.d.ts.map +1 -0
- package/dist/panelTheme.js +104 -0
- package/dist/panelTheme.js.map +1 -0
- package/dist/panelTypes.d.ts +18 -4
- package/dist/panelTypes.d.ts.map +1 -1
- package/dist/panelTypes.js.map +1 -1
- package/dist/panelVisualTheme.d.ts +176 -71
- package/dist/panelVisualTheme.d.ts.map +1 -1
- package/dist/panelVisualTheme.js +34 -36
- package/dist/panelVisualTheme.js.map +1 -1
- package/dist/panelWorkbenchHelpers.d.ts +12 -1
- package/dist/panelWorkbenchHelpers.d.ts.map +1 -1
- package/dist/panelWorkbenchHelpers.js +63 -2
- package/dist/panelWorkbenchHelpers.js.map +1 -1
- package/dist/panelWorkbenchStyles.d.ts +2 -0
- package/dist/panelWorkbenchStyles.d.ts.map +1 -0
- package/dist/panelWorkbenchStyles.js +101 -0
- package/dist/panelWorkbenchStyles.js.map +1 -0
- package/dist/panelWorkbenchView.d.ts +16 -0
- package/dist/panelWorkbenchView.d.ts.map +1 -1
- package/dist/panelWorkbenchView.js +228 -50
- package/dist/panelWorkbenchView.js.map +1 -1
- package/dist/query.js.map +1 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +161 -205
- package/dist/styles.js.map +1 -1
- package/dist/theme.d.ts +22 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +10 -0
- package/dist/theme.js.map +1 -0
- package/dist/themeDefinitions.d.ts +251 -0
- package/dist/themeDefinitions.d.ts.map +1 -0
- package/dist/themeDefinitions.js +96 -0
- package/dist/themeDefinitions.js.map +1 -0
- package/dist/themePalette.d.ts +66 -0
- package/dist/themePalette.d.ts.map +1 -0
- package/dist/themePalette.js +37 -0
- package/dist/themePalette.js.map +1 -0
- package/dist/themes.css +165 -0
- package/package.json +44 -10
- package/src/FrameGraphInspector.ts +145 -68
- package/src/capture.ts +4 -0
- package/src/debugCaptureModel.ts +97 -21
- package/src/index.ts +6 -2
- package/src/panelAliasAnalysis.ts +24 -70
- package/src/panelCytoscapeGraphRenderer.ts +177 -40
- package/src/panelDetailLayout.ts +155 -0
- package/src/panelDetailStyles.ts +56 -0
- package/src/panelDiagnosticsView.ts +167 -86
- package/src/panelDomHelpers.ts +4 -5
- package/src/panelGraphLayout.ts +20 -5
- package/src/panelGraphRenderer.ts +7 -0
- package/src/panelGraphScene.ts +204 -292
- package/src/panelGraphSearch.ts +96 -0
- package/src/panelGraphView.ts +41 -9
- package/src/panelGraphVisuals.ts +152 -118
- package/src/panelInspectorView.ts +315 -48
- package/src/panelListStyles.ts +154 -0
- package/src/panelMemoryStyles.ts +41 -0
- package/src/panelMemoryView.ts +178 -53
- package/src/panelPassesView.ts +190 -137
- package/src/panelRawView.ts +99 -0
- package/src/panelResourcesView.ts +69 -56
- package/src/panelSelection.ts +39 -7
- package/src/panelTheme.ts +85 -0
- package/src/panelTypes.ts +16 -4
- package/src/panelVisualTheme.ts +38 -38
- package/src/panelWorkbenchHelpers.ts +62 -4
- package/src/panelWorkbenchStyles.ts +100 -0
- package/src/panelWorkbenchView.ts +201 -52
- package/src/query.ts +11 -11
- package/src/styles.ts +162 -205
- package/src/theme.ts +24 -0
- package/src/themeDefinitions.ts +103 -0
- package/src/themePalette.ts +44 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { InspectorThemeController, resolveGraphTheme } from "./panelTheme.js";
|
|
1
2
|
import { FrameGraphSnapshotValidationError, decodeFrameGraphSnapshot, parseFrameGraphSnapshot, stringifyFrameGraphSnapshot, } from '@zenfg/snapshot';
|
|
2
3
|
import { createDebugViewModel, } from "./debugCaptureModel.js";
|
|
3
4
|
import { createToolbarButton } from "./panelDomHelpers.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { selectionExists } from "./panelSelection.js";
|
|
5
|
+
import { destroyGraph, fitGraph, resolveGraphScene, renderGraphLegend, } from "./panelGraphView.js";
|
|
6
|
+
import { graphGroupElementId, selectionKey } from "./panelGraphScene.js";
|
|
7
|
+
import { resolveNodeSelection, selectionExists } from "./panelSelection.js";
|
|
8
8
|
import { ensureFrameGraphInspectorStyles } from "./styles.js";
|
|
9
9
|
import { sameSelection } from "./panelWorkbenchHelpers.js";
|
|
10
10
|
import { FrameGraphDebugWorkbench } from "./panelWorkbenchView.js";
|
|
@@ -30,12 +30,12 @@ const DEFAULT_BRANDING = 'ZenFG Inspector';
|
|
|
30
30
|
export class FrameGraphInspector {
|
|
31
31
|
/** Root element owned by this inspector instance. */
|
|
32
32
|
dom = document.createElement('section');
|
|
33
|
+
themeController = new InspectorThemeController(this.dom);
|
|
33
34
|
body = document.createElement('div');
|
|
34
35
|
content = document.createElement('div');
|
|
35
36
|
dropOverlay = document.createElement('div');
|
|
36
|
-
passesGraphModeButton;
|
|
37
|
-
resourcesGraphModeButton;
|
|
38
37
|
groupsButton;
|
|
38
|
+
declarationsButton;
|
|
39
39
|
collapseGroupsButton;
|
|
40
40
|
graphView;
|
|
41
41
|
workbench;
|
|
@@ -56,6 +56,7 @@ export class FrameGraphInspector {
|
|
|
56
56
|
copyFeedbackTimeout;
|
|
57
57
|
maxImportBytes;
|
|
58
58
|
dragDepth = 0;
|
|
59
|
+
revealRevision = 0;
|
|
59
60
|
handleDragEnter = (event) => {
|
|
60
61
|
if (!isFileDrag(event))
|
|
61
62
|
return;
|
|
@@ -119,9 +120,10 @@ export class FrameGraphInspector {
|
|
|
119
120
|
host: document.createElement('div'),
|
|
120
121
|
toolbar: document.createElement('div'),
|
|
121
122
|
legend: graphLegend,
|
|
123
|
+
refreshTheme: () => this.refreshTheme(),
|
|
122
124
|
layoutElementBudget: normalizeLimit(options.maxGraphElements, DEFAULT_MAX_GRAPH_ELEMENTS, 'maxGraphElements'),
|
|
123
|
-
graphMode: 'passes',
|
|
124
125
|
groupsEnabled: true,
|
|
126
|
+
showResourceDeclarations: true,
|
|
125
127
|
expandedGroupPaths: new Set(),
|
|
126
128
|
fitOnNextRender: true,
|
|
127
129
|
};
|
|
@@ -129,26 +131,20 @@ export class FrameGraphInspector {
|
|
|
129
131
|
this.graphView.toolbar.className = 'zenfg-inspector-graph-toolbar';
|
|
130
132
|
this.graphView.toolbar.setAttribute('role', 'toolbar');
|
|
131
133
|
this.graphView.toolbar.setAttribute('aria-label', 'Frame graph view controls');
|
|
132
|
-
this.
|
|
133
|
-
this.resourcesGraphModeButton = createToolbarButton('Resource access', 'Show resource access graph', () => this.setGraphMode('resources'));
|
|
134
|
+
this.declarationsButton = createToolbarButton('Declarations', 'Show resource declaration nodes', () => this.toggleDeclarations());
|
|
134
135
|
this.groupsButton = createToolbarButton('Groups', 'Toggle diagnostic group projection', () => this.toggleGroups());
|
|
135
136
|
this.collapseGroupsButton = createToolbarButton('Collapse All', 'Collapse every diagnostic group', () => this.collapseAllGroups());
|
|
136
|
-
this.passesGraphModeButton.classList.add('zenfg-inspector-mode-button');
|
|
137
|
-
this.resourcesGraphModeButton.classList.add('zenfg-inspector-mode-button');
|
|
138
|
-
const modeControls = document.createElement('div');
|
|
139
|
-
modeControls.className = 'zenfg-inspector-graph-mode-controls';
|
|
140
|
-
modeControls.setAttribute('role', 'group');
|
|
141
|
-
modeControls.setAttribute('aria-label', 'Graph mode');
|
|
142
|
-
modeControls.append(this.passesGraphModeButton, this.resourcesGraphModeButton);
|
|
143
137
|
const actionControls = document.createElement('div');
|
|
144
138
|
actionControls.className = 'zenfg-inspector-graph-action-controls';
|
|
145
|
-
actionControls.append(this.groupsButton, this.collapseGroupsButton,
|
|
146
|
-
this.graphView.toolbar.append(
|
|
139
|
+
actionControls.append(this.declarationsButton, this.groupsButton, this.collapseGroupsButton, createToolbarButton('Fit', 'Fit graph to view', () => fitGraph(this.graphView)));
|
|
140
|
+
this.graphView.toolbar.append(actionControls);
|
|
147
141
|
const callbacks = {
|
|
148
142
|
onSelect: (selection) => this.handleSelect(selection),
|
|
149
143
|
onHover: (selection) => this.handleHover(selection),
|
|
150
144
|
onGroupToggle: (pathKey) => this.toggleGroup(pathKey),
|
|
151
145
|
isGroupExpanded: (pathKey) => this.graphView.expandedGroupPaths.has(pathKey),
|
|
146
|
+
onReveal: (selection, tab) => this.handleReveal(selection, tab),
|
|
147
|
+
onNavigate: (tab, filter) => this.workbench.navigate(tab, filter),
|
|
152
148
|
};
|
|
153
149
|
this.workbench = new FrameGraphDebugWorkbench(this.graphView, callbacks, {
|
|
154
150
|
onCapture: () => { void this.captureSnapshot(); },
|
|
@@ -168,22 +164,55 @@ export class FrameGraphInspector {
|
|
|
168
164
|
this.dom.addEventListener('dragend', this.handleDragEnd);
|
|
169
165
|
this.dom.addEventListener('drop', this.handleDrop);
|
|
170
166
|
this.updateCaptureActions();
|
|
171
|
-
this.
|
|
167
|
+
this.updateGraphControls();
|
|
172
168
|
this.showEmptyState();
|
|
173
|
-
|
|
169
|
+
if (options.theme)
|
|
170
|
+
this.setTheme(options.theme);
|
|
171
|
+
queueMicrotask(() => { if (!this.destroyed) {
|
|
172
|
+
this.refreshTheme();
|
|
173
|
+
this.maybeAutoCapture();
|
|
174
|
+
} });
|
|
175
|
+
}
|
|
176
|
+
/** Replace API-applied variables on this instance, then synchronize graph styles.
|
|
177
|
+
* Pass null to restore host CSS and defaults. Does not change capture or interaction state.
|
|
178
|
+
*/
|
|
179
|
+
setTheme(theme) {
|
|
180
|
+
if (this.destroyed)
|
|
181
|
+
return;
|
|
182
|
+
this.themeController.apply(theme);
|
|
183
|
+
this.refreshTheme();
|
|
184
|
+
}
|
|
185
|
+
/** Re-read final CSS values after external CSS changes and refresh graph and legend.
|
|
186
|
+
* Does not write theme variables, recapture, fit, or rebuild the component.
|
|
187
|
+
*/
|
|
188
|
+
refreshTheme() {
|
|
189
|
+
if (this.destroyed)
|
|
190
|
+
return;
|
|
191
|
+
const theme = resolveGraphTheme(this.dom);
|
|
192
|
+
this.graphView.theme = theme;
|
|
193
|
+
this.graphView.renderer?.setTheme?.(theme);
|
|
194
|
+
if (this.viewModel)
|
|
195
|
+
renderGraphLegend(this.graphView.legend, this.viewModel, theme, this.graphView.showResourceDeclarations);
|
|
174
196
|
}
|
|
175
197
|
/**
|
|
176
198
|
* Replaces or removes the live-capture provider.
|
|
177
199
|
*
|
|
178
200
|
* @remarks Installing a provider may immediately begin an asynchronous
|
|
179
|
-
* capture when no snapshot is displayed.
|
|
201
|
+
* capture when no snapshot is displayed. Replacing or removing a provider
|
|
202
|
+
* invalidates its pending capture results without cancelling the provider
|
|
203
|
+
* promise. An already displayed snapshot and any pending import are preserved.
|
|
180
204
|
*/
|
|
181
205
|
setCaptureSnapshotProvider(provider) {
|
|
182
|
-
|
|
206
|
+
if (this.destroyed || this.captureSnapshotCallback === provider)
|
|
207
|
+
return;
|
|
208
|
+
if (this.capturing) {
|
|
209
|
+
this.operationRevision += 1;
|
|
210
|
+
this.capturing = false;
|
|
211
|
+
}
|
|
183
212
|
this.captureSnapshotCallback = provider;
|
|
184
|
-
if (
|
|
213
|
+
if (!this.viewModel)
|
|
185
214
|
this.initialAutoCaptureAttempted = false;
|
|
186
|
-
if (!provider && !this.viewModel)
|
|
215
|
+
if (!provider && !this.viewModel && !this.importing)
|
|
187
216
|
this.showEmptyState();
|
|
188
217
|
this.updateCaptureActions();
|
|
189
218
|
this.maybeAutoCapture();
|
|
@@ -211,7 +240,8 @@ export class FrameGraphInspector {
|
|
|
211
240
|
this.workbench.showEmptyState('capturing', 'Capturing the next rendered frame…');
|
|
212
241
|
this.updateCaptureActions();
|
|
213
242
|
try {
|
|
214
|
-
const
|
|
243
|
+
const request = { timing: 'both' };
|
|
244
|
+
const snapshot = await this.captureSnapshotCallback(request);
|
|
215
245
|
if (this.destroyed || revision !== this.operationRevision)
|
|
216
246
|
return;
|
|
217
247
|
if (!snapshot) {
|
|
@@ -238,9 +268,9 @@ export class FrameGraphInspector {
|
|
|
238
268
|
}
|
|
239
269
|
}
|
|
240
270
|
/**
|
|
241
|
-
* Validates and synchronously displays a programmatic Snapshot 1.
|
|
271
|
+
* Validates and synchronously displays a programmatic Snapshot 1.2 value.
|
|
242
272
|
*
|
|
243
|
-
* @throws {@link FrameGraphSnapshotValidationError} if `snapshot` is invalid.
|
|
273
|
+
* @throws {@link @zenfg/snapshot!index.FrameGraphSnapshotValidationError | FrameGraphSnapshotValidationError} if `snapshot` is invalid.
|
|
244
274
|
*/
|
|
245
275
|
setSnapshot(snapshot) {
|
|
246
276
|
if (this.destroyed)
|
|
@@ -292,10 +322,17 @@ export class FrameGraphInspector {
|
|
|
292
322
|
});
|
|
293
323
|
const sourceFormat = decoded.snapshot.capture.migration?.sourceFormat;
|
|
294
324
|
if (sourceFormat) {
|
|
295
|
-
|
|
325
|
+
// The current import format can differ from retained historical provenance.
|
|
326
|
+
const sourceLabel = {
|
|
327
|
+
'legacy-v0': 'Legacy V0',
|
|
328
|
+
'legacy-candidate-v1': 'Legacy Candidate V1',
|
|
329
|
+
'snapshot-v1.1': 'Snapshot 1.1',
|
|
330
|
+
}[decoded.migrated && decoded.source !== 'v1' ? decoded.source : sourceFormat];
|
|
331
|
+
const version = decoded.snapshot.version;
|
|
332
|
+
const targetLabel = `Snapshot ${version.major}.${version.minor}`;
|
|
296
333
|
this.statusMessage = decoded.migrated
|
|
297
|
-
? `Imported ${sourceLabel} and migrated it to ZenFG
|
|
298
|
-
: `Imported
|
|
334
|
+
? `Imported ${sourceLabel} and migrated it to ZenFG ${targetLabel}.`
|
|
335
|
+
: `Imported ${targetLabel} with ${sourceLabel} migration provenance.`;
|
|
299
336
|
this.statusTone = 'neutral';
|
|
300
337
|
}
|
|
301
338
|
}
|
|
@@ -375,18 +412,20 @@ export class FrameGraphInspector {
|
|
|
375
412
|
this.protocolSnapshot = snapshot;
|
|
376
413
|
this.viewModel = viewModel;
|
|
377
414
|
this.graphView.fitOnNextRender = true;
|
|
415
|
+
this.graphView.captureRevision = (this.graphView.captureRevision ?? 0) + 1;
|
|
416
|
+
this.graphView.revealOnNextRender = undefined;
|
|
417
|
+
this.graphView.renderer?.cancelReveal?.();
|
|
378
418
|
this.hovered = undefined;
|
|
379
419
|
this.initialAutoCaptureAttempted = true;
|
|
380
420
|
this.statusMessage = undefined;
|
|
381
421
|
this.statusTone = 'neutral';
|
|
382
|
-
if (
|
|
383
|
-
this.selected = viewModel.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
422
|
+
if (this.selected?.kind === 'node' || this.selected?.kind === 'culled')
|
|
423
|
+
this.selected = resolveNodeSelection(viewModel, this.selected.id);
|
|
424
|
+
else if (this.selected && !selectionExists(viewModel, this.selected))
|
|
425
|
+
this.selected = undefined;
|
|
387
426
|
this.workbench.setSnapshot(viewModel, this.selected);
|
|
388
427
|
this.updateCaptureActions();
|
|
389
|
-
this.
|
|
428
|
+
this.updateGraphControls();
|
|
390
429
|
}
|
|
391
430
|
/**
|
|
392
431
|
* Idempotently cancels pending UI results, releases graph resources, and
|
|
@@ -405,7 +444,9 @@ export class FrameGraphInspector {
|
|
|
405
444
|
this.dom.removeEventListener('dragleave', this.handleDragLeave);
|
|
406
445
|
this.dom.removeEventListener('dragend', this.handleDragEnd);
|
|
407
446
|
this.dom.removeEventListener('drop', this.handleDrop);
|
|
447
|
+
this.themeController.destroy();
|
|
408
448
|
destroyGraph(this.graphView);
|
|
449
|
+
this.workbench.destroy();
|
|
409
450
|
this.dom.remove();
|
|
410
451
|
}
|
|
411
452
|
updateCaptureActions() {
|
|
@@ -432,59 +473,109 @@ export class FrameGraphInspector {
|
|
|
432
473
|
void this.captureSnapshot();
|
|
433
474
|
}
|
|
434
475
|
handleSelect(selection) {
|
|
476
|
+
if (!this.viewModel || !selectionExists(this.viewModel, selection))
|
|
477
|
+
return;
|
|
435
478
|
this.selected = selection;
|
|
436
479
|
this.workbench.setSelection(selection);
|
|
437
480
|
}
|
|
481
|
+
handleReveal(selection, tab) {
|
|
482
|
+
const snapshot = this.viewModel;
|
|
483
|
+
if (!snapshot || !selectionExists(snapshot, selection))
|
|
484
|
+
return;
|
|
485
|
+
if (tab === 'graph') {
|
|
486
|
+
const expanded = new Set(this.graphView.expandedGroupPaths);
|
|
487
|
+
const groupsEnabled = this.graphView.groupsEnabled;
|
|
488
|
+
const showResourceDeclarations = this.graphView.showResourceDeclarations;
|
|
489
|
+
if (selection.kind === 'resource')
|
|
490
|
+
this.graphView.showResourceDeclarations = true;
|
|
491
|
+
if (selection.kind === 'group')
|
|
492
|
+
this.graphView.groupsEnabled = true;
|
|
493
|
+
let groupId;
|
|
494
|
+
if (selection.kind === 'node')
|
|
495
|
+
groupId = snapshot.nodeById.get(selection.id)?.debugGroupId;
|
|
496
|
+
else if (selection.kind === 'resource')
|
|
497
|
+
groupId = snapshot.resourceById.get(selection.id)?.debugGroupId;
|
|
498
|
+
else if (selection.kind === 'group')
|
|
499
|
+
groupId = snapshot.groupByPathKey.get(selection.pathKey)?.parentId;
|
|
500
|
+
if (this.graphView.groupsEnabled && groupId) {
|
|
501
|
+
for (const id of snapshot.groupById.get(groupId)?.ancestorIds ?? []) {
|
|
502
|
+
const group = snapshot.groupById.get(id);
|
|
503
|
+
if (group)
|
|
504
|
+
this.graphView.expandedGroupPaths.add(group.pathKey);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const scene = resolveGraphScene(this.graphView, snapshot);
|
|
508
|
+
const availableIds = new Set([...scene.nodes, ...scene.edges].map((entry) => entry.id));
|
|
509
|
+
if (!(scene.interaction.primaryElementIdsBySelection.get(selectionKey(selection))?.some((id) => availableIds.has(id)))) {
|
|
510
|
+
this.graphView.groupsEnabled = groupsEnabled;
|
|
511
|
+
this.graphView.showResourceDeclarations = showResourceDeclarations;
|
|
512
|
+
this.graphView.expandedGroupPaths.clear();
|
|
513
|
+
for (const path of expanded)
|
|
514
|
+
this.graphView.expandedGroupPaths.add(path);
|
|
515
|
+
this.workbench.showNavigationIssue(selection.kind === 'culled' ? 'Culled passes are not part of Frame Flow.' : 'This object has no representation in Frame Flow.', selection);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
this.graphView.revealOnNextRender = { selection, revision: ++this.revealRevision };
|
|
519
|
+
this.updateGraphControls();
|
|
520
|
+
}
|
|
521
|
+
this.handleSelect(selection);
|
|
522
|
+
this.workbench.reveal(selection, tab);
|
|
523
|
+
}
|
|
438
524
|
handleHover(selection) {
|
|
439
525
|
if (!this.viewModel || sameSelection(this.hovered, selection))
|
|
440
526
|
return;
|
|
441
527
|
this.hovered = selection;
|
|
442
528
|
this.workbench.setHovered(selection);
|
|
443
529
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
this.
|
|
448
|
-
this.graphView.fitOnNextRender = true;
|
|
449
|
-
this.updateGraphModeButtonState();
|
|
450
|
-
this.workbench.refreshGraphStructure();
|
|
451
|
-
}
|
|
452
|
-
updateGraphModeButtonState() {
|
|
453
|
-
const passesActive = this.graphView.graphMode === 'passes';
|
|
530
|
+
updateGraphControls() {
|
|
531
|
+
const showDeclarations = this.graphView.showResourceDeclarations ?? true;
|
|
532
|
+
this.declarationsButton.classList.toggle('active', showDeclarations);
|
|
533
|
+
this.declarationsButton.setAttribute('aria-pressed', String(showDeclarations));
|
|
454
534
|
const hasGroups = (this.viewModel?.debugGroups.length ?? 0) > 0;
|
|
455
|
-
this.
|
|
456
|
-
this.
|
|
457
|
-
this.
|
|
458
|
-
this.
|
|
459
|
-
this.groupsButton.
|
|
460
|
-
this.groupsButton.classList.toggle('active', passesActive && hasGroups && this.graphView.groupsEnabled);
|
|
461
|
-
this.groupsButton.setAttribute('aria-pressed', passesActive && hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');
|
|
535
|
+
this.groupsButton.disabled = !hasGroups;
|
|
536
|
+
this.groupsButton.hidden = !hasGroups;
|
|
537
|
+
this.collapseGroupsButton.hidden = !hasGroups;
|
|
538
|
+
this.groupsButton.classList.toggle('active', hasGroups && this.graphView.groupsEnabled);
|
|
539
|
+
this.groupsButton.setAttribute('aria-pressed', hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');
|
|
462
540
|
const hasExpanded = this.viewModel?.debugGroups.some((group) => this.graphView.expandedGroupPaths.has(group.pathKey)) ?? false;
|
|
463
|
-
this.collapseGroupsButton.disabled = !
|
|
541
|
+
this.collapseGroupsButton.disabled = !hasGroups || !this.graphView.groupsEnabled || !hasExpanded;
|
|
542
|
+
}
|
|
543
|
+
toggleDeclarations() {
|
|
544
|
+
this.handleHover(undefined);
|
|
545
|
+
this.graphView.showResourceDeclarations = !(this.graphView.showResourceDeclarations ?? true);
|
|
546
|
+
this.graphView.renderer?.cancelReveal?.();
|
|
547
|
+
this.graphView.revealOnNextRender = undefined;
|
|
548
|
+
this.graphView.anchorElementIdOnNextRender = undefined;
|
|
549
|
+
this.graphView.fitOnNextRender = true;
|
|
550
|
+
this.updateGraphControls();
|
|
551
|
+
this.workbench.refreshGraphStructure();
|
|
464
552
|
}
|
|
465
553
|
toggleGroups() {
|
|
466
|
-
if (
|
|
554
|
+
if (!this.viewModel?.debugGroups.length)
|
|
467
555
|
return;
|
|
556
|
+
this.handleHover(undefined);
|
|
468
557
|
this.graphView.groupsEnabled = !this.graphView.groupsEnabled;
|
|
469
558
|
this.graphView.fitOnNextRender = true;
|
|
470
|
-
this.
|
|
559
|
+
this.updateGraphControls();
|
|
471
560
|
this.workbench.refreshGraphStructure();
|
|
472
561
|
}
|
|
473
562
|
toggleGroup(pathKey) {
|
|
563
|
+
this.handleHover(undefined);
|
|
474
564
|
if (this.graphView.expandedGroupPaths.has(pathKey))
|
|
475
565
|
this.graphView.expandedGroupPaths.delete(pathKey);
|
|
476
566
|
else
|
|
477
567
|
this.graphView.expandedGroupPaths.add(pathKey);
|
|
478
568
|
this.graphView.anchorElementIdOnNextRender = graphGroupElementId(pathKey);
|
|
479
|
-
this.
|
|
569
|
+
this.updateGraphControls();
|
|
480
570
|
this.workbench.refreshGraphStructure();
|
|
481
571
|
}
|
|
482
572
|
collapseAllGroups() {
|
|
483
573
|
if (this.graphView.expandedGroupPaths.size === 0)
|
|
484
574
|
return;
|
|
575
|
+
this.handleHover(undefined);
|
|
485
576
|
this.graphView.expandedGroupPaths.clear();
|
|
486
577
|
this.graphView.fitOnNextRender = true;
|
|
487
|
-
this.
|
|
578
|
+
this.updateGraphControls();
|
|
488
579
|
this.workbench.refreshGraphStructure();
|
|
489
580
|
}
|
|
490
581
|
showEmptyState() {
|
|
@@ -521,14 +612,9 @@ export class FrameGraphInspector {
|
|
|
521
612
|
export function mountFrameGraphInspector(host, options) {
|
|
522
613
|
const inspector = new FrameGraphInspector(options);
|
|
523
614
|
host.appendChild(inspector.dom);
|
|
615
|
+
inspector.refreshTheme();
|
|
524
616
|
return inspector;
|
|
525
617
|
}
|
|
526
|
-
function createGraphIconButton(icon, title, onClick) {
|
|
527
|
-
const button = createToolbarButton('', title, onClick);
|
|
528
|
-
button.classList.add('zenfg-inspector-icon-button');
|
|
529
|
-
button.appendChild(createPanelIcon(icon));
|
|
530
|
-
return button;
|
|
531
|
-
}
|
|
532
618
|
async function writeTextToClipboard(text) {
|
|
533
619
|
if (navigator.clipboard?.writeText) {
|
|
534
620
|
await navigator.clipboard.writeText(text);
|
|
@@ -567,7 +653,7 @@ function formatImportLimit(bytes) {
|
|
|
567
653
|
: `${bytes} bytes`;
|
|
568
654
|
}
|
|
569
655
|
function formatIssues(issues) {
|
|
570
|
-
return issues.
|
|
656
|
+
return issues.map((issue) => `${issue.path || '/'}: ${issue.message}`).join('\n');
|
|
571
657
|
}
|
|
572
658
|
function isFileDrag(event) {
|
|
573
659
|
return Array.from(event.dataTransfer?.types ?? []).includes('Files');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FrameGraphInspector.js","sourceRoot":"","sources":["../src/FrameGraphInspector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tFrameGraphSnapshotValidationError,\n\tdecodeFrameGraphSnapshot,\n\tparseFrameGraphSnapshot,\n\tstringifyFrameGraphSnapshot,\n\ttype FrameGraphSnapshot,\n} from '@zenfg/snapshot';\nimport {\n\tcreateDebugViewModel,\n\ttype FrameGraphDebugSnapshotSource,\n\ttype FrameGraphDebugViewModel,\n} from './debugCaptureModel.ts';\nimport { createToolbarButton } from './panelDomHelpers.ts';\nimport { createPanelIcon } from './panelIcons.ts';\nimport {\n\tdestroyGraph,\n\tfitGraph,\n} from './panelGraphView.ts';\nimport { graphGroupElementId } from './panelGraphScene.ts';\nimport { selectionExists } from './panelSelection.ts';\nimport type { GraphViewState, Selection } from './panelTypes.ts';\nimport { ensureFrameGraphInspectorStyles } from './styles.ts';\nimport { sameSelection, type WorkbenchCallbacks } from './panelWorkbenchHelpers.ts';\nimport { FrameGraphDebugWorkbench } from './panelWorkbenchView.ts';\n\n/** Construction and safety limits for an embedded {@link FrameGraphInspector}. */\nexport type FrameGraphInspectorOptions = {\n\t/**\n\t * Product label shown in the workbench command bar. Pass `false` to hide\n\t * visible branding while retaining the inspector's accessible name.\n\t *\n\t * @defaultValue `\"ZenFG Inspector\"`\n\t */\n\tbranding?: string | false;\n\t/**\n\t * Produces a live snapshot when capture is requested. The inspector awaits\n\t * promises and displays thrown or rejected errors in its status area.\n\t */\n\tcaptureSnapshot?: () => FrameGraphSnapshot | undefined | Promise<FrameGraphSnapshot | undefined>;\n\t/**\n\t * Maximum accepted import size in bytes.\n\t *\n\t * @defaultValue `67108864` (64 MiB)\n\t */\n\tmaxImportBytes?: number;\n\t/**\n\t * Maximum graph nodes plus edges accepted by automatic layout.\n\t *\n\t * @defaultValue `5000`\n\t */\n\tmaxGraphElements?: number;\n};\n\nconst DEFAULT_MAX_IMPORT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_MAX_GRAPH_ELEMENTS = 5_000;\nconst DEFAULT_BRANDING = 'ZenFG Inspector';\n\n/**\n * Browser lifecycle controller for one embeddable FrameGraph inspector.\n *\n * @remarks The constructor creates, but does not append, {@link dom}. Use\n * {@link mountFrameGraphInspector} for the common append-and-return workflow.\n * Async capture, import, and clipboard failures are reported in the UI. Call\n * {@link destroy} when the controller is no longer needed.\n *\n * @example\n * ```ts\n * const inspector = new FrameGraphInspector({ captureSnapshot: capture });\n * document.body.append(inspector.dom);\n * // Later:\n * inspector.destroy();\n * ```\n */\nexport class FrameGraphInspector {\n\t/** Root element owned by this inspector instance. */\n\treadonly dom = document.createElement('section');\n\n\tprivate readonly body = document.createElement('div');\n\tprivate readonly content = document.createElement('div');\n\tprivate readonly dropOverlay = document.createElement('div');\n\tprivate readonly passesGraphModeButton: HTMLButtonElement;\n\tprivate readonly resourcesGraphModeButton: HTMLButtonElement;\n\tprivate readonly groupsButton: HTMLButtonElement;\n\tprivate readonly collapseGroupsButton: HTMLButtonElement;\n\tprivate readonly graphView: GraphViewState;\n\tprivate readonly workbench: FrameGraphDebugWorkbench;\n\tprivate captureSnapshotCallback: FrameGraphInspectorOptions['captureSnapshot'];\n\tprivate protocolSnapshot: FrameGraphSnapshot | undefined;\n\tprivate operationRevision = 0;\n\tprivate viewModel: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate hovered: Selection | undefined;\n\tprivate capturing = false;\n\tprivate importing = false;\n\tprivate copying = false;\n\tprivate copied = false;\n\tprivate initialAutoCaptureAttempted = false;\n\tprivate statusMessage: string | undefined;\n\tprivate statusTone: 'neutral' | 'error' = 'neutral';\n\tprivate destroyed = false;\n\tprivate copyFeedbackTimeout: number | undefined;\n\tprivate readonly maxImportBytes: number;\n\tprivate dragDepth = 0;\n\tprivate readonly handleDragEnter = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tthis.dragDepth += 1;\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragOver = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tif (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragLeave = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event) && this.dragDepth === 0) return;\n\t\tthis.dragDepth = Math.max(0, this.dragDepth - 1);\n\t\tif (this.dragDepth === 0) this.setDropActive(false);\n\t};\n\tprivate readonly handleDragEnd = (): void => this.clearDropState();\n\tprivate readonly handleDrop = (event: DragEvent): void => {\n\t\tconst file = event.dataTransfer?.files?.[0];\n\t\tif (!file) return;\n\t\tevent.preventDefault();\n\t\tthis.clearDropState();\n\t\tvoid this.importSnapshot(file);\n\t};\n\n\t/**\n\t * Creates a detached inspector UI.\n\t *\n\t * @throws If a configured numeric limit is not a non-negative safe integer,\n\t * or if browser DOM globals are unavailable.\n\t */\n\tconstructor(options: FrameGraphInspectorOptions = {}) {\n\t\tensureFrameGraphInspectorStyles();\n\t\tthis.captureSnapshotCallback = options.captureSnapshot;\n\t\tthis.maxImportBytes = normalizeMaxImportBytes(options.maxImportBytes);\n\t\tconst branding = options.branding ?? DEFAULT_BRANDING;\n\t\tthis.dom.className = 'zenfg-inspector';\n\t\tthis.dom.id = createInspectorId();\n\t\tthis.dom.setAttribute('role', 'region');\n\t\tthis.dom.setAttribute('aria-label', branding === false ? DEFAULT_BRANDING : branding);\n\t\tthis.body.className = 'zenfg-inspector-body';\n\t\tthis.content.className = 'zenfg-inspector-content';\n\t\tthis.dropOverlay.className = 'zenfg-inspector-drop-overlay';\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dropOverlay.setAttribute('aria-hidden', 'true');\n\t\tconst dropTitle = document.createElement('strong');\n\t\tdropTitle.textContent = 'Drop snapshot to open';\n\t\tconst dropDetail = document.createElement('span');\n\t\tdropDetail.textContent = 'The first file will be imported locally.';\n\t\tthis.dropOverlay.append(dropTitle, dropDetail);\n\n\t\tconst graphLegend = document.createElement('div');\n\t\tgraphLegend.className = 'zenfg-inspector-graph-legend';\n\t\tgraphLegend.setAttribute('aria-label', 'Graph legend');\n\t\tthis.graphView = {\n\t\t\thost: document.createElement('div'),\n\t\t\ttoolbar: document.createElement('div'),\n\t\t\tlegend: graphLegend,\n\t\t\tlayoutElementBudget: normalizeLimit(options.maxGraphElements, DEFAULT_MAX_GRAPH_ELEMENTS, 'maxGraphElements'),\n\t\t\tgraphMode: 'passes',\n\t\t\tgroupsEnabled: true,\n\t\t\texpandedGroupPaths: new Set(),\n\t\t\tfitOnNextRender: true,\n\t\t};\n\t\tthis.graphView.host.className = 'zenfg-inspector-graph';\n\t\tthis.graphView.toolbar.className = 'zenfg-inspector-graph-toolbar';\n\t\tthis.graphView.toolbar.setAttribute('role', 'toolbar');\n\t\tthis.graphView.toolbar.setAttribute('aria-label', 'Frame graph view controls');\n\n\t\tthis.passesGraphModeButton = createToolbarButton('Pass dependency', 'Show pass dependency graph', () => this.setGraphMode('passes'));\n\t\tthis.resourcesGraphModeButton = createToolbarButton('Resource access', 'Show resource access graph', () => this.setGraphMode('resources'));\n\t\tthis.groupsButton = createToolbarButton('Groups', 'Toggle diagnostic group projection', () => this.toggleGroups());\n\t\tthis.collapseGroupsButton = createToolbarButton('Collapse All', 'Collapse every diagnostic group', () => this.collapseAllGroups());\n\t\tthis.passesGraphModeButton.classList.add('zenfg-inspector-mode-button');\n\t\tthis.resourcesGraphModeButton.classList.add('zenfg-inspector-mode-button');\n\n\t\tconst modeControls = document.createElement('div');\n\t\tmodeControls.className = 'zenfg-inspector-graph-mode-controls';\n\t\tmodeControls.setAttribute('role', 'group');\n\t\tmodeControls.setAttribute('aria-label', 'Graph mode');\n\t\tmodeControls.append(this.passesGraphModeButton, this.resourcesGraphModeButton);\n\t\tconst actionControls = document.createElement('div');\n\t\tactionControls.className = 'zenfg-inspector-graph-action-controls';\n\t\tactionControls.append(\n\t\t\tthis.groupsButton,\n\t\t\tthis.collapseGroupsButton,\n\t\t\tcreateGraphIconButton('fit', 'Fit graph to view', () => fitGraph(this.graphView)),\n\t\t);\n\t\tthis.graphView.toolbar.append(modeControls, graphLegend, actionControls);\n\n\t\tconst callbacks: WorkbenchCallbacks = {\n\t\t\tonSelect: (selection) => this.handleSelect(selection),\n\t\t\tonHover: (selection) => this.handleHover(selection),\n\t\t\tonGroupToggle: (pathKey) => this.toggleGroup(pathKey),\n\t\t\tisGroupExpanded: (pathKey) => this.graphView.expandedGroupPaths.has(pathKey),\n\t\t};\n\t\tthis.workbench = new FrameGraphDebugWorkbench(this.graphView, callbacks, {\n\t\t\tonCapture: () => { void this.captureSnapshot(); },\n\t\t\tonImport: (file) => { void this.importSnapshot(file); },\n\t\t\tonDownload: () => this.downloadSnapshot(),\n\t\t\tonCopyJson: () => { void this.copySnapshotJson(); },\n\t\t}, {\n\t\t\tbranding,\n\t\t\tidPrefix: this.dom.id,\n\t\t});\n\t\tthis.content.append(this.workbench.root);\n\t\tthis.body.appendChild(this.content);\n\t\tthis.dom.append(this.body, this.dropOverlay);\n\t\tthis.dom.addEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.addEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.addEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.addEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.addEventListener('drop', this.handleDrop);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphModeButtonState();\n\t\tthis.showEmptyState();\n\t\tqueueMicrotask(() => this.maybeAutoCapture());\n\t}\n\n\t/**\n\t * Replaces or removes the live-capture provider.\n\t *\n\t * @remarks Installing a provider may immediately begin an asynchronous\n\t * capture when no snapshot is displayed.\n\t */\n\tsetCaptureSnapshotProvider(provider: FrameGraphInspectorOptions['captureSnapshot']): void {\n\t\tconst changed = this.captureSnapshotCallback !== provider;\n\t\tthis.captureSnapshotCallback = provider;\n\t\tif (changed && !this.viewModel) this.initialAutoCaptureAttempted = false;\n\t\tif (!provider && !this.viewModel) this.showEmptyState();\n\t\tthis.updateCaptureActions();\n\t\tthis.maybeAutoCapture();\n\t}\n\n\t/**\n\t * Requests and displays a live snapshot from the configured provider.\n\t *\n\t * @remarks Concurrent requests are coalesced. Provider errors, invalid\n\t * snapshots, and an unavailable provider are displayed in the inspector and\n\t * do not reject the returned promise.\n\t */\n\tasync captureSnapshot(): Promise<void> {\n\t\tif (this.destroyed || this.capturing) return;\n\t\tif (!this.captureSnapshotCallback) {\n\t\t\tthis.reportCaptureIssue('Waiting for a FrameGraph capture source.');\n\t\t\treturn;\n\t\t}\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.importing = false;\n\t\tthis.capturing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('capturing', 'Capturing the next rendered frame…');\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst snapshot = await this.captureSnapshotCallback();\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tif (!snapshot) {\n\t\t\t\tthis.reportCaptureIssue('No snapshot was produced. Capture again when rendering is active.');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, { kind: 'live', label: 'Live Capture' });\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.capturing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/**\n\t * Validates and synchronously displays a programmatic Snapshot 1.0 value.\n\t *\n\t * @throws {@link FrameGraphSnapshotValidationError} if `snapshot` is invalid.\n\t */\n\tsetSnapshot(snapshot: FrameGraphSnapshot): void {\n\t\tif (this.destroyed) return;\n\t\tthis.operationRevision += 1;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\tif (!decoded.ok) throw new FrameGraphSnapshotValidationError(decoded.issues);\n\t\tthis.applySnapshot(decoded.snapshot, { kind: 'programmatic', label: 'Programmatic' });\n\t}\n\n\t/** Returns the currently displayed canonical snapshot, if any. */\n\tgetSnapshot(): FrameGraphSnapshot | undefined {\n\t\treturn this.protocolSnapshot;\n\t}\n\n\t/**\n\t * Reads, migrates, validates, and displays a snapshot JSON file.\n\t *\n\t * @remarks Files above `maxImportBytes`, read failures, invalid JSON, and\n\t * validation failures are displayed in the UI and do not reject the promise.\n\t */\n\tasync importSnapshot(file: File): Promise<void> {\n\t\tif (this.destroyed) return;\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tif (file.size > this.maxImportBytes) {\n\t\t\tthis.reportCaptureIssue(`Import exceeds the ${formatImportLimit(this.maxImportBytes)} limit.`);\n\t\t\treturn;\n\t\t}\n\t\tthis.importing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst text = await file.text();\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tconst decoded = parseFrameGraphSnapshot(text);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, {\n\t\t\t\tkind: 'file',\n\t\t\t\tlabel: file.name || 'Imported JSON',\n\t\t\t});\n\t\t\tconst sourceFormat = decoded.snapshot.capture.migration?.sourceFormat;\n\t\t\tif (sourceFormat) {\n\t\t\t\tconst sourceLabel = sourceFormat === 'legacy-v0' ? 'Legacy V0' : 'Legacy Candidate V1';\n\t\t\t\tthis.statusMessage = decoded.migrated\n\t\t\t\t\t? `Imported ${sourceLabel} and migrated it to ZenFG Snapshot V1.`\n\t\t\t\t\t: `Imported Snapshot V1 with ${sourceLabel} migration provenance.`;\n\t\t\t\tthis.statusTone = 'neutral';\n\t\t\t}\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.importing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/** Downloads the displayed snapshot as pretty-printed canonical JSON. */\n\tdownloadSnapshot(): void {\n\t\tif (this.destroyed || !this.protocolSnapshot) return;\n\t\tconst json = stringifyFrameGraphSnapshot(this.protocolSnapshot, { pretty: true });\n\t\tconst url = URL.createObjectURL(new Blob([json], { type: 'application/json;charset=utf-8' }));\n\t\tconst anchor = document.createElement('a');\n\t\tanchor.href = url;\n\t\tanchor.download = `frame-graph-${this.protocolSnapshot.capture.frameIndex}.fgsnapshot.json`;\n\t\tanchor.click();\n\t\tURL.revokeObjectURL(url);\n\t}\n\n\t/**\n\t * Copies the displayed snapshot as pretty-printed canonical JSON.\n\t *\n\t * @remarks Clipboard failures are shown in the UI and do not reject the\n\t * returned promise. A legacy `document.execCommand` fallback is used when the\n\t * async Clipboard API is unavailable.\n\t */\n\tasync copySnapshotJson(): Promise<void> {\n\t\tif (this.destroyed || this.copying || !this.protocolSnapshot) return;\n\t\tconst snapshot = this.protocolSnapshot;\n\t\tconst revision = this.operationRevision;\n\t\tthis.copying = true;\n\t\tthis.copied = false;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tawait writeTextToClipboard(stringifyFrameGraphSnapshot(snapshot, { pretty: true }));\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tthis.copied = true;\n\t\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = window.setTimeout(() => {\n\t\t\t\tthis.copied = false;\n\t\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t\t\tthis.updateCaptureActions();\n\t\t\t}, 1200);\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.statusMessage = `Failed to copy snapshot: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\t}\n\t\t\tconsole.warn('Failed to copy FrameGraph Snapshot.', error);\n\t\t}\n\t\tfinally {\n\t\t\tthis.copying = false;\n\t\t\tif (!this.destroyed) this.updateCaptureActions();\n\t\t}\n\t}\n\n\tprivate applySnapshot(snapshot: FrameGraphSnapshot, source: FrameGraphDebugSnapshotSource): void {\n\t\tconst viewModel = createDebugViewModel(snapshot, source);\n\t\tthis.copied = false;\n\t\tif (this.copyFeedbackTimeout !== undefined) {\n\t\t\twindow.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t}\n\t\tthis.protocolSnapshot = snapshot;\n\t\tthis.viewModel = viewModel;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.hovered = undefined;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (!this.selected || !selectionExists(viewModel, this.selected)) {\n\t\t\tthis.selected = viewModel.nodes[0]\n\t\t\t\t? { kind: 'node', id: viewModel.nodes[0].id }\n\t\t\t\t: undefined;\n\t\t}\n\t\tthis.workbench.setSnapshot(viewModel, this.selected);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphModeButtonState();\n\t}\n\n\t/**\n\t * Idempotently cancels pending UI results, releases graph resources, and\n\t * removes the inspector workbench. Do not reuse the controller afterward.\n\t */\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.operationRevision += 1;\n\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\tthis.clearDropState();\n\t\tthis.dom.removeEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.removeEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.removeEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.removeEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.removeEventListener('drop', this.handleDrop);\n\t\tdestroyGraph(this.graphView);\n\t\tthis.dom.remove();\n\t}\n\n\tprivate updateCaptureActions(): void {\n\t\tthis.workbench.setSnapshotActionState({\n\t\t\tproviderAvailable: Boolean(this.captureSnapshotCallback),\n\t\t\thasCapture: Boolean(this.viewModel),\n\t\t\tcapturing: this.capturing,\n\t\t\timporting: this.importing,\n\t\t\tcopying: this.copying,\n\t\t\tcopied: this.copied,\n\t\t\tmessage: this.viewModel ? this.statusMessage : undefined,\n\t\t\tmessageTone: this.statusTone,\n\t\t});\n\t}\n\n\tprivate maybeAutoCapture(): void {\n\t\tif (\n\t\t\tthis.destroyed\n\t\t\t|| this.viewModel\n\t\t\t|| this.initialAutoCaptureAttempted\n\t\t\t|| this.capturing\n\t\t\t|| this.importing\n\t\t\t|| !this.captureSnapshotCallback\n\t\t) return;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tvoid this.captureSnapshot();\n\t}\n\tprivate handleSelect(selection: Selection): void {\n\t\tthis.selected = selection;\n\t\tthis.workbench.setSelection(selection);\n\t}\n\n\tprivate handleHover(selection: Selection | undefined): void {\n\t\tif (!this.viewModel || sameSelection(this.hovered, selection)) return;\n\t\tthis.hovered = selection;\n\t\tthis.workbench.setHovered(selection);\n\t}\n\n\tprivate setGraphMode(mode: GraphViewState['graphMode']): void {\n\t\tif (this.graphView.graphMode === mode) return;\n\t\tthis.graphView.graphMode = mode;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphModeButtonState();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate updateGraphModeButtonState(): void {\n\t\tconst passesActive = this.graphView.graphMode === 'passes';\n\t\tconst hasGroups = (this.viewModel?.debugGroups.length ?? 0) > 0;\n\t\tthis.passesGraphModeButton.classList.toggle('active', passesActive);\n\t\tthis.resourcesGraphModeButton.classList.toggle('active', !passesActive);\n\t\tthis.passesGraphModeButton.setAttribute('aria-pressed', passesActive ? 'true' : 'false');\n\t\tthis.resourcesGraphModeButton.setAttribute('aria-pressed', passesActive ? 'false' : 'true');\n\t\tthis.groupsButton.disabled = !passesActive || !hasGroups;\n\t\tthis.groupsButton.classList.toggle('active', passesActive && hasGroups && this.graphView.groupsEnabled);\n\t\tthis.groupsButton.setAttribute('aria-pressed', passesActive && hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');\n\t\tconst hasExpanded = this.viewModel?.debugGroups.some((group) => this.graphView.expandedGroupPaths.has(group.pathKey)) ?? false;\n\t\tthis.collapseGroupsButton.disabled = !passesActive || !hasGroups || !this.graphView.groupsEnabled || !hasExpanded;\n\t}\n\n\tprivate toggleGroups(): void {\n\t\tif (this.graphView.graphMode !== 'passes' || !this.viewModel?.debugGroups.length) return;\n\t\tthis.graphView.groupsEnabled = !this.graphView.groupsEnabled;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphModeButtonState();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate toggleGroup(pathKey: string): void {\n\t\tif (this.graphView.expandedGroupPaths.has(pathKey)) this.graphView.expandedGroupPaths.delete(pathKey);\n\t\telse this.graphView.expandedGroupPaths.add(pathKey);\n\t\tthis.graphView.anchorElementIdOnNextRender = graphGroupElementId(pathKey);\n\t\tthis.updateGraphModeButtonState();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate collapseAllGroups(): void {\n\t\tif (this.graphView.expandedGroupPaths.size === 0) return;\n\t\tthis.graphView.expandedGroupPaths.clear();\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphModeButtonState();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate showEmptyState(): void {\n\t\tconst providerAvailable = Boolean(this.captureSnapshotCallback);\n\t\tthis.workbench.showEmptyState(\n\t\t\t'empty',\n\t\t\tproviderAvailable\n\t\t\t\t? 'No capture yet. Use Capture to request the next rendered frame.'\n\t\t\t\t: 'Drop a ZenFG Snapshot here or choose Import.',\n\t\t\tproviderAvailable ? undefined : 'Files are processed locally in your browser.',\n\t\t);\n\t}\n\n\tprivate setDropActive(active: boolean): void {\n\t\tif (this.destroyed) return;\n\t\tthis.dropOverlay.hidden = !active;\n\t\tthis.dom.classList.toggle('drop-active', active);\n\t}\n\n\tprivate clearDropState(): void {\n\t\tthis.dragDepth = 0;\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dom.classList.remove('drop-active');\n\t}\n\n\tprivate reportCaptureIssue(message: string): void {\n\t\tthis.statusMessage = message;\n\t\tthis.statusTone = 'error';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('error', message);\n\t\tthis.updateCaptureActions();\n\t}\n}\n\n/**\n * Creates an inspector, appends its root element to `host`, and returns its\n * lifecycle controller.\n *\n * @throws If inspector construction fails; see {@link FrameGraphInspector}.\n */\nexport function mountFrameGraphInspector(host: HTMLElement, options?: FrameGraphInspectorOptions): FrameGraphInspector {\n\tconst inspector = new FrameGraphInspector(options);\n\thost.appendChild(inspector.dom);\n\treturn inspector;\n}\n\nfunction createGraphIconButton(icon: 'fit', title: string, onClick: () => void): HTMLButtonElement {\n\tconst button = createToolbarButton('', title, onClick);\n\tbutton.classList.add('zenfg-inspector-icon-button');\n\tbutton.appendChild(createPanelIcon(icon));\n\treturn button;\n}\n\nasync function writeTextToClipboard(text: string): Promise<void> {\n\tif (navigator.clipboard?.writeText) {\n\t\tawait navigator.clipboard.writeText(text);\n\t\treturn;\n\t}\n\tconst textArea = document.createElement('textarea');\n\ttextArea.value = text;\n\ttextArea.setAttribute('readonly', 'true');\n\ttextArea.style.position = 'fixed';\n\ttextArea.style.left = '-9999px';\n\ttextArea.style.top = '0';\n\tdocument.body.appendChild(textArea);\n\ttextArea.select();\n\ttry {\n\t\tif (!document.execCommand('copy')) throw new Error('document.execCommand(\"copy\") returned false.');\n\t}\n\tfinally {\n\t\ttextArea.remove();\n\t}\n}\n\nfunction normalizeMaxImportBytes(value: number | undefined): number {\n\treturn normalizeLimit(value, DEFAULT_MAX_IMPORT_BYTES, 'maxImportBytes');\n}\n\nfunction normalizeLimit(value: number | undefined, fallback: number, name: string): number {\n\tif (value === undefined) return fallback;\n\tif (!Number.isSafeInteger(value) || value < 0) {\n\t\tthrow new Error(`${name} must be a non-negative safe integer.`);\n\t}\n\treturn value;\n}\n\nfunction formatImportLimit(bytes: number): string {\n\treturn bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0\n\t\t? `${bytes / (1024 * 1024)} MiB`\n\t\t: `${bytes} bytes`;\n}\n\nfunction formatIssues(issues: readonly { readonly path: string; readonly message: string }[]): string {\n\treturn issues.slice(0, 3).map((issue) => `${issue.path || '/'}: ${issue.message}`).join('; ');\n}\n\nfunction isFileDrag(event: DragEvent): boolean {\n\treturn Array.from(event.dataTransfer?.types ?? []).includes('Files');\n}\n\nlet nextInspectorId = 0;\nfunction createInspectorId(): string {\n\tnextInspectorId += 1;\n\treturn `zenfg-inspector-${nextInspectorId}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FrameGraphInspector.js","sourceRoot":"","sources":["../src/FrameGraphInspector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EACN,iCAAiC,EACjC,wBAAwB,EACxB,uBAAuB,EACvB,2BAA2B,GAE3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,oBAAoB,GAGpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACN,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,aAAa,EAA2B,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAgCnE,MAAM,wBAAwB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAClD,MAAM,0BAA0B,GAAG,KAAK,CAAC;AACzC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,mBAAmB;IAC/B,qDAAqD;IAC5C,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAChC,eAAe,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzD,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACrC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACxC,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5C,YAAY,CAAoB;IAChC,kBAAkB,CAAoB;IACtC,oBAAoB,CAAoB;IACxC,SAAS,CAAiB;IAC1B,SAAS,CAA2B;IAC7C,uBAAuB,CAAgD;IACvE,gBAAgB,CAAiC;IACjD,iBAAiB,GAAG,CAAC,CAAC;IACtB,SAAS,CAAuC;IAChD,QAAQ,CAAwB;IAChC,OAAO,CAAwB;IAC/B,SAAS,GAAG,KAAK,CAAC;IAClB,SAAS,GAAG,KAAK,CAAC;IAClB,OAAO,GAAG,KAAK,CAAC;IAChB,MAAM,GAAG,KAAK,CAAC;IACf,2BAA2B,GAAG,KAAK,CAAC;IACpC,aAAa,CAAqB;IAClC,UAAU,GAAwB,SAAS,CAAC;IAC5C,SAAS,GAAG,KAAK,CAAC;IAClB,mBAAmB,CAAqB;IAC/B,cAAc,CAAS;IAChC,SAAS,GAAG,CAAC,CAAC;IACd,cAAc,GAAG,CAAC,CAAC;IACV,eAAe,GAAG,CAAC,KAAgB,EAAQ,EAAE;QAC7D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO;QAC/B,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;IACe,cAAc,GAAG,CAAC,KAAgB,EAAQ,EAAE;QAC5D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO;QAC/B,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,IAAI,KAAK,CAAC,YAAY;YAAE,KAAK,CAAC,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC;QAC/D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;IACe,eAAe,GAAG,CAAC,KAAgB,EAAQ,EAAE;QAC7D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YAAE,OAAO;QACvD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC;YAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC;IACe,aAAa,GAAG,GAAS,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;IAClD,UAAU,GAAG,CAAC,KAAgB,EAAQ,EAAE;QACxD,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC;IAEF;;;;;OAKG;IACH,YAAY,UAAsC,EAAE;QACnD,+BAA+B,EAAE,CAAC;QAClC,IAAI,CAAC,uBAAuB,GAAG,OAAO,CAAC,eAAe,CAAC;QACvD,IAAI,CAAC,cAAc,GAAG,uBAAuB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,gBAAgB,CAAC;QACtD,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,iBAAiB,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,iBAAiB,EAAE,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,YAAY,EAAE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACtF,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,sBAAsB,CAAC;QAC7C,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,yBAAyB,CAAC;QACnD,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,8BAA8B,CAAC;QAC5D,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,SAAS,CAAC,WAAW,GAAG,uBAAuB,CAAC;QAChD,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAClD,UAAU,CAAC,WAAW,GAAG,0CAA0C,CAAC;QACpE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAE/C,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAClD,WAAW,CAAC,SAAS,GAAG,8BAA8B,CAAC;QACvD,WAAW,CAAC,YAAY,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS,GAAG;YAChB,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;YACnC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;YACtC,MAAM,EAAE,WAAW;YACnB,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE;YACvC,mBAAmB,EAAE,cAAc,CAAC,OAAO,CAAC,gBAAgB,EAAE,0BAA0B,EAAE,kBAAkB,CAAC;YAC7G,aAAa,EAAE,IAAI;YACnB,wBAAwB,EAAE,IAAI;YAC9B,kBAAkB,EAAE,IAAI,GAAG,EAAE;YAC7B,eAAe,EAAE,IAAI;SACrB,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,GAAG,uBAAuB,CAAC;QACxD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,GAAG,+BAA+B,CAAC;QACnE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,EAAE,2BAA2B,CAAC,CAAC;QAE/E,IAAI,CAAC,kBAAkB,GAAG,mBAAmB,CAAC,cAAc,EAAE,iCAAiC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;QAClI,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAC,QAAQ,EAAE,oCAAoC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACnH,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC,cAAc,EAAE,iCAAiC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAEnI,MAAM,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,SAAS,GAAG,uCAAuC,CAAC;QACnE,cAAc,CAAC,MAAM,CACpB,IAAI,CAAC,kBAAkB,EACvB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,oBAAoB,EACzB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAC/E,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAE9C,MAAM,SAAS,GAAuB;YACrC,QAAQ,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;YACrD,OAAO,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;YACnD,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC;YACrD,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC;YAC5E,QAAQ,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;YAC/D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;SACjE,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,IAAI,wBAAwB,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE;YACxE,SAAS,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;YACjD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvD,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE;YACzC,UAAU,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;SACnD,EAAE;YACF,QAAQ;YACR,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,OAAO,CAAC,KAAK;YAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,cAAc,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClG,CAAC;IAEE;;OAEG;IACH,QAAQ,CAAC,KAA4B;QACjC,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,YAAY,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,YAAY;QACR,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,SAAS;YAAE,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;IACjI,CAAC;IAEJ;;;;;;;OAOG;IACH,0BAA0B,CAAC,QAAuD;QACjF,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,uBAAuB,KAAK,QAAQ;YAAE,OAAO;QACxE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;YAC5B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,uBAAuB,GAAG,QAAQ,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,2BAA2B,GAAG,KAAK,CAAC;QAC9D,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,cAAc,EAAE,CAAC;QAC3E,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,eAAe;QACpB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC7C,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACnC,IAAI,CAAC,kBAAkB,CAAC,0CAA0C,CAAC,CAAC;YACpE,OAAO;QACR,CAAC;QACD,MAAM,QAAQ,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,WAAW,EAAE,oCAAoC,CAAC,CAAC;QACtG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,OAAO,GAA6B,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YAC7D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;YAC7D,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,OAAO;YAClE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,IAAI,CAAC,kBAAkB,CAAC,mEAAmE,CAAC,CAAC;gBAC7F,OAAO;YACR,CAAC;YACD,MAAM,OAAO,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,CAAC,kBAAkB,CAAC,iCAAiC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACzF,OAAO;YACR,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC5D,IAAI,CAAC,kBAAkB,CAAC,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACpH,CAAC;QACF,CAAC;gBACO,CAAC;YACR,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YAChE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACzF,CAAC;IACF,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,QAA4B;QACvC,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,MAAM,OAAO,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,MAAM,IAAI,iCAAiC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7E,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,kEAAkE;IAClE,WAAW;QACV,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,cAAc,CAAC,IAAU;QAC9B,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,MAAM,QAAQ,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACrC,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YAC/F,OAAO;QACR,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,OAAO;YAClE,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,CAAC,kBAAkB,CAAC,8BAA8B,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACtF,OAAO;YACR,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACpC,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,eAAe;aACnC,CAAC,CAAC;YACH,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC;YACtE,IAAI,YAAY,EAAE,CAAC;gBAClB,4EAA4E;gBAC5E,MAAM,WAAW,GAAG;oBACnB,WAAW,EAAE,WAAW;oBACxB,qBAAqB,EAAE,qBAAqB;oBAC5C,eAAe,EAAE,cAAc;iBAC/B,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC/E,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACzC,MAAM,WAAW,GAAG,YAAY,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjE,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,QAAQ;oBACpC,CAAC,CAAC,YAAY,WAAW,6BAA6B,WAAW,GAAG;oBACpE,CAAC,CAAC,YAAY,WAAW,SAAS,WAAW,wBAAwB,CAAC;gBACvE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAC7B,CAAC;QACF,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC5D,IAAI,CAAC,kBAAkB,CAAC,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACjH,CAAC;QACF,CAAC;gBACO,CAAC;YACR,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YAChE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACzF,CAAC;IACF,CAAC;IAED,yEAAyE;IACzE,gBAAgB;QACf,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO;QACrD,MAAM,IAAI,GAAG,2BAA2B,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,gCAAgC,EAAE,CAAC,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;QAClB,MAAM,CAAC,QAAQ,GAAG,eAAe,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAU,kBAAkB,CAAC;QAC5F,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,gBAAgB;QACrB,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC;YACJ,MAAM,oBAAoB,CAAC,2BAA2B,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACpF,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB;gBAAE,OAAO;YAClE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS;gBAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAC1F,IAAI,CAAC,mBAAmB,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;gBACjD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;gBACpB,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;gBACrC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC7B,CAAC,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;QACD,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC5D,IAAI,CAAC,aAAa,GAAG,4BAA4B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3G,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC5D,CAAC;gBACO,CAAC;YACR,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,SAAS;gBAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClD,CAAC;IACF,CAAC;IAEO,aAAa,CAAC,QAA4B,EAAE,MAAqC;QACxF,MAAM,SAAS,GAAG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAC5C,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAC9C,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,SAAS,CAAC,eAAe,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3E,IAAI,CAAC,SAAS,CAAC,kBAAkB,GAAG,SAAS,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,2BAA2B,GAAG,IAAI,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,SAAS,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,oBAAoB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;aACrI,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC;YAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAChG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,OAAO;QACN,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS;YAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC1F,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;QAC/B,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;IACnB,CAAC;IAEO,oBAAoB;QAC3B,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC;YACrC,iBAAiB,EAAE,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC;YACxD,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;YACnC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;YACxD,WAAW,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;IACJ,CAAC;IAEO,gBAAgB;QACvB,IACC,IAAI,CAAC,SAAS;eACX,IAAI,CAAC,SAAS;eACd,IAAI,CAAC,2BAA2B;eAChC,IAAI,CAAC,SAAS;eACd,IAAI,CAAC,SAAS;eACd,CAAC,IAAI,CAAC,uBAAuB;YAC/B,OAAO;QACT,IAAI,CAAC,2BAA2B,GAAG,IAAI,CAAC;QACxC,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;IAC7B,CAAC;IACO,YAAY,CAAC,SAAoB;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC;YAAE,OAAO;QAC3E,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAEO,YAAY,CAAC,SAAoB,EAAE,GAAiB;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC;YAAE,OAAO;QAC/D,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;YACnD,MAAM,wBAAwB,GAAG,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC;YACzE,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU;gBAAE,IAAI,CAAC,SAAS,CAAC,wBAAwB,GAAG,IAAI,CAAC;YAClF,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO;gBAAE,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC;YACpE,IAAI,OAA2B,CAAC;YAChC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC;iBACtF,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU;gBAAE,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC;iBACnG,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO;gBAAE,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;YACxG,IAAI,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,OAAO,EAAE,CAAC;gBAC7C,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,WAAW,IAAI,EAAE,EAAE,CAAC;oBACrE,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACzC,IAAI,KAAK;wBAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACjE,CAAC;YACF,CAAC;YACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC1D,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACxF,IAAI,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxH,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,aAAa,CAAC;gBAC7C,IAAI,CAAC,SAAS,CAAC,wBAAwB,GAAG,wBAAwB,CAAC;gBACnE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;gBAC1C,KAAK,MAAM,IAAI,IAAI,QAAQ;oBAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACzE,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,2CAA2C,CAAC,CAAC,CAAC,kDAAkD,EAAE,SAAS,CAAC,CAAC;gBAC9K,OAAO;YACR,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,kBAAkB,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC;YACnF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACvC,CAAC;IAEO,WAAW,CAAC,SAAgC;QACnD,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;YAAE,OAAO;QACtE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAEO,mBAAmB;QAC1B,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,wBAAwB,IAAI,IAAI,CAAC;QACzE,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QACrE,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC/E,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAChE,IAAI,CAAC,YAAY,CAAC,QAAQ,GAAG,CAAC,SAAS,CAAC;QACxC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC;QACtC,IAAI,CAAC,oBAAoB,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC;QAC9C,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACxF,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,cAAc,EAAE,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC7G,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC;QAC/H,IAAI,CAAC,oBAAoB,CAAC,QAAQ,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,CAAC,WAAW,CAAC;IAClG,CAAC;IAEO,kBAAkB;QACzB,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,wBAAwB,IAAI,IAAI,CAAC,CAAC;QAC7F,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC,SAAS,CAAC,kBAAkB,GAAG,SAAS,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,2BAA2B,GAAG,SAAS,CAAC;QACvD,IAAI,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC;IACxC,CAAC;IAEO,YAAY;QACnB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM;YAAE,OAAO;QAChD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;QAC7D,IAAI,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC;IACxC,CAAC;IAEO,WAAW,CAAC,OAAe;QAClC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;;YACjG,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,CAAC,2BAA2B,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC;IACxC,CAAC;IAEO,iBAAiB;QACxB,IAAI,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO;QACzD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAC1C,IAAI,CAAC,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC;QACtC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC;IACxC,CAAC;IAEO,cAAc;QACrB,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAChE,IAAI,CAAC,SAAS,CAAC,cAAc,CAC5B,OAAO,EACP,iBAAiB;YAChB,CAAC,CAAC,iEAAiE;YACnE,CAAC,CAAC,8CAA8C,EACjD,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,8CAA8C,CAC9E,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,MAAe;QACpC,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAEO,cAAc;QACrB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAEO,kBAAkB,CAAC,OAAe;QACzC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrE,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC7B,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAiB,EAAE,OAAoC;IAC/F,MAAM,SAAS,GAAG,IAAI,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,SAAS,CAAC,YAAY,EAAE,CAAC;IACzB,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC;QACpC,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO;IACR,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC;QACJ,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACpG,CAAC;YACO,CAAC;QACR,QAAQ,CAAC,MAAM,EAAE,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAyB;IACzD,OAAO,cAAc,CAAC,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB,EAAE,QAAgB,EAAE,IAAY;IAChF,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,uCAAuC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACvC,OAAO,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACzD,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM;QAChC,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC;AACrB,CAAC;AAED,SAAS,YAAY,CAAC,MAAsE;IAC3F,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,UAAU,CAAC,KAAgB;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,IAAI,eAAe,GAAG,CAAC,CAAC;AACxB,SAAS,iBAAiB;IACzB,eAAe,IAAI,CAAC,CAAC;IACrB,OAAO,mBAAmB,eAAe,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["import type { FrameGraphCaptureRequest } from './capture.ts';\nimport type { InspectorTheme } from './theme.ts';\nimport { InspectorThemeController, resolveGraphTheme } from './panelTheme.ts';\nimport {\n\tFrameGraphSnapshotValidationError,\n\tdecodeFrameGraphSnapshot,\n\tparseFrameGraphSnapshot,\n\tstringifyFrameGraphSnapshot,\n\ttype FrameGraphSnapshot,\n} from '@zenfg/snapshot';\nimport {\n\tcreateDebugViewModel,\n\ttype FrameGraphDebugSnapshotSource,\n\ttype FrameGraphDebugViewModel,\n} from './debugCaptureModel.ts';\nimport { createToolbarButton } from './panelDomHelpers.ts';\nimport {\n\tdestroyGraph,\n\tfitGraph,\n\tresolveGraphScene,\n\trenderGraphLegend,\n} from './panelGraphView.ts';\nimport { graphGroupElementId, selectionKey } from './panelGraphScene.ts';\nimport { resolveNodeSelection, selectionExists } from './panelSelection.ts';\nimport type { GraphViewState, Selection, WorkbenchTab } from './panelTypes.ts';\nimport { ensureFrameGraphInspectorStyles } from './styles.ts';\nimport { sameSelection, type WorkbenchCallbacks } from './panelWorkbenchHelpers.ts';\nimport { FrameGraphDebugWorkbench } from './panelWorkbenchView.ts';\n\n/** Construction and safety limits for an embedded {@link FrameGraphInspector}. */\nexport type FrameGraphInspectorOptions = {\n\t/** Optional CSS theme. Without one, host variables inherit over the Storm defaults. */\n\ttheme?: InspectorTheme;\n\t/**\n\t * Product label shown in the workbench command bar. Pass `false` to hide\n\t * visible branding while retaining the inspector's accessible name.\n\t *\n\t * @defaultValue `\"ZenFG Inspector\"`\n\t */\n\tbranding?: string | false;\n\t/**\n\t * Produces a live snapshot when capture is requested. The inspector awaits\n\t * promises and displays thrown or rejected errors in its status area.\n\t */\n\tcaptureSnapshot?: (request: FrameGraphCaptureRequest) => FrameGraphSnapshot | undefined | Promise<FrameGraphSnapshot | undefined>;\n\t/**\n\t * Maximum accepted import size in bytes.\n\t *\n\t * @defaultValue `67108864` (64 MiB)\n\t */\n\tmaxImportBytes?: number;\n\t/**\n\t * Maximum graph nodes plus edges accepted by automatic layout.\n\t *\n\t * @defaultValue `5000`\n\t */\n\tmaxGraphElements?: number;\n};\n\nconst DEFAULT_MAX_IMPORT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_MAX_GRAPH_ELEMENTS = 5_000;\nconst DEFAULT_BRANDING = 'ZenFG Inspector';\n\n/**\n * Browser lifecycle controller for one embeddable FrameGraph inspector.\n *\n * @remarks The constructor creates, but does not append, {@link dom}. Use\n * {@link mountFrameGraphInspector} for the common append-and-return workflow.\n * Async capture, import, and clipboard failures are reported in the UI. Call\n * {@link destroy} when the controller is no longer needed.\n *\n * @example\n * ```ts\n * const inspector = new FrameGraphInspector({ captureSnapshot: capture });\n * document.body.append(inspector.dom);\n * // Later:\n * inspector.destroy();\n * ```\n */\nexport class FrameGraphInspector {\n\t/** Root element owned by this inspector instance. */\n\treadonly dom = document.createElement('section');\n\tprivate readonly themeController = new InspectorThemeController(this.dom);\n\n\tprivate readonly body = document.createElement('div');\n\tprivate readonly content = document.createElement('div');\n\tprivate readonly dropOverlay = document.createElement('div');\n\tprivate readonly groupsButton: HTMLButtonElement;\n\tprivate readonly declarationsButton: HTMLButtonElement;\n\tprivate readonly collapseGroupsButton: HTMLButtonElement;\n\tprivate readonly graphView: GraphViewState;\n\tprivate readonly workbench: FrameGraphDebugWorkbench;\n\tprivate captureSnapshotCallback: FrameGraphInspectorOptions['captureSnapshot'];\n\tprivate protocolSnapshot: FrameGraphSnapshot | undefined;\n\tprivate operationRevision = 0;\n\tprivate viewModel: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate hovered: Selection | undefined;\n\tprivate capturing = false;\n\tprivate importing = false;\n\tprivate copying = false;\n\tprivate copied = false;\n\tprivate initialAutoCaptureAttempted = false;\n\tprivate statusMessage: string | undefined;\n\tprivate statusTone: 'neutral' | 'error' = 'neutral';\n\tprivate destroyed = false;\n\tprivate copyFeedbackTimeout: number | undefined;\n\tprivate readonly maxImportBytes: number;\n\tprivate dragDepth = 0;\n\tprivate revealRevision = 0;\n\tprivate readonly handleDragEnter = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tthis.dragDepth += 1;\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragOver = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event)) return;\n\t\tevent.preventDefault();\n\t\tif (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n\t\tthis.setDropActive(true);\n\t};\n\tprivate readonly handleDragLeave = (event: DragEvent): void => {\n\t\tif (!isFileDrag(event) && this.dragDepth === 0) return;\n\t\tthis.dragDepth = Math.max(0, this.dragDepth - 1);\n\t\tif (this.dragDepth === 0) this.setDropActive(false);\n\t};\n\tprivate readonly handleDragEnd = (): void => this.clearDropState();\n\tprivate readonly handleDrop = (event: DragEvent): void => {\n\t\tconst file = event.dataTransfer?.files?.[0];\n\t\tif (!file) return;\n\t\tevent.preventDefault();\n\t\tthis.clearDropState();\n\t\tvoid this.importSnapshot(file);\n\t};\n\n\t/**\n\t * Creates a detached inspector UI.\n\t *\n\t * @throws If a configured numeric limit is not a non-negative safe integer,\n\t * or if browser DOM globals are unavailable.\n\t */\n\tconstructor(options: FrameGraphInspectorOptions = {}) {\n\t\tensureFrameGraphInspectorStyles();\n\t\tthis.captureSnapshotCallback = options.captureSnapshot;\n\t\tthis.maxImportBytes = normalizeMaxImportBytes(options.maxImportBytes);\n\t\tconst branding = options.branding ?? DEFAULT_BRANDING;\n\t\tthis.dom.className = 'zenfg-inspector';\n\t\tthis.dom.id = createInspectorId();\n\t\tthis.dom.setAttribute('role', 'region');\n\t\tthis.dom.setAttribute('aria-label', branding === false ? DEFAULT_BRANDING : branding);\n\t\tthis.body.className = 'zenfg-inspector-body';\n\t\tthis.content.className = 'zenfg-inspector-content';\n\t\tthis.dropOverlay.className = 'zenfg-inspector-drop-overlay';\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dropOverlay.setAttribute('aria-hidden', 'true');\n\t\tconst dropTitle = document.createElement('strong');\n\t\tdropTitle.textContent = 'Drop snapshot to open';\n\t\tconst dropDetail = document.createElement('span');\n\t\tdropDetail.textContent = 'The first file will be imported locally.';\n\t\tthis.dropOverlay.append(dropTitle, dropDetail);\n\n\t\tconst graphLegend = document.createElement('div');\n\t\tgraphLegend.className = 'zenfg-inspector-graph-legend';\n\t\tgraphLegend.setAttribute('aria-label', 'Graph legend');\n\t\tthis.graphView = {\n\t\t\thost: document.createElement('div'),\n\t\t\ttoolbar: document.createElement('div'),\n\t\t\tlegend: graphLegend,\n\t\t\trefreshTheme: () => this.refreshTheme(),\n\t\t\tlayoutElementBudget: normalizeLimit(options.maxGraphElements, DEFAULT_MAX_GRAPH_ELEMENTS, 'maxGraphElements'),\n\t\t\tgroupsEnabled: true,\n\t\t\tshowResourceDeclarations: true,\n\t\t\texpandedGroupPaths: new Set(),\n\t\t\tfitOnNextRender: true,\n\t\t};\n\t\tthis.graphView.host.className = 'zenfg-inspector-graph';\n\t\tthis.graphView.toolbar.className = 'zenfg-inspector-graph-toolbar';\n\t\tthis.graphView.toolbar.setAttribute('role', 'toolbar');\n\t\tthis.graphView.toolbar.setAttribute('aria-label', 'Frame graph view controls');\n\n\t\tthis.declarationsButton = createToolbarButton('Declarations', 'Show resource declaration nodes', () => this.toggleDeclarations());\n\t\tthis.groupsButton = createToolbarButton('Groups', 'Toggle diagnostic group projection', () => this.toggleGroups());\n\t\tthis.collapseGroupsButton = createToolbarButton('Collapse All', 'Collapse every diagnostic group', () => this.collapseAllGroups());\n\n\t\tconst actionControls = document.createElement('div');\n\t\tactionControls.className = 'zenfg-inspector-graph-action-controls';\n\t\tactionControls.append(\n\t\t\tthis.declarationsButton,\n\t\t\tthis.groupsButton,\n\t\t\tthis.collapseGroupsButton,\n\t\t\tcreateToolbarButton('Fit', 'Fit graph to view', () => fitGraph(this.graphView)),\n\t\t);\n\t\tthis.graphView.toolbar.append(actionControls);\n\n\t\tconst callbacks: WorkbenchCallbacks = {\n\t\t\tonSelect: (selection) => this.handleSelect(selection),\n\t\t\tonHover: (selection) => this.handleHover(selection),\n\t\t\tonGroupToggle: (pathKey) => this.toggleGroup(pathKey),\n\t\t\tisGroupExpanded: (pathKey) => this.graphView.expandedGroupPaths.has(pathKey),\n\t\t\tonReveal: (selection, tab) => this.handleReveal(selection, tab),\n\t\t\tonNavigate: (tab, filter) => this.workbench.navigate(tab, filter),\n\t\t};\n\t\tthis.workbench = new FrameGraphDebugWorkbench(this.graphView, callbacks, {\n\t\t\tonCapture: () => { void this.captureSnapshot(); },\n\t\t\tonImport: (file) => { void this.importSnapshot(file); },\n\t\t\tonDownload: () => this.downloadSnapshot(),\n\t\t\tonCopyJson: () => { void this.copySnapshotJson(); },\n\t\t}, {\n\t\t\tbranding,\n\t\t\tidPrefix: this.dom.id,\n\t\t});\n\t\tthis.content.append(this.workbench.root);\n\t\tthis.body.appendChild(this.content);\n\t\tthis.dom.append(this.body, this.dropOverlay);\n\t\tthis.dom.addEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.addEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.addEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.addEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.addEventListener('drop', this.handleDrop);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphControls();\n\t\tthis.showEmptyState();\n\t\tif (options.theme) this.setTheme(options.theme);\n\t\tqueueMicrotask(() => { if (!this.destroyed) { this.refreshTheme(); this.maybeAutoCapture(); } });\n\t}\n\n /** Replace API-applied variables on this instance, then synchronize graph styles.\n * Pass null to restore host CSS and defaults. Does not change capture or interaction state.\n */\n setTheme(theme: InspectorTheme | null): void {\n if (this.destroyed) return;\n this.themeController.apply(theme);\n this.refreshTheme();\n }\n\n /** Re-read final CSS values after external CSS changes and refresh graph and legend.\n * Does not write theme variables, recapture, fit, or rebuild the component.\n */\n refreshTheme(): void {\n if (this.destroyed) return;\n const theme = resolveGraphTheme(this.dom);\n this.graphView.theme = theme;\n this.graphView.renderer?.setTheme?.(theme);\n if (this.viewModel) renderGraphLegend(this.graphView.legend, this.viewModel, theme, this.graphView.showResourceDeclarations);\n }\n\n\t/**\n\t * Replaces or removes the live-capture provider.\n\t *\n\t * @remarks Installing a provider may immediately begin an asynchronous\n\t * capture when no snapshot is displayed. Replacing or removing a provider\n\t * invalidates its pending capture results without cancelling the provider\n\t * promise. An already displayed snapshot and any pending import are preserved.\n\t */\n\tsetCaptureSnapshotProvider(provider: FrameGraphInspectorOptions['captureSnapshot']): void {\n\t\tif (this.destroyed || this.captureSnapshotCallback === provider) return;\n\t\tif (this.capturing) {\n\t\t\tthis.operationRevision += 1;\n\t\t\tthis.capturing = false;\n\t\t}\n\t\tthis.captureSnapshotCallback = provider;\n\t\tif (!this.viewModel) this.initialAutoCaptureAttempted = false;\n\t\tif (!provider && !this.viewModel && !this.importing) this.showEmptyState();\n\t\tthis.updateCaptureActions();\n\t\tthis.maybeAutoCapture();\n\t}\n\n\t/**\n\t * Requests and displays a live snapshot from the configured provider.\n\t *\n\t * @remarks Concurrent requests are coalesced. Provider errors, invalid\n\t * snapshots, and an unavailable provider are displayed in the inspector and\n\t * do not reject the returned promise.\n\t */\n\tasync captureSnapshot(): Promise<void> {\n\t\tif (this.destroyed || this.capturing) return;\n\t\tif (!this.captureSnapshotCallback) {\n\t\t\tthis.reportCaptureIssue('Waiting for a FrameGraph capture source.');\n\t\t\treturn;\n\t\t}\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.importing = false;\n\t\tthis.capturing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('capturing', 'Capturing the next rendered frame…');\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst request: FrameGraphCaptureRequest = { timing: 'both' };\n\t\t\tconst snapshot = await this.captureSnapshotCallback(request);\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tif (!snapshot) {\n\t\t\t\tthis.reportCaptureIssue('No snapshot was produced. Capture again when rendering is active.');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, { kind: 'live', label: 'Live Capture' });\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to capture FrameGraph: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.capturing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/**\n\t * Validates and synchronously displays a programmatic Snapshot 1.2 value.\n\t *\n\t * @throws {@link @zenfg/snapshot!index.FrameGraphSnapshotValidationError | FrameGraphSnapshotValidationError} if `snapshot` is invalid.\n\t */\n\tsetSnapshot(snapshot: FrameGraphSnapshot): void {\n\t\tif (this.destroyed) return;\n\t\tthis.operationRevision += 1;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tconst decoded = decodeFrameGraphSnapshot(snapshot);\n\t\tif (!decoded.ok) throw new FrameGraphSnapshotValidationError(decoded.issues);\n\t\tthis.applySnapshot(decoded.snapshot, { kind: 'programmatic', label: 'Programmatic' });\n\t}\n\n\t/** Returns the currently displayed canonical snapshot, if any. */\n\tgetSnapshot(): FrameGraphSnapshot | undefined {\n\t\treturn this.protocolSnapshot;\n\t}\n\n\t/**\n\t * Reads, migrates, validates, and displays a snapshot JSON file.\n\t *\n\t * @remarks Files above `maxImportBytes`, read failures, invalid JSON, and\n\t * validation failures are displayed in the UI and do not reject the promise.\n\t */\n\tasync importSnapshot(file: File): Promise<void> {\n\t\tif (this.destroyed) return;\n\t\tconst revision = ++this.operationRevision;\n\t\tthis.capturing = false;\n\t\tthis.importing = false;\n\t\tif (file.size > this.maxImportBytes) {\n\t\t\tthis.reportCaptureIssue(`Import exceeds the ${formatImportLimit(this.maxImportBytes)} limit.`);\n\t\t\treturn;\n\t\t}\n\t\tthis.importing = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tconst text = await file.text();\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tconst decoded = parseFrameGraphSnapshot(text);\n\t\t\tif (!decoded.ok) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${formatIssues(decoded.issues)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.applySnapshot(decoded.snapshot, {\n\t\t\t\tkind: 'file',\n\t\t\t\tlabel: file.name || 'Imported JSON',\n\t\t\t});\n\t\t\tconst sourceFormat = decoded.snapshot.capture.migration?.sourceFormat;\n\t\t\tif (sourceFormat) {\n\t\t\t\t// The current import format can differ from retained historical provenance.\n\t\t\t\tconst sourceLabel = {\n\t\t\t\t\t'legacy-v0': 'Legacy V0',\n\t\t\t\t\t'legacy-candidate-v1': 'Legacy Candidate V1',\n\t\t\t\t\t'snapshot-v1.1': 'Snapshot 1.1',\n\t\t\t\t}[decoded.migrated && decoded.source !== 'v1' ? decoded.source : sourceFormat];\n\t\t\t\tconst version = decoded.snapshot.version;\n\t\t\t\tconst targetLabel = `Snapshot ${version.major}.${version.minor}`;\n\t\t\t\tthis.statusMessage = decoded.migrated\n\t\t\t\t\t? `Imported ${sourceLabel} and migrated it to ZenFG ${targetLabel}.`\n\t\t\t\t\t: `Imported ${targetLabel} with ${sourceLabel} migration provenance.`;\n\t\t\t\tthis.statusTone = 'neutral';\n\t\t\t}\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.reportCaptureIssue(`Failed to import snapshot: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t}\n\t\tfinally {\n\t\t\tif (revision === this.operationRevision) this.importing = false;\n\t\t\tif (!this.destroyed && revision === this.operationRevision) this.updateCaptureActions();\n\t\t}\n\t}\n\n\t/** Downloads the displayed snapshot as pretty-printed canonical JSON. */\n\tdownloadSnapshot(): void {\n\t\tif (this.destroyed || !this.protocolSnapshot) return;\n\t\tconst json = stringifyFrameGraphSnapshot(this.protocolSnapshot, { pretty: true });\n\t\tconst url = URL.createObjectURL(new Blob([json], { type: 'application/json;charset=utf-8' }));\n\t\tconst anchor = document.createElement('a');\n\t\tanchor.href = url;\n\t\tanchor.download = `frame-graph-${this.protocolSnapshot.capture.frameIndex}.fgsnapshot.json`;\n\t\tanchor.click();\n\t\tURL.revokeObjectURL(url);\n\t}\n\n\t/**\n\t * Copies the displayed snapshot as pretty-printed canonical JSON.\n\t *\n\t * @remarks Clipboard failures are shown in the UI and do not reject the\n\t * returned promise. A legacy `document.execCommand` fallback is used when the\n\t * async Clipboard API is unavailable.\n\t */\n\tasync copySnapshotJson(): Promise<void> {\n\t\tif (this.destroyed || this.copying || !this.protocolSnapshot) return;\n\t\tconst snapshot = this.protocolSnapshot;\n\t\tconst revision = this.operationRevision;\n\t\tthis.copying = true;\n\t\tthis.copied = false;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tthis.updateCaptureActions();\n\t\ttry {\n\t\t\tawait writeTextToClipboard(stringifyFrameGraphSnapshot(snapshot, { pretty: true }));\n\t\t\tif (this.destroyed || revision !== this.operationRevision) return;\n\t\t\tthis.copied = true;\n\t\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = window.setTimeout(() => {\n\t\t\t\tthis.copied = false;\n\t\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t\t\tthis.updateCaptureActions();\n\t\t\t}, 1200);\n\t\t}\n\t\tcatch (error) {\n\t\t\tif (!this.destroyed && revision === this.operationRevision) {\n\t\t\t\tthis.statusMessage = `Failed to copy snapshot: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\t}\n\t\t\tconsole.warn('Failed to copy FrameGraph Snapshot.', error);\n\t\t}\n\t\tfinally {\n\t\t\tthis.copying = false;\n\t\t\tif (!this.destroyed) this.updateCaptureActions();\n\t\t}\n\t}\n\n\tprivate applySnapshot(snapshot: FrameGraphSnapshot, source: FrameGraphDebugSnapshotSource): void {\n\t\tconst viewModel = createDebugViewModel(snapshot, source);\n\t\tthis.copied = false;\n\t\tif (this.copyFeedbackTimeout !== undefined) {\n\t\t\twindow.clearTimeout(this.copyFeedbackTimeout);\n\t\t\tthis.copyFeedbackTimeout = undefined;\n\t\t}\n\t\tthis.protocolSnapshot = snapshot;\n\t\tthis.viewModel = viewModel;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.graphView.captureRevision = (this.graphView.captureRevision ?? 0) + 1;\n\t\tthis.graphView.revealOnNextRender = undefined;\n\t\tthis.graphView.renderer?.cancelReveal?.();\n\t\tthis.hovered = undefined;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tthis.statusMessage = undefined;\n\t\tthis.statusTone = 'neutral';\n\t\tif (this.selected?.kind === 'node' || this.selected?.kind === 'culled') this.selected = resolveNodeSelection(viewModel, this.selected.id);\n\t\telse if (this.selected && !selectionExists(viewModel, this.selected)) this.selected = undefined;\n\t\tthis.workbench.setSnapshot(viewModel, this.selected);\n\t\tthis.updateCaptureActions();\n\t\tthis.updateGraphControls();\n\t}\n\n\t/**\n\t * Idempotently cancels pending UI results, releases graph resources, and\n\t * removes the inspector workbench. Do not reuse the controller afterward.\n\t */\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.operationRevision += 1;\n\t\tif (this.copyFeedbackTimeout !== undefined) window.clearTimeout(this.copyFeedbackTimeout);\n\t\tthis.clearDropState();\n\t\tthis.dom.removeEventListener('dragenter', this.handleDragEnter);\n\t\tthis.dom.removeEventListener('dragover', this.handleDragOver);\n\t\tthis.dom.removeEventListener('dragleave', this.handleDragLeave);\n\t\tthis.dom.removeEventListener('dragend', this.handleDragEnd);\n\t\tthis.dom.removeEventListener('drop', this.handleDrop);\n\t\tthis.themeController.destroy();\n\t\tdestroyGraph(this.graphView);\n\t\tthis.workbench.destroy();\n\t\tthis.dom.remove();\n\t}\n\n\tprivate updateCaptureActions(): void {\n\t\tthis.workbench.setSnapshotActionState({\n\t\t\tproviderAvailable: Boolean(this.captureSnapshotCallback),\n\t\t\thasCapture: Boolean(this.viewModel),\n\t\t\tcapturing: this.capturing,\n\t\t\timporting: this.importing,\n\t\t\tcopying: this.copying,\n\t\t\tcopied: this.copied,\n\t\t\tmessage: this.viewModel ? this.statusMessage : undefined,\n\t\t\tmessageTone: this.statusTone,\n\t\t});\n\t}\n\n\tprivate maybeAutoCapture(): void {\n\t\tif (\n\t\t\tthis.destroyed\n\t\t\t|| this.viewModel\n\t\t\t|| this.initialAutoCaptureAttempted\n\t\t\t|| this.capturing\n\t\t\t|| this.importing\n\t\t\t|| !this.captureSnapshotCallback\n\t\t) return;\n\t\tthis.initialAutoCaptureAttempted = true;\n\t\tvoid this.captureSnapshot();\n\t}\n\tprivate handleSelect(selection: Selection): void {\n\t\tif (!this.viewModel || !selectionExists(this.viewModel, selection)) return;\n\t\tthis.selected = selection;\n\t\tthis.workbench.setSelection(selection);\n\t}\n\n\tprivate handleReveal(selection: Selection, tab: WorkbenchTab): void {\n\t\tconst snapshot = this.viewModel;\n\t\tif (!snapshot || !selectionExists(snapshot, selection)) return;\n\t\tif (tab === 'graph') {\n\t\t\tconst expanded = new Set(this.graphView.expandedGroupPaths);\n\t\t\tconst groupsEnabled = this.graphView.groupsEnabled;\n\t\t\tconst showResourceDeclarations = this.graphView.showResourceDeclarations;\n\t\t\tif (selection.kind === 'resource') this.graphView.showResourceDeclarations = true;\n\t\t\tif (selection.kind === 'group') this.graphView.groupsEnabled = true;\n\t\t\tlet groupId: string | undefined;\n\t\t\tif (selection.kind === 'node') groupId = snapshot.nodeById.get(selection.id)?.debugGroupId;\n\t\t\telse if (selection.kind === 'resource') groupId = snapshot.resourceById.get(selection.id)?.debugGroupId;\n\t\t\telse if (selection.kind === 'group') groupId = snapshot.groupByPathKey.get(selection.pathKey)?.parentId;\n\t\t\tif (this.graphView.groupsEnabled && groupId) {\n\t\t\t\tfor (const id of snapshot.groupById.get(groupId)?.ancestorIds ?? []) {\n\t\t\t\t\tconst group = snapshot.groupById.get(id);\n\t\t\t\t\tif (group) this.graphView.expandedGroupPaths.add(group.pathKey);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst scene = resolveGraphScene(this.graphView, snapshot);\n\t\t\tconst availableIds = new Set([...scene.nodes, ...scene.edges].map((entry) => entry.id));\n\t\t\tif (!(scene.interaction.primaryElementIdsBySelection.get(selectionKey(selection))?.some((id) => availableIds.has(id)))) {\n\t\t\t\tthis.graphView.groupsEnabled = groupsEnabled;\n\t\t\t\tthis.graphView.showResourceDeclarations = showResourceDeclarations;\n\t\t\t\tthis.graphView.expandedGroupPaths.clear();\n\t\t\t\tfor (const path of expanded) this.graphView.expandedGroupPaths.add(path);\n\t\t\t\tthis.workbench.showNavigationIssue(selection.kind === 'culled' ? 'Culled passes are not part of Frame Flow.' : 'This object has no representation in Frame Flow.', selection);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.graphView.revealOnNextRender = { selection, revision: ++this.revealRevision };\n\t\t\tthis.updateGraphControls();\n\t\t}\n\t\tthis.handleSelect(selection);\n\t\tthis.workbench.reveal(selection, tab);\n\t}\n\n\tprivate handleHover(selection: Selection | undefined): void {\n\t\tif (!this.viewModel || sameSelection(this.hovered, selection)) return;\n\t\tthis.hovered = selection;\n\t\tthis.workbench.setHovered(selection);\n\t}\n\n\tprivate updateGraphControls(): void {\n\t\tconst showDeclarations = this.graphView.showResourceDeclarations ?? true;\n\t\tthis.declarationsButton.classList.toggle('active', showDeclarations);\n\t\tthis.declarationsButton.setAttribute('aria-pressed', String(showDeclarations));\n\t\tconst hasGroups = (this.viewModel?.debugGroups.length ?? 0) > 0;\n\t\tthis.groupsButton.disabled = !hasGroups;\n\t\tthis.groupsButton.hidden = !hasGroups;\n\t\tthis.collapseGroupsButton.hidden = !hasGroups;\n\t\tthis.groupsButton.classList.toggle('active', hasGroups && this.graphView.groupsEnabled);\n\t\tthis.groupsButton.setAttribute('aria-pressed', hasGroups && this.graphView.groupsEnabled ? 'true' : 'false');\n\t\tconst hasExpanded = this.viewModel?.debugGroups.some((group) => this.graphView.expandedGroupPaths.has(group.pathKey)) ?? false;\n\t\tthis.collapseGroupsButton.disabled = !hasGroups || !this.graphView.groupsEnabled || !hasExpanded;\n\t}\n\n\tprivate toggleDeclarations(): void {\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.showResourceDeclarations = !(this.graphView.showResourceDeclarations ?? true);\n\t\tthis.graphView.renderer?.cancelReveal?.();\n\t\tthis.graphView.revealOnNextRender = undefined;\n\t\tthis.graphView.anchorElementIdOnNextRender = undefined;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate toggleGroups(): void {\n\t\tif (!this.viewModel?.debugGroups.length) return;\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.groupsEnabled = !this.graphView.groupsEnabled;\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate toggleGroup(pathKey: string): void {\n\t\tthis.handleHover(undefined);\n\t\tif (this.graphView.expandedGroupPaths.has(pathKey)) this.graphView.expandedGroupPaths.delete(pathKey);\n\t\telse this.graphView.expandedGroupPaths.add(pathKey);\n\t\tthis.graphView.anchorElementIdOnNextRender = graphGroupElementId(pathKey);\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate collapseAllGroups(): void {\n\t\tif (this.graphView.expandedGroupPaths.size === 0) return;\n\t\tthis.handleHover(undefined);\n\t\tthis.graphView.expandedGroupPaths.clear();\n\t\tthis.graphView.fitOnNextRender = true;\n\t\tthis.updateGraphControls();\n\t\tthis.workbench.refreshGraphStructure();\n\t}\n\n\tprivate showEmptyState(): void {\n\t\tconst providerAvailable = Boolean(this.captureSnapshotCallback);\n\t\tthis.workbench.showEmptyState(\n\t\t\t'empty',\n\t\t\tproviderAvailable\n\t\t\t\t? 'No capture yet. Use Capture to request the next rendered frame.'\n\t\t\t\t: 'Drop a ZenFG Snapshot here or choose Import.',\n\t\t\tproviderAvailable ? undefined : 'Files are processed locally in your browser.',\n\t\t);\n\t}\n\n\tprivate setDropActive(active: boolean): void {\n\t\tif (this.destroyed) return;\n\t\tthis.dropOverlay.hidden = !active;\n\t\tthis.dom.classList.toggle('drop-active', active);\n\t}\n\n\tprivate clearDropState(): void {\n\t\tthis.dragDepth = 0;\n\t\tthis.dropOverlay.hidden = true;\n\t\tthis.dom.classList.remove('drop-active');\n\t}\n\n\tprivate reportCaptureIssue(message: string): void {\n\t\tthis.statusMessage = message;\n\t\tthis.statusTone = 'error';\n\t\tif (!this.viewModel) this.workbench.showEmptyState('error', message);\n\t\tthis.updateCaptureActions();\n\t}\n}\n\n/**\n * Creates an inspector, appends its root element to `host`, and returns its\n * lifecycle controller.\n *\n * @throws If inspector construction fails; see {@link FrameGraphInspector}.\n */\nexport function mountFrameGraphInspector(host: HTMLElement, options?: FrameGraphInspectorOptions): FrameGraphInspector {\n\tconst inspector = new FrameGraphInspector(options);\n\thost.appendChild(inspector.dom);\n\tinspector.refreshTheme();\n\treturn inspector;\n}\n\nasync function writeTextToClipboard(text: string): Promise<void> {\n\tif (navigator.clipboard?.writeText) {\n\t\tawait navigator.clipboard.writeText(text);\n\t\treturn;\n\t}\n\tconst textArea = document.createElement('textarea');\n\ttextArea.value = text;\n\ttextArea.setAttribute('readonly', 'true');\n\ttextArea.style.position = 'fixed';\n\ttextArea.style.left = '-9999px';\n\ttextArea.style.top = '0';\n\tdocument.body.appendChild(textArea);\n\ttextArea.select();\n\ttry {\n\t\tif (!document.execCommand('copy')) throw new Error('document.execCommand(\"copy\") returned false.');\n\t}\n\tfinally {\n\t\ttextArea.remove();\n\t}\n}\n\nfunction normalizeMaxImportBytes(value: number | undefined): number {\n\treturn normalizeLimit(value, DEFAULT_MAX_IMPORT_BYTES, 'maxImportBytes');\n}\n\nfunction normalizeLimit(value: number | undefined, fallback: number, name: string): number {\n\tif (value === undefined) return fallback;\n\tif (!Number.isSafeInteger(value) || value < 0) {\n\t\tthrow new Error(`${name} must be a non-negative safe integer.`);\n\t}\n\treturn value;\n}\n\nfunction formatImportLimit(bytes: number): string {\n\treturn bytes >= 1024 * 1024 && bytes % (1024 * 1024) === 0\n\t\t? `${bytes / (1024 * 1024)} MiB`\n\t\t: `${bytes} bytes`;\n}\n\nfunction formatIssues(issues: readonly { readonly path: string; readonly message: string }[]): string {\n\treturn issues.map((issue) => `${issue.path || '/'}: ${issue.message}`).join('\\n');\n}\n\nfunction isFileDrag(event: DragEvent): boolean {\n\treturn Array.from(event.dataTransfer?.types ?? []).includes('Files');\n}\n\nlet nextInspectorId = 0;\nfunction createInspectorId(): string {\n\tnextInspectorId += 1;\n\treturn `zenfg-inspector-${nextInspectorId}`;\n}\n"]}
|