@seed-ship/mcp-ui-solid 2.2.10 → 2.3.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 (41) hide show
  1. package/dist/components/ArtifactRenderer.cjs +4 -3
  2. package/dist/components/ArtifactRenderer.cjs.map +1 -1
  3. package/dist/components/ArtifactRenderer.js +4 -3
  4. package/dist/components/ArtifactRenderer.js.map +1 -1
  5. package/dist/components/CodeBlockRenderer.cjs +6 -1
  6. package/dist/components/CodeBlockRenderer.cjs.map +1 -1
  7. package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
  8. package/dist/components/CodeBlockRenderer.js +6 -1
  9. package/dist/components/CodeBlockRenderer.js.map +1 -1
  10. package/dist/components/UIResourceRenderer.cjs +29 -27
  11. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  12. package/dist/components/UIResourceRenderer.js +30 -28
  13. package/dist/components/UIResourceRenderer.js.map +1 -1
  14. package/dist/index.cjs +2 -0
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -1
  20. package/dist/services/index.d.ts +1 -1
  21. package/dist/services/index.d.ts.map +1 -1
  22. package/dist/services/validation.cjs +176 -18
  23. package/dist/services/validation.cjs.map +1 -1
  24. package/dist/services/validation.d.ts +21 -0
  25. package/dist/services/validation.d.ts.map +1 -1
  26. package/dist/services/validation.js +176 -18
  27. package/dist/services/validation.js.map +1 -1
  28. package/dist/types/index.d.ts +1 -1
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/dist/types.d.cts +1 -1
  31. package/dist/types.d.ts +1 -1
  32. package/package.json +1 -1
  33. package/src/components/ArtifactRenderer.tsx +3 -3
  34. package/src/components/CodeBlockRenderer.tsx +7 -1
  35. package/src/components/UIResourceRenderer.tsx +2 -2
  36. package/src/index.ts +2 -0
  37. package/src/services/index.ts +2 -0
  38. package/src/services/validation.test.ts +158 -1
  39. package/src/services/validation.ts +221 -19
  40. package/src/types/index.ts +1 -1
  41. package/tsconfig.tsbuildinfo +1 -1
@@ -4,9 +4,10 @@ const web = require("solid-js/web");
4
4
  var _tmpl$ = /* @__PURE__ */ web.template(`<div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"><div class="flex items-center gap-3"><div class="w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-700 rounded-md shadow-sm text-xl"></div><div><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate max-w-[200px]"></h4><p class="text-xs text-gray-500 dark:text-gray-400"><!$><!/> • <!$><!/></p></div></div><a class="px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/40 rounded-md transition-colors flex items-center gap-1"><svg class="w-4 h-4"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>Download`);
