claude-artifact-framework 0.4.0 → 0.5.1

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 CHANGED
@@ -12,7 +12,7 @@ mirrors npm packages automatically.
12
12
  ### As a global script (`<script>` tag)
13
13
 
14
14
  ```html
15
- <script src="https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.4.0/dist/index.global.js"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.5.1/dist/index.global.js"></script>
16
16
  <script>
17
17
  const { storage, createStore, createPersistedStore, createSharedStore } = ArtifactKit;
18
18
  </script>
@@ -27,11 +27,11 @@ mirrors npm packages automatically.
27
27
  createStore,
28
28
  createPersistedStore,
29
29
  createSharedStore,
30
- } from "https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.4.0/dist/index.esm.js";
30
+ } from "https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.5.1/dist/index.esm.js";
31
31
  </script>
32
32
  ```
33
33
 
34
- Pin a version (`@0.4.0`) for reproducible artifacts, or drop the version
34
+ Pin a version (`@0.5.1`) for reproducible artifacts, or drop the version
35
35
  (`claude-artifact-framework/dist/...`) to always get the latest release.
36
36
 
37
37
  ### Inside a React artifact
@@ -175,6 +175,122 @@ blocks: [
175
175
  `text` blocks also accept a function of data — `{ text: (d) => "Hola " + d.nombre }` —
176
176
  with the same contract as `output`.
177
177
 
178
+ ### The `chat` layout — apps that talk to Claude
179
+
180
+ Tutors, advisors, generators, roleplay. Every piece of the network contract is
181
+ copied from code proven inside the real artifact runtime: the artifact fetches
182
+ `https://api.anthropic.com/v1/messages` directly with **no API key** (the
183
+ runtime proxies the call and injects auth), `stream: true` works, and tools
184
+ are prompted (the proxy does not support native function calling).
185
+
186
+ The author declares the system prompt and, optionally, tools that operate on
187
+ the app's data — a chat that can drive the app. The framework owns message
188
+ state, live streaming, the busy state, the tool loop, and errors as visible
189
+ bubbles. The conversation persists and survives reload.
190
+
191
+ ```js
192
+ ArtifactKit.createApp({
193
+ title: "Asistente de gastos",
194
+ theme: { seed: "#0f766e" },
195
+ layout: "chat",
196
+ chat: {
197
+ system: (d) => "Eres un asistente de gastos. Total actual: " + (d.total || 0),
198
+ greeting: "¡Hola! Contame tus gastos.",
199
+ tools: {
200
+ agregar_gasto: {
201
+ description: "Agrega un gasto",
202
+ input: { concepto: "string", monto: "number" },
203
+ run: (input, ctx) => {
204
+ ctx.update((d) => { d.total = (d.total || 0) + Number(input.monto); });
205
+ return { ok: true };
206
+ },
207
+ },
208
+ },
209
+ },
210
+ });
211
+ ```
212
+
213
+ `system` is a string or a function of data. Tool `run(input, ctx)` returns a
214
+ JSON-serializable result that is fed back to the model; an unknown tool name
215
+ is answered in-band so the model corrects itself. Optional: `greeting`,
216
+ `placeholder`, `model` (default `claude-sonnet-4-6`, proven through the
217
+ proxy), `maxTokens`.
218
+
219
+ ### Search, computed fields, and shared data
220
+
221
+ Three record-app multipliers, all declarative:
222
+
223
+ ```js
224
+ ArtifactKit.createApp({
225
+ title: "Inventario del club",
226
+ layout: "records",
227
+ shared: true, // one copy of the data for every viewer
228
+ records: {
229
+ search: true, // search box over all field values
230
+ fields: [
231
+ { key: "nombre", type: "text", required: true },
232
+ { key: "cantidad", type: "number", value: 1, min: 0 },
233
+ { key: "precio", type: "money", value: 0, min: 0 },
234
+ ],
235
+ compute: { // derived per record, never stored
236
+ subtotal: { label: "Subtotal", format: "money", value: (r) => r.cantidad * r.precio },
237
+ },
238
+ summary: (all) => [
239
+ { label: "Valor total", value: all.reduce((s, r) => s + r.subtotal, 0), format: "money", big: true },
240
+ ],
241
+ },
242
+ });
243
+ ```
244
+
245
+ - `search: true` adds a filter box over every field's value; the count shows
246
+ "n of total" while filtering.
247
+ - `compute` entries are functions of the record (or `{ label, format, value }`).
248
+ Computed values appear read-only in the detail screen and are available to
249
+ `title` / `subtitle` / `sort` / `summary` as if they were fields. A compute
250
+ key that collides with a field key throws.
251
+ - `shared: true` (top level) stores the app's data in the shared scope: every
252
+ viewer of the published artifact converges on the same data via polling.
253
+ Conflict handling is last-write-wins; a poll never overwrites local edits
254
+ that haven't been persisted yet. View state (which screen is open) stays
255
+ personal per viewer.
256
+
257
+ ## API reference
258
+
259
+ Everything an app can declare, in one place.
260
+
261
+ **Top-level keys**: `title`, `subtitle`, `theme: { seed }`, `layout`, `blocks`,
262
+ `records`, `steps`, `chat`, `data`, `shared`. Anything else throws.
263
+
264
+ **Layouts** (`layout:`): `panel` (default — grid of blocks), `records` (CRUD
265
+ list), `steps` (wizard), `chat` (conversation with Claude). Each requires its
266
+ matching key (`blocks` / `records` / `steps` / `chat`).
267
+
268
+ **Block types** (entries of `blocks`): `fields`, `output`, `text`, `list`,
269
+ `chart`, `timer`, `custom`. One type per entry, plus optional `title`, `empty`,
270
+ `wide`. In the `records` layout, `blocks` render below the list (never on the
271
+ detail screen); their functions receive the same `data` object as everywhere
272
+ else — the collection lives at `d.records`.
273
+
274
+ **Field types** (`type:` on any field): `text` (default), `textarea`,
275
+ `number`, `money`, `percent`, `check` (checkbox), `date`, `select` (needs
276
+ `options`). Other field keys: `key` (required), `label`, `value` (initial),
277
+ `required`, `min`, `max`, `step`, `placeholder`, `hint`, `rows`, `options`.
278
+ An unknown `type` throws naming the valid ones.
279
+
280
+ **`records` keys**: `label`, `fields`, `title(r)`, `subtitle(r)`, `sort(a,b)`,
281
+ `summary(all)`, `empty`, `search`, `compute`. `id` is framework-assigned and
282
+ reserved.
283
+
284
+ **`steps` keys** (per step): `title`, `text`, `fields`, `result(d)`. Field
285
+ keys must be unique across steps.
286
+
287
+ **`chat` keys**: `system` (string or `(d) => string`), `greeting`,
288
+ `placeholder`, `tools`, `model`, `maxTokens`. Each tool:
289
+ `{ description, input, run(input, ctx) }`.
290
+
291
+ **Formats** (`format:` on output/chart/compute items): `money`, `percent`,
292
+ `number`, `date`.
293
+
178
294
  ## `storage`
179
295
 
180
296
  Thin wrapper over `window.storage`, the persistence API Claude injects into a