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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-artifact-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|
package/src/app.js
CHANGED
|
@@ -229,15 +229,13 @@ function validate(spec) {
|
|
|
229
229
|
throw new Error("claude-artifact-framework: documents.title must be a function of the document's data returning the tab label.");
|
|
230
230
|
}
|
|
231
231
|
checkBlocks(d.blocks);
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
if (flat.some((b) => (b.fields || []).some((f) => f.type === "file"))) {
|
|
232
|
+
// Inside documents both chat and file are PER DOCUMENT: the scoped ctx
|
|
233
|
+
// gives each document its own data.chat and its own ctx.files. One chat
|
|
234
|
+
// block in the declaration = one conversation per document.
|
|
235
|
+
const chats = flattenBlocks(d.blocks).filter((b) => b && b.chat);
|
|
236
|
+
if (chats.length > 1) {
|
|
239
237
|
throw new Error(
|
|
240
|
-
|
|
238
|
+
"claude-artifact-framework: only one chat block per document — each document's conversation persists under its own data.chat and there is exactly one."
|
|
241
239
|
);
|
|
242
240
|
}
|
|
243
241
|
return layout;
|
|
@@ -573,6 +571,7 @@ function DocumentsLayout({ spec, ctx }) {
|
|
|
573
571
|
ctx.update((d) => {
|
|
574
572
|
d.docs = d.docs.filter((doc) => doc.id !== id);
|
|
575
573
|
});
|
|
574
|
+
delete ctx.files["doc:" + id];
|
|
576
575
|
if (active && active.id === id) {
|
|
577
576
|
const next = docs[idx + 1] || docs[idx - 1];
|
|
578
577
|
if (next) ctx.setTab(DOC_TAB_KEY, next.id);
|
|
@@ -603,6 +602,11 @@ function DocumentsLayout({ spec, ctx }) {
|
|
|
603
602
|
const doc = (d.docs || []).find((x) => x.id === active.id);
|
|
604
603
|
if (doc) fn(doc.data);
|
|
605
604
|
}),
|
|
605
|
+
// Live File objects scoped per document: each doc gets its own sub-map,
|
|
606
|
+
// so two documents with the same file field never collide. Like the flat
|
|
607
|
+
// pool, the File itself is memory-only — metadata survives reload, the
|
|
608
|
+
// file is re-picked per document.
|
|
609
|
+
files: (ctx.files["doc:" + active.id] = ctx.files["doc:" + active.id] || {}),
|
|
606
610
|
};
|
|
607
611
|
|
|
608
612
|
return h(
|