mcp-react-toolkit 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/README.md +24 -24
  2. package/node_modules/@mcp-showcase/shared/build/McpServerBase.d.ts +13 -0
  3. package/node_modules/@mcp-showcase/shared/build/McpServerBase.d.ts.map +1 -1
  4. package/node_modules/@mcp-showcase/shared/build/McpServerBase.js +40 -0
  5. package/node_modules/@mcp-showcase/shared/build/McpServerBase.js.map +1 -1
  6. package/node_modules/@mcp-showcase/shared/build/types.d.ts +11 -0
  7. package/node_modules/@mcp-showcase/shared/build/types.d.ts.map +1 -1
  8. package/node_modules/@mcp-showcase/shared/src/McpServerBase.ts +45 -0
  9. package/node_modules/@mcp-showcase/shared/src/types.ts +12 -0
  10. package/node_modules/@mcp-showcase/ui-kit/README.md +30 -0
  11. package/node_modules/@mcp-showcase/ui-kit/build/components.d.ts +10 -0
  12. package/node_modules/@mcp-showcase/ui-kit/build/components.d.ts.map +1 -0
  13. package/node_modules/@mcp-showcase/ui-kit/build/components.js +177 -0
  14. package/node_modules/@mcp-showcase/ui-kit/build/components.js.map +1 -0
  15. package/node_modules/@mcp-showcase/ui-kit/build/escape.d.ts +3 -0
  16. package/node_modules/@mcp-showcase/ui-kit/build/escape.d.ts.map +1 -0
  17. package/node_modules/@mcp-showcase/ui-kit/build/escape.js +10 -0
  18. package/node_modules/@mcp-showcase/ui-kit/build/escape.js.map +1 -0
  19. package/node_modules/@mcp-showcase/ui-kit/build/fixture.d.ts +4 -0
  20. package/node_modules/@mcp-showcase/ui-kit/build/fixture.d.ts.map +1 -0
  21. package/node_modules/@mcp-showcase/ui-kit/build/fixture.js +52 -0
  22. package/node_modules/@mcp-showcase/ui-kit/build/fixture.js.map +1 -0
  23. package/node_modules/@mcp-showcase/ui-kit/build/generate-template.d.ts +2 -0
  24. package/node_modules/@mcp-showcase/ui-kit/build/generate-template.d.ts.map +1 -0
  25. package/node_modules/@mcp-showcase/ui-kit/build/generate-template.js +19 -0
  26. package/node_modules/@mcp-showcase/ui-kit/build/generate-template.js.map +1 -0
  27. package/node_modules/@mcp-showcase/ui-kit/build/index.d.ts +6 -0
  28. package/node_modules/@mcp-showcase/ui-kit/build/index.d.ts.map +1 -0
  29. package/node_modules/@mcp-showcase/ui-kit/build/index.js +7 -0
  30. package/node_modules/@mcp-showcase/ui-kit/build/index.js.map +1 -0
  31. package/node_modules/@mcp-showcase/ui-kit/build/render.d.ts +3 -0
  32. package/node_modules/@mcp-showcase/ui-kit/build/render.d.ts.map +1 -0
  33. package/node_modules/@mcp-showcase/ui-kit/build/render.js +38 -0
  34. package/node_modules/@mcp-showcase/ui-kit/build/render.js.map +1 -0
  35. package/node_modules/@mcp-showcase/ui-kit/build/result-components.d.ts +9 -0
  36. package/node_modules/@mcp-showcase/ui-kit/build/result-components.d.ts.map +1 -0
  37. package/node_modules/@mcp-showcase/ui-kit/build/result-components.js +105 -0
  38. package/node_modules/@mcp-showcase/ui-kit/build/result-components.js.map +1 -0
  39. package/node_modules/@mcp-showcase/ui-kit/build/result-fixture.d.ts +4 -0
  40. package/node_modules/@mcp-showcase/ui-kit/build/result-fixture.d.ts.map +1 -0
  41. package/node_modules/@mcp-showcase/ui-kit/build/result-fixture.js +39 -0
  42. package/node_modules/@mcp-showcase/ui-kit/build/result-fixture.js.map +1 -0
  43. package/node_modules/@mcp-showcase/ui-kit/build/result-render.d.ts +3 -0
  44. package/node_modules/@mcp-showcase/ui-kit/build/result-render.d.ts.map +1 -0
  45. package/node_modules/@mcp-showcase/ui-kit/build/result-render.js +37 -0
  46. package/node_modules/@mcp-showcase/ui-kit/build/result-render.js.map +1 -0
  47. package/node_modules/@mcp-showcase/ui-kit/build/result-runtime.d.ts +2 -0
  48. package/node_modules/@mcp-showcase/ui-kit/build/result-runtime.d.ts.map +1 -0
  49. package/node_modules/@mcp-showcase/ui-kit/build/result-runtime.js +72 -0
  50. package/node_modules/@mcp-showcase/ui-kit/build/result-runtime.js.map +1 -0
  51. package/node_modules/@mcp-showcase/ui-kit/build/runtime.d.ts +2 -0
  52. package/node_modules/@mcp-showcase/ui-kit/build/runtime.d.ts.map +1 -0
  53. package/node_modules/@mcp-showcase/ui-kit/build/runtime.js +221 -0
  54. package/node_modules/@mcp-showcase/ui-kit/build/runtime.js.map +1 -0
  55. package/node_modules/@mcp-showcase/ui-kit/build/theme.d.ts +2 -0
  56. package/node_modules/@mcp-showcase/ui-kit/build/theme.d.ts.map +1 -0
  57. package/node_modules/@mcp-showcase/ui-kit/build/theme.js +278 -0
  58. package/node_modules/@mcp-showcase/ui-kit/build/theme.js.map +1 -0
  59. package/node_modules/@mcp-showcase/ui-kit/build/types.d.ts +113 -0
  60. package/node_modules/@mcp-showcase/ui-kit/build/types.d.ts.map +1 -0
  61. package/node_modules/@mcp-showcase/ui-kit/build/types.js +35 -0
  62. package/node_modules/@mcp-showcase/ui-kit/build/types.js.map +1 -0
  63. package/node_modules/@mcp-showcase/ui-kit/demo/index.html +653 -0
  64. package/node_modules/@mcp-showcase/ui-kit/demo/result.html +445 -0
  65. package/node_modules/@mcp-showcase/ui-kit/package.json +19 -0
  66. package/node_modules/@mcp-showcase/ui-kit/src/components.ts +191 -0
  67. package/node_modules/@mcp-showcase/ui-kit/src/escape.ts +9 -0
  68. package/node_modules/@mcp-showcase/ui-kit/src/fixture.ts +53 -0
  69. package/node_modules/@mcp-showcase/ui-kit/src/generate-template.ts +21 -0
  70. package/node_modules/@mcp-showcase/ui-kit/src/index.test.ts +72 -0
  71. package/node_modules/@mcp-showcase/ui-kit/src/index.ts +6 -0
  72. package/node_modules/@mcp-showcase/ui-kit/src/render.ts +48 -0
  73. package/node_modules/@mcp-showcase/ui-kit/src/result-components.ts +112 -0
  74. package/node_modules/@mcp-showcase/ui-kit/src/result-fixture.ts +40 -0
  75. package/node_modules/@mcp-showcase/ui-kit/src/result-render.test.ts +47 -0
  76. package/node_modules/@mcp-showcase/ui-kit/src/result-render.ts +47 -0
  77. package/node_modules/@mcp-showcase/ui-kit/src/result-runtime.ts +72 -0
  78. package/node_modules/@mcp-showcase/ui-kit/src/runtime.smoke.test.ts +103 -0
  79. package/node_modules/@mcp-showcase/ui-kit/src/runtime.ts +221 -0
  80. package/node_modules/@mcp-showcase/ui-kit/src/theme.ts +278 -0
  81. package/node_modules/@mcp-showcase/ui-kit/src/types.ts +140 -0
  82. package/node_modules/@mcp-showcase/ui-kit/tsconfig.json +9 -0
  83. package/package.json +6 -4
  84. package/tools/accessibility-checker/build/health-report.d.ts +27 -0
  85. package/tools/accessibility-checker/build/health-report.d.ts.map +1 -0
  86. package/tools/accessibility-checker/build/health-report.js +140 -0
  87. package/tools/accessibility-checker/build/health-report.js.map +1 -0
  88. package/tools/accessibility-checker/build/index.js +7 -1
  89. package/tools/accessibility-checker/build/index.js.map +1 -1
  90. package/tools/accessibility-checker/package.json +1 -0
  91. package/tools/code-modernizer/build/index.js +60 -44
  92. package/tools/code-modernizer/build/index.js.map +1 -1
  93. package/tools/code-modernizer/build/result-report.d.ts +24 -0
  94. package/tools/code-modernizer/build/result-report.d.ts.map +1 -0
  95. package/tools/code-modernizer/build/result-report.js +101 -0
  96. package/tools/code-modernizer/build/result-report.js.map +1 -0
  97. package/tools/code-modernizer/package.json +2 -0
  98. package/tools/component-factory/build/index.js +7 -1
  99. package/tools/component-factory/build/index.js.map +1 -1
  100. package/tools/component-factory/build/result-report.d.ts +11 -0
  101. package/tools/component-factory/build/result-report.d.ts.map +1 -0
  102. package/tools/component-factory/build/result-report.js +104 -0
  103. package/tools/component-factory/build/result-report.js.map +1 -0
  104. package/tools/component-factory/package.json +1 -0
  105. package/tools/component-fixer/build/index.js +6 -6
  106. package/tools/component-fixer/build/index.js.map +1 -1
  107. package/tools/component-fixer/build/result-report.d.ts +37 -0
  108. package/tools/component-fixer/build/result-report.d.ts.map +1 -0
  109. package/tools/component-fixer/build/result-report.js +106 -0
  110. package/tools/component-fixer/build/result-report.js.map +1 -0
  111. package/tools/component-fixer/package.json +1 -0
  112. package/tools/component-reviewer/build/health-report.d.ts +37 -0
  113. package/tools/component-reviewer/build/health-report.d.ts.map +1 -0
  114. package/tools/component-reviewer/build/health-report.js +116 -0
  115. package/tools/component-reviewer/build/health-report.js.map +1 -0
  116. package/tools/component-reviewer/build/index.d.ts.map +1 -1
  117. package/tools/component-reviewer/build/index.js +7 -6
  118. package/tools/component-reviewer/build/index.js.map +1 -1
  119. package/tools/component-reviewer/package.json +1 -0
  120. package/tools/dep-auditor/build/health-report.d.ts +16 -0
  121. package/tools/dep-auditor/build/health-report.d.ts.map +1 -0
  122. package/tools/dep-auditor/build/health-report.js +187 -0
  123. package/tools/dep-auditor/build/health-report.js.map +1 -0
  124. package/tools/dep-auditor/build/index.d.ts.map +1 -1
  125. package/tools/dep-auditor/build/index.js +7 -1
  126. package/tools/dep-auditor/build/index.js.map +1 -1
  127. package/tools/dep-auditor/package.json +1 -0
  128. package/tools/generate-tests/build/index.js +8 -1
  129. package/tools/generate-tests/build/index.js.map +1 -1
  130. package/tools/generate-tests/build/result-report.d.ts +14 -0
  131. package/tools/generate-tests/build/result-report.d.ts.map +1 -0
  132. package/tools/generate-tests/build/result-report.js +124 -0
  133. package/tools/generate-tests/build/result-report.js.map +1 -0
  134. package/tools/generate-tests/package.json +1 -0
  135. package/tools/legacy-analyzer/build/health-report.d.ts +4 -0
  136. package/tools/legacy-analyzer/build/health-report.d.ts.map +1 -0
  137. package/tools/legacy-analyzer/build/health-report.js +164 -0
  138. package/tools/legacy-analyzer/build/health-report.js.map +1 -0
  139. package/tools/legacy-analyzer/build/index.js +15 -1
  140. package/tools/legacy-analyzer/build/index.js.map +1 -1
  141. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.d.ts.map +1 -1
  142. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.js +3 -8
  143. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.js.map +1 -1
  144. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.d.ts.map +1 -1
  145. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.js +25 -3
  146. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.js.map +1 -1
  147. package/tools/legacy-analyzer/package.json +1 -0
  148. package/tools/lighthouse-runner/build/health-report.d.ts +14 -0
  149. package/tools/lighthouse-runner/build/health-report.d.ts.map +1 -0
  150. package/tools/lighthouse-runner/build/health-report.js +138 -0
  151. package/tools/lighthouse-runner/build/health-report.js.map +1 -0
  152. package/tools/lighthouse-runner/build/index.d.ts.map +1 -1
  153. package/tools/lighthouse-runner/build/index.js +7 -1
  154. package/tools/lighthouse-runner/build/index.js.map +1 -1
  155. package/tools/lighthouse-runner/package.json +1 -0
  156. package/tools/monorepo-manager/build/index.js +9 -1
  157. package/tools/monorepo-manager/build/index.js.map +1 -1
  158. package/tools/monorepo-manager/build/result-report.d.ts +20 -0
  159. package/tools/monorepo-manager/build/result-report.d.ts.map +1 -0
  160. package/tools/monorepo-manager/build/result-report.js +84 -0
  161. package/tools/monorepo-manager/build/result-report.js.map +1 -0
  162. package/tools/monorepo-manager/package.json +1 -0
  163. package/tools/performance-audit/build/health-report.d.ts +30 -0
  164. package/tools/performance-audit/build/health-report.d.ts.map +1 -0
  165. package/tools/performance-audit/build/health-report.js +152 -0
  166. package/tools/performance-audit/build/health-report.js.map +1 -0
  167. package/tools/performance-audit/build/index.d.ts.map +1 -1
  168. package/tools/performance-audit/build/index.js +7 -1
  169. package/tools/performance-audit/build/index.js.map +1 -1
  170. package/tools/performance-audit/package.json +1 -0
  171. package/tools/quality-pipeline/build/health-report.d.ts +11 -0
  172. package/tools/quality-pipeline/build/health-report.d.ts.map +1 -0
  173. package/tools/quality-pipeline/build/health-report.js +137 -0
  174. package/tools/quality-pipeline/build/health-report.js.map +1 -0
  175. package/tools/quality-pipeline/build/index.js +7 -1
  176. package/tools/quality-pipeline/build/index.js.map +1 -1
  177. package/tools/quality-pipeline/package.json +1 -0
  178. package/tools/render-analyzer/build/health-report.d.ts +33 -0
  179. package/tools/render-analyzer/build/health-report.d.ts.map +1 -0
  180. package/tools/render-analyzer/build/health-report.js +142 -0
  181. package/tools/render-analyzer/build/health-report.js.map +1 -0
  182. package/tools/render-analyzer/build/index.d.ts.map +1 -1
  183. package/tools/render-analyzer/build/index.js +7 -1
  184. package/tools/render-analyzer/build/index.js.map +1 -1
  185. package/tools/render-analyzer/package.json +1 -0
  186. package/tools/shared/build/McpServerBase.d.ts +13 -0
  187. package/tools/shared/build/McpServerBase.d.ts.map +1 -1
  188. package/tools/shared/build/McpServerBase.js +40 -0
  189. package/tools/shared/build/McpServerBase.js.map +1 -1
  190. package/tools/shared/build/types.d.ts +11 -0
  191. package/tools/shared/build/types.d.ts.map +1 -1
  192. package/tools/storybook-generator/build/index.d.ts.map +1 -1
  193. package/tools/storybook-generator/build/index.js +9 -1
  194. package/tools/storybook-generator/build/index.js.map +1 -1
  195. package/tools/storybook-generator/build/result-report.d.ts +22 -0
  196. package/tools/storybook-generator/build/result-report.d.ts.map +1 -0
  197. package/tools/storybook-generator/build/result-report.js +77 -0
  198. package/tools/storybook-generator/build/result-report.js.map +1 -0
  199. package/tools/storybook-generator/package.json +1 -0
  200. package/tools/test-gap-analyzer/build/health-report.d.ts +34 -0
  201. package/tools/test-gap-analyzer/build/health-report.d.ts.map +1 -0
  202. package/tools/test-gap-analyzer/build/health-report.js +190 -0
  203. package/tools/test-gap-analyzer/build/health-report.js.map +1 -0
  204. package/tools/test-gap-analyzer/build/index.d.ts.map +1 -1
  205. package/tools/test-gap-analyzer/build/index.js +7 -1
  206. package/tools/test-gap-analyzer/build/index.js.map +1 -1
  207. package/tools/test-gap-analyzer/package.json +1 -0
  208. package/tools/typescript-enforcer/build/health-report.d.ts +33 -0
  209. package/tools/typescript-enforcer/build/health-report.d.ts.map +1 -0
  210. package/tools/typescript-enforcer/build/health-report.js +143 -0
  211. package/tools/typescript-enforcer/build/health-report.js.map +1 -0
  212. package/tools/typescript-enforcer/build/index.js +6 -1
  213. package/tools/typescript-enforcer/build/index.js.map +1 -1
  214. package/tools/typescript-enforcer/package.json +1 -0
  215. package/tools/ui-kit/README.md +30 -0
  216. package/tools/ui-kit/build/components.d.ts +10 -0
  217. package/tools/ui-kit/build/components.d.ts.map +1 -0
  218. package/tools/ui-kit/build/components.js +177 -0
  219. package/tools/ui-kit/build/components.js.map +1 -0
  220. package/tools/ui-kit/build/escape.d.ts +3 -0
  221. package/tools/ui-kit/build/escape.d.ts.map +1 -0
  222. package/tools/ui-kit/build/escape.js +10 -0
  223. package/tools/ui-kit/build/escape.js.map +1 -0
  224. package/tools/ui-kit/build/fixture.d.ts +4 -0
  225. package/tools/ui-kit/build/fixture.d.ts.map +1 -0
  226. package/tools/ui-kit/build/fixture.js +52 -0
  227. package/tools/ui-kit/build/fixture.js.map +1 -0
  228. package/tools/ui-kit/build/generate-template.d.ts +2 -0
  229. package/tools/ui-kit/build/generate-template.d.ts.map +1 -0
  230. package/tools/ui-kit/build/generate-template.js +19 -0
  231. package/tools/ui-kit/build/generate-template.js.map +1 -0
  232. package/tools/ui-kit/build/index.d.ts +6 -0
  233. package/tools/ui-kit/build/index.d.ts.map +1 -0
  234. package/tools/ui-kit/build/index.js +7 -0
  235. package/tools/ui-kit/build/index.js.map +1 -0
  236. package/tools/ui-kit/build/render.d.ts +3 -0
  237. package/tools/ui-kit/build/render.d.ts.map +1 -0
  238. package/tools/ui-kit/build/render.js +38 -0
  239. package/tools/ui-kit/build/render.js.map +1 -0
  240. package/tools/ui-kit/build/result-components.d.ts +9 -0
  241. package/tools/ui-kit/build/result-components.d.ts.map +1 -0
  242. package/tools/ui-kit/build/result-components.js +105 -0
  243. package/tools/ui-kit/build/result-components.js.map +1 -0
  244. package/tools/ui-kit/build/result-fixture.d.ts +4 -0
  245. package/tools/ui-kit/build/result-fixture.d.ts.map +1 -0
  246. package/tools/ui-kit/build/result-fixture.js +39 -0
  247. package/tools/ui-kit/build/result-fixture.js.map +1 -0
  248. package/tools/ui-kit/build/result-render.d.ts +3 -0
  249. package/tools/ui-kit/build/result-render.d.ts.map +1 -0
  250. package/tools/ui-kit/build/result-render.js +37 -0
  251. package/tools/ui-kit/build/result-render.js.map +1 -0
  252. package/tools/ui-kit/build/result-runtime.d.ts +2 -0
  253. package/tools/ui-kit/build/result-runtime.d.ts.map +1 -0
  254. package/tools/ui-kit/build/result-runtime.js +72 -0
  255. package/tools/ui-kit/build/result-runtime.js.map +1 -0
  256. package/tools/ui-kit/build/runtime.d.ts +2 -0
  257. package/tools/ui-kit/build/runtime.d.ts.map +1 -0
  258. package/tools/ui-kit/build/runtime.js +221 -0
  259. package/tools/ui-kit/build/runtime.js.map +1 -0
  260. package/tools/ui-kit/build/theme.d.ts +2 -0
  261. package/tools/ui-kit/build/theme.d.ts.map +1 -0
  262. package/tools/ui-kit/build/theme.js +278 -0
  263. package/tools/ui-kit/build/theme.js.map +1 -0
  264. package/tools/ui-kit/build/types.d.ts +113 -0
  265. package/tools/ui-kit/build/types.d.ts.map +1 -0
  266. package/tools/ui-kit/build/types.js +35 -0
  267. package/tools/ui-kit/build/types.js.map +1 -0
  268. package/tools/ui-kit/package.json +19 -0
