@seed-ship/mcp-ui-solid 1.0.13 → 1.0.15

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.
package/LICENSE CHANGED
@@ -1,7 +1,5 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Gabriel Brument
4
-
5
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
4
  of this software and associated documentation files (the "Software"), to deal
7
5
  in the Software without restriction, including without limitation the rights
@@ -1 +1 @@
1
- {"version":3,"file":"UIResourceRenderer.d.ts","sourceRoot":"","sources":["../../src/components/UIResourceRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAgD,MAAM,UAAU,CAAA;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAA;AAKnF;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAA;IAE/B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAExC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAsRD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,uBAAuB,CAiEjE,CAAA"}
1
+ {"version":3,"file":"UIResourceRenderer.d.ts","sourceRoot":"","sources":["../../src/components/UIResourceRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAgD,MAAM,UAAU,CAAA;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAA;AAKnF;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAA;IAE/B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAExC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAmYD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,uBAAuB,CAiEjE,CAAA"}
@@ -5,7 +5,7 @@ const solidJs = require("solid-js");
5
5
  const validation = require("../services/validation.cjs");
6
6
  const GenerativeUIErrorBoundary = require("./GenerativeUIErrorBoundary.cjs");
7
7
  const marked_esm = require("../../../node_modules/.pnpm/marked@16.4.2/node_modules/marked/lib/marked.esm.cjs");
8
- var _tmpl$ = ["<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"></div></div>'], _tmpl$2 = ["<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">', "</p></div></div>"], _tmpl$3 = ["<h3", ' class="text-sm font-semibold text-gray-900 dark:text-white mb-3">', "</h3>"], _tmpl$4 = ["<div", ' class="w-full h-full p-4"><!--$-->', '<!--/--><div class="w-full h-full"><img', ' alt="Chart visualization" class="w-full h-auto max-h-[300px] object-contain"></div></div>'], _tmpl$5 = ["<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"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div>"], _tmpl$6 = ["<div", ' class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!--$-->', "<!--/--> - <!--$-->", "<!--/--> of <!--$-->", "<!--/--></span></div>"], _tmpl$7 = ["<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"><div class="p-4"><!--$-->', '<!--/--><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700"><thead class="bg-gray-50 dark:bg-gray-900"><tr>', '</tr></thead><tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">', "</tbody></table></div><!--$-->", "<!--/--></div></div>"], _tmpl$8 = ["<th", ' scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider" style="', '">', "</th>"], _tmpl$9 = ["<tr", ' class="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">', "</tr>"], _tmpl$0 = ["<td", ' class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap">', "</td>"], _tmpl$1 = ["<span", ' class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">', "</span>"], _tmpl$10 = ["<div", ' class="mt-3 flex items-center"><span class="', '"><!--$-->', "<!--/--> <!--$-->", "<!--/-->%</span></div>"], _tmpl$11 = ["<p", ' class="mt-2 text-xs text-gray-500 dark:text-gray-400">', "</p>"], _tmpl$12 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><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><!--$-->", "<!--/--><!--$-->", "<!--/--></div></div>"], _tmpl$13 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><div class="', '">', "</div></div>"], _tmpl$14 = ["<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">', "</p></div>"], _tmpl$15 = ["<div", ' class="', '"><div class="grid gap-4" style="', '">', "</div></div>"], _tmpl$16 = ["<div", ' style="', '">', "</div>"];
8
+ var _tmpl$ = ["<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"></div></div>'], _tmpl$2 = ["<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">', "</p></div></div>"], _tmpl$3 = ["<h3", ' class="text-sm font-semibold text-gray-900 dark:text-white mb-3">', "</h3>"], _tmpl$4 = ["<div", ' class="w-full h-full p-4"><!--$-->', '<!--/--><div class="w-full h-full"><img', ' alt="Chart visualization" class="w-full h-auto max-h-[300px] object-contain"></div></div>'], _tmpl$5 = ["<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"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div>"], _tmpl$6 = ["<div", ' class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!--$-->', "<!--/--> - <!--$-->", "<!--/--> of <!--$-->", "<!--/--></span></div>"], _tmpl$7 = ["<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"><div class="p-4"><!--$-->', '<!--/--><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700"><thead class="bg-gray-50 dark:bg-gray-900"><tr>', '</tr></thead><tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">', "</tbody></table></div><!--$-->", "<!--/--></div></div>"], _tmpl$8 = ["<th", ' scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider" style="', '">', "</th>"], _tmpl$9 = ["<tr", ' class="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">', "</tr>"], _tmpl$0 = ["<td", ' class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap">', "</td>"], _tmpl$1 = ["<span", ' class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">', "</span>"], _tmpl$10 = ["<div", ' class="mt-3 flex items-center"><span class="', '"><!--$-->', "<!--/--> <!--$-->", "<!--/-->%</span></div>"], _tmpl$11 = ["<p", ' class="mt-2 text-xs text-gray-500 dark:text-gray-400">', "</p>"], _tmpl$12 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><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><!--$-->", "<!--/--><!--$-->", "<!--/--></div></div>"], _tmpl$13 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><div class="', '">', "</div></div>"], _tmpl$14 = ["<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">', "</h3></div>"], _tmpl$15 = ["<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" style="', '" sandbox="allow-scripts allow-same-origin allow-popups allow-forms" loading="lazy"></iframe></div>'], _tmpl$16 = ["<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">', "</p></div>"], _tmpl$17 = ["<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]"><img', ' class="max-w-full max-h-[500px] object-contain rounded shadow-sm" loading="lazy"></div><!--$-->', "<!--/--></div>"], _tmpl$18 = ["<p", ' class="text-xs text-gray-500 dark:text-gray-400 truncate">', "</p>"], _tmpl$19 = ["<a", ' target="_blank" rel="noopener noreferrer" class="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"><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"><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">', "</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" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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"></line></svg></a>'], _tmpl$20 = ["<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">', "</p></div>"], _tmpl$21 = ["<div", ' class="', '"><div class="grid gap-4" style="', '">', "</div></div>"], _tmpl$22 = ["<div", ' style="', '">', "</div>"];
9
9
  function ChartRenderer(props) {
10
10
  const [iframeUrl, setIframeUrl] = solidJs.createSignal();
11
11
  const [isLoading, setIsLoading] = solidJs.createSignal(true);
@@ -128,6 +128,39 @@ function TextRenderer(props) {
128
128
  });
129
129
  return web.ssr(_tmpl$13, web.ssrHydrationKey(), `prose prose-sm dark:prose-invert max-w-none ${web.escape(textParams.className, true) || ""}`, htmlContent());
130
130
  }
131
+ function IframeRenderer(props) {
132
+ const params = props.component.params;
133
+ return web.ssr(_tmpl$15, web.ssrHydrationKey(), web.escape(web.createComponent(solidJs.Show, {
134
+ get when() {
135
+ return params.title;
136
+ },
137
+ get children() {
138
+ return web.ssr(_tmpl$14, web.ssrHydrationKey(), web.escape(params.title));
139
+ }
140
+ })), web.ssrAttribute("src", web.escape(params.url, true), false) + web.ssrAttribute("title", web.escape(params.title, true) || "Embedded content", false), web.ssrStyleProperty("height:", web.escape(params.height, true) || "400px") + web.ssrStyleProperty(";min-height:", "300px"));
141
+ }
142
+ function ImageRenderer(props) {
143
+ const params = props.component.params;
144
+ return web.ssr(_tmpl$17, web.ssrHydrationKey(), web.ssrAttribute("src", web.escape(params.url, true), false) + web.ssrAttribute("alt", web.escape(params.alt, true) || "Image", false), web.escape(web.createComponent(solidJs.Show, {
145
+ get when() {
146
+ return params.caption;
147
+ },
148
+ get children() {
149
+ return web.ssr(_tmpl$16, web.ssrHydrationKey(), web.escape(params.caption));
150
+ }
151
+ })));
152
+ }
153
+ function LinkRenderer(props) {
154
+ const params = props.component.params;
155
+ return web.ssr(_tmpl$19, web.ssrHydrationKey() + web.ssrAttribute("href", web.escape(params.url, true), false), web.escape(params.label) || web.escape(params.url), web.escape(web.createComponent(solidJs.Show, {
156
+ get when() {
157
+ return params.description;
158
+ },
159
+ get children() {
160
+ return web.ssr(_tmpl$18, web.ssrHydrationKey(), web.escape(params.description));
161
+ }
162
+ })));
163
+ }
131
164
  function ComponentRenderer(props) {
132
165
  var _a, _b, _c;
133
166
  const validation$1 = validation.validateComponent(props.component);
@@ -138,7 +171,7 @@ function ComponentRenderer(props) {
138
171
  componentId: props.component.id,
139
172
  details: validation$1.errors
140
173
  });
141
- return web.ssr(_tmpl$14, web.ssrHydrationKey(), web.escape((_c = (_b = validation$1.errors) == null ? void 0 : _b[0]) == null ? void 0 : _c.message) || "Unknown validation error");
174
+ return web.ssr(_tmpl$20, web.ssrHydrationKey(), web.escape((_c = (_b = validation$1.errors) == null ? void 0 : _b[0]) == null ? void 0 : _c.message) || "Unknown validation error");
142
175
  }
143
176
  return web.createComponent(GenerativeUIErrorBoundary.GenerativeUIErrorBoundary, {
144
177
  get componentId() {
@@ -202,6 +235,39 @@ function ComponentRenderer(props) {
202
235
  }
203
236
  });
204
237
  }
238
+ }), web.createComponent(solidJs.Show, {
239
+ get when() {
240
+ return props.component.type === "iframe";
241
+ },
242
+ get children() {
243
+ return web.createComponent(IframeRenderer, {
244
+ get component() {
245
+ return props.component;
246
+ }
247
+ });
248
+ }
249
+ }), web.createComponent(solidJs.Show, {
250
+ get when() {
251
+ return props.component.type === "image";
252
+ },
253
+ get children() {
254
+ return web.createComponent(ImageRenderer, {
255
+ get component() {
256
+ return props.component;
257
+ }
258
+ });
259
+ }
260
+ }), web.createComponent(solidJs.Show, {
261
+ get when() {
262
+ return props.component.type === "link";
263
+ },
264
+ get children() {
265
+ return web.createComponent(LinkRenderer, {
266
+ get component() {
267
+ return props.component;
268
+ }
269
+ });
270
+ }
205
271
  })];
