@zenfg/inspector 0.1.0-beta.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/GUIDE.md +182 -0
  2. package/README.md +61 -89
  3. package/THEMING.md +124 -0
  4. package/dist/FrameGraphInspector.d.ts +23 -4
  5. package/dist/FrameGraphInspector.d.ts.map +1 -1
  6. package/dist/FrameGraphInspector.js +137 -29
  7. package/dist/FrameGraphInspector.js.map +1 -1
  8. package/dist/capture.d.ts +5 -0
  9. package/dist/capture.d.ts.map +1 -0
  10. package/dist/capture.js +2 -0
  11. package/dist/capture.js.map +1 -0
  12. package/dist/debugCaptureModel.d.ts +19 -0
  13. package/dist/debugCaptureModel.d.ts.map +1 -1
  14. package/dist/debugCaptureModel.js +36 -2
  15. package/dist/debugCaptureModel.js.map +1 -1
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/panelAliasAnalysis.d.ts +1 -0
  20. package/dist/panelAliasAnalysis.d.ts.map +1 -1
  21. package/dist/panelAliasAnalysis.js +23 -54
  22. package/dist/panelAliasAnalysis.js.map +1 -1
  23. package/dist/panelCytoscapeGraphRenderer.d.ts +15 -2
  24. package/dist/panelCytoscapeGraphRenderer.d.ts.map +1 -1
  25. package/dist/panelCytoscapeGraphRenderer.js +145 -23
  26. package/dist/panelCytoscapeGraphRenderer.js.map +1 -1
  27. package/dist/panelDetailLayout.d.ts +27 -0
  28. package/dist/panelDetailLayout.d.ts.map +1 -0
  29. package/dist/panelDetailLayout.js +174 -0
  30. package/dist/panelDetailLayout.js.map +1 -0
  31. package/dist/panelDetailStyles.d.ts +2 -0
  32. package/dist/panelDetailStyles.d.ts.map +1 -0
  33. package/dist/panelDetailStyles.js +57 -0
  34. package/dist/panelDetailStyles.js.map +1 -0
  35. package/dist/panelDiagnosticsView.d.ts +10 -1
  36. package/dist/panelDiagnosticsView.d.ts.map +1 -1
  37. package/dist/panelDiagnosticsView.js +166 -57
  38. package/dist/panelDiagnosticsView.js.map +1 -1
  39. package/dist/panelDomHelpers.d.ts.map +1 -1
  40. package/dist/panelDomHelpers.js +6 -5
  41. package/dist/panelDomHelpers.js.map +1 -1
  42. package/dist/panelGraphLayout.d.ts +3 -2
  43. package/dist/panelGraphLayout.d.ts.map +1 -1
  44. package/dist/panelGraphLayout.js +6 -5
  45. package/dist/panelGraphLayout.js.map +1 -1
  46. package/dist/panelGraphRenderer.d.ts +10 -0
  47. package/dist/panelGraphRenderer.d.ts.map +1 -1
  48. package/dist/panelGraphRenderer.js.map +1 -1
  49. package/dist/panelGraphScene.d.ts +1 -0
  50. package/dist/panelGraphScene.d.ts.map +1 -1
  51. package/dist/panelGraphScene.js +69 -32
  52. package/dist/panelGraphScene.js.map +1 -1
  53. package/dist/panelGraphSearch.d.ts +16 -0
  54. package/dist/panelGraphSearch.d.ts.map +1 -0
  55. package/dist/panelGraphSearch.js +93 -0
  56. package/dist/panelGraphSearch.js.map +1 -0
  57. package/dist/panelGraphView.d.ts +82 -0
  58. package/dist/panelGraphView.d.ts.map +1 -1
  59. package/dist/panelGraphView.js +15 -4
  60. package/dist/panelGraphView.js.map +1 -1
  61. package/dist/panelGraphVisuals.d.ts +14 -6
  62. package/dist/panelGraphVisuals.d.ts.map +1 -1
  63. package/dist/panelGraphVisuals.js +126 -51
  64. package/dist/panelGraphVisuals.js.map +1 -1
  65. package/dist/panelInspectorView.d.ts +8 -0
  66. package/dist/panelInspectorView.d.ts.map +1 -1
  67. package/dist/panelInspectorView.js +242 -48
  68. package/dist/panelInspectorView.js.map +1 -1
  69. package/dist/panelListStyles.d.ts +3 -0
  70. package/dist/panelListStyles.d.ts.map +1 -0
  71. package/dist/panelListStyles.js +155 -0
  72. package/dist/panelListStyles.js.map +1 -0
  73. package/dist/panelMemoryStyles.d.ts +3 -0
  74. package/dist/panelMemoryStyles.d.ts.map +1 -0
  75. package/dist/panelMemoryStyles.js +42 -0
  76. package/dist/panelMemoryStyles.js.map +1 -0
  77. package/dist/panelMemoryView.d.ts +13 -1
  78. package/dist/panelMemoryView.d.ts.map +1 -1
  79. package/dist/panelMemoryView.js +161 -41
  80. package/dist/panelMemoryView.js.map +1 -1
  81. package/dist/panelPassesView.d.ts +15 -0
  82. package/dist/panelPassesView.d.ts.map +1 -1
  83. package/dist/panelPassesView.js +202 -72
  84. package/dist/panelPassesView.js.map +1 -1
  85. package/dist/panelRawView.d.ts +15 -0
  86. package/dist/panelRawView.d.ts.map +1 -0
  87. package/dist/panelRawView.js +105 -0
  88. package/dist/panelRawView.js.map +1 -0
  89. package/dist/panelResourcesView.d.ts +8 -0
  90. package/dist/panelResourcesView.d.ts.map +1 -1
  91. package/dist/panelResourcesView.js +62 -31
  92. package/dist/panelResourcesView.js.map +1 -1
  93. package/dist/panelSelection.d.ts +9 -1
  94. package/dist/panelSelection.d.ts.map +1 -1
  95. package/dist/panelSelection.js +34 -4
  96. package/dist/panelSelection.js.map +1 -1
  97. package/dist/panelTheme.d.ts +13 -0
  98. package/dist/panelTheme.d.ts.map +1 -0
  99. package/dist/panelTheme.js +104 -0
  100. package/dist/panelTheme.js.map +1 -0
  101. package/dist/panelTypes.d.ts +10 -1
  102. package/dist/panelTypes.d.ts.map +1 -1
  103. package/dist/panelTypes.js.map +1 -1
  104. package/dist/panelVisualTheme.d.ts +147 -50
  105. package/dist/panelVisualTheme.d.ts.map +1 -1
  106. package/dist/panelVisualTheme.js +34 -44
  107. package/dist/panelVisualTheme.js.map +1 -1
  108. package/dist/panelWorkbenchHelpers.d.ts +12 -1
  109. package/dist/panelWorkbenchHelpers.d.ts.map +1 -1
  110. package/dist/panelWorkbenchHelpers.js +62 -1
  111. package/dist/panelWorkbenchHelpers.js.map +1 -1
  112. package/dist/panelWorkbenchStyles.d.ts +2 -0
  113. package/dist/panelWorkbenchStyles.d.ts.map +1 -0
  114. package/dist/panelWorkbenchStyles.js +101 -0
  115. package/dist/panelWorkbenchStyles.js.map +1 -0
  116. package/dist/panelWorkbenchView.d.ts +16 -0
  117. package/dist/panelWorkbenchView.d.ts.map +1 -1
  118. package/dist/panelWorkbenchView.js +228 -50
  119. package/dist/panelWorkbenchView.js.map +1 -1
  120. package/dist/query.js.map +1 -1
  121. package/dist/styles.d.ts.map +1 -1
  122. package/dist/styles.js +147 -195
  123. package/dist/styles.js.map +1 -1
  124. package/dist/theme.d.ts +22 -0
  125. package/dist/theme.d.ts.map +1 -0
  126. package/dist/theme.js +10 -0
  127. package/dist/theme.js.map +1 -0
  128. package/dist/themeDefinitions.d.ts +251 -0
  129. package/dist/themeDefinitions.d.ts.map +1 -0
  130. package/dist/themeDefinitions.js +96 -0
  131. package/dist/themeDefinitions.js.map +1 -0
  132. package/dist/themePalette.d.ts +66 -0
  133. package/dist/themePalette.d.ts.map +1 -0
  134. package/dist/themePalette.js +37 -0
  135. package/dist/themePalette.js.map +1 -0
  136. package/dist/themes.css +165 -0
  137. package/package.json +44 -10
  138. package/src/FrameGraphInspector.ts +130 -31
  139. package/src/capture.ts +4 -0
  140. package/src/debugCaptureModel.ts +53 -2
  141. package/src/index.ts +6 -2
  142. package/src/panelAliasAnalysis.ts +24 -70
  143. package/src/panelCytoscapeGraphRenderer.ts +140 -23
  144. package/src/panelDetailLayout.ts +155 -0
  145. package/src/panelDetailStyles.ts +56 -0
  146. package/src/panelDiagnosticsView.ts +166 -85
  147. package/src/panelDomHelpers.ts +4 -5
  148. package/src/panelGraphLayout.ts +6 -5
  149. package/src/panelGraphRenderer.ts +7 -0
  150. package/src/panelGraphScene.ts +68 -30
  151. package/src/panelGraphSearch.ts +96 -0
  152. package/src/panelGraphView.ts +14 -4
  153. package/src/panelGraphVisuals.ts +122 -52
  154. package/src/panelInspectorView.ts +227 -48
  155. package/src/panelListStyles.ts +154 -0
  156. package/src/panelMemoryStyles.ts +41 -0
  157. package/src/panelMemoryView.ts +178 -53
  158. package/src/panelPassesView.ts +190 -137
  159. package/src/panelRawView.ts +99 -0
  160. package/src/panelResourcesView.ts +69 -56
  161. package/src/panelSelection.ts +37 -5
  162. package/src/panelTheme.ts +85 -0
  163. package/src/panelTypes.ts +7 -1
  164. package/src/panelVisualTheme.ts +38 -49
  165. package/src/panelWorkbenchHelpers.ts +60 -2
  166. package/src/panelWorkbenchStyles.ts +100 -0
  167. package/src/panelWorkbenchView.ts +201 -52
  168. package/src/query.ts +11 -11
  169. package/src/styles.ts +148 -195
  170. package/src/theme.ts +24 -0
  171. package/src/themeDefinitions.ts +103 -0
  172. package/src/themePalette.ts +44 -0