@@ -0,0 +1,30 @@
1
+ # @mcp-showcase/ui-kit
2
+
3
+ Reusable **single-file HTML report UI** for MCP tools — dependency-free, dual-theme (light/dark), and agentic. Any tool that maps its output to the `HealthReport` schema gets a premium interactive dashboard that renders inside an MCP host (MCP Apps / `ui://`) **and** opens standalone in a browser.
4
+
5
+ Flagship producer: `legacy-analyzer` → **Codebase Health Studio**.
6
+
7
+ ## Exports
8
+
9
+ ```ts
10
+ import { renderReportHTML, SAMPLE_REPORT, type HealthReport } from "@mcp-showcase/ui-kit";
11
+
12
+ const html = renderReportHTML(myReport); // one self-contained <!doctype html> string
13
+ ```
14
+
15
+ - `renderReportHTML(report: HealthReport): string` — styles, runtime and data all inlined (no external requests, safe for a sandboxed iframe).
16
+ - `HealthReport` / `ReportIssue` / `ReportCategory` / `ReportAction` — the tool-agnostic contract.
17
+ - `SAMPLE_REPORT` — fixture used by the standalone demo (`npm run build` → `demo/index.html`).
18
+
19
+ ## Surfaces (DataAdapter)
20
+
21
+ The runtime detects where it is running:
22
+
23
+ - **Embedded in an MCP host** → action buttons `postMessage` MCP-UI intents (`tool` / `prompt`) to the parent so the agent runs the fix.
24
+ - **Standalone browser tab** → graceful fallback: copies a ready-to-paste prompt to the clipboard.
25
+
26
+ Data is read from `window.__REPORT__`, then an inline `#report-data` script, then a `?data=` base64 URL param.
27
+
28
+ ## Why no framework
29
+
30
+ The artifact must be a tiny, robust, self-contained file for a sandboxed iframe. Plain CSS + browser JS keeps the bundle ~38 KB with zero supply chain. The React/Vite path is a documented future swap if richer interactivity is needed.
@@ -0,0 +1,10 @@
1
+ import { HealthReport, ReportAction } from "./types.js";
2
+ export declare function buildHeader(report: HealthReport): string;
3
+ export declare function buildHero(report: HealthReport): string;
4
+ declare function actionButtons(actions: ReportAction[] | undefined, primaryFirst?: boolean): string;
5
+ export declare function buildFixFirst(report: HealthReport): string;
6
+ export declare function buildCategories(report: HealthReport): string;
7
+ export declare function buildTriageShell(report: HealthReport): string;
8
+ export declare function buildChrome(): string;
9
+ export { actionButtons };
10
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,YAAY,EAEZ,YAAY,EAGb,MAAM,YAAY,CAAC;AAcpB,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAsBxD;AAsBD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAkBtD;AAED,iBAAS,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,YAAY,UAAQ,GAAG,MAAM,CAQxF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAiB1D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAkB5D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA+B7D;AAED,wBAAgB,WAAW,IAAI,MAAM,CAcpC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,177 @@
1
+ // ============================================================================
2
+ // SERVER-SIDE COMPONENT BUILDERS — pure string -> HTML. No framework.
3
+ // The hero, category cards and fix-first queue are rendered statically for an
4
+ // instant premium paint; the interactive triage table + drawer are hydrated
5
+ // client-side by runtime.ts from the injected report data.
6
+ // ============================================================================
7
+ import { esc } from "./escape.js";
8
+ import { scoreToBand, scoreToGrade, } from "./types.js";
9
+ const SUN = `<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>`;
10
+ const MOON = `<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>`;
11
+ const SEARCH = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>`;
12
+ function verdict(score) {
13
+ if (score >= 85)
14
+ return "Healthy & well-structured";
15
+ if (score >= 70)
16
+ return "Solid, with a few rough edges";
17
+ if (score >= 55)
18
+ return "Workable, but carrying debt";
19
+ if (score >= 40)
20
+ return "Significant tech debt";
21
+ return "High-risk — needs intervention";
22
+ }
23
+ export function buildHeader(report) {
24
+ return /* html */ `
25
+ <header class="hdr">
26
+ <div class="brand">
27
+ <span class="dot" aria-hidden="true">
28
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
29
+ </span>
30
+ <div style="min-width:0">
31
+ <h1>${esc(report.meta.title)}</h1>
32
+ <p class="sub">${esc(report.meta.target)}</p>
33
+ </div>
34
+ </div>
35
+ <div class="hdr-actions">
36
+ <button class="btn icon" id="theme-toggle" type="button" aria-label="Toggle colour theme" title="Toggle theme">
37
+ <span class="theme-sun" hidden>${SUN}</span><span class="theme-moon">${MOON}</span>
38
+ </button>
39
+ <button class="btn" id="export-btn" type="button" title="Copy report as Markdown">
40
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
41
+ Export
42
+ </button>
43
+ </div>
44
+ </header>`;
45
+ }
46
+ function gauge(score) {
47
+ const r = 64;
48
+ const circ = 2 * Math.PI * r;
49
+ const pct = Math.max(0, Math.min(100, score)) / 100;
50
+ const offset = circ * (1 - pct);
51
+ return /* html */ `
52
+ <div class="gauge" role="img" aria-label="Health score ${esc(score)} out of 100">
53
+ <svg width="148" height="148" viewBox="0 0 148 148">
54
+ <circle class="track" cx="74" cy="74" r="${r}" stroke-width="11"/>
55
+ <circle class="arc" cx="74" cy="74" r="${r}" stroke-width="11"
56
+ stroke-dasharray="${circ.toFixed(1)}" stroke-dashoffset="${circ.toFixed(1)}"
57
+ data-target="${offset.toFixed(1)}"/>
58
+ </svg>
59
+ <div class="center">
60
+ <div class="score num" data-count="${esc(score)}">0</div>
61
+ <div class="of">/ 100</div>
62
+ </div>
63
+ </div>`;
64
+ }
65
+ export function buildHero(report) {
66
+ const band = scoreToBand(report.score);
67
+ const grade = scoreToGrade(report.score);
68
+ const chips = (report.chips ?? [])
69
+ .map((c) => `<span class="chip"><span>${esc(c.label)}</span><b>${esc(c.value)}</b></span>`)
70
+ .join("");
71
+ return /* html */ `
72
+ <section class="hero" data-band="${band}">
73
+ ${gauge(report.score)}
74
+ <div class="hero-meta">
75
+ <div class="grade-row">
76
+ <span class="grade">Grade ${esc(grade)}</span>
77
+ <span class="verdict">${esc(verdict(report.score))}</span>
78
+ </div>
79
+ <p>${esc(report.totalIssues)} issue${report.totalIssues === 1 ? "" : "s"} found across ${esc(report.categories.length)} areas${report.meta.subtitle ? " · " + esc(report.meta.subtitle) : ""}.</p>
80
+ <div class="chips">${chips}</div>
81
+ </div>
82
+ </section>`;
83
+ }
84
+ function actionButtons(actions, primaryFirst = false) {
85
+ if (!actions || !actions.length)
86
+ return "";
87
+ return actions
88
+ .map((a, i) => {
89
+ const cls = primaryFirst && i === 0 ? "btn primary" : "btn";
90
+ return `<button class="${cls}" type="button" data-action="${esc(a.id)}">${esc(a.label)}</button>`;
91
+ })
92
+ .join("");
93
+ }
94
+ export function buildFixFirst(report) {
95
+ const actions = report.topActions ?? [];
96
+ if (!actions.length)
97
+ return "";
98
+ const items = actions
99
+ .map((a, i) => {
100
+ const sub = a.kind === "tool" ? `Runs ${esc(a.tool)}` : a.kind === "prompt" ? "Asks the agent" : "Opens link";
101
+ return /* html */ `
102
+ <div class="qitem" data-action="${esc(a.id)}" role="button" tabindex="0">
103
+ <span class="rank num">${i + 1}</span>
104
+ <span class="qt"><span class="t">${esc(a.label)}</span><span class="s">${sub}</span></span>
105
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color:var(--faint)"><path d="m9 18 6-6-6-6"/></svg>
106
+ </div>`;
107
+ })
108
+ .join("");
109
+ return /* html */ `
110
+ <div class="sec"><h2>Fix-first queue</h2><span class="count">${actions.length} prioritised</span></div>
111
+ <div class="queue">${items}</div>`;
112
+ }
113
+ export function buildCategories(report) {
114
+ const card = (c) => {
115
+ const hasScore = typeof c.score === "number";
116
+ const pct = hasScore ? Math.max(0, Math.min(100, c.score)) : 0;
117
+ return /* html */ `
118
+ <div class="card" data-category="${esc(c.id)}" role="button" tabindex="0" aria-label="Filter issues by ${esc(c.name)}">
119
+ <div class="top">
120
+ <span class="name">${esc(c.name)}</span>
121
+ <span class="badge ${esc(c.status)}">${hasScore ? esc(pct) : esc(c.status)}</span>
122
+ </div>
123
+ <div class="sum">${esc(c.summary)}</div>
124
+ ${hasScore ? `<div class="bar"><i class="${esc(c.status)}" data-w="${pct}" style="width:0"></i></div>` : ""}
125
+ <div class="foot"><span>${esc(c.issueCount)} issue${c.issueCount === 1 ? "" : "s"}</span><span>View →</span></div>
126
+ </div>`;
127
+ };
128
+ return /* html */ `
129
+ <div class="sec"><h2>Areas</h2><span class="count">${report.categories.length} analysed</span></div>
130
+ <div class="cards">${report.categories.map(card).join("")}</div>`;
131
+ }
132
+ export function buildTriageShell(report) {
133
+ const sevFilters = ["all", "critical", "high", "medium", "low"]
134
+ .map((s, i) => `<button type="button" data-sev="${s}" aria-pressed="${i === 0 ? "true" : "false"}">${s[0].toUpperCase() + s.slice(1)}</button>`)
135
+ .join("");
136
+ return /* html */ `
137
+ <div class="sec"><h2>Issues</h2><span class="count" id="issue-count">${report.issues.length} total</span></div>
138
+ <div class="toolbar">
139
+ <label class="search">
140
+ ${SEARCH}
141
+ <input id="search" type="search" placeholder="Search issues, files, categories…" aria-label="Search issues"/>
142
+ </label>
143
+ <div class="filter" role="group" aria-label="Filter by severity">${sevFilters}</div>
144
+ </div>
145
+ <div class="table-card">
146
+ <table>
147
+ <thead><tr>
148
+ <th data-sort="severity" aria-sort="descending">Severity<span class="arr">▼</span></th>
149
+ <th data-sort="title">Issue<span class="arr">▼</span></th>
150
+ <th data-sort="category">Area<span class="arr">▼</span></th>
151
+ <th data-sort="file">File<span class="arr">▼</span></th>
152
+ </tr></thead>
153
+ <tbody id="rows"></tbody>
154
+ </table>
155
+ <div class="empty" id="empty" hidden>
156
+ <div class="big">Nothing matches</div>
157
+ <div>Try clearing the search or severity filter.</div>
158
+ </div>
159
+ </div>`;
160
+ }
161
+ export function buildChrome() {
162
+ return /* html */ `
163
+ <div class="scrim" id="scrim"></div>
164
+ <aside class="drawer" id="drawer" role="dialog" aria-modal="true" aria-labelledby="d-title">
165
+ <header>
166
+ <h3 id="d-title"></h3>
167
+ <button class="btn icon" id="d-close" type="button" aria-label="Close detail">
168
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
169
+ </button>
170
+ </header>
171
+ <div class="body" id="d-body"></div>
172
+ <div class="acts" id="d-acts"></div>
173
+ </aside>
174
+ <div class="toast" id="toast" role="status" aria-live="polite"></div>`;
175
+ }
176
+ export { actionButtons };
177
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,sEAAsE;AACtE,8EAA8E;AAC9E,4EAA4E;AAC5E,2DAA2D;AAC3D,+EAA+E;AAE/E,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAIL,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,MAAM,GAAG,GAAG,+QAA+Q,CAAC;AAC5R,MAAM,IAAI,GAAG,kNAAkN,CAAC;AAChO,MAAM,MAAM,GAAG,2LAA2L,CAAC;AAE3M,SAAS,OAAO,CAAC,KAAa;IAC5B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,2BAA2B,CAAC;IACpD,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,+BAA+B,CAAC;IACxD,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,6BAA6B,CAAC;IACtD,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,uBAAuB,CAAC;IAChD,OAAO,gCAAgC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAoB;IAC9C,OAAO,UAAU,CAAC;;;;;;;cAON,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;yBACX,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;;;;;yCAKP,GAAG,mCAAmC,IAAI;;;;;;;YAOvE,CAAC;AACb,CAAC;AAED,SAAS,KAAK,CAAC,KAAa;IAC1B,MAAM,CAAC,GAAG,EAAE,CAAC;IACb,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC;2DACuC,GAAG,CAAC,KAAK,CAAC;;iDAEpB,CAAC;+CACH,CAAC;4BACpB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;uBAC3D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;;;2CAGG,GAAG,CAAC,KAAK,CAAC;;;SAG5C,CAAC;AACV,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAoB;IAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,4BAA4B,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC;SAC1F,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,UAAU,CAAC;qCACiB,IAAI;MACnC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;;;oCAGW,GAAG,CAAC,KAAK,CAAC;gCACd,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;;WAE/C,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,MAAM,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,iBAAiB,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;2BACvK,KAAK;;aAEnB,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,OAAmC,EAAE,YAAY,GAAG,KAAK;IAC9E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC3C,OAAO,OAAO;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACZ,MAAM,GAAG,GAAG,YAAY,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;QAC5D,OAAO,kBAAkB,GAAG,gCAAgC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;IACpG,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAoB;IAChD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,OAAO;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACZ,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC;QAC9G,OAAO,UAAU,CAAC;wCACgB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;iCAChB,CAAC,GAAG,CAAC;2CACK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,0BAA0B,GAAG;;aAEvE,CAAC;IACV,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,UAAU,CAAC;iEAC6C,OAAO,CAAC,MAAM;uBACxD,KAAK,QAAQ,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,MAAM,IAAI,GAAG,CAAC,CAAiB,EAAU,EAAE;QACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC;QAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,KAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,OAAO,UAAU,CAAC;uCACiB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,6DAA6D,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;;6BAE3F,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;6BACX,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;;yBAEzD,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/B,QAAQ,CAAC,CAAC,CAAC,8BAA8B,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,GAAG,8BAA8B,CAAC,CAAC,CAAC,EAAE;gCACjF,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;WAC5E,CAAC;IACV,CAAC,CAAC;IACF,OAAO,UAAU,CAAC;uDACmC,MAAM,CAAC,UAAU,CAAC,MAAM;uBACxD,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;SAC5D,GAAG,CACF,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,mCAAmC,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CACnI;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,UAAU,CAAC;yEACqD,MAAM,CAAC,MAAM,CAAC,MAAM;;;QAGrF,MAAM;;;uEAGyD,UAAU;;;;;;;;;;;;;;;;SAgBxE,CAAC;AACV,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,UAAU,CAAC;;;;;;;;;;;;wEAYoD,CAAC;AACzE,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Escape a string for safe interpolation into HTML text/attribute context. */
2
+ export declare function esc(value: unknown): string;
3
+ //# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAO1C"}
@@ -0,0 +1,10 @@
1
+ /** Escape a string for safe interpolation into HTML text/attribute context. */
2
+ export function esc(value) {
3
+ return String(value ?? "")
4
+ .replace(/&/g, "&amp;")
5
+ .replace(/</g, "&lt;")
6
+ .replace(/>/g, "&gt;")
7
+ .replace(/"/g, "&quot;")
8
+ .replace(/'/g, "&#39;");
9
+ }
10
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","sourceRoot":"","sources":["../src/escape.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,UAAU,GAAG,CAAC,KAAc;IAChC,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { HealthReport } from "./types.js";
2
+ /** Representative sample report — drives the standalone browser demo and tests. */
3
+ export declare const SAMPLE_REPORT: HealthReport;
4
+ //# sourceMappingURL=fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,mFAAmF;AACnF,eAAO,MAAM,aAAa,EAAE,YAiD3B,CAAC"}
@@ -0,0 +1,52 @@
1
+ /** Representative sample report — drives the standalone browser demo and tests. */
2
+ export const SAMPLE_REPORT = {
3
+ meta: {
4
+ title: "Codebase Health Studio",
5
+ subtitle: "React 18 · CRA",
6
+ target: "acme-dashboard",
7
+ generatedAt: "2026-06-27",
8
+ tool: "legacy-analyzer",
9
+ },
10
+ score: 62,
11
+ totalIssues: 18,
12
+ chips: [
13
+ { label: "Framework", value: "Create React App" },
14
+ { label: "React", value: "18.2.0" },
15
+ { label: "Language", value: "JavaScript" },
16
+ { label: "Components", value: "94" },
17
+ ],
18
+ topActions: [
19
+ { id: "fix-god", label: "Split the 3 god components", kind: "tool", tool: "component-fixer", params: { target: "components" }, fallback: "Refactor Dashboard.jsx, Settings.jsx and Reports.jsx into smaller components." },
20
+ { id: "plan", label: "Generate full refactor plan", kind: "tool", tool: "generate-refactor-plan", params: { path: "." }, fallback: "Generate a refactor plan for acme-dashboard." },
21
+ { id: "migrate-ts", label: "Migrate the API layer to TypeScript", kind: "prompt", prompt: "Convert src/api/*.js to TypeScript with typed responses and a centralised client." },
22
+ ],
23
+ categories: [
24
+ { id: "components", name: "Components", score: 48, status: "warn", summary: "3 god components over 300 lines; 11 with mixed responsibilities.", issueCount: 6, details: [{ label: "Total", value: "94" }, { label: "Large", value: "3" }] },
25
+ { id: "state", name: "State", score: 55, status: "warn", summary: "Redux without normalisation; derived state stored in the store.", issueCount: 3 },
26
+ { id: "api", name: "API layer", score: 40, status: "bad", summary: "Scattered axios calls, 4 duplicated endpoints, no central client.", issueCount: 4 },
27
+ { id: "routing", name: "Routing", score: 78, status: "good", summary: "react-router v6, nested routes, but no lazy loading.", issueCount: 1 },
28
+ { id: "styling", name: "Styling", score: 60, status: "warn", summary: "Mixed CSS + styled-components; 23 hardcoded colours.", issueCount: 2 },
29
+ { id: "deps", name: "Dependencies", score: 84, status: "good", summary: "2 unused deps; moment.js inflating the bundle.", issueCount: 2 },
30
+ ],
31
+ issues: [
32
+ { id: "i1", category: "components", severity: "critical", title: "God component: Dashboard.jsx (612 lines)", description: "Dashboard.jsx mixes data fetching, layout, and 4 unrelated widgets. It is the single largest re-render hotspot.", file: "src/pages/Dashboard.jsx", meta: [{ label: "Lines", value: "612" }, { label: "Responsibilities", value: "5" }], actions: [{ id: "fix-i1", label: "Split with component-fixer", kind: "tool", tool: "component-fixer", params: { file: "src/pages/Dashboard.jsx" }, fallback: "Split src/pages/Dashboard.jsx into smaller components." }, { id: "explain-i1", label: "Explain the risk", kind: "prompt", prompt: "Explain why a 612-line god component hurts maintainability and performance in React." }] },
33
+ { id: "i2", category: "api", severity: "critical", title: "Duplicated endpoint: GET /users called 4 ways", description: "Four components call GET /users with slightly different axios config — no shared client or cache.", file: "src/api/", meta: [{ label: "Call sites", value: "4" }], actions: [{ id: "fix-i2", label: "Centralise the API client", kind: "prompt", prompt: "Create a centralised typed axios client and replace the 4 duplicate GET /users call sites." }] },
34
+ { id: "i3", category: "components", severity: "high", title: "God component: Settings.jsx (438 lines)", file: "src/pages/Settings.jsx", meta: [{ label: "Lines", value: "438" }], actions: [{ id: "fix-i3", label: "Split with component-fixer", kind: "tool", tool: "component-fixer", params: { file: "src/pages/Settings.jsx" }, fallback: "Split src/pages/Settings.jsx." }] },
35
+ { id: "i4", category: "api", severity: "high", title: "No central HTTP client — axios imported in 19 files", file: "src/", actions: [] },
36
+ { id: "i5", category: "state", severity: "high", title: "Derived state stored in Redux (totals recomputed on every action)", file: "src/store/cartSlice.js", actions: [{ id: "explain-i5", label: "How to fix", kind: "prompt", prompt: "Show how to replace derived state in Redux with reselect selectors." }] },
37
+ { id: "i6", category: "deps", severity: "high", title: "moment.js adds ~230KB — replace with date-fns or Temporal", file: "package.json", meta: [{ label: "Bundle impact", value: "~230KB" }], actions: [] },
38
+ { id: "i7", category: "components", severity: "medium", title: "Prop drilling 4 levels deep for `user`", file: "src/pages/Reports.jsx", actions: [] },
39
+ { id: "i8", category: "styling", severity: "medium", title: "23 hardcoded hex colours outside the token system", file: "src/styles/", actions: [] },
40
+ { id: "i9", category: "state", severity: "medium", title: "No memoised selectors — components re-render on unrelated store changes", file: "src/store/", actions: [] },
41
+ { id: "i10", category: "api", severity: "medium", title: "Errors swallowed — 11 axios calls have no .catch", file: "src/api/", actions: [] },
42
+ { id: "i11", category: "components", severity: "medium", title: "List rendered with array index as key", file: "src/components/Table.jsx", actions: [] },
43
+ { id: "i12", category: "routing", severity: "medium", title: "No route-level code splitting (React.lazy)", file: "src/App.jsx", actions: [] },
44
+ { id: "i13", category: "deps", severity: "low", title: "2 unused dependencies in package.json", file: "package.json", actions: [] },
45
+ { id: "i14", category: "styling", severity: "low", title: "Duplicate utility classes across 6 CSS files", file: "src/styles/", actions: [] },
46
+ { id: "i15", category: "components", severity: "low", title: "12 components missing displayName", file: "src/components/", actions: [] },
47
+ { id: "i16", category: "api", severity: "low", title: "Base URL hardcoded instead of env var", file: "src/api/config.js", actions: [] },
48
+ { id: "i17", category: "components", severity: "low", title: "Inline arrow functions in 31 render paths", file: "src/", actions: [] },
49
+ { id: "i18", category: "state", severity: "low", title: "Local component state duplicates Redux store data", file: "src/pages/Profile.jsx", actions: [] },
50
+ ],
51
+ };
52
+ //# sourceMappingURL=fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=generate-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-template.d.ts","sourceRoot":"","sources":["../src/generate-template.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ // Build step: emit a standalone browser demo (fixture baked in) so the report
2
+ // UI can be opened directly in a browser — the public showcase artifact.
3
+ import { writeFileSync, mkdirSync } from "node:fs";
4
+ import { dirname, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { renderReportHTML } from "./render.js";
7
+ import { renderResultHTML } from "./result-render.js";
8
+ import { SAMPLE_REPORT } from "./fixture.js";
9
+ import { SAMPLE_RESULT } from "./result-fixture.js";
10
+ const here = dirname(fileURLToPath(import.meta.url));
11
+ const outDir = resolve(here, "..", "demo");
12
+ mkdirSync(outDir, { recursive: true });
13
+ const html = renderReportHTML(SAMPLE_REPORT);
14
+ writeFileSync(resolve(outDir, "index.html"), html, "utf8");
15
+ console.error(`[ui-kit] wrote demo/index.html (${(html.length / 1024).toFixed(1)} KB)`);
16
+ const resultHtml = renderResultHTML(SAMPLE_RESULT);
17
+ writeFileSync(resolve(outDir, "result.html"), resultHtml, "utf8");
18
+ console.error(`[ui-kit] wrote demo/result.html (${(resultHtml.length / 1024).toFixed(1)} KB)`);
19
+ //# sourceMappingURL=generate-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-template.js","sourceRoot":"","sources":["../src/generate-template.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yEAAyE;AACzE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3C,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAEvC,MAAM,IAAI,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;AAC7C,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3D,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAExF,MAAM,UAAU,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;AACnD,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AAClE,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export { renderReportHTML } from "./render.js";
3
+ export { renderResultHTML } from "./result-render.js";
4
+ export { SAMPLE_REPORT } from "./fixture.js";
5
+ export { SAMPLE_RESULT } from "./result-fixture.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ // @mcp-showcase/ui-kit — reusable single-file HTML report UI for MCP tools.
2
+ export * from "./types.js";
3
+ export { renderReportHTML } from "./render.js";
4
+ export { renderResultHTML } from "./result-render.js";
5
+ export { SAMPLE_REPORT } from "./fixture.js";
6
+ export { SAMPLE_RESULT } from "./result-fixture.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { HealthReport } from "./types.js";
2
+ export declare function renderReportHTML(report: HealthReport): string;
3
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO1C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAuB7D"}
@@ -0,0 +1,38 @@
1
+ // ============================================================================
2
+ // renderReportHTML — assembles ONE self-contained HTML document from a
3
+ // HealthReport. Styles + runtime + data are all inlined (no external requests),
4
+ // so the result drops straight into a sandboxed MCP iframe or a browser tab.
5
+ // ============================================================================
6
+ import { STYLES } from "./theme.js";
7
+ import { RUNTIME } from "./runtime.js";
8
+ import { esc } from "./escape.js";
9
+ import { buildHeader, buildHero, buildFixFirst, buildCategories, buildTriageShell, buildChrome, } from "./components.js";
10
+ /** Embed JSON safely inside a <script> tag (neutralise `</script>` break-out). */
11
+ function embedJson(data) {
12
+ return JSON.stringify(data).replace(/</g, "\\u003c");
13
+ }
14
+ export function renderReportHTML(report) {
15
+ return `<!doctype html>
16
+ <html lang="en" data-theme="light">
17
+ <head>
18
+ <meta charset="utf-8"/>
19
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
20
+ <title>${esc(report.meta.title)} — ${esc(report.meta.target)}</title>
21
+ <style>${STYLES}</style>
22
+ </head>
23
+ <body>
24
+ <div class="wrap">
25
+ ${buildHeader(report)}
26
+ ${buildHero(report)}
27
+ ${buildFixFirst(report)}
28
+ ${buildCategories(report)}
29
+ ${buildTriageShell(report)}
30
+ <div class="foot-note">${esc(report.meta.tool)} · generated ${esc(report.meta.generatedAt)} · mcp-react-toolkit</div>
31
+ </div>
32
+ ${buildChrome()}
33
+ <script id="report-data" type="application/json">${embedJson(report)}</script>
34
+ <script>${RUNTIME}</script>
35
+ </body>
36
+ </html>`;
37
+ }
38
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,uEAAuE;AACvE,gFAAgF;AAChF,6EAA6E;AAC7E,+EAA+E;AAE/E,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EACL,WAAW,EACX,SAAS,EACT,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAGzB,kFAAkF;AAClF,SAAS,SAAS,CAAC,IAAa;IAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,OAAO;;;;;SAKA,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;SACnD,MAAM;;;;EAIb,WAAW,CAAC,MAAM,CAAC;EACnB,SAAS,CAAC,MAAM,CAAC;EACjB,aAAa,CAAC,MAAM,CAAC;EACrB,eAAe,CAAC,MAAM,CAAC;EACvB,gBAAgB,CAAC,MAAM,CAAC;yBACD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;;EAExF,WAAW,EAAE;mDACoC,SAAS,CAAC,MAAM,CAAC;UAC1D,OAAO;;QAET,CAAC;AACT,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { buildChrome } from "./components.js";
2
+ import { ResultReport } from "./types.js";
3
+ export declare function buildResultHeader(report: ResultReport): string;
4
+ export declare function buildResultHero(report: ResultReport): string;
5
+ export declare function buildChanges(report: ResultReport): string;
6
+ export declare function buildSections(report: ResultReport): string;
7
+ export declare function buildNextSteps(report: ResultReport): string;
8
+ export { buildChrome };
9
+ //# sourceMappingURL=result-components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-components.d.ts","sourceRoot":"","sources":["../src/result-components.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAA2C,MAAM,YAAY,CAAC;AAMnF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAsB9D;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAiB5D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAsBzD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAkB1D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAS3D;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,105 @@
1
+ // ============================================================================
2
+ // SERVER-SIDE BUILDERS for the RESULT view (generative/action tools).
3
+ // Reuses the shared chrome (header, drawer, toast) and CSS classes.
4
+ // ============================================================================
5
+ import { esc } from "./escape.js";
6
+ import { buildChrome } from "./components.js";
7
+ import { statusToBand } from "./types.js";
8
+ const SUN = `<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>`;
9
+ const MOON = `<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>`;
10
+ const STATUS_LABEL = { success: "Success", partial: "Partial", noop: "No changes" };
11
+ export function buildResultHeader(report) {
12
+ return /* html */ `
13
+ <header class="hdr">
14
+ <div class="brand">
15
+ <span class="dot" aria-hidden="true">
16
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
17
+ </span>
18
+ <div style="min-width:0">
19
+ <h1>${esc(report.meta.title)}</h1>
20
+ <p class="sub">${esc(report.meta.target)}</p>
21
+ </div>
22
+ </div>
23
+ <div class="hdr-actions">
24
+ <button class="btn icon" id="theme-toggle" type="button" aria-label="Toggle colour theme" title="Toggle theme">
25
+ <span class="theme-sun" hidden>${SUN}</span><span class="theme-moon">${MOON}</span>
26
+ </button>
27
+ <button class="btn" id="export-btn" type="button" title="Copy summary as Markdown">
28
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
29
+ Export
30
+ </button>
31
+ </div>
32
+ </header>`;
33
+ }
34
+ export function buildResultHero(report) {
35
+ const band = statusToBand(report.status);
36
+ const chips = (report.stats ?? [])
37
+ .map((s) => `<span class="chip"><span>${esc(s.label)}</span><b>${esc(s.value)}</b></span>`)
38
+ .join("");
39
+ return /* html */ `
40
+ <section class="result-hero" data-band="${band}">
41
+ <span class="glyph" aria-hidden="true">
42
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
43
+ </span>
44
+ <div class="rh-main">
45
+ <div class="rh-title">${esc(report.headline)}</div>
46
+ ${report.meta.subtitle ? `<div class="rh-sub">${esc(report.meta.subtitle)}</div>` : ""}
47
+ ${chips ? `<div class="chips" style="margin-top:10px">${chips}</div>` : ""}
48
+ </div>
49
+ <span class="status-pill ${band}">${esc(STATUS_LABEL[report.status] ?? report.status)}</span>
50
+ </section>`;
51
+ }
52
+ export function buildChanges(report) {
53
+ const changes = report.changes ?? [];
54
+ if (!changes.length)
55
+ return "";
56
+ const row = (c, i) => {
57
+ const delta = c.additions != null || c.deletions != null
58
+ ? `<span class="change-delta">${c.additions != null ? `<span class="add">+${esc(c.additions)}</span> ` : ""}${c.deletions != null ? `<span class="del">-${esc(c.deletions)}</span>` : ""}</span>`
59
+ : "";
60
+ const clickable = c.diff ? "clickable" : "";
61
+ return /* html */ `
62
+ <div class="change-row ${clickable}" ${c.diff ? `data-change="${i}" role="button" tabindex="0"` : ""}>
63
+ <span class="kind ${esc(c.kind)}">${esc(c.kind)}</span>
64
+ <span class="change-main">
65
+ <span class="change-path">${esc(c.path)}</span>
66
+ ${c.summary ? `<span class="change-sum">${esc(c.summary)}</span>` : ""}
67
+ </span>
68
+ ${delta}
69
+ </div>`;
70
+ };
71
+ return /* html */ `
72
+ <div class="sec"><h2>Changes</h2><span class="count">${changes.length} file${changes.length === 1 ? "" : "s"}</span></div>
73
+ <div class="changes">${changes.map(row).join("")}</div>`;
74
+ }
75
+ export function buildSections(report) {
76
+ const sections = report.sections ?? [];
77
+ if (!sections.length)
78
+ return "";
79
+ const section = (s) => {
80
+ const items = s.items
81
+ .map((it) => `
82
+ <div class="section-item">
83
+ <span class="ip ${it.status ? esc(it.status) : ""}"></span>
84
+ <div style="min-width:0"><div class="it">${esc(it.title)}</div>${it.detail ? `<div class="id">${esc(it.detail)}</div>` : ""}</div>
85
+ </div>`)
86
+ .join("");
87
+ return /* html */ `
88
+ <div class="sec"><h2>${esc(s.title)}</h2><span class="count">${s.items.length}</span></div>
89
+ <div class="section">${items}</div>`;
90
+ };
91
+ return sections.map(section).join("");
92
+ }
93
+ export function buildNextSteps(report) {
94
+ const actions = report.nextActions ?? [];
95
+ if (!actions.length)
96
+ return "";
97
+ const btns = actions
98
+ .map((a, i) => `<button class="btn${i === 0 ? " primary" : ""}" type="button" data-action="${esc(a.id)}">${esc(a.label)}</button>`)
99
+ .join("");
100
+ return /* html */ `
101
+ <div class="sec"><h2>Next steps</h2></div>
102
+ <div class="next-steps">${btns}</div>`;
103
+ }
104
+ export { buildChrome };
105
+ //# sourceMappingURL=result-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-components.js","sourceRoot":"","sources":["../src/result-components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { ResultReport } from "./types.js";
2
+ /** Sample action report — drives the result-view demo and tests. */
3
+ export declare const SAMPLE_RESULT: ResultReport;
4
+ //# sourceMappingURL=result-fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-fixture.d.ts","sourceRoot":"","sources":["../src/result-fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,oEAAoE;AACpE,eAAO,MAAM,aAAa,EAAE,YAoC3B,CAAC"}