@v0-sdk/react 0.1.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,848 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React__default = /*#__PURE__*/_interopDefault(React);
9
+
10
+ /**
11
+ * Generic math renderer component
12
+ * Renders plain math content by default - consumers should provide their own math rendering
13
+ */ function MathPart({ content, inline = false, className = '', children }) {
14
+ // If children provided, use that (allows complete customization)
15
+ if (children) {
16
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
17
+ children: children
18
+ });
19
+ }
20
+ // Simple fallback - just render plain math content
21
+ const Element = inline ? 'span' : 'div';
22
+ return /*#__PURE__*/ jsxRuntime.jsx(Element, {
23
+ className: className,
24
+ "data-math-inline": inline,
25
+ children: content
26
+ });
27
+ }
28
+
29
+ /**
30
+ * Generic code block component
31
+ * Renders plain code by default - consumers should provide their own styling and highlighting
32
+ */ function CodeBlock({ language, code, className = '', children }) {
33
+ // If children provided, use that (allows complete customization)
34
+ if (children) {
35
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
36
+ children: children
37
+ });
38
+ }
39
+ // Simple fallback - just render plain code
40
+ return /*#__PURE__*/ jsxRuntime.jsx("pre", {
41
+ className: className,
42
+ "data-language": language,
43
+ children: /*#__PURE__*/ jsxRuntime.jsx("code", {
44
+ children: code
45
+ })
46
+ });
47
+ }
48
+
49
+ // Context for providing custom icon implementation
50
+ const IconContext = /*#__PURE__*/ React.createContext(null);
51
+ /**
52
+ * Generic icon component that can be customized by consumers.
53
+ * By default, renders a simple fallback. Consumers should provide
54
+ * their own icon implementation via context or props.
55
+ */ function Icon(props) {
56
+ const CustomIcon = React.useContext(IconContext);
57
+ // Use custom icon implementation if provided via context
58
+ if (CustomIcon) {
59
+ return /*#__PURE__*/ jsxRuntime.jsx(CustomIcon, {
60
+ ...props
61
+ });
62
+ }
63
+ // Fallback implementation - consumers should override this
64
+ return /*#__PURE__*/ jsxRuntime.jsx("span", {
65
+ className: props.className,
66
+ "data-icon": props.name,
67
+ suppressHydrationWarning: true,
68
+ "aria-label": props.name.replace('-', ' '),
69
+ children: getIconFallback(props.name)
70
+ });
71
+ }
72
+ function getIconFallback(name) {
73
+ const iconMap = {
74
+ 'chevron-right': '▶',
75
+ 'chevron-down': '▼',
76
+ search: '🔍',
77
+ folder: '📁',
78
+ settings: '⚙️',
79
+ 'file-text': '📄',
80
+ brain: '🧠',
81
+ wrench: '🔧'
82
+ };
83
+ return iconMap[name] || '•';
84
+ }
85
+
86
+ /**
87
+ * Generic code project block component
88
+ * Renders a collapsible code project with basic structure - consumers provide styling
89
+ */ function CodeProjectPart({ title, filename, code, language = 'typescript', collapsed: initialCollapsed = true, className, children, iconRenderer }) {
90
+ const [collapsed, setCollapsed] = React.useState(initialCollapsed);
91
+ // If children provided, use that (allows complete customization)
92
+ if (children) {
93
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
94
+ children: children
95
+ });
96
+ }
97
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
98
+ className: className,
99
+ "data-component": "code-project-block",
100
+ children: [
101
+ /*#__PURE__*/ jsxRuntime.jsxs("button", {
102
+ onClick: ()=>setCollapsed(!collapsed),
103
+ "data-expanded": !collapsed,
104
+ children: [
105
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
106
+ "data-header": true,
107
+ children: [
108
+ iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
109
+ name: 'folder'
110
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
111
+ name: "folder"
112
+ }),
113
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
114
+ "data-title": true,
115
+ children: title || 'Code Project'
116
+ })
117
+ ]
118
+ }),
119
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
120
+ "data-version": true,
121
+ children: "v1"
122
+ })
123
+ ]
124
+ }),
125
+ !collapsed && /*#__PURE__*/ jsxRuntime.jsxs("div", {
126
+ "data-content": true,
127
+ children: [
128
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
129
+ "data-file-list": true,
130
+ children: [
131
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
132
+ "data-file": true,
133
+ "data-active": true,
134
+ children: [
135
+ iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
136
+ name: 'file-text'
137
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
138
+ name: "file-text"
139
+ }),
140
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
141
+ "data-filename": true,
142
+ children: filename
143
+ }),
144
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
145
+ "data-filepath": true,
146
+ children: "app/page.tsx"
147
+ })
148
+ ]
149
+ }),
150
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
151
+ "data-file": true,
152
+ children: [
153
+ iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
154
+ name: 'file-text'
155
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
156
+ name: "file-text"
157
+ }),
158
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
159
+ "data-filename": true,
160
+ children: "layout.tsx"
161
+ }),
162
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
163
+ "data-filepath": true,
164
+ children: "app/layout.tsx"
165
+ })
166
+ ]
167
+ }),
168
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
169
+ "data-file": true,
170
+ children: [
171
+ iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
172
+ name: 'file-text'
173
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
174
+ name: "file-text"
175
+ }),
176
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
177
+ "data-filename": true,
178
+ children: "globals.css"
179
+ }),
180
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
181
+ "data-filepath": true,
182
+ children: "app/globals.css"
183
+ })
184
+ ]
185
+ })
186
+ ]
187
+ }),
188
+ code && /*#__PURE__*/ jsxRuntime.jsx(CodeBlock, {
189
+ language: language,
190
+ code: code
191
+ })
192
+ ]
193
+ })
194
+ ]
195
+ });
196
+ }
197
+
198
+ /**
199
+ * Generic thinking section component
200
+ * Renders a collapsible section with basic structure - consumers provide styling
201
+ */ function ThinkingSection({ title, duration, thought, collapsed: initialCollapsed = true, onCollapse, className, children, iconRenderer, brainIcon, chevronRightIcon, chevronDownIcon }) {
202
+ const [internalCollapsed, setInternalCollapsed] = React.useState(initialCollapsed);
203
+ const collapsed = onCollapse ? initialCollapsed : internalCollapsed;
204
+ const handleCollapse = onCollapse || (()=>setInternalCollapsed(!internalCollapsed));
205
+ // If children provided, use that (allows complete customization)
206
+ if (children) {
207
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
208
+ children: children
209
+ });
210
+ }
211
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
212
+ className: className,
213
+ "data-component": "thinking-section",
214
+ children: [
215
+ /*#__PURE__*/ jsxRuntime.jsxs("button", {
216
+ onClick: handleCollapse,
217
+ "data-expanded": !collapsed,
218
+ "data-button": true,
219
+ children: [
220
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
221
+ "data-icon-container": true,
222
+ children: collapsed ? /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
223
+ children: [
224
+ brainIcon || (iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
225
+ name: 'brain'
226
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
227
+ name: "brain"
228
+ })),
229
+ chevronRightIcon || (iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
230
+ name: 'chevron-right'
231
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
232
+ name: "chevron-right"
233
+ }))
234
+ ]
235
+ }) : chevronDownIcon || (iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
236
+ name: 'chevron-down'
237
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
238
+ name: "chevron-down"
239
+ }))
240
+ }),
241
+ /*#__PURE__*/ jsxRuntime.jsxs("span", {
242
+ "data-title": true,
243
+ children: [
244
+ title || 'Thinking',
245
+ duration && ` for ${Math.round(duration)}s`
246
+ ]
247
+ })
248
+ ]
249
+ }),
250
+ !collapsed && thought && /*#__PURE__*/ jsxRuntime.jsx("div", {
251
+ "data-content": true,
252
+ children: /*#__PURE__*/ jsxRuntime.jsx("div", {
253
+ "data-thought-container": true,
254
+ children: thought.split('\n\n').map((paragraph, index)=>/*#__PURE__*/ jsxRuntime.jsx("div", {
255
+ "data-paragraph": true,
256
+ children: paragraph
257
+ }, index))
258
+ })
259
+ })
260
+ ]
261
+ });
262
+ }
263
+
264
+ function getTypeIcon(type, title, iconRenderer) {
265
+ // Check title content for specific cases
266
+ if (title?.includes('No issues found')) {
267
+ return iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
268
+ name: 'wrench'
269
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
270
+ name: "wrench"
271
+ });
272
+ }
273
+ if (title?.includes('Analyzed codebase')) {
274
+ return iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
275
+ name: 'search'
276
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
277
+ name: "search"
278
+ });
279
+ }
280
+ // Fallback to type-based icons
281
+ switch(type){
282
+ case 'task-search-web-v1':
283
+ return iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
284
+ name: 'search'
285
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
286
+ name: "search"
287
+ });
288
+ case 'task-search-repo-v1':
289
+ return iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
290
+ name: 'folder'
291
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
292
+ name: "folder"
293
+ });
294
+ case 'task-diagnostics-v1':
295
+ return iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
296
+ name: 'settings'
297
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
298
+ name: "settings"
299
+ });
300
+ default:
301
+ return iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
302
+ name: 'wrench'
303
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
304
+ name: "wrench"
305
+ });
306
+ }
307
+ }
308
+ function renderTaskPart(part, index, iconRenderer) {
309
+ if (part.type === 'search-web') {
310
+ if (part.status === 'searching') {
311
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
312
+ children: `Searching "${part.query}"`
313
+ }, index);
314
+ }
315
+ if (part.status === 'analyzing') {
316
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
317
+ children: `Analyzing ${part.count} results...`
318
+ }, index);
319
+ }
320
+ if (part.status === 'complete' && part.answer) {
321
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
322
+ children: [
323
+ /*#__PURE__*/ jsxRuntime.jsx("p", {
324
+ children: part.answer
325
+ }),
326
+ part.sources && part.sources.length > 0 && /*#__PURE__*/ jsxRuntime.jsx("div", {
327
+ children: part.sources.map((source, sourceIndex)=>/*#__PURE__*/ jsxRuntime.jsx("a", {
328
+ href: source.url,
329
+ target: "_blank",
330
+ rel: "noopener noreferrer",
331
+ children: source.title
332
+ }, sourceIndex))
333
+ })
334
+ ]
335
+ }, index);
336
+ }
337
+ }
338
+ if (part.type === 'search-repo') {
339
+ if (part.status === 'searching') {
340
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
341
+ children: `Searching "${part.query}"`
342
+ }, index);
343
+ }
344
+ if (part.status === 'reading' && part.files) {
345
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
346
+ children: [
347
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
348
+ children: "Reading files"
349
+ }),
350
+ part.files.map((file, fileIndex)=>/*#__PURE__*/ jsxRuntime.jsxs("span", {
351
+ children: [
352
+ iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
353
+ name: 'file-text'
354
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
355
+ name: "file-text"
356
+ }),
357
+ ' ',
358
+ file
359
+ ]
360
+ }, fileIndex))
361
+ ]
362
+ }, index);
363
+ }
364
+ }
365
+ if (part.type === 'diagnostics') {
366
+ if (part.status === 'checking') {
367
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
368
+ children: "Checking for issues..."
369
+ }, index);
370
+ }
371
+ if (part.status === 'complete' && part.issues === 0) {
372
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
373
+ children: "✅ No issues found"
374
+ }, index);
375
+ }
376
+ }
377
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
378
+ children: JSON.stringify(part)
379
+ }, index);
380
+ }
381
+ /**
382
+ * Generic task section component
383
+ * Renders a collapsible task section with basic structure - consumers provide styling
384
+ */ function TaskSection({ title, type, parts = [], collapsed: initialCollapsed = true, onCollapse, className, children, iconRenderer, taskIcon, chevronRightIcon, chevronDownIcon }) {
385
+ const [internalCollapsed, setInternalCollapsed] = React.useState(initialCollapsed);
386
+ const collapsed = onCollapse ? initialCollapsed : internalCollapsed;
387
+ const handleCollapse = onCollapse || (()=>setInternalCollapsed(!internalCollapsed));
388
+ // If children provided, use that (allows complete customization)
389
+ if (children) {
390
+ return /*#__PURE__*/ jsxRuntime.jsx(jsxRuntime.Fragment, {
391
+ children: children
392
+ });
393
+ }
394
+ // Count meaningful parts (parts that would render something)
395
+ const meaningfulParts = parts.filter((part)=>{
396
+ // Check if the part would render meaningful content
397
+ if (part.type === 'search-web') {
398
+ return part.status === 'searching' || part.status === 'analyzing' || part.status === 'complete' && part.answer;
399
+ }
400
+ if (part.type === 'starting-repo-search' && part.query) return true;
401
+ if (part.type === 'select-files' && part.filePaths?.length > 0) return true;
402
+ if (part.type === 'starting-web-search' && part.query) return true;
403
+ if (part.type === 'got-results' && part.count) return true;
404
+ if (part.type === 'finished-web-search' && part.answer) return true;
405
+ if (part.type === 'diagnostics-passed') return true;
406
+ if (part.type === 'fetching-diagnostics') return true;
407
+ // Add more meaningful part types as needed
408
+ return false;
409
+ });
410
+ // If there's only one meaningful part, show just the content without the collapsible wrapper
411
+ if (meaningfulParts.length === 1) {
412
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
413
+ className: className,
414
+ "data-component": "task-section-inline",
415
+ children: /*#__PURE__*/ jsxRuntime.jsx("div", {
416
+ "data-part": true,
417
+ children: renderTaskPart(meaningfulParts[0], 0, iconRenderer)
418
+ })
419
+ });
420
+ }
421
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
422
+ className: className,
423
+ "data-component": "task-section",
424
+ children: [
425
+ /*#__PURE__*/ jsxRuntime.jsxs("button", {
426
+ onClick: handleCollapse,
427
+ "data-expanded": !collapsed,
428
+ "data-button": true,
429
+ children: [
430
+ /*#__PURE__*/ jsxRuntime.jsxs("div", {
431
+ "data-icon-container": true,
432
+ children: [
433
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
434
+ "data-task-icon": true,
435
+ children: taskIcon || getTypeIcon(type, title, iconRenderer)
436
+ }),
437
+ collapsed ? chevronRightIcon || (iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
438
+ name: 'chevron-right'
439
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
440
+ name: "chevron-right"
441
+ })) : chevronDownIcon || (iconRenderer ? /*#__PURE__*/ React__default.default.createElement(iconRenderer, {
442
+ name: 'chevron-down'
443
+ }) : /*#__PURE__*/ jsxRuntime.jsx(Icon, {
444
+ name: "chevron-down"
445
+ }))
446
+ ]
447
+ }),
448
+ /*#__PURE__*/ jsxRuntime.jsx("span", {
449
+ "data-title": true,
450
+ children: title || 'Task'
451
+ })
452
+ ]
453
+ }),
454
+ !collapsed && /*#__PURE__*/ jsxRuntime.jsx("div", {
455
+ "data-content": true,
456
+ children: /*#__PURE__*/ jsxRuntime.jsx("div", {
457
+ "data-parts-container": true,
458
+ children: parts.map((part, index)=>/*#__PURE__*/ jsxRuntime.jsx("div", {
459
+ "data-part": true,
460
+ children: renderTaskPart(part, index, iconRenderer)
461
+ }, index))
462
+ })
463
+ })
464
+ ]
465
+ });
466
+ }
467
+
468
+ function ContentPartRenderer({ part, iconRenderer, thinkingSectionRenderer, taskSectionRenderer, brainIcon, chevronRightIcon, chevronDownIcon, searchIcon, folderIcon, settingsIcon, wrenchIcon }) {
469
+ if (!part) return null;
470
+ const { type, parts = [], ...metadata } = part;
471
+ switch(type){
472
+ case 'task-thinking-v1':
473
+ {
474
+ const thinkingPart = parts.find((p)=>p.type === 'thinking-end');
475
+ const ThinkingComponent = thinkingSectionRenderer || ThinkingSection;
476
+ const [collapsed, setCollapsed] = React.useState(true);
477
+ return /*#__PURE__*/ jsxRuntime.jsx(ThinkingComponent, {
478
+ title: "Thought",
479
+ duration: thinkingPart?.duration,
480
+ thought: thinkingPart?.thought,
481
+ collapsed: collapsed,
482
+ onCollapse: ()=>setCollapsed(!collapsed),
483
+ brainIcon: brainIcon,
484
+ chevronRightIcon: chevronRightIcon,
485
+ chevronDownIcon: chevronDownIcon
486
+ });
487
+ }
488
+ case 'task-search-web-v1':
489
+ {
490
+ const TaskComponent = taskSectionRenderer || TaskSection;
491
+ const [collapsed, setCollapsed] = React.useState(true);
492
+ return /*#__PURE__*/ jsxRuntime.jsx(TaskComponent, {
493
+ title: metadata.taskNameComplete || metadata.taskNameActive,
494
+ type: type,
495
+ parts: parts,
496
+ collapsed: collapsed,
497
+ onCollapse: ()=>setCollapsed(!collapsed),
498
+ taskIcon: searchIcon,
499
+ chevronRightIcon: chevronRightIcon,
500
+ chevronDownIcon: chevronDownIcon
501
+ });
502
+ }
503
+ case 'task-search-repo-v1':
504
+ {
505
+ const TaskComponent = taskSectionRenderer || TaskSection;
506
+ const [collapsed, setCollapsed] = React.useState(true);
507
+ return /*#__PURE__*/ jsxRuntime.jsx(TaskComponent, {
508
+ title: metadata.taskNameComplete || metadata.taskNameActive,
509
+ type: type,
510
+ parts: parts,
511
+ collapsed: collapsed,
512
+ onCollapse: ()=>setCollapsed(!collapsed),
513
+ taskIcon: folderIcon,
514
+ chevronRightIcon: chevronRightIcon,
515
+ chevronDownIcon: chevronDownIcon
516
+ });
517
+ }
518
+ case 'task-diagnostics-v1':
519
+ {
520
+ const TaskComponent = taskSectionRenderer || TaskSection;
521
+ const [collapsed, setCollapsed] = React.useState(true);
522
+ return /*#__PURE__*/ jsxRuntime.jsx(TaskComponent, {
523
+ title: metadata.taskNameComplete || metadata.taskNameActive,
524
+ type: type,
525
+ parts: parts,
526
+ collapsed: collapsed,
527
+ onCollapse: ()=>setCollapsed(!collapsed),
528
+ taskIcon: settingsIcon,
529
+ chevronRightIcon: chevronRightIcon,
530
+ chevronDownIcon: chevronDownIcon
531
+ });
532
+ }
533
+ case 'task-start-v1':
534
+ // Usually just indicates task start - can be hidden or show as status
535
+ return null;
536
+ default:
537
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
538
+ "data-unknown-part-type": type,
539
+ children: [
540
+ "Unknown part type: ",
541
+ type
542
+ ]
543
+ });
544
+ }
545
+ }
546
+
547
+ // Utility function to merge class names
548
+ function cn(...classes) {
549
+ return classes.filter(Boolean).join(' ');
550
+ }
551
+
552
+ // Helper function to render HTML elements with component or className config
553
+ function renderHtmlElement(tagName, key, props, children, className, componentOrConfig, components) {
554
+ if (typeof componentOrConfig === 'function') {
555
+ const Component = componentOrConfig;
556
+ return /*#__PURE__*/ jsxRuntime.jsx(Component, {
557
+ ...props,
558
+ className: className,
559
+ children: renderChildren(children, key, components)
560
+ }, key);
561
+ } else if (componentOrConfig && typeof componentOrConfig === 'object') {
562
+ const mergedClassName = cn(className, componentOrConfig.className);
563
+ return /*#__PURE__*/ React__default.default.createElement(tagName, {
564
+ key,
565
+ ...props,
566
+ className: mergedClassName
567
+ }, renderChildren(children, key, components));
568
+ } else {
569
+ return /*#__PURE__*/ React__default.default.createElement(tagName, {
570
+ key,
571
+ ...props,
572
+ className
573
+ }, renderChildren(children, key, components));
574
+ }
575
+ }
576
+ /**
577
+ * Core renderer component for v0 Platform API message content
578
+ */ function MessageImpl({ content, messageId = 'unknown', role: _role = 'assistant', streaming: _streaming = false, isLastMessage: _isLastMessage = false, className, components, renderers }) {
579
+ if (!Array.isArray(content)) {
580
+ console.warn('MessageContent: content must be an array (MessageBinaryFormat)');
581
+ return null;
582
+ }
583
+ // Merge components and renderers (backward compatibility)
584
+ const mergedComponents = {
585
+ ...components,
586
+ // Map legacy renderers to new component names
587
+ ...renderers?.CodeBlock && {
588
+ CodeBlock: renderers.CodeBlock
589
+ },
590
+ ...renderers?.MathRenderer && {
591
+ MathPart: renderers.MathRenderer
592
+ },
593
+ ...renderers?.MathPart && {
594
+ MathPart: renderers.MathPart
595
+ },
596
+ ...renderers?.Icon && {
597
+ Icon: renderers.Icon
598
+ }
599
+ };
600
+ const elements = content.map(([type, ...data], index)=>{
601
+ const key = `${messageId}-${index}`;
602
+ // Markdown/text content (type 0)
603
+ if (type === 0) {
604
+ const markdownData = data[0];
605
+ if (!Array.isArray(markdownData)) {
606
+ return null;
607
+ }
608
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
609
+ children: markdownData.map((item, mdIndex)=>{
610
+ const mdKey = `${key}-md-${mdIndex}`;
611
+ return renderMarkdownElement(item, mdKey, mergedComponents);
612
+ })
613
+ }, key);
614
+ }
615
+ // Code block (type 1)
616
+ if (type === 1) {
617
+ const [language, code] = data;
618
+ const CodeBlockComponent = mergedComponents?.CodeBlock || CodeBlock;
619
+ return /*#__PURE__*/ jsxRuntime.jsx(CodeBlockComponent, {
620
+ language: language || 'text',
621
+ code: code || ''
622
+ }, key);
623
+ }
624
+ // Math (type 2 for inline, type 3 for block)
625
+ if (type === 2 || type === 3) {
626
+ const mathContent = data[0] || '';
627
+ const MathPartComponent = mergedComponents?.MathPart || MathPart;
628
+ return /*#__PURE__*/ jsxRuntime.jsx(MathPartComponent, {
629
+ content: mathContent,
630
+ inline: type === 2
631
+ }, key);
632
+ }
633
+ // Unknown type - render as text for debugging
634
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
635
+ children: [
636
+ "[Unknown content type: ",
637
+ type,
638
+ "]"
639
+ ]
640
+ }, key);
641
+ });
642
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
643
+ className: className,
644
+ children: elements
645
+ });
646
+ }
647
+ function renderMarkdownElement(item, key, components) {
648
+ if (typeof item === 'string') {
649
+ return /*#__PURE__*/ jsxRuntime.jsx("span", {
650
+ children: item
651
+ }, key);
652
+ }
653
+ if (Array.isArray(item)) {
654
+ const [tagName, props, ...children] = item;
655
+ // Handle special v0 Platform API elements
656
+ if (tagName === 'AssistantMessageContentPart') {
657
+ return /*#__PURE__*/ jsxRuntime.jsx(ContentPartRenderer, {
658
+ part: props.part,
659
+ iconRenderer: components?.Icon,
660
+ thinkingSectionRenderer: components?.ThinkingSection,
661
+ taskSectionRenderer: components?.TaskSection
662
+ }, key);
663
+ }
664
+ if (tagName === 'Codeblock') {
665
+ const CustomCodeProjectPart = components?.CodeProjectPart;
666
+ const CodeProjectComponent = CustomCodeProjectPart || CodeProjectPart;
667
+ return /*#__PURE__*/ jsxRuntime.jsx(CodeProjectComponent, {
668
+ language: props.lang,
669
+ code: children[0],
670
+ iconRenderer: components?.Icon
671
+ }, key);
672
+ }
673
+ if (tagName === 'text') {
674
+ return /*#__PURE__*/ jsxRuntime.jsx("span", {
675
+ children: children[0]
676
+ }, key);
677
+ }
678
+ // Handle standard markdown elements
679
+ const className = props?.className;
680
+ switch(tagName){
681
+ case 'p':
682
+ {
683
+ const componentOrConfig = components?.p;
684
+ if (typeof componentOrConfig === 'function') {
685
+ const Component = componentOrConfig;
686
+ return /*#__PURE__*/ jsxRuntime.jsx(Component, {
687
+ ...props,
688
+ className: className,
689
+ children: renderChildren(children, key, components)
690
+ }, key);
691
+ } else if (componentOrConfig && typeof componentOrConfig === 'object') {
692
+ const mergedClassName = cn(className, componentOrConfig.className);
693
+ return /*#__PURE__*/ jsxRuntime.jsx("p", {
694
+ ...props,
695
+ className: mergedClassName,
696
+ children: renderChildren(children, key, components)
697
+ }, key);
698
+ } else {
699
+ return /*#__PURE__*/ jsxRuntime.jsx("p", {
700
+ ...props,
701
+ className: className,
702
+ children: renderChildren(children, key, components)
703
+ }, key);
704
+ }
705
+ }
706
+ case 'h1':
707
+ return renderHtmlElement('h1', key, props, children, className, components?.h1, components);
708
+ case 'h2':
709
+ return renderHtmlElement('h2', key, props, children, className, components?.h2, components);
710
+ case 'h3':
711
+ return renderHtmlElement('h3', key, props, children, className, components?.h3, components);
712
+ case 'h4':
713
+ return renderHtmlElement('h4', key, props, children, className, components?.h4, components);
714
+ case 'h5':
715
+ return renderHtmlElement('h5', key, props, children, className, components?.h5, components);
716
+ case 'h6':
717
+ return renderHtmlElement('h6', key, props, children, className, components?.h6, components);
718
+ case 'ul':
719
+ return renderHtmlElement('ul', key, props, children, className, components?.ul, components);
720
+ case 'ol':
721
+ return renderHtmlElement('ol', key, props, children, className, components?.ol, components);
722
+ case 'li':
723
+ return renderHtmlElement('li', key, props, children, className, components?.li, components);
724
+ case 'blockquote':
725
+ return renderHtmlElement('blockquote', key, props, children, className, components?.blockquote, components);
726
+ case 'code':
727
+ return renderHtmlElement('code', key, props, children, className, components?.code, components);
728
+ case 'pre':
729
+ return renderHtmlElement('pre', key, props, children, className, components?.pre, components);
730
+ case 'strong':
731
+ return renderHtmlElement('strong', key, props, children, className, components?.strong, components);
732
+ case 'em':
733
+ return renderHtmlElement('em', key, props, children, className, components?.em, components);
734
+ case 'a':
735
+ {
736
+ const componentOrConfig = components?.a;
737
+ if (typeof componentOrConfig === 'function') {
738
+ const Component = componentOrConfig;
739
+ return /*#__PURE__*/ jsxRuntime.jsx(Component, {
740
+ ...props,
741
+ className: className,
742
+ target: "_blank",
743
+ rel: "noopener noreferrer",
744
+ children: renderChildren(children, key, components)
745
+ }, key);
746
+ } else if (componentOrConfig && typeof componentOrConfig === 'object') {
747
+ const mergedClassName = cn(className, componentOrConfig.className);
748
+ return /*#__PURE__*/ jsxRuntime.jsx("a", {
749
+ ...props,
750
+ className: mergedClassName,
751
+ target: "_blank",
752
+ rel: "noopener noreferrer",
753
+ children: renderChildren(children, key, components)
754
+ }, key);
755
+ } else {
756
+ return /*#__PURE__*/ jsxRuntime.jsx("a", {
757
+ ...props,
758
+ className: className,
759
+ target: "_blank",
760
+ rel: "noopener noreferrer",
761
+ children: renderChildren(children, key, components)
762
+ }, key);
763
+ }
764
+ }
765
+ case 'br':
766
+ return /*#__PURE__*/ jsxRuntime.jsx("br", {}, key);
767
+ case 'hr':
768
+ {
769
+ const componentOrConfig = components?.hr;
770
+ if (typeof componentOrConfig === 'function') {
771
+ const Component = componentOrConfig;
772
+ return /*#__PURE__*/ jsxRuntime.jsx(Component, {
773
+ ...props,
774
+ className: className
775
+ }, key);
776
+ } else if (componentOrConfig && typeof componentOrConfig === 'object') {
777
+ const mergedClassName = cn(className, componentOrConfig.className);
778
+ return /*#__PURE__*/ jsxRuntime.jsx("hr", {
779
+ ...props,
780
+ className: mergedClassName
781
+ }, key);
782
+ } else {
783
+ return /*#__PURE__*/ jsxRuntime.jsx("hr", {
784
+ ...props,
785
+ className: className
786
+ }, key);
787
+ }
788
+ }
789
+ case 'div':
790
+ return renderHtmlElement('div', key, props, children, className, components?.div, components);
791
+ case 'span':
792
+ return renderHtmlElement('span', key, props, children, className, components?.span, components);
793
+ default:
794
+ return /*#__PURE__*/ jsxRuntime.jsx("span", {
795
+ children: renderChildren(children, key, components)
796
+ }, key);
797
+ }
798
+ }
799
+ return null;
800
+ }
801
+ function renderChildren(children, parentKey, components) {
802
+ return children.map((child, index)=>{
803
+ const key = `${parentKey}-child-${index}`;
804
+ return renderMarkdownElement(child, key, components);
805
+ }).filter(Boolean);
806
+ }
807
+ /**
808
+ * Main component for rendering v0 Platform API message content
809
+ *
810
+ * @example
811
+ * ```tsx
812
+ * import { Message } from '@v0-sdk/react'
813
+ *
814
+ * function MyComponent({ apiResponse }) {
815
+ * const content = JSON.parse(apiResponse.content)
816
+ *
817
+ * return (
818
+ * <Message
819
+ * content={content}
820
+ * messageId={apiResponse.id}
821
+ * role={apiResponse.role}
822
+ * className="space-y-4"
823
+ * components={{
824
+ * p: ({ children, ...props }) => <p className="mb-4" {...props}>{children}</p>,
825
+ * h1: ({ children, ...props }) => <h1 className="mb-4 text-2xl font-bold" {...props}>{children}</h1>,
826
+ * CodeBlock: MyCustomCodeBlock,
827
+ * MathPart: MyCustomMathRenderer,
828
+ * }}
829
+ * />
830
+ * )
831
+ * }
832
+ * ```
833
+ */ const Message = /*#__PURE__*/ React__default.default.memo(MessageImpl);
834
+
835
+ exports.AssistantMessageContentPart = ContentPartRenderer;
836
+ exports.CodeBlock = CodeBlock;
837
+ exports.CodeProjectBlock = CodeProjectPart;
838
+ exports.CodeProjectPart = CodeProjectPart;
839
+ exports.ContentPartRenderer = ContentPartRenderer;
840
+ exports.Icon = Icon;
841
+ exports.MathPart = MathPart;
842
+ exports.MathRenderer = MathPart;
843
+ exports.Message = Message;
844
+ exports.MessageContent = Message;
845
+ exports.MessageRenderer = Message;
846
+ exports.TaskSection = TaskSection;
847
+ exports.ThinkingSection = ThinkingSection;
848
+ exports.V0MessageRenderer = Message;