claude-artifact-framework 0.10.0 → 0.11.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/README.md +33 -3
- package/dist/index.esm.js +10 -9
- package/dist/index.esm.js.map +2 -2
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +3 -3
- package/package.json +1 -1
- package/src/app.js +12 -8
package/README.md
CHANGED
|
@@ -428,9 +428,39 @@ blank pane), the per-document data pools (`d` inside any block, `output`,
|
|
|
428
428
|
`custom`, or `when` is THAT document's data; `ctx.update` writes there),
|
|
429
429
|
the empty state, and persistence — all documents and which one is open
|
|
430
430
|
survive reload. Documents keys: `label`, `title`, `blocks`, `empty`.
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
431
|
+
|
|
432
|
+
Inside `documents`, blocks work as in `panel` — **including `chat` and
|
|
433
|
+
`file`, which become per-document**:
|
|
434
|
+
|
|
435
|
+
- A `chat` block inside `documents` gives **each document its own
|
|
436
|
+
conversation**, persisted with that document (`data.chat` is scoped). Its
|
|
437
|
+
`system` function receives the document's data, so the copilot talks
|
|
438
|
+
about THIS document. One chat block per document (a second throws).
|
|
439
|
+
- A `file` field inside `documents` scopes `ctx.files[key]` to the active
|
|
440
|
+
document — two documents never collide on the same field key. As
|
|
441
|
+
everywhere, the live `File` is memory-only: metadata survives reload,
|
|
442
|
+
the file is re-picked per document.
|
|
443
|
+
|
|
444
|
+
That combination — one file plus one conversation per tab — is the
|
|
445
|
+
multi-document annotator shape (PDFs, images, CSVs) declared in full:
|
|
446
|
+
|
|
447
|
+
```js
|
|
448
|
+
ArtifactKit.createApp({
|
|
449
|
+
title: "Anotador de archivos",
|
|
450
|
+
layout: "documents",
|
|
451
|
+
documents: {
|
|
452
|
+
label: "archivo",
|
|
453
|
+
title: (d) => (d.archivo && d.archivo.name) || "Sin archivo",
|
|
454
|
+
blocks: [
|
|
455
|
+
{ fields: [{ key: "archivo", label: "Archivo", type: "file" }] },
|
|
456
|
+
{ custom: (ctx) => { /* render ctx.files.archivo */ }, fill: true },
|
|
457
|
+
{ title: "Copiloto", chat: {
|
|
458
|
+
system: (d) => "Ayudás con el archivo " + ((d.archivo && d.archivo.name) || "(ninguno)"),
|
|
459
|
+
}},
|
|
460
|
+
],
|
|
461
|
+
},
|
|
462
|
+
})
|
|
463
|
+
```
|
|
434
464
|
|
|
435
465
|
### External libraries, uploaded files, full-bleed custom, viewer identity
|
|
436
466
|
|
package/dist/index.esm.js
CHANGED
|
@@ -1550,15 +1550,10 @@ function validate(spec) {
|
|
|
1550
1550
|
throw new Error("claude-artifact-framework: documents.title must be a function of the document's data returning the tab label.");
|
|
1551
1551
|
}
|
|
1552
1552
|
checkBlocks(d.blocks);
|
|
1553
|
-
const
|
|
1554
|
-
if (
|
|
1555
|
-
throw new Error(
|
|
1556
|
-
'claude-artifact-framework: a chat block inside "documents" is not supported \u2014 the conversation store is app-wide, not per document.'
|
|
1557
|
-
);
|
|
1558
|
-
}
|
|
1559
|
-
if (flat.some((b) => (b.fields || []).some((f) => f.type === "file"))) {
|
|
1553
|
+
const chats = flattenBlocks(d.blocks).filter((b) => b && b.chat);
|
|
1554
|
+
if (chats.length > 1) {
|
|
1560
1555
|
throw new Error(
|
|
1561
|
-
"claude-artifact-framework:
|
|
1556
|
+
"claude-artifact-framework: only one chat block per document \u2014 each document's conversation persists under its own data.chat and there is exactly one."
|
|
1562
1557
|
);
|
|
1563
1558
|
}
|
|
1564
1559
|
return layout;
|
|
@@ -1845,6 +1840,7 @@ function DocumentsLayout({ spec, ctx }) {
|
|
|
1845
1840
|
ctx.update((d) => {
|
|
1846
1841
|
d.docs = d.docs.filter((doc) => doc.id !== id);
|
|
1847
1842
|
});
|
|
1843
|
+
delete ctx.files["doc:" + id];
|
|
1848
1844
|
if (active && active.id === id) {
|
|
1849
1845
|
const next = docs[idx + 1] || docs[idx - 1];
|
|
1850
1846
|
if (next) ctx.setTab(DOC_TAB_KEY, next.id);
|
|
@@ -1869,7 +1865,12 @@ function DocumentsLayout({ spec, ctx }) {
|
|
|
1869
1865
|
update: (fn) => ctx.update((d) => {
|
|
1870
1866
|
const doc = (d.docs || []).find((x) => x.id === active.id);
|
|
1871
1867
|
if (doc) fn(doc.data);
|
|
1872
|
-
})
|
|
1868
|
+
}),
|
|
1869
|
+
// Live File objects scoped per document: each doc gets its own sub-map,
|
|
1870
|
+
// so two documents with the same file field never collide. Like the flat
|
|
1871
|
+
// pool, the File itself is memory-only — metadata survives reload, the
|
|
1872
|
+
// file is re-picked per document.
|
|
1873
|
+
files: ctx.files["doc:" + active.id] = ctx.files["doc:" + active.id] || {}
|
|
1873
1874
|
};
|
|
1874
1875
|
return createElement(
|
|
1875
1876
|
"div",
|