@braincrew-lab/langchain-canvas 0.7.4 → 0.7.6
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/{DocumentRenderer-ER5TSNA6.js → DocumentRenderer-ZGJXDVKG.js} +2 -2
- package/dist/{DocxPreview-QK4K5427.js → DocxPreview-NGT3Z5KW.js} +116 -1
- package/dist/{FileRenderer-W2CR7BI2.js → FileRenderer-TZSZVVLY.js} +3 -3
- package/dist/{SlidesRenderer-AHE5ANBZ.js → SlidesRenderer-4QWZVWWD.js} +2 -2
- package/dist/chunk-ASMMPDYS.js +30 -0
- package/dist/{chunk-HCF2DXCR.js → chunk-HCOQ6XCQ.js} +1 -1
- package/dist/{chunk-7T5DRR3F.js → chunk-HMYM6BTB.js} +4 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.js +19 -14
- package/dist/langgraph/index.d.ts +3 -4
- package/dist/langgraph/index.js +3 -13
- package/dist/styles.css +1 -0
- package/dist/{types-CzJ4zeUR.d.ts → types-CKgpjs_G.d.ts} +28 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useAssetUrl } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
import { useAssetUrl } from './chunk-HCOQ6XCQ.js';
|
|
2
|
+
import './chunk-HMYM6BTB.js';
|
|
3
3
|
import { useArtifactPatch } from './chunk-N5JW2BKI.js';
|
|
4
4
|
import './chunk-RAPTQ6VH.js';
|
|
5
5
|
import { useState, useRef } from 'react';
|
|
@@ -141,6 +141,107 @@ function docxStats(root) {
|
|
|
141
141
|
substitutedFonts: substitutedFonts(root)
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
|
+
|
|
145
|
+
// src/io/symbolBullets.ts
|
|
146
|
+
var SYMBOL_FONT_BULLETS = {
|
|
147
|
+
symbol: {
|
|
148
|
+
61623: "\u2022"
|
|
149
|
+
// • bullet — Word's default list bullet
|
|
150
|
+
},
|
|
151
|
+
wingdings: {
|
|
152
|
+
61548: "\u25CF",
|
|
153
|
+
// ● black circle
|
|
154
|
+
61549: "\u274D",
|
|
155
|
+
// ❍ shadowed white circle
|
|
156
|
+
61550: "\u25A0",
|
|
157
|
+
// ■ black square
|
|
158
|
+
61551: "\u25A1",
|
|
159
|
+
// □ white square
|
|
160
|
+
61553: "\u2751",
|
|
161
|
+
// ❑ lower-right shadowed white square
|
|
162
|
+
61557: "\u25C6",
|
|
163
|
+
// ◆ black diamond
|
|
164
|
+
61607: "\u25AA",
|
|
165
|
+
// ▪ black small square
|
|
166
|
+
61656: "\u27A2",
|
|
167
|
+
// ➢ three-d top-lighted right arrowhead
|
|
168
|
+
61692: "\u2714",
|
|
169
|
+
// ✔ heavy check mark
|
|
170
|
+
61694: "\u2611"
|
|
171
|
+
// ☑ ballot box with check
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
function isPrivateUse(codePoint) {
|
|
175
|
+
return codePoint >= 57344 && codePoint <= 63743;
|
|
176
|
+
}
|
|
177
|
+
function primaryFont(fontFamily) {
|
|
178
|
+
const first = fontFamily.split(",")[0] ?? "";
|
|
179
|
+
return first.trim().replace(/^['"]|['"]$/g, "").toLowerCase();
|
|
180
|
+
}
|
|
181
|
+
function standardBullet(codePoint, fontFamily) {
|
|
182
|
+
const table = SYMBOL_FONT_BULLETS[primaryFont(fontFamily)];
|
|
183
|
+
return table?.[codePoint] ?? null;
|
|
184
|
+
}
|
|
185
|
+
function drawnOnPage(root, selectorText) {
|
|
186
|
+
return selectorText.split(",").some((part) => {
|
|
187
|
+
const base = part.trim().replace(/::?(before|after)\s*$/i, "").trim();
|
|
188
|
+
if (!base) return false;
|
|
189
|
+
try {
|
|
190
|
+
return root.querySelector(base) !== null;
|
|
191
|
+
} catch {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
function styleRules(sheet) {
|
|
197
|
+
const found = [];
|
|
198
|
+
const stack = [...sheet.cssRules];
|
|
199
|
+
while (stack.length) {
|
|
200
|
+
const rule = stack.pop();
|
|
201
|
+
if (rule.cssRules?.length) {
|
|
202
|
+
stack.push(...rule.cssRules);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (rule.style && rule.selectorText) found.push(rule);
|
|
206
|
+
}
|
|
207
|
+
return found;
|
|
208
|
+
}
|
|
209
|
+
function restoreSymbolBullets(root) {
|
|
210
|
+
const swaps = [];
|
|
211
|
+
for (const style of Array.from(root.querySelectorAll("style"))) {
|
|
212
|
+
let rules;
|
|
213
|
+
try {
|
|
214
|
+
rules = style.sheet ? styleRules(style.sheet) : [];
|
|
215
|
+
} catch {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
for (const rule of rules) {
|
|
219
|
+
const content = rule.style.getPropertyValue("content");
|
|
220
|
+
if (!content) continue;
|
|
221
|
+
const font = rule.style.getPropertyValue("font-family");
|
|
222
|
+
if (!font) continue;
|
|
223
|
+
if (!drawnOnPage(root, rule.selectorText)) continue;
|
|
224
|
+
let next = "";
|
|
225
|
+
let changed = false;
|
|
226
|
+
for (const character of content) {
|
|
227
|
+
const code = character.codePointAt(0) ?? 0;
|
|
228
|
+
const standard = isPrivateUse(code) ? standardBullet(code, font) : null;
|
|
229
|
+
if (standard === null) {
|
|
230
|
+
next += character;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
next += standard;
|
|
234
|
+
changed = true;
|
|
235
|
+
swaps.push({ from: character, to: standard, font: primaryFont(font) });
|
|
236
|
+
}
|
|
237
|
+
if (changed) rule.style.setProperty("content", next);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return swaps;
|
|
241
|
+
}
|
|
242
|
+
function redrawnFonts(swaps) {
|
|
243
|
+
return [...new Set(swaps.map((swap) => swap.font))];
|
|
244
|
+
}
|
|
144
245
|
var BANNER = "Preview only \u2014 to change it, ask in chat or select some text.";
|
|
145
246
|
function DocxPreview({
|
|
146
247
|
artifactId,
|
|
@@ -151,6 +252,7 @@ function DocxPreview({
|
|
|
151
252
|
const hostRef = useRef(null);
|
|
152
253
|
const [status, setStatus] = useState("loading");
|
|
153
254
|
const [stats, setStats] = useState(null);
|
|
255
|
+
const [redrawn, setRedrawn] = useState([]);
|
|
154
256
|
const [picked, setPicked] = useState(null);
|
|
155
257
|
const setSelections = useCanvasStore((s) => s.setSelections);
|
|
156
258
|
useEffect(() => {
|
|
@@ -160,6 +262,7 @@ function DocxPreview({
|
|
|
160
262
|
if (!host) return;
|
|
161
263
|
setStatus("loading");
|
|
162
264
|
setStats(null);
|
|
265
|
+
setRedrawn([]);
|
|
163
266
|
setPicked(null);
|
|
164
267
|
(async () => {
|
|
165
268
|
const { renderAsync } = await loadOptional(
|
|
@@ -181,6 +284,7 @@ function DocxPreview({
|
|
|
181
284
|
});
|
|
182
285
|
if (!live) return;
|
|
183
286
|
stampDocxAddresses(host);
|
|
287
|
+
setRedrawn(redrawnFonts(restoreSymbolBullets(host)));
|
|
184
288
|
setStats(docxStats(host));
|
|
185
289
|
setStatus("ready");
|
|
186
290
|
let fittedFor = host.clientWidth;
|
|
@@ -262,7 +366,18 @@ function DocxPreview({
|
|
|
262
366
|
stats.substitutedFonts.length > 0 && /* @__PURE__ */ jsxs("span", { className: "cv-docx__fonts", children: [
|
|
263
367
|
"substituted: ",
|
|
264
368
|
stats.substitutedFonts.join(", ")
|
|
265
|
-
] })
|
|
369
|
+
] }),
|
|
370
|
+
redrawn.length > 0 && /* @__PURE__ */ jsxs(
|
|
371
|
+
"span",
|
|
372
|
+
{
|
|
373
|
+
className: "cv-docx__redrawn",
|
|
374
|
+
title: "This document writes its list bullets as characters in a symbol font's own private area, which no other font can draw. They are shown here as the standard characters that mean the same mark; the stored file is unchanged.",
|
|
375
|
+
children: [
|
|
376
|
+
"bullets redrawn: ",
|
|
377
|
+
redrawn.join(", ")
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
)
|
|
266
381
|
]
|
|
267
382
|
}
|
|
268
383
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveCanvasFileUrl } from './chunk-HMYM6BTB.js';
|
|
2
2
|
import { useCanvasStore } from './chunk-RAPTQ6VH.js';
|
|
3
3
|
import { lazy, Suspense } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
@@ -10,7 +10,7 @@ function formatSize(size) {
|
|
|
10
10
|
return `${(size / (1024 * 1024)).toFixed(1)} MB`;
|
|
11
11
|
}
|
|
12
12
|
var DocxPreview = lazy(
|
|
13
|
-
() => import('./DocxPreview-
|
|
13
|
+
() => import('./DocxPreview-NGT3Z5KW.js').then((m) => ({ default: m.DocxPreview }))
|
|
14
14
|
);
|
|
15
15
|
function iconFor(mediaType, name) {
|
|
16
16
|
if (mediaType?.startsWith("image/")) return "\u{1F5BC}\uFE0F";
|
|
@@ -24,7 +24,7 @@ function iconFor(mediaType, name) {
|
|
|
24
24
|
function FileRenderer({ artifact }) {
|
|
25
25
|
const { path, name, mediaType, size, cover, excerpt, detail } = artifact.data;
|
|
26
26
|
const assetBaseUrl = useCanvasStore((s) => s.assetBaseUrl);
|
|
27
|
-
const href = assetBaseUrl &&
|
|
27
|
+
const href = assetBaseUrl && path ? resolveCanvasFileUrl(path, assetBaseUrl) : null;
|
|
28
28
|
const isImage = Boolean(mediaType?.startsWith("image/"));
|
|
29
29
|
const isWord = `${path} ${name}`.toLowerCase().includes(".docx");
|
|
30
30
|
const facts = [mediaType, formatSize(size), detail].filter(Boolean).join(" \xB7 ");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { deckPage, pageAspect, DEFAULT_SLIDE_PAGE_IN, resolveElements, fontScaleFor } from './chunk-MZ5WQWTS.js';
|
|
2
|
-
import { useAssetUrl } from './chunk-
|
|
3
|
-
import './chunk-
|
|
2
|
+
import { useAssetUrl } from './chunk-HCOQ6XCQ.js';
|
|
3
|
+
import './chunk-HMYM6BTB.js';
|
|
4
4
|
import { useArtifactPatch } from './chunk-N5JW2BKI.js';
|
|
5
5
|
import './chunk-RAPTQ6VH.js';
|
|
6
6
|
import { useState, useRef, useEffect } from 'react';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/protocol/selection.ts
|
|
2
|
+
var DOCUMENT_FILE_SUFFIXES = [".docx"];
|
|
3
|
+
function isDocumentSelection(selection) {
|
|
4
|
+
const id = selection.artifactId.toLowerCase();
|
|
5
|
+
return DOCUMENT_FILE_SUFFIXES.some((suffix) => id.endsWith(suffix));
|
|
6
|
+
}
|
|
7
|
+
function withSelections(message, selections) {
|
|
8
|
+
if (selections.length === 0) return message;
|
|
9
|
+
const artifactId = selections[0].artifactId;
|
|
10
|
+
if (selections.every(isDocumentSelection)) {
|
|
11
|
+
const listed2 = selections.map((s) => `- [${s.cid}]${s.text ? `: \u201C${s.text}\u201D` : ""}`).join("\n");
|
|
12
|
+
return `${message}
|
|
13
|
+
|
|
14
|
+
[Targeted edit] The user pointed at this place in \`${artifactId}\`:
|
|
15
|
+
${listed2}
|
|
16
|
+
First call read_canvas on the file for its current revision and the same addresses, then change that place with edit_canvas (or insert_document_paragraph / remove_document_paragraph / replace_document_image). Those take a text anchor, not the address \u2014 copy it from the read_canvas output, because the numbers move as soon as a paragraph is added or removed.`;
|
|
17
|
+
}
|
|
18
|
+
const listed = selections.map((s) => {
|
|
19
|
+
const shown = s.text ? ` \u2014 \u201C${s.text}\u201D` : "";
|
|
20
|
+
return s.outerHtml ? `- \`${s.selector}\`${shown}
|
|
21
|
+
${s.outerHtml}` : `- \`${s.selector}\`${shown}`;
|
|
22
|
+
}).join("\n");
|
|
23
|
+
return `${message}
|
|
24
|
+
|
|
25
|
+
[Targeted edit] Apply the change to these selected element(s) in file \`${artifactId}\`:
|
|
26
|
+
${listed}
|
|
27
|
+
First call read_canvas on the file for its current content and revision, then call edit_canvas with that element's exact markup from the file as \`old\` and your replacement as \`new\`. The markup listed above is the file's own; the screen adds attributes of its own for pointing, which are never stored, so do not look for them and do not add them.`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { DOCUMENT_FILE_SUFFIXES, isDocumentSelection, withSelections };
|
|
@@ -14,6 +14,9 @@ function isAssetReference(src) {
|
|
|
14
14
|
function resolveAssetUrl(src, assetBaseUrl) {
|
|
15
15
|
return assetBaseUrl + encodeURIComponent(normalizeAssetReference(src) ?? src);
|
|
16
16
|
}
|
|
17
|
+
function resolveCanvasFileUrl(path, assetBaseUrl) {
|
|
18
|
+
return assetBaseUrl + encodeURIComponent(path);
|
|
19
|
+
}
|
|
17
20
|
var REF_ALTERNATION = ASSET_REFERENCE_PREFIXES.map((p) => p.slice(0, -1)).join("|");
|
|
18
21
|
var srcAttrPattern = () => new RegExp(`(src=(["']))((?:\\.\\.?/)*(?:${REF_ALTERNATION})/[^"']+)(\\2)`, "g");
|
|
19
22
|
var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -106,4 +109,4 @@ async function inlineArtifactAssets(artifact, assetBaseUrl) {
|
|
|
106
109
|
return artifact;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
export { ASSET_REFERENCE_PREFIXES, fetchAssetDataUri, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, normalizeAssetReference, resolveAssetUrl };
|
|
112
|
+
export { ASSET_REFERENCE_PREFIXES, fetchAssetDataUri, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, normalizeAssetReference, resolveAssetUrl, resolveCanvasFileUrl };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as Artifact, a as CanvasEvent, E as ElementSelection, S as StreamEvent, C as CanvasTransport, F as FileData, b as SlidesData, T as TableData, D as DocumentData, c as ChartData, H as HtmlData } from './types-
|
|
2
|
-
export { d as ArtifactStatus, e as CanvasAppend, f as CanvasCommit, g as CanvasCreate, h as CanvasNodePatch, i as CanvasPatch, j as CanvasReplace, k as CanvasStatus, l as ChartArtifact, m as ChartOptions, n as ChartSeries, o as ChatEvent, p as
|
|
1
|
+
import { A as Artifact, a as CanvasEvent, E as ElementSelection, S as StreamEvent, C as CanvasTransport, F as FileData, b as SlidesData, T as TableData, D as DocumentData, c as ChartData, H as HtmlData } from './types-CKgpjs_G.js';
|
|
2
|
+
export { d as ArtifactStatus, e as CanvasAppend, f as CanvasCommit, g as CanvasCreate, h as CanvasNodePatch, i as CanvasPatch, j as CanvasReplace, k as CanvasStatus, l as ChartArtifact, m as ChartOptions, n as ChartSeries, o as ChatEvent, p as DOCUMENT_FILE_SUFFIXES, q as DocumentArtifact, r as DoneEvent, s as ErrorEvent, t as FileArtifact, u as HtmlArtifact, K as KnownArtifact, M as MessageDelta, v as MessageEnd, x as Slide, y as SlideElement, z as SlidePage, B as SlidesArtifact, G as TableArtifact, I as TableColumn, J as ToolEnd, L as ToolStart, N as TransportRequest, O as isCanvasEvent, P as isChatEvent, Q as isDocumentSelection, w as withSelections } from './types-CKgpjs_G.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ReactNode, ComponentType } from 'react';
|
|
5
5
|
import { StoreApi } from 'zustand/vanilla';
|
|
@@ -600,6 +600,19 @@ declare function isAssetReference(src: string | undefined | null): src is string
|
|
|
600
600
|
* `http://host/api/canvas/<id>/file?path=`.
|
|
601
601
|
*/
|
|
602
602
|
declare function resolveAssetUrl(src: string, assetBaseUrl: string): string;
|
|
603
|
+
/**
|
|
604
|
+
* Absolute URL for a stored canvas file, wherever on the canvas it sits.
|
|
605
|
+
*
|
|
606
|
+
* Not the same question as `isAssetReference`. That one reads a string found
|
|
607
|
+
* *inside* content and asks whether it points at a canvas file — a guess that
|
|
608
|
+
* has to be conservative, because most strings in a document are not paths. A
|
|
609
|
+
* `file` artifact's `path` needs no guessing: it came from the store, so it is
|
|
610
|
+
* a canvas file by definition, at the root or under any folder. Asking the
|
|
611
|
+
* reference gate instead would leave every file outside `assets/` / `sources/`
|
|
612
|
+
* with no URL — no preview, no download — and widening that gate to fix it
|
|
613
|
+
* would make body-text scanning claim paths it should leave alone.
|
|
614
|
+
*/
|
|
615
|
+
declare function resolveCanvasFileUrl(path: string, assetBaseUrl: string): string;
|
|
603
616
|
/** Fetch one canvas asset and encode it as a `data:` URI (null on any failure). */
|
|
604
617
|
declare function fetchAssetDataUri(path: string, assetBaseUrl: string): Promise<string | null>;
|
|
605
618
|
/**
|
|
@@ -632,4 +645,4 @@ declare function inlineArtifactAssets<T extends Artifact>(artifact: T, assetBase
|
|
|
632
645
|
*/
|
|
633
646
|
declare function useAssetUrl(): (src: string | undefined) => string | undefined;
|
|
634
647
|
|
|
635
|
-
export { ASSET_REFERENCE_PREFIXES, Artifact, ArtifactCard, type ArtifactRegistry, type ArtifactRenderer, Canvas, CanvasEvent, type CanvasProps, CanvasProvider, type CanvasProviderProps, CanvasRegistryProvider, type CanvasSaveHandler, type CanvasSavePayload, type CanvasState, type CanvasStore, CanvasTransport, ChartData, ChartRenderer, type ChatMessage, type ChatRequest, DocumentData, DocumentRenderer, ElementSelection, ExportMenu, FileData, type FileExport, FileRenderer, HtmlData, HtmlRenderer, IMPORTABLE_EXTENSIONS, INSPECTOR_MARK, type IframeCommand, type MockScript, type MockStreamOptions, type RendererProps, STYLE_PROPS, type Scenario, SelectionBar, SlidesData, SlidesRenderer, type SseTransportOptions, StreamEvent, type StreamOptions, StylePanel, TableData, TableRenderer, type UseCanvasStreamOptions, type UserEditHandler, builtinRenderers, canImport, createCanvasStore, dataExporters, downloadBlob, emptyCanvasState, fetchAssetDataUri, importFile, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, mergePatch, mergeRegistries, mockStream, mockTransport, normalizeAssetReference, parseCsv, parseSSE, printToPdf, reduceCanvas, resolveAssetUrl, scenarios, slidesToPrintHtml, slugify, sseTransport, streamChat, toStandaloneHtml, useArtifactPatch, useAssetUrl, useCanvasImport, useCanvasReplay, useCanvasSave, useCanvasStore, useCanvasStoreApi, useCanvasStream, useRenderer, withInspector };
|
|
648
|
+
export { ASSET_REFERENCE_PREFIXES, Artifact, ArtifactCard, type ArtifactRegistry, type ArtifactRenderer, Canvas, CanvasEvent, type CanvasProps, CanvasProvider, type CanvasProviderProps, CanvasRegistryProvider, type CanvasSaveHandler, type CanvasSavePayload, type CanvasState, type CanvasStore, CanvasTransport, ChartData, ChartRenderer, type ChatMessage, type ChatRequest, DocumentData, DocumentRenderer, ElementSelection, ExportMenu, FileData, type FileExport, FileRenderer, HtmlData, HtmlRenderer, IMPORTABLE_EXTENSIONS, INSPECTOR_MARK, type IframeCommand, type MockScript, type MockStreamOptions, type RendererProps, STYLE_PROPS, type Scenario, SelectionBar, SlidesData, SlidesRenderer, type SseTransportOptions, StreamEvent, type StreamOptions, StylePanel, TableData, TableRenderer, type UseCanvasStreamOptions, type UserEditHandler, builtinRenderers, canImport, createCanvasStore, dataExporters, downloadBlob, emptyCanvasState, fetchAssetDataUri, importFile, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, mergePatch, mergeRegistries, mockStream, mockTransport, normalizeAssetReference, parseCsv, parseSSE, printToPdf, reduceCanvas, resolveAssetUrl, resolveCanvasFileUrl, scenarios, slidesToPrintHtml, slugify, sseTransport, streamChat, toStandaloneHtml, useArtifactPatch, useAssetUrl, useCanvasImport, useCanvasReplay, useCanvasSave, useCanvasStore, useCanvasStoreApi, useCanvasStream, useRenderer, withInspector };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
export { DOCUMENT_FILE_SUFFIXES, isDocumentSelection, withSelections } from './chunk-ASMMPDYS.js';
|
|
2
3
|
import { projectSheetIntoRows, mergeRowsIntoSheet } from './chunk-IFNRLN4Y.js';
|
|
3
4
|
import { loadOptional } from './chunk-YZZSJJMQ.js';
|
|
4
5
|
import { deckPage, resolveElements } from './chunk-MZ5WQWTS.js';
|
|
5
|
-
export { useAssetUrl } from './chunk-
|
|
6
|
-
import { inlineArtifactAssets, inlineHtmlAssets } from './chunk-
|
|
7
|
-
export { ASSET_REFERENCE_PREFIXES, fetchAssetDataUri, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, normalizeAssetReference, resolveAssetUrl } from './chunk-
|
|
6
|
+
export { useAssetUrl } from './chunk-HCOQ6XCQ.js';
|
|
7
|
+
import { inlineArtifactAssets, inlineHtmlAssets } from './chunk-HMYM6BTB.js';
|
|
8
|
+
export { ASSET_REFERENCE_PREFIXES, fetchAssetDataUri, inlineArtifactAssets, inlineHtmlAssets, isAssetReference, normalizeAssetReference, resolveAssetUrl, resolveCanvasFileUrl } from './chunk-HMYM6BTB.js';
|
|
8
9
|
export { useArtifactPatch } from './chunk-N5JW2BKI.js';
|
|
9
10
|
import { useCanvasStoreApi, useCanvasStore } from './chunk-RAPTQ6VH.js';
|
|
10
11
|
export { CanvasProvider, createCanvasStore, emptyCanvasState, isCanvasEvent, isChatEvent, mergePatch, reduceCanvas, useCanvasStore, useCanvasStoreApi } from './chunk-RAPTQ6VH.js';
|
|
@@ -164,15 +165,19 @@ var INSPECTOR_SCRIPT = `
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
// The element's markup as the *stored file* has it: the inspector's own
|
|
169
|
+
// attributes and classes exist only on screen, so anything that leaves this
|
|
170
|
+
// frame \u2014 a saved edit, or the markup an agent is asked to match \u2014 has to be
|
|
171
|
+
// scrubbed first, or it names something the file does not contain.
|
|
172
|
+
function canonicalHtml(el) {
|
|
171
173
|
var clone = el.cloneNode(true);
|
|
172
174
|
scrub(clone);
|
|
173
175
|
var inner = clone.querySelectorAll ? clone.querySelectorAll("[data-cid],[contenteditable],[data-lcx-src],.lcx-hover,.lcx-selected") : [];
|
|
174
176
|
for (var i = 0; i < inner.length; i++) scrub(inner[i]);
|
|
175
|
-
|
|
177
|
+
return clone.outerHTML;
|
|
178
|
+
}
|
|
179
|
+
function emitEdit(el) {
|
|
180
|
+
parent.postMessage({ source: MARK, type: "node_edit", cid: el.getAttribute("data-cid"), html: canonicalHtml(el) }, "*");
|
|
176
181
|
}
|
|
177
182
|
// A structural change (insert/delete/move) shifts every cid, so we save the
|
|
178
183
|
// whole document: clone <html>, drop the injected inspector nodes, scrub the
|
|
@@ -427,7 +432,7 @@ var INSPECTOR_SCRIPT = `
|
|
|
427
432
|
selector: selectorFor(t),
|
|
428
433
|
tag: t.tagName.toLowerCase(),
|
|
429
434
|
text: (t.textContent || "").trim().slice(0, 80),
|
|
430
|
-
outerHtml: t.
|
|
435
|
+
outerHtml: canonicalHtml(t).slice(0, 4000),
|
|
431
436
|
styles: stylesOf(t),
|
|
432
437
|
isGroup: !!gid
|
|
433
438
|
}, "*");
|
|
@@ -788,7 +793,7 @@ function useCanvasStream(options = {}) {
|
|
|
788
793
|
const error = useCanvasStore((s) => s.error);
|
|
789
794
|
const selections = useCanvasStore((s) => s.selections);
|
|
790
795
|
const sendMessage = useCallback(
|
|
791
|
-
async (text,
|
|
796
|
+
async (text, withSelections2) => {
|
|
792
797
|
const store = api.getState();
|
|
793
798
|
if (store.isStreaming || !text.trim()) return;
|
|
794
799
|
store.addUserMessage(text);
|
|
@@ -799,7 +804,7 @@ function useCanvasStream(options = {}) {
|
|
|
799
804
|
const stream = transport.stream({
|
|
800
805
|
threadId: threadIdRef.current,
|
|
801
806
|
message: text,
|
|
802
|
-
selections:
|
|
807
|
+
selections: withSelections2,
|
|
803
808
|
signal: controller.signal
|
|
804
809
|
});
|
|
805
810
|
for await (const event of stream) {
|
|
@@ -2256,10 +2261,10 @@ function HtmlRenderer({ artifact: artifact2 }) {
|
|
|
2256
2261
|
|
|
2257
2262
|
// src/components/renderers/index.ts
|
|
2258
2263
|
var ChartRenderer = lazy(() => import('./ChartRenderer-TBTWNPV7.js').then((m) => ({ default: m.ChartRenderer })));
|
|
2259
|
-
var DocumentRenderer = lazy(() => import('./DocumentRenderer-
|
|
2264
|
+
var DocumentRenderer = lazy(() => import('./DocumentRenderer-ZGJXDVKG.js').then((m) => ({ default: m.DocumentRenderer })));
|
|
2260
2265
|
var TableRenderer = lazy(() => import('./TableRenderer-YTOF2ZIC.js').then((m) => ({ default: m.TableRenderer })));
|
|
2261
|
-
var SlidesRenderer = lazy(() => import('./SlidesRenderer-
|
|
2262
|
-
var FileRenderer = lazy(() => import('./FileRenderer-
|
|
2266
|
+
var SlidesRenderer = lazy(() => import('./SlidesRenderer-4QWZVWWD.js').then((m) => ({ default: m.SlidesRenderer })));
|
|
2267
|
+
var FileRenderer = lazy(() => import('./FileRenderer-TZSZVVLY.js').then((m) => ({ default: m.FileRenderer })));
|
|
2263
2268
|
var builtinRenderers = {
|
|
2264
2269
|
html: HtmlRenderer,
|
|
2265
2270
|
document: DocumentRenderer,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { C as CanvasTransport,
|
|
1
|
+
import { C as CanvasTransport, S as StreamEvent } from '../types-CKgpjs_G.js';
|
|
2
|
+
export { w as withSelections } from '../types-CKgpjs_G.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* `langgraphTransport` — speak to a LangGraph server without a translator
|
|
@@ -24,8 +25,6 @@ interface LangGraphTransportOptions {
|
|
|
24
25
|
/** Extra headers (e.g. auth) passed to the SDK client. */
|
|
25
26
|
headers?: Record<string, string>;
|
|
26
27
|
}
|
|
27
|
-
/** Frame a targeted edit so the agent changes only the selected element(s). */
|
|
28
|
-
declare function withSelections(message: string, selections: ElementSelection[]): string;
|
|
29
28
|
/**
|
|
30
29
|
* LangGraph requires UUID thread ids; the canvas allows any string. Non-UUID
|
|
31
30
|
* ids map deterministically (RFC 4122 v5 over `canvas-thread:<id>`), matching
|
|
@@ -65,4 +64,4 @@ declare function translateLangGraphStream(chunks: AsyncIterable<LangGraphStreamC
|
|
|
65
64
|
messageId?: string;
|
|
66
65
|
}): AsyncGenerator<StreamEvent>;
|
|
67
66
|
|
|
68
|
-
export { type LangGraphStreamChunk, type LangGraphTransportOptions, chunkText, langgraphTransport, threadUuid, translateLangGraphStream
|
|
67
|
+
export { type LangGraphStreamChunk, type LangGraphTransportOptions, chunkText, langgraphTransport, threadUuid, translateLangGraphStream };
|
package/dist/langgraph/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { withSelections } from '../chunk-ASMMPDYS.js';
|
|
2
|
+
export { withSelections } from '../chunk-ASMMPDYS.js';
|
|
1
3
|
import { Client } from '@langchain/langgraph-sdk';
|
|
2
4
|
|
|
3
|
-
// src/langgraph/transport.ts
|
|
4
|
-
|
|
5
5
|
// src/langgraph/translate.ts
|
|
6
6
|
function chunkText(content) {
|
|
7
7
|
if (typeof content === "string") return content;
|
|
@@ -60,16 +60,6 @@ async function* translateLangGraphStream(chunks, options = {}) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// src/langgraph/transport.ts
|
|
63
|
-
function withSelections(message, selections) {
|
|
64
|
-
if (selections.length === 0) return message;
|
|
65
|
-
const listed = selections.map((s) => `- \`${s.selector}\` (data-cid=${s.cid})`).join("\n");
|
|
66
|
-
const artifactId = selections[0].artifactId;
|
|
67
|
-
return `${message}
|
|
68
|
-
|
|
69
|
-
[Targeted edit] Apply the change to these selected element(s) in file \`${artifactId}\`:
|
|
70
|
-
${listed}
|
|
71
|
-
First call read_canvas on the file to get its current content and revision, then call edit_canvas with the element's exact current outer HTML as \`old\` and your replacement as \`new\` (keep the data-cid attribute).`;
|
|
72
|
-
}
|
|
73
63
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
74
64
|
var NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
|
|
75
65
|
async function threadUuid(threadId) {
|
|
@@ -108,4 +98,4 @@ function langgraphTransport(options) {
|
|
|
108
98
|
};
|
|
109
99
|
}
|
|
110
100
|
|
|
111
|
-
export { chunkText, langgraphTransport, threadUuid, translateLangGraphStream
|
|
101
|
+
export { chunkText, langgraphTransport, threadUuid, translateLangGraphStream };
|
package/dist/styles.css
CHANGED
|
@@ -1309,6 +1309,7 @@
|
|
|
1309
1309
|
}
|
|
1310
1310
|
.cv-docx__picked { color: var(--cv-accent); }
|
|
1311
1311
|
.cv-docx__fonts { color: var(--cv-warn, #b45309); }
|
|
1312
|
+
.cv-docx__redrawn { color: var(--cv-warn, #b45309); }
|
|
1312
1313
|
|
|
1313
1314
|
/* Tablet / narrow desktop: tighten paddings, let toolbars wrap. */
|
|
1314
1315
|
@media (max-width: 900px) {
|
|
@@ -292,6 +292,33 @@ interface ElementSelection {
|
|
|
292
292
|
/** True when the element is a group wrapper (offers "Ungroup"). */
|
|
293
293
|
isGroup?: boolean;
|
|
294
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* File suffixes whose selections address a document, not a DOM element.
|
|
297
|
+
*
|
|
298
|
+
* The twin of `DOCUMENT_OP_SUFFIXES` in `langchain_canvas.document_ops`; the
|
|
299
|
+
* protocol parity test compares the two, so a format the tools learn to edit
|
|
300
|
+
* cannot quietly keep the wrong framing here.
|
|
301
|
+
*/
|
|
302
|
+
declare const DOCUMENT_FILE_SUFFIXES: readonly [".docx"];
|
|
303
|
+
/** True when this selection points into a document file rather than a page. */
|
|
304
|
+
declare function isDocumentSelection(selection: ElementSelection): boolean;
|
|
305
|
+
/**
|
|
306
|
+
* Frame a targeted edit so the agent changes only what the user pointed at.
|
|
307
|
+
*
|
|
308
|
+
* The two kinds of canvas artifact are addressed in different languages and
|
|
309
|
+
* have different tools, so one framing cannot serve both. A document is
|
|
310
|
+
* addressed by position for *reading* only — `[p12]` moves the moment a
|
|
311
|
+
* paragraph is inserted — so the instruction hands over the words at that place
|
|
312
|
+
* and says to use them as the anchor. A page is edited by matching its markup,
|
|
313
|
+
* so the instruction hands over the element's markup as the *file* has it.
|
|
314
|
+
*
|
|
315
|
+
* Both halves are about naming something the agent can actually find. The
|
|
316
|
+
* screen's own pointing attributes (`data-cid` and friends) are stripped before
|
|
317
|
+
* the source is stored, so an instruction that names one sends the agent
|
|
318
|
+
* looking through the file for something that was never written there — and a
|
|
319
|
+
* careful agent then refuses the edit rather than guessing.
|
|
320
|
+
*/
|
|
321
|
+
declare function withSelections(message: string, selections: ElementSelection[]): string;
|
|
295
322
|
|
|
296
323
|
/**
|
|
297
324
|
* `CanvasTransport` — the socket between the canvas UI and an agent backend.
|
|
@@ -325,4 +352,4 @@ interface CanvasTransport {
|
|
|
325
352
|
stream(request: TransportRequest): AsyncIterable<StreamEvent>;
|
|
326
353
|
}
|
|
327
354
|
|
|
328
|
-
export { type Artifact as A, type
|
|
355
|
+
export { type Artifact as A, type SlidesArtifact as B, type CanvasTransport as C, type DocumentData as D, type ElementSelection as E, type FileData as F, type TableArtifact as G, type HtmlData as H, type TableColumn as I, type ToolEnd as J, type KnownArtifact as K, type ToolStart as L, type MessageDelta as M, type TransportRequest as N, isCanvasEvent as O, isChatEvent as P, isDocumentSelection as Q, type StreamEvent as S, type TableData as T, type CanvasEvent as a, type SlidesData as b, type ChartData as c, type ArtifactStatus as d, type CanvasAppend as e, type CanvasCommit as f, type CanvasCreate as g, type CanvasNodePatch as h, type CanvasPatch as i, type CanvasReplace as j, type CanvasStatus as k, type ChartArtifact as l, type ChartOptions as m, type ChartSeries as n, type ChatEvent as o, DOCUMENT_FILE_SUFFIXES as p, type DocumentArtifact as q, type DoneEvent as r, type ErrorEvent as s, type FileArtifact as t, type HtmlArtifact as u, type MessageEnd as v, withSelections as w, type Slide as x, type SlideElement as y, type SlidePage as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@braincrew-lab/langchain-canvas",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
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
|
"author": "Brain Crew (https://github.com/braincrew-lab)",
|