5
5
  const ArtifactRenderer = (props) => {
6
6
  const getIcon = () => {
7
- if (props.params.mimeType.includes("csv")) return "📊";
8
- if (props.params.mimeType.includes("json")) return "{}";
9
- if (props.params.mimeType.includes("pdf")) return "📄";
7
+ var _a, _b, _c;
8
+ if ((_a = props.params.mimeType) == null ? void 0 : _a.includes("csv")) return "📊";
9
+ if ((_b = props.params.mimeType) == null ? void 0 : _b.includes("json")) return "{}";
10
+ if ((_c = props.params.mimeType) == null ? void 0 : _c.includes("pdf")) return "📄";
10
11
  return "📁";
11
12
  };
12
13
  const formatSize = (bytes) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ArtifactRenderer.cjs","sources":["../../src/components/ArtifactRenderer.tsx"],"sourcesContent":["import { Component } from 'solid-js'\n\nexport interface ArtifactComponentParams {\n url: string\n filename: string\n mimeType: string\n size?: number\n description?: string\n}\n\nexport const ArtifactRenderer: Component<{ params: ArtifactComponentParams }> = (props) => {\n const getIcon = () => {\n if (props.params.mimeType.includes('csv')) return '📊'\n if (props.params.mimeType.includes('json')) return '{}'\n if (props.params.mimeType.includes('pdf')) return '📄'\n return '📁'\n }\n\n const formatSize = (bytes?: number) => {\n if (!bytes) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n }\n\n return (\n <div class=\"flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\">\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-700 rounded-md shadow-sm text-xl\">\n {getIcon()}\n </div>\n <div>\n <h4 class=\"text-sm font-medium text-gray-900 dark:text-white truncate max-w-[200px]\">\n {props.params.filename}\n </h4>\n <p class=\"text-xs text-gray-500 dark:text-gray-400\">\n {formatSize(props.params.size)} • {props.params.description || 'Generated artifact'}\n </p>\n </div>\n </div>\n\n <a\n href={props.params.url}\n download={props.params.filename}\n class=\"px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/40 rounded-md transition-colors flex items-center gap-1\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n Download\n </a>\n </div>\n )\n}\n"],"names":["ArtifactRenderer","props","getIcon","params","mimeType","includes","formatSize","bytes","toFixed","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$9","_co$","_$getNextMarker","_el$7","_el$0","_el$1","_co$2","_el$10","_$insert","filename","size","description","_$effect","_p$","_v$","url","_v$2","e","_$setAttribute","t","undefined"],"mappings":";;;;AAUO,MAAMA,mBAAoEC,CAAAA,UAAU;AACvF,QAAMC,UAAUA,MAAM;AAClB,QAAID,MAAME,OAAOC,SAASC,SAAS,KAAK,EAAG,QAAO;AAClD,QAAIJ,MAAME,OAAOC,SAASC,SAAS,MAAM,EAAG,QAAO;AACnD,QAAIJ,MAAME,OAAOC,SAASC,SAAS,KAAK,EAAG,QAAO;AAClD,WAAO;AAAA,EACX;AAEA,QAAMC,aAAaA,CAACC,UAAmB;AACnC,QAAI,CAACA,MAAO,QAAO;AACnB,QAAIA,QAAQ,KAAM,QAAO,GAAGA,KAAK;AACjC,QAAIA,QAAQ,OAAO,KAAM,QAAO,IAAIA,QAAQ,MAAMC,QAAQ,CAAC,CAAC;AAC5D,WAAO,IAAID,SAAS,OAAO,OAAOC,QAAQ,CAAC,CAAC;AAAA,EAChD;AAEA,UAAA,MAAA;AAAA,QAAAC,OAAAC,mBAAAC,MAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAC,YAAAE,QAAAD,MAAAE,aAAAC,QAAAF,MAAAF,YAAAK,QAAAD,MAAAD,aAAAG,QAAAD,MAAAL,YAAA,CAAAO,OAAAC,IAAA,IAAAC,IAAAA,cAAAH,MAAAH,WAAA,GAAAO,QAAAH,MAAAJ,aAAAQ,QAAAD,MAAAP,aAAA,CAAAS,OAAAC,KAAA,IAAAJ,IAAAA,cAAAE,MAAAR,WAAA,GAAAW,SAAAf,MAAAI;AAAAY,QAAAA,OAAAd,OAIiBZ,OAAO;AAAA0B,QAAAA,OAAAX,OAAA,MAIHhB,MAAME,OAAO0B,QAAQ;AAAAD,eAAAV,OAAA,MAGrBZ,WAAWL,MAAME,OAAO2B,IAAI,GAACV,OAAAC,IAAA;AAAAO,eAAAV,OAAA,MAAKjB,MAAME,OAAO4B,eAAe,sBAAoBN,OAAAC,KAAA;AAAAM,QAAAA,OAAAC,CAAAA,QAAA;AAAA,UAAAC,MAMrFjC,MAAME,OAAOgC,KAAGC,OACZnC,MAAME,OAAO0B;AAAQK,cAAAD,IAAAI,KAAAC,IAAAA,aAAAX,QAAA,QAAAM,IAAAI,IAAAH,GAAA;AAAAE,eAAAH,IAAAM,KAAAD,IAAAA,aAAAX,QAAA,YAAAM,IAAAM,IAAAH,IAAA;AAAA,aAAAH;AAAAA,IAAA,GAAA;AAAA,MAAAI,GAAAG;AAAAA,MAAAD,GAAAC;AAAAA,IAAAA,CAAA;AAAA,WAAA/B;AAAAA,EAAA,GAAA;AAU/C;;"}
1
+ {"version":3,"file":"ArtifactRenderer.cjs","sources":["../../src/components/ArtifactRenderer.tsx"],"sourcesContent":["import { Component } from 'solid-js'\n\nexport interface ArtifactComponentParams {\n url: string\n filename: string\n mimeType: string\n size?: number\n description?: string\n}\n\nexport const ArtifactRenderer: Component<{ params: ArtifactComponentParams }> = (props) => {\n const getIcon = () => {\n if (props.params.mimeType?.includes('csv')) return '📊'\n if (props.params.mimeType?.includes('json')) return '{}'\n if (props.params.mimeType?.includes('pdf')) return '📄'\n return '📁'\n }\n\n const formatSize = (bytes?: number) => {\n if (!bytes) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n }\n\n return (\n <div class=\"flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\">\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-700 rounded-md shadow-sm text-xl\">\n {getIcon()}\n </div>\n <div>\n <h4 class=\"text-sm font-medium text-gray-900 dark:text-white truncate max-w-[200px]\">\n {props.params.filename}\n </h4>\n <p class=\"text-xs text-gray-500 dark:text-gray-400\">\n {formatSize(props.params.size)} • {props.params.description || 'Generated artifact'}\n </p>\n </div>\n </div>\n\n <a\n href={props.params.url}\n download={props.params.filename}\n class=\"px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/40 rounded-md transition-colors flex items-center gap-1\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n Download\n </a>\n </div>\n )\n}\n"],"names":["ArtifactRenderer","props","getIcon","params","mimeType","includes","formatSize","bytes","toFixed","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$9","_co$","_$getNextMarker","_el$7","_el$0","_el$1","_co$2","_el$10","_$insert","filename","size","description","_$effect","_p$","_v$","url","_v$2","e","_$setAttribute","t","undefined"],"mappings":";;;;AAUO,MAAMA,mBAAoEC,CAAAA,UAAU;AACvF,QAAMC,UAAUA,MAAM;;AAClB,SAAID,WAAME,OAAOC,aAAbH,mBAAuBI,SAAS,OAAQ,QAAO;AACnD,SAAIJ,WAAME,OAAOC,aAAbH,mBAAuBI,SAAS,QAAS,QAAO;AACpD,SAAIJ,WAAME,OAAOC,aAAbH,mBAAuBI,SAAS,OAAQ,QAAO;AACnD,WAAO;AAAA,EACX;AAEA,QAAMC,aAAaA,CAACC,UAAmB;AACnC,QAAI,CAACA,MAAO,QAAO;AACnB,QAAIA,QAAQ,KAAM,QAAO,GAAGA,KAAK;AACjC,QAAIA,QAAQ,OAAO,KAAM,QAAO,IAAIA,QAAQ,MAAMC,QAAQ,CAAC,CAAC;AAC5D,WAAO,IAAID,SAAS,OAAO,OAAOC,QAAQ,CAAC,CAAC;AAAA,EAChD;AAEA,UAAA,MAAA;AAAA,QAAAC,OAAAC,mBAAAC,MAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAC,YAAAE,QAAAD,MAAAE,aAAAC,QAAAF,MAAAF,YAAAK,QAAAD,MAAAD,aAAAG,QAAAD,MAAAL,YAAA,CAAAO,OAAAC,IAAA,IAAAC,IAAAA,cAAAH,MAAAH,WAAA,GAAAO,QAAAH,MAAAJ,aAAAQ,QAAAD,MAAAP,aAAA,CAAAS,OAAAC,KAAA,IAAAJ,IAAAA,cAAAE,MAAAR,WAAA,GAAAW,SAAAf,MAAAI;AAAAY,QAAAA,OAAAd,OAIiBZ,OAAO;AAAA0B,QAAAA,OAAAX,OAAA,MAIHhB,MAAME,OAAO0B,QAAQ;AAAAD,eAAAV,OAAA,MAGrBZ,WAAWL,MAAME,OAAO2B,IAAI,GAACV,OAAAC,IAAA;AAAAO,eAAAV,OAAA,MAAKjB,MAAME,OAAO4B,eAAe,sBAAoBN,OAAAC,KAAA;AAAAM,QAAAA,OAAAC,CAAAA,QAAA;AAAA,UAAAC,MAMrFjC,MAAME,OAAOgC,KAAGC,OACZnC,MAAME,OAAO0B;AAAQK,cAAAD,IAAAI,KAAAC,IAAAA,aAAAX,QAAA,QAAAM,IAAAI,IAAAH,GAAA;AAAAE,eAAAH,IAAAM,KAAAD,IAAAA,aAAAX,QAAA,YAAAM,IAAAM,IAAAH,IAAA;AAAA,aAAAH;AAAAA,IAAA,GAAA;AAAA,MAAAI,GAAAG;AAAAA,MAAAD,GAAAC;AAAAA,IAAAA,CAAA;AAAA,WAAA/B;AAAAA,EAAA,GAAA;AAU/C;;"}
@@ -2,9 +2,10 @@ import { getNextElement, template, getNextMarker, insert, effect, setAttribute }
2
2
  var _tmpl$ = /* @__PURE__ */ template(`<div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"><div class="flex items-center gap-3"><div class="w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-700 rounded-md shadow-sm text-xl"></div><div><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate max-w-[200px]"></h4><p class="text-xs text-gray-500 dark:text-gray-400"><!$><!/> • <!$><!/></p></div></div><a class="px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/40 rounded-md transition-colors flex items-center gap-1"><svg class="w-4 h-4"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>Download`);
3
3
  const ArtifactRenderer = (props) => {
4
4
  const getIcon = () => {
5
- if (props.params.mimeType.includes("csv")) return "📊";
6
- if (props.params.mimeType.includes("json")) return "{}";
7
- if (props.params.mimeType.includes("pdf")) return "📄";
5
+ var _a, _b, _c;
6
+ if ((_a = props.params.mimeType) == null ? void 0 : _a.includes("csv")) return "📊";
7
+ if ((_b = props.params.mimeType) == null ? void 0 : _b.includes("json")) return "{}";
8
+ if ((_c = props.params.mimeType) == null ? void 0 : _c.includes("pdf")) return "📄";
8
9
  return "📁";
9
10
  };
10
11
  const formatSize = (bytes) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ArtifactRenderer.js","sources":["../../src/components/ArtifactRenderer.tsx"],"sourcesContent":["import { Component } from 'solid-js'\n\nexport interface ArtifactComponentParams {\n url: string\n filename: string\n mimeType: string\n size?: number\n description?: string\n}\n\nexport const ArtifactRenderer: Component<{ params: ArtifactComponentParams }> = (props) => {\n const getIcon = () => {\n if (props.params.mimeType.includes('csv')) return '📊'\n if (props.params.mimeType.includes('json')) return '{}'\n if (props.params.mimeType.includes('pdf')) return '📄'\n return '📁'\n }\n\n const formatSize = (bytes?: number) => {\n if (!bytes) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n }\n\n return (\n <div class=\"flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\">\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-700 rounded-md shadow-sm text-xl\">\n {getIcon()}\n </div>\n <div>\n <h4 class=\"text-sm font-medium text-gray-900 dark:text-white truncate max-w-[200px]\">\n {props.params.filename}\n </h4>\n <p class=\"text-xs text-gray-500 dark:text-gray-400\">\n {formatSize(props.params.size)} • {props.params.description || 'Generated artifact'}\n </p>\n </div>\n </div>\n\n <a\n href={props.params.url}\n download={props.params.filename}\n class=\"px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/40 rounded-md transition-colors flex items-center gap-1\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n Download\n </a>\n </div>\n )\n}\n"],"names":["ArtifactRenderer","props","getIcon","params","mimeType","includes","formatSize","bytes","toFixed","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$9","_co$","_$getNextMarker","_el$7","_el$0","_el$1","_co$2","_el$10","_$insert","filename","size","description","_$effect","_p$","_v$","url","_v$2","e","_$setAttribute","t","undefined"],"mappings":";;AAUO,MAAMA,mBAAoEC,CAAAA,UAAU;AACvF,QAAMC,UAAUA,MAAM;AAClB,QAAID,MAAME,OAAOC,SAASC,SAAS,KAAK,EAAG,QAAO;AAClD,QAAIJ,MAAME,OAAOC,SAASC,SAAS,MAAM,EAAG,QAAO;AACnD,QAAIJ,MAAME,OAAOC,SAASC,SAAS,KAAK,EAAG,QAAO;AAClD,WAAO;AAAA,EACX;AAEA,QAAMC,aAAaA,CAACC,UAAmB;AACnC,QAAI,CAACA,MAAO,QAAO;AACnB,QAAIA,QAAQ,KAAM,QAAO,GAAGA,KAAK;AACjC,QAAIA,QAAQ,OAAO,KAAM,QAAO,IAAIA,QAAQ,MAAMC,QAAQ,CAAC,CAAC;AAC5D,WAAO,IAAID,SAAS,OAAO,OAAOC,QAAQ,CAAC,CAAC;AAAA,EAChD;AAEA,UAAA,MAAA;AAAA,QAAAC,OAAAC,eAAAC,MAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAC,YAAAE,QAAAD,MAAAE,aAAAC,QAAAF,MAAAF,YAAAK,QAAAD,MAAAD,aAAAG,QAAAD,MAAAL,YAAA,CAAAO,OAAAC,IAAA,IAAAC,cAAAH,MAAAH,WAAA,GAAAO,QAAAH,MAAAJ,aAAAQ,QAAAD,MAAAP,aAAA,CAAAS,OAAAC,KAAA,IAAAJ,cAAAE,MAAAR,WAAA,GAAAW,SAAAf,MAAAI;AAAAY,WAAAd,OAIiBZ,OAAO;AAAA0B,WAAAX,OAAA,MAIHhB,MAAME,OAAO0B,QAAQ;AAAAD,WAAAV,OAAA,MAGrBZ,WAAWL,MAAME,OAAO2B,IAAI,GAACV,OAAAC,IAAA;AAAAO,WAAAV,OAAA,MAAKjB,MAAME,OAAO4B,eAAe,sBAAoBN,OAAAC,KAAA;AAAAM,WAAAC,CAAAA,QAAA;AAAA,UAAAC,MAMrFjC,MAAME,OAAOgC,KAAGC,OACZnC,MAAME,OAAO0B;AAAQK,cAAAD,IAAAI,KAAAC,aAAAX,QAAA,QAAAM,IAAAI,IAAAH,GAAA;AAAAE,eAAAH,IAAAM,KAAAD,aAAAX,QAAA,YAAAM,IAAAM,IAAAH,IAAA;AAAA,aAAAH;AAAAA,IAAA,GAAA;AAAA,MAAAI,GAAAG;AAAAA,MAAAD,GAAAC;AAAAA,IAAAA,CAAA;AAAA,WAAA/B;AAAAA,EAAA,GAAA;AAU/C;"}
1
+ {"version":3,"file":"ArtifactRenderer.js","sources":["../../src/components/ArtifactRenderer.tsx"],"sourcesContent":["import { Component } from 'solid-js'\n\nexport interface ArtifactComponentParams {\n url: string\n filename: string\n mimeType: string\n size?: number\n description?: string\n}\n\nexport const ArtifactRenderer: Component<{ params: ArtifactComponentParams }> = (props) => {\n const getIcon = () => {\n if (props.params.mimeType?.includes('csv')) return '📊'\n if (props.params.mimeType?.includes('json')) return '{}'\n if (props.params.mimeType?.includes('pdf')) return '📄'\n return '📁'\n }\n\n const formatSize = (bytes?: number) => {\n if (!bytes) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n }\n\n return (\n <div class=\"flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\">\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 flex items-center justify-center bg-white dark:bg-gray-700 rounded-md shadow-sm text-xl\">\n {getIcon()}\n </div>\n <div>\n <h4 class=\"text-sm font-medium text-gray-900 dark:text-white truncate max-w-[200px]\">\n {props.params.filename}\n </h4>\n <p class=\"text-xs text-gray-500 dark:text-gray-400\">\n {formatSize(props.params.size)} • {props.params.description || 'Generated artifact'}\n </p>\n </div>\n </div>\n\n <a\n href={props.params.url}\n download={props.params.filename}\n class=\"px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 hover:bg-blue-100 dark:hover:bg-blue-900/40 rounded-md transition-colors flex items-center gap-1\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\" />\n </svg>\n Download\n </a>\n </div>\n )\n}\n"],"names":["ArtifactRenderer","props","getIcon","params","mimeType","includes","formatSize","bytes","toFixed","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$9","_co$","_$getNextMarker","_el$7","_el$0","_el$1","_co$2","_el$10","_$insert","filename","size","description","_$effect","_p$","_v$","url","_v$2","e","_$setAttribute","t","undefined"],"mappings":";;AAUO,MAAMA,mBAAoEC,CAAAA,UAAU;AACvF,QAAMC,UAAUA,MAAM;;AAClB,SAAID,WAAME,OAAOC,aAAbH,mBAAuBI,SAAS,OAAQ,QAAO;AACnD,SAAIJ,WAAME,OAAOC,aAAbH,mBAAuBI,SAAS,QAAS,QAAO;AACpD,SAAIJ,WAAME,OAAOC,aAAbH,mBAAuBI,SAAS,OAAQ,QAAO;AACnD,WAAO;AAAA,EACX;AAEA,QAAMC,aAAaA,CAACC,UAAmB;AACnC,QAAI,CAACA,MAAO,QAAO;AACnB,QAAIA,QAAQ,KAAM,QAAO,GAAGA,KAAK;AACjC,QAAIA,QAAQ,OAAO,KAAM,QAAO,IAAIA,QAAQ,MAAMC,QAAQ,CAAC,CAAC;AAC5D,WAAO,IAAID,SAAS,OAAO,OAAOC,QAAQ,CAAC,CAAC;AAAA,EAChD;AAEA,UAAA,MAAA;AAAA,QAAAC,OAAAC,eAAAC,MAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAC,YAAAE,QAAAD,MAAAE,aAAAC,QAAAF,MAAAF,YAAAK,QAAAD,MAAAD,aAAAG,QAAAD,MAAAL,YAAA,CAAAO,OAAAC,IAAA,IAAAC,cAAAH,MAAAH,WAAA,GAAAO,QAAAH,MAAAJ,aAAAQ,QAAAD,MAAAP,aAAA,CAAAS,OAAAC,KAAA,IAAAJ,cAAAE,MAAAR,WAAA,GAAAW,SAAAf,MAAAI;AAAAY,WAAAd,OAIiBZ,OAAO;AAAA0B,WAAAX,OAAA,MAIHhB,MAAME,OAAO0B,QAAQ;AAAAD,WAAAV,OAAA,MAGrBZ,WAAWL,MAAME,OAAO2B,IAAI,GAACV,OAAAC,IAAA;AAAAO,WAAAV,OAAA,MAAKjB,MAAME,OAAO4B,eAAe,sBAAoBN,OAAAC,KAAA;AAAAM,WAAAC,CAAAA,QAAA;AAAA,UAAAC,MAMrFjC,MAAME,OAAOgC,KAAGC,OACZnC,MAAME,OAAO0B;AAAQK,cAAAD,IAAAI,KAAAC,aAAAX,QAAA,QAAAM,IAAAI,IAAAH,GAAA;AAAAE,eAAAH,IAAAM,KAAAD,aAAAX,QAAA,YAAAM,IAAAM,IAAAH,IAAA;AAAA,aAAAH;AAAAA,IAAA,GAAA;AAAA,MAAAI,GAAAG;AAAAA,MAAAD,GAAAC;AAAAA,IAAAA,CAAA;AAAA,WAAA/B;AAAAA,EAAA,GAAA;AAU/C;"}
@@ -20,7 +20,12 @@ const CodeBlockRenderer = (props) => {
20
20
  if (!hljs) {
21
21
  try {
22
22
  const module2 = await Promise.resolve().then(() => require("../node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/index.cjs"));
23
- hljs = module2.default || module2;
23
+ const resolved = module2.default || module2;
24
+ if (typeof (resolved == null ? void 0 : resolved.highlight) === "function") {
25
+ hljs = resolved;
26
+ } else {
27
+ console.warn("highlight.js loaded but missing highlight() method");
28
+ }
24
29
  setIsHljsLoaded(true);
25
30
  } catch (e) {
26
31
  console.warn("Failed to load highlight.js", e);
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlockRenderer.cjs","sources":["../../src/components/CodeBlockRenderer.tsx"],"sourcesContent":["/**\n * CodeBlockRenderer - Syntax highlighted code block\n * Sprint 6: Code & Maps\n * Sprint Ultimate: Theme Synchronization (U.1)\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show, For } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport type { UIComponent, CodeComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load highlight.js\nlet hljs: any = null\n// Track if styles have been loaded globally\nlet stylesLoaded = false\n\nexport interface CodeBlockRendererProps {\n /**\n * UIComponent containing code params\n */\n component?: UIComponent\n\n /**\n * Direct code params\n */\n params?: CodeComponentParams\n}\n\nexport const CodeBlockRenderer: Component<CodeBlockRendererProps> = (props) => {\n const [highlightedCode, setHighlightedCode] = createSignal<string>('')\n const [isCopied, setIsCopied] = createSignal(false)\n const [isHljsLoaded, setIsHljsLoaded] = createSignal(false)\n const [activeTheme, setActiveTheme] = createSignal<'light' | 'dark'>('dark')\n const [wordWrap, setWordWrap] = createSignal(false)\n\n const params = () => props.params || (props.component?.params as CodeComponentParams)\n\n // Load highlight.js on mount\n createEffect(async () => {\n if (!hljs) {\n try {\n // Use the full highlight.js bundle with all languages for simplicity\n const module = await import('highlight.js')\n hljs = module.default || module\n setIsHljsLoaded(true)\n } catch (e) {\n console.warn('Failed to load highlight.js', e)\n // Continue without highlighting - fallback to plain text\n setIsHljsLoaded(true)\n }\n } else {\n setIsHljsLoaded(true)\n }\n })\n\n // Theme management - Sprint Ultimate U.1: Reactive theme synchronization\n // Load both theme stylesheets once, then toggle via data-attribute\n createEffect(async () => {\n if (isServer || stylesLoaded) return\n\n // Load both themes upfront for instant switching\n try {\n await Promise.all([\n import('highlight.js/styles/github.css'),\n import('highlight.js/styles/github-dark.css')\n ])\n stylesLoaded = true\n } catch (e) {\n console.warn('Failed to load highlight.js themes', e)\n }\n })\n\n // Reactive theme detection - listens to system preference changes\n createEffect(() => {\n if (isServer) return\n\n // Priority 1: Explicit theme from params\n const paramTheme = params()?.theme\n if (paramTheme) {\n setActiveTheme(paramTheme)\n return\n }\n\n // Priority 2: System preference with live updates\n // Check if matchMedia is available (not in all test environments)\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n setActiveTheme(mediaQuery.matches ? 'dark' : 'light')\n\n const handleChange = (e: MediaQueryListEvent) => {\n // Only update if no explicit theme in params\n if (!params()?.theme) {\n setActiveTheme(e.matches ? 'dark' : 'light')\n }\n }\n\n mediaQuery.addEventListener('change', handleChange)\n onCleanup(() => mediaQuery.removeEventListener('change', handleChange))\n }\n })\n\n // Apply highlighting\n createEffect(() => {\n const code = params()?.code || ''\n const language = params()?.language || ''\n\n if (hljs && isHljsLoaded()) {\n try {\n let result\n if (language && hljs.getLanguage(language)) {\n result = hljs.highlight(code, { language }).value\n } else {\n result = hljs.highlightAuto(code).value\n }\n setHighlightedCode(result)\n } catch (e) {\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n } else {\n // Fallback: simple escaping\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n })\n\n // Line numbers generation\n const lineNumbers = () => {\n if (params()?.showLineNumbers === false) return []\n const code = params()?.code || ''\n const lines = code.split('\\n')\n const start = params()?.startLine || 1\n return lines.map((_, i) => start + i)\n }\n\n const handleCopy = async () => {\n const code = params()?.code\n if (code) {\n try {\n await navigator.clipboard.writeText(code)\n setIsCopied(true)\n setTimeout(() => setIsCopied(false), 2000)\n } catch (e) {\n console.error('Failed to copy code', e)\n }\n }\n }\n\n return (\n <ExpandableWrapper title={params()?.filename || params()?.language || 'Code'} copyData={params()?.code} copyLabel=\"Copy code\">\n <div class=\"w-full bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden text-sm flex flex-col\">\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-2 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shrink-0\">\n <div class=\"font-mono text-xs text-gray-600 dark:text-gray-400\">\n {params()?.filename || params()?.language || 'Code'}\n </div>\n <div class=\"flex items-center gap-2\">\n {/* Word wrap toggle */}\n <button\n onClick={() => setWordWrap(!wordWrap())}\n class={`focus:outline-none transition-colors ${wordWrap() ? 'text-blue-500 dark:text-blue-400' : 'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200'}`}\n aria-label=\"Toggle word wrap\"\n title={wordWrap() ? 'Disable word wrap' : 'Enable word wrap'}\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h10a4 4 0 010 8H9m4 0l-3-3m3 3l-3 3M3 6h18M3 14h4\" />\n </svg>\n </button>\n {/* Copy button */}\n <button\n onClick={handleCopy}\n class=\"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 focus:outline-none transition-colors\"\n aria-label=\"Copy code\"\n title=\"Copy code\"\n >\n <Show when={isCopied()} fallback={\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n }>\n <svg class=\"w-4 h-4 text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </Show>\n </button>\n </div>\n </div>\n\n {/* Code Area */}\n <div\n class=\"relative overflow-auto flex\"\n style={params()?.maxHeight ? { 'max-height': params()?.maxHeight } : {}}\n >\n {/* Line Numbers */}\n <Show when={params()?.showLineNumbers !== false}>\n <div class=\"flex-none text-right select-none bg-gray-100 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 py-4 px-2 text-gray-400 font-mono text-xs leading-5\">\n <For each={lineNumbers()}>\n {(num) => <div class=\"px-2\">{num}</div>}\n </For>\n </div>\n </Show>\n\n {/* Code Content - Sprint Ultimate U.1: data-theme for reactive theming */}\n <pre\n class=\"flex-1 m-0 p-4 font-mono text-gray-800 dark:text-gray-100 bg-transparent leading-5\"\n style={wordWrap() ? { 'white-space': 'pre-wrap', 'word-break': 'break-all' } : {}}\n data-theme={activeTheme()}\n >\n <code\n class={`hljs ${params()?.language ? `language-${params()?.language}` : ''}`}\n innerHTML={highlightedCode()}\n />\n </pre>\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["hljs","stylesLoaded","CodeBlockRenderer","props","highlightedCode","setHighlightedCode","createSignal","isCopied","setIsCopied","isHljsLoaded","setIsHljsLoaded","activeTheme","setActiveTheme","wordWrap","setWordWrap","params","component","createEffect","module","default","e","console","warn","isServer","Promise","all","paramTheme","theme","window","matchMedia","mediaQuery","matches","handleChange","addEventListener","onCleanup","removeEventListener","code","language","result","getLanguage","highlight","value","highlightAuto","replace","lineNumbers","showLineNumbers","lines","split","start","startLine","map","_","i","handleCopy","navigator","clipboard","writeText","setTimeout","error","_$createComponent","ExpandableWrapper","title","filename","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$10","_el$11","_co$","_$getNextMarker","_el$0","_el$1","_$insert","$$click","Show","when","fallback","_tmpl$4","_tmpl$","_el$9","_tmpl$2","For","each","num","_el$13","_tmpl$5","_$effect","_p$","_v$","_v$2","_v$3","maxHeight","_v$4","_v$5","_v$6","_v$7","_$className","t","_$setAttribute","a","_$style","o","n","s","_$setProperty","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"CodeBlockRenderer.cjs","sources":["../../src/components/CodeBlockRenderer.tsx"],"sourcesContent":["/**\n * CodeBlockRenderer - Syntax highlighted code block\n * Sprint 6: Code & Maps\n * Sprint Ultimate: Theme Synchronization (U.1)\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show, For } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport type { UIComponent, CodeComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load highlight.js\nlet hljs: any = null\n// Track if styles have been loaded globally\nlet stylesLoaded = false\n\nexport interface CodeBlockRendererProps {\n /**\n * UIComponent containing code params\n */\n component?: UIComponent\n\n /**\n * Direct code params\n */\n params?: CodeComponentParams\n}\n\nexport const CodeBlockRenderer: Component<CodeBlockRendererProps> = (props) => {\n const [highlightedCode, setHighlightedCode] = createSignal<string>('')\n const [isCopied, setIsCopied] = createSignal(false)\n const [isHljsLoaded, setIsHljsLoaded] = createSignal(false)\n const [activeTheme, setActiveTheme] = createSignal<'light' | 'dark'>('dark')\n const [wordWrap, setWordWrap] = createSignal(false)\n\n const params = () => props.params || (props.component?.params as CodeComponentParams)\n\n // Load highlight.js on mount\n createEffect(async () => {\n if (!hljs) {\n try {\n // Use the full highlight.js bundle with all languages for simplicity\n const module = await import('highlight.js')\n const resolved = module.default || module\n // Guard: verify the resolved module has the expected API\n if (typeof resolved?.highlight === 'function') {\n hljs = resolved\n } else {\n console.warn('highlight.js loaded but missing highlight() method')\n }\n setIsHljsLoaded(true)\n } catch (e) {\n console.warn('Failed to load highlight.js', e)\n // Continue without highlighting - fallback to plain text\n setIsHljsLoaded(true)\n }\n } else {\n setIsHljsLoaded(true)\n }\n })\n\n // Theme management - Sprint Ultimate U.1: Reactive theme synchronization\n // Load both theme stylesheets once, then toggle via data-attribute\n createEffect(async () => {\n if (isServer || stylesLoaded) return\n\n // Load both themes upfront for instant switching\n try {\n await Promise.all([\n import('highlight.js/styles/github.css'),\n import('highlight.js/styles/github-dark.css')\n ])\n stylesLoaded = true\n } catch (e) {\n console.warn('Failed to load highlight.js themes', e)\n }\n })\n\n // Reactive theme detection - listens to system preference changes\n createEffect(() => {\n if (isServer) return\n\n // Priority 1: Explicit theme from params\n const paramTheme = params()?.theme\n if (paramTheme) {\n setActiveTheme(paramTheme)\n return\n }\n\n // Priority 2: System preference with live updates\n // Check if matchMedia is available (not in all test environments)\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n setActiveTheme(mediaQuery.matches ? 'dark' : 'light')\n\n const handleChange = (e: MediaQueryListEvent) => {\n // Only update if no explicit theme in params\n if (!params()?.theme) {\n setActiveTheme(e.matches ? 'dark' : 'light')\n }\n }\n\n mediaQuery.addEventListener('change', handleChange)\n onCleanup(() => mediaQuery.removeEventListener('change', handleChange))\n }\n })\n\n // Apply highlighting\n createEffect(() => {\n const code = params()?.code || ''\n const language = params()?.language || ''\n\n if (hljs && isHljsLoaded()) {\n try {\n let result\n if (language && hljs.getLanguage(language)) {\n result = hljs.highlight(code, { language }).value\n } else {\n result = hljs.highlightAuto(code).value\n }\n setHighlightedCode(result)\n } catch (e) {\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n } else {\n // Fallback: simple escaping\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n })\n\n // Line numbers generation\n const lineNumbers = () => {\n if (params()?.showLineNumbers === false) return []\n const code = params()?.code || ''\n const lines = code.split('\\n')\n const start = params()?.startLine || 1\n return lines.map((_, i) => start + i)\n }\n\n const handleCopy = async () => {\n const code = params()?.code\n if (code) {\n try {\n await navigator.clipboard.writeText(code)\n setIsCopied(true)\n setTimeout(() => setIsCopied(false), 2000)\n } catch (e) {\n console.error('Failed to copy code', e)\n }\n }\n }\n\n return (\n <ExpandableWrapper title={params()?.filename || params()?.language || 'Code'} copyData={params()?.code} copyLabel=\"Copy code\">\n <div class=\"w-full bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden text-sm flex flex-col\">\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-2 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shrink-0\">\n <div class=\"font-mono text-xs text-gray-600 dark:text-gray-400\">\n {params()?.filename || params()?.language || 'Code'}\n </div>\n <div class=\"flex items-center gap-2\">\n {/* Word wrap toggle */}\n <button\n onClick={() => setWordWrap(!wordWrap())}\n class={`focus:outline-none transition-colors ${wordWrap() ? 'text-blue-500 dark:text-blue-400' : 'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200'}`}\n aria-label=\"Toggle word wrap\"\n title={wordWrap() ? 'Disable word wrap' : 'Enable word wrap'}\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h10a4 4 0 010 8H9m4 0l-3-3m3 3l-3 3M3 6h18M3 14h4\" />\n </svg>\n </button>\n {/* Copy button */}\n <button\n onClick={handleCopy}\n class=\"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 focus:outline-none transition-colors\"\n aria-label=\"Copy code\"\n title=\"Copy code\"\n >\n <Show when={isCopied()} fallback={\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n }>\n <svg class=\"w-4 h-4 text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </Show>\n </button>\n </div>\n </div>\n\n {/* Code Area */}\n <div\n class=\"relative overflow-auto flex\"\n style={params()?.maxHeight ? { 'max-height': params()?.maxHeight } : {}}\n >\n {/* Line Numbers */}\n <Show when={params()?.showLineNumbers !== false}>\n <div class=\"flex-none text-right select-none bg-gray-100 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 py-4 px-2 text-gray-400 font-mono text-xs leading-5\">\n <For each={lineNumbers()}>\n {(num) => <div class=\"px-2\">{num}</div>}\n </For>\n </div>\n </Show>\n\n {/* Code Content - Sprint Ultimate U.1: data-theme for reactive theming */}\n <pre\n class=\"flex-1 m-0 p-4 font-mono text-gray-800 dark:text-gray-100 bg-transparent leading-5\"\n style={wordWrap() ? { 'white-space': 'pre-wrap', 'word-break': 'break-all' } : {}}\n data-theme={activeTheme()}\n >\n <code\n class={`hljs ${params()?.language ? `language-${params()?.language}` : ''}`}\n innerHTML={highlightedCode()}\n />\n </pre>\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["hljs","stylesLoaded","CodeBlockRenderer","props","highlightedCode","setHighlightedCode","createSignal","isCopied","setIsCopied","isHljsLoaded","setIsHljsLoaded","activeTheme","setActiveTheme","wordWrap","setWordWrap","params","component","createEffect","module","resolved","default","highlight","console","warn","e","isServer","Promise","all","paramTheme","theme","window","matchMedia","mediaQuery","matches","handleChange","addEventListener","onCleanup","removeEventListener","code","language","result","getLanguage","value","highlightAuto","replace","lineNumbers","showLineNumbers","lines","split","start","startLine","map","_","i","handleCopy","navigator","clipboard","writeText","setTimeout","error","_$createComponent","ExpandableWrapper","title","filename","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$10","_el$11","_co$","_$getNextMarker","_el$0","_el$1","_$insert","$$click","Show","when","fallback","_tmpl$4","_tmpl$","_el$9","_tmpl$2","For","each","num","_el$13","_tmpl$5","_$effect","_p$","_v$","_v$2","_v$3","maxHeight","_v$4","_v$5","_v$6","_v$7","_$className","t","_$setAttribute","a","_$style","o","n","s","_$setProperty","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlockRenderer.d.ts","sourceRoot":"","sources":["../../src/components/CodeBlockRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAoD,MAAM,UAAU,CAAA;AAEtF,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAQhE,MAAM,WAAW,sBAAsB;IACnC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,mBAAmB,CAAA;CAC/B;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,sBAAsB,CA2L/D,CAAA"}
1
+ {"version":3,"file":"CodeBlockRenderer.d.ts","sourceRoot":"","sources":["../../src/components/CodeBlockRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAoD,MAAM,UAAU,CAAA;AAEtF,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAQhE,MAAM,WAAW,sBAAsB;IACnC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,mBAAmB,CAAA;CAC/B;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,CAAC,sBAAsB,CAiM/D,CAAA"}
@@ -18,7 +18,12 @@ const CodeBlockRenderer = (props) => {
18
18
  if (!hljs) {
19
19
  try {
20
20
  const module = await import("../node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/index.js");
21
- hljs = module.default || module;
21
+ const resolved = module.default || module;
22
+ if (typeof (resolved == null ? void 0 : resolved.highlight) === "function") {
23
+ hljs = resolved;
24
+ } else {
25
+ console.warn("highlight.js loaded but missing highlight() method");
26
+ }
22
27
  setIsHljsLoaded(true);
23
28
  } catch (e) {
24
29
  console.warn("Failed to load highlight.js", e);
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlockRenderer.js","sources":["../../src/components/CodeBlockRenderer.tsx"],"sourcesContent":["/**\n * CodeBlockRenderer - Syntax highlighted code block\n * Sprint 6: Code & Maps\n * Sprint Ultimate: Theme Synchronization (U.1)\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show, For } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport type { UIComponent, CodeComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load highlight.js\nlet hljs: any = null\n// Track if styles have been loaded globally\nlet stylesLoaded = false\n\nexport interface CodeBlockRendererProps {\n /**\n * UIComponent containing code params\n */\n component?: UIComponent\n\n /**\n * Direct code params\n */\n params?: CodeComponentParams\n}\n\nexport const CodeBlockRenderer: Component<CodeBlockRendererProps> = (props) => {\n const [highlightedCode, setHighlightedCode] = createSignal<string>('')\n const [isCopied, setIsCopied] = createSignal(false)\n const [isHljsLoaded, setIsHljsLoaded] = createSignal(false)\n const [activeTheme, setActiveTheme] = createSignal<'light' | 'dark'>('dark')\n const [wordWrap, setWordWrap] = createSignal(false)\n\n const params = () => props.params || (props.component?.params as CodeComponentParams)\n\n // Load highlight.js on mount\n createEffect(async () => {\n if (!hljs) {\n try {\n // Use the full highlight.js bundle with all languages for simplicity\n const module = await import('highlight.js')\n hljs = module.default || module\n setIsHljsLoaded(true)\n } catch (e) {\n console.warn('Failed to load highlight.js', e)\n // Continue without highlighting - fallback to plain text\n setIsHljsLoaded(true)\n }\n } else {\n setIsHljsLoaded(true)\n }\n })\n\n // Theme management - Sprint Ultimate U.1: Reactive theme synchronization\n // Load both theme stylesheets once, then toggle via data-attribute\n createEffect(async () => {\n if (isServer || stylesLoaded) return\n\n // Load both themes upfront for instant switching\n try {\n await Promise.all([\n import('highlight.js/styles/github.css'),\n import('highlight.js/styles/github-dark.css')\n ])\n stylesLoaded = true\n } catch (e) {\n console.warn('Failed to load highlight.js themes', e)\n }\n })\n\n // Reactive theme detection - listens to system preference changes\n createEffect(() => {\n if (isServer) return\n\n // Priority 1: Explicit theme from params\n const paramTheme = params()?.theme\n if (paramTheme) {\n setActiveTheme(paramTheme)\n return\n }\n\n // Priority 2: System preference with live updates\n // Check if matchMedia is available (not in all test environments)\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n setActiveTheme(mediaQuery.matches ? 'dark' : 'light')\n\n const handleChange = (e: MediaQueryListEvent) => {\n // Only update if no explicit theme in params\n if (!params()?.theme) {\n setActiveTheme(e.matches ? 'dark' : 'light')\n }\n }\n\n mediaQuery.addEventListener('change', handleChange)\n onCleanup(() => mediaQuery.removeEventListener('change', handleChange))\n }\n })\n\n // Apply highlighting\n createEffect(() => {\n const code = params()?.code || ''\n const language = params()?.language || ''\n\n if (hljs && isHljsLoaded()) {\n try {\n let result\n if (language && hljs.getLanguage(language)) {\n result = hljs.highlight(code, { language }).value\n } else {\n result = hljs.highlightAuto(code).value\n }\n setHighlightedCode(result)\n } catch (e) {\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n } else {\n // Fallback: simple escaping\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n })\n\n // Line numbers generation\n const lineNumbers = () => {\n if (params()?.showLineNumbers === false) return []\n const code = params()?.code || ''\n const lines = code.split('\\n')\n const start = params()?.startLine || 1\n return lines.map((_, i) => start + i)\n }\n\n const handleCopy = async () => {\n const code = params()?.code\n if (code) {\n try {\n await navigator.clipboard.writeText(code)\n setIsCopied(true)\n setTimeout(() => setIsCopied(false), 2000)\n } catch (e) {\n console.error('Failed to copy code', e)\n }\n }\n }\n\n return (\n <ExpandableWrapper title={params()?.filename || params()?.language || 'Code'} copyData={params()?.code} copyLabel=\"Copy code\">\n <div class=\"w-full bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden text-sm flex flex-col\">\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-2 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shrink-0\">\n <div class=\"font-mono text-xs text-gray-600 dark:text-gray-400\">\n {params()?.filename || params()?.language || 'Code'}\n </div>\n <div class=\"flex items-center gap-2\">\n {/* Word wrap toggle */}\n <button\n onClick={() => setWordWrap(!wordWrap())}\n class={`focus:outline-none transition-colors ${wordWrap() ? 'text-blue-500 dark:text-blue-400' : 'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200'}`}\n aria-label=\"Toggle word wrap\"\n title={wordWrap() ? 'Disable word wrap' : 'Enable word wrap'}\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h10a4 4 0 010 8H9m4 0l-3-3m3 3l-3 3M3 6h18M3 14h4\" />\n </svg>\n </button>\n {/* Copy button */}\n <button\n onClick={handleCopy}\n class=\"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 focus:outline-none transition-colors\"\n aria-label=\"Copy code\"\n title=\"Copy code\"\n >\n <Show when={isCopied()} fallback={\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n }>\n <svg class=\"w-4 h-4 text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </Show>\n </button>\n </div>\n </div>\n\n {/* Code Area */}\n <div\n class=\"relative overflow-auto flex\"\n style={params()?.maxHeight ? { 'max-height': params()?.maxHeight } : {}}\n >\n {/* Line Numbers */}\n <Show when={params()?.showLineNumbers !== false}>\n <div class=\"flex-none text-right select-none bg-gray-100 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 py-4 px-2 text-gray-400 font-mono text-xs leading-5\">\n <For each={lineNumbers()}>\n {(num) => <div class=\"px-2\">{num}</div>}\n </For>\n </div>\n </Show>\n\n {/* Code Content - Sprint Ultimate U.1: data-theme for reactive theming */}\n <pre\n class=\"flex-1 m-0 p-4 font-mono text-gray-800 dark:text-gray-100 bg-transparent leading-5\"\n style={wordWrap() ? { 'white-space': 'pre-wrap', 'word-break': 'break-all' } : {}}\n data-theme={activeTheme()}\n >\n <code\n class={`hljs ${params()?.language ? `language-${params()?.language}` : ''}`}\n innerHTML={highlightedCode()}\n />\n </pre>\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["hljs","stylesLoaded","CodeBlockRenderer","props","highlightedCode","setHighlightedCode","createSignal","isCopied","setIsCopied","isHljsLoaded","setIsHljsLoaded","activeTheme","setActiveTheme","wordWrap","setWordWrap","params","component","createEffect","module","default","e","console","warn","isServer","Promise","all","paramTheme","theme","window","matchMedia","mediaQuery","matches","handleChange","addEventListener","onCleanup","removeEventListener","code","language","result","getLanguage","highlight","value","highlightAuto","replace","lineNumbers","showLineNumbers","lines","split","start","startLine","map","_","i","handleCopy","navigator","clipboard","writeText","setTimeout","error","_$createComponent","ExpandableWrapper","title","filename","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$10","_el$11","_co$","_$getNextMarker","_el$0","_el$1","_$insert","$$click","Show","when","fallback","_tmpl$4","_tmpl$","_el$9","_tmpl$2","For","each","num","_el$13","_tmpl$5","_$effect","_p$","_v$","_v$2","_v$3","maxHeight","_v$4","_v$5","_v$6","_v$7","_$className","t","_$setAttribute","a","_$style","o","n","s","_$setProperty","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"CodeBlockRenderer.js","sources":["../../src/components/CodeBlockRenderer.tsx"],"sourcesContent":["/**\n * CodeBlockRenderer - Syntax highlighted code block\n * Sprint 6: Code & Maps\n * Sprint Ultimate: Theme Synchronization (U.1)\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show, For } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport type { UIComponent, CodeComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load highlight.js\nlet hljs: any = null\n// Track if styles have been loaded globally\nlet stylesLoaded = false\n\nexport interface CodeBlockRendererProps {\n /**\n * UIComponent containing code params\n */\n component?: UIComponent\n\n /**\n * Direct code params\n */\n params?: CodeComponentParams\n}\n\nexport const CodeBlockRenderer: Component<CodeBlockRendererProps> = (props) => {\n const [highlightedCode, setHighlightedCode] = createSignal<string>('')\n const [isCopied, setIsCopied] = createSignal(false)\n const [isHljsLoaded, setIsHljsLoaded] = createSignal(false)\n const [activeTheme, setActiveTheme] = createSignal<'light' | 'dark'>('dark')\n const [wordWrap, setWordWrap] = createSignal(false)\n\n const params = () => props.params || (props.component?.params as CodeComponentParams)\n\n // Load highlight.js on mount\n createEffect(async () => {\n if (!hljs) {\n try {\n // Use the full highlight.js bundle with all languages for simplicity\n const module = await import('highlight.js')\n const resolved = module.default || module\n // Guard: verify the resolved module has the expected API\n if (typeof resolved?.highlight === 'function') {\n hljs = resolved\n } else {\n console.warn('highlight.js loaded but missing highlight() method')\n }\n setIsHljsLoaded(true)\n } catch (e) {\n console.warn('Failed to load highlight.js', e)\n // Continue without highlighting - fallback to plain text\n setIsHljsLoaded(true)\n }\n } else {\n setIsHljsLoaded(true)\n }\n })\n\n // Theme management - Sprint Ultimate U.1: Reactive theme synchronization\n // Load both theme stylesheets once, then toggle via data-attribute\n createEffect(async () => {\n if (isServer || stylesLoaded) return\n\n // Load both themes upfront for instant switching\n try {\n await Promise.all([\n import('highlight.js/styles/github.css'),\n import('highlight.js/styles/github-dark.css')\n ])\n stylesLoaded = true\n } catch (e) {\n console.warn('Failed to load highlight.js themes', e)\n }\n })\n\n // Reactive theme detection - listens to system preference changes\n createEffect(() => {\n if (isServer) return\n\n // Priority 1: Explicit theme from params\n const paramTheme = params()?.theme\n if (paramTheme) {\n setActiveTheme(paramTheme)\n return\n }\n\n // Priority 2: System preference with live updates\n // Check if matchMedia is available (not in all test environments)\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n setActiveTheme(mediaQuery.matches ? 'dark' : 'light')\n\n const handleChange = (e: MediaQueryListEvent) => {\n // Only update if no explicit theme in params\n if (!params()?.theme) {\n setActiveTheme(e.matches ? 'dark' : 'light')\n }\n }\n\n mediaQuery.addEventListener('change', handleChange)\n onCleanup(() => mediaQuery.removeEventListener('change', handleChange))\n }\n })\n\n // Apply highlighting\n createEffect(() => {\n const code = params()?.code || ''\n const language = params()?.language || ''\n\n if (hljs && isHljsLoaded()) {\n try {\n let result\n if (language && hljs.getLanguage(language)) {\n result = hljs.highlight(code, { language }).value\n } else {\n result = hljs.highlightAuto(code).value\n }\n setHighlightedCode(result)\n } catch (e) {\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n } else {\n // Fallback: simple escaping\n setHighlightedCode(code.replace(/</g, '&lt;').replace(/>/g, '&gt;'))\n }\n })\n\n // Line numbers generation\n const lineNumbers = () => {\n if (params()?.showLineNumbers === false) return []\n const code = params()?.code || ''\n const lines = code.split('\\n')\n const start = params()?.startLine || 1\n return lines.map((_, i) => start + i)\n }\n\n const handleCopy = async () => {\n const code = params()?.code\n if (code) {\n try {\n await navigator.clipboard.writeText(code)\n setIsCopied(true)\n setTimeout(() => setIsCopied(false), 2000)\n } catch (e) {\n console.error('Failed to copy code', e)\n }\n }\n }\n\n return (\n <ExpandableWrapper title={params()?.filename || params()?.language || 'Code'} copyData={params()?.code} copyLabel=\"Copy code\">\n <div class=\"w-full bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden text-sm flex flex-col\">\n {/* Header */}\n <div class=\"flex items-center justify-between px-4 py-2 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 shrink-0\">\n <div class=\"font-mono text-xs text-gray-600 dark:text-gray-400\">\n {params()?.filename || params()?.language || 'Code'}\n </div>\n <div class=\"flex items-center gap-2\">\n {/* Word wrap toggle */}\n <button\n onClick={() => setWordWrap(!wordWrap())}\n class={`focus:outline-none transition-colors ${wordWrap() ? 'text-blue-500 dark:text-blue-400' : 'text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200'}`}\n aria-label=\"Toggle word wrap\"\n title={wordWrap() ? 'Disable word wrap' : 'Enable word wrap'}\n >\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h10a4 4 0 010 8H9m4 0l-3-3m3 3l-3 3M3 6h18M3 14h4\" />\n </svg>\n </button>\n {/* Copy button */}\n <button\n onClick={handleCopy}\n class=\"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 focus:outline-none transition-colors\"\n aria-label=\"Copy code\"\n title=\"Copy code\"\n >\n <Show when={isCopied()} fallback={\n <svg class=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\" />\n </svg>\n }>\n <svg class=\"w-4 h-4 text-green-500\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n </svg>\n </Show>\n </button>\n </div>\n </div>\n\n {/* Code Area */}\n <div\n class=\"relative overflow-auto flex\"\n style={params()?.maxHeight ? { 'max-height': params()?.maxHeight } : {}}\n >\n {/* Line Numbers */}\n <Show when={params()?.showLineNumbers !== false}>\n <div class=\"flex-none text-right select-none bg-gray-100 dark:bg-gray-800 border-r border-gray-200 dark:border-gray-700 py-4 px-2 text-gray-400 font-mono text-xs leading-5\">\n <For each={lineNumbers()}>\n {(num) => <div class=\"px-2\">{num}</div>}\n </For>\n </div>\n </Show>\n\n {/* Code Content - Sprint Ultimate U.1: data-theme for reactive theming */}\n <pre\n class=\"flex-1 m-0 p-4 font-mono text-gray-800 dark:text-gray-100 bg-transparent leading-5\"\n style={wordWrap() ? { 'white-space': 'pre-wrap', 'word-break': 'break-all' } : {}}\n data-theme={activeTheme()}\n >\n <code\n class={`hljs ${params()?.language ? `language-${params()?.language}` : ''}`}\n innerHTML={highlightedCode()}\n />\n </pre>\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["hljs","stylesLoaded","CodeBlockRenderer","props","highlightedCode","setHighlightedCode","createSignal","isCopied","setIsCopied","isHljsLoaded","setIsHljsLoaded","activeTheme","setActiveTheme","wordWrap","setWordWrap","params","component","createEffect","module","resolved","default","highlight","console","warn","e","isServer","Promise","all","paramTheme","theme","window","matchMedia","mediaQuery","matches","handleChange","addEventListener","onCleanup","removeEventListener","code","language","result","getLanguage","value","highlightAuto","replace","lineNumbers","showLineNumbers","lines","split","start","startLine","map","_","i","handleCopy","navigator","clipboard","writeText","setTimeout","error","_$createComponent","ExpandableWrapper","title","filename","copyData","copyLabel","children","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$8","_el$10","_el$11","_co$","_$getNextMarker","_el$0","_el$1","_$insert","$$click","Show","when","fallback","_tmpl$4","_tmpl$","_el$9","_tmpl$2","For","each","num","_el$13","_tmpl$5","_$effect","_p$","_v$","_v$2","_v$3","maxHeight","_v$4","_v$5","_v$6","_v$7","_$className","t","_$setAttribute","a","_$style","o","n","s","_$setProperty","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
@@ -21,7 +21,7 @@ const ExpandableWrapper = require("./ExpandableWrapper.cjs");
21
21
  const RenderContext = require("./RenderContext.cjs");
22
22
  const useAction = require("../hooks/useAction.cjs");
23
23
  const marked_esm = require("../node_modules/.pnpm/marked@16.4.2/node_modules/marked/lib/marked.esm.cjs");
24
- var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button>`), _tmpl$3 = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 text-green-500"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><p class="text-red-500 dark:text-red-400 text-sm">Invalid chart data: missing data.datasets`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600">`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center p-4"><div class=text-center><p class="text-red-600 dark:text-red-400 text-sm font-medium">Chart Error</p><p class="text-gray-600 dark:text-gray-400 text-xs mt-1">`), _tmpl$7 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3">`), _tmpl$8 = /* @__PURE__ */ web.template(`<div class="w-full h-full p-4"><!$><!/><div class="w-full h-full"role=img><img class="w-full h-auto max-h-[300px] object-contain">`), _tmpl$9 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full min-h-[300px] bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><!$><!/><!$><!/>`), _tmpl$0 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">`), _tmpl$1 = /* @__PURE__ */ web.template(`<tr>`), _tmpl$10 = /* @__PURE__ */ web.template(`<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6"><div>`), _tmpl$11 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 relative">`), _tmpl$12 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Copy TSV`), _tmpl$13 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download CSV`), _tmpl$14 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download JSON`), _tmpl$15 = /* @__PURE__ */ web.template(`<div class="absolute right-0 mt-1 w-36 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1 text-sm"><!$><!/><!$><!/><!$><!/>`), _tmpl$16 = /* @__PURE__ */ web.template(`<div class="absolute right-10 top-2 z-10"><button class="opacity-60 hover:opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"title="Export table"aria-label="Export table"><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg></button><!$><!/>`), _tmpl$17 = /* @__PURE__ */ web.template(`<span class="ml-2 text-xs font-normal text-gray-400">(virtualized: <!$><!/> rows)`), _tmpl$18 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3"><!$><!/><!$><!/>`), _tmpl$19 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!$><!/> - <!$><!/> of <!$><!/>`), _tmpl$20 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden group"><!$><!/><div class=p-4><!$><!/><div class=overflow-x-auto role=region tabindex=0><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"><thead class="bg-gray-50 dark:bg-gray-900/50 sticky top-0 z-10"><tr></tr></thead><!$><!/></table></div><!$><!/>`), _tmpl$21 = /* @__PURE__ */ web.template(`<th scope=col class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-50 dark:bg-gray-900/50">`), _tmpl$22 = /* @__PURE__ */ web.template(`<span class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">`), _tmpl$23 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center"><span><!$><!/> <!$><!/>%`), _tmpl$24 = /* @__PURE__ */ web.template(`<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">`), _tmpl$25 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div class="flex flex-col h-full justify-between"><div><p class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide"></p><div class="mt-2 flex items-baseline"><p class="text-2xl font-semibold text-gray-900 dark:text-white"></p><!$><!/></div></div><!$><!/><!$><!/>`), _tmpl$26 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div>`), _tmpl$27 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class=cursor-zoom-in><img class="max-w-full max-h-[400px] object-contain rounded shadow-sm hover:opacity-90 transition-opacity"loading=lazy></a></div><div class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center italic">`, true, false, false), _tmpl$28 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$29 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><!$><!/><iframe class="w-full border-0 flex-1"sandbox="allow-scripts allow-same-origin allow-popups allow-forms"loading=lazy>`, true, false, false), _tmpl$30 = /* @__PURE__ */ web.template(`<figcaption class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center">`), _tmpl$31 = /* @__PURE__ */ web.template(`<figure><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class="cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded"><img class="max-w-full max-h-[500px] object-contain rounded shadow-sm hover:opacity-95 transition-opacity"loading=lazy></a></div><!$><!/>`, true, false, false), _tmpl$32 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 truncate">`), _tmpl$33 = /* @__PURE__ */ web.template(`<a target=_blank rel="noopener noreferrer"><div class="p-2 bg-blue-50 dark:bg-blue-900/30 rounded-full text-blue-600 dark:text-blue-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 shrink-0 transition-colors"aria-hidden=true><svg xmlns=http://www.w3.org/2000/svg class="w-5 h-5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"></h4><!$><!/></div><svg xmlns=http://www.w3.org/2000/svg class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0 transition-colors"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1=10 y1=14 x2=21 y2=3>`), _tmpl$34 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4"><p class="text-sm font-medium text-red-900 dark:text-red-100">Validation Error</p><p class="text-xs text-red-700 dark:text-red-300 mt-1">`), _tmpl$35 = /* @__PURE__ */ web.template(`<span aria-hidden=true>`), _tmpl$36 = /* @__PURE__ */ web.template(`<a rel="noopener noreferrer"><!$><!/><!$><!/>`), _tmpl$37 = /* @__PURE__ */ web.template(`<span class="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full"aria-hidden=true>`), _tmpl$38 = /* @__PURE__ */ web.template(`<button><!$><!/><!$><!/><!$><!/>`), _tmpl$39 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-600 dark:text-red-400 mt-1">Type: <!$><!/>`), _tmpl$40 = /* @__PURE__ */ web.template(`<div class=mt-3><p class="text-xs font-medium text-red-700 dark:text-red-300">Suggestions:</p><ul class="mt-1 text-xs text-red-600 dark:text-red-400 list-disc list-inside">`), _tmpl$41 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-500 dark:text-red-500 mt-2">`), _tmpl$42 = /* @__PURE__ */ web.template(`<div class="relative w-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 group"><!$><!/><div class="flex items-start gap-3"><div class="p-2 bg-red-100 dark:bg-red-900/40 rounded-full shrink-0"><svg class="w-5 h-5 text-red-600 dark:text-red-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-semibold text-red-800 dark:text-red-200">Tool Error: <!$><!/></h4><p class="text-sm text-red-700 dark:text-red-300 mt-1"></p><!$><!/><!$><!/><!$><!/>`), _tmpl$43 = /* @__PURE__ */ web.template(`<li>`), _tmpl$44 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white capitalize">`), _tmpl$45 = /* @__PURE__ */ web.template(`<div class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><div class="p-4 prose prose-sm dark:prose-invert max-w-none">`), _tmpl$46 = /* @__PURE__ */ web.template(`<div><div class="grid gap-4"></div><!$><!/>`), _tmpl$47 = /* @__PURE__ */ web.template(`<div>`);
24
+ var _tmpl$ = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button>`), _tmpl$3 = /* @__PURE__ */ web.template(`<svg class="w-3 h-3 text-green-500"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M5 13l4 4L19 7">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"><p class="text-red-500 dark:text-red-400 text-sm">Invalid chart data: missing data.datasets`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600">`), _tmpl$6 = /* @__PURE__ */ web.template(`<div class="absolute inset-0 flex items-center justify-center p-4"><div class=text-center><p class="text-red-600 dark:text-red-400 text-sm font-medium">Chart Error</p><p class="text-gray-600 dark:text-gray-400 text-xs mt-1">`), _tmpl$7 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3">`), _tmpl$8 = /* @__PURE__ */ web.template(`<div class="w-full h-full p-4"><!$><!/><div class="w-full h-full"role=img><img class="w-full h-auto max-h-[300px] object-contain">`), _tmpl$9 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full min-h-[300px] bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><!$><!/><!$><!/>`), _tmpl$0 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">`), _tmpl$1 = /* @__PURE__ */ web.template(`<tr>`), _tmpl$10 = /* @__PURE__ */ web.template(`<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6"><div>`), _tmpl$11 = /* @__PURE__ */ web.template(`<tbody class="bg-white dark:bg-gray-800 relative">`), _tmpl$12 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Copy TSV`), _tmpl$13 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download CSV`), _tmpl$14 = /* @__PURE__ */ web.template(`<button class="w-full text-left px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">Download JSON`), _tmpl$15 = /* @__PURE__ */ web.template(`<div class="absolute right-0 mt-1 w-36 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1 text-sm"><!$><!/><!$><!/><!$><!/>`), _tmpl$16 = /* @__PURE__ */ web.template(`<div class="absolute right-10 top-2 z-10"><button class="opacity-60 hover:opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"title="Export table"aria-label="Export table"><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg></button><!$><!/>`), _tmpl$17 = /* @__PURE__ */ web.template(`<span class="ml-2 text-xs font-normal text-gray-400">(virtualized: <!$><!/> rows)`), _tmpl$18 = /* @__PURE__ */ web.template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3"><!$><!/><!$><!/>`), _tmpl$19 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!$><!/> - <!$><!/> of <!$><!/>`), _tmpl$20 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden group"><!$><!/><div class=p-4><!$><!/><div class=overflow-x-auto role=region tabindex=0><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"><thead class="bg-gray-50 dark:bg-gray-900/50 sticky top-0 z-10"><tr></tr></thead><!$><!/></table></div><!$><!/>`), _tmpl$21 = /* @__PURE__ */ web.template(`<th scope=col class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-50 dark:bg-gray-900/50">`), _tmpl$22 = /* @__PURE__ */ web.template(`<span class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">`), _tmpl$23 = /* @__PURE__ */ web.template(`<div class="mt-3 flex items-center"><span><!$><!/> <!$><!/>%`), _tmpl$24 = /* @__PURE__ */ web.template(`<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">`), _tmpl$25 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div class="flex flex-col h-full justify-between"><div><p class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide"></p><div class="mt-2 flex items-baseline"><p class="text-2xl font-semibold text-gray-900 dark:text-white"></p><!$><!/></div></div><!$><!/><!$><!/>`), _tmpl$26 = /* @__PURE__ */ web.template(`<div class="relative w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 group"><!$><!/><div>`), _tmpl$27 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class=cursor-zoom-in><img class="max-w-full max-h-[400px] object-contain rounded shadow-sm hover:opacity-90 transition-opacity"loading=lazy></a></div><div class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center italic">`, true, false, false), _tmpl$28 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$29 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col"><!$><!/><iframe class="w-full border-0 flex-1"loading=lazy>`, true, false, false), _tmpl$30 = /* @__PURE__ */ web.template(`<figcaption class="p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800"><p class="text-sm text-gray-600 dark:text-gray-400 text-center">`), _tmpl$31 = /* @__PURE__ */ web.template(`<figure><div class="flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]"><a target=_blank rel="noopener noreferrer"class="cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded"><img class="max-w-full max-h-[500px] object-contain rounded shadow-sm hover:opacity-95 transition-opacity"loading=lazy></a></div><!$><!/>`, true, false, false), _tmpl$32 = /* @__PURE__ */ web.template(`<p class="text-xs text-gray-500 dark:text-gray-400 truncate">`), _tmpl$33 = /* @__PURE__ */ web.template(`<a target=_blank rel="noopener noreferrer"><div class="p-2 bg-blue-50 dark:bg-blue-900/30 rounded-full text-blue-600 dark:text-blue-400 group-hover:bg-blue-100 dark:group-hover:bg-blue-900/50 shrink-0 transition-colors"aria-hidden=true><svg xmlns=http://www.w3.org/2000/svg class="w-5 h-5"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-medium text-gray-900 dark:text-white truncate group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors"></h4><!$><!/></div><svg xmlns=http://www.w3.org/2000/svg class="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0 transition-colors"viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1=10 y1=14 x2=21 y2=3>`), _tmpl$34 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4"><p class="text-sm font-medium text-red-900 dark:text-red-100">Validation Error</p><p class="text-xs text-red-700 dark:text-red-300 mt-1">`), _tmpl$35 = /* @__PURE__ */ web.template(`<span aria-hidden=true>`), _tmpl$36 = /* @__PURE__ */ web.template(`<a rel="noopener noreferrer"><!$><!/><!$><!/>`), _tmpl$37 = /* @__PURE__ */ web.template(`<span class="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full"aria-hidden=true>`), _tmpl$38 = /* @__PURE__ */ web.template(`<button><!$><!/><!$><!/><!$><!/>`), _tmpl$39 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-600 dark:text-red-400 mt-1">Type: <!$><!/>`), _tmpl$40 = /* @__PURE__ */ web.template(`<div class=mt-3><p class="text-xs font-medium text-red-700 dark:text-red-300">Suggestions:</p><ul class="mt-1 text-xs text-red-600 dark:text-red-400 list-disc list-inside">`), _tmpl$41 = /* @__PURE__ */ web.template(`<p class="text-xs text-red-500 dark:text-red-500 mt-2">`), _tmpl$42 = /* @__PURE__ */ web.template(`<div class="relative w-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 group"><!$><!/><div class="flex items-start gap-3"><div class="p-2 bg-red-100 dark:bg-red-900/40 rounded-full shrink-0"><svg class="w-5 h-5 text-red-600 dark:text-red-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><h4 class="text-sm font-semibold text-red-800 dark:text-red-200">Tool Error: <!$><!/></h4><p class="text-sm text-red-700 dark:text-red-300 mt-1"></p><!$><!/><!$><!/><!$><!/>`), _tmpl$43 = /* @__PURE__ */ web.template(`<li>`), _tmpl$44 = /* @__PURE__ */ web.template(`<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"><h3 class="text-sm font-semibold text-gray-900 dark:text-white capitalize">`), _tmpl$45 = /* @__PURE__ */ web.template(`<div class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><!$><!/><div class="p-4 prose prose-sm dark:prose-invert max-w-none">`), _tmpl$46 = /* @__PURE__ */ web.template(`<div><div class="grid gap-4"></div><!$><!/>`), _tmpl$47 = /* @__PURE__ */ web.template(`<div>`);
25
25
  function CopyButton(props) {
26
26
  const [copied, setCopied] = solidJs.createSignal(false);
27
27
  const handleCopy = async () => {
@@ -743,15 +743,17 @@ function IframeRenderer(props) {
743
743
  }
744
744
  }), _el$120, _co$24);
