@davincidreams/dynamic-canvas-react 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +261 -297
  2. package/dist/RendererFrame-ri9awAzI.cjs +1 -0
  3. package/dist/RendererFrame-w1obQvoH.js +25 -0
  4. package/dist/core/CanvasContainer.d.ts +23 -0
  5. package/dist/core/CanvasContainer.d.ts.map +1 -0
  6. package/dist/core/CanvasContext.d.ts +45 -0
  7. package/dist/core/CanvasContext.d.ts.map +1 -0
  8. package/dist/core/ComponentRegistry.d.ts +36 -0
  9. package/dist/core/ComponentRegistry.d.ts.map +1 -0
  10. package/dist/core/ErrorBoundary.d.ts +18 -0
  11. package/dist/core/ErrorBoundary.d.ts.map +1 -0
  12. package/dist/core/RendererResolver.d.ts +14 -0
  13. package/dist/core/RendererResolver.d.ts.map +1 -0
  14. package/dist/core/StreamProcessor.d.ts +34 -0
  15. package/dist/core/StreamProcessor.d.ts.map +1 -0
  16. package/dist/core/SurfaceManager.d.ts +36 -0
  17. package/dist/core/SurfaceManager.d.ts.map +1 -0
  18. package/dist/hooks/useA2UISurface.d.ts +41 -0
  19. package/dist/hooks/useA2UISurface.d.ts.map +1 -0
  20. package/dist/hooks/useStreamingContent.d.ts +17 -0
  21. package/dist/hooks/useStreamingContent.d.ts.map +1 -0
  22. package/dist/index.cjs +38 -0
  23. package/dist/index.d.ts +28 -302
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +1096 -0
  26. package/dist/renderers/ArtifactRenderer.d.ts +6 -0
  27. package/dist/renderers/ArtifactRenderer.d.ts.map +1 -0
  28. package/dist/renderers/ArtifactRenderer.test.d.ts +2 -0
  29. package/dist/renderers/ArtifactRenderer.test.d.ts.map +1 -0
  30. package/dist/renderers/ChartRenderer.d.ts +20 -0
  31. package/dist/renderers/ChartRenderer.d.ts.map +1 -0
  32. package/dist/renderers/CodeRenderer.d.ts +16 -0
  33. package/dist/renderers/CodeRenderer.d.ts.map +1 -0
  34. package/dist/renderers/CustomRenderer.d.ts +14 -0
  35. package/dist/renderers/CustomRenderer.d.ts.map +1 -0
  36. package/dist/renderers/DocumentRenderer.d.ts +15 -0
  37. package/dist/renderers/DocumentRenderer.d.ts.map +1 -0
  38. package/dist/renderers/KnowledgeGraphRenderer.d.ts +6 -0
  39. package/dist/renderers/KnowledgeGraphRenderer.d.ts.map +1 -0
  40. package/dist/renderers/MapRenderer.d.ts +6 -0
  41. package/dist/renderers/MapRenderer.d.ts.map +1 -0
  42. package/dist/renderers/MediaRenderer.d.ts +6 -0
  43. package/dist/renderers/MediaRenderer.d.ts.map +1 -0
  44. package/dist/renderers/MediaRenderer.test.d.ts +2 -0
  45. package/dist/renderers/MediaRenderer.test.d.ts.map +1 -0
  46. package/dist/renderers/TimelineRenderer.d.ts +16 -0
  47. package/dist/renderers/TimelineRenderer.d.ts.map +1 -0
  48. package/dist/renderers/artifact.cjs +2 -0
  49. package/dist/renderers/artifact.js +35 -0
  50. package/dist/renderers/chart.cjs +1 -0
  51. package/dist/renderers/chart.js +121 -0
  52. package/dist/renderers/code.cjs +2 -0
  53. package/dist/renderers/code.js +100 -0
  54. package/dist/renderers/document.cjs +1 -0
  55. package/dist/renderers/document.js +46 -0
  56. package/dist/renderers/index.d.ts +15 -0
  57. package/dist/renderers/index.d.ts.map +1 -0
  58. package/dist/renderers/knowledge-graph.cjs +1 -0
  59. package/dist/renderers/knowledge-graph.js +120 -0
  60. package/dist/renderers/map.cjs +1 -0
  61. package/dist/renderers/map.js +56 -0
  62. package/dist/renderers/media.cjs +1 -0
  63. package/dist/renderers/media.js +71 -0
  64. package/dist/renderers/shared/LazyWrapper.d.ts +9 -0
  65. package/dist/renderers/shared/LazyWrapper.d.ts.map +1 -0
  66. package/dist/renderers/shared/RendererFrame.d.ts +10 -0
  67. package/dist/renderers/shared/RendererFrame.d.ts.map +1 -0
  68. package/dist/renderers/timeline.cjs +1 -0
  69. package/dist/renderers/timeline.js +105 -0
  70. package/dist/schema/a2ui-envelope.d.ts +60 -0
  71. package/dist/schema/a2ui-envelope.d.ts.map +1 -0
  72. package/dist/schema/catalog-definition.d.ts +25 -0
  73. package/dist/schema/catalog-definition.d.ts.map +1 -0
  74. package/dist/schema/component-types.d.ts +28 -0
  75. package/dist/schema/component-types.d.ts.map +1 -0
  76. package/dist/schema/components/artifact.d.ts +18 -0
  77. package/dist/schema/components/artifact.d.ts.map +1 -0
  78. package/dist/schema/components/chart.d.ts +33 -0
  79. package/dist/schema/components/chart.d.ts.map +1 -0
  80. package/dist/schema/components/code.d.ts +15 -0
  81. package/dist/schema/components/code.d.ts.map +1 -0
  82. package/dist/schema/components/custom.d.ts +13 -0
  83. package/dist/schema/components/custom.d.ts.map +1 -0
  84. package/dist/schema/components/document.d.ts +13 -0
  85. package/dist/schema/components/document.d.ts.map +1 -0
  86. package/dist/schema/components/knowledge-graph.d.ts +35 -0
  87. package/dist/schema/components/knowledge-graph.d.ts.map +1 -0
  88. package/dist/schema/components/map.d.ts +35 -0
  89. package/dist/schema/components/map.d.ts.map +1 -0
  90. package/dist/schema/components/media.d.ts +20 -0
  91. package/dist/schema/components/media.d.ts.map +1 -0
  92. package/dist/schema/components/timeline.d.ts +28 -0
  93. package/dist/schema/components/timeline.d.ts.map +1 -0
  94. package/dist/schema/index.d.ts +12 -0
  95. package/dist/schema/index.d.ts.map +1 -0
  96. package/dist/schema/validation.d.ts +15 -0
  97. package/dist/schema/validation.d.ts.map +1 -0
  98. package/dist/schema.cjs +1 -0
  99. package/dist/schema.d.ts +7 -0
  100. package/dist/schema.d.ts.map +1 -0
  101. package/dist/schema.js +194 -0
  102. package/dist/themes/darkTheme.d.ts +3 -0
  103. package/dist/themes/darkTheme.d.ts.map +1 -0
  104. package/dist/themes/defaultTheme.d.ts +3 -0
  105. package/dist/themes/defaultTheme.d.ts.map +1 -0
  106. package/dist/themes/index.d.ts +9 -0
  107. package/dist/themes/index.d.ts.map +1 -0
  108. package/dist/themes/lightTheme.d.ts +3 -0
  109. package/dist/themes/lightTheme.d.ts.map +1 -0
  110. package/dist/themes/types.d.ts +8 -0
  111. package/dist/themes/types.d.ts.map +1 -0
  112. package/dist/types/index.d.ts +164 -0
  113. package/dist/types/index.d.ts.map +1 -0
  114. package/dist/utils/contentAnalyzer.d.ts +46 -0
  115. package/dist/utils/contentAnalyzer.d.ts.map +1 -0
  116. package/dist/utils/jsonPointer.d.ts +15 -0
  117. package/dist/utils/jsonPointer.d.ts.map +1 -0
  118. package/dist/utils/streaming.d.ts +10 -0
  119. package/dist/utils/streaming.d.ts.map +1 -0
  120. package/package.json +97 -15
  121. package/dist/dynamic-canvas.cjs.js +0 -65
  122. package/dist/dynamic-canvas.es.js +0 -966
  123. package/dist/dynamic-canvas.umd.js +0 -65
