@braincrew-lab/langchain-canvas 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.
@@ -0,0 +1,669 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, ComponentType } from 'react';
3
+ import { StoreApi } from 'zustand/vanilla';
4
+
5
+ /**
6
+ * Artifact data shapes — mirror of `langchain_canvas/protocol/artifacts.py`.
7
+ *
8
+ * An `Artifact` is transport-agnostic: `{ id, type, title, version, status,
9
+ * data }`. `type` is a registry key resolved to a React component; `data` is the
10
+ * type-specific payload that component reads. Keep this file in lockstep with
11
+ * the Python module — a field here must exist there, and vice versa.
12
+ */
13
+ type ArtifactStatus = "streaming" | "complete" | "error";
14
+ interface Artifact<TData = unknown> {
15
+ /** Stable identity — the reconciliation key. */
16
+ id: string;
17
+ /** Registry key: "document" | "chart" | ... */
18
+ type: string;
19
+ /** Shown in the canvas header / tab. */
20
+ title: string;
21
+ /** 1-based; bumped on every `canvas.replace`. */
22
+ version: number;
23
+ status: ArtifactStatus;
24
+ data: TData;
25
+ meta?: Record<string, unknown>;
26
+ }
27
+ /**
28
+ * The base substrate: raw HTML, rendered in a sandboxed iframe. Everything a
29
+ * canvas can show is ultimately HTML; `document` / `chart` / `table` are
30
+ * structured conveniences the SDK renders for you, while `html` lets an agent
31
+ * emit an arbitrary self-contained page (the Claude-Artifacts / Genspark model).
32
+ */
33
+ interface HtmlData {
34
+ html: string;
35
+ }
36
+ interface DocumentData {
37
+ format: "markdown";
38
+ content: string;
39
+ }
40
+ interface ChartSeries {
41
+ /** Column in `ChartData.rows` to plot. */
42
+ key: string;
43
+ label?: string;
44
+ color?: string;
45
+ }
46
+ interface ChartOptions {
47
+ stacked?: boolean;
48
+ yLabel?: string;
49
+ /** Per-slice colors for pie charts, index-aligned to `rows`. */
50
+ colors?: string[];
51
+ }
52
+ interface ChartData {
53
+ chart: "line" | "bar" | "area" | "pie";
54
+ /** Tidy/long-form rows, consumed directly by the charting library. */
55
+ rows: Array<Record<string, string | number>>;
56
+ /** Category / x-axis field. */
57
+ xKey: string;
58
+ series: ChartSeries[];
59
+ options?: ChartOptions;
60
+ /**
61
+ * Optional raw ECharts `option`. When present it's rendered verbatim — an
62
+ * escape hatch for agents/apps that already produce a full ECharts config
63
+ * (the tidy `rows`/`series` model is ignored, and inline editing is disabled).
64
+ */
65
+ echartsOption?: Record<string, unknown>;
66
+ }
67
+ interface TableColumn {
68
+ key: string;
69
+ label?: string;
70
+ align?: "left" | "right" | "center";
71
+ }
72
+ interface TableData {
73
+ columns: TableColumn[];
74
+ rows: Array<Record<string, string | number>>;
75
+ /**
76
+ * Opaque spreadsheet state (Fortune-sheet sheets) once the user has edited the
77
+ * grid — carries merges, per-cell fonts/formats, and formulas that the simple
78
+ * columns/rows shape can't hold. Present after the first interactive edit;
79
+ * exporters prefer it over columns/rows.
80
+ */
81
+ sheet?: Array<Record<string, unknown>>;
82
+ }
83
+ /** A freely-positioned element on a "blank" slide (percent geometry, 0–100). */
84
+ interface SlideElement {
85
+ id: string;
86
+ type: "text" | "image";
87
+ x: number;
88
+ y: number;
89
+ w: number;
90
+ h: number;
91
+ text?: string;
92
+ src?: string;
93
+ fontSize?: number;
94
+ bold?: boolean;
95
+ color?: string;
96
+ align?: "left" | "center" | "right";
97
+ }
98
+ interface Slide {
99
+ /** title · content (bullets) · section · image · two-column · blank (free canvas). */
100
+ layout?: "title" | "content" | "section" | "image" | "two-column" | "blank";
101
+ /** Freely-positioned elements for the "blank" layout. */
102
+ elements?: SlideElement[];
103
+ title?: string;
104
+ subtitle?: string;
105
+ bullets?: string[];
106
+ /** Right-hand bullets for the "two-column" layout. */
107
+ bullets2?: string[];
108
+ /** Image (data: URL or https URL) for the "image" layout. */
109
+ image?: string;
110
+ /** Slide background color (hex). */
111
+ background?: string;
112
+ /** Slide text color (hex). */
113
+ textColor?: string;
114
+ /** Speaker notes (not shown on the slide; exported to the .pptx notes pane). */
115
+ notes?: string;
116
+ }
117
+ interface SlidesData {
118
+ slides: Slide[];
119
+ }
120
+ type HtmlArtifact = Artifact<HtmlData> & {
121
+ type: "html";
122
+ };
123
+ type DocumentArtifact = Artifact<DocumentData> & {
124
+ type: "document";
125
+ };
126
+ type ChartArtifact = Artifact<ChartData> & {
127
+ type: "chart";
128
+ };
129
+ type TableArtifact = Artifact<TableData> & {
130
+ type: "table";
131
+ };
132
+ type SlidesArtifact = Artifact<SlidesData> & {
133
+ type: "slides";
134
+ };
135
+ type KnownArtifact = HtmlArtifact | DocumentArtifact | ChartArtifact | TableArtifact | SlidesArtifact;
136
+
137
+ /**
138
+ * Canvas Wire Protocol v1 — event envelopes. Mirror of
139
+ * `langchain_canvas/protocol/events.py`. Every SSE frame is one `StreamEvent`,
140
+ * discriminated by `type`. See `docs/02-protocol.md` for the specification.
141
+ */
142
+
143
+ interface MessageDelta {
144
+ type: "message.delta";
145
+ messageId: string;
146
+ text: string;
147
+ }
148
+ interface MessageEnd {
149
+ type: "message.end";
150
+ messageId: string;
151
+ }
152
+ interface ToolStart {
153
+ type: "tool.start";
154
+ toolCallId: string;
155
+ name: string;
156
+ }
157
+ interface ToolEnd {
158
+ type: "tool.end";
159
+ toolCallId: string;
160
+ ok: boolean;
161
+ }
162
+ interface CanvasCreate {
163
+ type: "canvas.create";
164
+ artifact: Artifact;
165
+ }
166
+ /** Append `text` to the string at `data.<path>` (e.g. a document body). */
167
+ interface CanvasAppend {
168
+ type: "canvas.append";
169
+ id: string;
170
+ path: string;
171
+ text: string;
172
+ }
173
+ /** JSON-merge-patch (RFC 7386) `patch` into the artifact's `data`. */
174
+ interface CanvasPatch {
175
+ type: "canvas.patch";
176
+ id: string;
177
+ patch: Record<string, unknown>;
178
+ }
179
+ /**
180
+ * Replace a single element (by its `data-cid` tree path) inside an `html`
181
+ * artifact with new outer HTML — an O(1) surgical edit that avoids resending the
182
+ * whole page. The reconciler resolves the `cid` path against the source HTML.
183
+ */
184
+ interface CanvasNodePatch {
185
+ type: "canvas.node_patch";
186
+ id: string;
187
+ cid: string;
188
+ html: string;
189
+ }
190
+ /** Replace wholesale — the reconciler snapshots a new version. */
191
+ interface CanvasReplace {
192
+ type: "canvas.replace";
193
+ id: string;
194
+ artifact: Artifact;
195
+ }
196
+ interface CanvasStatus {
197
+ type: "canvas.status";
198
+ id: string;
199
+ status: ArtifactStatus;
200
+ }
201
+ interface CanvasClose {
202
+ type: "canvas.close";
203
+ id: string;
204
+ }
205
+ interface ErrorEvent {
206
+ type: "error";
207
+ message: string;
208
+ }
209
+ interface DoneEvent {
210
+ type: "done";
211
+ }
212
+ type ChatEvent = MessageDelta | MessageEnd | ToolStart | ToolEnd;
213
+ type CanvasEvent = CanvasCreate | CanvasAppend | CanvasPatch | CanvasNodePatch | CanvasReplace | CanvasStatus | CanvasClose;
214
+ type StreamEvent = ChatEvent | CanvasEvent | ErrorEvent | DoneEvent;
215
+ /** Narrow a `StreamEvent` to the canvas family. */
216
+ declare function isCanvasEvent(event: StreamEvent): event is CanvasEvent;
217
+ /** Narrow a `StreamEvent` to the chat family. */
218
+ declare function isChatEvent(event: StreamEvent): event is ChatEvent;
219
+
220
+ /**
221
+ * Element selection — a client→server concern (it rides the chat request, not
222
+ * the SSE wire). When the user clicks an element inside an `html` artifact, the
223
+ * inspector reports which element was chosen; an edit instruction then carries
224
+ * this context so the agent can make a targeted change.
225
+ */
226
+ interface ElementSelection {
227
+ /** The `html` artifact the element belongs to. */
228
+ artifactId: string;
229
+ /** Deterministic path id assigned by the inspector (e.g. "e-0-2"). */
230
+ cid: string;
231
+ /** Human/agent-readable selector, e.g. "button.cta". */
232
+ selector: string;
233
+ /** Lowercased tag name. */
234
+ tag: string;
235
+ /** Short text preview of the element. */
236
+ text?: string;
237
+ /** The element's current outer HTML (truncated) — edit context for the agent. */
238
+ outerHtml?: string;
239
+ /** Snapshot of the element's key computed styles (for the style panel). */
240
+ styles?: Record<string, string>;
241
+ /** True when the element is a group wrapper (offers "Ungroup"). */
242
+ isGroup?: boolean;
243
+ }
244
+
245
+ /**
246
+ * The reconciler — the single place artifact state is mutated.
247
+ *
248
+ * `reduceCanvas(state, event)` is a pure function: given the current canvas
249
+ * state and one canvas event, it returns the next state. The store, hooks, and
250
+ * components never branch on event `type` — they read the reconciled artifacts.
251
+ * That keeps streaming (`append`), partial updates (`patch`), and versioning
252
+ * (`replace`) auditable in one reducer.
253
+ */
254
+
255
+ interface CanvasState {
256
+ /** Current (latest-version) artifact per id. */
257
+ artifacts: Record<string, Artifact>;
258
+ /** Version snapshots per id, oldest first. Grows on `canvas.replace`. */
259
+ history: Record<string, Artifact[]>;
260
+ /** Creation order — drives tab ordering in the panel. */
261
+ order: string[];
262
+ /** The artifact the panel currently focuses. */
263
+ activeId: string | null;
264
+ }
265
+ declare function emptyCanvasState(): CanvasState;
266
+ declare function reduceCanvas(state: CanvasState, event: CanvasEvent): CanvasState;
267
+ /**
268
+ * RFC 7386 JSON Merge Patch: `null` deletes a key, plain objects merge
269
+ * recursively, everything else (arrays, scalars) replaces.
270
+ */
271
+ declare function mergePatch(target: unknown, patch: unknown): unknown;
272
+
273
+ /**
274
+ * SSE client — POST a chat message and yield parsed `StreamEvent`s.
275
+ *
276
+ * We use `fetch` + `ReadableStream` rather than the browser `EventSource`
277
+ * because the chat endpoint is a POST (EventSource is GET-only) and we want an
278
+ * `AbortSignal` for cancellation. Frames are separated by a blank line; each
279
+ * `data:` payload is one JSON `StreamEvent`.
280
+ */
281
+
282
+ interface ChatRequest {
283
+ threadId: string;
284
+ message: string;
285
+ /** Element context for a targeted edit (set when editing selected elements). */
286
+ selections?: ElementSelection[];
287
+ }
288
+ interface StreamOptions {
289
+ signal?: AbortSignal;
290
+ headers?: Record<string, string>;
291
+ }
292
+ /** Open the chat stream and yield events until the server sends `done`. */
293
+ declare function streamChat(endpoint: string, request: ChatRequest, options?: StreamOptions): AsyncGenerator<StreamEvent>;
294
+ /** Turn a byte stream of SSE frames into a stream of typed events. */
295
+ declare function parseSSE(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<StreamEvent>;
296
+
297
+ /**
298
+ * The iframe inspector — makes an `html` artifact directly editable.
299
+ *
300
+ * `withInspector(html)` injects a small, self-contained script + style into the
301
+ * page rendered inside the sandboxed iframe. That script:
302
+ *
303
+ * 1. stamps every element with a deterministic `data-cid` (a tree path like
304
+ * `e-0-2`), so a selection survives re-renders and the agent can target it;
305
+ * 2. outlines the element under the cursor on hover;
306
+ * 3. on click, marks it selected and `postMessage`s a selection payload —
307
+ * including a snapshot of its key computed styles — to the parent window;
308
+ * 4. on double-click, makes a text element `contenteditable`; on blur it posts
309
+ * the edited element back as `node_edit` (the host commits it as a
310
+ * `canvas.node_patch`);
311
+ * 5. responds to parent commands: `set_style` (apply a style live), `commit`
312
+ * (post the element's current HTML back as `node_edit`), and `clear`.
313
+ *
314
+ * The script runs inside a `sandbox="allow-scripts"` iframe with a null origin,
315
+ * so it cannot reach the parent DOM, cookies, or storage — only `postMessage`.
316
+ */
317
+ declare const INSPECTOR_MARK = "langchain-canvas";
318
+ /** Inject the inspector into an HTML string, before `</body>` when present. The
319
+ * injected nodes are tagged `data-lcx` so a full-document save can strip them.
320
+ * Also ensures a responsive viewport meta so device-width media queries behave
321
+ * the same in the preview, in export, and on a real device. */
322
+ declare function withInspector(html: string): string;
323
+ /** Computed-style properties surfaced to the style panel (camelCase). */
324
+ declare const STYLE_PROPS: readonly ["color", "backgroundColor", "fontSize", "fontWeight", "textAlign", "lineHeight", "letterSpacing", "padding", "borderRadius", "width"];
325
+
326
+ /**
327
+ * Schema-driven playback — render the canvas from a scripted list of wire
328
+ * events, with no backend, no LLM, and no API key.
329
+ *
330
+ * The canvas is defined entirely by the wire protocol (`StreamEvent`s). That
331
+ * means you can develop and demo the UI purely against the schema: hand it a
332
+ * fixture and watch it render exactly as a real LangGraph agent would drive it.
333
+ * `mockStream` turns an event array into a timed async stream, shaped identically
334
+ * to `streamChat`, so anything that consumes one consumes the other.
335
+ */
336
+
337
+ interface MockStreamOptions {
338
+ /** Delay between events, ms. Simulates streaming cadence. Default 120. */
339
+ delayMs?: number;
340
+ signal?: AbortSignal;
341
+ }
342
+ /** Yield a fixed list of events over time — a drop-in for `streamChat`. */
343
+ declare function mockStream(events: StreamEvent[], options?: MockStreamOptions): AsyncGenerator<StreamEvent>;
344
+
345
+ /**
346
+ * The canvas store — chat transcript + reconciled canvas state in one place.
347
+ *
348
+ * This is a *factory*, not a singleton: `createCanvasStore()` returns an
349
+ * isolated store so an app can host several independent canvas/chat instances.
350
+ * `<CanvasProvider>` (see `context.tsx`) wires one up; provider-less apps share a
351
+ * lazily-created default store, keeping the simple API working.
352
+ *
353
+ * Every wire event flows through `applyEvent` → the pure `reduceCanvas` reducer
354
+ * for canvas events, folded into `messages` for chat events, so streaming,
355
+ * patching, and versioning stay in one auditable place.
356
+ */
357
+
358
+ interface ChatMessage {
359
+ id: string;
360
+ role: "user" | "assistant";
361
+ text: string;
362
+ /** Artifact ids this assistant message produced — drives inline artifact cards. */
363
+ artifactIds?: string[];
364
+ }
365
+ /** A command the editing UI forwards to the active html artifact's iframe. */
366
+ interface IframeCommand {
367
+ artifactId: string;
368
+ /** style · structure (duplicate/delete/move/insert/insert_html) · group/ungroup · set_src · clear. */
369
+ type: "set_style" | "commit" | "clear" | "set_src" | "duplicate" | "delete" | "move_up" | "move_down" | "insert" | "insert_html" | "group" | "ungroup";
370
+ /** Target element (omitted for document-level inserts with no selection). */
371
+ cid?: string;
372
+ /** Members to wrap for `group`. */
373
+ cids?: string[];
374
+ prop?: string;
375
+ value?: string;
376
+ /** Tag/block to insert for `insert` (e.g. "h2", "p", "button", "img", "hr", "section"). */
377
+ block?: string;
378
+ /** HTML fragment to insert for `insert_html` (a built-in section template). */
379
+ html?: string;
380
+ /** Monotonic counter so re-issuing an identical command still fires. */
381
+ seq: number;
382
+ }
383
+ interface CanvasStore {
384
+ canvas: CanvasState;
385
+ messages: ChatMessage[];
386
+ isStreaming: boolean;
387
+ error: string | null;
388
+ /** Elements the user selected inside an `html` artifact (click = 1, marquee = N). */
389
+ selections: ElementSelection[];
390
+ /** Last command forwarded to the html iframe (style panel → renderer bus). */
391
+ iframeCommand: IframeCommand | null;
392
+ /** Snapshots for undo/redo — only user edits are recorded (not agent streaming). */
393
+ undoStack: CanvasState[];
394
+ redoStack: CanvasState[];
395
+ applyEvent: (event: StreamEvent) => void;
396
+ /** Apply a batch of events in a single store write (one re-render per frame). */
397
+ applyEvents: (events: StreamEvent[]) => void;
398
+ /** Apply a *user*-initiated event, recording a snapshot so it can be undone. */
399
+ applyUserEvent: (event: StreamEvent) => void;
400
+ undo: () => void;
401
+ redo: () => void;
402
+ addUserMessage: (text: string) => void;
403
+ setStreaming: (value: boolean) => void;
404
+ setActiveArtifact: (id: string) => void;
405
+ setSelections: (selections: ElementSelection[]) => void;
406
+ sendIframeCommand: (command: Omit<IframeCommand, "seq">) => void;
407
+ reset: () => void;
408
+ }
409
+ /** Create an isolated canvas store. */
410
+ declare function createCanvasStore(): StoreApi<CanvasStore>;
411
+
412
+ interface CanvasProviderProps {
413
+ children: ReactNode;
414
+ /** Bring your own store (e.g. shared across trees); one is created otherwise. */
415
+ store?: StoreApi<CanvasStore>;
416
+ }
417
+ declare function CanvasProvider({ children, store }: CanvasProviderProps): react.JSX.Element;
418
+ /** The raw store API for the nearest provider (or the default store). */
419
+ declare function useCanvasStoreApi(): StoreApi<CanvasStore>;
420
+ /** Subscribe to a slice of the canvas store. */
421
+ declare function useCanvasStore<T>(selector: (state: CanvasStore) => T): T;
422
+
423
+ interface UseCanvasStreamOptions {
424
+ /** Chat SSE endpoint. Defaults to `/api/chat`. */
425
+ endpoint?: string;
426
+ /** Conversation thread id (for server-side memory). Defaults to a fresh uuid. */
427
+ threadId?: string;
428
+ /**
429
+ * Offline mock: given the user's message, return a scripted `StreamEvent[]`
430
+ * to play instead of hitting the network — an OpenAPI-style "try it" with no
431
+ * real LLM call. Return `null` to fall through to the live endpoint.
432
+ */
433
+ mock?: (message: string) => StreamEvent[] | null;
434
+ }
435
+ declare function useCanvasStream(options?: UseCanvasStreamOptions): {
436
+ sendMessage: (text: string, withSelections?: ElementSelection[]) => Promise<void>;
437
+ stop: () => void | undefined;
438
+ reset: () => void;
439
+ setActiveArtifact: (id: string) => void;
440
+ selections: ElementSelection[];
441
+ editSelection: (instruction: string) => void;
442
+ clearSelection: () => void;
443
+ messages: ChatMessage[];
444
+ canvas: CanvasState;
445
+ isStreaming: boolean;
446
+ error: string | null;
447
+ threadId: string;
448
+ };
449
+
450
+ declare function useCanvasReplay(): {
451
+ play: (events: StreamEvent[], options?: MockStreamOptions) => Promise<void>;
452
+ stop: () => void | undefined;
453
+ reset: () => void;
454
+ canvas: CanvasState;
455
+ isPlaying: boolean;
456
+ };
457
+
458
+ /**
459
+ * `useArtifactPatch` — let a renderer commit an inline edit back to the store.
460
+ *
461
+ * Editing an artifact on the canvas is just a client-side `canvas.patch`: it
462
+ * flows through the exact same reconciler an agent's edits do, so the edited
463
+ * value is the one that renders, versions, and exports. Renderers stay in sync
464
+ * with the single source of truth instead of holding a private copy.
465
+ */
466
+ declare function useArtifactPatch(id: string): (patch: Record<string, unknown>) => void;
467
+
468
+ /**
469
+ * Schema fixtures — scripted wire-event sequences that render the canvas with no
470
+ * backend. Feed one to `useCanvasReplay().play(scenario.events)`.
471
+ *
472
+ * Each scenario is nothing but `StreamEvent`s: exactly what a LangGraph agent
473
+ * would emit over the wire. They double as living documentation of the protocol
474
+ * and as a zero-dependency way to develop renderers.
475
+ */
476
+
477
+ interface Scenario {
478
+ id: string;
479
+ title: string;
480
+ description: string;
481
+ events: StreamEvent[];
482
+ }
483
+ declare const scenarios: Scenario[];
484
+
485
+ interface RendererProps<TData = unknown> {
486
+ artifact: Artifact<TData>;
487
+ }
488
+ type ArtifactRenderer = ComponentType<RendererProps<any>>;
489
+ type ArtifactRegistry = Record<string, ArtifactRenderer>;
490
+ interface CanvasRegistryProviderProps {
491
+ registry: ArtifactRegistry;
492
+ children: ReactNode;
493
+ }
494
+ declare function CanvasRegistryProvider({ registry, children }: CanvasRegistryProviderProps): react.JSX.Element;
495
+ /** Resolve the renderer for an artifact type, or `undefined` if unregistered. */
496
+ declare function useRenderer(type: string): ArtifactRenderer | undefined;
497
+ /** Merge registries — later entries win. Handy for extending the built-ins. */
498
+ declare function mergeRegistries(...registries: ArtifactRegistry[]): ArtifactRegistry;
499
+
500
+ interface CanvasProps {
501
+ /** Renderer map. Defaults to the built-in html/document/chart/table renderers. */
502
+ registry?: ArtifactRegistry;
503
+ /** Rendered when no artifact has been opened yet. */
504
+ emptyState?: ReactNode;
505
+ /**
506
+ * Handle a targeted edit of the selected element (from `useCanvasStream`'s
507
+ * `editSelection`). When provided, clicking an element in an `html` artifact
508
+ * reveals a quick-edit bar.
509
+ */
510
+ onEditElement?: (instruction: string) => void;
511
+ }
512
+ declare function Canvas({ registry, emptyState, onEditElement }: CanvasProps): react.JSX.Element;
513
+
514
+ interface ExportMenuProps {
515
+ artifact: Artifact;
516
+ getRenderedHtml: () => string | null;
517
+ }
518
+ declare function ExportMenu({ artifact, getRenderedHtml }: ExportMenuProps): react.JSX.Element;
519
+
520
+ interface SelectionBarProps {
521
+ selections: ElementSelection[];
522
+ onEdit: (instruction: string) => void;
523
+ onClear: () => void;
524
+ }
525
+ declare function SelectionBar({ selections, onEdit, onClear }: SelectionBarProps): react.JSX.Element;
526
+
527
+ declare function StylePanel({ selection }: {
528
+ selection: ElementSelection;
529
+ }): react.JSX.Element;
530
+
531
+ /**
532
+ * `<ArtifactCard>` — an inline reference to an artifact, for the chat transcript.
533
+ *
534
+ * Assistant messages carry the ids of the artifacts they produced
535
+ * (`message.artifactIds`); render a card per id under the bubble so the artifact
536
+ * shows up *in the conversation* (like ChatGPT), and clicking it focuses that
537
+ * artifact in the `<Canvas />` panel.
538
+ */
539
+ declare function ArtifactCard({ artifactId }: {
540
+ artifactId: string;
541
+ }): react.JSX.Element | null;
542
+
543
+ declare function SlidesRenderer$1({ artifact }: RendererProps<SlidesData>): react.JSX.Element;
544
+
545
+ declare function TableRenderer$1({ artifact }: RendererProps<TableData>): react.JSX.Element;
546
+
547
+ declare function DocumentRenderer$1({ artifact }: RendererProps<DocumentData>): react.JSX.Element;
548
+
549
+ declare function ChartRenderer$1({ artifact }: RendererProps<ChartData>): react.JSX.Element;
550
+
551
+ declare function HtmlRenderer({ artifact }: RendererProps<HtmlData>): react.JSX.Element;
552
+
553
+ declare const ChartRenderer: react.LazyExoticComponent<typeof ChartRenderer$1>;
554
+ declare const DocumentRenderer: react.LazyExoticComponent<typeof DocumentRenderer$1>;
555
+ declare const TableRenderer: react.LazyExoticComponent<typeof TableRenderer$1>;
556
+ declare const SlidesRenderer: react.LazyExoticComponent<typeof SlidesRenderer$1>;
557
+
558
+ /**
559
+ * The batteries-included renderers. `html` is the base substrate (sandboxed
560
+ * iframe); the rest are structured conveniences, lazily loaded. Pass to
561
+ * `<Canvas registry />` or merge with your own. They render under `<Canvas>`'s
562
+ * Suspense boundary, so the on-demand chunks resolve transparently.
563
+ */
564
+ declare const builtinRenderers: ArtifactRegistry;
565
+
566
+ /** Browser download helpers — trigger a file save from an in-memory string. */
567
+ /** Save `content` as a file named `filename` with the given MIME type. */
568
+ declare function downloadBlob(filename: string, mime: string, content: BlobPart): void;
569
+ /** Turn a title into a safe file stem: "Q1 Report!" -> "q1-report". */
570
+ declare function slugify(text: string): string;
571
+
572
+ /**
573
+ * Artifact → file exporters.
574
+ *
575
+ * Two kinds of export:
576
+ *
577
+ * 1. **HTML** (`toStandaloneHtml`) — wrap the *rendered* DOM of any artifact into
578
+ * a self-contained `.html` document with inlined styles.
579
+ * 2. **Data exporters** (`dataExporters`) — deterministic, per-type conversions
580
+ * straight from `artifact.data`: markdown `.md`, table `.csv`/`.xlsx`,
581
+ * document `.docx`, slides `.pptx`, raw `.json`.
582
+ *
583
+ * Office formats (xlsx / docx / pptx) are produced with `exceljs` / `docx` /
584
+ * `pptxgenjs`, loaded via **dynamic import** so they never touch the main
585
+ * bundle — only the code path a user actually clicks pulls them in.
586
+ */
587
+
588
+ interface FileExport {
589
+ /** Menu label, e.g. "Excel". */
590
+ label: string;
591
+ /** File extension without the dot, e.g. "xlsx". */
592
+ extension: string;
593
+ mime: string;
594
+ /** Build the file contents (text or binary; may be async for Office formats). */
595
+ build: (artifact: Artifact) => BlobPart | Promise<BlobPart>;
596
+ }
597
+ /** Per-type data exporters, keyed by `artifact.type`. */
598
+ declare const dataExporters: Record<string, FileExport[]>;
599
+ /** Wrap already-rendered inner HTML into a standalone, styled `.html` document. */
600
+ declare function toStandaloneHtml(title: string, renderedHtml: string): string;
601
+ /**
602
+ * A print-ready HTML document with one landscape page per slide — fed to the
603
+ * browser's print pipeline to produce a multi-page PDF. Elements keep their
604
+ * percentage geometry, so pages match the on-canvas layout exactly.
605
+ */
606
+ declare function slidesToPrintHtml(data: SlidesData, title: string): string;
607
+
608
+ /**
609
+ * PDF export via the browser's own print pipeline — zero dependencies, and the
610
+ * output is pixel-faithful to what the canvas renders (the browser is the best
611
+ * HTML→PDF engine there is).
612
+ *
613
+ * We write the standalone HTML into an offscreen iframe and trigger `print()`
614
+ * on it; the user picks "Save as PDF" in the print dialog. Using an iframe (not
615
+ * a popup) avoids popup blockers and never navigates the host page away.
616
+ */
617
+ /**
618
+ * Print an HTML document to PDF through an offscreen iframe.
619
+ *
620
+ * Security: the export HTML may be untrusted (LLM-generated or imported), so the
621
+ * frame is **sandboxed without `allow-scripts`** — scripts, `onerror`, `onload`,
622
+ * etc. never execute, so nothing can run in the host origin. `allow-same-origin`
623
+ * (safe here precisely because scripts are disabled) lets us call `print()` on
624
+ * the frame; `allow-modals` permits the print dialog. `srcdoc` is used instead of
625
+ * `document.write` so the content is parsed inertly.
626
+ */
627
+ declare function printToPdf(html: string): void;
628
+
629
+ /**
630
+ * File → artifact importers — the inverse of `export/exporters.ts`.
631
+ *
632
+ * `langchain-canvas` isn't only a viewer for agent output: you can open a real
633
+ * file and edit it on the canvas, then export it back out (round-trip). Each
634
+ * importer maps a file to a `canvas.create` + `canvas.status: complete` event
635
+ * pair, so an opened file flows through the exact same reconciler path an
636
+ * agent's stream would — no special-casing downstream.
637
+ *
638
+ * Dependency policy mirrors the exporters: text formats (csv / md / html / json)
639
+ * are parsed inline with zero dependencies; `.xlsx` reuses `exceljs`, loaded via
640
+ * dynamic import so it never touches the main bundle.
641
+ */
642
+
643
+ /** Extensions we can turn into an artifact, for `accept="…"` and drop filtering. */
644
+ declare const IMPORTABLE_EXTENSIONS: readonly [".csv", ".md", ".markdown", ".txt", ".html", ".htm", ".json", ".xlsx"];
645
+ /** True when the file has an extension we know how to import. */
646
+ declare const canImport: (file: File) => boolean;
647
+ /**
648
+ * Parse a file into canvas events. Rejects if the extension is unsupported so
649
+ * callers can surface a clear message. Text parsing is synchronous; `.xlsx`
650
+ * awaits its dynamic import.
651
+ */
652
+ declare function importFile(file: File): Promise<StreamEvent[]>;
653
+ /** RFC-4180-ish CSV parser: handles quoted fields, embedded commas, and "" escapes. */
654
+ declare function parseCsv(text: string): TableData;
655
+
656
+ /**
657
+ * `useCanvasImport` — open local files onto the canvas.
658
+ *
659
+ * Turns a `File` (from a file picker or a drag-and-drop) into canvas events and
660
+ * applies them through the store, so the imported document/sheet/page becomes a
661
+ * first-class artifact you can edit and re-export. Returns the id of the last
662
+ * artifact created so callers can focus it.
663
+ */
664
+ declare function useCanvasImport(): {
665
+ importFiles: (files: Iterable<File>) => Promise<string | null>;
666
+ canImport: (file: File) => boolean;
667
+ };
668
+
669
+ export { type Artifact, ArtifactCard, type ArtifactRegistry, type ArtifactRenderer, type ArtifactStatus, Canvas, type CanvasAppend, type CanvasClose, type CanvasCreate, type CanvasEvent, type CanvasNodePatch, type CanvasPatch, type CanvasProps, CanvasProvider, type CanvasProviderProps, CanvasRegistryProvider, type CanvasReplace, type CanvasState, type CanvasStatus, type CanvasStore, type ChartArtifact, type ChartData, type ChartOptions, ChartRenderer, type ChartSeries, type ChatEvent, type ChatMessage, type ChatRequest, type DocumentArtifact, type DocumentData, DocumentRenderer, type DoneEvent, type ElementSelection, type ErrorEvent, ExportMenu, type FileExport, type HtmlArtifact, type HtmlData, HtmlRenderer, IMPORTABLE_EXTENSIONS, INSPECTOR_MARK, type IframeCommand, type KnownArtifact, type MessageDelta, type MessageEnd, type MockStreamOptions, type RendererProps, STYLE_PROPS, type Scenario, SelectionBar, type Slide, type SlideElement, type SlidesArtifact, type SlidesData, SlidesRenderer, type StreamEvent, type StreamOptions, StylePanel, type TableArtifact, type TableColumn, type TableData, TableRenderer, type ToolEnd, type ToolStart, type UseCanvasStreamOptions, builtinRenderers, canImport, createCanvasStore, dataExporters, downloadBlob, emptyCanvasState, importFile, isCanvasEvent, isChatEvent, mergePatch, mergeRegistries, mockStream, parseCsv, parseSSE, printToPdf, reduceCanvas, scenarios, slidesToPrintHtml, slugify, streamChat, toStandaloneHtml, useArtifactPatch, useCanvasImport, useCanvasReplay, useCanvasStore, useCanvasStoreApi, useCanvasStream, useRenderer, withInspector };