@braincrew-lab/langchain-canvas 0.1.7 → 0.1.8

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.
@@ -1,5 +1,5 @@
1
- import { useArtifactPatch } from './chunk-HHJWIO2C.js';
2
- import './chunk-PSIT32I5.js';
1
+ import { useArtifactPatch } from './chunk-TERWLUW3.js';
2
+ import './chunk-KKLWKR5G.js';
3
3
  import { useState, useMemo, useRef, useEffect } from 'react';
4
4
  import * as echarts from 'echarts/core';
5
5
  import { BarChart, LineChart, PieChart } from 'echarts/charts';
@@ -1,5 +1,5 @@
1
- import { useArtifactPatch } from './chunk-HHJWIO2C.js';
2
- import './chunk-PSIT32I5.js';
1
+ import { useArtifactPatch } from './chunk-TERWLUW3.js';
2
+ import './chunk-KKLWKR5G.js';
3
3
  import { useState } from 'react';
4
4
  import ReactMarkdown from 'react-markdown';
5
5
  import remarkGfm from 'remark-gfm';
@@ -1,6 +1,6 @@
1
1
  import { resolveElements } from './chunk-6L3AL6W4.js';
2
- import { useArtifactPatch } from './chunk-HHJWIO2C.js';
3
- import './chunk-PSIT32I5.js';
2
+ import { useArtifactPatch } from './chunk-TERWLUW3.js';
3
+ import './chunk-KKLWKR5G.js';
4
4
  import { useState, useRef, useEffect } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
 
@@ -1,5 +1,5 @@
1
1
  import { loadOptional } from './chunk-YZZSJJMQ.js';
2
- import { useCanvasStore } from './chunk-PSIT32I5.js';
2
+ import { useCanvasStore } from './chunk-KKLWKR5G.js';
3
3
  import { lazy, useMemo, useState, useRef, useEffect, useCallback, Suspense } from 'react';
4
4
  import '@fortune-sheet/react/dist/index.css';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -208,7 +208,7 @@ function TableRenderer({ artifact }) {
208
208
  // eslint-disable-next-line react-hooks/exhaustive-deps
209
209
  [dataKey, formulasReady]
210
210
  );
211
- const applyEvent = useCanvasStore((s) => s.applyEvent);
211
+ const applyEvent = useCanvasStore((s) => s.applyUserEvent);
212
212
  const persistTimer = useRef(null);