745
745
  web.effect((_p$) => {
746
- var _v$14 = params.url, _v$15 = params.title || "Embedded content", _v$16 = `height: ${params.height || "400px"}; min-height: 300px;`;
746
+ var _v$14 = params.url, _v$15 = params.title || "Embedded content", _v$16 = `height: ${params.height || "400px"}; min-height: 300px;`, _v$17 = validation.getIframeSandbox(params.url);
747
747
  _v$14 !== _p$.e && web.setAttribute(_el$118, "src", _p$.e = _v$14);
748
748
  _v$15 !== _p$.t && web.setAttribute(_el$118, "title", _p$.t = _v$15);
749
749
  _p$.a = web.style(_el$118, _v$16, _p$.a);
750
+ _v$17 !== _p$.o && web.setAttribute(_el$118, "sandbox", _p$.o = _v$17);
750
751
  return _p$;
751
752
  }, {
752
753
  e: void 0,
753
754
  t: void 0,
754
- a: void 0
755
+ a: void 0,
756
+ o: void 0
755
757
  });
756
758
  return _el$115;
757
759
  })();
@@ -771,12 +773,12 @@ function ImageRenderer(props) {
771
773
  }
772
774
  }), _el$128, _co$25);
773
775
  web.effect((_p$) => {
774
- var _v$17 = `w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col ${params.className || ""}`, _v$18 = params.url, _v$19 = `View full size: ${params.alt || "image"}`, _v$20 = params.url, _v$21 = params.alt || "Image";
775
- _v$17 !== _p$.e && web.className(_el$121, _p$.e = _v$17);
776
- _v$18 !== _p$.t && web.setAttribute(_el$123, "href", _p$.t = _v$18);
777
- _v$19 !== _p$.a && web.setAttribute(_el$123, "aria-label", _p$.a = _v$19);
778
- _v$20 !== _p$.o && web.setAttribute(_el$124, "src", _p$.o = _v$20);
779
- _v$21 !== _p$.i && web.setAttribute(_el$124, "alt", _p$.i = _v$21);
776
+ var _v$18 = `w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col ${params.className || ""}`, _v$19 = params.url, _v$20 = `View full size: ${params.alt || "image"}`, _v$21 = params.url, _v$22 = params.alt || "Image";
777
+ _v$18 !== _p$.e && web.className(_el$121, _p$.e = _v$18);
778
+ _v$19 !== _p$.t && web.setAttribute(_el$123, "href", _p$.t = _v$19);
779
+ _v$20 !== _p$.a && web.setAttribute(_el$123, "aria-label", _p$.a = _v$20);
780
+ _v$21 !== _p$.o && web.setAttribute(_el$124, "src", _p$.o = _v$21);
781
+ _v$22 !== _p$.i && web.setAttribute(_el$124, "alt", _p$.i = _v$22);
780
782
  return _p$;
781
783
  }, {
782
784
  e: void 0,
@@ -805,10 +807,10 @@ function LinkRenderer(props) {
805
807
  }
806
808
  }), _el$135, _co$26);
