@seed-ship/mcp-ui-solid 1.2.0 → 1.2.2

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 (47) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/components/ActionRenderer.cjs +34 -0
  3. package/dist/components/ActionRenderer.cjs.map +1 -0
  4. package/dist/components/ActionRenderer.js +34 -0
  5. package/dist/components/ActionRenderer.js.map +1 -0
  6. package/dist/components/ArtifactRenderer.cjs +37 -0
  7. package/dist/components/ArtifactRenderer.cjs.map +1 -0
  8. package/dist/components/ArtifactRenderer.js +37 -0
  9. package/dist/components/ArtifactRenderer.js.map +1 -0
  10. package/dist/components/CarouselRenderer.cjs +58 -0
  11. package/dist/components/CarouselRenderer.cjs.map +1 -0
  12. package/dist/components/CarouselRenderer.js +58 -0
  13. package/dist/components/CarouselRenderer.js.map +1 -0
  14. package/dist/components/UIResourceRenderer.cjs +238 -160
  15. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  16. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  17. package/dist/components/UIResourceRenderer.js +238 -160
  18. package/dist/components/UIResourceRenderer.js.map +1 -1
  19. package/dist/components/index.d.ts +10 -0
  20. package/dist/components/index.d.ts.map +1 -1
  21. package/dist/components.cjs +10 -0
  22. package/dist/components.cjs.map +1 -1
  23. package/dist/components.d.ts +10 -0
  24. package/dist/components.js +10 -0
  25. package/dist/components.js.map +1 -1
  26. package/dist/hooks/useStreamingUI.cjs +4 -1
  27. package/dist/hooks/useStreamingUI.cjs.map +1 -1
  28. package/dist/hooks/useStreamingUI.d.ts +2 -0
  29. package/dist/hooks/useStreamingUI.d.ts.map +1 -1
  30. package/dist/hooks/useStreamingUI.js +4 -1
  31. package/dist/hooks/useStreamingUI.js.map +1 -1
  32. package/dist/index.cjs +4 -0
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.js +4 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/services/component-registry.cjs +211 -1
  37. package/dist/services/component-registry.cjs.map +1 -1
  38. package/dist/services/component-registry.d.ts +25 -0
  39. package/dist/services/component-registry.d.ts.map +1 -1
  40. package/dist/services/component-registry.js +211 -1
  41. package/dist/services/component-registry.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/components/UIResourceRenderer.tsx +79 -3
  44. package/src/components/index.ts +16 -0
  45. package/src/hooks/useStreamingUI.ts +7 -1
  46. package/src/services/component-registry.ts +239 -0
  47. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.2] - 2025-11-26
9
+
10
+ ### Added - Sprint 4: Public Exports & Registry
11
+
12
+ #### Component Exports (NEW)
13
+ - **FooterRenderer**: Now publicly exported for custom footer implementations
14
+ - **ActionRenderer**: Interactive button/link component with tool-call support
15
+ - **ArtifactRenderer**: Downloadable artifact display with filename, size, MIME type
16
+ - **CarouselRenderer**: Horizontal carousel with snap scrolling and navigation
17
+ - **GridRenderer**: Nested CSS Grid layout for complex dashboard templates
18
+
19
+ #### Component Registry Entries (NEW)
20
+ - Added 5 new registry entries in `component-registry.ts`:
21
+ - `grid`: Nested CSS Grid layout with columns, gap, areas, children
22
+ - `action`: Interactive button/link with tool-call, link, submit actions
23
+ - `footer`: Metadata display with executionTime, model, sourceCount
24
+ - `carousel`: Horizontal item carousel with snap scrolling
25
+ - `artifact`: Downloadable file display with URL, filename, mimeType, size
26
+
27
+ ### Technical
28
+ - All Sprint 4 components now available via main package export
29
+ - Registry entries enable LLM prompt engineering with schema definitions
30
+ - Full TypeScript types exported for all new components
31
+
32
+ ## [1.2.1] - 2025-11-25
33
+
34
+ ### Fixed
35
+ - Minor build fixes and dependency updates
36
+
8
37
  ## [1.2.0] - 2025-11-25
9
38
 