package/README.md CHANGED
@@ -1,399 +1,363 @@
1
- # @dynamic-canvas/react
1
+ # @davincidreams/dynamic-canvas-react
2
2
 
3
- A modular, reusable dynamic canvas component for React that renders conversation-driven visuals alongside 3D avatars in chat applications.
3
+ A2UI-native dynamic canvas component for React. Renders streaming, agent-driven visuals from any A2UI-speaking source LangChain agents, 3dchat, Microsoft Agent Framework (Orleans), or direct JSON.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Multiple Content Types**: Support for charts, timelines, code, documents, and custom components
8
- - **Theme System**: Built-in light/dark themes with full customization options
9
- - **Content Analysis**: Automatic content type detection from text
10
- - **Extensible**: Easy to add new renderers and themes
11
- - **Type Safe**: Full TypeScript support
12
- - **Responsive**: Works on all screen sizes
7
+ - **A2UI Protocol**: Native support for the Agent-to-UI message protocol (createSurface, updateDataModel, updateComponents, etc.)
8
+ - **9 Renderers**: Chart, Timeline, KnowledgeGraph, Map, Media, Document, Code, Artifact, Custom
9
+ - **Streaming**: JSONL, SSE, WebSocket, and direct message ingestion with batched updates
10
+ - **Lazy Loading**: Heavy renderers (D3, Cesium, shiki) loaded on demand with SVG fallbacks
11
+ - **Schema-Only Export**: Zero-React-dependency `./schema` entry point for server-side / non-JS consumers
12
+ - **Multi-Entry Build**: Tree-shake individual renderers via `./renderers/chart`, `./renderers/map`, etc.
13
+ - **Theme System**: Built-in light/dark themes with full customization
14
+ - **Type Safe**: Full TypeScript support with discriminated union component types
15
+ - **Backward Compatible**: Legacy `CanvasProvider`, `useCanvas`, `useCanvasContent` hooks still work
13
16
 