206
272
  }
207
273
  });
@@ -234,11 +300,11 @@ const UIResourceRenderer = (props) => {
234
300
  } = component.position;
235
301
  return `grid-column: ${colStart} / span ${colSpan}; grid-row: ${rowStart ? `${rowStart} / span ${rowSpan}` : "auto"}`;
236
302
  };
237
- return web.ssr(_tmpl$15, web.ssrHydrationKey(), `w-full ${web.escape(props.class, true) || ""}`, web.ssrStyle(gridContainerStyle()), web.escape(web.createComponent(solidJs.For, {
303
+ return web.ssr(_tmpl$21, web.ssrHydrationKey(), `w-full ${web.escape(props.class, true) || ""}`, web.ssrStyle(gridContainerStyle()), web.escape(web.createComponent(solidJs.For, {
238
304
  get each() {
239
305
  return layout().components;
240
306
  },
241
- children: (component) => web.ssr(_tmpl$16, web.ssrHydrationKey(), web.ssrStyle(getGridStyleString(component)), web.escape(web.createComponent(ComponentRenderer, {
307
+ children: (component) => web.ssr(_tmpl$22, web.ssrHydrationKey(), web.ssrStyle(getGridStyleString(component)), web.escape(web.createComponent(ComponentRenderer, {
242
308
  component,
243
309
  get onError() {
244
310
  return props.onError;
@@ -1 +1 @@
1
- {"version":3,"file":"UIResourceRenderer.cjs","sources":["../../../../src/components/UIResourceRenderer.tsx"],"sourcesContent":["/**\n * UI Resource Renderer Component\n * Phase 0: Foundation with iframe sandbox and composite grid support\n *\n * Security features:\n * - Sandboxed iframes for untrusted content\n * - CSP enforcement via middleware\n * - XSS prevention with DOMPurify\n * - Domain whitelist validation\n *\n * Performance:\n * - Lazy loading with Intersection Observer\n * - Render timeout enforcement\n * - Error boundaries for isolation\n */\n\nimport { Component, createSignal, onMount, Show, For, createMemo } from 'solid-js'\nimport type { UIComponent, UILayout, RendererError, ComponentType } from '../types'\nimport { validateComponent, DEFAULT_RESOURCE_LIMITS } from '../services/validation'\nimport { GenerativeUIErrorBoundary } from './GenerativeUIErrorBoundary'\nimport { marked } from 'marked'\n\n/**\n * Props for UIResourceRenderer\n */\nexport interface UIResourceRendererProps {\n /**\n * Single component or full layout to render\n */\n content: UIComponent | UILayout\n\n /**\n * Lazy loading (default: true)\n */\n lazyLoad?: boolean\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Custom CSS class\n */\n class?: string\n}\n\n/**\n * Render a single chart component in a sandboxed iframe\n */\nfunction ChartRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const [iframeUrl, setIframeUrl] = createSignal<string>()\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n\n onMount(() => {\n const chartParams = props.component.params as any\n\n // Build Quickchart URL\n const chartConfig = {\n type: chartParams.type,\n data: chartParams.data,\n options: {\n ...chartParams.options,\n responsive: true,\n maintainAspectRatio: false,\n },\n }\n\n // Encode chart configuration for Quickchart API\n const configStr = encodeURIComponent(JSON.stringify(chartConfig))\n const url = `https://quickchart.io/chart?c=${configStr}&width=500&height=300&devicePixelRatio=2`\n\n // Validate domain (should always pass for quickchart.io)\n setIframeUrl(url)\n setIsLoading(false)\n })\n\n return (\n <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\">\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4\">\n <div class=\"text-center\">\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <Show when={iframeUrl() && !error()}>\n <div class=\"w-full h-full p-4\">\n <Show when={(props.component.params as any).title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {(props.component.params as any).title}\n </h3>\n </Show>\n <div class=\"w-full h-full\">\n <img\n src={iframeUrl()}\n alt=\"Chart visualization\"\n class=\"w-full h-auto max-h-[300px] object-contain\"\n onError={() => {\n setError('Failed to load chart')\n props.onError?.({\n type: 'render',\n message: 'Chart rendering failed',\n componentId: props.component.id,\n })\n }}\n />\n </div>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Render a table component\n */\nfunction TableRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const tableParams = props.component.params as any\n\n return (\n <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\">\n <div class=\"p-4\">\n <Show when={tableParams.title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {tableParams.title}\n </h3>\n </Show>\n\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\n <thead class=\"bg-gray-50 dark:bg-gray-900\">\n <tr>\n <For each={tableParams.columns}>\n {(column: any) => (\n <th\n scope=\"col\"\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider\"\n style={column.width ? { width: column.width } : {}}\n >\n {column.label}\n </th>\n )}\n </For>\n </tr>\n </thead>\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\n <For each={tableParams.rows.slice(0, DEFAULT_RESOURCE_LIMITS.maxTableRows)}>\n {(row: any) => (\n <tr class=\"hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\n <For each={tableParams.columns}>\n {(column: any) => (\n <td class=\"px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap\">\n {row[column.key] || '-'}\n </td>\n )}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n </div>\n\n <Show when={tableParams.pagination}>\n <div class=\"mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400\">\n <span>\n Showing {tableParams.pagination.currentPage * tableParams.pagination.pageSize + 1} -{' '}\n {Math.min(\n (tableParams.pagination.currentPage + 1) * tableParams.pagination.pageSize,\n tableParams.pagination.totalRows\n )}{' '}\n of {tableParams.pagination.totalRows}\n </span>\n </div>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a metric card component\n */\nfunction MetricRenderer(props: { component: UIComponent }) {\n const metricParams = props.component.params as any\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div class=\"flex flex-col h-full justify-between\">\n <div>\n <p class=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n {metricParams.title}\n </p>\n <div class=\"mt-2 flex items-baseline\">\n <p class=\"text-2xl font-semibold text-gray-900 dark:text-white\">{metricParams.value}</p>\n <Show when={metricParams.unit}>\n <span class=\"ml-2 text-sm font-medium text-gray-500 dark:text-gray-400\">\n {metricParams.unit}\n </span>\n </Show>\n </div>\n </div>\n\n <Show when={metricParams.trend}>\n <div class=\"mt-3 flex items-center\">\n <span\n class={`text-sm font-medium ${\n metricParams.trend.direction === 'up'\n ? 'text-green-600 dark:text-green-400'\n : metricParams.trend.direction === 'down'\n ? 'text-red-600 dark:text-red-400'\n : 'text-gray-600 dark:text-gray-400'\n }`}\n >\n {metricParams.trend.direction === 'up'\n ? '�'\n : metricParams.trend.direction === 'down'\n ? '�'\n : '�'}{' '}\n {Math.abs(metricParams.trend.value)}%\n </span>\n </div>\n </Show>\n\n <Show when={metricParams.subtitle}>\n <p class=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">{metricParams.subtitle}</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a text component (with optional markdown)\n */\nfunction TextRenderer(props: { component: UIComponent }) {\n const textParams = props.component.params as any\n\n // Convert markdown to HTML if markdown flag is true\n const htmlContent = createMemo(() => {\n if (textParams.markdown) {\n return marked.parse(textParams.content, { async: false }) as string\n }\n return textParams.content\n })\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div\n class={`prose prose-sm dark:prose-invert max-w-none ${textParams.className || ''}`}\n innerHTML={htmlContent()}\n />\n </div>\n )\n}\n\n/**\n * Render a single component with error boundary\n */\nfunction ComponentRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n // Validate component before rendering\n const validation = validateComponent(props.component)\n if (!validation.valid) {\n props.onError?.({\n type: 'validation',\n message: 'Component validation failed',\n componentId: props.component.id,\n details: validation.errors,\n })\n\n return (\n <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\">\n <p class=\"text-sm font-medium text-red-900 dark:text-red-100\">Validation Error</p>\n <p class=\"text-xs text-red-700 dark:text-red-300 mt-1\">\n {validation.errors?.[0]?.message || 'Unknown validation error'}\n </p>\n </div>\n )\n }\n\n // Render based on component type with enhanced error boundary\n return (\n <GenerativeUIErrorBoundary\n componentId={props.component.id}\n componentType={props.component.type}\n onError={props.onError}\n allowRetry={true}\n >\n <Show when={props.component.type === 'chart'}>\n <ChartRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'table'}>\n <TableRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'metric'}>\n <MetricRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'text'}>\n <TextRenderer component={props.component} />\n </Show>\n </GenerativeUIErrorBoundary>\n )\n}\n\n/**\n * Main UIResourceRenderer component\n */\nexport const UIResourceRenderer: Component<UIResourceRendererProps> = (props) => {\n const layout = () => {\n // ✅ PHASE 3.3 FIX: Check if content is a UIComponent (non-composite) vs UILayout (composite)\n // UILayout has type='composite', UIComponent has type='chart'|'table'|'metric'|'text'\n if ('type' in props.content && (props.content as any).type !== 'composite') {\n return {\n id: 'single-component',\n components: [props.content as UIComponent],\n grid: {\n columns: 12,\n gap: '1rem',\n },\n } as UILayout\n }\n return props.content as UILayout\n }\n\n // Grid position to CSS Grid styles\n const getGridStyles = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return {\n 'grid-column': '1 / span 12',\n 'grid-row': 'auto',\n }\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n\n return {\n 'grid-column': `${colStart} / span ${colSpan}`,\n 'grid-row': rowStart ? `${rowStart} / span ${rowSpan}` : 'auto',\n }\n }\n\n // Convert grid styles to CSS string to avoid setStyleProperty\n const gridContainerStyle = () =>\n `grid-template-columns: repeat(${layout().grid.columns}, 1fr); gap: ${layout().grid.gap}`\n\n // Convert component grid styles to CSS string\n const getGridStyleString = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return 'grid-column: 1 / span 12; grid-row: auto' // Default to full width\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n return `grid-column: ${colStart} / span ${colSpan}; grid-row: ${rowStart ? `${rowStart} / span ${rowSpan}` : 'auto'}`\n }\n\n return (\n <div class={`w-full ${props.class || ''}`}>\n <div class=\"grid gap-4\" style={gridContainerStyle()}>\n <For each={layout().components}>\n {(component) => (\n <div style={getGridStyleString(component)}>\n <ComponentRenderer component={component} onError={props.onError} />\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n"],"names":["ChartRenderer","props","iframeUrl","setIframeUrl","createSignal","isLoading","setIsLoading","error","setError","onMount","chartParams","component","params","chartConfig","type","data","options","responsive","maintainAspectRatio","configStr","encodeURIComponent","JSON","stringify","url","_$ssr","_tmpl$5","_$ssrHydrationKey","_$escape","_$createComponent","Show","when","children","_tmpl$","_tmpl$2","_tmpl$4","title","_tmpl$3","_$ssrAttribute","TableRenderer","tableParams","_tmpl$7","For","each","columns","column","_tmpl$8","_$ssrStyle","width","label","rows","slice","DEFAULT_RESOURCE_LIMITS","maxTableRows","row","_tmpl$9","_tmpl$0","key","pagination","_tmpl$6","currentPage","pageSize","Math","min","totalRows","MetricRenderer","metricParams","_tmpl$12","value","unit","_tmpl$1","trend","_tmpl$10","direction","abs","subtitle","_tmpl$11","TextRenderer","textParams","htmlContent","createMemo","markdown","marked","parse","content","async","_tmpl$13","className","ComponentRenderer","validation","validateComponent","valid","onError","message","componentId","id","details","errors","_tmpl$14","GenerativeUIErrorBoundary","componentType","allowRetry","UIResourceRenderer","layout","components","grid","gap","gridContainerStyle","getGridStyleString","position","console","colStart","colSpan","rowStart","rowSpan","_tmpl$15","class","_tmpl$16"],"mappings":"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"}
1
+ {"version":3,"file":"UIResourceRenderer.cjs","sources":["../../../../src/components/UIResourceRenderer.tsx"],"sourcesContent":["/**\n * UI Resource Renderer Component\n * Phase 0: Foundation with iframe sandbox and composite grid support\n *\n * Security features:\n * - Sandboxed iframes for untrusted content\n * - CSP enforcement via middleware\n * - XSS prevention with DOMPurify\n * - Domain whitelist validation\n *\n * Performance:\n * - Lazy loading with Intersection Observer\n * - Render timeout enforcement\n * - Error boundaries for isolation\n */\n\nimport { Component, createSignal, onMount, Show, For, createMemo } from 'solid-js'\nimport type { UIComponent, UILayout, RendererError, ComponentType } from '../types'\nimport { validateComponent, DEFAULT_RESOURCE_LIMITS } from '../services/validation'\nimport { GenerativeUIErrorBoundary } from './GenerativeUIErrorBoundary'\nimport { marked } from 'marked'\n\n/**\n * Props for UIResourceRenderer\n */\nexport interface UIResourceRendererProps {\n /**\n * Single component or full layout to render\n */\n content: UIComponent | UILayout\n\n /**\n * Lazy loading (default: true)\n */\n lazyLoad?: boolean\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Custom CSS class\n */\n class?: string\n}\n\n/**\n * Render a single chart component in a sandboxed iframe\n */\nfunction ChartRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const [iframeUrl, setIframeUrl] = createSignal<string>()\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n\n onMount(() => {\n const chartParams = props.component.params as any\n\n // Build Quickchart URL\n const chartConfig = {\n type: chartParams.type,\n data: chartParams.data,\n options: {\n ...chartParams.options,\n responsive: true,\n maintainAspectRatio: false,\n },\n }\n\n // Encode chart configuration for Quickchart API\n const configStr = encodeURIComponent(JSON.stringify(chartConfig))\n const url = `https://quickchart.io/chart?c=${configStr}&width=500&height=300&devicePixelRatio=2`\n\n // Validate domain (should always pass for quickchart.io)\n setIframeUrl(url)\n setIsLoading(false)\n })\n\n return (\n <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\">\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4\">\n <div class=\"text-center\">\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <Show when={iframeUrl() && !error()}>\n <div class=\"w-full h-full p-4\">\n <Show when={(props.component.params as any).title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {(props.component.params as any).title}\n </h3>\n </Show>\n <div class=\"w-full h-full\">\n <img\n src={iframeUrl()}\n alt=\"Chart visualization\"\n class=\"w-full h-auto max-h-[300px] object-contain\"\n onError={() => {\n setError('Failed to load chart')\n props.onError?.({\n type: 'render',\n message: 'Chart rendering failed',\n componentId: props.component.id,\n })\n }}\n />\n </div>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Render a table component\n */\nfunction TableRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const tableParams = props.component.params as any\n\n return (\n <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\">\n <div class=\"p-4\">\n <Show when={tableParams.title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {tableParams.title}\n </h3>\n </Show>\n\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\n <thead class=\"bg-gray-50 dark:bg-gray-900\">\n <tr>\n <For each={tableParams.columns}>\n {(column: any) => (\n <th\n scope=\"col\"\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider\"\n style={column.width ? { width: column.width } : {}}\n >\n {column.label}\n </th>\n )}\n </For>\n </tr>\n </thead>\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\n <For each={tableParams.rows.slice(0, DEFAULT_RESOURCE_LIMITS.maxTableRows)}>\n {(row: any) => (\n <tr class=\"hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\n <For each={tableParams.columns}>\n {(column: any) => (\n <td class=\"px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap\">\n {row[column.key] || '-'}\n </td>\n )}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n </div>\n\n <Show when={tableParams.pagination}>\n <div class=\"mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400\">\n <span>\n Showing {tableParams.pagination.currentPage * tableParams.pagination.pageSize + 1} -{' '}\n {Math.min(\n (tableParams.pagination.currentPage + 1) * tableParams.pagination.pageSize,\n tableParams.pagination.totalRows\n )}{' '}\n of {tableParams.pagination.totalRows}\n </span>\n </div>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a metric card component\n */\nfunction MetricRenderer(props: { component: UIComponent }) {\n const metricParams = props.component.params as any\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div class=\"flex flex-col h-full justify-between\">\n <div>\n <p class=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n {metricParams.title}\n </p>\n <div class=\"mt-2 flex items-baseline\">\n <p class=\"text-2xl font-semibold text-gray-900 dark:text-white\">{metricParams.value}</p>\n <Show when={metricParams.unit}>\n <span class=\"ml-2 text-sm font-medium text-gray-500 dark:text-gray-400\">\n {metricParams.unit}\n </span>\n </Show>\n </div>\n </div>\n\n <Show when={metricParams.trend}>\n <div class=\"mt-3 flex items-center\">\n <span\n class={`text-sm font-medium ${metricParams.trend.direction === 'up'\n ? 'text-green-600 dark:text-green-400'\n : metricParams.trend.direction === 'down'\n ? 'text-red-600 dark:text-red-400'\n : 'text-gray-600 dark:text-gray-400'\n }`}\n >\n {metricParams.trend.direction === 'up'\n ? '�'\n : metricParams.trend.direction === 'down'\n ? '�'\n : '�'}{' '}\n {Math.abs(metricParams.trend.value)}%\n </span>\n </div>\n </Show>\n\n <Show when={metricParams.subtitle}>\n <p class=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">{metricParams.subtitle}</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a text component (with optional markdown)\n */\nfunction TextRenderer(props: { component: UIComponent }) {\n const textParams = props.component.params as any\n\n // Convert markdown to HTML if markdown flag is true\n const htmlContent = createMemo(() => {\n if (textParams.markdown) {\n return marked.parse(textParams.content, { async: false }) as string\n }\n return textParams.content\n })\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div\n class={`prose prose-sm dark:prose-invert max-w-none ${textParams.className || ''}`}\n innerHTML={htmlContent()}\n />\n </div>\n )\n}\n\n/**\n * Render an iframe component\n */\nfunction IframeRenderer(props: { component: UIComponent }) {\n const params = props.component.params as any\n return (\n <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\">\n <Show when={params.title}>\n <div class=\"px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params.title}</h3>\n </div>\n </Show>\n <iframe\n src={params.url}\n title={params.title || 'Embedded content'}\n class=\"w-full border-0 flex-1\"\n style={{ height: params.height || '400px', 'min-height': '300px' }}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-forms\"\n loading=\"lazy\"\n />\n </div>\n )\n}\n\n/**\n * Render an image component\n */\nfunction ImageRenderer(props: { component: UIComponent }) {\n const params = props.component.params as any\n return (\n <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\">\n <div class=\"flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]\">\n <img\n src={params.url}\n alt={params.alt || 'Image'}\n class=\"max-w-full max-h-[500px] object-contain rounded shadow-sm\"\n loading=\"lazy\"\n />\n </div>\n <Show when={params.caption}>\n <div class=\"p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400 text-center\">{params.caption}</p>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Render a link component\n */\nfunction LinkRenderer(props: { component: UIComponent }) {\n const params = props.component.params as any\n return (\n <a\n href={params.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"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\"\n >\n <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\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-5 h-5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <h4 class=\"text-sm font-medium text-gray-900 dark:text-white truncate\">\n {params.label || params.url}\n </h4>\n <Show when={params.description}>\n <p class=\"text-xs text-gray-500 dark:text-gray-400 truncate\">{params.description}</p>\n </Show>\n </div>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n </a>\n )\n}\n\n/**\n * Render a single component with error boundary\n */\nfunction ComponentRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n // Validate component before rendering\n const validation = validateComponent(props.component)\n if (!validation.valid) {\n props.onError?.({\n type: 'validation',\n message: 'Component validation failed',\n componentId: props.component.id,\n details: validation.errors,\n })\n\n return (\n <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\">\n <p class=\"text-sm font-medium text-red-900 dark:text-red-100\">Validation Error</p>\n <p class=\"text-xs text-red-700 dark:text-red-300 mt-1\">\n {validation.errors?.[0]?.message || 'Unknown validation error'}\n </p>\n </div>\n )\n }\n\n // Render based on component type with enhanced error boundary\n return (\n <GenerativeUIErrorBoundary\n componentId={props.component.id}\n componentType={props.component.type}\n onError={props.onError}\n allowRetry={true}\n >\n <Show when={props.component.type === 'chart'}>\n <ChartRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'table'}>\n <TableRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'metric'}>\n <MetricRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'text'}>\n <TextRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'iframe'}>\n <IframeRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'image'}>\n <ImageRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'link'}>\n <LinkRenderer component={props.component} />\n </Show>\n </GenerativeUIErrorBoundary>\n )\n}\n\n/**\n * Main UIResourceRenderer component\n */\nexport const UIResourceRenderer: Component<UIResourceRendererProps> = (props) => {\n const layout = () => {\n // ✅ PHASE 3.3 FIX: Check if content is a UIComponent (non-composite) vs UILayout (composite)\n // UILayout has type='composite', UIComponent has type='chart'|'table'|'metric'|'text'\n if ('type' in props.content && (props.content as any).type !== 'composite') {\n return {\n id: 'single-component',\n components: [props.content as UIComponent],\n grid: {\n columns: 12,\n gap: '1rem',\n },\n } as UILayout\n }\n return props.content as UILayout\n }\n\n // Grid position to CSS Grid styles\n const getGridStyles = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return {\n 'grid-column': '1 / span 12',\n 'grid-row': 'auto',\n }\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n\n return {\n 'grid-column': `${colStart} / span ${colSpan}`,\n 'grid-row': rowStart ? `${rowStart} / span ${rowSpan}` : 'auto',\n }\n }\n\n // Convert grid styles to CSS string to avoid setStyleProperty\n const gridContainerStyle = () =>\n `grid-template-columns: repeat(${layout().grid.columns}, 1fr); gap: ${layout().grid.gap}`\n\n // Convert component grid styles to CSS string\n const getGridStyleString = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return 'grid-column: 1 / span 12; grid-row: auto' // Default to full width\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n return `grid-column: ${colStart} / span ${colSpan}; grid-row: ${rowStart ? `${rowStart} / span ${rowSpan}` : 'auto'}`\n }\n\n return (\n <div class={`w-full ${props.class || ''}`}>\n <div class=\"grid gap-4\" style={gridContainerStyle()}>\n <For each={layout().components}>\n {(component) => (\n <div style={getGridStyleString(component)}>\n <ComponentRenderer component={component} onError={props.onError} />\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n"],"names":["ChartRenderer","props","iframeUrl","setIframeUrl","createSignal","isLoading","setIsLoading","error","setError","onMount","chartParams","component","params","chartConfig","type","data","options","responsive","maintainAspectRatio","configStr","encodeURIComponent","JSON","stringify","url","_$ssr","_tmpl$5","_$ssrHydrationKey","_$escape","_$createComponent","Show","when","children","_tmpl$","_tmpl$2","_tmpl$4","title","_tmpl$3","_$ssrAttribute","TableRenderer","tableParams","_tmpl$7","For","each","columns","column","_tmpl$8","_$ssrStyle","width","label","rows","slice","DEFAULT_RESOURCE_LIMITS","maxTableRows","row","_tmpl$9","_tmpl$0","key","pagination","_tmpl$6","currentPage","pageSize","Math","min","totalRows","MetricRenderer","metricParams","_tmpl$12","value","unit","_tmpl$1","trend","_tmpl$10","direction","abs","subtitle","_tmpl$11","TextRenderer","textParams","htmlContent","createMemo","markdown","marked","parse","content","async","_tmpl$13","className","IframeRenderer","_tmpl$15","_tmpl$14","_$ssrStyleProperty","height","ImageRenderer","_tmpl$17","alt","caption","_tmpl$16","LinkRenderer","_tmpl$19","description","_tmpl$18","ComponentRenderer","validation","validateComponent","valid","onError","message","componentId","id","details","errors","_tmpl$20","GenerativeUIErrorBoundary","componentType","allowRetry","UIResourceRenderer","layout","components","grid","gap","gridContainerStyle","getGridStyleString","position","console","colStart","colSpan","rowStart","rowSpan","_tmpl$21","class","_tmpl$22"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { ssr, ssrHydrationKey, escape, ssrStyle, createComponent, ssrAttribute } from "solid-js/web";
1
+ import { ssr, ssrHydrationKey, escape, ssrStyle, createComponent, ssrAttribute, ssrStyleProperty } from "solid-js/web";
2
2
  import { For, Show, createSignal, onMount, createMemo } from "solid-js";
3
3
  import { validateComponent, DEFAULT_RESOURCE_LIMITS } from "../services/validation.js";
4
4
  import { GenerativeUIErrorBoundary } from "./GenerativeUIErrorBoundary.js";
5
5
  import { marked as k } from "../../../node_modules/.pnpm/marked@16.4.2/node_modules/marked/lib/marked.esm.js";
6
- var _tmpl$ = ["<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"></div></div>'], _tmpl$2 = ["<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">', "</p></div></div>"], _tmpl$3 = ["<h3", ' class="text-sm font-semibold text-gray-900 dark:text-white mb-3">', "</h3>"], _tmpl$4 = ["<div", ' class="w-full h-full p-4"><!--$-->', '<!--/--><div class="w-full h-full"><img', ' alt="Chart visualization" class="w-full h-auto max-h-[300px] object-contain"></div></div>'], _tmpl$5 = ["<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"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div>"], _tmpl$6 = ["<div", ' class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!--$-->', "<!--/--> - <!--$-->", "<!--/--> of <!--$-->", "<!--/--></span></div>"], _tmpl$7 = ["<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"><div class="p-4"><!--$-->', '<!--/--><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700"><thead class="bg-gray-50 dark:bg-gray-900"><tr>', '</tr></thead><tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">', "</tbody></table></div><!--$-->", "<!--/--></div></div>"], _tmpl$8 = ["<th", ' scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider" style="', '">', "</th>"], _tmpl$9 = ["<tr", ' class="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">', "</tr>"], _tmpl$0 = ["<td", ' class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap">', "</td>"], _tmpl$1 = ["<span", ' class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">', "</span>"], _tmpl$10 = ["<div", ' class="mt-3 flex items-center"><span class="', '"><!--$-->', "<!--/--> <!--$-->", "<!--/-->%</span></div>"], _tmpl$11 = ["<p", ' class="mt-2 text-xs text-gray-500 dark:text-gray-400">', "</p>"], _tmpl$12 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><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><!--$-->", "<!--/--><!--$-->", "<!--/--></div></div>"], _tmpl$13 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><div class="', '">', "</div></div>"], _tmpl$14 = ["<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">', "</p></div>"], _tmpl$15 = ["<div", ' class="', '"><div class="grid gap-4" style="', '">', "</div></div>"], _tmpl$16 = ["<div", ' style="', '">', "</div>"];
6
+ var _tmpl$ = ["<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"></div></div>'], _tmpl$2 = ["<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">', "</p></div></div>"], _tmpl$3 = ["<h3", ' class="text-sm font-semibold text-gray-900 dark:text-white mb-3">', "</h3>"], _tmpl$4 = ["<div", ' class="w-full h-full p-4"><!--$-->', '<!--/--><div class="w-full h-full"><img', ' alt="Chart visualization" class="w-full h-auto max-h-[300px] object-contain"></div></div>'], _tmpl$5 = ["<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"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div>"], _tmpl$6 = ["<div", ' class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!--$-->', "<!--/--> - <!--$-->", "<!--/--> of <!--$-->", "<!--/--></span></div>"], _tmpl$7 = ["<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"><div class="p-4"><!--$-->', '<!--/--><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700"><thead class="bg-gray-50 dark:bg-gray-900"><tr>', '</tr></thead><tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">', "</tbody></table></div><!--$-->", "<!--/--></div></div>"], _tmpl$8 = ["<th", ' scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider" style="', '">', "</th>"], _tmpl$9 = ["<tr", ' class="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">', "</tr>"], _tmpl$0 = ["<td", ' class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap">', "</td>"], _tmpl$1 = ["<span", ' class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">', "</span>"], _tmpl$10 = ["<div", ' class="mt-3 flex items-center"><span class="', '"><!--$-->', "<!--/--> <!--$-->", "<!--/-->%</span></div>"], _tmpl$11 = ["<p", ' class="mt-2 text-xs text-gray-500 dark:text-gray-400">', "</p>"], _tmpl$12 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><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><!--$-->", "<!--/--><!--$-->", "<!--/--></div></div>"], _tmpl$13 = ["<div", ' class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><div class="', '">', "</div></div>"], _tmpl$14 = ["<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">', "</h3></div>"], _tmpl$15 = ["<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" style="', '" sandbox="allow-scripts allow-same-origin allow-popups allow-forms" loading="lazy"></iframe></div>'], _tmpl$16 = ["<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">', "</p></div>"], _tmpl$17 = ["<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]"><img', ' class="max-w-full max-h-[500px] object-contain rounded shadow-sm" loading="lazy"></div><!--$-->', "<!--/--></div>"], _tmpl$18 = ["<p", ' class="text-xs text-gray-500 dark:text-gray-400 truncate">', "</p>"], _tmpl$19 = ["<a", ' target="_blank" rel="noopener noreferrer" class="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"><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"><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">', "</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" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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"></line></svg></a>'], _tmpl$20 = ["<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">', "</p></div>"], _tmpl$21 = ["<div", ' class="', '"><div class="grid gap-4" style="', '">', "</div></div>"], _tmpl$22 = ["<div", ' style="', '">', "</div>"];
7
7
  function ChartRenderer(props) {
8
8
  const [iframeUrl, setIframeUrl] = createSignal();
9
9
  const [isLoading, setIsLoading] = createSignal(true);
@@ -126,6 +126,39 @@ function TextRenderer(props) {
126
126
  });
127
127
  return ssr(_tmpl$13, ssrHydrationKey(), `prose prose-sm dark:prose-invert max-w-none ${escape(textParams.className, true) || ""}`, htmlContent());
128
128
  }
129
+ function IframeRenderer(props) {
130
+ const params = props.component.params;
131
+ return ssr(_tmpl$15, ssrHydrationKey(), escape(createComponent(Show, {
132
+ get when() {
133
+ return params.title;
134
+ },
135
+ get children() {
136
+ return ssr(_tmpl$14, ssrHydrationKey(), escape(params.title));
137
+ }
138
+ })), ssrAttribute("src", escape(params.url, true), false) + ssrAttribute("title", escape(params.title, true) || "Embedded content", false), ssrStyleProperty("height:", escape(params.height, true) || "400px") + ssrStyleProperty(";min-height:", "300px"));
139
+ }
140
+ function ImageRenderer(props) {
141
+ const params = props.component.params;
142
+ return ssr(_tmpl$17, ssrHydrationKey(), ssrAttribute("src", escape(params.url, true), false) + ssrAttribute("alt", escape(params.alt, true) || "Image", false), escape(createComponent(Show, {
143
+ get when() {
144
+ return params.caption;
145
+ },
146
+ get children() {
147
+ return ssr(_tmpl$16, ssrHydrationKey(), escape(params.caption));
148
+ }
149
+ })));
150
+ }
151
+ function LinkRenderer(props) {
152
+ const params = props.component.params;
153
+ return ssr(_tmpl$19, ssrHydrationKey() + ssrAttribute("href", escape(params.url, true), false), escape(params.label) || escape(params.url), escape(createComponent(Show, {
154
+ get when() {
155
+ return params.description;
156
+ },
157
+ get children() {
158
+ return ssr(_tmpl$18, ssrHydrationKey(), escape(params.description));
159
+ }
160
+ })));
161
+ }
129
162
  function ComponentRenderer(props) {
130
163
  var _a, _b, _c;
131
164
  const validation = validateComponent(props.component);
@@ -136,7 +169,7 @@ function ComponentRenderer(props) {
136
169
  componentId: props.component.id,
137
170
  details: validation.errors
138
171
  });
139
- return ssr(_tmpl$14, ssrHydrationKey(), escape((_c = (_b = validation.errors) == null ? void 0 : _b[0]) == null ? void 0 : _c.message) || "Unknown validation error");
172
+ return ssr(_tmpl$20, ssrHydrationKey(), escape((_c = (_b = validation.errors) == null ? void 0 : _b[0]) == null ? void 0 : _c.message) || "Unknown validation error");
140
173
  }
141
174
  return createComponent(GenerativeUIErrorBoundary, {
142
175
  get componentId() {
@@ -200,6 +233,39 @@ function ComponentRenderer(props) {
200
233
  }
201
234
  });
202
235
  }
236
+ }), createComponent(Show, {
237
+ get when() {
238
+ return props.component.type === "iframe";
239
+ },
240
+ get children() {
241
+ return createComponent(IframeRenderer, {
242
+ get component() {
243
+ return props.component;
244
+ }
245
+ });
246
+ }
247
+ }), createComponent(Show, {
248
+ get when() {
249
+ return props.component.type === "image";
250
+ },
251
+ get children() {
252
+ return createComponent(ImageRenderer, {
253
+ get component() {
254
+ return props.component;
255
+ }
256
+ });
257
+ }
258
+ }), createComponent(Show, {
259
+ get when() {
260
+ return props.component.type === "link";
261
+ },
262
+ get children() {
263
+ return createComponent(LinkRenderer, {
264
+ get component() {
265
+ return props.component;
266
+ }
267
+ });
268
+ }
203
269
  })];
204
270
  }
205
271
  });
@@ -232,11 +298,11 @@ const UIResourceRenderer = (props) => {
232
298
  } = component.position;
233
299
  return `grid-column: ${colStart} / span ${colSpan}; grid-row: ${rowStart ? `${rowStart} / span ${rowSpan}` : "auto"}`;
234
300
  };
235
- return ssr(_tmpl$15, ssrHydrationKey(), `w-full ${escape(props.class, true) || ""}`, ssrStyle(gridContainerStyle()), escape(createComponent(For, {
301
+ return ssr(_tmpl$21, ssrHydrationKey(), `w-full ${escape(props.class, true) || ""}`, ssrStyle(gridContainerStyle()), escape(createComponent(For, {
236
302
  get each() {
237
303
  return layout().components;
238
304
  },
239
- children: (component) => ssr(_tmpl$16, ssrHydrationKey(), ssrStyle(getGridStyleString(component)), escape(createComponent(ComponentRenderer, {
305
+ children: (component) => ssr(_tmpl$22, ssrHydrationKey(), ssrStyle(getGridStyleString(component)), escape(createComponent(ComponentRenderer, {
240
306
  component,
241
307
  get onError() {
242
308
  return props.onError;
@@ -1 +1 @@
1
- {"version":3,"file":"UIResourceRenderer.js","sources":["../../../../src/components/UIResourceRenderer.tsx"],"sourcesContent":["/**\n * UI Resource Renderer Component\n * Phase 0: Foundation with iframe sandbox and composite grid support\n *\n * Security features:\n * - Sandboxed iframes for untrusted content\n * - CSP enforcement via middleware\n * - XSS prevention with DOMPurify\n * - Domain whitelist validation\n *\n * Performance:\n * - Lazy loading with Intersection Observer\n * - Render timeout enforcement\n * - Error boundaries for isolation\n */\n\nimport { Component, createSignal, onMount, Show, For, createMemo } from 'solid-js'\nimport type { UIComponent, UILayout, RendererError, ComponentType } from '../types'\nimport { validateComponent, DEFAULT_RESOURCE_LIMITS } from '../services/validation'\nimport { GenerativeUIErrorBoundary } from './GenerativeUIErrorBoundary'\nimport { marked } from 'marked'\n\n/**\n * Props for UIResourceRenderer\n */\nexport interface UIResourceRendererProps {\n /**\n * Single component or full layout to render\n */\n content: UIComponent | UILayout\n\n /**\n * Lazy loading (default: true)\n */\n lazyLoad?: boolean\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Custom CSS class\n */\n class?: string\n}\n\n/**\n * Render a single chart component in a sandboxed iframe\n */\nfunction ChartRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const [iframeUrl, setIframeUrl] = createSignal<string>()\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n\n onMount(() => {\n const chartParams = props.component.params as any\n\n // Build Quickchart URL\n const chartConfig = {\n type: chartParams.type,\n data: chartParams.data,\n options: {\n ...chartParams.options,\n responsive: true,\n maintainAspectRatio: false,\n },\n }\n\n // Encode chart configuration for Quickchart API\n const configStr = encodeURIComponent(JSON.stringify(chartConfig))\n const url = `https://quickchart.io/chart?c=${configStr}&width=500&height=300&devicePixelRatio=2`\n\n // Validate domain (should always pass for quickchart.io)\n setIframeUrl(url)\n setIsLoading(false)\n })\n\n return (\n <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\">\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4\">\n <div class=\"text-center\">\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <Show when={iframeUrl() && !error()}>\n <div class=\"w-full h-full p-4\">\n <Show when={(props.component.params as any).title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {(props.component.params as any).title}\n </h3>\n </Show>\n <div class=\"w-full h-full\">\n <img\n src={iframeUrl()}\n alt=\"Chart visualization\"\n class=\"w-full h-auto max-h-[300px] object-contain\"\n onError={() => {\n setError('Failed to load chart')\n props.onError?.({\n type: 'render',\n message: 'Chart rendering failed',\n componentId: props.component.id,\n })\n }}\n />\n </div>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Render a table component\n */\nfunction TableRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const tableParams = props.component.params as any\n\n return (\n <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\">\n <div class=\"p-4\">\n <Show when={tableParams.title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {tableParams.title}\n </h3>\n </Show>\n\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\n <thead class=\"bg-gray-50 dark:bg-gray-900\">\n <tr>\n <For each={tableParams.columns}>\n {(column: any) => (\n <th\n scope=\"col\"\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider\"\n style={column.width ? { width: column.width } : {}}\n >\n {column.label}\n </th>\n )}\n </For>\n </tr>\n </thead>\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\n <For each={tableParams.rows.slice(0, DEFAULT_RESOURCE_LIMITS.maxTableRows)}>\n {(row: any) => (\n <tr class=\"hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\n <For each={tableParams.columns}>\n {(column: any) => (\n <td class=\"px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap\">\n {row[column.key] || '-'}\n </td>\n )}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n </div>\n\n <Show when={tableParams.pagination}>\n <div class=\"mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400\">\n <span>\n Showing {tableParams.pagination.currentPage * tableParams.pagination.pageSize + 1} -{' '}\n {Math.min(\n (tableParams.pagination.currentPage + 1) * tableParams.pagination.pageSize,\n tableParams.pagination.totalRows\n )}{' '}\n of {tableParams.pagination.totalRows}\n </span>\n </div>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a metric card component\n */\nfunction MetricRenderer(props: { component: UIComponent }) {\n const metricParams = props.component.params as any\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div class=\"flex flex-col h-full justify-between\">\n <div>\n <p class=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n {metricParams.title}\n </p>\n <div class=\"mt-2 flex items-baseline\">\n <p class=\"text-2xl font-semibold text-gray-900 dark:text-white\">{metricParams.value}</p>\n <Show when={metricParams.unit}>\n <span class=\"ml-2 text-sm font-medium text-gray-500 dark:text-gray-400\">\n {metricParams.unit}\n </span>\n </Show>\n </div>\n </div>\n\n <Show when={metricParams.trend}>\n <div class=\"mt-3 flex items-center\">\n <span\n class={`text-sm font-medium ${\n metricParams.trend.direction === 'up'\n ? 'text-green-600 dark:text-green-400'\n : metricParams.trend.direction === 'down'\n ? 'text-red-600 dark:text-red-400'\n : 'text-gray-600 dark:text-gray-400'\n }`}\n >\n {metricParams.trend.direction === 'up'\n ? '�'\n : metricParams.trend.direction === 'down'\n ? '�'\n : '�'}{' '}\n {Math.abs(metricParams.trend.value)}%\n </span>\n </div>\n </Show>\n\n <Show when={metricParams.subtitle}>\n <p class=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">{metricParams.subtitle}</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a text component (with optional markdown)\n */\nfunction TextRenderer(props: { component: UIComponent }) {\n const textParams = props.component.params as any\n\n // Convert markdown to HTML if markdown flag is true\n const htmlContent = createMemo(() => {\n if (textParams.markdown) {\n return marked.parse(textParams.content, { async: false }) as string\n }\n return textParams.content\n })\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div\n class={`prose prose-sm dark:prose-invert max-w-none ${textParams.className || ''}`}\n innerHTML={htmlContent()}\n />\n </div>\n )\n}\n\n/**\n * Render a single component with error boundary\n */\nfunction ComponentRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n // Validate component before rendering\n const validation = validateComponent(props.component)\n if (!validation.valid) {\n props.onError?.({\n type: 'validation',\n message: 'Component validation failed',\n componentId: props.component.id,\n details: validation.errors,\n })\n\n return (\n <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\">\n <p class=\"text-sm font-medium text-red-900 dark:text-red-100\">Validation Error</p>\n <p class=\"text-xs text-red-700 dark:text-red-300 mt-1\">\n {validation.errors?.[0]?.message || 'Unknown validation error'}\n </p>\n </div>\n )\n }\n\n // Render based on component type with enhanced error boundary\n return (\n <GenerativeUIErrorBoundary\n componentId={props.component.id}\n componentType={props.component.type}\n onError={props.onError}\n allowRetry={true}\n >\n <Show when={props.component.type === 'chart'}>\n <ChartRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'table'}>\n <TableRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'metric'}>\n <MetricRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'text'}>\n <TextRenderer component={props.component} />\n </Show>\n </GenerativeUIErrorBoundary>\n )\n}\n\n/**\n * Main UIResourceRenderer component\n */\nexport const UIResourceRenderer: Component<UIResourceRendererProps> = (props) => {\n const layout = () => {\n // ✅ PHASE 3.3 FIX: Check if content is a UIComponent (non-composite) vs UILayout (composite)\n // UILayout has type='composite', UIComponent has type='chart'|'table'|'metric'|'text'\n if ('type' in props.content && (props.content as any).type !== 'composite') {\n return {\n id: 'single-component',\n components: [props.content as UIComponent],\n grid: {\n columns: 12,\n gap: '1rem',\n },\n } as UILayout\n }\n return props.content as UILayout\n }\n\n // Grid position to CSS Grid styles\n const getGridStyles = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return {\n 'grid-column': '1 / span 12',\n 'grid-row': 'auto',\n }\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n\n return {\n 'grid-column': `${colStart} / span ${colSpan}`,\n 'grid-row': rowStart ? `${rowStart} / span ${rowSpan}` : 'auto',\n }\n }\n\n // Convert grid styles to CSS string to avoid setStyleProperty\n const gridContainerStyle = () =>\n `grid-template-columns: repeat(${layout().grid.columns}, 1fr); gap: ${layout().grid.gap}`\n\n // Convert component grid styles to CSS string\n const getGridStyleString = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return 'grid-column: 1 / span 12; grid-row: auto' // Default to full width\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n return `grid-column: ${colStart} / span ${colSpan}; grid-row: ${rowStart ? `${rowStart} / span ${rowSpan}` : 'auto'}`\n }\n\n return (\n <div class={`w-full ${props.class || ''}`}>\n <div class=\"grid gap-4\" style={gridContainerStyle()}>\n <For each={layout().components}>\n {(component) => (\n <div style={getGridStyleString(component)}>\n <ComponentRenderer component={component} onError={props.onError} />\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n"],"names":["ChartRenderer","props","iframeUrl","setIframeUrl","createSignal","isLoading","setIsLoading","error","setError","onMount","chartParams","component","params","chartConfig","type","data","options","responsive","maintainAspectRatio","configStr","encodeURIComponent","JSON","stringify","url","_$ssr","_tmpl$5","_$ssrHydrationKey","_$escape","_$createComponent","Show","when","children","_tmpl$","_tmpl$2","_tmpl$4","title","_tmpl$3","_$ssrAttribute","TableRenderer","tableParams","_tmpl$7","For","each","columns","column","_tmpl$8","_$ssrStyle","width","label","rows","slice","DEFAULT_RESOURCE_LIMITS","maxTableRows","row","_tmpl$9","_tmpl$0","key","pagination","_tmpl$6","currentPage","pageSize","Math","min","totalRows","MetricRenderer","metricParams","_tmpl$12","value","unit","_tmpl$1","trend","_tmpl$10","direction","abs","subtitle","_tmpl$11","TextRenderer","textParams","htmlContent","createMemo","markdown","marked","parse","content","async","_tmpl$13","className","ComponentRenderer","validation","validateComponent","valid","onError","message","componentId","id","details","errors","_tmpl$14","GenerativeUIErrorBoundary","componentType","allowRetry","UIResourceRenderer","layout","components","grid","gap","gridContainerStyle","getGridStyleString","position","console","colStart","colSpan","rowStart","rowSpan","_tmpl$15","class","_tmpl$16"],"mappings":"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"}
1
+ {"version":3,"file":"UIResourceRenderer.js","sources":["../../../../src/components/UIResourceRenderer.tsx"],"sourcesContent":["/**\n * UI Resource Renderer Component\n * Phase 0: Foundation with iframe sandbox and composite grid support\n *\n * Security features:\n * - Sandboxed iframes for untrusted content\n * - CSP enforcement via middleware\n * - XSS prevention with DOMPurify\n * - Domain whitelist validation\n *\n * Performance:\n * - Lazy loading with Intersection Observer\n * - Render timeout enforcement\n * - Error boundaries for isolation\n */\n\nimport { Component, createSignal, onMount, Show, For, createMemo } from 'solid-js'\nimport type { UIComponent, UILayout, RendererError, ComponentType } from '../types'\nimport { validateComponent, DEFAULT_RESOURCE_LIMITS } from '../services/validation'\nimport { GenerativeUIErrorBoundary } from './GenerativeUIErrorBoundary'\nimport { marked } from 'marked'\n\n/**\n * Props for UIResourceRenderer\n */\nexport interface UIResourceRendererProps {\n /**\n * Single component or full layout to render\n */\n content: UIComponent | UILayout\n\n /**\n * Lazy loading (default: true)\n */\n lazyLoad?: boolean\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Custom CSS class\n */\n class?: string\n}\n\n/**\n * Render a single chart component in a sandboxed iframe\n */\nfunction ChartRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const [iframeUrl, setIframeUrl] = createSignal<string>()\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n\n onMount(() => {\n const chartParams = props.component.params as any\n\n // Build Quickchart URL\n const chartConfig = {\n type: chartParams.type,\n data: chartParams.data,\n options: {\n ...chartParams.options,\n responsive: true,\n maintainAspectRatio: false,\n },\n }\n\n // Encode chart configuration for Quickchart API\n const configStr = encodeURIComponent(JSON.stringify(chartConfig))\n const url = `https://quickchart.io/chart?c=${configStr}&width=500&height=300&devicePixelRatio=2`\n\n // Validate domain (should always pass for quickchart.io)\n setIframeUrl(url)\n setIsLoading(false)\n })\n\n return (\n <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\">\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4\">\n <div class=\"text-center\">\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <Show when={iframeUrl() && !error()}>\n <div class=\"w-full h-full p-4\">\n <Show when={(props.component.params as any).title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {(props.component.params as any).title}\n </h3>\n </Show>\n <div class=\"w-full h-full\">\n <img\n src={iframeUrl()}\n alt=\"Chart visualization\"\n class=\"w-full h-auto max-h-[300px] object-contain\"\n onError={() => {\n setError('Failed to load chart')\n props.onError?.({\n type: 'render',\n message: 'Chart rendering failed',\n componentId: props.component.id,\n })\n }}\n />\n </div>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Render a table component\n */\nfunction TableRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n const tableParams = props.component.params as any\n\n return (\n <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\">\n <div class=\"p-4\">\n <Show when={tableParams.title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white mb-3\">\n {tableParams.title}\n </h3>\n </Show>\n\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\n <thead class=\"bg-gray-50 dark:bg-gray-900\">\n <tr>\n <For each={tableParams.columns}>\n {(column: any) => (\n <th\n scope=\"col\"\n class=\"px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider\"\n style={column.width ? { width: column.width } : {}}\n >\n {column.label}\n </th>\n )}\n </For>\n </tr>\n </thead>\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\n <For each={tableParams.rows.slice(0, DEFAULT_RESOURCE_LIMITS.maxTableRows)}>\n {(row: any) => (\n <tr class=\"hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\n <For each={tableParams.columns}>\n {(column: any) => (\n <td class=\"px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap\">\n {row[column.key] || '-'}\n </td>\n )}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n </div>\n\n <Show when={tableParams.pagination}>\n <div class=\"mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400\">\n <span>\n Showing {tableParams.pagination.currentPage * tableParams.pagination.pageSize + 1} -{' '}\n {Math.min(\n (tableParams.pagination.currentPage + 1) * tableParams.pagination.pageSize,\n tableParams.pagination.totalRows\n )}{' '}\n of {tableParams.pagination.totalRows}\n </span>\n </div>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a metric card component\n */\nfunction MetricRenderer(props: { component: UIComponent }) {\n const metricParams = props.component.params as any\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div class=\"flex flex-col h-full justify-between\">\n <div>\n <p class=\"text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide\">\n {metricParams.title}\n </p>\n <div class=\"mt-2 flex items-baseline\">\n <p class=\"text-2xl font-semibold text-gray-900 dark:text-white\">{metricParams.value}</p>\n <Show when={metricParams.unit}>\n <span class=\"ml-2 text-sm font-medium text-gray-500 dark:text-gray-400\">\n {metricParams.unit}\n </span>\n </Show>\n </div>\n </div>\n\n <Show when={metricParams.trend}>\n <div class=\"mt-3 flex items-center\">\n <span\n class={`text-sm font-medium ${metricParams.trend.direction === 'up'\n ? 'text-green-600 dark:text-green-400'\n : metricParams.trend.direction === 'down'\n ? 'text-red-600 dark:text-red-400'\n : 'text-gray-600 dark:text-gray-400'\n }`}\n >\n {metricParams.trend.direction === 'up'\n ? '�'\n : metricParams.trend.direction === 'down'\n ? '�'\n : '�'}{' '}\n {Math.abs(metricParams.trend.value)}%\n </span>\n </div>\n </Show>\n\n <Show when={metricParams.subtitle}>\n <p class=\"mt-2 text-xs text-gray-500 dark:text-gray-400\">{metricParams.subtitle}</p>\n </Show>\n </div>\n </div>\n )\n}\n\n/**\n * Render a text component (with optional markdown)\n */\nfunction TextRenderer(props: { component: UIComponent }) {\n const textParams = props.component.params as any\n\n // Convert markdown to HTML if markdown flag is true\n const htmlContent = createMemo(() => {\n if (textParams.markdown) {\n return marked.parse(textParams.content, { async: false }) as string\n }\n return textParams.content\n })\n\n return (\n <div class=\"w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <div\n class={`prose prose-sm dark:prose-invert max-w-none ${textParams.className || ''}`}\n innerHTML={htmlContent()}\n />\n </div>\n )\n}\n\n/**\n * Render an iframe component\n */\nfunction IframeRenderer(props: { component: UIComponent }) {\n const params = props.component.params as any\n return (\n <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\">\n <Show when={params.title}>\n <div class=\"px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params.title}</h3>\n </div>\n </Show>\n <iframe\n src={params.url}\n title={params.title || 'Embedded content'}\n class=\"w-full border-0 flex-1\"\n style={{ height: params.height || '400px', 'min-height': '300px' }}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-forms\"\n loading=\"lazy\"\n />\n </div>\n )\n}\n\n/**\n * Render an image component\n */\nfunction ImageRenderer(props: { component: UIComponent }) {\n const params = props.component.params as any\n return (\n <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\">\n <div class=\"flex-1 flex items-center justify-center p-4 bg-gray-50 dark:bg-gray-900 min-h-[200px]\">\n <img\n src={params.url}\n alt={params.alt || 'Image'}\n class=\"max-w-full max-h-[500px] object-contain rounded shadow-sm\"\n loading=\"lazy\"\n />\n </div>\n <Show when={params.caption}>\n <div class=\"p-3 border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400 text-center\">{params.caption}</p>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Render a link component\n */\nfunction LinkRenderer(props: { component: UIComponent }) {\n const params = props.component.params as any\n return (\n <a\n href={params.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"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\"\n >\n <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\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-5 h-5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <h4 class=\"text-sm font-medium text-gray-900 dark:text-white truncate\">\n {params.label || params.url}\n </h4>\n <Show when={params.description}>\n <p class=\"text-xs text-gray-500 dark:text-gray-400 truncate\">{params.description}</p>\n </Show>\n </div>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n </a>\n )\n}\n\n/**\n * Render a single component with error boundary\n */\nfunction ComponentRenderer(props: {\n component: UIComponent\n onError?: (error: RendererError) => void\n}) {\n // Validate component before rendering\n const validation = validateComponent(props.component)\n if (!validation.valid) {\n props.onError?.({\n type: 'validation',\n message: 'Component validation failed',\n componentId: props.component.id,\n details: validation.errors,\n })\n\n return (\n <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\">\n <p class=\"text-sm font-medium text-red-900 dark:text-red-100\">Validation Error</p>\n <p class=\"text-xs text-red-700 dark:text-red-300 mt-1\">\n {validation.errors?.[0]?.message || 'Unknown validation error'}\n </p>\n </div>\n )\n }\n\n // Render based on component type with enhanced error boundary\n return (\n <GenerativeUIErrorBoundary\n componentId={props.component.id}\n componentType={props.component.type}\n onError={props.onError}\n allowRetry={true}\n >\n <Show when={props.component.type === 'chart'}>\n <ChartRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'table'}>\n <TableRenderer component={props.component} onError={props.onError} />\n </Show>\n <Show when={props.component.type === 'metric'}>\n <MetricRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'text'}>\n <TextRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'iframe'}>\n <IframeRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'image'}>\n <ImageRenderer component={props.component} />\n </Show>\n <Show when={props.component.type === 'link'}>\n <LinkRenderer component={props.component} />\n </Show>\n </GenerativeUIErrorBoundary>\n )\n}\n\n/**\n * Main UIResourceRenderer component\n */\nexport const UIResourceRenderer: Component<UIResourceRendererProps> = (props) => {\n const layout = () => {\n // ✅ PHASE 3.3 FIX: Check if content is a UIComponent (non-composite) vs UILayout (composite)\n // UILayout has type='composite', UIComponent has type='chart'|'table'|'metric'|'text'\n if ('type' in props.content && (props.content as any).type !== 'composite') {\n return {\n id: 'single-component',\n components: [props.content as UIComponent],\n grid: {\n columns: 12,\n gap: '1rem',\n },\n } as UILayout\n }\n return props.content as UILayout\n }\n\n // Grid position to CSS Grid styles\n const getGridStyles = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return {\n 'grid-column': '1 / span 12',\n 'grid-row': 'auto',\n }\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n\n return {\n 'grid-column': `${colStart} / span ${colSpan}`,\n 'grid-row': rowStart ? `${rowStart} / span ${rowSpan}` : 'auto',\n }\n }\n\n // Convert grid styles to CSS string to avoid setStyleProperty\n const gridContainerStyle = () =>\n `grid-template-columns: repeat(${layout().grid.columns}, 1fr); gap: ${layout().grid.gap}`\n\n // Convert component grid styles to CSS string\n const getGridStyleString = (component: UIComponent) => {\n // ✅ PHASE 3 FIX: Defensive check for position field\n if (!component.position) {\n console.error('[UIResourceRenderer] Component missing position field:', component)\n return 'grid-column: 1 / span 12; grid-row: auto' // Default to full width\n }\n\n const { colStart, colSpan, rowStart, rowSpan = 1 } = component.position\n return `grid-column: ${colStart} / span ${colSpan}; grid-row: ${rowStart ? `${rowStart} / span ${rowSpan}` : 'auto'}`\n }\n\n return (\n <div class={`w-full ${props.class || ''}`}>\n <div class=\"grid gap-4\" style={gridContainerStyle()}>\n <For each={layout().components}>\n {(component) => (\n <div style={getGridStyleString(component)}>\n <ComponentRenderer component={component} onError={props.onError} />\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n"],"names":["ChartRenderer","props","iframeUrl","setIframeUrl","createSignal","isLoading","setIsLoading","error","setError","onMount","chartParams","component","params","chartConfig","type","data","options","responsive","maintainAspectRatio","configStr","encodeURIComponent","JSON","stringify","url","_$ssr","_tmpl$5","_$ssrHydrationKey","_$escape","_$createComponent","Show","when","children","_tmpl$","_tmpl$2","_tmpl$4","title","_tmpl$3","_$ssrAttribute","TableRenderer","tableParams","_tmpl$7","For","each","columns","column","_tmpl$8","_$ssrStyle","width","label","rows","slice","DEFAULT_RESOURCE_LIMITS","maxTableRows","row","_tmpl$9","_tmpl$0","key","pagination","_tmpl$6","currentPage","pageSize","Math","min","totalRows","MetricRenderer","metricParams","_tmpl$12","value","unit","_tmpl$1","trend","_tmpl$10","direction","abs","subtitle","_tmpl$11","TextRenderer","textParams","htmlContent","createMemo","markdown","marked","parse","content","async","_tmpl$13","className","IframeRenderer","_tmpl$15","_tmpl$14","_$ssrStyleProperty","height","ImageRenderer","_tmpl$17","alt","caption","_tmpl$16","LinkRenderer","_tmpl$19","description","_tmpl$18","ComponentRenderer","validation","validateComponent","valid","onError","message","componentId","id","details","errors","_tmpl$20","GenerativeUIErrorBoundary","componentType","allowRetry","UIResourceRenderer","layout","components","grid","gap","gridContainerStyle","getGridStyleString","position","console","colStart","colSpan","rowStart","rowSpan","_tmpl$21","class","_tmpl$22"],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  /**
8
8
  * Component types supported by the renderer
9
9
  */
10
- export type ComponentType = 'chart' | 'table' | 'metric' | 'text' | 'grid';
10
+ export type ComponentType = 'chart' | 'table' | 'metric' | 'text' | 'grid' | 'iframe' | 'image' | 'link';
11
11
  /**
12
12
  * Chart types (powered by Quickchart)
13
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-ship/mcp-ui-solid",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "SolidJS components for rendering MCP-generated UI resources",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",