10
39
  ### Added - Phase 5.0 Quick Wins
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const web = require("solid-js/web");
4
+ var _tmpl$ = /* @__PURE__ */ web.template(`<button>`);
5
+ const ActionRenderer = (props) => {
6
+ const handleClick = async () => {
7
+ if (props.disabled) return;
8
+ await props.onExecute(props.action.toolName, props.action.params);
9
+ };
10
+ const variantClasses = {
11
+ primary: "bg-blue-600 hover:bg-blue-700 text-white",
12
+ secondary: "bg-gray-200 hover:bg-gray-300 text-gray-800 dark:bg-gray-700 dark:hover:bg-gray-600 dark:text-white",
13
+ danger: "bg-red-600 hover:bg-red-700 text-white"
14
+ };
15
+ return (() => {
16
+ var _el$ = web.getNextElement(_tmpl$);
17
+ _el$.$$click = handleClick;
18
+ web.insert(_el$, () => props.action.label);
19
+ web.effect((_p$) => {
20
+ var _v$ = props.disabled, _v$2 = `px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${variantClasses[props.action.variant || "primary"]} ${props.disabled ? "opacity-50 cursor-not-allowed" : ""}`;
21
+ _v$ !== _p$.e && web.setProperty(_el$, "disabled", _p$.e = _v$);
22
+ _v$2 !== _p$.t && web.className(_el$, _p$.t = _v$2);
23
+ return _p$;
24
+ }, {
25
+ e: void 0,
26
+ t: void 0
27
+ });
28
+ web.runHydrationEvents();
29
+ return _el$;
30
+ })();
31
+ };
32
+ web.delegateEvents(["click"]);
33
+ exports.ActionRenderer = ActionRenderer;
34
+ //# sourceMappingURL=ActionRenderer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionRenderer.cjs","sources":["../../src/components/ActionRenderer.tsx"],"sourcesContent":["import { Component, Show } from 'solid-js'\n// import type { ActionSpec } from '@seed-ship/mcp-ui-spec'\ntype ActionSpec = any\n\nexport interface ActionRendererProps {\n action: ActionSpec\n onExecute: (toolName: string, params: any) => Promise<any>\n disabled?: boolean\n}\n\nexport const ActionRenderer: Component<ActionRendererProps> = (props) => {\n const handleClick = async () => {\n if (props.disabled) return\n await props.onExecute(props.action.toolName, props.action.params)\n }\n\n const variantClasses: Record<string, string> = {\n primary: 'bg-blue-600 hover:bg-blue-700 text-white',\n secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800 dark:bg-gray-700 dark:hover:bg-gray-600 dark:text-white',\n danger: 'bg-red-600 hover:bg-red-700 text-white'\n }\n\n return (\n <button\n onClick={handleClick}\n disabled={props.disabled}\n class={`px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${variantClasses[props.action.variant || 'primary']\n } ${props.disabled ? 'opacity-50 cursor-not-allowed' : ''}`}\n >\n {props.action.label}\n </button>\n )\n}\n"],"names":["ActionRenderer","props","handleClick","disabled","onExecute","action","toolName","params","variantClasses","primary","secondary","danger","_el$","_$getNextElement","_tmpl$","$$click","_$insert","label","_$effect","_p$","_v$","_v$2","variant","e","_$setProperty","t","_$className","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":";;;;AAUO,MAAMA,iBAAkDC,CAAAA,UAAU;AACrE,QAAMC,cAAc,YAAY;AAC5B,QAAID,MAAME,SAAU;AACpB,UAAMF,MAAMG,UAAUH,MAAMI,OAAOC,UAAUL,MAAMI,OAAOE,MAAM;AAAA,EACpE;AAEA,QAAMC,iBAAyC;AAAA,IAC3CC,SAAS;AAAA,IACTC,WAAW;AAAA,IACXC,QAAQ;AAAA,EAAA;AAGZ,UAAA,MAAA;AAAA,QAAAC,OAAAC,IAAAA,eAAAC,MAAA;AAAAF,SAAAG,UAEiBb;AAAWc,QAAAA,OAAAJ,MAAA,MAKnBX,MAAMI,OAAOY,KAAK;AAAAC,QAAAA,OAAAC,CAAAA,QAAA;AAAA,UAAAC,MAJTnB,MAAME,UAAQkB,OACjB,gEAAgEb,eAAeP,MAAMI,OAAOiB,WAAW,SAAS,CAAC,IAChHrB,MAAME,WAAW,kCAAkC,EAAE;AAAEiB,cAAAD,IAAAI,KAAAC,IAAAA,YAAAZ,MAAA,YAAAO,IAAAI,IAAAH,GAAA;AAAAC,eAAAF,IAAAM,KAAAC,IAAAA,UAAAd,MAAAO,IAAAM,IAAAJ,IAAA;AAAA,aAAAF;AAAAA,IAAA,GAAA;AAAA,MAAAI,GAAAI;AAAAA,MAAAF,GAAAE;AAAAA,IAAAA,CAAA;AAAAC,2BAAAA;AAAA,WAAAhB;AAAAA,EAAA,GAAA;AAK3E;AAACiB,IAAAA,eAAA,CAAA,OAAA,CAAA;;"}
@@ -0,0 +1,34 @@
1
+ import { delegateEvents, getNextElement, template, insert, effect, setProperty, className, runHydrationEvents } from "solid-js/web";
2
+ var _tmpl$ = /* @__PURE__ */ template(`<button>`);
3
+ const ActionRenderer = (props) => {
4
+ const handleClick = async () => {
5
+ if (props.disabled) return;
6
+ await props.onExecute(props.action.toolName, props.action.params);
7
+ };
8
+ const variantClasses = {
9
+ primary: "bg-blue-600 hover:bg-blue-700 text-white",
10
+ secondary: "bg-gray-200 hover:bg-gray-300 text-gray-800 dark:bg-gray-700 dark:hover:bg-gray-600 dark:text-white",
11
+ danger: "bg-red-600 hover:bg-red-700 text-white"
12
+ };
13
+ return (() => {
14
+ var _el$ = getNextElement(_tmpl$);
15
+ _el$.$$click = handleClick;
16
+ insert(_el$, () => props.action.label);
17
+ effect((_p$) => {
18
+ var _v$ = props.disabled, _v$2 = `px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${variantClasses[props.action.variant || "primary"]} ${props.disabled ? "opacity-50 cursor-not-allowed" : ""}`;
19
+ _v$ !== _p$.e && setProperty(_el$, "disabled", _p$.e = _v$);
20
+ _v$2 !== _p$.t && className(_el$, _p$.t = _v$2);
21
+ return _p$;
22
+ }, {
23
+ e: void 0,
24
+ t: void 0
25
+ });
26
+ runHydrationEvents();
27
+ return _el$;
28
+ })();
29
+ };
30
+ delegateEvents(["click"]);
31
+ export {
32
+ ActionRenderer
33
+ };
34
+ //# sourceMappingURL=ActionRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionRenderer.js","sources":["../../src/components/ActionRenderer.tsx"],"sourcesContent":["import { Component, Show } from 'solid-js'\n// import type { ActionSpec } from '@seed-ship/mcp-ui-spec'\ntype ActionSpec = any\n\nexport interface ActionRendererProps {\n action: ActionSpec\n onExecute: (toolName: string, params: any) => Promise<any>\n disabled?: boolean\n}\n\nexport const ActionRenderer: Component<ActionRendererProps> = (props) => {\n const handleClick = async () => {\n if (props.disabled) return\n await props.onExecute(props.action.toolName, props.action.params)\n }\n\n const variantClasses: Record<string, string> = {\n primary: 'bg-blue-600 hover:bg-blue-700 text-white',\n secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800 dark:bg-gray-700 dark:hover:bg-gray-600 dark:text-white',\n danger: 'bg-red-600 hover:bg-red-700 text-white'\n }\n\n return (\n <button\n onClick={handleClick}\n disabled={props.disabled}\n class={`px-3 py-1.5 rounded-md text-sm font-medium transition-colors ${variantClasses[props.action.variant || 'primary']\n } ${props.disabled ? 'opacity-50 cursor-not-allowed' : ''}`}\n >\n {props.action.label}\n </button>\n )\n}\n"],"names":["ActionRenderer","props","handleClick","disabled","onExecute","action","toolName","params","variantClasses","primary","secondary","danger","_el$","_$getNextElement","_tmpl$","$$click","_$insert","label","_$effect","_p$","_v$","_v$2","variant","e","_$setProperty","t","_$className","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":";;AAUO,MAAMA,iBAAkDC,CAAAA,UAAU;AACrE,QAAMC,cAAc,YAAY;AAC5B,QAAID,MAAME,SAAU;AACpB,UAAMF,MAAMG,UAAUH,MAAMI,OAAOC,UAAUL,MAAMI,OAAOE,MAAM;AAAA,EACpE;AAEA,QAAMC,iBAAyC;AAAA,IAC3CC,SAAS;AAAA,IACTC,WAAW;AAAA,IACXC,QAAQ;AAAA,EAAA;AAGZ,UAAA,MAAA;AAAA,QAAAC,OAAAC,eAAAC,MAAA;AAAAF,SAAAG,UAEiBb;AAAWc,WAAAJ,MAAA,MAKnBX,MAAMI,OAAOY,KAAK;AAAAC,WAAAC,CAAAA,QAAA;AAAA,UAAAC,MAJTnB,MAAME,UAAQkB,OACjB,gEAAgEb,eAAeP,MAAMI,OAAOiB,WAAW,SAAS,CAAC,IAChHrB,MAAME,WAAW,kCAAkC,EAAE;AAAEiB,cAAAD,IAAAI,KAAAC,YAAAZ,MAAA,YAAAO,IAAAI,IAAAH,GAAA;AAAAC,eAAAF,IAAAM,KAAAC,UAAAd,MAAAO,IAAAM,IAAAJ,IAAA;AAAA,aAAAF;AAAAA,IAAA,GAAA;AAAA,MAAAI,GAAAI;AAAAA,MAAAF,GAAAE;AAAAA,IAAAA,CAAA;AAAAC,uBAAAA;AAAA,WAAAhB;AAAAA,EAAA,GAAA;AAK3E;AAACiB,eAAA,CAAA,OAAA,CAAA;"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const web = require("solid-js/web");
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
+ const ArtifactRenderer = (props) => {
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 "📄";
10
+ return "📁";
11
+ };
12
+ const formatSize = (bytes) => {
13
+ if (!bytes) return "";
14
+ if (bytes < 1024) return `${bytes} B`;
15
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
16
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
17
+ };
18
+ return (() => {
19
+ var _el$ = web.getNextElement(_tmpl$), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling, _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling, _el$8 = _el$6.firstChild, [_el$9, _co$] = web.getNextMarker(_el$8.nextSibling), _el$7 = _el$9.nextSibling, _el$0 = _el$7.nextSibling, [_el$1, _co$2] = web.getNextMarker(_el$0.nextSibling), _el$10 = _el$2.nextSibling;
20
+ web.insert(_el$3, getIcon);
21
+ web.insert(_el$5, () => props.params.filename);
22
+ web.insert(_el$6, () => formatSize(props.params.size), _el$9, _co$);
23
+ web.insert(_el$6, () => props.params.description || "Generated artifact", _el$1, _co$2);
24
+ web.effect((_p$) => {
25
+ var _v$ = props.params.url, _v$2 = props.params.filename;
26
+ _v$ !== _p$.e && web.setAttribute(_el$10, "href", _p$.e = _v$);
27
+ _v$2 !== _p$.t && web.setAttribute(_el$10, "download", _p$.t = _v$2);
28
+ return _p$;
29
+ }, {
30
+ e: void 0,
31
+ t: void 0
32
+ });
33
+ return _el$;
34
+ })();
35
+ };
36
+ exports.ArtifactRenderer = ArtifactRenderer;
37
+ //# sourceMappingURL=ArtifactRenderer.cjs.map
@@ -0,0 +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;;"}
@@ -0,0 +1,37 @@
1
+ import { getNextElement, template, getNextMarker, insert, effect, setAttribute } from "solid-js/web";
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
+ const ArtifactRenderer = (props) => {
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 "📄";
8
+ return "📁";
9
+ };
10
+ const formatSize = (bytes) => {
11
+ if (!bytes) return "";
12
+ if (bytes < 1024) return `${bytes} B`;
13
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
14
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
15
+ };
16
+ return (() => {
17
+ var _el$ = getNextElement(_tmpl$), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.nextSibling, _el$5 = _el$4.firstChild, _el$6 = _el$5.nextSibling, _el$8 = _el$6.firstChild, [_el$9, _co$] = getNextMarker(_el$8.nextSibling), _el$7 = _el$9.nextSibling, _el$0 = _el$7.nextSibling, [_el$1, _co$2] = getNextMarker(_el$0.nextSibling), _el$10 = _el$2.nextSibling;
18
+ insert(_el$3, getIcon);
19
+ insert(_el$5, () => props.params.filename);
20
+ insert(_el$6, () => formatSize(props.params.size), _el$9, _co$);
21
+ insert(_el$6, () => props.params.description || "Generated artifact", _el$1, _co$2);
22
+ effect((_p$) => {
23
+ var _v$ = props.params.url, _v$2 = props.params.filename;
24
+ _v$ !== _p$.e && setAttribute(_el$10, "href", _p$.e = _v$);
25
+ _v$2 !== _p$.t && setAttribute(_el$10, "download", _p$.t = _v$2);
26
+ return _p$;
27
+ }, {
28
+ e: void 0,
29
+ t: void 0
30
+ });
31
+ return _el$;
32
+ })();
33
+ };
34
+ export {
35
+ ArtifactRenderer
36
+ };
37
+ //# sourceMappingURL=ArtifactRenderer.js.map
@@ -0,0 +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;"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const web = require("solid-js/web");
4
+ const solidJs = require("solid-js");
5
+ const UIResourceRenderer = require("./UIResourceRenderer.cjs");
6
+ var _tmpl$ = /* @__PURE__ */ web.template(`<div class="relative group"><button><svg class="w-5 h-5 text-gray-700 dark:text-gray-300"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M15 19l-7-7 7-7"></path></svg></button><button><svg class="w-5 h-5 text-gray-700 dark:text-gray-300"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M9 5l7 7-7 7"></path></svg></button><div class="flex gap-4 overflow-x-auto snap-x snap-mandatory pb-4 scrollbar-hide"style=scroll-behavior:smooth>`), _tmpl$2 = /* @__PURE__ */ web.template(`<div class="flex-none w-[85%] sm:w-[45%] snap-center"><div class="h-full border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden bg-white dark:bg-gray-800">`);
7
+ const CarouselRenderer = (props) => {
8
+ let scrollContainer;
9
+ const [canScrollLeft, setCanScrollLeft] = solidJs.createSignal(false);
10
+ const [canScrollRight, setCanScrollRight] = solidJs.createSignal(true);
11
+ const checkScroll = () => {
12
+ if (web.isServer || !scrollContainer) return;
13
+ setCanScrollLeft(scrollContainer.scrollLeft > 0);
14
+ setCanScrollRight(scrollContainer.scrollLeft < scrollContainer.scrollWidth - scrollContainer.clientWidth - 10);
15
+ };
16
+ const scroll = (direction) => {
17
+ if (web.isServer || !scrollContainer) return;
18
+ const scrollAmount = scrollContainer.clientWidth * 0.8;
19
+ scrollContainer.scrollBy({
20
+ left: direction === "left" ? -scrollAmount : scrollAmount,
21
+ behavior: "smooth"
22
+ });
23
+ };
24
+ return (() => {
25
+ var _el$ = web.getNextElement(_tmpl$), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.nextSibling;
26
+ _el$2.$$click = () => scroll("left");
27
+ _el$3.$$click = () => scroll("right");
28
+ _el$4.addEventListener("scroll", checkScroll);
29
+ var _ref$ = scrollContainer;
30
+ typeof _ref$ === "function" ? web.use(_ref$, _el$4) : scrollContainer = _el$4;
31
+ web.insert(_el$4, web.createComponent(solidJs.For, {
32
+ get each() {
33
+ return props.items;
34
+ },
35
+ children: (item) => (() => {
36
+ var _el$5 = web.getNextElement(_tmpl$2), _el$6 = _el$5.firstChild;
37
+ web.insert(_el$6, web.createComponent(UIResourceRenderer.UIResourceRenderer, {
38
+ content: item
39
+ }));
40
+ return _el$5;
41
+ })()
42
+ }));
43
+ web.effect((_p$) => {
44
+ var _v$ = `absolute left-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollLeft() ? "opacity-0 group-hover:opacity-100" : "opacity-0 pointer-events-none"}`, _v$2 = `absolute right-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollRight() ? "opacity-0 group-hover:opacity-100" : "opacity-0 pointer-events-none"}`;
45
+ _v$ !== _p$.e && web.className(_el$2, _p$.e = _v$);
46
+ _v$2 !== _p$.t && web.className(_el$3, _p$.t = _v$2);
47
+ return _p$;
48
+ }, {
49
+ e: void 0,
50
+ t: void 0
51
+ });
52
+ web.runHydrationEvents();
53
+ return _el$;
54
+ })();
55
+ };
56
+ web.delegateEvents(["click"]);
57
+ exports.CarouselRenderer = CarouselRenderer;
58
+ //# sourceMappingURL=CarouselRenderer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselRenderer.cjs","sources":["../../src/components/CarouselRenderer.tsx"],"sourcesContent":["import { Component, For, createSignal, onMount } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { UIResourceRenderer } from './UIResourceRenderer'\n\n// Local definition to avoid missing module error\ntype UIComponent = any\n\nexport interface CarouselRendererProps {\n items: UIComponent[]\n height?: string\n}\n\nexport const CarouselRenderer: Component<CarouselRendererProps> = (props) => {\n let scrollContainer: HTMLDivElement | undefined\n const [canScrollLeft, setCanScrollLeft] = createSignal(false)\n const [canScrollRight, setCanScrollRight] = createSignal(true)\n\n const checkScroll = () => {\n if (isServer || !scrollContainer) return\n setCanScrollLeft(scrollContainer.scrollLeft > 0)\n setCanScrollRight(\n scrollContainer.scrollLeft < scrollContainer.scrollWidth - scrollContainer.clientWidth - 10\n )\n }\n\n const scroll = (direction: 'left' | 'right') => {\n if (isServer || !scrollContainer) return\n const scrollAmount = scrollContainer.clientWidth * 0.8\n scrollContainer.scrollBy({\n left: direction === 'left' ? -scrollAmount : scrollAmount,\n behavior: 'smooth'\n })\n }\n\n return (\n <div class=\"relative group\">\n {/* Navigation Buttons */}\n <button\n onClick={() => scroll('left')}\n class={`absolute left-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollLeft() ? 'opacity-0 group-hover:opacity-100' : 'opacity-0 pointer-events-none'\n }`}\n >\n <svg class=\"w-5 h-5 text-gray-700 dark:text-gray-300\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n\n <button\n onClick={() => scroll('right')}\n class={`absolute right-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollRight() ? 'opacity-0 group-hover:opacity-100' : 'opacity-0 pointer-events-none'\n }`}\n >\n <svg class=\"w-5 h-5 text-gray-700 dark:text-gray-300\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n\n {/* Scroll Container */}\n <div\n ref={scrollContainer}\n onScroll={checkScroll}\n class=\"flex gap-4 overflow-x-auto snap-x snap-mandatory pb-4 scrollbar-hide\"\n style={{ \"scroll-behavior\": \"smooth\" }}\n >\n <For each={props.items}>\n {(item) => (\n <div class=\"flex-none w-[85%] sm:w-[45%] snap-center\">\n <div class=\"h-full border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden bg-white dark:bg-gray-800\">\n <UIResourceRenderer content={item} />\n </div>\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n"],"names":["CarouselRenderer","props","scrollContainer","canScrollLeft","setCanScrollLeft","createSignal","canScrollRight","setCanScrollRight","checkScroll","isServer","scrollLeft","scrollWidth","clientWidth","scroll","direction","scrollAmount","scrollBy","left","behavior","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","_el$3","nextSibling","_el$4","$$click","addEventListener","_ref$","_$use","_$insert","_$createComponent","For","each","items","children","item","_el$5","_tmpl$2","_el$6","UIResourceRenderer","content","_$effect","_p$","_v$","_v$2","e","_$className","t","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":";;;;;;AAYO,MAAMA,mBAAsDC,CAAAA,UAAU;AACzE,MAAIC;AACJ,QAAM,CAACC,eAAeC,gBAAgB,IAAIC,QAAAA,aAAa,KAAK;AAC5D,QAAM,CAACC,gBAAgBC,iBAAiB,IAAIF,QAAAA,aAAa,IAAI;AAE7D,QAAMG,cAAcA,MAAM;AACtB,QAAIC,IAAAA,YAAY,CAACP,gBAAiB;AAClCE,qBAAiBF,gBAAgBQ,aAAa,CAAC;AAC/CH,sBACIL,gBAAgBQ,aAAaR,gBAAgBS,cAAcT,gBAAgBU,cAAc,EAC7F;AAAA,EACJ;AAEA,QAAMC,SAASA,CAACC,cAAgC;AAC5C,QAAIL,IAAAA,YAAY,CAACP,gBAAiB;AAClC,UAAMa,eAAeb,gBAAgBU,cAAc;AACnDV,oBAAgBc,SAAS;AAAA,MACrBC,MAAMH,cAAc,SAAS,CAACC,eAAeA;AAAAA,MAC7CG,UAAU;AAAA,IAAA,CACb;AAAA,EACL;AAEA,UAAA,MAAA;AAAA,QAAAC,OAAAC,IAAAA,eAAAC,MAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAG,aAAAC,QAAAF,MAAAC;AAAAH,UAAAK,UAIqB,MAAMd,OAAO,MAAM;AAACW,UAAAG,UAUpB,MAAMd,OAAO,OAAO;AAACa,UAAAE,iBAAA,UAYpBpB,WAAW;AAAA,QAAAqB,QADhB3B;AAAe,WAAA2B,UAAA,aAAAC,IAAAA,IAAAD,OAAAH,KAAA,IAAfxB,kBAAewB;AAAAK,eAAAL,OAAAM,IAAAA,gBAKnBC,aAAG;AAAA,MAAA,IAACC,OAAI;AAAA,eAAEjC,MAAMkC;AAAAA,MAAK;AAAA,MAAAC,UAChBC,WAAI,MAAA;AAAA,YAAAC,QAAAlB,IAAAA,eAAAmB,OAAA,GAAAC,QAAAF,MAAAf;AAAAQ,mBAAAS,OAAAR,IAAAA,gBAGOS,uCAAkB;AAAA,UAACC,SAASL;AAAAA,QAAAA,CAAI,CAAA;AAAA,eAAAC;AAAAA,MAAA,GAAA;AAAA,IAAA,CAG5C,CAAA;AAAAK,QAAAA,OAAAC,CAAAA,QAAA;AAAA,UAAAC,MAhCE,4LAA4L1C,cAAAA,IAAkB,sCAAsC,+BAA+B,IACpR2C,OASC,6LAA6LxC,eAAAA,IAAmB,sCAAsC,+BAA+B;AACtRuC,cAAAD,IAAAG,KAAAC,IAAAA,UAAA1B,OAAAsB,IAAAG,IAAAF,GAAA;AAAAC,eAAAF,IAAAK,KAAAD,IAAAA,UAAAxB,OAAAoB,IAAAK,IAAAH,IAAA;AAAA,aAAAF;AAAAA,IAAA,GAAA;AAAA,MAAAG,GAAAG;AAAAA,MAAAD,GAAAC;AAAAA,IAAAA,CAAA;AAAAC,2BAAAA;AAAA,WAAAhC;AAAAA,EAAA,GAAA;AA0BtB;AAACiC,IAAAA,eAAA,CAAA,OAAA,CAAA;;"}
@@ -0,0 +1,58 @@
1
+ import { delegateEvents, getNextElement, template, insert, createComponent, effect, className, runHydrationEvents, isServer, use } from "solid-js/web";
2
+ import { createSignal, For } from "solid-js";
3
+ import { UIResourceRenderer } from "./UIResourceRenderer.js";
4
+ var _tmpl$ = /* @__PURE__ */ template(`<div class="relative group"><button><svg class="w-5 h-5 text-gray-700 dark:text-gray-300"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M15 19l-7-7 7-7"></path></svg></button><button><svg class="w-5 h-5 text-gray-700 dark:text-gray-300"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M9 5l7 7-7 7"></path></svg></button><div class="flex gap-4 overflow-x-auto snap-x snap-mandatory pb-4 scrollbar-hide"style=scroll-behavior:smooth>`), _tmpl$2 = /* @__PURE__ */ template(`<div class="flex-none w-[85%] sm:w-[45%] snap-center"><div class="h-full border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden bg-white dark:bg-gray-800">`);
5
+ const CarouselRenderer = (props) => {
6
+ let scrollContainer;
7
+ const [canScrollLeft, setCanScrollLeft] = createSignal(false);
8
+ const [canScrollRight, setCanScrollRight] = createSignal(true);
9
+ const checkScroll = () => {
10
+ if (isServer || !scrollContainer) return;
11
+ setCanScrollLeft(scrollContainer.scrollLeft > 0);
12
+ setCanScrollRight(scrollContainer.scrollLeft < scrollContainer.scrollWidth - scrollContainer.clientWidth - 10);
13
+ };
14
+ const scroll = (direction) => {
15
+ if (isServer || !scrollContainer) return;
16
+ const scrollAmount = scrollContainer.clientWidth * 0.8;
17
+ scrollContainer.scrollBy({
18
+ left: direction === "left" ? -scrollAmount : scrollAmount,
19
+ behavior: "smooth"
20
+ });
21
+ };
22
+ return (() => {
23
+ var _el$ = getNextElement(_tmpl$), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.nextSibling;
24
+ _el$2.$$click = () => scroll("left");
25
+ _el$3.$$click = () => scroll("right");
26
+ _el$4.addEventListener("scroll", checkScroll);
27
+ var _ref$ = scrollContainer;
28
+ typeof _ref$ === "function" ? use(_ref$, _el$4) : scrollContainer = _el$4;
29
+ insert(_el$4, createComponent(For, {
30
+ get each() {
31
+ return props.items;
32
+ },
33
+ children: (item) => (() => {
34
+ var _el$5 = getNextElement(_tmpl$2), _el$6 = _el$5.firstChild;
35
+ insert(_el$6, createComponent(UIResourceRenderer, {
36
+ content: item
37
+ }));
38
+ return _el$5;
39
+ })()
40
+ }));
41
+ effect((_p$) => {
42
+ var _v$ = `absolute left-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollLeft() ? "opacity-0 group-hover:opacity-100" : "opacity-0 pointer-events-none"}`, _v$2 = `absolute right-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollRight() ? "opacity-0 group-hover:opacity-100" : "opacity-0 pointer-events-none"}`;
43
+ _v$ !== _p$.e && className(_el$2, _p$.e = _v$);
44
+ _v$2 !== _p$.t && className(_el$3, _p$.t = _v$2);
45
+ return _p$;
46
+ }, {
47
+ e: void 0,
48
+ t: void 0
49
+ });
50
+ runHydrationEvents();
51
+ return _el$;
52
+ })();
53
+ };
54
+ delegateEvents(["click"]);
55
+ export {
56
+ CarouselRenderer
57
+ };
58
+ //# sourceMappingURL=CarouselRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CarouselRenderer.js","sources":["../../src/components/CarouselRenderer.tsx"],"sourcesContent":["import { Component, For, createSignal, onMount } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { UIResourceRenderer } from './UIResourceRenderer'\n\n// Local definition to avoid missing module error\ntype UIComponent = any\n\nexport interface CarouselRendererProps {\n items: UIComponent[]\n height?: string\n}\n\nexport const CarouselRenderer: Component<CarouselRendererProps> = (props) => {\n let scrollContainer: HTMLDivElement | undefined\n const [canScrollLeft, setCanScrollLeft] = createSignal(false)\n const [canScrollRight, setCanScrollRight] = createSignal(true)\n\n const checkScroll = () => {\n if (isServer || !scrollContainer) return\n setCanScrollLeft(scrollContainer.scrollLeft > 0)\n setCanScrollRight(\n scrollContainer.scrollLeft < scrollContainer.scrollWidth - scrollContainer.clientWidth - 10\n )\n }\n\n const scroll = (direction: 'left' | 'right') => {\n if (isServer || !scrollContainer) return\n const scrollAmount = scrollContainer.clientWidth * 0.8\n scrollContainer.scrollBy({\n left: direction === 'left' ? -scrollAmount : scrollAmount,\n behavior: 'smooth'\n })\n }\n\n return (\n <div class=\"relative group\">\n {/* Navigation Buttons */}\n <button\n onClick={() => scroll('left')}\n class={`absolute left-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollLeft() ? 'opacity-0 group-hover:opacity-100' : 'opacity-0 pointer-events-none'\n }`}\n >\n <svg class=\"w-5 h-5 text-gray-700 dark:text-gray-300\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n\n <button\n onClick={() => scroll('right')}\n class={`absolute right-2 top-1/2 -translate-y-1/2 z-10 p-2 bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm rounded-full shadow-md border border-gray-200 dark:border-gray-700 transition-opacity ${canScrollRight() ? 'opacity-0 group-hover:opacity-100' : 'opacity-0 pointer-events-none'\n }`}\n >\n <svg class=\"w-5 h-5 text-gray-700 dark:text-gray-300\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n\n {/* Scroll Container */}\n <div\n ref={scrollContainer}\n onScroll={checkScroll}\n class=\"flex gap-4 overflow-x-auto snap-x snap-mandatory pb-4 scrollbar-hide\"\n style={{ \"scroll-behavior\": \"smooth\" }}\n >\n <For each={props.items}>\n {(item) => (\n <div class=\"flex-none w-[85%] sm:w-[45%] snap-center\">\n <div class=\"h-full border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden bg-white dark:bg-gray-800\">\n <UIResourceRenderer content={item} />\n </div>\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n"],"names":["CarouselRenderer","props","scrollContainer","canScrollLeft","setCanScrollLeft","createSignal","canScrollRight","setCanScrollRight","checkScroll","isServer","scrollLeft","scrollWidth","clientWidth","scroll","direction","scrollAmount","scrollBy","left","behavior","_el$","_$getNextElement","_tmpl$","_el$2","firstChild","_el$3","nextSibling","_el$4","$$click","addEventListener","_ref$","_$use","_$insert","_$createComponent","For","each","items","children","item","_el$5","_tmpl$2","_el$6","UIResourceRenderer","content","_$effect","_p$","_v$","_v$2","e","_$className","t","undefined","_$runHydrationEvents","_$delegateEvents"],"mappings":";;;;AAYO,MAAMA,mBAAsDC,CAAAA,UAAU;AACzE,MAAIC;AACJ,QAAM,CAACC,eAAeC,gBAAgB,IAAIC,aAAa,KAAK;AAC5D,QAAM,CAACC,gBAAgBC,iBAAiB,IAAIF,aAAa,IAAI;AAE7D,QAAMG,cAAcA,MAAM;AACtB,QAAIC,YAAY,CAACP,gBAAiB;AAClCE,qBAAiBF,gBAAgBQ,aAAa,CAAC;AAC/CH,sBACIL,gBAAgBQ,aAAaR,gBAAgBS,cAAcT,gBAAgBU,cAAc,EAC7F;AAAA,EACJ;AAEA,QAAMC,SAASA,CAACC,cAAgC;AAC5C,QAAIL,YAAY,CAACP,gBAAiB;AAClC,UAAMa,eAAeb,gBAAgBU,cAAc;AACnDV,oBAAgBc,SAAS;AAAA,MACrBC,MAAMH,cAAc,SAAS,CAACC,eAAeA;AAAAA,MAC7CG,UAAU;AAAA,IAAA,CACb;AAAA,EACL;AAEA,UAAA,MAAA;AAAA,QAAAC,OAAAC,eAAAC,MAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAG,aAAAC,QAAAF,MAAAC;AAAAH,UAAAK,UAIqB,MAAMd,OAAO,MAAM;AAACW,UAAAG,UAUpB,MAAMd,OAAO,OAAO;AAACa,UAAAE,iBAAA,UAYpBpB,WAAW;AAAA,QAAAqB,QADhB3B;AAAe,WAAA2B,UAAA,aAAAC,IAAAD,OAAAH,KAAA,IAAfxB,kBAAewB;AAAAK,WAAAL,OAAAM,gBAKnBC,KAAG;AAAA,MAAA,IAACC,OAAI;AAAA,eAAEjC,MAAMkC;AAAAA,MAAK;AAAA,MAAAC,UAChBC,WAAI,MAAA;AAAA,YAAAC,QAAAlB,eAAAmB,OAAA,GAAAC,QAAAF,MAAAf;AAAAQ,eAAAS,OAAAR,gBAGOS,oBAAkB;AAAA,UAACC,SAASL;AAAAA,QAAAA,CAAI,CAAA;AAAA,eAAAC;AAAAA,MAAA,GAAA;AAAA,IAAA,CAG5C,CAAA;AAAAK,WAAAC,CAAAA,QAAA;AAAA,UAAAC,MAhCE,4LAA4L1C,cAAAA,IAAkB,sCAAsC,+BAA+B,IACpR2C,OASC,6LAA6LxC,eAAAA,IAAmB,sCAAsC,+BAA+B;AACtRuC,cAAAD,IAAAG,KAAAC,UAAA1B,OAAAsB,IAAAG,IAAAF,GAAA;AAAAC,eAAAF,IAAAK,KAAAD,UAAAxB,OAAAoB,IAAAK,IAAAH,IAAA;AAAA,aAAAF;AAAAA,IAAA,GAAA;AAAA,MAAAG,GAAAG;AAAAA,MAAAD,GAAAC;AAAAA,IAAAA,CAAA;AAAAC,uBAAAA;AAAA,WAAAhC;AAAAA,EAAA,GAAA;AA0BtB;AAACiC,eAAA,CAAA,OAAA,CAAA;"}