claude-artifact-framework 0.3.0 → 0.5.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 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.3.0/dist/index.global.js"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.5.0/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.3.0/dist/index.esm.js";
30
+ } from "https://cdn.jsdelivr.net/npm/claude-artifact-framework@0.5.0/dist/index.esm.js";
31
31
  </script>
32
32
  ```
33
33
 
34
- Pin a version (`@0.3.0`) for reproducible artifacts, or drop the version
34
+ Pin a version (`@0.5.0`) 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
@@ -123,6 +123,137 @@ persistence path as everything else. `id` is assigned by the framework and
123
123
  reserved. Optional: `title(r)` / `subtitle(r)` for rows, `sort(a, b)`,
124
124
  `summary(records)` for stats above the list, `empty` for the empty-state text.
125
125
 
126
+ ### The `steps` layout — wizards, quizzes, staged calculators
127
+
128
+ Declare the sequence; next/back/progress/result are framework-owned. Step
129
+ fields write into the same flat `data` pool, so the result step is just a
130
+ function of data. Next is gated on the current step's validation; the current
131
+ step survives a reload.
132
+
133
+ ```js
134
+ ArtifactKit.createApp({
135
+ title: "Quiz de riesgo",
136
+ layout: "steps",
137
+ steps: [
138
+ { title: "Tu edad", fields: [{ key: "edad", type: "number", required: true, min: 18 }] },
139
+ { title: "Tu perfil", fields: [{ key: "perfil", type: "select", required: true, options: ["conservador", "moderado", "agresivo"] }] },
140
+ { title: "Resultado", result: (d) => [{ label: "Puntaje", value: score(d), big: true }] },
141
+ ],
142
+ });
143
+ ```
144
+
145
+ Field keys must be unique across all steps (they share one data pool); a
146
+ duplicate throws at creation, as does an unknown step key.
147
+
148
+ ### The `chart` block — bar, line, donut
149
+
150
+ Same vocabulary as `output` (items of `{ label, value }` plus an optional
151
+ `format`), so declaring one teaches nothing new. Colors derive from the theme
152
+ seed by golden-angle rotation — a chart can't clash with the app it lives in.
153
+
154
+ ```js
155
+ blocks: [
156
+ { chart: (d) => ({ type: "bar", format: "money", items: monthlyTotals(d) }), title: "Ventas", wide: true },
157
+ { chart: { type: "donut", items: [{ label: "Comida", value: 45 }, { label: "Otros", value: 55 }] } },
158
+ ]
159
+ ```
160
+
161
+ ### The `timer` block — countdowns that persist their effects
162
+
163
+ The interval is framework-owned and cleaned up on unmount (a leaked
164
+ `setInterval` is a classic half-built artifact bug). The countdown itself is
165
+ deliberately ephemeral; what you declare is what happens when it finishes —
166
+ `onDone` runs through `update()`, so its effects persist like any other change.
167
+
168
+ ```js
169
+ blocks: [
170
+ { timer: { minutes: 25, label: "Focus", onDone: (d) => { d.completados = (d.completados || 0) + 1; } } },
171
+ { output: (d) => [{ label: "Pomodoros", value: d.completados || 0, big: true }] },
172
+ ]
173
+ ```
174
+
175
+ `text` blocks also accept a function of data — `{ text: (d) => "Hola " + d.nombre }` —
176
+ with the same contract as `output`.
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
+
126
257
  ## `storage`
127
258
 
128
259
  Thin wrapper over `window.storage`, the persistence API Claude injects into a