14
17
  ## Installation
15
18
 
16
19
  ```bash
17
- npm install @dynamic-canvas/react
18
- # or
19
- yarn add @dynamic-canvas/react
20
- # or
21
- pnpm add @dynamic-canvas/react
20
+ npm install @davincidreams/dynamic-canvas-react
22
21
  ```
23
22
 
24
- ## Quick Start
23
+ ### Optional Peer Dependencies
25
24
 
26
- ```tsx
27
- import { CanvasProvider, useCanvas, themes } from '@dynamic-canvas/react';
25
+ Install only the renderers you need:
28
26
 
29
- function App() {
30
- const { content, setContent } = useCanvas();
27
+ ```bash
28
+ # Charts (D3)
29
+ npm install d3
31
30
 
32
- return (
33
- <CanvasProvider theme={themes.dark}>
34
- <div className="flex h-screen">
35
- <div className="w-3/4">
36
- {/* Your main app content */}
37
- </div>
38
- <CanvasContainer theme={themes.dark}>
39
- {content && (
40
- <ContentRenderer content={content} theme={themes.dark} />
41
- )}
42
- </CanvasContainer>
43
- </div>
44
- </CanvasProvider>
45
- );
46
- }
31
+ # Documents (Markdown)
32
+ npm install react-markdown remark-gfm
33
+
34
+ # Code (syntax highlighting)
35
+ npm install shiki
36
+
37
+ # Knowledge Graph (force-directed)
38
+ npm install react-force-graph-2d
39
+ # or for 3D:
40
+ npm install react-force-graph-3d
41
+
42
+ # Map (Cesium globe)
43
+ npm install @cesium/engine resium
47
44
  ```
48
45
 
49
- ## Usage
46
+ All renderers include built-in SVG/HTML fallbacks when their optional deps are not installed.
50
47
 
51
- ### Basic Usage
48
+ ## Quick Start
49
+
50
+ ### A2UI Messages (recommended)
51
+
52
+ Feed A2UI JSON messages from your AI agent and the canvas renders automatically:
52
53
 
53
54
  ```tsx
54
- import { CanvasProvider, useCanvas, themes, ChartRenderer } from '@dynamic-canvas/react';
55
+ import { useA2UISurface, RendererResolver } from '@davincidreams/dynamic-canvas-react';
55
56
 
