@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
@@ -0,0 +1,105 @@
1
+ import { createSearchInput, writeClipboardText } from "./panelWorkbenchHelpers.js";
2
+ /** Created only when Raw is visited and retained for the current object/capture. */
3
+ export class RawDetailView {
4
+ detail;
5
+ root = document.createElement('div');
6
+ tree = document.createElement('div');
7
+ status = document.createElement('span');
8
+ expanded = new Set(['$']);
9
+ query = '';
10
+ json;
11
+ constructor(detail, migrated) {
12
+ this.detail = detail;
13
+ this.root.className = 'zenfg-inspector-raw-view';
14
+ this.json = JSON.stringify(detail.value, null, 2);
15
+ const path = document.createElement('code');
16
+ path.className = 'zenfg-inspector-raw-path';
17
+ path.textContent = detail.path;
18
+ const toolbar = document.createElement('div');
19
+ toolbar.className = 'zenfg-inspector-raw-toolbar';
20
+ const search = createSearchInput('Search Raw fields or values', '', (value) => {
21
+ this.query = value.trim().toLocaleLowerCase();
22
+ this.renderTree();
23
+ });
24
+ search.addEventListener('keydown', (event) => {
25
+ if (event.key !== 'Escape' || !search.value)
26
+ return;
27
+ search.value = '';
28
+ this.query = '';
29
+ this.renderTree();
30
+ event.preventDefault();
31
+ event.stopPropagation();
32
+ });
33
+ const copy = document.createElement('button');
34
+ copy.type = 'button';
35
+ copy.textContent = 'Copy object';
36
+ copy.title = 'Copy the complete canonical object, including fields hidden by search';
37
+ copy.addEventListener('click', () => {
38
+ void writeClipboardText(this.json).then(() => {
39
+ this.status.textContent = 'Copied complete object';
40
+ }, () => {
41
+ this.status.textContent = 'Copy failed. Select the Raw fields to copy manually.';
42
+ });
43
+ });
44
+ this.status.setAttribute('role', 'status');
45
+ this.status.className = 'zenfg-inspector-muted';
46
+ toolbar.append(search, copy);
47
+ this.tree.className = 'zenfg-inspector-raw-detail';
48
+ this.tree.setAttribute('aria-label', 'Canonical object fields');
49
+ this.root.append(path, toolbar, this.status);
50
+ if (migrated) {
51
+ const note = document.createElement('p');
52
+ note.className = 'zenfg-inspector-muted';
53
+ note.textContent = 'Legacy import: showing the migrated canonical Snapshot object.';
54
+ this.root.appendChild(note);
55
+ }
56
+ this.root.appendChild(this.tree);
57
+ this.renderTree();
58
+ }
59
+ renderTree() {
60
+ this.tree.replaceChildren();
61
+ const node = this.createValue('$', this.detail.value, '$', false);
62
+ if (node)
63
+ this.tree.appendChild(node);
64
+ else
65
+ this.tree.textContent = 'No matching fields or values.';
66
+ }
67
+ createValue(key, value, path, includeChildren) {
68
+ const keyMatches = key.toLocaleLowerCase().includes(this.query);
69
+ const matched = !this.query || includeChildren || keyMatches;
70
+ if (typeof value !== 'object' || value === null) {
71
+ const literal = JSON.stringify(value) ?? 'undefined';
72
+ if (!matched && !literal.toLocaleLowerCase().includes(this.query))
73
+ return undefined;
74
+ const leaf = document.createElement('div');
75
+ leaf.className = 'zenfg-inspector-raw-leaf';
76
+ leaf.textContent = `${key}: ${literal}`;
77
+ return leaf;
78
+ }
79
+ const entries = Object.entries(value);
80
+ const children = entries.flatMap(([childKey, childValue]) => {
81
+ const child = this.createValue(childKey, childValue, `${path}.${childKey}`, matched);
82
+ return child ? [child] : [];
83
+ });
84
+ if (this.query && !matched && children.length === 0)
85
+ return undefined;
86
+ const group = document.createElement('details');
87
+ const summary = document.createElement('summary');
88
+ summary.textContent = `${key}: ${Array.isArray(value) ? `[${entries.length} items]` : `{${entries.length} fields}`}`;
89
+ group.open = Boolean(this.query) || this.expanded.has(path);
90
+ group.addEventListener('toggle', () => {
91
+ if (this.query)
92
+ return;
93
+ if (group.open)
94
+ this.expanded.add(path);
95
+ else
96
+ this.expanded.delete(path);
97
+ });
98
+ const body = document.createElement('div');
99
+ body.className = 'zenfg-inspector-raw-children';
100
+ body.append(...children);
101
+ group.append(summary, body);
102
+ return group;
103
+ }
104
+ }
105
+ //# sourceMappingURL=panelRawView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panelRawView.js","sourceRoot":"","sources":["../src/panelRawView.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SelectedCanonicalDetail } from './panelSelection.ts';\nimport { createSearchInput, writeClipboardText } from './panelWorkbenchHelpers.ts';\n\n/** Created only when Raw is visited and retained for the current object/capture. */\nexport class RawDetailView {\n\treadonly root = document.createElement('div');\n\tprivate readonly tree = document.createElement('div');\n\tprivate readonly status = document.createElement('span');\n\tprivate readonly expanded = new Set<string>(['$']);\n\tprivate query = '';\n\tprivate readonly json: string;\n\n\tconstructor(private readonly detail: SelectedCanonicalDetail, migrated: boolean) {\n\t\tthis.root.className = 'zenfg-inspector-raw-view';\n\t\tthis.json = JSON.stringify(detail.value, null, 2);\n\t\tconst path = document.createElement('code');\n\t\tpath.className = 'zenfg-inspector-raw-path';\n\t\tpath.textContent = detail.path;\n\t\tconst toolbar = document.createElement('div');\n\t\ttoolbar.className = 'zenfg-inspector-raw-toolbar';\n\t\tconst search = createSearchInput('Search Raw fields or values', '', (value) => {\n\t\t\tthis.query = value.trim().toLocaleLowerCase();\n\t\t\tthis.renderTree();\n\t\t});\n\t\tsearch.addEventListener('keydown', (event) => {\n\t\t\tif (event.key !== 'Escape' || !search.value) return;\n\t\t\tsearch.value = '';\n\t\t\tthis.query = '';\n\t\t\tthis.renderTree();\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t});\n\t\tconst copy = document.createElement('button');\n\t\tcopy.type = 'button';\n\t\tcopy.textContent = 'Copy object';\n\t\tcopy.title = 'Copy the complete canonical object, including fields hidden by search';\n\t\tcopy.addEventListener('click', () => {\n\t\t\tvoid writeClipboardText(this.json).then(() => {\n\t\t\t\tthis.status.textContent = 'Copied complete object';\n\t\t\t}, () => {\n\t\t\t\tthis.status.textContent = 'Copy failed. Select the Raw fields to copy manually.';\n\t\t\t});\n\t\t});\n\t\tthis.status.setAttribute('role', 'status');\n\t\tthis.status.className = 'zenfg-inspector-muted';\n\t\ttoolbar.append(search, copy);\n\t\tthis.tree.className = 'zenfg-inspector-raw-detail';\n\t\tthis.tree.setAttribute('aria-label', 'Canonical object fields');\n\t\tthis.root.append(path, toolbar, this.status);\n\t\tif (migrated) {\n\t\t\tconst note = document.createElement('p');\n\t\t\tnote.className = 'zenfg-inspector-muted';\n\t\t\tnote.textContent = 'Legacy import: showing the migrated canonical Snapshot object.';\n\t\t\tthis.root.appendChild(note);\n\t\t}\n\t\tthis.root.appendChild(this.tree);\n\t\tthis.renderTree();\n\t}\n\n\tprivate renderTree(): void {\n\t\tthis.tree.replaceChildren();\n\t\tconst node = this.createValue('$', this.detail.value, '$', false);\n\t\tif (node) this.tree.appendChild(node);\n\t\telse this.tree.textContent = 'No matching fields or values.';\n\t}\n\n\tprivate createValue(key: string, value: unknown, path: string, includeChildren: boolean): HTMLElement | undefined {\n\t\tconst keyMatches = key.toLocaleLowerCase().includes(this.query);\n\t\tconst matched = !this.query || includeChildren || keyMatches;\n\t\tif (typeof value !== 'object' || value === null) {\n\t\t\tconst literal = JSON.stringify(value) ?? 'undefined';\n\t\t\tif (!matched && !literal.toLocaleLowerCase().includes(this.query)) return undefined;\n\t\t\tconst leaf = document.createElement('div');\n\t\t\tleaf.className = 'zenfg-inspector-raw-leaf';\n\t\t\tleaf.textContent = `${key}: ${literal}`;\n\t\t\treturn leaf;\n\t\t}\n\t\tconst entries = Object.entries(value);\n\t\tconst children = entries.flatMap(([childKey, childValue]) => {\n\t\t\tconst child = this.createValue(childKey, childValue, `${path}.${childKey}`, matched);\n\t\t\treturn child ? [child] : [];\n\t\t});\n\t\tif (this.query && !matched && children.length === 0) return undefined;\n\t\tconst group = document.createElement('details');\n\t\tconst summary = document.createElement('summary');\n\t\tsummary.textContent = `${key}: ${Array.isArray(value) ? `[${entries.length} items]` : `{${entries.length} fields}`}`;\n\t\tgroup.open = Boolean(this.query) || this.expanded.has(path);\n\t\tgroup.addEventListener('toggle', () => {\n\t\t\tif (this.query) return;\n\t\t\tif (group.open) this.expanded.add(path);\n\t\t\telse this.expanded.delete(path);\n\t\t});\n\t\tconst body = document.createElement('div');\n\t\tbody.className = 'zenfg-inspector-raw-children';\n\t\tbody.append(...children);\n\t\tgroup.append(summary, body);\n\t\treturn group;\n\t}\n}\n"]}
@@ -6,14 +6,22 @@ export declare class ResourcesView {
6
6
  readonly root: HTMLElement;
7
7
  private readonly table;
8
8
  private readonly rows;
9
+ private readonly count;
10
+ private readonly searchInput;
11
+ private readonly kindSelect;
12
+ private readonly originSelect;
9
13
  private snapshot;
10
14
  private selected;
11
15
  private search;
12
16
  private kind;
13
17
  private origin;
18
+ private sort;
14
19
  constructor(callbacks: WorkbenchCallbacks, idPrefix: string);
15
20
  setSnapshot(snapshot: FrameGraphDebugViewModel): void;
16
21
  setSelection(selected: Selection | undefined): void;
22
+ reveal(selection: Selection): void;
23
+ private clearFilters;
17
24
  private renderRows;
25
+ private compareResources;
18
26
  }