213
213
  const handleChange = useCallback(
214
214
  (sheets) => {
@@ -129,6 +129,19 @@ function lastOf(order, excludeId) {
129
129
  const remaining = order.filter((id) => id !== excludeId);
130
130
  return remaining.length ? remaining[remaining.length - 1] : null;
131
131
  }
132
+ function editedArtifactId(event) {
133
+ switch (event.type) {
134
+ case "canvas.create":
135
+ case "canvas.replace":
136
+ return event.artifact.id;
137
+ case "canvas.append":
138
+ case "canvas.patch":
139
+ case "canvas.node_patch":
140
+ return event.id;
141
+ default:
142
+ return null;
143
+ }
144
+ }
132
145
  var initialState = () => ({
133
146
  canvas: emptyCanvasState(),
134
147
  messages: [],
@@ -137,17 +150,24 @@ var initialState = () => ({
137
150
  selections: [],
138
151
  iframeCommand: null,
139
152
  undoStack: [],
140
- redoStack: []
153
+ redoStack: [],
154
+ onUserEdit: null
141
155
  });
142
156
  function createCanvasStore() {
143
- return createStore((set) => ({
157
+ return createStore((set, get) => ({
144
158
  ...initialState(),
145
159
  applyEvent: (event) => set((state) => foldEvent(state, event)),
146
160
  applyEvents: (events) => set((state) => events.reduce(foldEvent, state)),
147
- applyUserEvent: (event) => set((state) => {
148
- const undoStack = [...state.undoStack, state.canvas].slice(-50);
149
- return { ...foldEvent(state, event), undoStack, redoStack: [] };
150
- }),
161
+ applyUserEvent: (event) => {
162
+ set((state2) => {
163
+ const undoStack = [...state2.undoStack, state2.canvas].slice(-50);
164
+ return { ...foldEvent(state2, event), undoStack, redoStack: [] };
165
+ });
166
+ const state = get();
167
+ const id = editedArtifactId(event);
168
+ const artifact = id ? state.canvas.artifacts[id] : void 0;
169
+ if (artifact) state.onUserEdit?.(artifact);
170
+ },
151
171
  undo: () => set((state) => {
152
172
  if (!state.undoStack.length) return state;
153
173
  const previous = state.undoStack[state.undoStack.length - 1];
@@ -176,6 +196,7 @@ function createCanvasStore() {
176
196
  setActiveArtifact: (id) => set((state) => ({ canvas: { ...state.canvas, activeId: id } })),
177
197
  setSelections: (selections) => set({ selections }),
178
198
  sendIframeCommand: (command) => set((state) => ({ iframeCommand: { ...command, seq: (state.iframeCommand?.seq ?? 0) + 1 } })),
199
+ setOnUserEdit: (handler) => set({ onUserEdit: handler }),
179
200
  reset: () => set(initialState())
180
201
  }));
181
202
  }
@@ -1,4 +1,4 @@
1
- import { useCanvasStore } from './chunk-PSIT32I5.js';
1
+ import { useCanvasStore } from './chunk-KKLWKR5G.js';
2
2
  import { useCallback } from 'react';
3
3
 
4
4
  function useArtifactPatch(id) {
package/dist/index.d.ts CHANGED
@@ -355,6 +355,10 @@ declare function mockStream(events: StreamEvent[], options?: MockStreamOptions):
355
355
  * patching, and versioning stay in one auditable place.
356
356
  */
357
357
 
358
+ /** Fired when the *user* edits an artifact in the canvas (a table cell, a chart
359
+ * value, document text, a slide/HTML element). The host wires this to sync the
360
+ * edit back to the agent/backend so the next turn sees it. */
361
+ type UserEditHandler = (artifact: Artifact) => void;
358
362
  interface ChatMessage {
359
363
  id: string;
360
364
  role: "user" | "assistant";
@@ -392,6 +396,8 @@ interface CanvasStore {
392
396
  /** Snapshots for undo/redo — only user edits are recorded (not agent streaming). */
393
397
  undoStack: CanvasState[];
394
398
  redoStack: CanvasState[];
399
+ /** Host callback fired after a user edit reconciles — the write-back hook. */
400
+ onUserEdit: UserEditHandler | null;
395
401
  applyEvent: (event: StreamEvent) => void;
396
402
  /** Apply a batch of events in a single store write (one re-render per frame). */
397
403
  applyEvents: (events: StreamEvent[]) => void;
@@ -404,6 +410,8 @@ interface CanvasStore {
404
410
  setActiveArtifact: (id: string) => void;
405
411
  setSelections: (selections: ElementSelection[]) => void;
406
412
  sendIframeCommand: (command: Omit<IframeCommand, "seq">) => void;
413
+ /** Register (or clear) the user-edit write-back handler. */
414
+ setOnUserEdit: (handler: UserEditHandler | null) => void;
407
415
  reset: () => void;
408
416
  }
409
417
  /** Create an isolated canvas store. */
@@ -508,8 +516,16 @@ interface CanvasProps {
508
516
  * reveals a quick-edit bar.
509
517
  */
510
518
  onEditElement?: (instruction: string) => void;
519
+ /**
520
+ * Fired after the *user* edits an artifact directly in the canvas — a table
521
+ * cell, a chart value, document text, a slide/HTML element — with the
522
+ * reconciled artifact. Wire this to sync the edit back to the agent/backend so
523
+ * the next turn sees it. Fires per committed edit (table edits are debounced);
524
+ * debounce further on the host before hitting the network.
525
+ */
526
+ onUserEdit?: (artifact: Artifact) => void;
511
527
  }
512
- declare function Canvas({ registry, emptyState, onEditElement }: CanvasProps): react.JSX.Element;
528
+ declare function Canvas({ registry, emptyState, onEditElement, onUserEdit }: CanvasProps): react.JSX.Element;
513
529
 
514
530
  interface ExportMenuProps {
515
531
  artifact: Artifact;
@@ -666,4 +682,4 @@ declare function useCanvasImport(): {
666
682
  canImport: (file: File) => boolean;
667
683
  };
668
684
 
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 };
685
+ 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, type UserEditHandler, 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 };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { loadOptional } from './chunk-YZZSJJMQ.js';
3
3
  import { resolveElements } from './chunk-6L3AL6W4.js';
4
- export { useArtifactPatch } from './chunk-HHJWIO2C.js';
5
- import { useCanvasStoreApi, useCanvasStore } from './chunk-PSIT32I5.js';
6
- export { CanvasProvider, createCanvasStore, emptyCanvasState, isCanvasEvent, isChatEvent, mergePatch, reduceCanvas, useCanvasStore, useCanvasStoreApi } from './chunk-PSIT32I5.js';
4
+ export { useArtifactPatch } from './chunk-TERWLUW3.js';
5
+ import { useCanvasStoreApi, useCanvasStore } from './chunk-KKLWKR5G.js';
6
+ export { CanvasProvider, createCanvasStore, emptyCanvasState, isCanvasEvent, isChatEvent, mergePatch, reduceCanvas, useCanvasStore, useCanvasStoreApi } from './chunk-KKLWKR5G.js';
7
7
  import { createContext, lazy, useRef, useCallback, useEffect, useContext, useState, useMemo, Suspense, Component } from 'react';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
 
@@ -1738,10 +1738,10 @@ function HtmlRenderer({ artifact: artifact2 }) {
1738
1738
  }
1739
1739
 
1740
1740
  // src/components/renderers/index.ts
1741
- var ChartRenderer = lazy(() => import('./ChartRenderer-CKCJ2LQX.js').then((m) => ({ default: m.ChartRenderer })));
1742
- var DocumentRenderer = lazy(() => import('./DocumentRenderer-7HP3YQUK.js').then((m) => ({ default: m.DocumentRenderer })));
1743
- var TableRenderer = lazy(() => import('./TableRenderer-TRYSMQA7.js').then((m) => ({ default: m.TableRenderer })));
1744
- var SlidesRenderer = lazy(() => import('./SlidesRenderer-KFSPD63I.js').then((m) => ({ default: m.SlidesRenderer })));
1741
+ var ChartRenderer = lazy(() => import('./ChartRenderer-4MWKP2J4.js').then((m) => ({ default: m.ChartRenderer })));
1742
+ var DocumentRenderer = lazy(() => import('./DocumentRenderer-LJGP6N7E.js').then((m) => ({ default: m.DocumentRenderer })));
1743
+ var TableRenderer = lazy(() => import('./TableRenderer-ZF7MVA7I.js').then((m) => ({ default: m.TableRenderer })));
1744
+ var SlidesRenderer = lazy(() => import('./SlidesRenderer-A5HX4MOA.js').then((m) => ({ default: m.SlidesRenderer })));
1745
1745
  var builtinRenderers = {
1746
1746
  html: HtmlRenderer,
1747
1747
  document: DocumentRenderer,
@@ -2362,17 +2362,22 @@ function useCanvasImport() {
2362
2362
  return { importFiles, canImport };
2363
2363
  }
2364
2364
  var ACCEPT = IMPORTABLE_EXTENSIONS.join(",");
2365
- function Canvas({ registry = builtinRenderers, emptyState, onEditElement }) {
2366
- return /* @__PURE__ */ jsx(CanvasRegistryProvider, { registry, children: /* @__PURE__ */ jsx(CanvasPanel, { emptyState, onEditElement }) });
2365
+ function Canvas({ registry = builtinRenderers, emptyState, onEditElement, onUserEdit }) {
2366
+ return /* @__PURE__ */ jsx(CanvasRegistryProvider, { registry, children: /* @__PURE__ */ jsx(CanvasPanel, { emptyState, onEditElement, onUserEdit }) });
2367
2367
  }
2368
- function CanvasPanel({ emptyState, onEditElement }) {
2368
+ function CanvasPanel({ emptyState, onEditElement, onUserEdit }) {
2369
2369
  const { artifacts, order, activeId } = useCanvasStore((s) => s.canvas);
2370
2370
  const history = useCanvasStore((s) => s.canvas.history);
2371
2371
  const setActive = useCanvasStore((s) => s.setActiveArtifact);
2372
2372
  const selections = useCanvasStore((s) => s.selections);
2373
2373
  const setSelections = useCanvasStore((s) => s.setSelections);
2374
+ const setOnUserEdit = useCanvasStore((s) => s.setOnUserEdit);
2374
2375
  const { importFiles } = useCanvasImport();
2375
2376
  const [dropping, setDropping] = useState(false);
2377
+ useEffect(() => {
2378
+ setOnUserEdit(onUserEdit ?? null);
2379
+ return () => setOnUserEdit(null);
2380
+ }, [onUserEdit, setOnUserEdit]);
2376
2381
  useEffect(() => {
2377
2382
  if (!selections.length) return;
2378
2383
  const onKey = (e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@braincrew-lab/langchain-canvas",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A live canvas for LangChain agents — stream documents, charts, and rich artifacts into a React panel.",
5
5
  "license": "MIT",
6
6
  "type": "module",