807
809
  web.effect((_p$) => {
808
- var _v$22 = params.url, _v$23 = `${params.label || "Link"}: ${params.description || params.url} (opens in new tab)`, _v$24 = `flex items-center gap-3 p-4 bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors group h-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 ${params.className || ""}`;
809
- _v$22 !== _p$.e && web.setAttribute(_el$129, "href", _p$.e = _v$22);
810
- _v$23 !== _p$.t && web.setAttribute(_el$129, "aria-label", _p$.t = _v$23);
811
- _v$24 !== _p$.a && web.className(_el$129, _p$.a = _v$24);
810
+ var _v$23 = params.url, _v$24 = `${params.label || "Link"}: ${params.description || params.url} (opens in new tab)`, _v$25 = `flex items-center gap-3 p-4 bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors group h-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 ${params.className || ""}`;
811
+ _v$23 !== _p$.e && web.setAttribute(_el$129, "href", _p$.e = _v$23);
812
+ _v$24 !== _p$.t && web.setAttribute(_el$129, "aria-label", _p$.t = _v$24);
813
+ _v$25 !== _p$.a && web.className(_el$129, _p$.a = _v$25);
812
814
  return _p$;
813
815
  }, {
814
816
  e: void 0,
@@ -1095,13 +1097,13 @@ function ActionRenderer(props) {
1095
1097
  }), _el$142, _co$27);