@@ -1 +1 @@
1
- {"version":3,"file":"panelDiagnosticsView.d.ts","sourceRoot":"","sources":["../src/panelDiagnosticsView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAON,KAAK,kBAAkB,EAEvB,MAAM,4BAA4B,CAAC;AAEpC,qBAAa,eAAe;IAQf,OAAO,CAAC,QAAQ,CAAC,SAAS;IAPtC,QAAQ,CAAC,IAAI,cAAqC;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,QAAQ,CAAwB;gBAEX,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM;IAU5E,WAAW,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI;IAKrD,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI;IAKnD,OAAO,CAAC,MAAM;IAad,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,WAAW;IAmBnB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,YAAY;CA2BpB"}
1
+ {"version":3,"file":"panelDiagnosticsView.d.ts","sourceRoot":"","sources":["../src/panelDiagnosticsView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAGvE,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAE4B,KAAK,kBAAkB,EACzD,MAAM,4BAA4B,CAAC;AAIpC,qBAAa,eAAe;IAcf,OAAO,CAAC,QAAQ,CAAC,SAAS;IAbtC,QAAQ,CAAC,IAAI,cAAqC;IAClD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IACnD,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAM;gBAES,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM;IAyB5E,WAAW,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI;IAKrD,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI;IAKnD,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAYlC,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,cAAc;IAmDtB,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,cAAc;CA0BtB"}
@@ -1,22 +1,45 @@
1
- import { createCell, labelNode, labelResource } from "./panelDomHelpers.js";
2
- import { createEmptyTableRow, createKindCell, createRelationButton, createSelectionCell, createTableScroller, registerSelectable, updateSelectedRows, } from "./panelWorkbenchHelpers.js";
1
+ import { labelNode, labelResource } from "./panelDomHelpers.js";
2
+ import { resolveNodeSelection } from "./panelSelection.js";
3
+ import { createFilterSelect, createRelationButton, createSearchInput, createViewToolbar, registerSelectable, selectionKey, updateSelectedRows, } from "./panelWorkbenchHelpers.js";
4
+ const severityOrder = { error: 0, warning: 1, info: 2 };
3
5
  export class DiagnosticsView {
4
6
  callbacks;
5
7
  root = document.createElement('section');
6
8
  scroller = document.createElement('div');
7
9
  content = document.createElement('div');
8
10
  rows = new Map();
11
+ openSections = new Set();
12
+ count = document.createElement('span');
13
+ searchInput;
14
+ severitySelect;
9
15
  snapshot;
10
16
  selected;
17
+ severity = 'all';
18
+ search = '';
11
19
  constructor(callbacks, idPrefix) {
12
20
  this.callbacks = callbacks;
13
21
  this.root.className = 'zenfg-inspector-view zenfg-inspector-diagnostics-view';
14
22
  this.root.id = `${idPrefix}-view-diagnostics`;
15
23
  this.root.setAttribute('role', 'tabpanel');
24
+ const toolbar = createViewToolbar('Diagnostic filters');
25
+ this.searchInput = createSearchInput('Search diagnostic code or message', '', (value) => {
26
+ this.search = value.trim().toLocaleLowerCase();
27
+ this.render();
28
+ });
29
+ this.severitySelect = createFilterSelect('Diagnostic severity', this.severity, [
30
+ ['all', 'All severities'], ['error', 'Error'], ['warning', 'Warning'], ['info', 'Info'],
31
+ ], (value) => { this.severity = value; this.render(); });
32
+ const clear = document.createElement('button');
33
+ clear.type = 'button';
34
+ clear.textContent = 'Clear filters';
35
+ clear.addEventListener('click', () => { this.clearFilters(); this.render(); });
36
+ this.count.className = 'zenfg-inspector-result-count';
37
+ this.count.setAttribute('role', 'status');
38
+ toolbar.append(this.searchInput, this.severitySelect, clear, this.count);
16
39
  this.scroller.className = 'zenfg-inspector-diagnostics-scroller';
17
- this.content.className = 'zenfg-inspector-diagnostics-grid';
40
+ this.content.className = 'zenfg-inspector-diagnostics-sections';
18
41
  this.scroller.appendChild(this.content);
19
- this.root.appendChild(this.scroller);
42
+ this.root.append(toolbar, this.scroller);
20
43
  }
21
44
  setSnapshot(snapshot) {
22
45
  this.snapshot = snapshot;
@@ -26,18 +49,105 @@ export class DiagnosticsView {
26
49
  this.selected = selected;
27
50
  updateSelectedRows(this.rows, selected);
28
51
  }
52
+ reveal(selection) {
53
+ this.clearFilters();
54
+ if (selection.kind === 'root')
55
+ this.openSections.add('roots');
56
+ if (selection.kind === 'culled')
57
+ this.openSections.add('culled');
58
+ if (selection.kind === 'segment') {
59
+ this.openSections.add('segments');
60
+ this.openSections.add(`segment:${selection.index}`);
61
+ }
62
+ this.render();
63
+ this.rows.get(selectionKey(selection))?.[0]?.scrollIntoView?.({ block: 'nearest' });
64
+ }
65
+ clearFilters() {
66
+ this.search = '';
67
+ this.severity = 'all';
68
+ this.searchInput.value = '';
69
+ this.severitySelect.value = 'all';
70
+ }
29
71
  render() {
30
72
  const snapshot = this.snapshot;
31
73
  if (!snapshot)
32
74
  return;
33
75
  this.rows.clear();
34
- this.content.replaceChildren(this.createRoots(snapshot), this.createCulled(snapshot), this.createSegments(snapshot), this.createTiming(snapshot));
76
+ this.content.replaceChildren(this.createMessages(snapshot), this.createRoots(snapshot), this.createCulled(snapshot), this.createSegments(snapshot));
35
77
  updateSelectedRows(this.rows, this.selected);
36
78
  }
37
- createSection(title, description) {
79
+ createMessages(snapshot) {
38
80
  const section = document.createElement('section');
39
- section.className = 'zenfg-inspector-diagnostic-card';
81
+ section.className = 'zenfg-inspector-diagnostic-messages';
40
82
  const heading = document.createElement('h2');
83
+ heading.textContent = 'Diagnostics';
84
+ const summary = document.createElement('p');
85
+ const all = snapshot.protocol.diagnostics;
86
+ const errors = all.filter((entry) => entry.severity === 'error').length;
87
+ const warnings = all.filter((entry) => entry.severity === 'warning').length;
88
+ const infos = all.length - errors - warnings;
89
+ summary.textContent = `${errors} errors · ${warnings} warnings · ${infos} info`;
90
+ section.append(heading, summary);
91
+ // Sort a copy. Stable sort preserves capture order within each severity, including repeated codes.
92
+ const messages = all.filter((entry) => (this.severity === 'all' || entry.severity === this.severity)
93
+ && (!this.search || `${entry.code} ${entry.message}`.toLocaleLowerCase().includes(this.search)))
94
+ .sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
95
+ this.count.textContent = `${messages.length} / ${all.length} diagnostics`;
96
+ for (const diagnostic of messages) {
97
+ const article = document.createElement('article');
98
+ article.className = 'zenfg-inspector-diagnostic-message';
99
+ article.dataset.severity = diagnostic.severity;
100
+ const title = document.createElement('h3');
101
+ const severity = document.createElement('span');
102
+ severity.className = 'zenfg-inspector-diagnostic-severity';
103
+ severity.textContent = diagnostic.severity;
104
+ const code = document.createElement('code');
105
+ code.textContent = diagnostic.code;
106
+ title.append(severity, code);
107
+ const message = document.createElement('p');
108
+ message.textContent = diagnostic.message;
109
+ article.append(title, message);
110
+ if (diagnostic.nodeId !== undefined) {
111
+ const selection = resolveNodeSelection(snapshot, diagnostic.nodeId);
112
+ const node = snapshot.canonicalNodeById.get(diagnostic.nodeId);
113
+ if (selection && node)
114
+ article.appendChild(this.createObjectLink(labelNode(node), selection, 'passes'));
115
+ }
116
+ if (diagnostic.resourceId !== undefined) {
117
+ const resource = snapshot.resourceById.get(diagnostic.resourceId);
118
+ if (resource)
119
+ article.appendChild(this.createObjectLink(labelResource(resource), { kind: 'resource', id: resource.id }, 'resources'));
120
+ }
121
+ section.appendChild(article);
122
+ }
123
+ if (messages.length === 0) {
124
+ const empty = document.createElement('p');
125
+ empty.className = 'zenfg-inspector-muted';
126
+ empty.textContent = all.length === 0 ? 'No diagnostic messages in this snapshot.' : 'No diagnostics match the current filters.';
127
+ section.appendChild(empty);
128
+ }
129
+ return section;
130
+ }
131
+ createObjectLink(label, selection, tab) {
132
+ const links = document.createElement('span');
133
+ links.className = 'zenfg-inspector-diagnostic-links';
134
+ const select = createRelationButton(label, selection, this.callbacks.onSelect);
135
+ registerSelectable(this.rows, select, selection, this.callbacks);
136
+ const reveal = document.createElement('button');
137
+ reveal.type = 'button';
138
+ reveal.className = 'zenfg-inspector-relation-button zenfg-inspector-diagnostic-reveal';
139
+ reveal.textContent = `Show in ${tab === 'passes' ? 'Passes' : 'Resources'}`;
140
+ reveal.setAttribute('aria-label', `${reveal.textContent}: ${label}`);
141
+ reveal.addEventListener('click', () => this.callbacks.onReveal?.(selection, tab));
142
+ links.append(select, reveal);
143
+ return links;
144
+ }
145
+ createSection(key, title, description) {
146
+ const section = document.createElement('details');
147
+ section.className = 'zenfg-inspector-diagnostic-section';
148
+ section.dataset.section = key;
149
+ section.open = this.openSections.has(key);
150
+ const heading = document.createElement('summary');
41
151
  heading.textContent = title;
42
152
  section.appendChild(heading);
43
153
  if (description) {
@@ -45,78 +155,77 @@ export class DiagnosticsView {
45
155
  text.textContent = description;
46
156
  section.appendChild(text);
47
157
  }
158
+ section.addEventListener('toggle', () => {
159
+ if (section.open)
160
+ this.openSections.add(key);
161
+ else
162
+ this.openSections.delete(key);
163
+ });
48
164
  return section;
49
165
  }
50
166
  createRoots(snapshot) {
51
- const section = this.createSection('Retention roots', 'Roots explain why graph work survived dead-node elimination.');
167
+ const section = this.createSection('roots', `Retention roots (${snapshot.roots.length})`, 'Roots explain why graph work survived dead-node elimination.');
52
168
  const list = document.createElement('div');
53
169
  list.className = 'zenfg-inspector-diagnostic-list';
54
- snapshot.roots.forEach((root) => {
170
+ for (const root of snapshot.roots) {
55
171
  const selection = { kind: 'root', key: root.key };
56
- const button = createRelationButton(`${root.reason} · ${root.resource ? labelResource(root.resource) : root.nodeId === undefined ? '-' : `node-${root.nodeId}`}`, selection, this.callbacks.onSelect);
172
+ const node = root.nodeId === undefined ? undefined : snapshot.canonicalNodeById.get(root.nodeId);
173
+ const label = root.resource ? labelResource(root.resource) : node ? labelNode(node) : root.nodeId ?? 'Unknown';
174
+ const button = createRelationButton(`${root.reason} · ${label}`, selection, this.callbacks.onSelect);
57
175
  registerSelectable(this.rows, button, selection, this.callbacks);
58
176
  list.appendChild(button);
59
- });
177
+ }
60
178
  if (snapshot.roots.length === 0)
61
179
  list.textContent = 'No retention roots.';
62
180
  section.appendChild(list);
63
181
  return section;
64
182
  }
65
183
  createCulled(snapshot) {
66
- const section = this.createSection('Culled nodes', 'Recorded nodes that were not reachable from a retention root.');
67
- const table = createTableScroller([{ label: 'Node' }, { label: 'Kind', column: 'kind' }, { label: 'Reason' }]);
68
- for (const [index, entry] of snapshot.culledNodes.entries()) {
69
- const selection = { kind: 'culled', index };
70
- const row = document.createElement('tr');
71
- registerSelectable(this.rows, row, selection, this.callbacks);
72
- row.append(createSelectionCell(labelNode(entry.node), selection, this.callbacks), createKindCell(entry.node.kind), createCell(entry.reason));
73
- table.body.appendChild(row);
184
+ const section = this.createSection('culled', `Culled passes (${snapshot.culledNodes.length})`, 'Recorded passes removed during compilation. Inspect their reasons and accesses in Passes.');
185
+ const reasons = new Map();
186
+ for (const entry of snapshot.culledNodes)
187
+ reasons.set(entry.reason, (reasons.get(entry.reason) ?? 0) + 1);
188
+ const list = document.createElement('ul');
189
+ for (const [reason, count] of reasons) {
190
+ const item = document.createElement('li');
191
+ item.textContent = `${reason}: ${count}`;
192
+ list.appendChild(item);
193
+ }
194
+ section.appendChild(list);
195
+ if (snapshot.culledNodes.length > 0) {
196
+ const button = document.createElement('button');
197
+ button.type = 'button';
198
+ button.className = 'zenfg-inspector-relation-button';
199
+ button.textContent = 'Show culled passes';
200
+ button.addEventListener('click', () => this.callbacks.onNavigate?.('passes', 'culled'));
201
+ section.appendChild(button);
74
202
  }
75
- if (snapshot.culledNodes.length === 0)
76
- table.body.appendChild(createEmptyTableRow(3, 'No culled nodes.'));
77
- section.appendChild(table.scroller);
78
203
  return section;
79
204
  }
80
205
  createSegments(snapshot) {
81
- const section = this.createSection('Execution segments', 'An opaque interval is a graph boundary around external work; it is not a count or timing of third-party GPU submissions.');
82
- const table = createTableScroller([{ label: '#', column: 'numeric' }, { label: 'Kind', column: 'kind' }, { label: 'Nodes' }]);
206
+ const section = this.createSection('segments', `Execution segments (${snapshot.executionSegments.length})`, 'An opaque interval marks external work. Its GPU submissions and duration are not measured here.');
83
207
  for (const segment of snapshot.executionSegments) {
84
208
  const selection = { kind: 'segment', index: segment.index };
85
- const row = document.createElement('tr');
86
- registerSelectable(this.rows, row, selection, this.callbacks);
87
- const labels = segment.nodeIds.map((id) => snapshot.nodeById.get(id))
88
- .filter((node) => node !== undefined)
89
- .map((node) => labelNode(node));
90
- row.append(createSelectionCell(String(segment.index), selection, this.callbacks, 'numeric'), createKindCell(segment.kind, segment.kind === 'frame-graph' ? 'FrameGraph command segment' : 'Opaque interval'), createCell(labels.join(', ') || '-'));
91
- table.body.appendChild(row);
92
- }
93
- if (snapshot.executionSegments.length === 0)
94
- table.body.appendChild(createEmptyTableRow(3, 'No execution segments.'));
95
- section.appendChild(table.scroller);
96
- return section;
97
- }
98
- createTiming(snapshot) {
99
- const metrics = snapshot.metrics;
100
- const coverage = metrics.timingEligibleNodeCount === 0
101
- ? 'No eligible render or compute passes'
102
- : `${metrics.timedNodeCount}/${metrics.timingEligibleNodeCount} eligible passes timed (${((metrics.timedNodeCount / metrics.timingEligibleNodeCount) * 100).toFixed(0)}%)`;
103
- const section = this.createSection('GPU timing coverage', coverage);
104
- if (snapshot.profiling.status === 'unavailable') {
105
- const status = document.createElement('p');
106
- status.textContent = `Timing unavailable: ${snapshot.profiling.reason}.`;
107
- section.appendChild(status);
209
+ const members = this.createSection(`segment:${segment.index}`, `${segment.index} · ${segment.kind === 'frame-graph' ? 'FrameGraph command segment' : 'Opaque interval'} · ${segment.nodeIds.length} passes`);
210
+ const button = createRelationButton('Inspect segment', selection, this.callbacks.onSelect);
211
+ registerSelectable(this.rows, button, selection, this.callbacks);
212
+ members.appendChild(button);
213
+ const list = document.createElement('div');
214
+ list.className = 'zenfg-inspector-diagnostic-list';
215
+ for (const id of segment.nodeIds) {
216
+ const node = snapshot.canonicalNodeById.get(id);
217
+ const nodeSelection = resolveNodeSelection(snapshot, id);
218
+ if (node && nodeSelection)
219
+ list.appendChild(this.createObjectLink(labelNode(node), nodeSelection, 'passes'));
220
+ }
221
+ members.appendChild(list);
222
+ section.appendChild(members);
108
223
  }
109
- const table = createTableScroller([{ label: 'Pass' }, { label: 'Status', column: 'kind' }, { label: 'GPU (ms)', column: 'numeric' }]);
110
- for (const node of snapshot.nodes.filter((candidate) => candidate.kind === 'render' || candidate.kind === 'compute')) {
111
- const selection = { kind: 'node', id: node.id };
112
- const row = document.createElement('tr');
113
- registerSelectable(this.rows, row, selection, this.callbacks);
114
- row.append(createSelectionCell(labelNode(node), selection, this.callbacks), createKindCell(node.gpuDurationMicros === undefined ? 'not-timed' : 'timed', node.gpuDurationMicros === undefined ? 'Not timed' : 'Timed'), createCell(node.gpuDurationMicros === undefined ? '-' : (node.gpuDurationMicros / 1000).toFixed(3), { column: 'numeric' }));
115
- table.body.appendChild(row);
224
+ if (snapshot.executionSegments.length === 0) {
225
+ const empty = document.createElement('p');
226
+ empty.textContent = 'No execution segments.';
227
+ section.appendChild(empty);
116
228
  }
117
- if (table.body.childElementCount === 0)
118
- table.body.appendChild(createEmptyTableRow(3, 'No timing-eligible passes.'));
119
- section.appendChild(table.scroller);
120
229
  return section;
121
230
  }
122
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"panelDiagnosticsView.js","sourceRoot":"","sources":["../src/panelDiagnosticsView.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport { createCell, labelNode, labelResource } from './panelDomHelpers.ts';\nimport type { Selection } from './panelTypes.ts';\nimport {\n\tcreateEmptyTableRow,\n\tcreateKindCell,\n\tcreateRelationButton,\n\tcreateSelectionCell,\n\tcreateTableScroller,\n\tregisterSelectable,\n\ttype WorkbenchCallbacks,\n\tupdateSelectedRows,\n} from './panelWorkbenchHelpers.ts';\n\nexport class DiagnosticsView {\n\treadonly root = document.createElement('section');\n\tprivate readonly scroller = document.createElement('div');\n\tprivate readonly content = document.createElement('div');\n\tprivate readonly rows = new Map<string, HTMLElement[]>();\n\tprivate snapshot: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\n\tconstructor(private readonly callbacks: WorkbenchCallbacks, idPrefix: string) {\n\t\tthis.root.className = 'zenfg-inspector-view zenfg-inspector-diagnostics-view';\n\t\tthis.root.id = `${idPrefix}-view-diagnostics`;\n\t\tthis.root.setAttribute('role', 'tabpanel');\n\t\tthis.scroller.className = 'zenfg-inspector-diagnostics-scroller';\n\t\tthis.content.className = 'zenfg-inspector-diagnostics-grid';\n\t\tthis.scroller.appendChild(this.content);\n\t\tthis.root.appendChild(this.scroller);\n\t}\n\n\tsetSnapshot(snapshot: FrameGraphDebugViewModel): void {\n\t\tthis.snapshot = snapshot;\n\t\tthis.render();\n\t}\n\n\tsetSelection(selected: Selection | undefined): void {\n\t\tthis.selected = selected;\n\t\tupdateSelectedRows(this.rows, selected);\n\t}\n\n\tprivate render(): void {\n\t\tconst snapshot = this.snapshot;\n\t\tif (!snapshot) return;\n\t\tthis.rows.clear();\n\t\tthis.content.replaceChildren(\n\t\t\tthis.createRoots(snapshot),\n\t\t\tthis.createCulled(snapshot),\n\t\t\tthis.createSegments(snapshot),\n\t\t\tthis.createTiming(snapshot),\n\t\t);\n\t\tupdateSelectedRows(this.rows, this.selected);\n\t}\n\n\tprivate createSection(title: string, description?: string): HTMLElement {\n\t\tconst section = document.createElement('section');\n\t\tsection.className = 'zenfg-inspector-diagnostic-card';\n\t\tconst heading = document.createElement('h2');\n\t\theading.textContent = title;\n\t\tsection.appendChild(heading);\n\t\tif (description) {\n\t\t\tconst text = document.createElement('p');\n\t\t\ttext.textContent = description;\n\t\t\tsection.appendChild(text);\n\t\t}\n\t\treturn section;\n\t}\n\n\tprivate createRoots(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = this.createSection('Retention roots', 'Roots explain why graph work survived dead-node elimination.');\n\t\tconst list = document.createElement('div');\n\t\tlist.className = 'zenfg-inspector-diagnostic-list';\n\t\tsnapshot.roots.forEach((root) => {\n\t\t\tconst selection: Selection = { kind: 'root', key: root.key };\n\t\t\tconst button = createRelationButton(\n\t\t\t\t`${root.reason} · ${root.resource ? labelResource(root.resource) : root.nodeId === undefined ? '-' : `node-${root.nodeId}`}`,\n\t\t\t\tselection,\n\t\t\t\tthis.callbacks.onSelect,\n\t\t\t);\n\t\t\tregisterSelectable(this.rows, button, selection, this.callbacks);\n\t\t\tlist.appendChild(button);\n\t\t});\n\t\tif (snapshot.roots.length === 0) list.textContent = 'No retention roots.';\n\t\tsection.appendChild(list);\n\t\treturn section;\n\t}\n\n\tprivate createCulled(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = this.createSection('Culled nodes', 'Recorded nodes that were not reachable from a retention root.');\n\t\tconst table = createTableScroller([{ label: 'Node' }, { label: 'Kind', column: 'kind' }, { label: 'Reason' }]);\n\t\tfor (const [index, entry] of snapshot.culledNodes.entries()) {\n\t\t\tconst selection: Selection = { kind: 'culled', index };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\trow.append(\n\t\t\t\tcreateSelectionCell(labelNode(entry.node), selection, this.callbacks),\n\t\t\t\tcreateKindCell(entry.node.kind),\n\t\t\t\tcreateCell(entry.reason),\n\t\t\t);\n\t\t\ttable.body.appendChild(row);\n\t\t}\n\t\tif (snapshot.culledNodes.length === 0) table.body.appendChild(createEmptyTableRow(3, 'No culled nodes.'));\n\t\tsection.appendChild(table.scroller);\n\t\treturn section;\n\t}\n\n\tprivate createSegments(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = this.createSection(\n\t\t\t'Execution segments',\n\t\t\t'An opaque interval is a graph boundary around external work; it is not a count or timing of third-party GPU submissions.',\n\t\t);\n\t\tconst table = createTableScroller([{ label: '#', column: 'numeric' }, { label: 'Kind', column: 'kind' }, { label: 'Nodes' }]);\n\t\tfor (const segment of snapshot.executionSegments) {\n\t\t\tconst selection: Selection = { kind: 'segment', index: segment.index };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst labels = segment.nodeIds.map((id) => snapshot.nodeById.get(id))\n\t\t\t\t.filter((node) => node !== undefined)\n\t\t\t\t.map((node) => labelNode(node));\n\t\t\trow.append(\n\t\t\t\tcreateSelectionCell(String(segment.index), selection, this.callbacks, 'numeric'),\n\t\t\t\tcreateKindCell(segment.kind, segment.kind === 'frame-graph' ? 'FrameGraph command segment' : 'Opaque interval'),\n\t\t\t\tcreateCell(labels.join(', ') || '-'),\n\t\t\t);\n\t\t\ttable.body.appendChild(row);\n\t\t}\n\t\tif (snapshot.executionSegments.length === 0) table.body.appendChild(createEmptyTableRow(3, 'No execution segments.'));\n\t\tsection.appendChild(table.scroller);\n\t\treturn section;\n\t}\n\n\tprivate createTiming(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst metrics = snapshot.metrics;\n\t\tconst coverage = metrics.timingEligibleNodeCount === 0\n\t\t\t? 'No eligible render or compute passes'\n\t\t\t: `${metrics.timedNodeCount}/${metrics.timingEligibleNodeCount} eligible passes timed (${((metrics.timedNodeCount / metrics.timingEligibleNodeCount) * 100).toFixed(0)}%)`;\n\t\tconst section = this.createSection('GPU timing coverage', coverage);\n\t\tif (snapshot.profiling.status === 'unavailable') {\n\t\t\tconst status = document.createElement('p');\n\t\t\tstatus.textContent = `Timing unavailable: ${snapshot.profiling.reason}.`;\n\t\t\tsection.appendChild(status);\n\t\t}\n\t\tconst table = createTableScroller([{ label: 'Pass' }, { label: 'Status', column: 'kind' }, { label: 'GPU (ms)', column: 'numeric' }]);\n\t\tfor (const node of snapshot.nodes.filter((candidate) => candidate.kind === 'render' || candidate.kind === 'compute')) {\n\t\t\tconst selection: Selection = { kind: 'node', id: node.id };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\trow.append(\n\t\t\t\tcreateSelectionCell(labelNode(node), selection, this.callbacks),\n\t\t\t\tcreateKindCell(node.gpuDurationMicros === undefined ? 'not-timed' : 'timed', node.gpuDurationMicros === undefined ? 'Not timed' : 'Timed'),\n\t\t\t\tcreateCell(node.gpuDurationMicros === undefined ? '-' : (node.gpuDurationMicros / 1000).toFixed(3), { column: 'numeric' }),\n\t\t\t);\n\t\t\ttable.body.appendChild(row);\n\t\t}\n\t\tif (table.body.childElementCount === 0) table.body.appendChild(createEmptyTableRow(3, 'No timing-eligible passes.'));\n\t\tsection.appendChild(table.scroller);\n\t\treturn section;\n\t}\n}\n"]}
1
+ {"version":3,"file":"panelDiagnosticsView.js","sourceRoot":"","sources":["../src/panelDiagnosticsView.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport { labelNode, labelResource } from './panelDomHelpers.ts';\nimport { resolveNodeSelection } from './panelSelection.ts';\nimport type { Selection, WorkbenchTab } from './panelTypes.ts';\nimport {\n\tcreateFilterSelect, createRelationButton, createSearchInput, createViewToolbar,\n\tregisterSelectable, selectionKey, type WorkbenchCallbacks, updateSelectedRows,\n} from './panelWorkbenchHelpers.ts';\n\nconst severityOrder = { error: 0, warning: 1, info: 2 } as const;\n\nexport class DiagnosticsView {\n\treadonly root = document.createElement('section');\n\tprivate readonly scroller = document.createElement('div');\n\tprivate readonly content = document.createElement('div');\n\tprivate readonly rows = new Map<string, HTMLElement[]>();\n\tprivate readonly openSections = new Set<string>();\n\tprivate readonly count = document.createElement('span');\n\tprivate readonly searchInput: HTMLInputElement;\n\tprivate readonly severitySelect: HTMLSelectElement;\n\tprivate snapshot: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate severity = 'all';\n\tprivate search = '';\n\n\tconstructor(private readonly callbacks: WorkbenchCallbacks, idPrefix: string) {\n\t\tthis.root.className = 'zenfg-inspector-view zenfg-inspector-diagnostics-view';\n\t\tthis.root.id = `${idPrefix}-view-diagnostics`;\n\t\tthis.root.setAttribute('role', 'tabpanel');\n\t\tconst toolbar = createViewToolbar('Diagnostic filters');\n\t\tthis.searchInput = createSearchInput('Search diagnostic code or message', '', (value) => {\n\t\t\tthis.search = value.trim().toLocaleLowerCase();\n\t\t\tthis.render();\n\t\t});\n\t\tthis.severitySelect = createFilterSelect('Diagnostic severity', this.severity, [\n\t\t\t['all', 'All severities'], ['error', 'Error'], ['warning', 'Warning'], ['info', 'Info'],\n\t\t], (value) => { this.severity = value; this.render(); });\n\t\tconst clear = document.createElement('button');\n\t\tclear.type = 'button';\n\t\tclear.textContent = 'Clear filters';\n\t\tclear.addEventListener('click', () => { this.clearFilters(); this.render(); });\n\t\tthis.count.className = 'zenfg-inspector-result-count';\n\t\tthis.count.setAttribute('role', 'status');\n\t\ttoolbar.append(this.searchInput, this.severitySelect, clear, this.count);\n\t\tthis.scroller.className = 'zenfg-inspector-diagnostics-scroller';\n\t\tthis.content.className = 'zenfg-inspector-diagnostics-sections';\n\t\tthis.scroller.appendChild(this.content);\n\t\tthis.root.append(toolbar, this.scroller);\n\t}\n\n\tsetSnapshot(snapshot: FrameGraphDebugViewModel): void {\n\t\tthis.snapshot = snapshot;\n\t\tthis.render();\n\t}\n\n\tsetSelection(selected: Selection | undefined): void {\n\t\tthis.selected = selected;\n\t\tupdateSelectedRows(this.rows, selected);\n\t}\n\n\treveal(selection: Selection): void {\n\t\tthis.clearFilters();\n\t\tif (selection.kind === 'root') this.openSections.add('roots');\n\t\tif (selection.kind === 'culled') this.openSections.add('culled');\n\t\tif (selection.kind === 'segment') {\n\t\t\tthis.openSections.add('segments');\n\t\t\tthis.openSections.add(`segment:${selection.index}`);\n\t\t}\n\t\tthis.render();\n\t\tthis.rows.get(selectionKey(selection))?.[0]?.scrollIntoView?.({ block: 'nearest' });\n\t}\n\n\tprivate clearFilters(): void {\n\t\tthis.search = '';\n\t\tthis.severity = 'all';\n\t\tthis.searchInput.value = '';\n\t\tthis.severitySelect.value = 'all';\n\t}\n\n\tprivate render(): void {\n\t\tconst snapshot = this.snapshot;\n\t\tif (!snapshot) return;\n\t\tthis.rows.clear();\n\t\tthis.content.replaceChildren(\n\t\t\tthis.createMessages(snapshot), this.createRoots(snapshot), this.createCulled(snapshot), this.createSegments(snapshot),\n\t\t);\n\t\tupdateSelectedRows(this.rows, this.selected);\n\t}\n\n\tprivate createMessages(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = document.createElement('section');\n\t\tsection.className = 'zenfg-inspector-diagnostic-messages';\n\t\tconst heading = document.createElement('h2');\n\t\theading.textContent = 'Diagnostics';\n\t\tconst summary = document.createElement('p');\n\t\tconst all = snapshot.protocol.diagnostics;\n\t\tconst errors = all.filter((entry) => entry.severity === 'error').length;\n\t\tconst warnings = all.filter((entry) => entry.severity === 'warning').length;\n\t\tconst infos = all.length - errors - warnings;\n\t\tsummary.textContent = `${errors} errors · ${warnings} warnings · ${infos} info`;\n\t\tsection.append(heading, summary);\n\t\t// Sort a copy. Stable sort preserves capture order within each severity, including repeated codes.\n\t\tconst messages = all.filter((entry) => (this.severity === 'all' || entry.severity === this.severity)\n\t\t\t&& (!this.search || `${entry.code} ${entry.message}`.toLocaleLowerCase().includes(this.search)))\n\t\t\t.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);\n\t\tthis.count.textContent = `${messages.length} / ${all.length} diagnostics`;\n\t\tfor (const diagnostic of messages) {\n\t\t\tconst article = document.createElement('article');\n\t\t\tarticle.className = 'zenfg-inspector-diagnostic-message';\n\t\t\tarticle.dataset.severity = diagnostic.severity;\n\t\t\tconst title = document.createElement('h3');\n\t\t\tconst severity = document.createElement('span');\n\t\t\tseverity.className = 'zenfg-inspector-diagnostic-severity';\n\t\t\tseverity.textContent = diagnostic.severity;\n\t\t\tconst code = document.createElement('code');\n\t\t\tcode.textContent = diagnostic.code;\n\t\t\ttitle.append(severity, code);\n\t\t\tconst message = document.createElement('p');\n\t\t\tmessage.textContent = diagnostic.message;\n\t\t\tarticle.append(title, message);\n\t\t\tif (diagnostic.nodeId !== undefined) {\n\t\t\t\tconst selection = resolveNodeSelection(snapshot, diagnostic.nodeId);\n\t\t\t\tconst node = snapshot.canonicalNodeById.get(diagnostic.nodeId);\n\t\t\t\tif (selection && node) article.appendChild(this.createObjectLink(labelNode(node), selection, 'passes'));\n\t\t\t}\n\t\t\tif (diagnostic.resourceId !== undefined) {\n\t\t\t\tconst resource = snapshot.resourceById.get(diagnostic.resourceId);\n\t\t\t\tif (resource) article.appendChild(this.createObjectLink(labelResource(resource), { kind: 'resource', id: resource.id }, 'resources'));\n\t\t\t}\n\t\t\tsection.appendChild(article);\n\t\t}\n\t\tif (messages.length === 0) {\n\t\t\tconst empty = document.createElement('p');\n\t\t\tempty.className = 'zenfg-inspector-muted';\n\t\t\tempty.textContent = all.length === 0 ? 'No diagnostic messages in this snapshot.' : 'No diagnostics match the current filters.';\n\t\t\tsection.appendChild(empty);\n\t\t}\n\t\treturn section;\n\t}\n\n\tprivate createObjectLink(label: string, selection: Selection, tab: WorkbenchTab): HTMLElement {\n\t\tconst links = document.createElement('span');\n\t\tlinks.className = 'zenfg-inspector-diagnostic-links';\n\t\tconst select = createRelationButton(label, selection, this.callbacks.onSelect);\n\t\tregisterSelectable(this.rows, select, selection, this.callbacks);\n\t\tconst reveal = document.createElement('button');\n\t\treveal.type = 'button';\n\t\treveal.className = 'zenfg-inspector-relation-button zenfg-inspector-diagnostic-reveal';\n\t\treveal.textContent = `Show in ${tab === 'passes' ? 'Passes' : 'Resources'}`;\n\t\treveal.setAttribute('aria-label', `${reveal.textContent}: ${label}`);\n\t\treveal.addEventListener('click', () => this.callbacks.onReveal?.(selection, tab));\n\t\tlinks.append(select, reveal);\n\t\treturn links;\n\t}\n\n\tprivate createSection(key: string, title: string, description?: string): HTMLDetailsElement {\n\t\tconst section = document.createElement('details');\n\t\tsection.className = 'zenfg-inspector-diagnostic-section';\n\t\tsection.dataset.section = key;\n\t\tsection.open = this.openSections.has(key);\n\t\tconst heading = document.createElement('summary');\n\t\theading.textContent = title;\n\t\tsection.appendChild(heading);\n\t\tif (description) {\n\t\t\tconst text = document.createElement('p');\n\t\t\ttext.textContent = description;\n\t\t\tsection.appendChild(text);\n\t\t}\n\t\tsection.addEventListener('toggle', () => {\n\t\t\tif (section.open) this.openSections.add(key);\n\t\t\telse this.openSections.delete(key);\n\t\t});\n\t\treturn section;\n\t}\n\n\tprivate createRoots(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = this.createSection('roots', `Retention roots (${snapshot.roots.length})`, 'Roots explain why graph work survived dead-node elimination.');\n\t\tconst list = document.createElement('div');\n\t\tlist.className = 'zenfg-inspector-diagnostic-list';\n\t\tfor (const root of snapshot.roots) {\n\t\t\tconst selection: Selection = { kind: 'root', key: root.key };\n\t\t\tconst node = root.nodeId === undefined ? undefined : snapshot.canonicalNodeById.get(root.nodeId);\n\t\t\tconst label = root.resource ? labelResource(root.resource) : node ? labelNode(node) : root.nodeId ?? 'Unknown';\n\t\t\tconst button = createRelationButton(`${root.reason} · ${label}`, selection, this.callbacks.onSelect);\n\t\t\tregisterSelectable(this.rows, button, selection, this.callbacks);\n\t\t\tlist.appendChild(button);\n\t\t}\n\t\tif (snapshot.roots.length === 0) list.textContent = 'No retention roots.';\n\t\tsection.appendChild(list);\n\t\treturn section;\n\t}\n\n\tprivate createCulled(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = this.createSection('culled', `Culled passes (${snapshot.culledNodes.length})`, 'Recorded passes removed during compilation. Inspect their reasons and accesses in Passes.');\n\t\tconst reasons = new Map<string, number>();\n\t\tfor (const entry of snapshot.culledNodes) reasons.set(entry.reason, (reasons.get(entry.reason) ?? 0) + 1);\n\t\tconst list = document.createElement('ul');\n\t\tfor (const [reason, count] of reasons) {\n\t\t\tconst item = document.createElement('li');\n\t\t\titem.textContent = `${reason}: ${count}`;\n\t\t\tlist.appendChild(item);\n\t\t}\n\t\tsection.appendChild(list);\n\t\tif (snapshot.culledNodes.length > 0) {\n\t\t\tconst button = document.createElement('button');\n\t\t\tbutton.type = 'button';\n\t\t\tbutton.className = 'zenfg-inspector-relation-button';\n\t\t\tbutton.textContent = 'Show culled passes';\n\t\t\tbutton.addEventListener('click', () => this.callbacks.onNavigate?.('passes', 'culled'));\n\t\t\tsection.appendChild(button);\n\t\t}\n\t\treturn section;\n\t}\n\n\tprivate createSegments(snapshot: FrameGraphDebugViewModel): HTMLElement {\n\t\tconst section = this.createSection('segments', `Execution segments (${snapshot.executionSegments.length})`,\n\t\t\t'An opaque interval marks external work. Its GPU submissions and duration are not measured here.');\n\t\tfor (const segment of snapshot.executionSegments) {\n\t\t\tconst selection: Selection = { kind: 'segment', index: segment.index };\n\t\t\tconst members = this.createSection(`segment:${segment.index}`, `${segment.index} · ${segment.kind === 'frame-graph' ? 'FrameGraph command segment' : 'Opaque interval'} · ${segment.nodeIds.length} passes`);\n\t\t\tconst button = createRelationButton('Inspect segment', selection, this.callbacks.onSelect);\n\t\t\tregisterSelectable(this.rows, button, selection, this.callbacks);\n\t\t\tmembers.appendChild(button);\n\t\t\tconst list = document.createElement('div');\n\t\t\tlist.className = 'zenfg-inspector-diagnostic-list';\n\t\t\tfor (const id of segment.nodeIds) {\n\t\t\t\tconst node = snapshot.canonicalNodeById.get(id);\n\t\t\t\tconst nodeSelection = resolveNodeSelection(snapshot, id);\n\t\t\t\tif (node && nodeSelection) list.appendChild(this.createObjectLink(labelNode(node), nodeSelection, 'passes'));\n\t\t\t}\n\t\t\tmembers.appendChild(list);\n\t\t\tsection.appendChild(members);\n\t\t}\n\t\tif (snapshot.executionSegments.length === 0) {\n\t\t\tconst empty = document.createElement('p');\n\t\t\tempty.textContent = 'No execution segments.';\n\t\t\tsection.appendChild(empty);\n\t\t}\n\t\treturn section;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"panelDomHelpers.d.ts","sourceRoot":"","sources":["../src/panelDomHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,mBAAmB,EACnB,wBAAwB,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAOxD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,CAYxE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAQpE;AAED,MAAM,MAAM,0BAA0B,GAAG;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,oBAAoB,CAMnG;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,oBAAoB,CAQxF;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,iBAAiB,CAQvG;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,iBAAiB,CASxG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAKzD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAU3H;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAShF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAKnE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAKjF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAM5E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,MAAM,CAEjF;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEvH"}
1
+ {"version":3,"file":"panelDomHelpers.d.ts","sourceRoot":"","sources":["../src/panelDomHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,mBAAmB,EACnB,wBAAwB,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAOxD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,CAYxE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAQpE;AAED,MAAM,MAAM,0BAA0B,GAAG;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,GAAG,oBAAoB,CAMnG;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,oBAAoB,CAQxF;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,iBAAiB,CAQvG;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,iBAAiB,CASxG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAKzD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAU3H;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAShF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAKnE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAKjF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAK5E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,MAAM,CAEjF;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEvH"}
@@ -106,9 +106,10 @@ export function formatGpuFrameDuration(snapshot) {
106
106
  }
107
107
  export function formatPoolHitRate(snapshot) {
108
108
  const pool = snapshot.resourcePool;
109
- if (!pool || pool.status !== 'available' || pool.acquireCount === 0) {
110
- return '-';
111
- }
109
+ if (!pool || pool.status !== 'available')
110
+ return 'Unavailable';
111
+ if (pool.acquireCount === 0)
112
+ return 'Not applicable · no acquisitions';
112
113
  return `${((pool.reuseCount / pool.acquireCount) * 100).toFixed(0)}%`;
113
114
  }
114
115
  export function formatBytes(bytes) {
@@ -121,9 +122,9 @@ export function formatBytes(bytes) {
121
122
  return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
122
123
  }
123
124
  export function labelNode(node) {
124
- return node.label ?? `node-${node.id}`;
125
+ return node.label ?? node.id;
125
126
  }
126
127
  export function labelResource(resource) {
127
- return resource.label ?? `${resource.kind}-${resource.id}`;
128
+ return resource.label ?? resource.id;
128
129
  }
129
130
  //# sourceMappingURL=panelDomHelpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"panelDomHelpers.js","sourceRoot":"","sources":["../src/panelDomHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n FrameGraphDebugNode,\n FrameGraphDebugViewModel,\n} from './debugCaptureModel.ts';\n\nexport function createSection(title: string): HTMLElement {\n const section = document.createElement('section');\n section.className = 'zenfg-inspector-section';\n const heading = document.createElement('h2');\n heading.textContent = title;\n section.appendChild(heading);\n return section;\n}\n\nexport function createTable(headers: readonly string[]): HTMLTableElement {\n const table = document.createElement('table');\n const head = document.createElement('thead');\n const headRow = document.createElement('tr');\n for (const header of headers) {\n const cell = document.createElement('th');\n cell.textContent = header;\n headRow.appendChild(cell);\n }\n head.appendChild(headRow);\n table.append(head, document.createElement('tbody'));\n return table;\n}\n\nexport function createStat(label: string, value: string): HTMLElement {\n const item = document.createElement('div');\n const name = document.createElement('span');\n name.textContent = label;\n const count = document.createElement('strong');\n count.textContent = value;\n item.append(name, count);\n return item;\n}\n\nexport type FrameGraphDebugCellOptions = {\n\treadonly column?: 'code' | 'kind' | 'numeric';\n\treadonly kind?: string;\n};\n\nexport function createCell(text: string, options?: FrameGraphDebugCellOptions): HTMLTableCellElement {\n const cell = document.createElement('td');\n cell.textContent = text;\n if (options?.column) cell.dataset.column = options.column;\n if (options?.kind) cell.dataset.kind = options.kind;\n return cell;\n}\n\nexport function createButtonCell(text: string, onClick: () => void): HTMLTableCellElement {\n const cell = document.createElement('td');\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = text;\n button.addEventListener('click', onClick);\n cell.appendChild(button);\n return cell;\n}\n\nexport function createToolbarButton(text: string, title: string, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = text;\n button.title = title;\n button.setAttribute('aria-label', title);\n button.addEventListener('click', onClick);\n return button;\n}\n\nexport function createListButton(text: string, selected: boolean, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = text;\n if (selected) {\n button.className = 'selected';\n }\n button.addEventListener('click', onClick);\n return button;\n}\n\nexport function createMutedText(text: string): HTMLElement {\n const element = document.createElement('p');\n element.className = 'zenfg-inspector-muted';\n element.textContent = text;\n return element;\n}\n\nexport function createMutedActionText(prefix: string, actionText: string, suffix: string, onAction: () => void): HTMLElement {\n const element = document.createElement('p');\n element.className = 'zenfg-inspector-muted';\n const button = document.createElement('button');\n button.type = 'button';\n button.className = 'zenfg-inspector-inline-action';\n button.textContent = actionText;\n button.addEventListener('click', onAction);\n element.append(document.createTextNode(prefix), button, document.createTextNode(suffix));\n return element;\n}\n\nexport function formatProfilingStatus(snapshot: FrameGraphDebugViewModel): string {\n const profiling = snapshot.profiling;\n if (!profiling) {\n return 'off';\n }\n if (profiling.status === 'available') {\n return `frame ${profiling.frameIndex}`;\n }\n return profiling.reason;\n}\n\nexport function formatGpuDuration(node: FrameGraphDebugNode): string {\n if (node.gpuDurationMicros === undefined) {\n return '-';\n }\n return (node.gpuDurationMicros / 1000).toFixed(3);\n}\n\nexport function formatGpuFrameDuration(snapshot: FrameGraphDebugViewModel): string {\n if (snapshot.profiling.status !== 'available') {\n return '-';\n }\n return (snapshot.profiling.gpuFrameDurationMicros / 1000).toFixed(3);\n}\n\nexport function formatPoolHitRate(snapshot: FrameGraphDebugViewModel): string {\n const pool = snapshot.resourcePool;\n if (!pool || pool.status !== 'available' || pool.acquireCount === 0) {\n return '-';\n }\n return `${((pool.reuseCount / pool.acquireCount) * 100).toFixed(0)}%`;\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KiB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;\n}\n\nexport function labelNode(node: Pick<FrameGraphDebugNode, 'id' | 'label'>): string {\n return node.label ?? `node-${node.id}`;\n}\n\nexport function labelResource(resource: { readonly id: string; readonly kind: string; readonly label?: string }): string {\n return resource.label ?? `${resource.kind}-${resource.id}`;\n}\n"]}
1
+ {"version":3,"file":"panelDomHelpers.js","sourceRoot":"","sources":["../src/panelDomHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n FrameGraphDebugNode,\n FrameGraphDebugViewModel,\n} from './debugCaptureModel.ts';\n\nexport function createSection(title: string): HTMLElement {\n const section = document.createElement('section');\n section.className = 'zenfg-inspector-section';\n const heading = document.createElement('h2');\n heading.textContent = title;\n section.appendChild(heading);\n return section;\n}\n\nexport function createTable(headers: readonly string[]): HTMLTableElement {\n const table = document.createElement('table');\n const head = document.createElement('thead');\n const headRow = document.createElement('tr');\n for (const header of headers) {\n const cell = document.createElement('th');\n cell.textContent = header;\n headRow.appendChild(cell);\n }\n head.appendChild(headRow);\n table.append(head, document.createElement('tbody'));\n return table;\n}\n\nexport function createStat(label: string, value: string): HTMLElement {\n const item = document.createElement('div');\n const name = document.createElement('span');\n name.textContent = label;\n const count = document.createElement('strong');\n count.textContent = value;\n item.append(name, count);\n return item;\n}\n\nexport type FrameGraphDebugCellOptions = {\n\treadonly column?: 'code' | 'kind' | 'numeric';\n\treadonly kind?: string;\n};\n\nexport function createCell(text: string, options?: FrameGraphDebugCellOptions): HTMLTableCellElement {\n const cell = document.createElement('td');\n cell.textContent = text;\n if (options?.column) cell.dataset.column = options.column;\n if (options?.kind) cell.dataset.kind = options.kind;\n return cell;\n}\n\nexport function createButtonCell(text: string, onClick: () => void): HTMLTableCellElement {\n const cell = document.createElement('td');\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = text;\n button.addEventListener('click', onClick);\n cell.appendChild(button);\n return cell;\n}\n\nexport function createToolbarButton(text: string, title: string, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = text;\n button.title = title;\n button.setAttribute('aria-label', title);\n button.addEventListener('click', onClick);\n return button;\n}\n\nexport function createListButton(text: string, selected: boolean, onClick: () => void): HTMLButtonElement {\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = text;\n if (selected) {\n button.className = 'selected';\n }\n button.addEventListener('click', onClick);\n return button;\n}\n\nexport function createMutedText(text: string): HTMLElement {\n const element = document.createElement('p');\n element.className = 'zenfg-inspector-muted';\n element.textContent = text;\n return element;\n}\n\nexport function createMutedActionText(prefix: string, actionText: string, suffix: string, onAction: () => void): HTMLElement {\n const element = document.createElement('p');\n element.className = 'zenfg-inspector-muted';\n const button = document.createElement('button');\n button.type = 'button';\n button.className = 'zenfg-inspector-inline-action';\n button.textContent = actionText;\n button.addEventListener('click', onAction);\n element.append(document.createTextNode(prefix), button, document.createTextNode(suffix));\n return element;\n}\n\nexport function formatProfilingStatus(snapshot: FrameGraphDebugViewModel): string {\n const profiling = snapshot.profiling;\n if (!profiling) {\n return 'off';\n }\n if (profiling.status === 'available') {\n return `frame ${profiling.frameIndex}`;\n }\n return profiling.reason;\n}\n\nexport function formatGpuDuration(node: FrameGraphDebugNode): string {\n if (node.gpuDurationMicros === undefined) {\n return '-';\n }\n return (node.gpuDurationMicros / 1000).toFixed(3);\n}\n\nexport function formatGpuFrameDuration(snapshot: FrameGraphDebugViewModel): string {\n if (snapshot.profiling.status !== 'available') {\n return '-';\n }\n return (snapshot.profiling.gpuFrameDurationMicros / 1000).toFixed(3);\n}\n\nexport function formatPoolHitRate(snapshot: FrameGraphDebugViewModel): string {\n const pool = snapshot.resourcePool;\n if (!pool || pool.status !== 'available') return 'Unavailable';\n if (pool.acquireCount === 0) return 'Not applicable · no acquisitions';\n return `${((pool.reuseCount / pool.acquireCount) * 100).toFixed(0)}%`;\n}\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KiB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;\n}\n\nexport function labelNode(node: Pick<FrameGraphDebugNode, 'id' | 'label'>): string {\n return node.label ?? node.id;\n}\n\nexport function labelResource(resource: { readonly id: string; readonly kind: string; readonly label?: string }): string {\n return resource.label ?? resource.id;\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { type GraphVisualTheme } from './panelVisualTheme.ts';
1
2
  import type cytoscape from 'cytoscape';
2
3
  import type { ELK, ElkNode } from 'elkjs/lib/elk-api';
3
4
  import type { GraphScene, GraphSceneElementId } from './panelGraphScene.ts';
@@ -20,8 +21,8 @@ export type CytoscapeEdgeRouteData = {
20
21
  readonly segmentWeights: string;
21
22
  readonly segmentDistances: string;
22
23
  };
23
- export declare function layoutGraphScene(elk: ELK, scene: GraphScene): Promise<GraphLayoutResult>;
24
- export declare function createElkLayoutGraph(scene: GraphScene): ElkNode;
24
+ export declare function layoutGraphScene(elk: ELK, scene: GraphScene, theme?: GraphVisualTheme): Promise<GraphLayoutResult>;
25
+ export declare function createElkLayoutGraph(scene: GraphScene, theme?: GraphVisualTheme): ElkNode;
25
26
  export declare function applyGraphLayout(core: cytoscape.Core, scene: GraphScene, layout: GraphLayoutResult): void;
26
27
  export declare function syncExpandedGroupLabelGeometry(core: cytoscape.Core): void;
27
28
  export declare function createCytoscapeEdgeRouteData(route: GraphEdgeRoute | undefined, sourceCenter: GraphPosition, targetCenter: GraphPosition): CytoscapeEdgeRouteData | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"panelGraphLayout.d.ts","sourceRoot":"","sources":["../src/panelGraphLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAmB,OAAO,EAAW,MAAM,mBAAmB,CAAC;AAEhF,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAkB,MAAM,sBAAsB,CAAC;AAG5F,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG;IACzB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CACpC,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;IACpE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU9F;AAOD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAoF/D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAoBzG;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,IAAI,CAWzE;AAED,wBAAgB,4BAA4B,CACxC,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,YAAY,EAAE,aAAa,EAC3B,YAAY,EAAE,aAAa,GAC5B,sBAAsB,GAAG,SAAS,CASpC"}
1
+ {"version":3,"file":"panelGraphLayout.d.ts","sourceRoot":"","sources":["../src/panelGraphLayout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAmB,OAAO,EAAW,MAAM,mBAAmB,CAAC;AAEhF,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAkB,MAAM,sBAAsB,CAAC;AAG5F,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACvE,MAAM,MAAM,cAAc,GAAG;IACzB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;CACpC,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;IACpE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,GAAE,gBAAqC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAU5I;AAOD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,GAAE,gBAAqC,GAAG,OAAO,CAoF7G;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAoBzG;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,IAAI,CAWzE;AAED,wBAAgB,4BAA4B,CACxC,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,YAAY,EAAE,aAAa,EAC3B,YAAY,EAAE,aAAa,GAC5B,sBAAsB,GAAG,SAAS,CASpC"}
@@ -1,6 +1,7 @@
1
+ import { GRAPH_VISUAL_THEME } from "./panelVisualTheme.js";
1
2
  import { expandedGroupLabelMaxWidth, GRAPH_GEOMETRY, nodeDimensions } from "./panelGraphVisuals.js";
2
- export async function layoutGraphScene(elk, scene) {
3
- const graph = createElkLayoutGraph(scene);
3
+ export async function layoutGraphScene(elk, scene, theme = GRAPH_VISUAL_THEME) {
4
+ const graph = createElkLayoutGraph(scene, theme);
4
5
  const layout = await elk.layout(graph);
5
6
  const positions = new Map();
6
7
  collectLayoutPositions(layout, 0, 0, positions);
@@ -14,7 +15,7 @@ function usesCenterPorts(node) {
14
15
  return node.kind === 'resource' || node.kind === 'root'
15
16
  || (node.kind === 'pass' && node.passKind === 'external-submission');
16
17
  }
17
- export function createElkLayoutGraph(scene) {
18
+ export function createElkLayoutGraph(scene, theme = GRAPH_VISUAL_THEME) {
18
19
  const childrenByParent = new Map();
19
20
  const portsByNode = new Map();
20
21
  const nodesById = new Map(scene.nodes.map((node) => [node.id, node]));
@@ -22,7 +23,7 @@ export function createElkLayoutGraph(scene) {
22
23
  const node = nodesById.get(id);
23
24
  if (!usesCenterPorts(node))
24
25
  return {};
25
- const dimensions = nodeDimensions(node);
26
+ const dimensions = nodeDimensions(node, theme);
26
27
  return { x: source ? dimensions.width : 0, y: dimensions.height / 2 };
27
28
  };
28
29
  const elkEdges = scene.edges.map((edge) => {
@@ -55,7 +56,7 @@ export function createElkLayoutGraph(scene) {
55
56
  }
56
57
  const createNode = (node) => {
57
58
  const children = childrenByParent.get(node.id)?.map(createNode);
58
- const dimensions = nodeDimensions(node);
59
+ const dimensions = nodeDimensions(node, theme);
59
60
  return {
60
61
  id: node.id,
61
62
  width: dimensions.width,