56
- function App() {
57
- const { content, setContent } = useCanvas();
57
+ function AgentCanvas() {
58
+ const { activeSurface, getComponents, resolveData, store } = useA2UISurface({
59
+ sseUrl: '/api/agent/stream',
60
+ });
58
61
 
59
- const handleResponse = (response: string) => {
60
- const analyzed = ContentAnalyzer.analyze(response);
61
- setContent(analyzed);
62
- };
62
+ if (!activeSurface) return <div>Waiting for agent...</div>;
63
63
 
64
64
  return (
65
- <CanvasProvider theme={themes.dark}>
66
- <div className="flex h-screen">
67
- <div className="w-3/4">
68
- {/* Chat interface */}
69
- </div>
70
- <div className="w-1/3">
71
- {content && (
72
- <ChartRenderer content={content} theme={themes.dark} />
73
- )}
74
- </div>
75
- </div>
76
- </CanvasProvider>
65
+ <div>
66
+ {getComponents(activeSurface.id).map((component) => (
67
+ <RendererResolver
68
+ key={component.id}
69
+ component={component}
70
+ data={resolveData(activeSurface.id, '/')}
71
+ theme="dark"
72
+ />
73
+ ))}
74
+ </div>
77
75
  );
78
76
  }
79
77
  ```
80
78
 
81
- ### Chart Content
79
+ ### Direct Messages
80
+
81
+ Process A2UI messages directly without a stream:
82
82
 
83
83
  ```tsx
84
- const chartContent = {
85
- type: 'chart',
86
- chartType: 'bar',
87
- data: {
88
- labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
89
- values: [10, 25, 18, 30, 22]
84
+ import { useA2UISurface } from '@davincidreams/dynamic-canvas-react';
85
+
86
+ const messages = [
87
+ { createSurface: { surfaceId: 's1' } },
88
+ {
89
+ updateDataModel: {
90
+ surfaceId: 's1',
91
+ path: '/chart',
92
+ value: { labels: ['Jan', 'Feb', 'Mar'], values: [10, 25, 18] },
93
+ },
90
94
  },
91
- options: {
92
- colors: ['#0ea5e9', '#6366f1', '#8b5cf6', '#ec4899', '#f43f5e']
93
- }
94
- };
95
+ {
96
+ updateComponents: {
97
+ surfaceId: 's1',
98
+ components: [
99
+ {
100
+ id: 'c1',
101
+ component: 'Chart',
102
+ chartType: 'bar',
103
+ data: '/chart',
104
+ },
105
+ ],
106
+ },
107
+ },
108
+ ];
95
109
 
96
- setContent(chartContent);
110
+ function App() {
111
+ const { activeSurface, getComponents } = useA2UISurface({ messages });
112
+ // ...render components
113
+ }
97
114
  ```
98
115
 
99
- ### Timeline Content
116
+ ### WebSocket / Fetch Stream
100
117
 
101
118
  ```tsx
102
- const timelineContent = {
103
- type: 'timeline',
104
- events: [
105
- {
106
- date: '2024-01-15',
107
- title: 'Project Started',
108
- description: 'Initial planning and requirements gathering'
109
- },
110
- {
111
- date: '2024-02-01',
112
- title: 'Development Phase',
113
- description: 'Core features implementation'
114
- }
115
- ]
116
- };
119
+ // WebSocket
120
+ const result = useA2UISurface({ wsUrl: 'wss://agent.example.com/stream' });
121
+
122
+ // Fetch (JSONL body)
123
+ const result = useA2UISurface({
124
+ streamUrl: '/api/agent/generate',
125
+ streamInit: { method: 'POST', body: JSON.stringify({ prompt: '...' }) },
126
+ });
117
127
  ```
118
128
 
119
- ### Code Content
129
+ ### Legacy API
120
130
 
121
- ```tsx
122
- const codeContent = {
123
- type: 'code',
124
- code: 'console.log("Hello, World!");',
125
- language: 'javascript',
126
- filename: 'app.js'
127
- };
128
- ```
129
-
130
- ### Document Content
131
+ The original `CanvasProvider` / `useCanvas` API still works:
131
132
 
132
133
  ```tsx
133
- const documentContent = {
134
- type: 'document',
135
- content: '# Welcome\n\nThis is a document rendered in the canvas.',
136
- format: 'markdown'
137
- };
138
- ```
139
-
140
- ## API Reference
141
-
142
- ### CanvasProvider
134
+ import { CanvasProvider, useCanvas, themes } from '@davincidreams/dynamic-canvas-react';
143
135
 
144
- Provides context for the canvas component.
136
+ function App() {
137
+ return (
138
+ <CanvasProvider initialTheme={themes.dark}>
139
+ <MyApp />
140
+ </CanvasProvider>
141
+ );
142
+ }
145
143
 
146
- ```tsx
147
- <CanvasProvider
148
- initialTheme={themes.dark}
149
- initialThemeMode="dark"
150
- initialContent={initialContent}
151
- >
152
- {children}
153
- </CanvasProvider>
144
+ function MyApp() {
145
+ const { content, setContent } = useCanvas();
146
+ // ...
147
+ }
154
148
  ```
155
149
 
156
- **Props:**
157
- - `initialTheme`: Initial theme object (default: `defaultTheme`)
158
- - `initialThemeMode`: Initial theme mode ('light' | 'dark' | 'system')
159
- - `initialContent`: Initial canvas content
160
-
161
- ### useCanvas
150
+ ## A2UI Protocol
151
+
152
+ The library speaks the A2UI (Agent-to-UI) protocol. Agents send JSON messages to create surfaces, populate data models, and attach components:
153
+
154
+ ### Envelope Messages
155
+
156
+ | Message | Description |
157
+ |---------|-------------|
158
+ | `createSurface` | Create a new UI surface (canvas) |
159
+ | `destroySurface` | Remove a surface |
160
+ | `updateDataModel` | Set data at a JSON Pointer path |
161
+ | `updateComponents` | Set or replace components on a surface |
162
+ | `removeComponents` | Remove components by ID |
163
+ | `appendData` | Append items to an array (streaming convenience) |
164
+ | `patchDataModel` | JSON merge-patch the data model |
165
+
166
+ ### Component Types
167
+
168
+ | Component | Description | Optional Dep |
169
+ |-----------|-------------|-------------|
170
+ | `Chart` | Bar, line, scatter, pie, area, donut charts | `d3` |
171
+ | `Timeline` | Events with alternating/grouped layouts | — |
172
+ | `KnowledgeGraph` | Force-directed node-edge graph | `react-force-graph-2d` |
173
+ | `Map` | Globe with markers | `@cesium/engine` + `resium` |
174
+ | `Media` | Image, video, audio | — |
175
+ | `Document` | Markdown/HTML documents | `react-markdown` |
176
+ | `Code` | Syntax-highlighted code blocks | `shiki` |
177
+ | `Artifact` | Sandboxed iframe (HTML/CSS/JS) | — |
178
+ | `Custom` | Registry-key based escape hatch | — |
179
+
180
+ ### Example: Streaming a Chart
181
+
182
+ ```jsonl
183
+ {"createSurface":{"surfaceId":"s1","title":"Sales Dashboard"}}
184
+ {"updateDataModel":{"surfaceId":"s1","path":"/sales","value":{"labels":["Q1","Q2","Q3","Q4"],"values":[120,340,250,410]}}}
185
+ {"updateComponents":{"surfaceId":"s1","components":[{"id":"chart1","component":"Chart","chartType":"bar","data":"/sales","title":"Quarterly Sales"}]}}
186
+ ```
162
187
 
163
- Hook for accessing canvas state.
188
+ ### Example: Streaming a Timeline
164
189
 
165
- ```tsx
166
- const { content, setContent, theme, setTheme } = useCanvas();
190
+ ```jsonl
191
+ {"createSurface":{"surfaceId":"s1"}}
192
+ {"updateDataModel":{"surfaceId":"s1","path":"/events","value":[{"date":"2024-01-15","title":"Project Started","description":"Kickoff meeting"},{"date":"2024-06-01","title":"v1.0 Release","description":"First public release"}]}}
193
+ {"updateComponents":{"surfaceId":"s1","components":[{"id":"t1","component":"Timeline","events":"/events","layout":"alternating"}]}}
167
194
  ```
168
195
 
169
- **Returns:**
170
- - `content`: Current canvas content
171
- - `setContent`: Function to set content
172
- - `theme`: Current theme
173
- - `setTheme`: Function to set theme
196
+ ## Schema-Only Import
174
197
 
175
- ### useCanvasContent
198
+ For server-side validation or non-React consumers (Python, C#, etc.), import types and validation without React:
176
199
 
177
- Hook specifically for content management.
200
+ ```ts
201
+ import {
202
+ validateMessage,
203
+ validateComponent,
204
+ isA2UIMessage,
205
+ DYNAMIC_CANVAS_CATALOG,
206
+ type A2UIMessage,
207
+ type A2UIComponent,
208
+ } from '@davincidreams/dynamic-canvas-react/schema';
178
209
 
179
- ```tsx
180
- const { content, setContent } = useCanvasContent();
210
+ const msg = { createSurface: { surfaceId: 's1' } };
211
+ const result = validateMessage(msg);
212
+ // { valid: true, messageType: 'createSurface' }
181
213
  ```
182
214
 
183
- ### useCanvasLayout
184
-
185
- Hook for layout management.
215
+ ## API Reference
186
216
 
187
- ```tsx
188
- const { layout, widthRatio, setLayout, setWidthRatio } = useCanvasLayout();
189
- ```
217
+ ### Hooks
190
218
 
191
- ### Renderers
219
+ #### `useA2UISurface(options?)`
192
220
 
193
- #### ChartRenderer
221
+ Primary hook — connects to a stream and manages surfaces.
194
222
 
195
- ```tsx
196
- <ChartRenderer
197
- content={chartContent}
198
- theme={themes.dark}
199
- />
223
+ ```ts
224
+ interface UseA2UISurfaceOptions {
225
+ sseUrl?: string; // SSE endpoint
226
+ wsUrl?: string; // WebSocket endpoint
227
+ streamUrl?: string; // Fetch stream URL
228
+ streamInit?: RequestInit; // Fetch init options
229
+ messages?: A2UIMessage[]; // Direct messages
230
+ batchWindow?: number; // Batch window in ms (default: 50)
231
+ onError?: (error: Error) => void;
232
+ store?: StoreApi<SurfaceManagerStore>; // Shared store
233
+ }
200
234
  ```
201
235
 
202
- #### TimelineRenderer
236
+ Returns: `surfaces`, `activeSurface`, `setActiveSurface`, `processMessage`, `processMessages`, `resolveData`, `getComponents`, `store`
203
237
 
204
- ```tsx
205
- <TimelineRenderer
206
- content={timelineContent}
207
- theme={themes.dark}
208
- />
209
- ```
238
+ #### `useStreamingContent(options)`
210
239
 
211
- #### CodeRenderer
240
+ Subscribe to a single surface's streaming updates.
212
241
 
213
- ```tsx
214
- <CodeRenderer
215
- content={codeContent}
216
- theme={themes.dark}
217
- />
242
+ ```ts
243
+ const { surface, components, dataModel, resolveData, updatedAt } = useStreamingContent({
244
+ store, // from useA2UISurface
245
+ surfaceId, // surface to watch
246
+ });
218
247
  ```
219
248
 
220
- #### DocumentRenderer
249
+ ### Individual Renderer Imports
221
250
 
222
- ```tsx
223
- <DocumentRenderer
224
- content={documentContent}
225
- theme={themes.dark}
226
- />
251
+ Tree-shake by importing only what you need:
252
+
253
+ ```ts
254
+ import ChartRenderer from '@davincidreams/dynamic-canvas-react/renderers/chart';
255
+ import TimelineRenderer from '@davincidreams/dynamic-canvas-react/renderers/timeline';
256
+ import KnowledgeGraphRenderer from '@davincidreams/dynamic-canvas-react/renderers/knowledge-graph';
257
+ import MapRenderer from '@davincidreams/dynamic-canvas-react/renderers/map';
258
+ import MediaRenderer from '@davincidreams/dynamic-canvas-react/renderers/media';
259
+ import DocumentRenderer from '@davincidreams/dynamic-canvas-react/renderers/document';
260
+ import CodeRenderer from '@davincidreams/dynamic-canvas-react/renderers/code';
261
+ import ArtifactRenderer from '@davincidreams/dynamic-canvas-react/renderers/artifact';
227
262
  ```
228
263
 
229
- #### CustomRenderer
264
+ ### Content Analyzer
230
265
 
231
- ```tsx
232
- const CustomComponent = ({ data }) => <div>{data}</div>;
266
+ Auto-detect content type from raw text and convert to A2UI messages:
233
267
 
234
- const customContent = {
235
- type: 'custom',
236
- component: CustomComponent,
237
- props: { data: 'Hello' }
238
- };
268
+ ```ts
269
+ import { ContentAnalyzer } from '@davincidreams/dynamic-canvas-react';
239
270
 
240
- <CustomRenderer content={customContent} theme={themes.dark} />
271
+ // Detect content type
272
+ ContentAnalyzer.detectType('```js\nconsole.log("hi")\n```'); // 'code'
273
+ ContentAnalyzer.detectType('# Hello World'); // 'document'
274
+ ContentAnalyzer.detectType('2024-01-01 Project Start'); // 'timeline'
275
+
276
+ // Convert to A2UI messages
277
+ const messages = ContentAnalyzer.toA2UIMessages('```python\nprint("hello")\n```');
278
+ // Returns: [createSurface, updateComponents with Code component]
241
279
  ```
242
280
 
243
281
  ## Theming
244
282
 
245
- ### Default Themes
246
-
247
283
  ```tsx
248
- import { themes } from '@dynamic-canvas/react';
249
-
250
- // Use built-in themes
251
- <CanvasProvider theme={themes.light}>
252
- {/* Light theme */}
253
- </CanvasProvider>
284
+ import { themes } from '@davincidreams/dynamic-canvas-react';
254
285
 
255
- <CanvasProvider theme={themes.dark}>
256
- {/* Dark theme */}
257
- </CanvasProvider>
258
- ```
259
-
260
- ### Custom Theme
286
+ // Built-in themes
287
+ themes.light
288
+ themes.dark
289
+ themes.default
261
290
 
262
- ```tsx
263
- const customTheme = {
291
+ // Custom theme
292
+ const myTheme = {
264
293
  colors: {
265
- background: '#ffffff',
266
- surface: '#f8fafc',
294
+ background: '#0a0a0a',
295
+ surface: '#1a1a2e',
267
296
  primary: '#0ea5e9',
268
297
  secondary: '#6366f1',
269
- text: '#0f172a',
298
+ text: '#e2e8f0',
270
299
  muted: '#64748b',
271
- border: '#e2e8f0',
272
- highlight: '#f1f5f9'
300
+ border: '#334155',
301
+ highlight: '#1e293b',
273
302
  },
274
- spacing: {
275
- xs: '4px',
276
- sm: '8px',
277
- md: '16px',
278
- lg: '24px',
279
- xl: '32px'
280
- },
281
- typography: {
282
- font: 'Inter, sans-serif',
283
- sizes: {
284
- xs: '12px',
285
- sm: '14px',
286
- md: '16px',
287
- lg: '18px',
288
- xl: '20px'
289
- },
290
- weights: {
291
- normal: 400,
292
- medium: 500,
293
- bold: 700
294
- }
295
- },
296
- borderRadius: {
297
- sm: '4px',
298
- md: '8px',
299
- lg: '12px',
300
- xl: '16px'
301
- },
302
- shadows: {
303
- sm: '0 1px 2px rgba(0,0,0,0.05)',
304
- md: '0 4px 6px rgba(0,0,0,0.1)',
305
- lg: '0 10px 15px rgba(0,0,0,0.1)'
306
- }
303
+ // ...spacing, typography, borderRadius, shadows
307
304
  };
308
-
309
- <CanvasProvider theme={customTheme}>
310
- {/* Custom theme */}
311
- </CanvasProvider>
312
305
  ```
313
306
 
314
- ## Content Analysis
307
+ ## Custom Renderers
315
308
 
316
- The `ContentAnalyzer` class automatically detects content types:
309
+ Register custom renderers by key:
317
310
 
318
311
  ```tsx
319
- import { ContentAnalyzer } from '@dynamic-canvas/react';
312
+ import { ComponentRegistry } from '@davincidreams/dynamic-canvas-react';
320
313
 
321
- const response = "Sales: 50%, Growth: 25%";
322
- const analyzed = ContentAnalyzer.analyze(response);
323
- // Returns: { type: 'chart', data: { labels: ['50', '25'], values: [] } }
324
- ```
314
+ const registry = new ComponentRegistry();
315
+ registry.register('MyWidget', () => import('./MyWidget'));
325
316
 
326
- ## Content Types
317
+ // Then in A2UI messages:
318
+ {
319
+ updateComponents: {
320
+ surfaceId: 's1',
321
+ components: [{ id: 'w1', component: 'Custom', rendererKey: 'MyWidget', props: { foo: 'bar' } }]
322
+ }
323
+ }
324
+ ```
327
325
 
328
- | Type | Description | Renderer |
329
- |------|-------------|----------|
330
- | `chart` | Data visualizations | `ChartRenderer` |
331
- | `timeline` | Timeline events | `TimelineRenderer` |
332
- | `code` | Code snippets | `CodeRenderer` |
333
- | `document` | Documents | `DocumentRenderer` |
334
- | `custom` | Custom components | `CustomRenderer` |
326
+ ## Architecture
335
327
 
336
- ## Dependencies
328
+ ```
329
+ AI Agent → A2UI JSON → StreamProcessor → SurfaceManager → RendererResolver → React Renderers
330
+ (JSONL/SSE/WS) (zustand store) (Suspense + ErrorBoundary)
331
+
332
+ Chart | Timeline | Graph | Map | Media | Doc | Code | Artifact | Custom
333
+ ```
337
334
 
338
- **Core Dependencies:**
339
- - `react`: ^18.0.0
340
- - `react-dom`: ^18.0.0
341
- - `framer-motion`: ^11.0.0
342
- - `lucide-react`: ^0.400.0
343
- - `zustand`: ^5.0.0
335
+ - **StreamProcessor**: Parses JSONL, SSE, WebSocket, or direct JSON arrays
336
+ - **SurfaceManager**: Zustand store managing surfaces, data models, and components
337
+ - **RendererResolver**: Suspense + ErrorBoundary wrapper for lazy-loaded renderers
338
+ - **ComponentRegistry**: Maps component type strings to React renderer factories
344
339
 
345
- **Optional Dependencies:**
346
- - `d3`: ^7.9.0 (for enhanced charts)
347
- - `react-syntax-highlighter`: ^15.5.0 (for code highlighting)
348
- - `react-pdf`: ^7.7.0 (for PDF rendering)
349
- - `markdown-it`: ^14.0.0 (for markdown rendering)
340
+ ## Bundle Size
350
341
 
351
- ## Extending
342
+ | Entry | Gzip |
343
+ |-------|------|
344
+ | Schema only (`./schema`) | ~2 KB |
345
+ | Core + all renderers (`.`) | ~8 KB |
346
+ | Individual renderers | 0.4–2.5 KB each |
352
347
 
353
- ### Adding a New Renderer
348
+ Heavy dependencies (D3, Cesium, shiki) are loaded on demand when a component requires them.
354
349
 
355
- ```tsx
356
- // src/renderers/VideoRenderer.tsx
357
- import React from 'react';
358
- import type { Theme } from '../types';
350
+ ## Development
359
351
 
360
- interface VideoRendererProps {
361
- content: any;
362
- theme: Theme;
363
- }
364
-
365
- export const VideoRenderer: React.FC<VideoRendererProps> = ({ content, theme }) => {
366
- return (
367
- <div style={{ color: theme.colors.text }}>
368
- <video src={content.url} controls />
369
- </div>
370
- );
371
- };
372
-
373
- // Export and register
374
- export { VideoRenderer };
375
- ```
376
-
377
- ### Adding a New Theme
378
-
379
- ```tsx
380
- // src/themes/customTheme.ts
381
- import type { Theme } from '../types';
382
- import { defaultTheme } from './defaultTheme';
383
-
384
- export const customTheme: Theme = {
385
- ...defaultTheme,
386
- colors: {
387
- ...defaultTheme.colors,
388
- primary: '#ff6b6b'
389
- }
390
- };
352
+ ```bash
353
+ npm install
354
+ npm run dev # Start Vite dev server
355
+ npm run build # Build library (ES + CJS)
356
+ npm run type-check # TypeScript check
357
+ npm test # Run tests (124 tests)
358
+ npm run test:watch # Watch mode
391
359
  ```
392
360
 
393
361
  ## License
394
362
 
395
363
  MIT
396
-
397
- ## Contributing
398
-
399
- Contributions are welcome! Please feel free to submit a Pull Request.
@@ -0,0 +1 @@
1
+ "use strict";const e=require("react/jsx-runtime"),n=({title:d,children:s,actions:r,style:i})=>e.jsxs("div",{style:{borderRadius:"8px",overflow:"hidden",border:"1px solid rgba(128,128,128,0.2)",...i},children:[(d||r)&&e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 12px",borderBottom:"1px solid rgba(128,128,128,0.2)",fontSize:"13px",fontWeight:500,background:"rgba(128,128,128,0.05)"},children:[e.jsx("span",{children:d}),r&&e.jsx("div",{style:{display:"flex",gap:"4px"},children:r})]}),e.jsx("div",{children:s})]});exports.RendererFrame=n;