19
27
  //# sourceMappingURL=panelResourcesView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panelResourcesView.d.ts","sourceRoot":"","sources":["../src/panelResourcesView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAaN,KAAK,kBAAkB,EAEvB,MAAM,4BAA4B,CAAC;AAEpC,qBAAa,aAAa;IAkBb,OAAO,CAAC,QAAQ,CAAC,SAAS;IAjBtC,QAAQ,CAAC,IAAI,cAAqC;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAQnB;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;gBAEM,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM;IA+B5E,WAAW,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI;IAKrD,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI;IAKnD,OAAO,CAAC,UAAU;CAmClB"}
1
+ {"version":3,"file":"panelResourcesView.d.ts","sourceRoot":"","sources":["../src/panelResourcesView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA2B,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAEhG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAG8B,KAAK,kBAAkB,EAC3D,MAAM,4BAA4B,CAAC;AAIpC,qBAAa,aAAa;IAqBb,OAAO,CAAC,QAAQ,CAAC,SAAS;IApBtC,QAAQ,CAAC,IAAI,cAAqC;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAMnB;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAwB;gBAEP,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM;IA4B5E,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;IAOlC,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,UAAU;IAmClB,OAAO,CAAC,gBAAgB;CAUxB"}
@@ -1,48 +1,52 @@
1
1
  import { createCell, labelResource } from "./panelDomHelpers.js";
2
- import { createEmptyTableRow, createKindCell, createFilterSelect, createSearchInput, createSelectionCell, createTableScroller, createViewToolbar, formatEstimatedBytes, formatResourceDescriptor, groupPath, registerSelectable, resourceAccessCounts, updateSelectedRows, } from "./panelWorkbenchHelpers.js";
2
+ import { createEmptyTableRow, createKindCell, createFilterSelect, createSearchInput, createSelectionCell, createTableScroller, createViewToolbar, formatEstimatedBytes, groupPath, registerSelectable, resourceAccessCounts, selectionKey, updateSelectedRows, } from "./panelWorkbenchHelpers.js";
3
3
  export class ResourcesView {
4
4
  callbacks;
5
5
  root = document.createElement('section');
6
6
  table = createTableScroller([
7
- { label: 'Resource / Group' },
7
+ { label: 'Name' },
8
8
  { label: 'Type / Origin', column: 'kind' },
9
- { label: 'Descriptor', column: 'code' },
10
9
  { label: 'Estimated', column: 'numeric' },
11
10
  { label: 'Lifetime', column: 'code' },
12
- { label: 'Physical', column: 'numeric' },
13
11
  { label: 'R / W', column: 'numeric' },
14
12
  ]);
15
13
  rows = new Map();
14
+ count = document.createElement('span');
15
+ searchInput;
16
+ kindSelect;
17
+ originSelect;
16
18
  snapshot;
17
19
  selected;
18
20
  search = '';
19
21
  kind = 'all';
20
22
  origin = 'all';
23
+ sort = 'name';
21
24
  constructor(callbacks, idPrefix) {
22
25
  this.callbacks = callbacks;
23
26
  this.root.className = 'zenfg-inspector-view zenfg-inspector-resources-view';
24
27
  this.root.id = `${idPrefix}-view-resources`;
25
28
  this.root.setAttribute('role', 'tabpanel');
26
- const toolbar = createViewToolbar('Resource filters');
27
- toolbar.append(createSearchInput('Search resource or group', this.search, (value) => {
29
+ const toolbar = createViewToolbar('Resource filters and sorting');
30
+ this.searchInput = createSearchInput('Search resource, ID or group', this.search, (value) => {
28
31
  this.search = value.trim().toLocaleLowerCase();
29
32
  this.renderRows();
30
- }), createFilterSelect('Resource kind', this.kind, [
31
- ['all', 'All kinds'],
32
- ['texture', 'Texture'],
33
- ['buffer', 'Buffer'],
34
- ], (value) => {
35
- this.kind = value;
36
- this.renderRows();
37
- }), createFilterSelect('Resource origin', this.origin, [
38
- ['all', 'All origins'],
39
- ['transient', 'Transient'],
40
- ['imported', 'Imported'],
41
- ['swapchain', 'Swapchain'],
42
- ], (value) => {
43
- this.origin = value;
44
- this.renderRows();
45
- }));
33
+ });
34
+ this.kindSelect = createFilterSelect('Resource kind', this.kind, [
35
+ ['all', 'All kinds'], ['texture', 'Texture'], ['buffer', 'Buffer'],
36
+ ], (value) => { this.kind = value; this.renderRows(); });
37
+ this.originSelect = createFilterSelect('Resource origin', this.origin, [
38
+ ['all', 'All origins'], ['transient', 'Transient'], ['imported', 'Imported'], ['surface', 'Surface'],
39
+ ], (value) => { this.origin = value; this.renderRows(); });
40
+ const sort = createFilterSelect('Sort resources', this.sort, [
41
+ ['name', 'Name'], ['size', 'Size: largest first'], ['lifetime', 'Lifetime: first use'],
42
+ ], (value) => { this.sort = value; this.renderRows(); });
43
+ const clear = document.createElement('button');
44
+ clear.type = 'button';
45
+ clear.textContent = 'Clear filters';
46
+ clear.addEventListener('click', () => { this.clearFilters(); this.renderRows(); });
47
+ this.count.className = 'zenfg-inspector-result-count';
48
+ this.count.setAttribute('role', 'status');
49
+ toolbar.append(this.searchInput, this.kindSelect, this.originSelect, sort, clear, this.count);
46
50
  this.root.append(toolbar, this.table.scroller);
47
51
  }
48
52
  setSnapshot(snapshot) {
@@ -53,6 +57,21 @@ export class ResourcesView {
53
57
  this.selected = selected;
54
58
  updateSelectedRows(this.rows, selected);
55
59
  }
60
+ reveal(selection) {
61
+ if (selection.kind !== 'resource')
62
+ return;
63
+ this.clearFilters();
64
+ this.renderRows();
65
+ this.rows.get(selectionKey(selection))?.[0]?.scrollIntoView?.({ block: 'nearest' });
66
+ }
67
+ clearFilters() {
68
+ this.search = '';
69
+ this.kind = 'all';
70
+ this.origin = 'all';
71
+ this.searchInput.value = '';
72
+ this.kindSelect.value = 'all';
73
+ this.originSelect.value = 'all';
74
+ }
56
75
  renderRows() {
57
76
  const snapshot = this.snapshot;
58
77
  if (!snapshot)
@@ -64,26 +83,38 @@ export class ResourcesView {
64
83
  return false;
65
84
  if (this.origin !== 'all' && resource.origin !== this.origin)
66
85
  return false;
67
- if (this.search.length === 0)
68
- return true;
69
- return `${labelResource(resource)} ${groupPath(snapshot, resource.debugGroupId)}`
86
+ return !this.search || `${labelResource(resource)} ${resource.id} ${groupPath(snapshot, resource.debugGroupId)}`
70
87
  .toLocaleLowerCase().includes(this.search);
71
- });
88
+ }).sort((a, b) => this.compareResources(a, b));
89
+ this.count.textContent = `${resources.length} / ${snapshot.resources.length} resources`;
72
90
  for (const resource of resources) {
73
91
  const selection = { kind: 'resource', id: resource.id };
74
92
  const row = document.createElement('tr');
75
93
  registerSelectable(this.rows, row, selection, this.callbacks);
76
94
  const [reads, writes] = resourceAccessCounts(snapshot, resource.id);
77
95
  const resourceCell = createSelectionCell(labelResource(resource), selection, this.callbacks);
78
- const group = document.createElement('small');
79
- group.textContent = groupPath(snapshot, resource.debugGroupId);
80
- resourceCell.appendChild(group);
81
- row.append(resourceCell, createKindCell(resource.kind, `${resource.kind} · ${resource.origin}`), createCell(formatResourceDescriptor(resource), { column: 'code' }), createCell(formatEstimatedBytes(resource.estimatedByteSize), { column: 'numeric' }), createCell(resource.lifetime ? `${resource.lifetime.firstUse}–${resource.lifetime.lastUse}` : '-', { column: 'code' }), createCell(resource.physicalResourceId === undefined ? '-' : `#${resource.physicalResourceId}`, { column: 'numeric' }), createCell(`${reads} / ${writes}`, { column: 'numeric' }));
96
+ resourceCell.title = resource.id;
97
+ if (resource.debugGroupId !== undefined) {
98
+ const group = document.createElement('small');
99
+ group.textContent = groupPath(snapshot, resource.debugGroupId);
100
+ resourceCell.appendChild(group);
101
+ }
102
+ row.append(resourceCell, createKindCell(resource.kind, `${resource.kind} · ${resource.origin}`), createCell(formatEstimatedBytes(resource.estimatedByteSize), { column: 'numeric' }), createCell(resource.lifetime ? `${resource.lifetime.firstUse}–${resource.lifetime.lastUse}` : 'Unknown', { column: 'code' }), createCell(`${reads} / ${writes}`, { column: 'numeric' }));
82
103
  this.table.body.appendChild(row);
83
104
  }
84
105
  if (resources.length === 0)
85
- this.table.body.appendChild(createEmptyTableRow(7, 'No resources match the current filters.'));
106
+ this.table.body.appendChild(createEmptyTableRow(5, 'No resources match the current filters.'));
86
107
  updateSelectedRows(this.rows, this.selected);
87
108
  }
