@seed-ship/mcp-ui-solid 1.0.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # @mcp-ui/solid Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-01-14
9
+
10
+ ### Added
11
+ - Initial release of `@mcp-ui/solid` package
12
+ - `UIResourceRenderer` component for static dashboard rendering
13
+ - `StreamingUIRenderer` component for progressive streaming rendering
14
+ - `GenerativeUIErrorBoundary` for error isolation and retry logic
15
+ - `useStreamingUI` hook for SSE connection management
16
+ - Component validation and layout validation services
17
+ - Component registry system
18
+ - Internal logger utility (self-contained)
19
+ - Full TypeScript support with comprehensive types
20
+ - 12-column responsive grid layout system
21
+ - Support for chart, table, metric, and text components
22
+
23
+ ### Features
24
+ - **Progressive Streaming**: Components appear incrementally via SSE
25
+ - **Error Boundaries**: Graceful error handling with retry capability
26
+ - **Validation**: Built-in component and layout validation
27
+ - **Type Safety**: Full TypeScript definitions
28
+ - **Performance**: TTFB <500ms, optimized rendering
29
+ - **Responsive**: 12-column grid with flexible positioning
30
+ - **Clean API**: Simple, intuitive component interfaces
31
+ - **Zero Config**: Works out of the box with sensible defaults
32
+
33
+ ### Documentation
34
+ - README with installation and usage examples
35
+ - JSDoc comments for all public APIs
36
+ - TypeScript definitions for IntelliSense support
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Gabriel Brument
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # @mcp-ui/solid
2
+
3
+ SolidJS components for rendering MCP-generated UI resources.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @mcp-ui/solid
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```tsx
14
+ import { UIResourceRenderer, StreamingUIRenderer } from '@mcp-ui/solid'
15
+ import { useStreamingUI } from '@mcp-ui/solid/hooks'
16
+
17
+ // Static rendering
18
+ function Dashboard() {
19
+ const layout = {
20
+ id: 'dashboard-1',
21
+ type: 'composite',
22
+ components: [/* ... */]
23
+ }
24
+
25
+ return <UIResourceRenderer content={layout} />
26
+ }
27
+
28
+ // Streaming rendering
29
+ function StreamingDashboard() {
30
+ return (
31
+ <StreamingUIRenderer
32
+ query="Show me revenue trends"
33
+ spaceIds={['space-1']}
34
+ onComplete={(metadata) => console.log('Done!', metadata)}
35
+ />
36
+ )
37
+ }
38
+ ```
39
+
40
+ ## Features
41
+
42
+ - 📊 **12-Column Grid Layout**: Responsive Bootstrap-like grid system
43
+ - ⚡ **Progressive Streaming**: Components appear as they're generated
44
+ - 🎨 **Smooth Animations**: Fade-in effects and skeleton loading states
45
+ - 🔒 **Type Safety**: Full TypeScript support
46
+ - ✅ **Validation**: Built-in component and layout validation
47
+ - 🛡️ **Error Boundaries**: Graceful error handling
48
+
49
+ ## Documentation
50
+
51
+ See the [full documentation](../../docs/features/generative-ui/) for more details.
52
+
53
+ ## License
54
+
55
+ MIT
@@ -0,0 +1,5 @@
1
+ "use strict";const e=require("solid-js/web"),d=require("solid-js"),A=require("./useStreamingUI-CXmvpRhz.cjs"),_={maxDataPoints:1e3,maxTableRows:100,maxPayloadSize:50*1024,renderTimeout:5e3};function V(t){const r=[];return(t.colStart<1||t.colStart>12)&&r.push({path:"position.colStart",message:"Column start must be between 1 and 12",code:"INVALID_GRID_COL_START"}),(t.colSpan<1||t.colSpan>12)&&r.push({path:"position.colSpan",message:"Column span must be between 1 and 12",code:"INVALID_GRID_COL_SPAN"}),t.colStart+t.colSpan-1>12&&r.push({path:"position",message:"Column start + span exceeds grid width (12)",code:"GRID_OVERFLOW"}),t.rowStart!==void 0&&t.rowStart<1&&r.push({path:"position.rowStart",message:"Row start must be >= 1",code:"INVALID_GRID_ROW_START"}),t.rowSpan!==void 0&&t.rowSpan<1&&r.push({path:"position.rowSpan",message:"Row span must be >= 1",code:"INVALID_GRID_ROW_SPAN"}),{valid:r.length===0,errors:r.length>0?r:void 0}}function Y(t,r=_){const n=[],i=t.data.datasets.reduce((l,a)=>l+a.data.length,0);i>r.maxDataPoints&&n.push({path:"params.data",message:`Chart exceeds max data points: ${i} > ${r.maxDataPoints}`,code:"RESOURCE_LIMIT_EXCEEDED"});const o=t.data.labels.length;for(const[l,a]of t.data.datasets.entries())a.data.length!==o&&n.push({path:`params.data.datasets[${l}]`,message:`Dataset length mismatch: expected ${o}, got ${a.data.length}`,code:"DATA_LENGTH_MISMATCH"});for(const[l,a]of t.data.datasets.entries())for(const[s,c]of a.data.entries())(typeof c!="number"||!Number.isFinite(c))&&n.push({path:`params.data.datasets[${l}].data[${s}]`,message:`Invalid data value: ${c} (must be finite number)`,code:"INVALID_DATA_TYPE"});return{valid:n.length===0,errors:n.length>0?n:void 0}}function j(t,r=_){const n=[];t.rows.length>r.maxTableRows&&n.push({path:"params.rows",message:`Table exceeds max rows: ${t.rows.length} > ${r.maxTableRows}`,code:"RESOURCE_LIMIT_EXCEEDED"}),t.columns.length===0&&n.push({path:"params.columns",message:"Table must have at least one column",code:"EMPTY_COLUMNS"});const i=new Set;for(const[o,l]of t.columns.entries())i.has(l.key)&&n.push({path:`params.columns[${o}]`,message:`Duplicate column key: ${l.key}`,code:"DUPLICATE_COLUMN_KEY"}),i.add(l.key);for(const[o,l]of t.rows.entries())for(const a of t.columns)a.key in l||n.push({path:`params.rows[${o}]`,message:`Missing column key: ${a.key}`,code:"MISSING_COLUMN_DATA"});return{valid:n.length===0,errors:n.length>0?n:void 0}}function B(t,r=_){const n=JSON.stringify(t).length;return n>r.maxPayloadSize?{valid:!1,errors:[{path:"component",message:`Payload size exceeds limit: ${n} > ${r.maxPayloadSize} bytes`,code:"PAYLOAD_TOO_LARGE"}]}:{valid:!0}}function b(t,r=_){const n=[],i=V(t.position);i.valid||n.push(...i.errors||[]);const o=B(t,r);switch(o.valid||n.push(...o.errors||[]),t.type){case"chart":const l=Y(t.params,r);l.valid||n.push(...l.errors||[]);break;case"table":const a=j(t.params,r);a.valid||n.push(...a.errors||[]);break;case"metric":const s=t.params;(!s.title||!s.value)&&n.push({path:"params",message:"Metric must have title and value",code:"INVALID_METRIC"});break;case"text":t.params.content||n.push({path:"params",message:"Text component must have content",code:"INVALID_TEXT"});break;default:n.push({path:"type",message:`Unknown component type: ${t.type}`,code:"UNKNOWN_COMPONENT_TYPE"})}return{valid:n.length===0,errors:n.length>0?n:void 0}}function q(t,r=_){var i;const n=[];t.components.length===0&&n.push({path:"components",message:"Layout must have at least one component",code:"EMPTY_LAYOUT"}),t.components.length>12&&n.push({path:"components",message:`Layout exceeds max components: ${t.components.length} > 12`,code:"TOO_MANY_COMPONENTS"});for(const[o,l]of t.components.entries()){const a=b(l,r);a.valid||n.push(...((i=a.errors)==null?void 0:i.map(s=>({...s,path:`components[${o}].${s.path}`})))||[])}return t.grid.columns!==12&&n.push({path:"grid.columns",message:"Grid must have 12 columns (Bootstrap-like)",code:"INVALID_GRID_COLUMNS"}),{valid:n.length===0,errors:n.length>0?n:void 0}}var K=e.template('<p class="text-xs text-yellow-600 dark:text-yellow-400 mt-2 font-mono">'),W=e.template('<button class="mt-3 text-xs font-medium text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 underline">Retry Rendering'),H=e.template('<div class="w-full h-full bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4"><div class="flex items-start gap-3"><div class=flex-shrink-0><svg class="w-5 h-5 text-yellow-600 dark:text-yellow-400"fill=none stroke=currentColor viewBox="0 0 24 24"><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><p class="text-sm font-medium text-yellow-900 dark:text-yellow-100">Component Failed to Render</p><p class="text-xs text-yellow-700 dark:text-yellow-300 mt-1">Type: <!> | ID: <!>...');const P=A.createLogger("generative-ui");function J(t){return(()=>{var r=H(),n=r.firstChild,i=n.firstChild,o=i.nextSibling,l=o.firstChild,a=l.nextSibling,s=a.firstChild,c=s.nextSibling,g=c.nextSibling,m=g.nextSibling;return m.nextSibling,e.insert(a,()=>t.componentType,c),e.insert(a,()=>t.componentId.slice(0,8),m),e.insert(o,e.createComponent(d.Show,{get when(){return!1},get children(){var u=K();return e.insert(u,()=>t.error.message),u}}),null),e.insert(o,e.createComponent(d.Show,{get when(){return t.allowRetry},get children(){var u=W();return e.addEventListener(u,"click",t.onRetry,!0),u}}),null),r})()}const S=t=>{const[r,n]=d.createSignal(0),[i]=d.createSignal(performance.now()),o=a=>{var m;const c=performance.now()-i(),g={componentId:t.componentId,componentType:t.componentType,errorMessage:a.message,errorStack:a.stack,renderDuration:c,retryCount:r(),timestamp:new Date().toISOString(),userAgent:navigator.userAgent,viewport:{width:window.innerWidth,height:window.innerHeight}};P.error(`Component render failed: ${t.componentType}`,g),(m=t.onError)==null||m.call(t,{type:"render",message:a.message,componentId:t.componentId,details:g})},l=()=>{const a=r()+1;P.info(`Retrying component render: ${t.componentType}`,{componentId:t.componentId,retryCount:a}),n(a)};return e.createComponent(d.ErrorBoundary,{fallback:a=>(o(a),t.fallback?t.fallback(a,t.allowRetry?l:void 0):e.createComponent(J,{error:a,get componentId(){return t.componentId},get componentType(){return t.componentType},get allowRetry(){return t.allowRetry},onRetry:l})),get children(){return r(),e.memo(()=>t.children)}})};e.delegateEvents(["click"]);var X=e.template('<div class="absolute inset-0 flex items-center justify-center"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600">'),Q=e.template('<div class="absolute inset-0 flex items-center justify-center p-4"><div class=text-center><p class="text-red-600 dark:text-red-400 text-sm font-medium">Chart Error</p><p class="text-gray-600 dark:text-gray-400 text-xs mt-1">'),N=e.template('<h3 class="text-sm font-semibold text-gray-900 dark:text-white mb-3">'),Z=e.template('<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">'),ee=e.template('<div class="relative w-full h-full min-h-[300px] bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden">'),te=e.template('<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400"><span>Showing <!> - <!> of '),re=e.template('<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden"><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">'),ne=e.template('<th scope=col class="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">'),ae=e.template('<tr class="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors">'),le=e.template('<td class="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap">'),oe=e.template('<span class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">'),ie=e.template('<div class="mt-3 flex items-center"><span> <!>%'),se=e.template('<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">'),de=e.template('<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 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">'),ce=e.template('<div class="w-full h-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4"><div>'),me=e.template('<div class="w-full h-full bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4"><p class="text-sm font-medium text-red-900 dark:text-red-100">Validation Error</p><p class="text-xs text-red-700 dark:text-red-300 mt-1">'),ue=e.template('<div><div class="grid gap-4">'),ge=e.template("<div>");function he(t){const[r,n]=d.createSignal(),[i,o]=d.createSignal(!0),[l,a]=d.createSignal();return d.onMount(()=>{const s=t.component.params,c={type:s.type,data:s.data,options:{...s.options,responsive:!0,maintainAspectRatio:!1}},m=`https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(c))}&width=500&height=300&devicePixelRatio=2`;n(m),o(!1)}),(()=>{var s=ee();return e.insert(s,e.createComponent(d.Show,{get when(){return i()},get children(){return X()}}),null),e.insert(s,e.createComponent(d.Show,{get when(){return l()},get children(){var c=Q(),g=c.firstChild,m=g.firstChild,u=m.nextSibling;return e.insert(u,l),c}}),null),e.insert(s,e.createComponent(d.Show,{get when(){return e.memo(()=>!!r())()&&!l()},get children(){var c=Z(),g=c.firstChild,m=g.firstChild;return e.insert(c,e.createComponent(d.Show,{get when(){return t.component.params.title},get children(){var u=N();return e.insert(u,()=>t.component.params.title),u}}),g),m.addEventListener("error",()=>{var u;a("Failed to load chart"),(u=t.onError)==null||u.call(t,{type:"render",message:"Chart rendering failed",componentId:t.component.id})}),e.effect(()=>e.setAttribute(m,"src",r())),c}}),null),s})()}function pe(t){const r=t.component.params;return(()=>{var n=re(),i=n.firstChild,o=i.firstChild,l=o.firstChild,a=l.firstChild,s=a.firstChild,c=a.nextSibling;return e.insert(i,e.createComponent(d.Show,{get when(){return r.title},get children(){var g=N();return e.insert(g,()=>r.title),g}}),o),e.insert(s,e.createComponent(d.For,{get each(){return r.columns},children:g=>(()=>{var m=ne();return e.insert(m,()=>g.label),e.effect(u=>e.style(m,g.width?{width:g.width}:{},u)),m})()})),e.insert(c,e.createComponent(d.For,{get each(){return r.rows.slice(0,_.maxTableRows)},children:g=>(()=>{var m=ae();return e.insert(m,e.createComponent(d.For,{get each(){return r.columns},children:u=>(()=>{var x=le();return e.insert(x,()=>g[u.key]||"-"),x})()})),m})()})),e.insert(i,e.createComponent(d.Show,{get when(){return r.pagination},get children(){var g=te(),m=g.firstChild,u=m.firstChild,x=u.nextSibling,h=x.nextSibling,v=h.nextSibling;return v.nextSibling,e.insert(m,()=>r.pagination.currentPage*r.pagination.pageSize+1,x),e.insert(m,()=>Math.min((r.pagination.currentPage+1)*r.pagination.pageSize,r.pagination.totalRows),v),e.insert(m,()=>r.pagination.totalRows,null),g}}),null),n})()}function ve(t){const r=t.component.params;return(()=>{var n=de(),i=n.firstChild,o=i.firstChild,l=o.firstChild,a=l.nextSibling,s=a.firstChild;return e.insert(l,()=>r.title),e.insert(s,()=>r.value),e.insert(a,e.createComponent(d.Show,{get when(){return r.unit},get children(){var c=oe();return e.insert(c,()=>r.unit),c}}),null),e.insert(i,e.createComponent(d.Show,{get when(){return r.trend},get children(){var c=ie(),g=c.firstChild,m=g.firstChild,u=m.nextSibling;return u.nextSibling,e.insert(g,(()=>{var x=e.memo(()=>r.trend.direction==="up");return()=>(x()||r.trend.direction==="down","�")})(),m),e.insert(g,()=>Math.abs(r.trend.value),u),e.effect(()=>e.className(g,`text-sm font-medium ${r.trend.direction==="up"?"text-green-600 dark:text-green-400":r.trend.direction==="down"?"text-red-600 dark:text-red-400":"text-gray-600 dark:text-gray-400"}`)),c}}),null),e.insert(i,e.createComponent(d.Show,{get when(){return r.subtitle},get children(){var c=se();return e.insert(c,()=>r.subtitle),c}}),null),n})()}function fe(t){const r=t.component.params;return(()=>{var n=ce(),i=n.firstChild;return e.effect(o=>{var l=`prose prose-sm dark:prose-invert max-w-none ${r.className||""}`,a=r.content;return l!==o.e&&e.className(i,o.e=l),a!==o.t&&(i.innerHTML=o.t=a),o},{e:void 0,t:void 0}),n})()}function xe(t){var n;const r=b(t.component);return r.valid?e.createComponent(S,{get componentId(){return t.component.id},get componentType(){return t.component.type},get onError(){return t.onError},allowRetry:!0,get children(){return[e.createComponent(d.Show,{get when(){return t.component.type==="chart"},get children(){return e.createComponent(he,{get component(){return t.component},get onError(){return t.onError}})}}),e.createComponent(d.Show,{get when(){return t.component.type==="table"},get children(){return e.createComponent(pe,{get component(){return t.component},get onError(){return t.onError}})}}),e.createComponent(d.Show,{get when(){return t.component.type==="metric"},get children(){return e.createComponent(ve,{get component(){return t.component}})}}),e.createComponent(d.Show,{get when(){return t.component.type==="text"},get children(){return e.createComponent(fe,{get component(){return t.component}})}})]}}):((n=t.onError)==null||n.call(t,{type:"validation",message:"Component validation failed",componentId:t.component.id,details:r.errors}),(()=>{var i=me(),o=i.firstChild,l=o.nextSibling;return e.insert(l,()=>{var a,s;return((s=(a=r.errors)==null?void 0:a[0])==null?void 0:s.message)||"Unknown validation error"}),i})())}const $e=t=>{const r=()=>"type"in t.content?{id:"single-component",components:[t.content],grid:{columns:12,gap:"1rem"}}:t.content,n=i=>{const{colStart:o,colSpan:l,rowStart:a,rowSpan:s=1}=i.position;return{"grid-column":`${o} / span ${l}`,"grid-row":a?`${a} / span ${s}`:"auto"}};return(()=>{var i=ue(),o=i.firstChild;return e.insert(o,e.createComponent(d.For,{get each(){return r().components},children:l=>(()=>{var a=ge();return e.insert(a,e.createComponent(xe,{component:l,get onError(){return t.onError}})),e.effect(s=>e.style(a,n(l),s)),a})()})),e.effect(l=>{var a=`w-full ${t.class||""}`,s=`repeat(${r().grid.columns}, 1fr)`,c=r().grid.gap;return a!==l.e&&e.className(i,l.e=a),s!==l.t&&e.setStyleProperty(o,"grid-template-columns",l.t=s),c!==l.a&&e.setStyleProperty(o,"gap",l.a=c),l},{e:void 0,t:void 0,a:void 0}),i})()};var ye=e.template('<div class="w-full bg-error-subtle border border-border-error rounded-lg p-4"><p class="text-sm font-medium text-error-primary">Validation Error</p><p class="text-xs text-text-secondary mt-1">'),we=e.template('<h3 class="text-sm font-semibold text-text-primary">'),_e=e.template('<span class="text-sm text-text-secondary">'),be=e.template('<div class=mt-2><p class="text-2xl font-semibold text-text-primary">'),Ce=e.template('<div class="w-full bg-surface-secondary border border-border-subtle rounded-lg p-4"><div class="flex items-center gap-2 mb-2"><span class="text-xs font-medium text-text-tertiary uppercase"></span></div><div class="mt-3 text-xs text-text-tertiary">Component ID: <!>...'),Se=e.template('<span class="text-sm text-text-secondary"> / '),ke=e.template('<div class=mt-2><div class="h-1 w-full overflow-hidden rounded-full bg-surface-tertiary"><div class="animate-progress-indeterminate h-full w-1/3 bg-brand-primary">'),Ie=e.template('<div class="mb-4 rounded-lg border border-border-subtle bg-surface-secondary p-4"><div class="mb-2 flex items-center justify-between"><span class="text-sm font-medium text-text-primary"></span></div><div class="h-2 w-full overflow-hidden rounded-full bg-surface-tertiary"><div class="h-full bg-brand-primary transition-all duration-300 ease-out">'),Re=e.template('<button type=button class="mt-3 rounded-md bg-error-primary px-3 py-1.5 text-sm font-medium text-white hover:bg-error-hover">Retry'),Ee=e.template('<div class="mb-4 rounded-lg border border-border-error bg-error-subtle p-4"><div class="mb-2 flex items-center gap-2"><svg class="h-5 w-5 text-error-primary"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg><span class="font-medium text-error-primary"></span></div><p class="text-sm text-text-secondary">'),Te=e.template('<div><div class="font-medium text-text-primary">Cost</div><div>$'),Le=e.template('<div><div class="font-medium text-text-primary">Cached</div><div class=text-success-primary>Yes'),De=e.template('<div class="mt-6 rounded-lg border border-border-subtle bg-surface-secondary p-4 text-sm text-text-secondary"><div class="grid grid-cols-2 gap-4 md:grid-cols-4"><div><div class="font-medium text-text-primary">Provider</div><div></div></div><div><div class="font-medium text-text-primary">Model</div><div></div></div><div><div class="font-medium text-text-primary">Execution Time</div><div>ms</div></div><div><div class="font-medium text-text-primary">TTFB</div><div>ms'),Pe=e.template('<div><div class="grid grid-cols-12 gap-4">'),Ae=e.template("<div>"),Ne=e.template('<div class="col-span-12 md:col-span-6 lg:col-span-4"><div class="animate-pulse rounded-lg border border-border-subtle bg-surface-secondary p-4"><div class="mb-4 h-6 w-1/2 rounded bg-surface-tertiary"></div><div class=space-y-3><div class="h-4 rounded bg-surface-tertiary"></div><div class="h-4 w-5/6 rounded bg-surface-tertiary"></div><div class="h-4 w-4/6 rounded bg-surface-tertiary"></div></div><div class="mt-4 h-32 rounded bg-surface-tertiary">');function Me(t){var i;const r=b(t.component);if(!r.valid)return(i=t.onError)==null||i.call(t,{type:"validation",message:"Component validation failed",componentId:t.component.id,details:r.errors}),(()=>{var o=ye(),l=o.firstChild,a=l.nextSibling;return e.insert(a,()=>{var s,c;return((c=(s=r.errors)==null?void 0:s[0])==null?void 0:c.message)||"Unknown validation error"}),o})();const n=t.component.params;return e.createComponent(S,{get componentId(){return t.component.id},get componentType(){return t.component.type},get onError(){return t.onError},allowRetry:!1,get children(){var o=Ce(),l=o.firstChild,a=l.firstChild,s=l.nextSibling,c=s.firstChild,g=c.nextSibling;return g.nextSibling,e.insert(a,()=>t.component.type),e.insert(o,e.createComponent(d.Show,{get when(){return n==null?void 0:n.title},get children(){var m=we();return e.insert(m,()=>n.title),m}}),s),e.insert(o,e.createComponent(d.Show,{get when(){return e.memo(()=>t.component.type==="metric")()&&(n==null?void 0:n.value)},get children(){var m=be(),u=m.firstChild;return e.insert(u,()=>n.value),e.insert(m,e.createComponent(d.Show,{get when(){return n.unit},get children(){var x=_e();return e.insert(x,()=>n.unit),x}}),null),m}}),s),e.insert(s,()=>t.component.id.slice(0,8),g),o}})}function Ue(t){const{components:r,isLoading:n,isStreaming:i,error:o,progress:l,metadata:a,startStreaming:s}=A.useStreamingUI({query:t.query,spaceIds:t.spaceIds,sessionId:t.sessionId,options:t.options,onComplete:t.onComplete,onError:t.onError,onComponentReceived:t.onComponentReceived}),[c,g]=d.createSignal(new Set),m=u=>{g(x=>new Set([...x,u])),setTimeout(()=>{g(x=>{const h=new Set(x);return h.delete(u),h})},500)};return(()=>{var u=Pe(),x=u.firstChild;return e.insert(u,e.createComponent(d.Show,{get when(){return e.memo(()=>t.showProgress!==!1)()&&(n()||i())},get children(){var h=Ie(),v=h.firstChild,$=v.firstChild,y=v.nextSibling,w=y.firstChild;return e.insert($,()=>l().message),e.insert(v,e.createComponent(d.Show,{get when(){return l().totalCount!==null},get children(){var p=Se(),C=p.firstChild;return e.insert(p,()=>l().receivedCount,C),e.insert(p,()=>l().totalCount,null),p}}),null),e.insert(h,e.createComponent(d.Show,{get when(){return e.memo(()=>l().totalCount===null)()&&i()},get children(){return ke()}}),null),e.effect(p=>e.setStyleProperty(w,"width",l().totalCount!==null?`${l().receivedCount/l().totalCount*100}%`:"0%")),h}}),x),e.insert(u,e.createComponent(d.Show,{get when(){return o()},get children(){var h=Ee(),v=h.firstChild,$=v.firstChild,y=$.nextSibling,w=v.nextSibling;return e.insert(y,()=>{var p;return(p=o())==null?void 0:p.error}),e.insert(w,()=>{var p;return(p=o())==null?void 0:p.message}),e.insert(h,e.createComponent(d.Show,{get when(){var p;return(p=o())==null?void 0:p.recoverable},get children(){var p=Re();return p.$$click=()=>s(),p}}),null),h}}),x),e.insert(x,e.createComponent(d.For,{get each(){return r()},children:h=>(()=>{var v=Ae();return e.use(()=>m(h.id),v),e.insert(v,e.createComponent(Me,{component:h,get onError(){return t.onRenderError}})),e.effect($=>{var y=`
2
+ col-span-${h.position.colSpan}
3
+ ${c().has(h.id)?"animate-fade-in-up":""}
4
+ `,w=h.position.colStart,p=h.position.colStart+h.position.colSpan;return y!==$.e&&e.className(v,$.e=y),w!==$.t&&e.setStyleProperty(v,"grid-column-start",$.t=w),p!==$.a&&e.setStyleProperty(v,"grid-column-end",$.a=p),$},{e:void 0,t:void 0,a:void 0}),v})()}),null),e.insert(x,e.createComponent(d.Show,{get when(){return e.memo(()=>!!i())()&&l().totalCount!==null},get children(){return e.createComponent(d.For,{get each(){return Array.from({length:l().totalCount-l().receivedCount})},children:()=>e.createComponent(Oe,{})})}}),null),e.insert(u,e.createComponent(d.Show,{get when(){return e.memo(()=>t.showMetadata!==!1)()&&a()},get children(){var h=De(),v=h.firstChild,$=v.firstChild,y=$.firstChild,w=y.nextSibling,p=$.nextSibling,C=p.firstChild,M=C.nextSibling,k=p.nextSibling,U=k.firstChild,I=U.nextSibling,O=I.firstChild,R=k.nextSibling,F=R.firstChild,E=F.nextSibling,G=E.firstChild;return e.insert(w,()=>{var f;return(f=a())==null?void 0:f.provider}),e.insert(M,()=>{var f;return(f=a())==null?void 0:f.model}),e.insert(I,()=>{var f;return(f=a())==null?void 0:f.executionTimeMs},O),e.insert(v,e.createComponent(d.Show,{get when(){var f;return((f=a())==null?void 0:f.costUSD)!==void 0},get children(){var f=Te(),z=f.firstChild,T=z.nextSibling;return T.firstChild,e.insert(T,()=>{var L,D;return(D=(L=a())==null?void 0:L.costUSD)==null?void 0:D.toFixed(4)},null),f}}),R),e.insert(E,()=>{var f;return(f=a())==null?void 0:f.firstTokenMs},G),e.insert(v,e.createComponent(d.Show,{get when(){var f;return(f=a())==null?void 0:f.cached},get children(){return Le()}}),null),h}}),null),e.effect(()=>e.className(u,`streaming-ui-renderer ${t.class||""}`)),u})()}function Oe(){return Ne()}e.delegateEvents(["click"]);exports.DEFAULT_RESOURCE_LIMITS=_;exports.GenerativeUIErrorBoundary=S;exports.StreamingUIRenderer=Ue;exports.UIResourceRenderer=$e;exports.validateComponent=b;exports.validateLayout=q;
5
+ //# sourceMappingURL=StreamingUIRenderer-DQ1WoVV6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingUIRenderer-DQ1WoVV6.cjs","sources":["../src/services/validation.ts","../src/components/GenerativeUIErrorBoundary.tsx","../src/components/UIResourceRenderer.tsx","../src/components/StreamingUIRenderer.tsx"],"sourcesContent":["/**\n * Component Validation Service\n * Phase 0: Resource Limits & Schema Validation\n *\n * Validates LLM-generated components against:\n * - JSON schema\n * - Resource limits (data points, payload size, grid bounds)\n * - Security constraints (domain whitelist, XSS prevention)\n */\n\nimport type {\n UIComponent,\n UILayout,\n ValidationResult,\n ResourceLimits,\n ChartComponentParams,\n TableComponentParams,\n} from '../types'\n\n/**\n * Default resource limits (configurable via env)\n */\nexport const DEFAULT_RESOURCE_LIMITS: ResourceLimits = {\n maxDataPoints: 1000,\n maxTableRows: 100,\n maxPayloadSize: 50 * 1024, // 50KB\n renderTimeout: 5000, // 5 seconds\n}\n\n/**\n * Allowed iframe domains (whitelist)\n * Must match CSP frame-src directive\n */\nconst ALLOWED_IFRAME_DOMAINS = [\n 'quickchart.io',\n 'www.quickchart.io',\n 'deposium.com',\n 'deposium.vip',\n 'localhost',\n]\n\n/**\n * Validate grid position bounds (1-12 columns)\n */\nexport function validateGridPosition(position: UIComponent['position']): ValidationResult {\n const errors: ValidationResult['errors'] = []\n\n if (position.colStart < 1 || position.colStart > 12) {\n errors.push({\n path: 'position.colStart',\n message: 'Column start must be between 1 and 12',\n code: 'INVALID_GRID_COL_START',\n })\n }\n\n if (position.colSpan < 1 || position.colSpan > 12) {\n errors.push({\n path: 'position.colSpan',\n message: 'Column span must be between 1 and 12',\n code: 'INVALID_GRID_COL_SPAN',\n })\n }\n\n if (position.colStart + position.colSpan - 1 > 12) {\n errors.push({\n path: 'position',\n message: 'Column start + span exceeds grid width (12)',\n code: 'GRID_OVERFLOW',\n })\n }\n\n if (position.rowStart !== undefined && position.rowStart < 1) {\n errors.push({\n path: 'position.rowStart',\n message: 'Row start must be >= 1',\n code: 'INVALID_GRID_ROW_START',\n })\n }\n\n if (position.rowSpan !== undefined && position.rowSpan < 1) {\n errors.push({\n path: 'position.rowSpan',\n message: 'Row span must be >= 1',\n code: 'INVALID_GRID_ROW_SPAN',\n })\n }\n\n return {\n valid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n }\n}\n\n/**\n * Validate chart component against resource limits\n */\nexport function validateChartComponent(\n params: ChartComponentParams,\n limits: ResourceLimits = DEFAULT_RESOURCE_LIMITS\n): ValidationResult {\n const errors: ValidationResult['errors'] = []\n\n // Validate data points count\n const totalDataPoints = params.data.datasets.reduce(\n (sum, dataset) => sum + dataset.data.length,\n 0\n )\n\n if (totalDataPoints > limits.maxDataPoints) {\n errors.push({\n path: 'params.data',\n message: `Chart exceeds max data points: ${totalDataPoints} > ${limits.maxDataPoints}`,\n code: 'RESOURCE_LIMIT_EXCEEDED',\n })\n }\n\n // Validate labels match dataset length\n const expectedLength = params.data.labels.length\n for (const [index, dataset] of params.data.datasets.entries()) {\n if (dataset.data.length !== expectedLength) {\n errors.push({\n path: `params.data.datasets[${index}]`,\n message: `Dataset length mismatch: expected ${expectedLength}, got ${dataset.data.length}`,\n code: 'DATA_LENGTH_MISMATCH',\n })\n }\n }\n\n // Validate numeric data\n for (const [index, dataset] of params.data.datasets.entries()) {\n for (const [dataIndex, value] of dataset.data.entries()) {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n errors.push({\n path: `params.data.datasets[${index}].data[${dataIndex}]`,\n message: `Invalid data value: ${value} (must be finite number)`,\n code: 'INVALID_DATA_TYPE',\n })\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n }\n}\n\n/**\n * Validate table component against resource limits\n */\nexport function validateTableComponent(\n params: TableComponentParams,\n limits: ResourceLimits = DEFAULT_RESOURCE_LIMITS\n): ValidationResult {\n const errors: ValidationResult['errors'] = []\n\n // Validate row count\n if (params.rows.length > limits.maxTableRows) {\n errors.push({\n path: 'params.rows',\n message: `Table exceeds max rows: ${params.rows.length} > ${limits.maxTableRows}`,\n code: 'RESOURCE_LIMIT_EXCEEDED',\n })\n }\n\n // Validate columns\n if (params.columns.length === 0) {\n errors.push({\n path: 'params.columns',\n message: 'Table must have at least one column',\n code: 'EMPTY_COLUMNS',\n })\n }\n\n // Validate column keys are unique\n const columnKeys = new Set<string>()\n for (const [index, column] of params.columns.entries()) {\n if (columnKeys.has(column.key)) {\n errors.push({\n path: `params.columns[${index}]`,\n message: `Duplicate column key: ${column.key}`,\n code: 'DUPLICATE_COLUMN_KEY',\n })\n }\n columnKeys.add(column.key)\n }\n\n // Validate rows have valid data for defined columns\n for (const [rowIndex, row] of params.rows.entries()) {\n for (const column of params.columns) {\n if (!(column.key in row)) {\n errors.push({\n path: `params.rows[${rowIndex}]`,\n message: `Missing column key: ${column.key}`,\n code: 'MISSING_COLUMN_DATA',\n })\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n }\n}\n\n/**\n * Validate payload size\n */\nexport function validatePayloadSize(\n component: UIComponent,\n limits: ResourceLimits = DEFAULT_RESOURCE_LIMITS\n): ValidationResult {\n const payloadSize = JSON.stringify(component).length\n\n if (payloadSize > limits.maxPayloadSize) {\n return {\n valid: false,\n errors: [\n {\n path: 'component',\n message: `Payload size exceeds limit: ${payloadSize} > ${limits.maxPayloadSize} bytes`,\n code: 'PAYLOAD_TOO_LARGE',\n },\n ],\n }\n }\n\n return { valid: true }\n}\n\n/**\n * Sanitize string to prevent XSS\n * Basic implementation - DOMPurify used at render time\n */\nexport function sanitizeString(input: string): string {\n return input\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/on\\w+=\"[^\"]*\"/gi, '')\n .replace(/javascript:/gi, '')\n}\n\n/**\n * Validate iframe domain against whitelist\n */\nexport function validateIframeDomain(url: string): ValidationResult {\n try {\n const parsedUrl = new URL(url)\n const domain = parsedUrl.hostname\n\n const isAllowed = ALLOWED_IFRAME_DOMAINS.some(\n (allowed) => domain === allowed || domain.endsWith(`.${allowed}`) || allowed === 'localhost'\n )\n\n if (!isAllowed) {\n return {\n valid: false,\n errors: [\n {\n path: 'url',\n message: `Domain not whitelisted: ${domain}`,\n code: 'DOMAIN_NOT_WHITELISTED',\n },\n ],\n }\n }\n\n return { valid: true }\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'url',\n message: 'Invalid URL format',\n code: 'INVALID_URL',\n },\n ],\n }\n }\n}\n\n/**\n * Validate entire component\n */\nexport function validateComponent(\n component: UIComponent,\n limits: ResourceLimits = DEFAULT_RESOURCE_LIMITS\n): ValidationResult {\n const errors: ValidationResult['errors'] = []\n\n // Validate grid position\n const gridResult = validateGridPosition(component.position)\n if (!gridResult.valid) {\n errors.push(...(gridResult.errors || []))\n }\n\n // Validate payload size\n const sizeResult = validatePayloadSize(component, limits)\n if (!sizeResult.valid) {\n errors.push(...(sizeResult.errors || []))\n }\n\n // Type-specific validation\n switch (component.type) {\n case 'chart':\n const chartResult = validateChartComponent(component.params as ChartComponentParams, limits)\n if (!chartResult.valid) {\n errors.push(...(chartResult.errors || []))\n }\n break\n\n case 'table':\n const tableResult = validateTableComponent(component.params as TableComponentParams, limits)\n if (!tableResult.valid) {\n errors.push(...(tableResult.errors || []))\n }\n break\n\n case 'metric':\n // Basic validation for metrics\n const metricParams = component.params as any\n if (!metricParams.title || !metricParams.value) {\n errors.push({\n path: 'params',\n message: 'Metric must have title and value',\n code: 'INVALID_METRIC',\n })\n }\n break\n\n case 'text':\n // Basic validation for text\n const textParams = component.params as any\n if (!textParams.content) {\n errors.push({\n path: 'params',\n message: 'Text component must have content',\n code: 'INVALID_TEXT',\n })\n }\n break\n\n default:\n errors.push({\n path: 'type',\n message: `Unknown component type: ${component.type}`,\n code: 'UNKNOWN_COMPONENT_TYPE',\n })\n }\n\n return {\n valid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n }\n}\n\n/**\n * Validate entire layout\n */\nexport function validateLayout(\n layout: UILayout,\n limits: ResourceLimits = DEFAULT_RESOURCE_LIMITS\n): ValidationResult {\n const errors: ValidationResult['errors'] = []\n\n // Validate component count\n if (layout.components.length === 0) {\n errors.push({\n path: 'components',\n message: 'Layout must have at least one component',\n code: 'EMPTY_LAYOUT',\n })\n }\n\n if (layout.components.length > 12) {\n errors.push({\n path: 'components',\n message: `Layout exceeds max components: ${layout.components.length} > 12`,\n code: 'TOO_MANY_COMPONENTS',\n })\n }\n\n // Validate each component\n for (const [index, component] of layout.components.entries()) {\n const result = validateComponent(component, limits)\n if (!result.valid) {\n errors.push(\n ...(result.errors?.map((error) => ({\n ...error,\n path: `components[${index}].${error.path}`,\n })) || [])\n )\n }\n }\n\n // Validate grid configuration\n if (layout.grid.columns !== 12) {\n errors.push({\n path: 'grid.columns',\n message: 'Grid must have 12 columns (Bootstrap-like)',\n code: 'INVALID_GRID_COLUMNS',\n })\n }\n\n return {\n valid: errors.length === 0,\n errors: errors.length > 0 ? errors : undefined,\n }\n}\n","/**\n * Generative UI Error Boundary with Telemetry\n * Phase 0: Error isolation + structured logging\n *\n * Features:\n * - Component-level error isolation\n * - Structured logging with context\n * - Performance timing\n * - Retry mechanism\n * - User-friendly fallback UI\n */\n\nimport { Component, ErrorBoundary, createSignal, Show } from 'solid-js'\nimport { createLogger } from '../utils/logger'\nimport type { RendererError } from '../types'\n\nconst logger = createLogger('generative-ui')\n\n/**\n * Props for GenerativeUIErrorBoundary\n */\nexport interface GenerativeUIErrorBoundaryProps {\n /**\n * Component identifier for telemetry\n */\n componentId: string\n\n /**\n * Component type for context\n */\n componentType: string\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Allow retry on error\n */\n allowRetry?: boolean\n\n /**\n * Child components to wrap\n */\n children: any\n\n /**\n * Custom fallback UI (optional)\n */\n fallback?: (error: Error, retry?: () => void) => any\n}\n\n/**\n * Default fallback UI for errors\n */\nfunction DefaultErrorFallback(props: {\n error: Error\n componentId: string\n componentType: string\n allowRetry?: boolean\n onRetry?: () => void\n}) {\n return (\n <div class=\"w-full h-full bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-shrink-0\">\n <svg\n class=\"w-5 h-5 text-yellow-600 dark:text-yellow-400\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-yellow-900 dark:text-yellow-100\">\n Component Failed to Render\n </p>\n <p class=\"text-xs text-yellow-700 dark:text-yellow-300 mt-1\">\n Type: {props.componentType} | ID: {props.componentId.slice(0, 8)}...\n </p>\n <Show when={import.meta.env.DEV}>\n <p class=\"text-xs text-yellow-600 dark:text-yellow-400 mt-2 font-mono\">\n {props.error.message}\n </p>\n </Show>\n <Show when={props.allowRetry}>\n <button\n onClick={props.onRetry}\n class=\"mt-3 text-xs font-medium text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 underline\"\n >\n Retry Rendering\n </button>\n </Show>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Generative UI Error Boundary Component\n */\nexport const GenerativeUIErrorBoundary: Component<GenerativeUIErrorBoundaryProps> = (props) => {\n const [retryKey, setRetryKey] = createSignal(0)\n const [renderStartTime] = createSignal(performance.now())\n\n // Handle error with telemetry\n const handleError = (error: Error) => {\n const renderEndTime = performance.now()\n const renderDuration = renderEndTime - renderStartTime()\n\n // Structure error context\n const errorContext = {\n componentId: props.componentId,\n componentType: props.componentType,\n errorMessage: error.message,\n errorStack: error.stack,\n renderDuration,\n retryCount: retryKey(),\n timestamp: new Date().toISOString(),\n userAgent: navigator.userAgent,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n }\n\n // Log to structured logger\n logger.error(`Component render failed: ${props.componentType}`, errorContext)\n\n // Call error callback\n props.onError?.({\n type: 'render',\n message: error.message,\n componentId: props.componentId,\n details: errorContext,\n })\n\n // In production, send to monitoring service\n if (import.meta.env.PROD) {\n // Future: Send to Sentry or other APM\n // Sentry.captureException(error, { contexts: { component: errorContext } })\n }\n }\n\n // Retry mechanism\n const handleRetry = () => {\n const newRetryCount = retryKey() + 1\n logger.info(`Retrying component render: ${props.componentType}`, {\n componentId: props.componentId,\n retryCount: newRetryCount,\n })\n setRetryKey(newRetryCount)\n }\n\n return (\n <ErrorBoundary\n fallback={(error) => {\n handleError(error)\n\n // Use custom fallback if provided\n if (props.fallback) {\n return props.fallback(error, props.allowRetry ? handleRetry : undefined)\n }\n\n // Default fallback\n return (\n <DefaultErrorFallback\n error={error}\n componentId={props.componentId}\n componentType={props.componentType}\n allowRetry={props.allowRetry}\n onRetry={handleRetry}\n />\n )\n }}\n >\n {/* Key prop for forcing remount on retry */}\n {(() => {\n const _ = retryKey() // Access signal to track changes\n return <>{props.children}</>\n })()}\n </ErrorBoundary>\n )\n}\n\n/**\n * Performance monitoring wrapper\n * Logs render times for performance analysis\n */\nexport function withPerformanceMonitoring<P extends { componentId: string; componentType: string }>(\n WrappedComponent: Component<P>\n) {\n return (props: P) => {\n const renderStart = performance.now()\n\n // Log render start\n logger.debug(`Component render start: ${props.componentType}`, {\n componentId: props.componentId,\n timestamp: new Date().toISOString(),\n })\n\n // Measure on mount completion\n if (typeof window !== 'undefined') {\n requestAnimationFrame(() => {\n const renderEnd = performance.now()\n const duration = renderEnd - renderStart\n\n logger.info(`Component rendered: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n timestamp: new Date().toISOString(),\n })\n\n // Warn if render is slow (>50ms target)\n if (duration > 50) {\n logger.warn(`Slow component render: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n threshold: 50,\n })\n }\n })\n }\n\n return <WrappedComponent {...props} />\n }\n}\n\n/**\n * Hook to track component lifecycle events\n */\nexport function useComponentTelemetry(componentId: string, componentType: string) {\n const mountTime = performance.now()\n\n // Log mount\n logger.debug(`Component mounted: ${componentType}`, {\n componentId,\n timestamp: new Date().toISOString(),\n })\n\n // Return cleanup function for unmount\n return () => {\n const lifetime = performance.now() - mountTime\n logger.debug(`Component unmounted: ${componentType}`, {\n componentId,\n lifetime,\n timestamp: new Date().toISOString(),\n })\n }\n}\n","/**\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 } from 'solid-js'\nimport type { UIComponent, UILayout, RendererError, ComponentType } from '../types'\nimport { validateComponent, DEFAULT_RESOURCE_LIMITS } from '../services/validation'\nimport { GenerativeUIErrorBoundary } from './GenerativeUIErrorBoundary'\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 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={textParams.content} // Note: Should be sanitized at generation time\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 // Convert single component to layout\n if ('type' in props.content) {\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 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 return (\n <div class={`w-full ${props.class || ''}`}>\n <div\n class=\"grid gap-4\"\n style={{\n 'grid-template-columns': `repeat(${layout().grid.columns}, 1fr)`,\n gap: layout().grid.gap,\n }}\n >\n <For each={layout().components}>\n {(component) => (\n <div style={getGridStyles(component)}>\n <ComponentRenderer component={component} onError={props.onError} />\n </div>\n )}\n </For>\n </div>\n </div>\n )\n}\n","/**\n * StreamingUIRenderer Component - Phase 2\n *\n * Renders streaming dashboard components with skeleton states and progress indicators.\n * Uses the useStreamingUI hook for SSE connection and state management.\n *\n * Features:\n * - Skeleton loading states while components stream\n * - Progress bar and status messages\n * - Smooth component animations on arrival\n * - Error handling with retry capability\n * - Responsive 12-column grid layout\n *\n * Usage:\n * ```tsx\n * <StreamingUIRenderer\n * query=\"Show me revenue trends\"\n * spaceIds={['uuid1', 'uuid2']}\n * onComplete={(metadata) => console.log('Done!', metadata)}\n * />\n * ```\n */\n\nimport { Show, For, createSignal } from 'solid-js'\nimport { useStreamingUI, type UseStreamingUIOptions } from '../hooks/useStreamingUI'\nimport type { UIComponent, RendererError } from '../types'\nimport { validateComponent } from '../services/validation'\nimport { GenerativeUIErrorBoundary } from './GenerativeUIErrorBoundary'\n\nexport interface StreamingUIRendererProps extends UseStreamingUIOptions {\n class?: string\n showProgress?: boolean\n showMetadata?: boolean\n onRenderError?: (error: RendererError) => void\n}\n\n/**\n * Component Renderer - Inline lightweight version\n * (Full implementation in UIResourceRenderer)\n */\nfunction StreamingComponentRenderer(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 bg-error-subtle border border-border-error rounded-lg p-4\">\n <p class=\"text-sm font-medium text-error-primary\">Validation Error</p>\n <p class=\"text-xs text-text-secondary mt-1\">\n {validation.errors?.[0]?.message || 'Unknown validation error'}\n </p>\n </div>\n )\n }\n\n // Simplified renderer - just show component type and title\n // Full rendering logic in UIResourceRenderer\n const params = props.component.params as any\n\n return (\n <GenerativeUIErrorBoundary\n componentId={props.component.id}\n componentType={props.component.type}\n onError={props.onError}\n allowRetry={false}\n >\n <div class=\"w-full bg-surface-secondary border border-border-subtle rounded-lg p-4\">\n <div class=\"flex items-center gap-2 mb-2\">\n <span class=\"text-xs font-medium text-text-tertiary uppercase\">\n {props.component.type}\n </span>\n </div>\n <Show when={params?.title}>\n <h3 class=\"text-sm font-semibold text-text-primary\">{params.title}</h3>\n </Show>\n <Show when={props.component.type === 'metric' && params?.value}>\n <div class=\"mt-2\">\n <p class=\"text-2xl font-semibold text-text-primary\">{params.value}</p>\n <Show when={params.unit}>\n <span class=\"text-sm text-text-secondary\">{params.unit}</span>\n </Show>\n </div>\n </Show>\n <div class=\"mt-3 text-xs text-text-tertiary\">\n Component ID: {props.component.id.slice(0, 8)}...\n </div>\n </div>\n </GenerativeUIErrorBoundary>\n )\n}\n\nexport function StreamingUIRenderer(props: StreamingUIRendererProps) {\n const { components, isLoading, isStreaming, error, progress, metadata, startStreaming } =\n useStreamingUI({\n query: props.query,\n spaceIds: props.spaceIds,\n sessionId: props.sessionId,\n options: props.options,\n onComplete: props.onComplete,\n onError: props.onError,\n onComponentReceived: props.onComponentReceived,\n })\n\n const [animatingComponents, setAnimatingComponents] = createSignal<Set<string>>(new Set())\n\n // Track new components for animation\n const handleComponentRender = (componentId: string) => {\n setAnimatingComponents((prev) => new Set([...prev, componentId]))\n\n // Remove from animating set after animation completes\n setTimeout(() => {\n setAnimatingComponents((prev) => {\n const next = new Set(prev)\n next.delete(componentId)\n return next\n })\n }, 500)\n }\n\n return (\n <div class={`streaming-ui-renderer ${props.class || ''}`}>\n {/* Progress Bar */}\n <Show when={props.showProgress !== false && (isLoading() || isStreaming())}>\n <div class=\"mb-4 rounded-lg border border-border-subtle bg-surface-secondary p-4\">\n {/* Status Message */}\n <div class=\"mb-2 flex items-center justify-between\">\n <span class=\"text-sm font-medium text-text-primary\">{progress().message}</span>\n <Show when={progress().totalCount !== null}>\n <span class=\"text-sm text-text-secondary\">\n {progress().receivedCount} / {progress().totalCount}\n </span>\n </Show>\n </div>\n\n {/* Progress Bar */}\n <div class=\"h-2 w-full overflow-hidden rounded-full bg-surface-tertiary\">\n <div\n class=\"h-full bg-brand-primary transition-all duration-300 ease-out\"\n style={{\n width:\n progress().totalCount !== null\n ? `${(progress().receivedCount / progress().totalCount!) * 100}%`\n : '0%',\n }}\n />\n </div>\n\n {/* Indeterminate Progress (when totalCount unknown) */}\n <Show when={progress().totalCount === null && isStreaming()}>\n <div class=\"mt-2\">\n <div class=\"h-1 w-full overflow-hidden rounded-full bg-surface-tertiary\">\n <div class=\"animate-progress-indeterminate h-full w-1/3 bg-brand-primary\" />\n </div>\n </div>\n </Show>\n </div>\n </Show>\n\n {/* Error State */}\n <Show when={error()}>\n <div class=\"mb-4 rounded-lg border border-border-error bg-error-subtle p-4\">\n <div class=\"mb-2 flex items-center gap-2\">\n <svg\n class=\"h-5 w-5 text-error-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span class=\"font-medium text-error-primary\">{error()?.error}</span>\n </div>\n <p class=\"text-sm text-text-secondary\">{error()?.message}</p>\n\n {/* Retry Button (if recoverable) */}\n <Show when={error()?.recoverable}>\n <button\n type=\"button\"\n class=\"mt-3 rounded-md bg-error-primary px-3 py-1.5 text-sm font-medium text-white hover:bg-error-hover\"\n onClick={() => startStreaming()}\n >\n Retry\n </button>\n </Show>\n </div>\n </Show>\n\n {/* Components Grid */}\n <div class=\"grid grid-cols-12 gap-4\">\n {/* Render received components */}\n <For each={components()}>\n {(component) => (\n <div\n ref={() => handleComponentRender(component.id)}\n class={`\n col-span-${component.position.colSpan}\n ${animatingComponents().has(component.id) ? 'animate-fade-in-up' : ''}\n `}\n style={{\n 'grid-column-start': component.position.colStart,\n 'grid-column-end': component.position.colStart + component.position.colSpan,\n }}\n >\n <StreamingComponentRenderer component={component} onError={props.onRenderError} />\n </div>\n )}\n </For>\n\n {/* Skeleton placeholders (if streaming and expecting more) */}\n <Show when={isStreaming() && progress().totalCount !== null}>\n <For\n each={Array.from({\n length: progress().totalCount! - progress().receivedCount,\n })}\n >\n {() => <SkeletonComponent />}\n </For>\n </Show>\n </div>\n\n {/* Metadata Display */}\n <Show when={props.showMetadata !== false && metadata()}>\n <div class=\"mt-6 rounded-lg border border-border-subtle bg-surface-secondary p-4 text-sm text-text-secondary\">\n <div class=\"grid grid-cols-2 gap-4 md:grid-cols-4\">\n <div>\n <div class=\"font-medium text-text-primary\">Provider</div>\n <div>{metadata()?.provider}</div>\n </div>\n <div>\n <div class=\"font-medium text-text-primary\">Model</div>\n <div>{metadata()?.model}</div>\n </div>\n <div>\n <div class=\"font-medium text-text-primary\">Execution Time</div>\n <div>{metadata()?.executionTimeMs}ms</div>\n </div>\n <Show when={metadata()?.costUSD !== undefined}>\n <div>\n <div class=\"font-medium text-text-primary\">Cost</div>\n <div>${metadata()?.costUSD?.toFixed(4)}</div>\n </div>\n </Show>\n <div>\n <div class=\"font-medium text-text-primary\">TTFB</div>\n <div>{metadata()?.firstTokenMs}ms</div>\n </div>\n <Show when={metadata()?.cached}>\n <div>\n <div class=\"font-medium text-text-primary\">Cached</div>\n <div class=\"text-success-primary\">Yes</div>\n </div>\n </Show>\n </div>\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Skeleton Component - Placeholder while components load\n */\nfunction SkeletonComponent() {\n return (\n <div class=\"col-span-12 md:col-span-6 lg:col-span-4\">\n <div class=\"animate-pulse rounded-lg border border-border-subtle bg-surface-secondary p-4\">\n {/* Header skeleton */}\n <div class=\"mb-4 h-6 w-1/2 rounded bg-surface-tertiary\" />\n\n {/* Content skeleton */}\n <div class=\"space-y-3\">\n <div class=\"h-4 rounded bg-surface-tertiary\" />\n <div class=\"h-4 w-5/6 rounded bg-surface-tertiary\" />\n <div class=\"h-4 w-4/6 rounded bg-surface-tertiary\" />\n </div>\n\n {/* Chart/visual skeleton */}\n <div class=\"mt-4 h-32 rounded bg-surface-tertiary\" />\n </div>\n </div>\n )\n}\n\n// CSS Animations (add to global styles or Tailwind config)\n/*\n@keyframes fade-in-up {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes progress-indeterminate {\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(400%);\n }\n}\n\n.animate-fade-in-up {\n animation: fade-in-up 0.5s ease-out;\n}\n\n.animate-progress-indeterminate {\n animation: progress-indeterminate 1.5s infinite ease-in-out;\n}\n*/\n"],"names":["DEFAULT_RESOURCE_LIMITS","validateGridPosition","position","errors","validateChartComponent","params","limits","totalDataPoints","sum","dataset","expectedLength","index","dataIndex","value","validateTableComponent","columnKeys","column","rowIndex","row","validatePayloadSize","component","payloadSize","validateComponent","gridResult","sizeResult","chartResult","tableResult","metricParams","validateLayout","layout","result","_a","error","logger","createLogger","DefaultErrorFallback","props","_el$","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$7","_el$0","_el$8","_el$1","_$insert","componentType","componentId","slice","_$createComponent","Show","when","import","children","_el$10","_tmpl$","message","allowRetry","_el$11","_tmpl$2","_$addEventListener","onRetry","GenerativeUIErrorBoundary","retryKey","setRetryKey","createSignal","renderStartTime","performance","now","handleError","renderDuration","errorContext","errorMessage","errorStack","stack","retryCount","timestamp","Date","toISOString","userAgent","navigator","viewport","width","window","innerWidth","height","innerHeight","onError","type","details","handleRetry","newRetryCount","info","ErrorBoundary","fallback","undefined","_$memo","_$delegateEvents","ChartRenderer","iframeUrl","setIframeUrl","isLoading","setIsLoading","setError","onMount","chartParams","chartConfig","data","options","responsive","maintainAspectRatio","url","encodeURIComponent","JSON","stringify","_tmpl$5","_tmpl$4","_el$9","title","addEventListener","id","_$effect","_$setAttribute","TableRenderer","tableParams","_tmpl$7","_el$12","_el$13","_el$14","_el$15","_el$16","For","each","columns","_el$26","_tmpl$8","label","_$p","_$style","rows","maxTableRows","_el$27","_tmpl$9","_el$28","_tmpl$0","key","pagination","_el$17","_tmpl$6","_el$18","_el$19","_el$24","_el$20","_el$25","currentPage","pageSize","Math","min","totalRows","MetricRenderer","_el$29","_tmpl$12","_el$30","_el$31","_el$32","_el$33","_el$34","unit","_el$35","_tmpl$1","trend","_el$36","_tmpl$10","_el$37","_el$38","_el$40","_c$","direction","abs","_$className","subtitle","_el$41","_tmpl$11","TextRenderer","textParams","_el$42","_tmpl$13","_el$43","_p$","_v$","className","_v$2","content","e","t","innerHTML","ComponentRenderer","validation","valid","_el$44","_tmpl$14","_el$45","_el$46","UIResourceRenderer","components","grid","gap","getGridStyles","colStart","colSpan","rowStart","rowSpan","_el$47","_tmpl$15","_el$48","_el$49","_tmpl$16","_v$3","class","_v$4","_v$5","_$setStyleProperty","a","StreamingComponentRenderer","StreamingUIRenderer","isStreaming","progress","metadata","startStreaming","useStreamingUI","query","spaceIds","sessionId","onComplete","onComponentReceived","animatingComponents","setAnimatingComponents","Set","handleComponentRender","prev","setTimeout","next","delete","showProgress","totalCount","receivedCount","_el$22","_el$23","recoverable","$$click","_el$50","_$use","onRenderError","has","Array","from","length","SkeletonComponent","showMetadata","_el$39","provider","model","executionTimeMs","costUSD","toFixed","firstTokenMs","cached"],"mappings":"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"}