1096
1098
  web.insert(_el$139, () => params.label, _el$144, _co$28);
1097
1099
  web.effect((_p$) => {
1098
- var _v$25 = params.url || "#", _v$26 = params.url ? "_blank" : void 0, _v$27 = params.ariaLabel || params.label, _v$28 = `inline-flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500
1100
+ var _v$26 = params.url || "#", _v$27 = params.url ? "_blank" : void 0, _v$28 = params.ariaLabel || params.label, _v$29 = `inline-flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500
1099
1101
  ${params.variant === "primary" ? "bg-blue-600 text-white hover:bg-blue-700" : params.variant === "outline" ? "border border-gray-300 text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800" : "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"}
1100
1102
  ${params.className || ""}`;
1101
- _v$25 !== _p$.e && web.setAttribute(_el$139, "href", _p$.e = _v$25);
1102
- _v$26 !== _p$.t && web.setAttribute(_el$139, "target", _p$.t = _v$26);
1103
- _v$27 !== _p$.a && web.setAttribute(_el$139, "aria-label", _p$.a = _v$27);
1104
- _v$28 !== _p$.o && web.className(_el$139, _p$.o = _v$28);
1103
+ _v$26 !== _p$.e && web.setAttribute(_el$139, "href", _p$.e = _v$26);
1104
+ _v$27 !== _p$.t && web.setAttribute(_el$139, "target", _p$.t = _v$27);
1105
+ _v$28 !== _p$.a && web.setAttribute(_el$139, "aria-label", _p$.a = _v$28);
1106
+ _v$29 !== _p$.o && web.className(_el$139, _p$.o = _v$29);
1105
1107
  return _p$;
1106
1108
  }, {
1107
1109
  e: void 0,
@@ -1136,16 +1138,16 @@ function ActionRenderer(props) {
1136
1138
  }), _el$151, _co$30);
1137
1139
  web.insert(_el$145, () => params.label, _el$153, _co$31);
1138
1140
  web.effect((_p$) => {
1139
- var _v$29 = params.action === "submit" ? "submit" : "button", _v$30 = isDisabled(), _v$31 = isExecuting() && params.action === "tool-call", _v$32 = params.ariaLabel || params.label, _v$33 = `inline-flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500
1141
+ var _v$30 = params.action === "submit" ? "submit" : "button", _v$31 = isDisabled(), _v$32 = isExecuting() && params.action === "tool-call", _v$33 = params.ariaLabel || params.label, _v$34 = `inline-flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500
1140
1142
  ${params.variant === "primary" ? "bg-blue-600 text-white hover:bg-blue-700 shadow-sm" : params.variant === "secondary" ? "bg-gray-100 text-gray-900 hover:bg-gray-200 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600" : params.variant === "outline" ? "border border-gray-300 text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800" : params.variant === "danger" ? "bg-red-600 text-white hover:bg-red-700" : "bg-transparent text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800"}
1141
1143
  ${isDisabled() ? "opacity-50 cursor-not-allowed" : ""}
1142
1144
  ${params.size === "sm" ? "px-3 py-1.5 text-xs" : params.size === "lg" ? "px-6 py-3 text-base" : ""}
1143
1145
  ${params.className || ""}`;
1144
- _v$29 !== _p$.e && web.setAttribute(_el$145, "type", _p$.e = _v$29);
1145
- _v$30 !== _p$.t && web.setProperty(_el$145, "disabled", _p$.t = _v$30);
1146
- _v$31 !== _p$.a && web.setAttribute(_el$145, "aria-busy", _p$.a = _v$31);
1147
- _v$32 !== _p$.o && web.setAttribute(_el$145, "aria-label", _p$.o = _v$32);
1148
- _v$33 !== _p$.i && web.className(_el$145, _p$.i = _v$33);
1146
+ _v$30 !== _p$.e && web.setAttribute(_el$145, "type", _p$.e = _v$30);
1147
+ _v$31 !== _p$.t && web.setProperty(_el$145, "disabled", _p$.t = _v$31);
1148
+ _v$32 !== _p$.a && web.setAttribute(_el$145, "aria-busy", _p$.a = _v$32);
1149
+ _v$33 !== _p$.o && web.setAttribute(_el$145, "aria-label", _p$.o = _v$33);
1150
+ _v$34 !== _p$.i && web.className(_el$145, _p$.i = _v$34);
1149
1151
  return _p$;
1150
1152
  }, {
1151
1153
  e: void 0,
@@ -1357,9 +1359,9 @@ const UIResourceRenderer = (props) => {
1357
1359
  }
1358
1360
  }), _el$189, _co$39);
1359
1361
  web.effect((_p$) => {
1360
- var _v$34 = `w-full ${props.class || ""}`, _v$35 = gridContainerStyle();
1361
- _v$34 !== _p$.e && web.className(_el$186, _p$.e = _v$34);
1362
- _p$.t = web.style(_el$187, _v$35, _p$.t);
1362
+ var _v$35 = `w-full ${props.class || ""}`, _v$36 = gridContainerStyle();
1363
+ _v$35 !== _p$.e && web.className(_el$186, _p$.e = _v$35);
1364
+ _p$.t = web.style(_el$187, _v$36, _p$.t);
1363
1365
  return _p$;
1364
1366
  }, {
1365
1367
  e: void 0,