109
+ compareResources(a, b) {
110
+ const byName = () => labelResource(a).localeCompare(labelResource(b)) || a.id.localeCompare(b.id);
111
+ const knownFirst = (left, right, descending) => (left === undefined ? right === undefined ? 0 : 1
112
+ : right === undefined ? -1 : descending ? right - left : left - right);
113
+ if (this.sort === 'size')
114
+ return knownFirst(a.estimatedByteSize, b.estimatedByteSize, true) || byName();
115
+ if (this.sort === 'lifetime')
116
+ return knownFirst(a.lifetime?.firstUse, b.lifetime?.firstUse, false) || byName();
117
+ return byName();
118
+ }
88
119
  }
89
120
  //# sourceMappingURL=panelResourcesView.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"panelResourcesView.js","sourceRoot":"","sources":["../src/panelResourcesView.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport { createCell, labelResource } from './panelDomHelpers.ts';\nimport type { Selection } from './panelTypes.ts';\nimport {\n\tcreateEmptyTableRow,\n\tcreateKindCell,\n\tcreateFilterSelect,\n\tcreateSearchInput,\n\tcreateSelectionCell,\n\tcreateTableScroller,\n\tcreateViewToolbar,\n\tformatEstimatedBytes,\n\tformatResourceDescriptor,\n\tgroupPath,\n\tregisterSelectable,\n\tresourceAccessCounts,\n\ttype WorkbenchCallbacks,\n\tupdateSelectedRows,\n} from './panelWorkbenchHelpers.ts';\n\nexport class ResourcesView {\n\treadonly root = document.createElement('section');\n\tprivate readonly table = createTableScroller([\n\t\t{ label: 'Resource / Group' },\n\t\t{ label: 'Type / Origin', column: 'kind' },\n\t\t{ label: 'Descriptor', column: 'code' },\n\t\t{ label: 'Estimated', column: 'numeric' },\n\t\t{ label: 'Lifetime', column: 'code' },\n\t\t{ label: 'Physical', column: 'numeric' },\n\t\t{ label: 'R / W', column: 'numeric' },\n\t]);\n\tprivate readonly rows = new Map<string, HTMLElement[]>();\n\tprivate snapshot: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate search = '';\n\tprivate kind = 'all';\n\tprivate origin = 'all';\n\n\tconstructor(private readonly callbacks: WorkbenchCallbacks, idPrefix: string) {\n\t\tthis.root.className = 'zenfg-inspector-view zenfg-inspector-resources-view';\n\t\tthis.root.id = `${idPrefix}-view-resources`;\n\t\tthis.root.setAttribute('role', 'tabpanel');\n\t\tconst toolbar = createViewToolbar('Resource filters');\n\t\ttoolbar.append(\n\t\t\tcreateSearchInput('Search resource or group', this.search, (value) => {\n\t\t\t\tthis.search = value.trim().toLocaleLowerCase();\n\t\t\t\tthis.renderRows();\n\t\t\t}),\n\t\t\tcreateFilterSelect('Resource kind', this.kind, [\n\t\t\t\t['all', 'All kinds'],\n\t\t\t\t['texture', 'Texture'],\n\t\t\t\t['buffer', 'Buffer'],\n\t\t\t], (value) => {\n\t\t\t\tthis.kind = value;\n\t\t\t\tthis.renderRows();\n\t\t\t}),\n\t\t\tcreateFilterSelect('Resource origin', this.origin, [\n\t\t\t\t['all', 'All origins'],\n\t\t\t\t['transient', 'Transient'],\n\t\t\t\t['imported', 'Imported'],\n\t\t\t\t['swapchain', 'Swapchain'],\n\t\t\t], (value) => {\n\t\t\t\tthis.origin = value;\n\t\t\t\tthis.renderRows();\n\t\t\t}),\n\t\t);\n\t\tthis.root.append(toolbar, this.table.scroller);\n\t}\n\n\tsetSnapshot(snapshot: FrameGraphDebugViewModel): void {\n\t\tthis.snapshot = snapshot;\n\t\tthis.renderRows();\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 renderRows(): void {\n\t\tconst snapshot = this.snapshot;\n\t\tif (!snapshot) return;\n\t\tthis.rows.clear();\n\t\tthis.table.body.replaceChildren();\n\t\tconst resources = snapshot.resources.filter((resource) => {\n\t\t\tif (this.kind !== 'all' && resource.kind !== this.kind) return false;\n\t\t\tif (this.origin !== 'all' && resource.origin !== this.origin) return false;\n\t\t\tif (this.search.length === 0) return true;\n\t\t\treturn `${labelResource(resource)} ${groupPath(snapshot, resource.debugGroupId)}`\n\t\t\t\t.toLocaleLowerCase().includes(this.search);\n\t\t});\n\t\tfor (const resource of resources) {\n\t\t\tconst selection: Selection = { kind: 'resource', id: resource.id };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst [reads, writes] = resourceAccessCounts(snapshot, resource.id);\n\t\t\tconst resourceCell = createSelectionCell(labelResource(resource), selection, this.callbacks);\n\t\t\tconst group = document.createElement('small');\n\t\t\tgroup.textContent = groupPath(snapshot, resource.debugGroupId);\n\t\t\tresourceCell.appendChild(group);\n\t\t\trow.append(\n\t\t\t\tresourceCell,\n\t\t\t\tcreateKindCell(resource.kind, `${resource.kind} · ${resource.origin}`),\n\t\t\t\tcreateCell(formatResourceDescriptor(resource), { column: 'code' }),\n\t\t\t\tcreateCell(formatEstimatedBytes(resource.estimatedByteSize), { column: 'numeric' }),\n\t\t\t\tcreateCell(resource.lifetime ? `${resource.lifetime.firstUse}–${resource.lifetime.lastUse}` : '-', { column: 'code' }),\n\t\t\t\tcreateCell(resource.physicalResourceId === undefined ? '-' : `#${resource.physicalResourceId}`, { column: 'numeric' }),\n\t\t\t\tcreateCell(`${reads} / ${writes}`, { column: 'numeric' }),\r\n\t\t\t);\n\t\t\tthis.table.body.appendChild(row);\n\t\t}\n\t\tif (resources.length === 0) this.table.body.appendChild(createEmptyTableRow(7, 'No resources match the current filters.'));\n\t\tupdateSelectedRows(this.rows, this.selected);\n\t}\n}\n"]}
1
+ {"version":3,"file":"panelResourcesView.js","sourceRoot":"","sources":["../src/panelResourcesView.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,EACN,mBAAmB,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAC/F,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,SAAS,EAAE,kBAAkB,EAC3F,oBAAoB,EAAE,YAAY,EAA2B,kBAAkB,GAC/E,MAAM,4BAA4B,CAAC;AAIpC,MAAM,OAAO,aAAa;IAqBI;IApBpB,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACjC,KAAK,GAAG,mBAAmB,CAAC;QAC5C,EAAE,KAAK,EAAE,MAAM,EAAE;QACjB,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE;QAC1C,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE;QACzC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;QACrC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE;KACrC,CAAC,CAAC;IACc,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IACxC,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,WAAW,CAAmB;IAC9B,UAAU,CAAoB;IAC9B,YAAY,CAAoB;IACzC,QAAQ,CAAuC;IAC/C,QAAQ,CAAwB;IAChC,MAAM,GAAG,EAAE,CAAC;IACZ,IAAI,GAAG,KAAK,CAAC;IACb,MAAM,GAAG,KAAK,CAAC;IACf,IAAI,GAAiB,MAAM,CAAC;IAEpC,YAA6B,SAA6B,EAAE,QAAgB;QAA/C,cAAS,GAAT,SAAS,CAAoB;QACzD,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,qDAAqD,CAAC;QAC5E,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,QAAQ,iBAAiB,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,GAAG,iBAAiB,CAAC,8BAA8B,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3F,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,GAAG,kBAAkB,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,EAAE;YAChE,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAClE,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,GAAG,kBAAkB,CAAC,iBAAiB,EAAE,IAAI,CAAC,MAAM,EAAE;YACtE,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;SACpG,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,kBAAkB,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,EAAE;YAC5D,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAAE,CAAC,UAAU,EAAE,qBAAqB,CAAC;SACtF,EAAE,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,KAAqB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC;QACtB,KAAK,CAAC,WAAW,GAAG,eAAe,CAAC;QACpC,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,8BAA8B,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9F,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,WAAW,CAAC,QAAkC;QAC7C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,CAAC;IACnB,CAAC;IAED,YAAY,CAAC,QAA+B;QAC3C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,SAAoB;QAC1B,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU;YAAE,OAAO;QAC1C,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACrF,CAAC;IAEO,YAAY;QACnB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;QAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACzD,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,EAAE,CAAC;QAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;QAAC,IAAI,CAAC,YAAY,CAAC,KAAK,GAAG,KAAK,CAAC;IAC7F,CAAC;IAEO,UAAU;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE;YACxD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;gBAAE,OAAO,KAAK,CAAC;YACrE,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;YAC3E,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,EAAE,IAAI,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE;iBAC9G,iBAAiB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,SAAS,CAAC,MAAM,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,YAAY,CAAC;QACxF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,SAAS,GAAc,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;YACnE,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACzC,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9D,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;YACpE,MAAM,YAAY,GAAG,mBAAmB,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7F,YAAY,CAAC,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC;YACjC,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBAC9C,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;gBAC/D,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,YAAY,EACtB,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,IAAI,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,EACtE,UAAU,CAAC,oBAAoB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EACnF,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAC5H,UAAU,CAAC,GAAG,KAAK,MAAM,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YAC5D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,EAAE,yCAAyC,CAAC,CAAC,CAAC;QAC3H,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAEO,gBAAgB,CAAC,CAA0B,EAAE,CAA0B;QAC9E,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClG,MAAM,UAAU,GAAG,CAAC,IAAwB,EAAE,KAAyB,EAAE,UAAmB,EAAU,EAAE,CAAC,CACxG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CACtE,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,UAAU,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;QACxG,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU;YAAE,OAAO,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAC/G,OAAO,MAAM,EAAE,CAAC;IACjB,CAAC;CACD","sourcesContent":["import type { FrameGraphDebugResource, FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport { createCell, labelResource } from './panelDomHelpers.ts';\nimport type { Selection } from './panelTypes.ts';\nimport {\n\tcreateEmptyTableRow, createKindCell, createFilterSelect, createSearchInput, createSelectionCell,\n\tcreateTableScroller, createViewToolbar, formatEstimatedBytes, groupPath, registerSelectable,\n\tresourceAccessCounts, selectionKey, type WorkbenchCallbacks, updateSelectedRows,\n} from './panelWorkbenchHelpers.ts';\n\ntype ResourceSort = 'name' | 'size' | 'lifetime';\n\nexport class ResourcesView {\n\treadonly root = document.createElement('section');\n\tprivate readonly table = createTableScroller([\n\t\t{ label: 'Name' },\n\t\t{ label: 'Type / Origin', column: 'kind' },\n\t\t{ label: 'Estimated', column: 'numeric' },\n\t\t{ label: 'Lifetime', column: 'code' },\n\t\t{ label: 'R / W', column: 'numeric' },\n\t]);\n\tprivate readonly rows = new Map<string, HTMLElement[]>();\n\tprivate readonly count = document.createElement('span');\n\tprivate readonly searchInput: HTMLInputElement;\n\tprivate readonly kindSelect: HTMLSelectElement;\n\tprivate readonly originSelect: HTMLSelectElement;\n\tprivate snapshot: FrameGraphDebugViewModel | undefined;\n\tprivate selected: Selection | undefined;\n\tprivate search = '';\n\tprivate kind = 'all';\n\tprivate origin = 'all';\n\tprivate sort: ResourceSort = 'name';\n\n\tconstructor(private readonly callbacks: WorkbenchCallbacks, idPrefix: string) {\n\t\tthis.root.className = 'zenfg-inspector-view zenfg-inspector-resources-view';\n\t\tthis.root.id = `${idPrefix}-view-resources`;\n\t\tthis.root.setAttribute('role', 'tabpanel');\n\t\tconst toolbar = createViewToolbar('Resource filters and sorting');\n\t\tthis.searchInput = createSearchInput('Search resource, ID or group', this.search, (value) => {\n\t\t\tthis.search = value.trim().toLocaleLowerCase();\n\t\t\tthis.renderRows();\n\t\t});\n\t\tthis.kindSelect = createFilterSelect('Resource kind', this.kind, [\n\t\t\t['all', 'All kinds'], ['texture', 'Texture'], ['buffer', 'Buffer'],\n\t\t], (value) => { this.kind = value; this.renderRows(); });\n\t\tthis.originSelect = createFilterSelect('Resource origin', this.origin, [\n\t\t\t['all', 'All origins'], ['transient', 'Transient'], ['imported', 'Imported'], ['surface', 'Surface'],\n\t\t], (value) => { this.origin = value; this.renderRows(); });\n\t\tconst sort = createFilterSelect('Sort resources', this.sort, [\n\t\t\t['name', 'Name'], ['size', 'Size: largest first'], ['lifetime', 'Lifetime: first use'],\n\t\t], (value) => { this.sort = value as ResourceSort; this.renderRows(); });\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.renderRows(); });\n\t\tthis.count.className = 'zenfg-inspector-result-count';\n\t\tthis.count.setAttribute('role', 'status');\n\t\ttoolbar.append(this.searchInput, this.kindSelect, this.originSelect, sort, clear, this.count);\n\t\tthis.root.append(toolbar, this.table.scroller);\n\t}\n\n\tsetSnapshot(snapshot: FrameGraphDebugViewModel): void {\n\t\tthis.snapshot = snapshot;\n\t\tthis.renderRows();\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\tif (selection.kind !== 'resource') return;\n\t\tthis.clearFilters();\n\t\tthis.renderRows();\n\t\tthis.rows.get(selectionKey(selection))?.[0]?.scrollIntoView?.({ block: 'nearest' });\n\t}\n\n\tprivate clearFilters(): void {\n\t\tthis.search = ''; this.kind = 'all'; this.origin = 'all';\n\t\tthis.searchInput.value = ''; this.kindSelect.value = 'all'; this.originSelect.value = 'all';\n\t}\n\n\tprivate renderRows(): void {\n\t\tconst snapshot = this.snapshot;\n\t\tif (!snapshot) return;\n\t\tthis.rows.clear();\n\t\tthis.table.body.replaceChildren();\n\t\tconst resources = snapshot.resources.filter((resource) => {\n\t\t\tif (this.kind !== 'all' && resource.kind !== this.kind) return false;\n\t\t\tif (this.origin !== 'all' && resource.origin !== this.origin) return false;\n\t\t\treturn !this.search || `${labelResource(resource)} ${resource.id} ${groupPath(snapshot, resource.debugGroupId)}`\n\t\t\t\t.toLocaleLowerCase().includes(this.search);\n\t\t}).sort((a, b) => this.compareResources(a, b));\n\t\tthis.count.textContent = `${resources.length} / ${snapshot.resources.length} resources`;\n\t\tfor (const resource of resources) {\n\t\t\tconst selection: Selection = { kind: 'resource', id: resource.id };\n\t\t\tconst row = document.createElement('tr');\n\t\t\tregisterSelectable(this.rows, row, selection, this.callbacks);\n\t\t\tconst [reads, writes] = resourceAccessCounts(snapshot, resource.id);\n\t\t\tconst resourceCell = createSelectionCell(labelResource(resource), selection, this.callbacks);\n\t\t\tresourceCell.title = resource.id;\n\t\t\tif (resource.debugGroupId !== undefined) {\n\t\t\t\tconst group = document.createElement('small');\n\t\t\t\tgroup.textContent = groupPath(snapshot, resource.debugGroupId);\n\t\t\t\tresourceCell.appendChild(group);\n\t\t\t}\n\t\t\trow.append(resourceCell,\n\t\t\t\tcreateKindCell(resource.kind, `${resource.kind} · ${resource.origin}`),\n\t\t\t\tcreateCell(formatEstimatedBytes(resource.estimatedByteSize), { column: 'numeric' }),\n\t\t\t\tcreateCell(resource.lifetime ? `${resource.lifetime.firstUse}–${resource.lifetime.lastUse}` : 'Unknown', { column: 'code' }),\n\t\t\t\tcreateCell(`${reads} / ${writes}`, { column: 'numeric' }));\n\t\t\tthis.table.body.appendChild(row);\n\t\t}\n\t\tif (resources.length === 0) this.table.body.appendChild(createEmptyTableRow(5, 'No resources match the current filters.'));\n\t\tupdateSelectedRows(this.rows, this.selected);\n\t}\n\n\tprivate compareResources(a: FrameGraphDebugResource, b: FrameGraphDebugResource): number {\n\t\tconst byName = () => labelResource(a).localeCompare(labelResource(b)) || a.id.localeCompare(b.id);\n\t\tconst knownFirst = (left: number | undefined, right: number | undefined, descending: boolean): number => (\n\t\t\tleft === undefined ? right === undefined ? 0 : 1\n\t\t\t\t: right === undefined ? -1 : descending ? right - left : left - right\n\t\t);\n\t\tif (this.sort === 'size') return knownFirst(a.estimatedByteSize, b.estimatedByteSize, true) || byName();\n\t\tif (this.sort === 'lifetime') return knownFirst(a.lifetime?.firstUse, b.lifetime?.firstUse, false) || byName();\n\t\treturn byName();\n\t}\n}\n"]}
@@ -1,5 +1,13 @@
1
- import type { FrameGraphDebugViewModel } from './debugCaptureModel.ts';
1
+ import { type FrameGraphDebugViewModel } from './debugCaptureModel.ts';
2
2
  import type { Selection } from './panelTypes.ts';
3
3
  export declare function resolveSelectedDetail(snapshot: FrameGraphDebugViewModel, selected: Selection | undefined): unknown;
4
4
  export declare function selectionExists(snapshot: FrameGraphDebugViewModel, selected: Selection): boolean;
5
+ /** Resolve identity again after a capture, including retained/culled transitions. */
6
+ export declare function resolveNodeSelection(snapshot: FrameGraphDebugViewModel, id: string): Selection | undefined;
7
+ export type SelectedCanonicalDetail = {
8
+ readonly path: string;
9
+ readonly value: unknown;
10
+ };
11
+ /** Raw shows the canonical source object, never the presentation model. */
12
+ export declare function resolveSelectedCanonicalDetail(snapshot: FrameGraphDebugViewModel, selected: Selection | undefined): SelectedCanonicalDetail | undefined;
5
13
  //# sourceMappingURL=panelSelection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panelSelection.d.ts","sourceRoot":"","sources":["../src/panelSelection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,wBAAwB,EAClC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAC7B,OAAO,CAuCT;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,wBAAwB,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAiBhG"}
1
+ {"version":3,"file":"panelSelection.d.ts","sourceRoot":"","sources":["../src/panelSelection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,wBAAwB,EAClC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAC7B,OAAO,CAuCT;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,wBAAwB,EAAE,QAAQ,EAAE,SAAS,GAAG,OAAO,CAiBhG;AAgCD,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,wBAAwB,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAI1G;AAED,MAAM,MAAM,uBAAuB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzF,2EAA2E;AAC3E,wBAAgB,8BAA8B,CAC7C,QAAQ,EAAE,wBAAwB,EAClC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAC7B,uBAAuB,GAAG,SAAS,CAqBrC"}
@@ -1,3 +1,4 @@
1
+ import { rootKey } from "./debugCaptureModel.js";
1
2
  export function resolveSelectedDetail(snapshot, selected) {
2
3
  if (!selected)
3
4
  return snapshot;
@@ -22,7 +23,7 @@ export function resolveSelectedDetail(snapshot, selected) {
22
23
  case 'root':
23
24
  return snapshot.roots.find((root) => root.key === selected.key);
24
25
  case 'culled': {
25
- const culled = snapshot.culledNodes[selected.index];
26
+ const culled = snapshot.culledById.get(selected.id);
26
27
  return culled ? {
27
28
  ...culled,
28
29
  node: {
@@ -49,7 +50,7 @@ export function selectionExists(snapshot, selected) {
49
50
  case 'root':
50
51
  return snapshot.roots.filter((root) => root.key === selected.key).length === 1;
51
52
  case 'culled':
52
- return isValidIndex(selected.index, snapshot.culledNodes.length);
53
+ return snapshot.culledById.has(selected.id);
53
54
  case 'allocation':
54
55
  return snapshot.allocationById.has(selected.id);
55
56
  case 'segment':
@@ -82,7 +83,36 @@ function debugGroupPath(snapshot, groupId) {
82
83
  return '-';
83
84
  return snapshot.groupById.get(groupId)?.path.join(' / ') ?? `#${groupId}`;
84
85
  }
85
- function isValidIndex(index, length) {
86
- return Number.isInteger(index) && index >= 0 && index < length;
86
+ /** Resolve identity again after a capture, including retained/culled transitions. */
87
+ export function resolveNodeSelection(snapshot, id) {
88
+ if (snapshot.nodeById.has(id))
89
+ return { kind: 'node', id };
90
+ if (snapshot.culledById.has(id))
91
+ return { kind: 'culled', id };
92
+ return undefined;
93
+ }
94
+ /** Raw shows the canonical source object, never the presentation model. */
95
+ export function resolveSelectedCanonicalDetail(snapshot, selected) {
96
+ if (!selected)
97
+ return undefined;
98
+ const protocol = snapshot.protocol;
99
+ function at(values, path, predicate) {
100
+ const index = values.findIndex(predicate);
101
+ return index < 0 ? undefined : { path: `${path}[${index}]`, value: values[index] };
102
+ }
103
+ switch (selected.kind) {
104
+ case 'node':
105
+ case 'culled': return at(protocol.graph.nodes, '$.graph.nodes', (node) => node.id === selected.id);
106
+ case 'resource': return at(protocol.graph.resources, '$.graph.resources', (resource) => resource.id === selected.id);
107
+ case 'group': {
108
+ const id = snapshot.groupByPathKey.get(selected.pathKey)?.id;
109
+ return at(protocol.graph.groups, '$.graph.groups', (group) => group.id === id);
110
+ }
111
+ case 'root': return at(protocol.graph.roots, '$.graph.roots', (root) => rootKey(root) === selected.key);
112
+ case 'allocation': return protocol.memory.allocationReport.status === 'available'
113
+ ? at(protocol.memory.allocationReport.allocations, '$.memory.allocationReport.allocations', (allocation) => allocation.id === selected.id)
114
+ : undefined;
115
+ case 'segment': return at(protocol.graph.segments, '$.graph.segments', (segment) => segment.order === selected.index);
116
+ }
87
117
  }
88
118
  //# sourceMappingURL=panelSelection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"panelSelection.js","sourceRoot":"","sources":["../src/panelSelection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport type { Selection } from './panelTypes.ts';\n\nexport function resolveSelectedDetail(\n\tsnapshot: FrameGraphDebugViewModel,\n\tselected: Selection | undefined,\n): unknown {\n\tif (!selected) return snapshot;\n\n\tswitch (selected.kind) {\n\t\tcase 'node': {\n\t\t\tconst node = snapshot.nodeById.get(selected.id);\n\t\t\tconst executionSegment = snapshot.segmentByNodeId.get(selected.id);\n\t\t\treturn node\n\t\t\t\t? {\n\t\t\t\t\t...node,\n\t\t\t\t\tdebugGroupPath: debugGroupPath(snapshot, node.debugGroupId),\n\t\t\t\t\texecutionSegment,\n\t\t\t\t\treads: node.reads.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t\twrites: node.writes.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'resource':\n\t\t\treturn resolveResourceDetail(snapshot, selected.id);\n\t\tcase 'group':\n\t\t\treturn snapshot.groupByPathKey.get(selected.pathKey);\n\t\tcase 'root':\n\t\t\treturn snapshot.roots.find((root) => root.key === selected.key);\n\t\tcase 'culled': {\n\t\t\tconst culled = snapshot.culledNodes[selected.index];\n\t\t\treturn culled ? {\n\t\t\t\t...culled,\n\t\t\t\tnode: {\n\t\t\t\t\t...culled.node,\n\t\t\t\t\treads: culled.node.reads.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t\twrites: culled.node.writes.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t},\n\t\t\t} : undefined;\n\t\t}\n\t\tcase 'allocation':\n\t\t\treturn snapshot.allocationById.get(selected.id);\n\t\tcase 'segment':\n\t\t\treturn snapshot.segmentByIndex.get(selected.index);\n\t}\n}\n\nexport function selectionExists(snapshot: FrameGraphDebugViewModel, selected: Selection): boolean {\n\tswitch (selected.kind) {\n\t\tcase 'node':\n\t\t\treturn snapshot.nodeById.has(selected.id);\n\t\tcase 'group':\n\t\t\treturn snapshot.groupByPathKey.has(selected.pathKey);\n\t\tcase 'resource':\n\t\t\treturn snapshot.resourceById.has(selected.id);\n\t\tcase 'root':\n\t\t\treturn snapshot.roots.filter((root) => root.key === selected.key).length === 1;\n\t\tcase 'culled':\n\t\t\treturn isValidIndex(selected.index, snapshot.culledNodes.length);\n\t\tcase 'allocation':\n\t\t\treturn snapshot.allocationById.has(selected.id);\n\t\tcase 'segment':\n\t\t\treturn snapshot.segmentByIndex.has(selected.index);\n\t}\n}\n\nfunction resolveResourceDetail(snapshot: FrameGraphDebugViewModel, resourceId: string): unknown {\n\tconst resource = snapshot.resourceById.get(resourceId);\n\tif (!resource) return undefined;\n\tconst accesses = (snapshot.accessesByResourceId.get(resourceId) ?? [])\n\t\t.map((access) => resolveAccessDetail(snapshot, access));\n\treturn {\n\t\t...resource,\n\t\tdebugGroupPath: debugGroupPath(snapshot, resource.debugGroupId),\n\t\twrites: accesses.filter((access) => access.mode === 'write'),\n\t\treads: accesses.filter((access) => access.mode === 'read'),\n\t};\n}\n\nfunction resolveAccessDetail<TAccess extends { readonly textureViewId?: string }>(\n\tsnapshot: FrameGraphDebugViewModel,\n\taccess: TAccess,\n): TAccess & { readonly textureView?: FrameGraphDebugViewModel['protocol']['graph']['textureViews'][number] } {\n\treturn access.textureViewId === undefined\n\t\t? access\n\t\t: {\n\t\t\t...access,\n\t\t\ttextureView: snapshot.textureViewById.get(access.textureViewId),\n\t\t};\n}\n\nfunction debugGroupPath(snapshot: FrameGraphDebugViewModel, groupId: string | undefined): string {\n\tif (groupId === undefined) return '-';\n\treturn snapshot.groupById.get(groupId)?.path.join(' / ') ?? `#${groupId}`;\n}\n\nfunction isValidIndex(index: number, length: number): boolean {\n\treturn Number.isInteger(index) && index >= 0 && index < length;\n}\n"]}
1
+ {"version":3,"file":"panelSelection.js","sourceRoot":"","sources":["../src/panelSelection.ts"],"names":[],"mappings":"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","sourcesContent":["import { rootKey, type FrameGraphDebugViewModel } from './debugCaptureModel.ts';\nimport type { Selection } from './panelTypes.ts';\n\nexport function resolveSelectedDetail(\n\tsnapshot: FrameGraphDebugViewModel,\n\tselected: Selection | undefined,\n): unknown {\n\tif (!selected) return snapshot;\n\n\tswitch (selected.kind) {\n\t\tcase 'node': {\n\t\t\tconst node = snapshot.nodeById.get(selected.id);\n\t\t\tconst executionSegment = snapshot.segmentByNodeId.get(selected.id);\n\t\t\treturn node\n\t\t\t\t? {\n\t\t\t\t\t...node,\n\t\t\t\t\tdebugGroupPath: debugGroupPath(snapshot, node.debugGroupId),\n\t\t\t\t\texecutionSegment,\n\t\t\t\t\treads: node.reads.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t\twrites: node.writes.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase 'resource':\n\t\t\treturn resolveResourceDetail(snapshot, selected.id);\n\t\tcase 'group':\n\t\t\treturn snapshot.groupByPathKey.get(selected.pathKey);\n\t\tcase 'root':\n\t\t\treturn snapshot.roots.find((root) => root.key === selected.key);\n\t\tcase 'culled': {\n\t\t\tconst culled = snapshot.culledById.get(selected.id);\n\t\t\treturn culled ? {\n\t\t\t\t...culled,\n\t\t\t\tnode: {\n\t\t\t\t\t...culled.node,\n\t\t\t\t\treads: culled.node.reads.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t\twrites: culled.node.writes.map((access) => resolveAccessDetail(snapshot, access)),\n\t\t\t\t},\n\t\t\t} : undefined;\n\t\t}\n\t\tcase 'allocation':\n\t\t\treturn snapshot.allocationById.get(selected.id);\n\t\tcase 'segment':\n\t\t\treturn snapshot.segmentByIndex.get(selected.index);\n\t}\n}\n\nexport function selectionExists(snapshot: FrameGraphDebugViewModel, selected: Selection): boolean {\n\tswitch (selected.kind) {\n\t\tcase 'node':\n\t\t\treturn snapshot.nodeById.has(selected.id);\n\t\tcase 'group':\n\t\t\treturn snapshot.groupByPathKey.has(selected.pathKey);\n\t\tcase 'resource':\n\t\t\treturn snapshot.resourceById.has(selected.id);\n\t\tcase 'root':\n\t\t\treturn snapshot.roots.filter((root) => root.key === selected.key).length === 1;\n\t\tcase 'culled':\n\t\t\treturn snapshot.culledById.has(selected.id);\n\t\tcase 'allocation':\n\t\t\treturn snapshot.allocationById.has(selected.id);\n\t\tcase 'segment':\n\t\t\treturn snapshot.segmentByIndex.has(selected.index);\n\t}\n}\n\nfunction resolveResourceDetail(snapshot: FrameGraphDebugViewModel, resourceId: string): unknown {\n\tconst resource = snapshot.resourceById.get(resourceId);\n\tif (!resource) return undefined;\n\tconst accesses = (snapshot.accessesByResourceId.get(resourceId) ?? [])\n\t\t.map((access) => resolveAccessDetail(snapshot, access));\n\treturn {\n\t\t...resource,\n\t\tdebugGroupPath: debugGroupPath(snapshot, resource.debugGroupId),\n\t\twrites: accesses.filter((access) => access.mode === 'write'),\n\t\treads: accesses.filter((access) => access.mode === 'read'),\n\t};\n}\n\nfunction resolveAccessDetail<TAccess extends { readonly textureViewId?: string }>(\n\tsnapshot: FrameGraphDebugViewModel,\n\taccess: TAccess,\n): TAccess & { readonly textureView?: FrameGraphDebugViewModel['protocol']['graph']['textureViews'][number] } {\n\treturn access.textureViewId === undefined\n\t\t? access\n\t\t: {\n\t\t\t...access,\n\t\t\ttextureView: snapshot.textureViewById.get(access.textureViewId),\n\t\t};\n}\n\nfunction debugGroupPath(snapshot: FrameGraphDebugViewModel, groupId: string | undefined): string {\n\tif (groupId === undefined) return '-';\n\treturn snapshot.groupById.get(groupId)?.path.join(' / ') ?? `#${groupId}`;\n}\n\n/** Resolve identity again after a capture, including retained/culled transitions. */\nexport function resolveNodeSelection(snapshot: FrameGraphDebugViewModel, id: string): Selection | undefined {\n\tif (snapshot.nodeById.has(id)) return { kind: 'node', id };\n\tif (snapshot.culledById.has(id)) return { kind: 'culled', id };\n\treturn undefined;\n}\n\nexport type SelectedCanonicalDetail = { readonly path: string; readonly value: unknown };\n\n/** Raw shows the canonical source object, never the presentation model. */\nexport function resolveSelectedCanonicalDetail(\n\tsnapshot: FrameGraphDebugViewModel,\n\tselected: Selection | undefined,\n): SelectedCanonicalDetail | undefined {\n\tif (!selected) return undefined;\n\tconst protocol = snapshot.protocol;\n\tfunction at<T>(values: readonly T[], path: string, predicate: (value: T) => boolean): SelectedCanonicalDetail | undefined {\n\t\tconst index = values.findIndex(predicate);\n\t\treturn index < 0 ? undefined : { path: `${path}[${index}]`, value: values[index] };\n\t}\n\tswitch (selected.kind) {\n\t\tcase 'node':\n\t\tcase 'culled': return at(protocol.graph.nodes, '$.graph.nodes', (node) => node.id === selected.id);\n\t\tcase 'resource': return at(protocol.graph.resources, '$.graph.resources', (resource) => resource.id === selected.id);\n\t\tcase 'group': {\n\t\t\tconst id = snapshot.groupByPathKey.get(selected.pathKey)?.id;\n\t\t\treturn at(protocol.graph.groups, '$.graph.groups', (group) => group.id === id);\n\t\t}\n\t\tcase 'root': return at(protocol.graph.roots, '$.graph.roots', (root) => rootKey(root) === selected.key);\n\t\tcase 'allocation': return protocol.memory.allocationReport.status === 'available'\n\t\t\t? at(protocol.memory.allocationReport.allocations, '$.memory.allocationReport.allocations', (allocation) => allocation.id === selected.id)\n\t\t\t: undefined;\n\t\tcase 'segment': return at(protocol.graph.segments, '$.graph.segments', (segment) => segment.order === selected.index);\n\t}\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { InspectorTheme } from './theme.ts';
2
+ import { type GraphVisualTheme } from './panelVisualTheme.ts';
3
+ /** Own only declarations written by this API, restoring pre-existing inline styles on reset. */
4
+ export declare class InspectorThemeController {
5
+ private readonly root;
6
+ private readonly owned;
7
+ constructor(root: HTMLElement);
8
+ apply(theme: InspectorTheme | null): void;
9
+ destroy(): void;
10
+ }
11
+ /** Resolve through the DOM once per refresh, including var(), color-mix(), and CSS lengths. */
12
+ export declare function resolveGraphTheme(root: HTMLElement): GraphVisualTheme;
13
+ //# sourceMappingURL=panelTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panelTheme.d.ts","sourceRoot":"","sources":["../src/panelTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,YAAY,CAAC;AAE1E,OAAO,EAA6C,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzG,gGAAgG;AAChG,qBAAa,wBAAwB;IAErB,OAAO,CAAC,QAAQ,CAAC,IAAI;IADjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8E;gBACvE,IAAI,EAAE,WAAW;IAE9C,KAAK,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI;IAmBzC,OAAO,IAAI,IAAI;CAClB;AAED,+FAA+F;AAC/F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAoDrE"}
@@ -0,0 +1,104 @@
1
+ import { internalThemeProperty, stormVariables } from "./themeDefinitions.js";
2
+ import { createGraphVisualTheme, defaultThemeValue } from "./panelVisualTheme.js";
3
+ /** Own only declarations written by this API, restoring pre-existing inline styles on reset. */
4
+ export class InspectorThemeController {
5
+ root;
6
+ owned = new Map();
7
+ constructor(root) {
8
+ this.root = root;
9
+ }
10
+ apply(theme) {
11
+ const style = this.root.style;
12
+ for (const [key, entry] of this.owned) {
13
+ if (style.getPropertyValue(key) !== entry.applied || style.getPropertyPriority(key))
14
+ continue;
15
+ if (entry.previous)
16
+ style.setProperty(key, entry.previous, entry.priority);
17
+ else
18
+ style.removeProperty(key);
19
+ }
20
+ this.owned.clear();
21
+ const entries = Object.entries(theme?.variables ?? {}).filter(([key]) => Object.hasOwn(stormVariables, key));
22
+ if (theme?.colorScheme)
23
+ entries.push(['--zfgi-color-scheme', theme.colorScheme]);
24
+ for (const [key, value] of entries) {
25
+ if (typeof value !== 'string')
26
+ continue;
27
+ const previous = style.getPropertyValue(key);
28
+ const priority = style.getPropertyPriority(key);
29
+ style.setProperty(key, value);
30
+ this.owned.set(key, { previous, priority, applied: style.getPropertyValue(key) });
31
+ }
32
+ }
33
+ destroy() { this.owned.clear(); }
34
+ }
35
+ /** Resolve through the DOM once per refresh, including var(), color-mix(), and CSS lengths. */
36
+ export function resolveGraphTheme(root) {
37
+ const document = root.ownerDocument;
38
+ const view = document?.defaultView;
39
+ if (!view || !root.isConnected)
40
+ return createGraphVisualTheme();
41
+ const styles = view.getComputedStyle(root);
42
+ const probe = document.createElement('span');
43
+ probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none;width:0;height:0;overflow:hidden;';
44
+ probe.setAttribute('aria-hidden', 'true');
45
+ root.appendChild(probe);
46
+ const cache = new Map();
47
+ let context;
48
+ const color = (value) => {
49
+ probe.style.color = '';
50
+ probe.style.color = value;
51
+ if (!probe.style.color)
52
+ return undefined;
53
+ const resolved = view.getComputedStyle(probe).color;
54
+ if (/^(#[\da-f]{3,8}|rgba?\([\d.,\s]+\))$/i.test(resolved))
55
+ return resolved;
56
+ // Normalize newer CSS color spaces into sRGB supported by Cytoscape.
57
+ if (context === undefined) {
58
+ const canvas = document.createElement('canvas');
59
+ canvas.width = canvas.height = 1;
60
+ context = canvas.getContext('2d', { willReadFrequently: true });
61
+ }
62
+ if (!context)
63
+ return undefined;
64
+ context.clearRect(0, 0, 1, 1);
65
+ context.fillStyle = resolved;
66
+ context.fillRect(0, 0, 1, 1);
67
+ const [r, g, b, a] = context.getImageData(0, 0, 1, 1).data;
68
+ return `rgba(${r}, ${g}, ${b}, ${a / 255})`;
69
+ };
70
+ const read = (key) => {
71
+ const cached = cache.get(key);
72
+ if (cached !== undefined)
73
+ return cached;
74
+ const value = styles.getPropertyValue(internalThemeProperty(key)).trim() || defaultThemeValue(key);
75
+ let result = value;
76
+ if (key.endsWith('font-family')) {
77
+ probe.style.fontFamily = value;
78
+ result = view.getComputedStyle(probe).fontFamily;
79
+ }
80
+ else if (key.endsWith('size') || key.endsWith('width')) {
81
+ probe.style.fontSize = '';
82
+ probe.style.fontSize = value;
83
+ result = probe.style.fontSize ? view.getComputedStyle(probe).fontSize : defaultThemeValue(key);
84
+ if (!(parseFloat(result) > 0))
85
+ result = defaultThemeValue(key);
86
+ }
87
+ else if (key.endsWith('opacity') || key.endsWith('scale')) {
88
+ const n = Number(value);
89
+ result = Number.isFinite(n) && n >= 0 && (!key.endsWith('opacity') || n <= 1) ? value : defaultThemeValue(key);
90
+ }
91
+ else {
92
+ result = color(value) ?? defaultThemeValue(key);
93
+ }
94
+ cache.set(key, result);
95
+ return result;
96
+ };
97
+ try {
98
+ return createGraphVisualTheme(read);
99
+ }
100
+ finally {
101
+ probe.remove();
102
+ }
103
+ }
104
+ //# sourceMappingURL=panelTheme.js.map