claude-artifact-framework 0.2.0 → 0.3.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/storage.js", "../src/state.js"],
4
- "sourcesContent": ["// storage.js \u2014 wrapper over window.storage (Chat Artifacts, published only).\n//\n// Verified empirically against the real runtime: get/set/delete/list all\n// take (key, shared = false) and return a Promise resolving to\n// { key, value, shared, \"@type\": \"...StorageXResponse\" }. Confirmed:\n// - values must be strings (a raw object throws \"Invalid payload content\")\n// - shared=true/false is a real, working scope switch\n// - failures (including \"key not found\") all throw the same generic\n// message with no distinguishing `code` \u2014 there is no reliable way to\n// tell \"empty\" from \"backend error\" from the error alone.\n\nfunction available() {\n return typeof window !== \"undefined\" && typeof window.storage === \"object\" && window.storage !== null;\n}\n\nfunction scope(shared) {\n return {\n async get(key, fallback = undefined) {\n if (!available()) return fallback;\n try {\n const res = await window.storage.get(key, shared);\n if (res?.value === undefined || res?.value === null) return fallback;\n try {\n return JSON.parse(res.value);\n } catch {\n return res.value; // not JSON \u2014 a plain string written via set(key, value, { raw: true })\n }\n } catch {\n // See file header: this same catch fires for \"key does not exist\"\n // and for a real backend failure. Treating both as \"no value\" is\n // the safer default for a read path, at the cost of hiding outages.\n return fallback;\n }\n },\n\n async set(key, value, { raw = false } = {}) {\n if (!available()) {\n throw new Error(\"window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)\");\n }\n const payload = raw ? value : JSON.stringify(value);\n if (typeof payload !== \"string\") {\n throw new Error(\"window.storage only accepts strings \u2014 the value must be JSON-serializable\");\n }\n return window.storage.set(key, payload, shared);\n },\n\n async delete(key) {\n if (!available()) return;\n try {\n await window.storage.delete(key, shared);\n } catch {\n // same ambiguity as get() \u2014 silently a no-op if the key never existed\n }\n },\n\n async list(prefix) {\n if (!available()) return [];\n try {\n const res = await window.storage.list(prefix, shared);\n return res?.keys || [];\n } catch {\n return [];\n }\n },\n };\n}\n\n// storage.get/set/delete/list operate on the per-viewer (personal) scope.\n// storage.shared.* are the same four methods against the shared scope, where\n// every viewer of the artifact reads and writes the same state.\nexport const storage = { ...scope(false), shared: scope(true), available };\n", "// state.js \u2014 small reactive stores for artifact UI state, layered on storage.js.\n//\n// Three tiers, each a superset of the previous:\n// createStore in-memory only, no persistence\n// createPersistedStore loads from storage once, saves (debounced) on every\n// change \u2014 personal scope, single viewer\n// createSharedStore same, but polls storage.shared so every viewer of a\n// published artifact converges on the same state\n//\n// createSharedStore is last-write-wins with no merge: if two viewers change\n// the same key inside one poll window, whichever write lands last on the\n// server wins and the other is silently overwritten on the next poll. Fine\n// for \"everyone sees the same board/list\", not a CRDT.\n\nimport { storage } from \"./storage.js\";\n\nfunction makeStore(initialState) {\n let state = initialState;\n const subscribers = new Set();\n\n function get() {\n return state;\n }\n\n function set(next) {\n state = typeof next === \"function\" ? next(state) : next;\n subscribers.forEach((fn) => fn(state));\n }\n\n function subscribe(fn) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n return { get, set, subscribe };\n}\n\nfunction debounce(fn, ms) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n };\n}\n\nexport function createStore(initialState) {\n return makeStore(initialState);\n}\n\nexport function createPersistedStore(key, initialState, { debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.set(key, value), debounceMs);\n\n const ready = storage.get(key, initialState).then((loaded) => store.set(loaded));\n store.subscribe(persist);\n\n return { ...store, ready };\n}\n\nexport function createSharedStore(key, initialState, { pollMs = 2000, debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.shared.set(key, value), debounceMs);\n let applyingRemote = false;\n\n store.subscribe((value) => {\n if (!applyingRemote) persist(value);\n });\n\n async function poll() {\n const remote = await storage.shared.get(key, initialState);\n if (JSON.stringify(remote) === JSON.stringify(store.get())) return;\n applyingRemote = true;\n store.set(remote);\n applyingRemote = false;\n }\n\n const ready = poll();\n const timer = setInterval(poll, pollMs);\n\n return { ...store, ready, stop: () => clearInterval(timer) };\n}\n"],
5
- "mappings": "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",
6
- "names": []
3
+ "sources": ["../src/storage.js", "../src/state.js", "../src/react-runtime.js", "../src/appState.js", "../src/theme.js", "../src/blocks.js", "../src/records.js", "../src/app.js"],
4
+ "sourcesContent": ["// storage.js \u2014 wrapper over window.storage (Chat Artifacts, published only).\n//\n// Verified empirically against the real runtime: get/set/delete/list all\n// take (key, shared = false) and return a Promise resolving to\n// { key, value, shared, \"@type\": \"...StorageXResponse\" }. Confirmed:\n// - values must be strings (a raw object throws \"Invalid payload content\")\n// - shared=true/false is a real, working scope switch\n// - failures (including \"key not found\") all throw the same generic\n// message with no distinguishing `code` \u2014 there is no reliable way to\n// tell \"empty\" from \"backend error\" from the error alone.\n\nfunction available() {\n return typeof window !== \"undefined\" && typeof window.storage === \"object\" && window.storage !== null;\n}\n\nfunction scope(shared) {\n return {\n async get(key, fallback = undefined) {\n if (!available()) return fallback;\n try {\n const res = await window.storage.get(key, shared);\n if (res?.value === undefined || res?.value === null) return fallback;\n try {\n return JSON.parse(res.value);\n } catch {\n return res.value; // not JSON \u2014 a plain string written via set(key, value, { raw: true })\n }\n } catch {\n // See file header: this same catch fires for \"key does not exist\"\n // and for a real backend failure. Treating both as \"no value\" is\n // the safer default for a read path, at the cost of hiding outages.\n return fallback;\n }\n },\n\n async set(key, value, { raw = false } = {}) {\n if (!available()) {\n throw new Error(\"window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)\");\n }\n const payload = raw ? value : JSON.stringify(value);\n if (typeof payload !== \"string\") {\n throw new Error(\"window.storage only accepts strings \u2014 the value must be JSON-serializable\");\n }\n return window.storage.set(key, payload, shared);\n },\n\n async delete(key) {\n if (!available()) return;\n try {\n await window.storage.delete(key, shared);\n } catch {\n // same ambiguity as get() \u2014 silently a no-op if the key never existed\n }\n },\n\n async list(prefix) {\n if (!available()) return [];\n try {\n const res = await window.storage.list(prefix, shared);\n return res?.keys || [];\n } catch {\n return [];\n }\n },\n };\n}\n\n// storage.get/set/delete/list operate on the per-viewer (personal) scope.\n// storage.shared.* are the same four methods against the shared scope, where\n// every viewer of the artifact reads and writes the same state.\nexport const storage = { ...scope(false), shared: scope(true), available };\n", "// state.js \u2014 small reactive stores for artifact UI state, layered on storage.js.\n//\n// Three tiers, each a superset of the previous:\n// createStore in-memory only, no persistence\n// createPersistedStore loads from storage once, saves (debounced) on every\n// change \u2014 personal scope, single viewer\n// createSharedStore same, but polls storage.shared so every viewer of a\n// published artifact converges on the same state\n//\n// createSharedStore is last-write-wins with no merge: if two viewers change\n// the same key inside one poll window, whichever write lands last on the\n// server wins and the other is silently overwritten on the next poll. Fine\n// for \"everyone sees the same board/list\", not a CRDT.\n\nimport { storage } from \"./storage.js\";\n\nfunction makeStore(initialState) {\n let state = initialState;\n const subscribers = new Set();\n\n function get() {\n return state;\n }\n\n function set(next) {\n state = typeof next === \"function\" ? next(state) : next;\n subscribers.forEach((fn) => fn(state));\n }\n\n function subscribe(fn) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n return { get, set, subscribe };\n}\n\nfunction debounce(fn, ms) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n };\n}\n\nexport function createStore(initialState) {\n return makeStore(initialState);\n}\n\nexport function createPersistedStore(key, initialState, { debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.set(key, value), debounceMs);\n\n const ready = storage.get(key, initialState).then((loaded) => store.set(loaded));\n store.subscribe(persist);\n\n return { ...store, ready };\n}\n\nexport function createSharedStore(key, initialState, { pollMs = 2000, debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.shared.set(key, value), debounceMs);\n let applyingRemote = false;\n\n store.subscribe((value) => {\n if (!applyingRemote) persist(value);\n });\n\n async function poll() {\n const remote = await storage.shared.get(key, initialState);\n if (JSON.stringify(remote) === JSON.stringify(store.get())) return;\n applyingRemote = true;\n store.set(remote);\n applyingRemote = false;\n }\n\n const ready = poll();\n const timer = setInterval(poll, pollMs);\n\n return { ...store, ready, stop: () => clearInterval(timer) };\n}\n", "// react-runtime.js \u2014 how the framework gets hold of React.\n//\n// It must use the SAME React the host already loaded: a second copy on the\n// page makes every hook throw. But it must not depend on it with a static\n// `import React from \"react\"` either \u2014 a specifier the host can't resolve\n// kills the whole module at load time, before anything is left running to\n// report why.\n//\n// So React is resolved at runtime, from whichever of these is available:\n//\n// 1. globalThis.React \u2014 present when the host exposes it\n// 2. useReact(React) \u2014 the explicit hand-off\n//\n// The hand-off is one line and always available, because an artifact already\n// imports React for its own code:\n//\n// import React from \"react\";\n// ArtifactKit.useReact(React);\n//\n// Deliberately no dynamic import(\"react\") fallback: it would need top-level\n// await, which the IIFE build can't have, and it only pays off in a runtime\n// with a native import map \u2014 which is not the way artifacts load code.\n\nlet React = typeof globalThis !== \"undefined\" ? globalThis.React : undefined;\n\nexport function useReact(instance) {\n React = instance;\n return instance;\n}\n\nexport function hasReact() {\n return Boolean(React);\n}\n\n// The live instance, for the few places that need React itself rather than one\n// of its functions \u2014 `class extends React.Component`, most of all.\nexport function getReact() {\n return required();\n}\n\nfunction required() {\n if (!React) {\n throw new Error(\n \"claude-artifact-framework: React not found. Hand it over once, before createApp:\\n\\n\" +\n ' import React from \"react\";\\n' +\n \" ArtifactKit.useReact(React);\\n\"\n );\n }\n return React;\n}\n\n// Bound lazily, because modules import these at load time \u2014 which is before\n// useReact() can possibly have run.\nexport const createElement = (...args) => required().createElement(...args);\nexport const useState = (...args) => required().useState(...args);\nexport const useEffect = (...args) => required().useEffect(...args);\nexport const useMemo = (...args) => required().useMemo(...args);\nexport const useRef = (...args) => required().useRef(...args);\n\n// A class component is read as a value at module scope, so it can't be\n// deferred behind a call. This stand-in is only ever constructed if React was\n// still missing at render time, and it reports the same error then.\nexport const Component =\n (React && React.Component) ||\n class ReactMissing {\n render() {\n return required();\n }\n };\n\n// The default export mirrors `import React from \"react\"`, so the source files\n// can keep using React.createElement / React.useState unchanged.\nexport default {\n get createElement() { return required().createElement; },\n get Component() { return required().Component; },\n get useState() { return required().useState; },\n get useEffect() { return required().useEffect; },\n get useMemo() { return required().useMemo; },\n get useRef() { return required().useRef; },\n};\n", "// appState.js \u2014 the store behind createApp.\n//\n// Two states, and the split is the point:\n// data domain data only. Declared by the author, persisted whole in one write.\n// view navigation stack, selection, current step, form drafts, pending flags.\n// Owned by the framework, persisted under its own key, never declared\n// and never seen by the author.\n//\n// That split is why `data` needs no zones or transient markers: nothing that\n// would be wrong to restore (an open modal, a half-typed draft) ever lives in\n// it. It also removes every storage key as an invention point \u2014 the author\n// never names one.\n\nimport { storage } from \"./storage.js\";\n\nconst DATA_KEY = \"caf:data\";\nconst VIEW_KEY = \"caf:view\";\n\nconst EMPTY_VIEW = { screen: null, arg: null, stack: [], step: 0, selected: null };\n\nfunction isPlainObject(v) {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\n\n// Stored values win, but only where they exist. A field the author added\n// after data was already saved simply falls through to its declared default,\n// which is what makes additive edits need no migration at all.\nfunction mergeDefaults(defaults, stored) {\n if (!isPlainObject(defaults) || !isPlainObject(stored)) {\n return stored === undefined ? defaults : stored;\n }\n const out = { ...defaults };\n for (const key of Object.keys(stored)) {\n out[key] = isPlainObject(defaults[key]) ? mergeDefaults(defaults[key], stored[key]) : stored[key];\n }\n return out;\n}\n\nfunction debounce(fn, ms) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n };\n}\n\nexport function createAppState(defaults, { debounceMs = 400 } = {}) {\n let data = structuredCloneish(defaults);\n let view = { ...EMPTY_VIEW };\n let hydrated = false;\n const listeners = new Set();\n\n // Notification is batched to a microtask: three mutations in a row produce\n // one render, not three. Persistence is separately debounced, because\n // writing to window.storage is async and must not run at typing speed.\n let queued = false;\n function notify() {\n if (queued) return;\n queued = true;\n Promise.resolve().then(() => {\n queued = false;\n for (const fn of listeners) fn();\n });\n }\n\n const persistData = debounce(() => storage.set(DATA_KEY, data), debounceMs);\n const persistView = debounce(() => storage.set(VIEW_KEY, view), debounceMs);\n\n const ready = (async () => {\n const [storedData, storedView] = await Promise.all([\n storage.get(DATA_KEY, undefined),\n storage.get(VIEW_KEY, undefined),\n ]);\n if (storedData !== undefined) data = mergeDefaults(defaults, storedData);\n if (storedView !== undefined) view = { ...EMPTY_VIEW, ...storedView };\n hydrated = true;\n notify();\n })();\n\n function update(fn) {\n const result = fn(data);\n // Handlers may either mutate the draft or return a replacement.\n if (result !== undefined) data = result;\n data = { ...data };\n persistData();\n notify();\n }\n\n function setView(patch) {\n view = { ...view, ...patch };\n persistView();\n notify();\n }\n\n return {\n ready,\n isHydrated: () => hydrated,\n getData: () => data,\n getView: () => view,\n update,\n setView,\n go(screen, arg) {\n setView({ stack: [...view.stack, { screen: view.screen, arg: view.arg }], screen, arg });\n },\n back() {\n const stack = view.stack.slice();\n const previous = stack.pop() || { screen: null, arg: null };\n setView({ stack, screen: previous.screen, arg: previous.arg });\n },\n subscribe(fn) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n };\n}\n\n// Defaults come from a literal in the declaration; a shallow structural copy\n// is enough and avoids depending on structuredClone being present.\nfunction structuredCloneish(value) {\n if (Array.isArray(value)) return value.map(structuredCloneish);\n if (isPlainObject(value)) {\n const out = {};\n for (const k of Object.keys(value)) out[k] = structuredCloneish(value[k]);\n return out;\n }\n return value;\n}\n", "// theme.js \u2014 derives a complete palette from a single seed colour.\n//\n// One token in, a full light+dark palette out, with contrast checked rather\n// than assumed. The point is that an app gets its own visual identity from\n// one line while structure stays shared, so apps built with this framework\n// don't all look alike.\n//\n// Neutrals carry a slight hue bias toward the seed instead of being pure\n// grey \u2014 a pure mid-grey reads as unconsidered.\n\nfunction clamp(n, lo, hi) {\n return Math.min(hi, Math.max(lo, n));\n}\n\nfunction hexToRgb(hex) {\n let h = String(hex).replace(\"#\", \"\").trim();\n if (h.length === 3) h = h.split(\"\").map((c) => c + c).join(\"\");\n const n = parseInt(h, 16);\n if (!Number.isFinite(n)) return [59, 110, 246];\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nfunction rgbToHex(rgb) {\n return \"#\" + rgb.map((v) => clamp(Math.round(v), 0, 255).toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction rgbToHsl([r, g, b]) {\n r /= 255; g /= 255; b /= 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n const d = max - min;\n let h = 0;\n let s = 0;\n if (d) {\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0);\n else if (max === g) h = (b - r) / d + 2;\n else h = (r - g) / d + 4;\n h /= 6;\n }\n return [h * 360, s * 100, l * 100];\n}\n\nfunction hslToRgb(h, s, l) {\n h = (((h % 360) + 360) % 360) / 360;\n s = clamp(s, 0, 100) / 100;\n l = clamp(l, 0, 100) / 100;\n if (!s) return [l * 255, l * 255, l * 255];\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const channel = (t) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n return [channel(h + 1 / 3) * 255, channel(h) * 255, channel(h - 1 / 3) * 255];\n}\n\nfunction hsl(h, s, l) {\n return rgbToHex(hslToRgb(h, s, l));\n}\n\nfunction luminance(rgb) {\n const a = rgb.map((v) => {\n v /= 255;\n return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n });\n return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];\n}\n\n// WCAG contrast ratio between two hex colours, 1 (identical) to 21 (max).\nexport function contrast(a, b) {\n const la = luminance(hexToRgb(a));\n const lb = luminance(hexToRgb(b));\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\n// Walks lightness until the colour clears `min` contrast against `against`,\n// so the accent is guaranteed legible instead of merely hoped to be.\nfunction accentAt(h, s, against, min, from, step) {\n for (let l = from; l >= 4 && l <= 96; l += step) {\n const candidate = hsl(h, s, l);\n if (contrast(candidate, against) >= min) return candidate;\n }\n return hsl(h, s, step < 0 ? 24 : 82);\n}\n\nexport function palette(seed = \"#3b6ef6\") {\n const [h, rawSat] = rgbToHsl(hexToRgb(seed));\n const sat = clamp(rawSat, 30, 88);\n // Neutrals keep a trace of the seed's hue: chosen, not inherited.\n const tint = clamp(sat * 0.1, 3, 9);\n\n const lightSurface = hsl(h, tint * 0.4, 100);\n const darkSurface = hsl(h, tint * 1.4, 13);\n\n return {\n light: {\n bg: hsl(h, tint, 96.5),\n surface: lightSurface,\n sunken: hsl(h, tint, 93),\n border: hsl(h, tint, 86),\n text: hsl(h, tint * 1.6, 11),\n muted: hsl(h, tint * 1.2, 41),\n accent: accentAt(h, sat, \"#ffffff\", 4.5, 54, -2),\n accentText: \"#ffffff\",\n danger: accentAt(2, 68, \"#ffffff\", 4.5, 54, -2),\n ok: accentAt(148, 62, \"#ffffff\", 4.5, 44, -2),\n warn: accentAt(38, 88, \"#ffffff\", 4.5, 44, -2),\n },\n dark: {\n bg: hsl(h, tint * 1.5, 9),\n surface: darkSurface,\n sunken: hsl(h, tint * 1.5, 7),\n border: hsl(h, tint * 1.3, 24),\n text: hsl(h, tint * 0.6, 95),\n muted: hsl(h, tint * 0.8, 66),\n accent: accentAt(h, clamp(sat, 40, 80), darkSurface, 4.5, 62, 2),\n accentText: hsl(h, tint * 2, 8),\n danger: accentAt(2, 70, darkSurface, 4.5, 62, 2),\n ok: accentAt(148, 55, darkSurface, 4.5, 62, 2),\n warn: accentAt(38, 80, darkSurface, 4.5, 62, 2),\n },\n };\n}\n\nfunction vars(scheme) {\n return Object.entries(scheme)\n .map(([k, v]) => `--caf-${k}: ${v};`)\n .join(\"\");\n}\n\n// Both themes are styled through the same tokens, and the viewer's explicit\n// toggle (data-theme on the root) must beat the OS preference in both\n// directions \u2014 hence the two attribute blocks after the media query.\nexport function themeCss(seed) {\n const p = palette(seed);\n return `\n:root { ${vars(p.light)} }\n@media (prefers-color-scheme: dark) { :root { ${vars(p.dark)} } }\n:root[data-theme=\"dark\"] { ${vars(p.dark)} }\n:root[data-theme=\"light\"] { ${vars(p.light)} }\n`;\n}\n", "// blocks.js \u2014 the content blocks that fill a layout's slots.\n//\n// Every block is a plain React component taking (spec, ctx). Custom code from\n// the escape hatch implements exactly the same contract, which is why ejecting\n// one block never requires ejecting the app.\n//\n// Loading / empty / error are part of the contract rather than edge cases the\n// author opts into: a block that has nothing to show says so by default, so an\n// app can't ship a blank pane while it waits.\n\n// Bound lazily rather than snapshotted as `React.createElement`, because this\n// runs at module load \u2014 before the host has had a chance to hand React over.\nimport { createElement as h } from \"react\";\n\nconst FIELD_TYPES = [\"text\", \"textarea\", \"number\", \"money\", \"percent\", \"check\", \"date\", \"select\"];\n\nexport function formatValue(value, format) {\n if (value === null || value === undefined || value === \"\") return \"\u2014\";\n const n = Number(value);\n switch (format) {\n case \"money\":\n return Number.isFinite(n)\n ? n.toLocaleString(undefined, { style: \"currency\", currency: \"USD\", maximumFractionDigits: 2 })\n : String(value);\n case \"percent\":\n return Number.isFinite(n) ? `${n.toLocaleString(undefined, { maximumFractionDigits: 2 })}%` : String(value);\n case \"number\":\n return Number.isFinite(n) ? n.toLocaleString(undefined, { maximumFractionDigits: 2 }) : String(value);\n case \"date\":\n return value instanceof Date ? value.toLocaleDateString() : String(value);\n default:\n return String(value);\n }\n}\n\n// Validation is derived from the field declaration, so the author gets it\n// without writing any: declaring a type and a range IS the validation.\nexport function validateField(field, value) {\n if (field.required && (value === \"\" || value === null || value === undefined)) {\n return \"Required\";\n }\n if (value === \"\" || value === null || value === undefined) return null;\n if (field.type === \"number\" || field.type === \"money\" || field.type === \"percent\") {\n const n = Number(value);\n if (!Number.isFinite(n)) return \"Must be a number\";\n if (field.min !== undefined && n < field.min) return `Must be at least ${field.min}`;\n if (field.max !== undefined && n > field.max) return `Must be at most ${field.max}`;\n }\n return null;\n}\n\nexport function Field({ field, value, onChange }) {\n const error = validateField(field, value);\n const id = `caf-f-${field.key}`;\n const numeric = field.type === \"number\" || field.type === \"money\" || field.type === \"percent\";\n\n if (field.type === \"check\") {\n return h(\n \"label\",\n { className: \"caf-check\" },\n h(\"input\", {\n id,\n type: \"checkbox\",\n checked: Boolean(value),\n onChange: (e) => onChange(e.target.checked),\n }),\n h(\"span\", null, field.label || field.key)\n );\n }\n\n const common = {\n id,\n value: value === null || value === undefined ? \"\" : value,\n \"aria-invalid\": error ? \"true\" : undefined,\n onChange: (e) => onChange(numeric ? toNumber(e.target.value) : e.target.value),\n };\n\n let control;\n if (field.type === \"textarea\") {\n control = h(\"textarea\", { ...common, rows: field.rows || 3 });\n } else if (field.type === \"select\") {\n control = h(\n \"select\",\n common,\n h(\"option\", { value: \"\" }, field.placeholder || \"Select\u2026\"),\n (field.options || []).map((opt) => {\n const val = typeof opt === \"string\" ? opt : opt.value;\n const label = typeof opt === \"string\" ? opt : opt.label;\n return h(\"option\", { key: val, value: val }, label);\n })\n );\n } else {\n control = h(\"input\", {\n ...common,\n type: field.type === \"date\" ? \"date\" : numeric ? \"number\" : \"text\",\n min: field.min,\n max: field.max,\n step: field.step || (field.type === \"money\" || field.type === \"percent\" ? \"any\" : undefined),\n placeholder: field.placeholder,\n });\n }\n\n return h(\n \"div\",\n { className: \"caf-field\" },\n h(\"label\", { htmlFor: id }, field.label || field.key),\n control,\n field.hint && !error ? h(\"small\", { className: \"caf-hint\" }, field.hint) : null,\n error ? h(\"small\", { className: \"caf-error\" }, error) : null\n );\n}\n\nfunction toNumber(raw) {\n if (raw === \"\") return \"\";\n const n = Number(raw);\n return Number.isFinite(n) ? n : raw;\n}\n\nexport function FieldsBlock({ spec, ctx }) {\n const fields = spec.fields || [];\n return h(\n \"div\",\n { className: \"caf-block caf-fields\" },\n spec.title ? h(\"h2\", { className: \"caf-block-title\" }, spec.title) : null,\n fields.map((field) =>\n h(Field, {\n key: field.key,\n field,\n value: ctx.data[field.key],\n onChange: (v) => ctx.update((d) => { d[field.key] = v; }),\n })\n )\n );\n}\n\nexport function OutputBlock({ spec, ctx }) {\n const items = typeof spec.output === \"function\" ? spec.output(ctx.data) : spec.output || [];\n if (!items.length) {\n return h(\"div\", { className: \"caf-block caf-empty\" }, spec.empty || \"Nothing to show yet.\");\n }\n return h(\n \"div\",\n { className: \"caf-block caf-output\" },\n spec.title ? h(\"h2\", { className: \"caf-block-title\" }, spec.title) : null,\n h(\n \"div\",\n { className: \"caf-output-grid\" },\n items.map((item, i) =>\n h(\n \"div\",\n { key: item.label || i, className: item.big ? \"caf-stat caf-stat-big\" : \"caf-stat\" },\n h(\"span\", { className: \"caf-stat-label\" }, item.label),\n h(\"span\", { className: \"caf-stat-value\" }, formatValue(item.value, item.format)),\n item.hint ? h(\"small\", { className: \"caf-hint\" }, item.hint) : null\n )\n )\n )\n );\n}\n\nexport function TextBlock({ spec }) {\n const body = typeof spec.text === \"function\" ? spec.text() : spec.text;\n return h(\n \"div\",\n { className: \"caf-block caf-text\" },\n spec.title ? h(\"h2\", { className: \"caf-block-title\" }, spec.title) : null,\n h(\"p\", null, body)\n );\n}\n\nexport function ListBlock({ spec, ctx }) {\n const rows = (typeof spec.list === \"function\" ? spec.list(ctx.data) : spec.list) || [];\n if (!rows.length) {\n return h(\"div\", { className: \"caf-block caf-empty\" }, spec.empty || \"Nothing here yet.\");\n }\n const title = spec.title || ((r) => r.title ?? r.name ?? r.label ?? String(r));\n return h(\n \"div\",\n { className: \"caf-block caf-list\" },\n rows.map((row, i) =>\n h(\n \"button\",\n {\n key: row.id ?? i,\n className: \"caf-row\",\n type: \"button\",\n onClick: spec.onSelect ? () => spec.onSelect(row, ctx) : undefined,\n },\n h(\"span\", { className: \"caf-row-title\" }, title(row)),\n spec.subtitle ? h(\"span\", { className: \"caf-row-sub\" }, spec.subtitle(row)) : null\n )\n )\n );\n}\n\n// The escape hatch. Receives the same ctx every built-in block gets, so a\n// custom block keeps persistence, theming, navigation and the error boundary.\nexport function CustomBlock({ spec, ctx }) {\n const rendered = spec.custom(ctx);\n if (typeof rendered === \"string\") {\n return h(\"div\", { className: \"caf-block\", dangerouslySetInnerHTML: { __html: rendered } });\n }\n return h(\"div\", { className: \"caf-block\" }, rendered);\n}\n\nexport const BLOCKS = {\n fields: FieldsBlock,\n output: OutputBlock,\n text: TextBlock,\n list: ListBlock,\n custom: CustomBlock,\n};\n\nexport const BLOCK_NAMES = Object.keys(BLOCKS);\nexport { FIELD_TYPES };\n", "// records.js \u2014 the \"list of things\" layout: expenses, habits, notes, todos.\n//\n// The author declares what a record IS (the same field declarations the\n// fields block uses) and optionally what the collection summarises to. The\n// whole CRUD lifecycle \u2014 list, add, edit, delete, empty state, selection,\n// navigation \u2014 is framework-owned, so none of it can be half-built.\n//\n// Two deliberate choices keep the state model tiny:\n//\n// add-then-edit \"Add\" creates the record from field defaults and navigates\n// straight into it. There is no separate draft object, so a\n// half-typed record can't be lost \u2014 it already exists.\n// edit-in-place Detail fields write into the record directly through\n// update(), so persistence and re-render are the same\n// debounced path every other block uses.\n//\n// Which record is open lives in view state (screen \"record\", arg = id), never\n// in data \u2014 restoring it on reload is correct, and deleting the open record\n// simply falls back to the list.\n\nimport { createElement as h } from \"react\";\nimport { Field, formatValue } from \"./blocks.js\";\n\nexport function recordDefaults(fields) {\n const rec = {};\n for (const f of fields) {\n rec[f.key] = f.value !== undefined ? f.value : f.type === \"check\" ? false : \"\";\n }\n return rec;\n}\n\n// Collision-proof enough for a per-user list; no coordination needed.\nfunction makeId() {\n return \"r\" + Date.now().toString(36) + Math.random().toString(36).slice(2, 8);\n}\n\nfunction rowTitle(spec, rec) {\n if (spec.title) return spec.title(rec);\n // Default: the first text-ish field, which is what a human would label by.\n const f = spec.fields.find((f) => !f.type || f.type === \"text\" || f.type === \"textarea\" || f.type === \"select\");\n const v = f && rec[f.key];\n return v === \"\" || v === undefined || v === null ? \"(untitled)\" : String(v);\n}\n\nfunction Summary({ spec, records }) {\n if (!spec.summary) return null;\n const items = spec.summary(records) || [];\n if (!items.length) return null;\n return h(\n \"div\",\n { className: \"caf-block caf-output\" },\n h(\n \"div\",\n { className: \"caf-output-grid\" },\n items.map((item, i) =>\n h(\n \"div\",\n { key: item.label || i, className: item.big ? \"caf-stat caf-stat-big\" : \"caf-stat\" },\n h(\"span\", { className: \"caf-stat-label\" }, item.label),\n h(\"span\", { className: \"caf-stat-value\" }, formatValue(item.value, item.format))\n )\n )\n )\n );\n}\n\nfunction ListScreen({ spec, ctx }) {\n const label = spec.label || \"item\";\n let records = ctx.data.records;\n if (spec.sort) records = records.slice().sort(spec.sort);\n\n function add() {\n const rec = { id: makeId(), ...recordDefaults(spec.fields) };\n ctx.update((d) => {\n d.records = [...d.records, rec];\n });\n ctx.go(\"record\", rec.id);\n }\n\n return h(\n \"div\",\n { className: \"caf-block caf-list\" },\n h(\n \"div\",\n { className: \"caf-toolbar\" },\n h(\"span\", { className: \"caf-count\" }, `${records.length} ${label}${records.length === 1 ? \"\" : \"s\"}`),\n h(\"button\", { type: \"button\", className: \"caf-btn caf-btn-primary\", onClick: add }, `Add ${label}`)\n ),\n records.length === 0\n ? h(\"div\", { className: \"caf-empty\" }, spec.empty || `No ${label}s yet. Add the first one.`)\n : records.map((rec) =>\n h(\n \"button\",\n {\n key: rec.id,\n type: \"button\",\n className: \"caf-row\",\n onClick: () => ctx.go(\"record\", rec.id),\n },\n h(\"span\", { className: \"caf-row-title\" }, rowTitle(spec, rec)),\n spec.subtitle ? h(\"span\", { className: \"caf-row-sub\" }, spec.subtitle(rec)) : null\n )\n )\n );\n}\n\nfunction DetailScreen({ spec, ctx, record }) {\n const label = spec.label || \"item\";\n\n function remove() {\n ctx.update((d) => {\n d.records = d.records.filter((r) => r.id !== record.id);\n });\n ctx.back();\n }\n\n return h(\n \"div\",\n { className: \"caf-block caf-fields\" },\n h(\n \"div\",\n { className: \"caf-toolbar\" },\n h(\"button\", { type: \"button\", className: \"caf-btn\", onClick: ctx.back }, \"\u2039 Back\"),\n h(\"button\", { type: \"button\", className: \"caf-btn caf-btn-danger\", onClick: remove }, `Delete ${label}`)\n ),\n spec.fields.map((field) =>\n h(Field, {\n key: field.key,\n field,\n value: record[field.key],\n onChange: (v) =>\n ctx.update((d) => {\n const rec = d.records.find((r) => r.id === record.id);\n if (rec) rec[field.key] = v;\n }),\n })\n )\n );\n}\n\nexport function RecordsLayout({ spec, ctx }) {\n const rspec = spec.records;\n\n if (ctx.view.screen === \"record\") {\n const record = ctx.data.records.find((r) => r.id === ctx.view.arg);\n // The open record can vanish (deleted, or stale view state from an earlier\n // version of the data) \u2014 fall back to the list rather than a blank pane.\n if (record) {\n return h(\"div\", { className: \"caf-panel caf-panel-single\" }, h(DetailScreen, { spec: rspec, ctx, record }));\n }\n }\n return h(\n \"div\",\n { className: \"caf-panel caf-panel-single\" },\n h(Summary, { spec: rspec, records: ctx.data.records }),\n h(ListScreen, { spec: rspec, ctx })\n );\n}\n", "// app.js \u2014 createApp: the whole framework's entry point.\n//\n// Returns a React component, so an artifact is `export default createApp({\u2026})`\n// with no mounting ceremony.\n//\n// Lifecycle, and deliberately only four stages:\n// hydrate read data + view from storage, merge over declared defaults\n// mount first render already holding real data, so there's no flash\n// run update() -> batched notify -> render, persistence debounced apart\n// error a boundary per block: one broken block shows its error, the rest live\n\nimport { createElement as h, useState, useEffect, hasReact, getReact } from \"react\";\nimport { createAppState } from \"./appState.js\";\nimport { themeCss } from \"./theme.js\";\nimport { BLOCKS, BLOCK_NAMES } from \"./blocks.js\";\nimport { RecordsLayout } from \"./records.js\";\n\nconst LAYOUTS = [\"panel\", \"records\"];\nconst RESERVED = [\"title\", \"empty\", \"wide\", \"onSelect\", \"subtitle\"];\n\n// Frontier models still invent identifiers a few percent of the time, so an\n// unknown name has to fail loudly and name the alternatives rather than\n// silently rendering nothing \u2014 a blank pane is indistinguishable from a bug.\nfunction validate(spec) {\n const layout = spec.layout || \"panel\";\n if (!LAYOUTS.includes(layout)) {\n throw new Error(\n `claude-artifact-framework: unknown layout \"${layout}\". Valid layouts: ${LAYOUTS.join(\", \")}.`\n );\n }\n if (layout === \"records\") {\n const r = spec.records;\n if (!r || !Array.isArray(r.fields) || r.fields.length === 0) {\n throw new Error(\n 'claude-artifact-framework: layout \"records\" needs `records: { fields: [...] }` \u2014 the same field declarations the fields block uses.'\n );\n }\n const seen = new Set();\n for (const f of r.fields) {\n if (!f || !f.key) throw new Error(\"claude-artifact-framework: every records field needs a `key`.\");\n if (f.key === \"id\") throw new Error('claude-artifact-framework: \"id\" is reserved on records \u2014 the framework assigns it.');\n if (seen.has(f.key)) throw new Error(`claude-artifact-framework: duplicate records field key \"${f.key}\".`);\n seen.add(f.key);\n }\n return layout;\n }\n const blocks = spec.blocks || [];\n if (!Array.isArray(blocks)) {\n throw new Error(\"claude-artifact-framework: `blocks` must be an array.\");\n }\n blocks.forEach((block, i) => {\n if (!block || typeof block !== \"object\") {\n throw new Error(`claude-artifact-framework: blocks[${i}] must be an object like { fields: [...] }.`);\n }\n const keys = Object.keys(block).filter((k) => !RESERVED.includes(k));\n const known = keys.filter((k) => BLOCK_NAMES.includes(k));\n if (known.length === 0) {\n throw new Error(\n `claude-artifact-framework: blocks[${i}] has no recognised block type (found: ${\n keys.join(\", \") || \"nothing\"\n }). Valid block types: ${BLOCK_NAMES.join(\", \")}.`\n );\n }\n if (known.length > 1) {\n throw new Error(\n `claude-artifact-framework: blocks[${i}] declares more than one block type (${known.join(\n \", \"\n )}). Split them into separate entries of \\`blocks\\`.`\n );\n }\n });\n return layout;\n}\n\n// Fields declare their own initial value, so the data shape is derived from\n// the declaration instead of being restated in a separate object. That removes\n// the key as an invention point: it is written exactly once.\nfunction defaultsFrom(spec) {\n const data = { ...(spec.data || {}) };\n if ((spec.layout || \"panel\") === \"records\" && !Array.isArray(data.records)) {\n data.records = [];\n }\n for (const block of spec.blocks || []) {\n for (const field of block.fields || []) {\n if (field && field.key !== undefined && !(field.key in data)) {\n data[field.key] = field.value !== undefined ? field.value : field.type === \"check\" ? false : \"\";\n }\n }\n }\n return data;\n}\n\n// Built on first use, not at module scope: `extends React.Component` needs a\n// real React, and at load time the host may not have handed one over yet.\nlet BlockBoundary = null;\n\nfunction boundary(React) {\n if (!BlockBoundary) {\n BlockBoundary = class extends React.Component {\n constructor(props) {\n super(props);\n this.state = { error: null };\n }\n static getDerivedStateFromError(error) {\n return { error };\n }\n render() {\n if (this.state.error) {\n return h(\n \"div\",\n { className: \"caf-block caf-block-error\" },\n h(\"strong\", null, \"This section failed to render\"),\n h(\"code\", null, String(this.state.error.message || this.state.error))\n );\n }\n return this.props.children;\n }\n };\n }\n return BlockBoundary;\n}\n\nfunction Block({ block, ctx }) {\n const name = Object.keys(block).find((k) => BLOCK_NAMES.includes(k));\n const Component = BLOCKS[name];\n return h(boundary(ctx.React), null, h(Component, { spec: block, ctx }));\n}\n\nfunction Panel({ spec, ctx }) {\n return h(\n \"div\",\n { className: \"caf-panel\" },\n (spec.blocks || []).map((block, i) =>\n h(\n \"section\",\n { key: i, className: block.wide ? \"caf-slot caf-slot-wide\" : \"caf-slot\" },\n h(Block, { block, ctx })\n )\n )\n );\n}\n\nconst LAYOUT_COMPONENTS = { panel: Panel, records: RecordsLayout };\n\nexport function createApp(spec = {}) {\n const layout = validate(spec);\n const state = createAppState(defaultsFrom(spec));\n const css = themeCss(spec.theme && spec.theme.seed) + BASE_CSS;\n\n return function App() {\n if (!hasReact()) {\n throw new Error(\n \"claude-artifact-framework: React not found. Hand it over once, before rendering:\\n\\n\" +\n ' import React from \"react\";\\n' +\n \" ArtifactKit.useReact(React);\\n\"\n );\n }\n const [, force] = useState(0);\n useEffect(() => {\n const unsubscribe = state.subscribe(() => force((n) => n + 1));\n // Hydration can finish before this effect runs \u2014 its notify() then lands\n // on zero listeners and nothing ever re-renders. Re-check on subscribe,\n // so a mount that raced hydration still leaves the loading screen.\n if (state.isHydrated()) force((n) => n + 1);\n return unsubscribe;\n }, []);\n\n const ctx = {\n React: getReact(),\n data: state.getData(),\n view: state.getView(),\n update: state.update,\n go: state.go,\n back: state.back,\n };\n\n const Layout = LAYOUT_COMPONENTS[layout];\n\n return h(\n \"div\",\n { className: \"caf-root\" },\n h(\"style\", { dangerouslySetInnerHTML: { __html: css } }),\n h(\n \"header\",\n { className: \"caf-header\" },\n spec.title ? h(\"h1\", null, spec.title) : null,\n spec.subtitle ? h(\"p\", null, spec.subtitle) : null\n ),\n state.isHydrated()\n ? h(Layout, { spec, ctx })\n : h(\"div\", { className: \"caf-block caf-loading\" }, \"Loading\u2026\")\n );\n };\n}\n\nconst BASE_CSS = `\n.caf-root {\n --caf-radius: 10px;\n box-sizing: border-box;\n min-height: 100vh;\n padding: 2rem 1.25rem 4rem;\n background: var(--caf-bg);\n color: var(--caf-text);\n font-family: -apple-system, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.caf-root *, .caf-root *::before, .caf-root *::after { box-sizing: inherit; }\n.caf-header { max-width: 760px; margin: 0 auto 1.5rem; }\n.caf-header h1 { margin: 0; font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; text-wrap: balance; }\n.caf-header p { margin: 0.4rem 0 0; color: var(--caf-muted); font-size: 0.95rem; line-height: 1.5; }\n.caf-panel { max-width: 760px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }\n.caf-slot { grid-column: span 2; min-width: 0; }\n@media (min-width: 720px) { .caf-slot { grid-column: span 1; } .caf-slot-wide { grid-column: span 2; } }\n.caf-block {\n background: var(--caf-surface);\n border: 1px solid var(--caf-border);\n border-radius: var(--caf-radius);\n padding: 1.1rem;\n display: flex;\n flex-direction: column;\n gap: 0.8rem;\n height: 100%;\n}\n.caf-block-title { margin: 0; font-size: 0.95rem; font-weight: 650; }\n.caf-field { display: flex; flex-direction: column; gap: 0.3rem; }\n.caf-field label { font-size: 0.78rem; font-weight: 600; color: var(--caf-muted); letter-spacing: 0.02em; }\n.caf-field input, .caf-field select, .caf-field textarea {\n font: inherit; font-size: 0.95rem; padding: 0.5rem 0.6rem;\n border-radius: 7px; border: 1px solid var(--caf-border);\n background: var(--caf-sunken); color: var(--caf-text); width: 100%;\n}\n.caf-field input:focus-visible, .caf-field select:focus-visible, .caf-field textarea:focus-visible,\n.caf-row:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }\n.caf-field input[aria-invalid=\"true\"] { border-color: var(--caf-danger); }\n.caf-check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; }\n.caf-hint { color: var(--caf-muted); font-size: 0.75rem; }\n.caf-error { color: var(--caf-danger); font-size: 0.75rem; font-weight: 600; }\n.caf-output-grid { display: flex; flex-direction: column; gap: 0.7rem; }\n.caf-stat { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }\n.caf-stat-label { color: var(--caf-muted); font-size: 0.82rem; }\n.caf-stat-value { font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }\n.caf-stat-big { flex-direction: column; align-items: flex-start; gap: 0.15rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--caf-border); }\n.caf-stat-big .caf-stat-value { font-size: 1.9rem; font-weight: 680; letter-spacing: -0.02em; color: var(--caf-accent); }\n.caf-list { padding: 0.4rem; gap: 0; }\n.caf-row {\n font: inherit; text-align: left; cursor: pointer;\n display: flex; flex-direction: column; gap: 0.15rem;\n padding: 0.65rem 0.7rem; border: none; border-radius: 7px;\n background: transparent; color: inherit; width: 100%;\n}\n.caf-row:hover { background: var(--caf-sunken); }\n.caf-row-title { font-size: 0.92rem; font-weight: 550; }\n.caf-row-sub { font-size: 0.78rem; color: var(--caf-muted); }\n.caf-panel-single { grid-template-columns: 1fr; }\n.caf-panel-single .caf-slot, .caf-panel-single > * { grid-column: span 1; }\n.caf-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.3rem 0.3rem 0.5rem; }\n.caf-count { font-size: 0.8rem; color: var(--caf-muted); font-variant-numeric: tabular-nums; }\n.caf-btn {\n font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;\n padding: 0.45rem 0.8rem; border-radius: 7px;\n border: 1px solid var(--caf-border); background: var(--caf-sunken); color: var(--caf-text);\n}\n.caf-btn:hover { filter: brightness(0.97); }\n.caf-btn:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }\n.caf-btn-primary { background: var(--caf-accent); border-color: var(--caf-accent); color: var(--caf-accentText); }\n.caf-btn-danger { background: transparent; border-color: var(--caf-danger); color: var(--caf-danger); }\n.caf-empty, .caf-loading { color: var(--caf-muted); font-size: 0.9rem; text-align: center; padding: 1.6rem 1rem; }\n.caf-block-error { border-color: var(--caf-danger); gap: 0.4rem; }\n.caf-block-error strong { font-size: 0.9rem; color: var(--caf-danger); }\n.caf-block-error code { font-size: 0.78rem; color: var(--caf-muted); word-break: break-word; }\n`;\n"],
5
+ "mappings": "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",
6
+ "names": ["debounce", "f", "React", "Component"]
7
7
  }
@@ -1,2 +1,90 @@
1
- var ArtifactKit=(()=>{var d=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var N=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},O=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of v(e))!J.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(n=m(e,o))||n.enumerable});return t};var x=t=>O(d({},"__esModule",{value:!0}),t);var E={};N(E,{createPersistedStore:()=>y,createSharedStore:()=>h,createStore:()=>p,storage:()=>a});function u(){return typeof window<"u"&&typeof window.storage=="object"&&window.storage!==null}function w(t){return{async get(e,r=void 0){if(!u())return r;try{let n=await window.storage.get(e,t);if(n?.value===void 0||n?.value===null)return r;try{return JSON.parse(n.value)}catch{return n.value}}catch{return r}},async set(e,r,{raw:n=!1}={}){if(!u())throw new Error("window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)");let o=n?r:JSON.stringify(r);if(typeof o!="string")throw new Error("window.storage only accepts strings \u2014 the value must be JSON-serializable");return window.storage.set(e,o,t)},async delete(e){if(u())try{await window.storage.delete(e,t)}catch{}},async list(e){if(!u())return[];try{return(await window.storage.list(e,t))?.keys||[]}catch{return[]}}}}var a={...w(!1),shared:w(!0),available:u};function l(t){let e=t,r=new Set;function n(){return e}function o(s){e=typeof s=="function"?s(e):s,r.forEach(f=>f(e))}function c(s){return r.add(s),()=>r.delete(s)}return{get:n,set:o,subscribe:c}}function g(t,e){let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>t(...n),e)}}function p(t){return l(t)}function y(t,e,{debounceMs:r=300}={}){let n=l(e),o=g(s=>a.set(t,s),r),c=a.get(t,e).then(s=>n.set(s));return n.subscribe(o),{...n,ready:c}}function h(t,e,{pollMs:r=2e3,debounceMs:n=300}={}){let o=l(e),c=g(i=>a.shared.set(t,i),n),s=!1;o.subscribe(i=>{s||c(i)});async function f(){let i=await a.shared.get(t,e);JSON.stringify(i)!==JSON.stringify(o.get())&&(s=!0,o.set(i),s=!1)}let b=f(),S=setInterval(f,r);return{...o,ready:b,stop:()=>clearInterval(S)}}return x(E);})();
1
+ var ArtifactKit=(()=>{var A=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var oe=Object.prototype.hasOwnProperty;var ce=(e,t)=>{for(var r in t)A(e,r,{get:t[r],enumerable:!0})},ie=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of ae(t))!oe.call(e,a)&&a!==r&&A(e,a,{get:()=>t[a],enumerable:!(n=ne(t,a))||n.enumerable});return e};var se=e=>ie(A({},"__esModule",{value:!0}),e);var Oe={};ce(Oe,{contrast:()=>M,createApp:()=>te,createPersistedStore:()=>_,createSharedStore:()=>H,createStore:()=>V,hasReact:()=>x,palette:()=>z,storage:()=>m,themeCss:()=>S,useReact:()=>I});function k(){return typeof window<"u"&&typeof window.storage=="object"&&window.storage!==null}function F(e){return{async get(t,r=void 0){if(!k())return r;try{let n=await window.storage.get(t,e);if(n?.value===void 0||n?.value===null)return r;try{return JSON.parse(n.value)}catch{return n.value}}catch{return r}},async set(t,r,{raw:n=!1}={}){if(!k())throw new Error("window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)");let a=n?r:JSON.stringify(r);if(typeof a!="string")throw new Error("window.storage only accepts strings \u2014 the value must be JSON-serializable");return window.storage.set(t,a,e)},async delete(t){if(k())try{await window.storage.delete(t,e)}catch{}},async list(t){if(!k())return[];try{return(await window.storage.list(t,e))?.keys||[]}catch{return[]}}}}var m={...F(!1),shared:F(!0),available:k};function C(e){let t=e,r=new Set;function n(){return t}function a(c){t=typeof c=="function"?c(t):c,r.forEach(s=>s(t))}function i(c){return r.add(c),()=>r.delete(c)}return{get:n,set:a,subscribe:i}}function B(e,t){let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>e(...n),t)}}function V(e){return C(e)}function _(e,t,{debounceMs:r=300}={}){let n=C(t),a=B(c=>m.set(e,c),r),i=m.get(e,t).then(c=>n.set(c));return n.subscribe(a),{...n,ready:i}}function H(e,t,{pollMs:r=2e3,debounceMs:n=300}={}){let a=C(t),i=B(p=>m.shared.set(e,p),n),c=!1;a.subscribe(p=>{c||i(p)});async function s(){let p=await m.shared.get(e,t);JSON.stringify(p)!==JSON.stringify(a.get())&&(c=!0,a.set(p),c=!1)}let f=s(),d=setInterval(s,r);return{...a,ready:f,stop:()=>clearInterval(d)}}var y=typeof globalThis<"u"?globalThis.React:void 0;function I(e){return y=e,e}function x(){return!!y}function P(){return w()}function w(){if(!y)throw new Error(`claude-artifact-framework: React not found. Hand it over once, before createApp:
2
+
3
+ import React from "react";
4
+ ArtifactKit.useReact(React);
5
+ `);return y}var o=(...e)=>w().createElement(...e),K=(...e)=>w().useState(...e),Y=(...e)=>w().useEffect(...e);var Be=y&&y.Component||class{render(){return w()}};var q="caf:data",J="caf:view",U={screen:null,arg:null,stack:[],step:0,selected:null};function v(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function G(e,t){if(!v(e)||!v(t))return t===void 0?e:t;let r={...e};for(let n of Object.keys(t))r[n]=v(e[n])?G(e[n],t[n]):t[n];return r}function W(e,t){let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>e(...n),t)}}function Q(e,{debounceMs:t=400}={}){let r=$(e),n={...U},a=!1,i=new Set,c=!1;function s(){c||(c=!0,Promise.resolve().then(()=>{c=!1;for(let l of i)l()}))}let f=W(()=>m.set(q,r),t),d=W(()=>m.set(J,n),t),p=(async()=>{let[l,b]=await Promise.all([m.get(q,void 0),m.get(J,void 0)]);l!==void 0&&(r=G(e,l)),b!==void 0&&(n={...U,...b}),a=!0,s()})();function re(l){let b=l(r);b!==void 0&&(r=b),r={...r},f(),s()}function R(l){n={...n,...l},d(),s()}return{ready:p,isHydrated:()=>a,getData:()=>r,getView:()=>n,update:re,setView:R,go(l,b){R({stack:[...n.stack,{screen:n.screen,arg:n.arg}],screen:l,arg:b})},back(){let l=n.stack.slice(),b=l.pop()||{screen:null,arg:null};R({stack:l,screen:b.screen,arg:b.arg})},subscribe(l){return i.add(l),()=>i.delete(l)}}}function $(e){if(Array.isArray(e))return e.map($);if(v(e)){let t={};for(let r of Object.keys(e))t[r]=$(e[r]);return t}return e}function h(e,t,r){return Math.min(r,Math.max(t,e))}function T(e){let t=String(e).replace("#","").trim();t.length===3&&(t=t.split("").map(n=>n+n).join(""));let r=parseInt(t,16);return Number.isFinite(r)?[r>>16&255,r>>8&255,r&255]:[59,110,246]}function fe(e){return"#"+e.map(t=>h(Math.round(t),0,255).toString(16).padStart(2,"0")).join("")}function le([e,t,r]){e/=255,t/=255,r/=255;let n=Math.max(e,t,r),a=Math.min(e,t,r),i=(n+a)/2,c=n-a,s=0,f=0;return c&&(f=i>.5?c/(2-n-a):c/(n+a),n===e?s=(t-r)/c+(t<r?6:0):n===t?s=(r-e)/c+2:s=(e-t)/c+4,s/=6),[s*360,f*100,i*100]}function ue(e,t,r){if(e=(e%360+360)%360/360,t=h(t,0,100)/100,r=h(r,0,100)/100,!t)return[r*255,r*255,r*255];let n=r<.5?r*(1+t):r+t-r*t,a=2*r-n,i=c=>(c<0&&(c+=1),c>1&&(c-=1),c<1/6?a+(n-a)*6*c:c<1/2?n:c<2/3?a+(n-a)*(2/3-c)*6:a);return[i(e+1/3)*255,i(e)*255,i(e-1/3)*255]}function u(e,t,r){return fe(ue(e,t,r))}function X(e){let t=e.map(r=>(r/=255,r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4)));return .2126*t[0]+.7152*t[1]+.0722*t[2]}function M(e,t){let r=X(T(e)),n=X(T(t));return(Math.max(r,n)+.05)/(Math.min(r,n)+.05)}function g(e,t,r,n,a,i){for(let c=a;c>=4&&c<=96;c+=i){let s=u(e,t,c);if(M(s,r)>=n)return s}return u(e,t,i<0?24:82)}function z(e="#3b6ef6"){let[t,r]=le(T(e)),n=h(r,30,88),a=h(n*.1,3,9),i=u(t,a*.4,100),c=u(t,a*1.4,13);return{light:{bg:u(t,a,96.5),surface:i,sunken:u(t,a,93),border:u(t,a,86),text:u(t,a*1.6,11),muted:u(t,a*1.2,41),accent:g(t,n,"#ffffff",4.5,54,-2),accentText:"#ffffff",danger:g(2,68,"#ffffff",4.5,54,-2),ok:g(148,62,"#ffffff",4.5,44,-2),warn:g(38,88,"#ffffff",4.5,44,-2)},dark:{bg:u(t,a*1.5,9),surface:c,sunken:u(t,a*1.5,7),border:u(t,a*1.3,24),text:u(t,a*.6,95),muted:u(t,a*.8,66),accent:g(t,h(n,40,80),c,4.5,62,2),accentText:u(t,a*2,8),danger:g(2,70,c,4.5,62,2),ok:g(148,55,c,4.5,62,2),warn:g(38,80,c,4.5,62,2)}}}function N(e){return Object.entries(e).map(([t,r])=>`--caf-${t}: ${r};`).join("")}function S(e){let t=z(e);return`
6
+ :root { ${N(t.light)} }
7
+ @media (prefers-color-scheme: dark) { :root { ${N(t.dark)} } }
8
+ :root[data-theme="dark"] { ${N(t.dark)} }
9
+ :root[data-theme="light"] { ${N(t.light)} }
10
+ `}function O(e,t){if(e==null||e==="")return"\u2014";let r=Number(e);switch(t){case"money":return Number.isFinite(r)?r.toLocaleString(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2}):String(e);case"percent":return Number.isFinite(r)?`${r.toLocaleString(void 0,{maximumFractionDigits:2})}%`:String(e);case"number":return Number.isFinite(r)?r.toLocaleString(void 0,{maximumFractionDigits:2}):String(e);case"date":return e instanceof Date?e.toLocaleDateString():String(e);default:return String(e)}}function de(e,t){if(e.required&&(t===""||t===null||t===void 0))return"Required";if(t===""||t===null||t===void 0)return null;if(e.type==="number"||e.type==="money"||e.type==="percent"){let r=Number(t);if(!Number.isFinite(r))return"Must be a number";if(e.min!==void 0&&r<e.min)return`Must be at least ${e.min}`;if(e.max!==void 0&&r>e.max)return`Must be at most ${e.max}`}return null}function j({field:e,value:t,onChange:r}){let n=de(e,t),a=`caf-f-${e.key}`,i=e.type==="number"||e.type==="money"||e.type==="percent";if(e.type==="check")return o("label",{className:"caf-check"},o("input",{id:a,type:"checkbox",checked:!!t,onChange:f=>r(f.target.checked)}),o("span",null,e.label||e.key));let c={id:a,value:t??"","aria-invalid":n?"true":void 0,onChange:f=>r(i?me(f.target.value):f.target.value)},s;return e.type==="textarea"?s=o("textarea",{...c,rows:e.rows||3}):e.type==="select"?s=o("select",c,o("option",{value:""},e.placeholder||"Select\u2026"),(e.options||[]).map(f=>{let d=typeof f=="string"?f:f.value,p=typeof f=="string"?f:f.label;return o("option",{key:d,value:d},p)})):s=o("input",{...c,type:e.type==="date"?"date":i?"number":"text",min:e.min,max:e.max,step:e.step||(e.type==="money"||e.type==="percent"?"any":void 0),placeholder:e.placeholder}),o("div",{className:"caf-field"},o("label",{htmlFor:a},e.label||e.key),s,e.hint&&!n?o("small",{className:"caf-hint"},e.hint):null,n?o("small",{className:"caf-error"},n):null)}function me(e){if(e==="")return"";let t=Number(e);return Number.isFinite(t)?t:e}function pe({spec:e,ctx:t}){let r=e.fields||[];return o("div",{className:"caf-block caf-fields"},e.title?o("h2",{className:"caf-block-title"},e.title):null,r.map(n=>o(j,{key:n.key,field:n,value:t.data[n.key],onChange:a=>t.update(i=>{i[n.key]=a})})))}function be({spec:e,ctx:t}){let r=typeof e.output=="function"?e.output(t.data):e.output||[];return r.length?o("div",{className:"caf-block caf-output"},e.title?o("h2",{className:"caf-block-title"},e.title):null,o("div",{className:"caf-output-grid"},r.map((n,a)=>o("div",{key:n.label||a,className:n.big?"caf-stat caf-stat-big":"caf-stat"},o("span",{className:"caf-stat-label"},n.label),o("span",{className:"caf-stat-value"},O(n.value,n.format)),n.hint?o("small",{className:"caf-hint"},n.hint):null)))):o("div",{className:"caf-block caf-empty"},e.empty||"Nothing to show yet.")}function ge({spec:e}){let t=typeof e.text=="function"?e.text():e.text;return o("div",{className:"caf-block caf-text"},e.title?o("h2",{className:"caf-block-title"},e.title):null,o("p",null,t))}function ye({spec:e,ctx:t}){let r=(typeof e.list=="function"?e.list(t.data):e.list)||[];if(!r.length)return o("div",{className:"caf-block caf-empty"},e.empty||"Nothing here yet.");let n=e.title||(a=>a.title??a.name??a.label??String(a));return o("div",{className:"caf-block caf-list"},r.map((a,i)=>o("button",{key:a.id??i,className:"caf-row",type:"button",onClick:e.onSelect?()=>e.onSelect(a,t):void 0},o("span",{className:"caf-row-title"},n(a)),e.subtitle?o("span",{className:"caf-row-sub"},e.subtitle(a)):null)))}function he({spec:e,ctx:t}){let r=e.custom(t);return typeof r=="string"?o("div",{className:"caf-block",dangerouslySetInnerHTML:{__html:r}}):o("div",{className:"caf-block"},r)}var D={fields:pe,output:be,text:ge,list:ye,custom:he},E=Object.keys(D);function ke(e){let t={};for(let r of e)t[r.key]=r.value!==void 0?r.value:r.type==="check"?!1:"";return t}function we(){return"r"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function xe(e,t){if(e.title)return e.title(t);let r=e.fields.find(a=>!a.type||a.type==="text"||a.type==="textarea"||a.type==="select"),n=r&&t[r.key];return n===""||n===void 0||n===null?"(untitled)":String(n)}function ve({spec:e,records:t}){if(!e.summary)return null;let r=e.summary(t)||[];return r.length?o("div",{className:"caf-block caf-output"},o("div",{className:"caf-output-grid"},r.map((n,a)=>o("div",{key:n.label||a,className:n.big?"caf-stat caf-stat-big":"caf-stat"},o("span",{className:"caf-stat-label"},n.label),o("span",{className:"caf-stat-value"},O(n.value,n.format)))))):null}function Ne({spec:e,ctx:t}){let r=e.label||"item",n=t.data.records;e.sort&&(n=n.slice().sort(e.sort));function a(){let i={id:we(),...ke(e.fields)};t.update(c=>{c.records=[...c.records,i]}),t.go("record",i.id)}return o("div",{className:"caf-block caf-list"},o("div",{className:"caf-toolbar"},o("span",{className:"caf-count"},`${n.length} ${r}${n.length===1?"":"s"}`),o("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:a},`Add ${r}`)),n.length===0?o("div",{className:"caf-empty"},e.empty||`No ${r}s yet. Add the first one.`):n.map(i=>o("button",{key:i.id,type:"button",className:"caf-row",onClick:()=>t.go("record",i.id)},o("span",{className:"caf-row-title"},xe(e,i)),e.subtitle?o("span",{className:"caf-row-sub"},e.subtitle(i)):null)))}function Se({spec:e,ctx:t,record:r}){let n=e.label||"item";function a(){t.update(i=>{i.records=i.records.filter(c=>c.id!==r.id)}),t.back()}return o("div",{className:"caf-block caf-fields"},o("div",{className:"caf-toolbar"},o("button",{type:"button",className:"caf-btn",onClick:t.back},"\u2039 Back"),o("button",{type:"button",className:"caf-btn caf-btn-danger",onClick:a},`Delete ${n}`)),e.fields.map(i=>o(j,{key:i.key,field:i,value:r[i.key],onChange:c=>t.update(s=>{let f=s.records.find(d=>d.id===r.id);f&&(f[i.key]=c)})})))}function Z({spec:e,ctx:t}){let r=e.records;if(t.view.screen==="record"){let n=t.data.records.find(a=>a.id===t.view.arg);if(n)return o("div",{className:"caf-panel caf-panel-single"},o(Se,{spec:r,ctx:t,record:n}))}return o("div",{className:"caf-panel caf-panel-single"},o(ve,{spec:r,records:t.data.records}),o(Ne,{spec:r,ctx:t}))}var ee=["panel","records"],Ee=["title","empty","wide","onSelect","subtitle"];function Re(e){let t=e.layout||"panel";if(!ee.includes(t))throw new Error(`claude-artifact-framework: unknown layout "${t}". Valid layouts: ${ee.join(", ")}.`);if(t==="records"){let n=e.records;if(!n||!Array.isArray(n.fields)||n.fields.length===0)throw new Error('claude-artifact-framework: layout "records" needs `records: { fields: [...] }` \u2014 the same field declarations the fields block uses.');let a=new Set;for(let i of n.fields){if(!i||!i.key)throw new Error("claude-artifact-framework: every records field needs a `key`.");if(i.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on records \u2014 the framework assigns it.');if(a.has(i.key))throw new Error(`claude-artifact-framework: duplicate records field key "${i.key}".`);a.add(i.key)}return t}let r=e.blocks||[];if(!Array.isArray(r))throw new Error("claude-artifact-framework: `blocks` must be an array.");return r.forEach((n,a)=>{if(!n||typeof n!="object")throw new Error(`claude-artifact-framework: blocks[${a}] must be an object like { fields: [...] }.`);let i=Object.keys(n).filter(s=>!Ee.includes(s)),c=i.filter(s=>E.includes(s));if(c.length===0)throw new Error(`claude-artifact-framework: blocks[${a}] has no recognised block type (found: ${i.join(", ")||"nothing"}). Valid block types: ${E.join(", ")}.`);if(c.length>1)throw new Error(`claude-artifact-framework: blocks[${a}] declares more than one block type (${c.join(", ")}). Split them into separate entries of \`blocks\`.`)}),t}function Ae(e){let t={...e.data||{}};(e.layout||"panel")==="records"&&!Array.isArray(t.records)&&(t.records=[]);for(let r of e.blocks||[])for(let n of r.fields||[])n&&n.key!==void 0&&!(n.key in t)&&(t[n.key]=n.value!==void 0?n.value:n.type==="check"?!1:"");return t}var L=null;function Ce(e){return L||(L=class extends e.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?o("div",{className:"caf-block caf-block-error"},o("strong",null,"This section failed to render"),o("code",null,String(this.state.error.message||this.state.error))):this.props.children}}),L}function $e({block:e,ctx:t}){let r=Object.keys(e).find(a=>E.includes(a)),n=D[r];return o(Ce(t.React),null,o(n,{spec:e,ctx:t}))}function Te({spec:e,ctx:t}){return o("div",{className:"caf-panel"},(e.blocks||[]).map((r,n)=>o("section",{key:n,className:r.wide?"caf-slot caf-slot-wide":"caf-slot"},o($e,{block:r,ctx:t}))))}var Me={panel:Te,records:Z};function te(e={}){let t=Re(e),r=Q(Ae(e)),n=S(e.theme&&e.theme.seed)+ze;return function(){if(!x())throw new Error(`claude-artifact-framework: React not found. Hand it over once, before rendering:
11
+
12
+ import React from "react";
13
+ ArtifactKit.useReact(React);
14
+ `);let[,i]=K(0);Y(()=>{let f=r.subscribe(()=>i(d=>d+1));return r.isHydrated()&&i(d=>d+1),f},[]);let c={React:P(),data:r.getData(),view:r.getView(),update:r.update,go:r.go,back:r.back},s=Me[t];return o("div",{className:"caf-root"},o("style",{dangerouslySetInnerHTML:{__html:n}}),o("header",{className:"caf-header"},e.title?o("h1",null,e.title):null,e.subtitle?o("p",null,e.subtitle):null),r.isHydrated()?o(s,{spec:e,ctx:c}):o("div",{className:"caf-block caf-loading"},"Loading\u2026"))}}var ze=`
15
+ .caf-root {
16
+ --caf-radius: 10px;
17
+ box-sizing: border-box;
18
+ min-height: 100vh;
19
+ padding: 2rem 1.25rem 4rem;
20
+ background: var(--caf-bg);
21
+ color: var(--caf-text);
22
+ font-family: -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
23
+ -webkit-font-smoothing: antialiased;
24
+ }
25
+ .caf-root *, .caf-root *::before, .caf-root *::after { box-sizing: inherit; }
26
+ .caf-header { max-width: 760px; margin: 0 auto 1.5rem; }
27
+ .caf-header h1 { margin: 0; font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; text-wrap: balance; }
28
+ .caf-header p { margin: 0.4rem 0 0; color: var(--caf-muted); font-size: 0.95rem; line-height: 1.5; }
29
+ .caf-panel { max-width: 760px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
30
+ .caf-slot { grid-column: span 2; min-width: 0; }
31
+ @media (min-width: 720px) { .caf-slot { grid-column: span 1; } .caf-slot-wide { grid-column: span 2; } }
32
+ .caf-block {
33
+ background: var(--caf-surface);
34
+ border: 1px solid var(--caf-border);
35
+ border-radius: var(--caf-radius);
36
+ padding: 1.1rem;
37
+ display: flex;
38
+ flex-direction: column;
39
+ gap: 0.8rem;
40
+ height: 100%;
41
+ }
42
+ .caf-block-title { margin: 0; font-size: 0.95rem; font-weight: 650; }
43
+ .caf-field { display: flex; flex-direction: column; gap: 0.3rem; }
44
+ .caf-field label { font-size: 0.78rem; font-weight: 600; color: var(--caf-muted); letter-spacing: 0.02em; }
45
+ .caf-field input, .caf-field select, .caf-field textarea {
46
+ font: inherit; font-size: 0.95rem; padding: 0.5rem 0.6rem;
47
+ border-radius: 7px; border: 1px solid var(--caf-border);
48
+ background: var(--caf-sunken); color: var(--caf-text); width: 100%;
49
+ }
50
+ .caf-field input:focus-visible, .caf-field select:focus-visible, .caf-field textarea:focus-visible,
51
+ .caf-row:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
52
+ .caf-field input[aria-invalid="true"] { border-color: var(--caf-danger); }
53
+ .caf-check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; }
54
+ .caf-hint { color: var(--caf-muted); font-size: 0.75rem; }
55
+ .caf-error { color: var(--caf-danger); font-size: 0.75rem; font-weight: 600; }
56
+ .caf-output-grid { display: flex; flex-direction: column; gap: 0.7rem; }
57
+ .caf-stat { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
58
+ .caf-stat-label { color: var(--caf-muted); font-size: 0.82rem; }
59
+ .caf-stat-value { font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
60
+ .caf-stat-big { flex-direction: column; align-items: flex-start; gap: 0.15rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--caf-border); }
61
+ .caf-stat-big .caf-stat-value { font-size: 1.9rem; font-weight: 680; letter-spacing: -0.02em; color: var(--caf-accent); }
62
+ .caf-list { padding: 0.4rem; gap: 0; }
63
+ .caf-row {
64
+ font: inherit; text-align: left; cursor: pointer;
65
+ display: flex; flex-direction: column; gap: 0.15rem;
66
+ padding: 0.65rem 0.7rem; border: none; border-radius: 7px;
67
+ background: transparent; color: inherit; width: 100%;
68
+ }
69
+ .caf-row:hover { background: var(--caf-sunken); }
70
+ .caf-row-title { font-size: 0.92rem; font-weight: 550; }
71
+ .caf-row-sub { font-size: 0.78rem; color: var(--caf-muted); }
72
+ .caf-panel-single { grid-template-columns: 1fr; }
73
+ .caf-panel-single .caf-slot, .caf-panel-single > * { grid-column: span 1; }
74
+ .caf-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.3rem 0.3rem 0.5rem; }
75
+ .caf-count { font-size: 0.8rem; color: var(--caf-muted); font-variant-numeric: tabular-nums; }
76
+ .caf-btn {
77
+ font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
78
+ padding: 0.45rem 0.8rem; border-radius: 7px;
79
+ border: 1px solid var(--caf-border); background: var(--caf-sunken); color: var(--caf-text);
80
+ }
81
+ .caf-btn:hover { filter: brightness(0.97); }
82
+ .caf-btn:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
83
+ .caf-btn-primary { background: var(--caf-accent); border-color: var(--caf-accent); color: var(--caf-accentText); }
84
+ .caf-btn-danger { background: transparent; border-color: var(--caf-danger); color: var(--caf-danger); }
85
+ .caf-empty, .caf-loading { color: var(--caf-muted); font-size: 0.9rem; text-align: center; padding: 1.6rem 1rem; }
86
+ .caf-block-error { border-color: var(--caf-danger); gap: 0.4rem; }
87
+ .caf-block-error strong { font-size: 0.9rem; color: var(--caf-danger); }
88
+ .caf-block-error code { font-size: 0.78rem; color: var(--caf-muted); word-break: break-word; }
89
+ `;return se(Oe);})();
2
90
  //# sourceMappingURL=index.global.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.js", "../src/storage.js", "../src/state.js"],
4
- "sourcesContent": ["// Barrel file \u2014 every module lives in its own src/<name>.js and gets one\n// export line here. Nothing else needs to change to add a module: no build\n// config, no separate entry points, both dist bundles pick it up automatically.\n\nexport { storage } from \"./storage.js\";\nexport { createStore, createPersistedStore, createSharedStore } from \"./state.js\";\n", "// storage.js \u2014 wrapper over window.storage (Chat Artifacts, published only).\n//\n// Verified empirically against the real runtime: get/set/delete/list all\n// take (key, shared = false) and return a Promise resolving to\n// { key, value, shared, \"@type\": \"...StorageXResponse\" }. Confirmed:\n// - values must be strings (a raw object throws \"Invalid payload content\")\n// - shared=true/false is a real, working scope switch\n// - failures (including \"key not found\") all throw the same generic\n// message with no distinguishing `code` \u2014 there is no reliable way to\n// tell \"empty\" from \"backend error\" from the error alone.\n\nfunction available() {\n return typeof window !== \"undefined\" && typeof window.storage === \"object\" && window.storage !== null;\n}\n\nfunction scope(shared) {\n return {\n async get(key, fallback = undefined) {\n if (!available()) return fallback;\n try {\n const res = await window.storage.get(key, shared);\n if (res?.value === undefined || res?.value === null) return fallback;\n try {\n return JSON.parse(res.value);\n } catch {\n return res.value; // not JSON \u2014 a plain string written via set(key, value, { raw: true })\n }\n } catch {\n // See file header: this same catch fires for \"key does not exist\"\n // and for a real backend failure. Treating both as \"no value\" is\n // the safer default for a read path, at the cost of hiding outages.\n return fallback;\n }\n },\n\n async set(key, value, { raw = false } = {}) {\n if (!available()) {\n throw new Error(\"window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)\");\n }\n const payload = raw ? value : JSON.stringify(value);\n if (typeof payload !== \"string\") {\n throw new Error(\"window.storage only accepts strings \u2014 the value must be JSON-serializable\");\n }\n return window.storage.set(key, payload, shared);\n },\n\n async delete(key) {\n if (!available()) return;\n try {\n await window.storage.delete(key, shared);\n } catch {\n // same ambiguity as get() \u2014 silently a no-op if the key never existed\n }\n },\n\n async list(prefix) {\n if (!available()) return [];\n try {\n const res = await window.storage.list(prefix, shared);\n return res?.keys || [];\n } catch {\n return [];\n }\n },\n };\n}\n\n// storage.get/set/delete/list operate on the per-viewer (personal) scope.\n// storage.shared.* are the same four methods against the shared scope, where\n// every viewer of the artifact reads and writes the same state.\nexport const storage = { ...scope(false), shared: scope(true), available };\n", "// state.js \u2014 small reactive stores for artifact UI state, layered on storage.js.\n//\n// Three tiers, each a superset of the previous:\n// createStore in-memory only, no persistence\n// createPersistedStore loads from storage once, saves (debounced) on every\n// change \u2014 personal scope, single viewer\n// createSharedStore same, but polls storage.shared so every viewer of a\n// published artifact converges on the same state\n//\n// createSharedStore is last-write-wins with no merge: if two viewers change\n// the same key inside one poll window, whichever write lands last on the\n// server wins and the other is silently overwritten on the next poll. Fine\n// for \"everyone sees the same board/list\", not a CRDT.\n\nimport { storage } from \"./storage.js\";\n\nfunction makeStore(initialState) {\n let state = initialState;\n const subscribers = new Set();\n\n function get() {\n return state;\n }\n\n function set(next) {\n state = typeof next === \"function\" ? next(state) : next;\n subscribers.forEach((fn) => fn(state));\n }\n\n function subscribe(fn) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n return { get, set, subscribe };\n}\n\nfunction debounce(fn, ms) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n };\n}\n\nexport function createStore(initialState) {\n return makeStore(initialState);\n}\n\nexport function createPersistedStore(key, initialState, { debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.set(key, value), debounceMs);\n\n const ready = storage.get(key, initialState).then((loaded) => store.set(loaded));\n store.subscribe(persist);\n\n return { ...store, ready };\n}\n\nexport function createSharedStore(key, initialState, { pollMs = 2000, debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.shared.set(key, value), debounceMs);\n let applyingRemote = false;\n\n store.subscribe((value) => {\n if (!applyingRemote) persist(value);\n });\n\n async function poll() {\n const remote = await storage.shared.get(key, initialState);\n if (JSON.stringify(remote) === JSON.stringify(store.get())) return;\n applyingRemote = true;\n store.set(remote);\n applyingRemote = false;\n }\n\n const ready = poll();\n const timer = setInterval(poll, pollMs);\n\n return { ...store, ready, stop: () => clearInterval(timer) };\n}\n"],
5
- "mappings": "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",
6
- "names": ["index_exports", "__export", "createPersistedStore", "createSharedStore", "createStore", "storage", "available", "scope", "shared", "key", "fallback", "res", "value", "raw", "payload", "prefix", "storage", "makeStore", "initialState", "state", "subscribers", "get", "set", "next", "fn", "subscribe", "debounce", "ms", "timer", "args", "createStore", "createPersistedStore", "key", "debounceMs", "store", "persist", "value", "storage", "ready", "loaded", "createSharedStore", "pollMs", "applyingRemote", "poll", "remote"]
3
+ "sources": ["../src/index.js", "../src/storage.js", "../src/state.js", "../src/react-runtime.js", "../src/appState.js", "../src/theme.js", "../src/blocks.js", "../src/records.js", "../src/app.js"],
4
+ "sourcesContent": ["// Barrel file \u2014 every module lives in its own src/<name>.js and gets one\n// export line here. Nothing else needs to change to add a module: no build\n// config, no separate entry points, both dist bundles pick it up automatically.\n\nexport { storage } from \"./storage.js\";\nexport { createStore, createPersistedStore, createSharedStore } from \"./state.js\";\nexport { createApp } from \"./app.js\";\nexport { palette, themeCss, contrast } from \"./theme.js\";\nexport { useReact, hasReact } from \"./react-runtime.js\";\n", "// storage.js \u2014 wrapper over window.storage (Chat Artifacts, published only).\n//\n// Verified empirically against the real runtime: get/set/delete/list all\n// take (key, shared = false) and return a Promise resolving to\n// { key, value, shared, \"@type\": \"...StorageXResponse\" }. Confirmed:\n// - values must be strings (a raw object throws \"Invalid payload content\")\n// - shared=true/false is a real, working scope switch\n// - failures (including \"key not found\") all throw the same generic\n// message with no distinguishing `code` \u2014 there is no reliable way to\n// tell \"empty\" from \"backend error\" from the error alone.\n\nfunction available() {\n return typeof window !== \"undefined\" && typeof window.storage === \"object\" && window.storage !== null;\n}\n\nfunction scope(shared) {\n return {\n async get(key, fallback = undefined) {\n if (!available()) return fallback;\n try {\n const res = await window.storage.get(key, shared);\n if (res?.value === undefined || res?.value === null) return fallback;\n try {\n return JSON.parse(res.value);\n } catch {\n return res.value; // not JSON \u2014 a plain string written via set(key, value, { raw: true })\n }\n } catch {\n // See file header: this same catch fires for \"key does not exist\"\n // and for a real backend failure. Treating both as \"no value\" is\n // the safer default for a read path, at the cost of hiding outages.\n return fallback;\n }\n },\n\n async set(key, value, { raw = false } = {}) {\n if (!available()) {\n throw new Error(\"window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)\");\n }\n const payload = raw ? value : JSON.stringify(value);\n if (typeof payload !== \"string\") {\n throw new Error(\"window.storage only accepts strings \u2014 the value must be JSON-serializable\");\n }\n return window.storage.set(key, payload, shared);\n },\n\n async delete(key) {\n if (!available()) return;\n try {\n await window.storage.delete(key, shared);\n } catch {\n // same ambiguity as get() \u2014 silently a no-op if the key never existed\n }\n },\n\n async list(prefix) {\n if (!available()) return [];\n try {\n const res = await window.storage.list(prefix, shared);\n return res?.keys || [];\n } catch {\n return [];\n }\n },\n };\n}\n\n// storage.get/set/delete/list operate on the per-viewer (personal) scope.\n// storage.shared.* are the same four methods against the shared scope, where\n// every viewer of the artifact reads and writes the same state.\nexport const storage = { ...scope(false), shared: scope(true), available };\n", "// state.js \u2014 small reactive stores for artifact UI state, layered on storage.js.\n//\n// Three tiers, each a superset of the previous:\n// createStore in-memory only, no persistence\n// createPersistedStore loads from storage once, saves (debounced) on every\n// change \u2014 personal scope, single viewer\n// createSharedStore same, but polls storage.shared so every viewer of a\n// published artifact converges on the same state\n//\n// createSharedStore is last-write-wins with no merge: if two viewers change\n// the same key inside one poll window, whichever write lands last on the\n// server wins and the other is silently overwritten on the next poll. Fine\n// for \"everyone sees the same board/list\", not a CRDT.\n\nimport { storage } from \"./storage.js\";\n\nfunction makeStore(initialState) {\n let state = initialState;\n const subscribers = new Set();\n\n function get() {\n return state;\n }\n\n function set(next) {\n state = typeof next === \"function\" ? next(state) : next;\n subscribers.forEach((fn) => fn(state));\n }\n\n function subscribe(fn) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n return { get, set, subscribe };\n}\n\nfunction debounce(fn, ms) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n };\n}\n\nexport function createStore(initialState) {\n return makeStore(initialState);\n}\n\nexport function createPersistedStore(key, initialState, { debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.set(key, value), debounceMs);\n\n const ready = storage.get(key, initialState).then((loaded) => store.set(loaded));\n store.subscribe(persist);\n\n return { ...store, ready };\n}\n\nexport function createSharedStore(key, initialState, { pollMs = 2000, debounceMs = 300 } = {}) {\n const store = makeStore(initialState);\n const persist = debounce((value) => storage.shared.set(key, value), debounceMs);\n let applyingRemote = false;\n\n store.subscribe((value) => {\n if (!applyingRemote) persist(value);\n });\n\n async function poll() {\n const remote = await storage.shared.get(key, initialState);\n if (JSON.stringify(remote) === JSON.stringify(store.get())) return;\n applyingRemote = true;\n store.set(remote);\n applyingRemote = false;\n }\n\n const ready = poll();\n const timer = setInterval(poll, pollMs);\n\n return { ...store, ready, stop: () => clearInterval(timer) };\n}\n", "// react-runtime.js \u2014 how the framework gets hold of React.\n//\n// It must use the SAME React the host already loaded: a second copy on the\n// page makes every hook throw. But it must not depend on it with a static\n// `import React from \"react\"` either \u2014 a specifier the host can't resolve\n// kills the whole module at load time, before anything is left running to\n// report why.\n//\n// So React is resolved at runtime, from whichever of these is available:\n//\n// 1. globalThis.React \u2014 present when the host exposes it\n// 2. useReact(React) \u2014 the explicit hand-off\n//\n// The hand-off is one line and always available, because an artifact already\n// imports React for its own code:\n//\n// import React from \"react\";\n// ArtifactKit.useReact(React);\n//\n// Deliberately no dynamic import(\"react\") fallback: it would need top-level\n// await, which the IIFE build can't have, and it only pays off in a runtime\n// with a native import map \u2014 which is not the way artifacts load code.\n\nlet React = typeof globalThis !== \"undefined\" ? globalThis.React : undefined;\n\nexport function useReact(instance) {\n React = instance;\n return instance;\n}\n\nexport function hasReact() {\n return Boolean(React);\n}\n\n// The live instance, for the few places that need React itself rather than one\n// of its functions \u2014 `class extends React.Component`, most of all.\nexport function getReact() {\n return required();\n}\n\nfunction required() {\n if (!React) {\n throw new Error(\n \"claude-artifact-framework: React not found. Hand it over once, before createApp:\\n\\n\" +\n ' import React from \"react\";\\n' +\n \" ArtifactKit.useReact(React);\\n\"\n );\n }\n return React;\n}\n\n// Bound lazily, because modules import these at load time \u2014 which is before\n// useReact() can possibly have run.\nexport const createElement = (...args) => required().createElement(...args);\nexport const useState = (...args) => required().useState(...args);\nexport const useEffect = (...args) => required().useEffect(...args);\nexport const useMemo = (...args) => required().useMemo(...args);\nexport const useRef = (...args) => required().useRef(...args);\n\n// A class component is read as a value at module scope, so it can't be\n// deferred behind a call. This stand-in is only ever constructed if React was\n// still missing at render time, and it reports the same error then.\nexport const Component =\n (React && React.Component) ||\n class ReactMissing {\n render() {\n return required();\n }\n };\n\n// The default export mirrors `import React from \"react\"`, so the source files\n// can keep using React.createElement / React.useState unchanged.\nexport default {\n get createElement() { return required().createElement; },\n get Component() { return required().Component; },\n get useState() { return required().useState; },\n get useEffect() { return required().useEffect; },\n get useMemo() { return required().useMemo; },\n get useRef() { return required().useRef; },\n};\n", "// appState.js \u2014 the store behind createApp.\n//\n// Two states, and the split is the point:\n// data domain data only. Declared by the author, persisted whole in one write.\n// view navigation stack, selection, current step, form drafts, pending flags.\n// Owned by the framework, persisted under its own key, never declared\n// and never seen by the author.\n//\n// That split is why `data` needs no zones or transient markers: nothing that\n// would be wrong to restore (an open modal, a half-typed draft) ever lives in\n// it. It also removes every storage key as an invention point \u2014 the author\n// never names one.\n\nimport { storage } from \"./storage.js\";\n\nconst DATA_KEY = \"caf:data\";\nconst VIEW_KEY = \"caf:view\";\n\nconst EMPTY_VIEW = { screen: null, arg: null, stack: [], step: 0, selected: null };\n\nfunction isPlainObject(v) {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\n\n// Stored values win, but only where they exist. A field the author added\n// after data was already saved simply falls through to its declared default,\n// which is what makes additive edits need no migration at all.\nfunction mergeDefaults(defaults, stored) {\n if (!isPlainObject(defaults) || !isPlainObject(stored)) {\n return stored === undefined ? defaults : stored;\n }\n const out = { ...defaults };\n for (const key of Object.keys(stored)) {\n out[key] = isPlainObject(defaults[key]) ? mergeDefaults(defaults[key], stored[key]) : stored[key];\n }\n return out;\n}\n\nfunction debounce(fn, ms) {\n let timer;\n return (...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n };\n}\n\nexport function createAppState(defaults, { debounceMs = 400 } = {}) {\n let data = structuredCloneish(defaults);\n let view = { ...EMPTY_VIEW };\n let hydrated = false;\n const listeners = new Set();\n\n // Notification is batched to a microtask: three mutations in a row produce\n // one render, not three. Persistence is separately debounced, because\n // writing to window.storage is async and must not run at typing speed.\n let queued = false;\n function notify() {\n if (queued) return;\n queued = true;\n Promise.resolve().then(() => {\n queued = false;\n for (const fn of listeners) fn();\n });\n }\n\n const persistData = debounce(() => storage.set(DATA_KEY, data), debounceMs);\n const persistView = debounce(() => storage.set(VIEW_KEY, view), debounceMs);\n\n const ready = (async () => {\n const [storedData, storedView] = await Promise.all([\n storage.get(DATA_KEY, undefined),\n storage.get(VIEW_KEY, undefined),\n ]);\n if (storedData !== undefined) data = mergeDefaults(defaults, storedData);\n if (storedView !== undefined) view = { ...EMPTY_VIEW, ...storedView };\n hydrated = true;\n notify();\n })();\n\n function update(fn) {\n const result = fn(data);\n // Handlers may either mutate the draft or return a replacement.\n if (result !== undefined) data = result;\n data = { ...data };\n persistData();\n notify();\n }\n\n function setView(patch) {\n view = { ...view, ...patch };\n persistView();\n notify();\n }\n\n return {\n ready,\n isHydrated: () => hydrated,\n getData: () => data,\n getView: () => view,\n update,\n setView,\n go(screen, arg) {\n setView({ stack: [...view.stack, { screen: view.screen, arg: view.arg }], screen, arg });\n },\n back() {\n const stack = view.stack.slice();\n const previous = stack.pop() || { screen: null, arg: null };\n setView({ stack, screen: previous.screen, arg: previous.arg });\n },\n subscribe(fn) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n };\n}\n\n// Defaults come from a literal in the declaration; a shallow structural copy\n// is enough and avoids depending on structuredClone being present.\nfunction structuredCloneish(value) {\n if (Array.isArray(value)) return value.map(structuredCloneish);\n if (isPlainObject(value)) {\n const out = {};\n for (const k of Object.keys(value)) out[k] = structuredCloneish(value[k]);\n return out;\n }\n return value;\n}\n", "// theme.js \u2014 derives a complete palette from a single seed colour.\n//\n// One token in, a full light+dark palette out, with contrast checked rather\n// than assumed. The point is that an app gets its own visual identity from\n// one line while structure stays shared, so apps built with this framework\n// don't all look alike.\n//\n// Neutrals carry a slight hue bias toward the seed instead of being pure\n// grey \u2014 a pure mid-grey reads as unconsidered.\n\nfunction clamp(n, lo, hi) {\n return Math.min(hi, Math.max(lo, n));\n}\n\nfunction hexToRgb(hex) {\n let h = String(hex).replace(\"#\", \"\").trim();\n if (h.length === 3) h = h.split(\"\").map((c) => c + c).join(\"\");\n const n = parseInt(h, 16);\n if (!Number.isFinite(n)) return [59, 110, 246];\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\n\nfunction rgbToHex(rgb) {\n return \"#\" + rgb.map((v) => clamp(Math.round(v), 0, 255).toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction rgbToHsl([r, g, b]) {\n r /= 255; g /= 255; b /= 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n const d = max - min;\n let h = 0;\n let s = 0;\n if (d) {\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0);\n else if (max === g) h = (b - r) / d + 2;\n else h = (r - g) / d + 4;\n h /= 6;\n }\n return [h * 360, s * 100, l * 100];\n}\n\nfunction hslToRgb(h, s, l) {\n h = (((h % 360) + 360) % 360) / 360;\n s = clamp(s, 0, 100) / 100;\n l = clamp(l, 0, 100) / 100;\n if (!s) return [l * 255, l * 255, l * 255];\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const channel = (t) => {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n return [channel(h + 1 / 3) * 255, channel(h) * 255, channel(h - 1 / 3) * 255];\n}\n\nfunction hsl(h, s, l) {\n return rgbToHex(hslToRgb(h, s, l));\n}\n\nfunction luminance(rgb) {\n const a = rgb.map((v) => {\n v /= 255;\n return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n });\n return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];\n}\n\n// WCAG contrast ratio between two hex colours, 1 (identical) to 21 (max).\nexport function contrast(a, b) {\n const la = luminance(hexToRgb(a));\n const lb = luminance(hexToRgb(b));\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\n// Walks lightness until the colour clears `min` contrast against `against`,\n// so the accent is guaranteed legible instead of merely hoped to be.\nfunction accentAt(h, s, against, min, from, step) {\n for (let l = from; l >= 4 && l <= 96; l += step) {\n const candidate = hsl(h, s, l);\n if (contrast(candidate, against) >= min) return candidate;\n }\n return hsl(h, s, step < 0 ? 24 : 82);\n}\n\nexport function palette(seed = \"#3b6ef6\") {\n const [h, rawSat] = rgbToHsl(hexToRgb(seed));\n const sat = clamp(rawSat, 30, 88);\n // Neutrals keep a trace of the seed's hue: chosen, not inherited.\n const tint = clamp(sat * 0.1, 3, 9);\n\n const lightSurface = hsl(h, tint * 0.4, 100);\n const darkSurface = hsl(h, tint * 1.4, 13);\n\n return {\n light: {\n bg: hsl(h, tint, 96.5),\n surface: lightSurface,\n sunken: hsl(h, tint, 93),\n border: hsl(h, tint, 86),\n text: hsl(h, tint * 1.6, 11),\n muted: hsl(h, tint * 1.2, 41),\n accent: accentAt(h, sat, \"#ffffff\", 4.5, 54, -2),\n accentText: \"#ffffff\",\n danger: accentAt(2, 68, \"#ffffff\", 4.5, 54, -2),\n ok: accentAt(148, 62, \"#ffffff\", 4.5, 44, -2),\n warn: accentAt(38, 88, \"#ffffff\", 4.5, 44, -2),\n },\n dark: {\n bg: hsl(h, tint * 1.5, 9),\n surface: darkSurface,\n sunken: hsl(h, tint * 1.5, 7),\n border: hsl(h, tint * 1.3, 24),\n text: hsl(h, tint * 0.6, 95),\n muted: hsl(h, tint * 0.8, 66),\n accent: accentAt(h, clamp(sat, 40, 80), darkSurface, 4.5, 62, 2),\n accentText: hsl(h, tint * 2, 8),\n danger: accentAt(2, 70, darkSurface, 4.5, 62, 2),\n ok: accentAt(148, 55, darkSurface, 4.5, 62, 2),\n warn: accentAt(38, 80, darkSurface, 4.5, 62, 2),\n },\n };\n}\n\nfunction vars(scheme) {\n return Object.entries(scheme)\n .map(([k, v]) => `--caf-${k}: ${v};`)\n .join(\"\");\n}\n\n// Both themes are styled through the same tokens, and the viewer's explicit\n// toggle (data-theme on the root) must beat the OS preference in both\n// directions \u2014 hence the two attribute blocks after the media query.\nexport function themeCss(seed) {\n const p = palette(seed);\n return `\n:root { ${vars(p.light)} }\n@media (prefers-color-scheme: dark) { :root { ${vars(p.dark)} } }\n:root[data-theme=\"dark\"] { ${vars(p.dark)} }\n:root[data-theme=\"light\"] { ${vars(p.light)} }\n`;\n}\n", "// blocks.js \u2014 the content blocks that fill a layout's slots.\n//\n// Every block is a plain React component taking (spec, ctx). Custom code from\n// the escape hatch implements exactly the same contract, which is why ejecting\n// one block never requires ejecting the app.\n//\n// Loading / empty / error are part of the contract rather than edge cases the\n// author opts into: a block that has nothing to show says so by default, so an\n// app can't ship a blank pane while it waits.\n\n// Bound lazily rather than snapshotted as `React.createElement`, because this\n// runs at module load \u2014 before the host has had a chance to hand React over.\nimport { createElement as h } from \"react\";\n\nconst FIELD_TYPES = [\"text\", \"textarea\", \"number\", \"money\", \"percent\", \"check\", \"date\", \"select\"];\n\nexport function formatValue(value, format) {\n if (value === null || value === undefined || value === \"\") return \"\u2014\";\n const n = Number(value);\n switch (format) {\n case \"money\":\n return Number.isFinite(n)\n ? n.toLocaleString(undefined, { style: \"currency\", currency: \"USD\", maximumFractionDigits: 2 })\n : String(value);\n case \"percent\":\n return Number.isFinite(n) ? `${n.toLocaleString(undefined, { maximumFractionDigits: 2 })}%` : String(value);\n case \"number\":\n return Number.isFinite(n) ? n.toLocaleString(undefined, { maximumFractionDigits: 2 }) : String(value);\n case \"date\":\n return value instanceof Date ? value.toLocaleDateString() : String(value);\n default:\n return String(value);\n }\n}\n\n// Validation is derived from the field declaration, so the author gets it\n// without writing any: declaring a type and a range IS the validation.\nexport function validateField(field, value) {\n if (field.required && (value === \"\" || value === null || value === undefined)) {\n return \"Required\";\n }\n if (value === \"\" || value === null || value === undefined) return null;\n if (field.type === \"number\" || field.type === \"money\" || field.type === \"percent\") {\n const n = Number(value);\n if (!Number.isFinite(n)) return \"Must be a number\";\n if (field.min !== undefined && n < field.min) return `Must be at least ${field.min}`;\n if (field.max !== undefined && n > field.max) return `Must be at most ${field.max}`;\n }\n return null;\n}\n\nexport function Field({ field, value, onChange }) {\n const error = validateField(field, value);\n const id = `caf-f-${field.key}`;\n const numeric = field.type === \"number\" || field.type === \"money\" || field.type === \"percent\";\n\n if (field.type === \"check\") {\n return h(\n \"label\",\n { className: \"caf-check\" },\n h(\"input\", {\n id,\n type: \"checkbox\",\n checked: Boolean(value),\n onChange: (e) => onChange(e.target.checked),\n }),\n h(\"span\", null, field.label || field.key)\n );\n }\n\n const common = {\n id,\n value: value === null || value === undefined ? \"\" : value,\n \"aria-invalid\": error ? \"true\" : undefined,\n onChange: (e) => onChange(numeric ? toNumber(e.target.value) : e.target.value),\n };\n\n let control;\n if (field.type === \"textarea\") {\n control = h(\"textarea\", { ...common, rows: field.rows || 3 });\n } else if (field.type === \"select\") {\n control = h(\n \"select\",\n common,\n h(\"option\", { value: \"\" }, field.placeholder || \"Select\u2026\"),\n (field.options || []).map((opt) => {\n const val = typeof opt === \"string\" ? opt : opt.value;\n const label = typeof opt === \"string\" ? opt : opt.label;\n return h(\"option\", { key: val, value: val }, label);\n })\n );\n } else {\n control = h(\"input\", {\n ...common,\n type: field.type === \"date\" ? \"date\" : numeric ? \"number\" : \"text\",\n min: field.min,\n max: field.max,\n step: field.step || (field.type === \"money\" || field.type === \"percent\" ? \"any\" : undefined),\n placeholder: field.placeholder,\n });\n }\n\n return h(\n \"div\",\n { className: \"caf-field\" },\n h(\"label\", { htmlFor: id }, field.label || field.key),\n control,\n field.hint && !error ? h(\"small\", { className: \"caf-hint\" }, field.hint) : null,\n error ? h(\"small\", { className: \"caf-error\" }, error) : null\n );\n}\n\nfunction toNumber(raw) {\n if (raw === \"\") return \"\";\n const n = Number(raw);\n return Number.isFinite(n) ? n : raw;\n}\n\nexport function FieldsBlock({ spec, ctx }) {\n const fields = spec.fields || [];\n return h(\n \"div\",\n { className: \"caf-block caf-fields\" },\n spec.title ? h(\"h2\", { className: \"caf-block-title\" }, spec.title) : null,\n fields.map((field) =>\n h(Field, {\n key: field.key,\n field,\n value: ctx.data[field.key],\n onChange: (v) => ctx.update((d) => { d[field.key] = v; }),\n })\n )\n );\n}\n\nexport function OutputBlock({ spec, ctx }) {\n const items = typeof spec.output === \"function\" ? spec.output(ctx.data) : spec.output || [];\n if (!items.length) {\n return h(\"div\", { className: \"caf-block caf-empty\" }, spec.empty || \"Nothing to show yet.\");\n }\n return h(\n \"div\",\n { className: \"caf-block caf-output\" },\n spec.title ? h(\"h2\", { className: \"caf-block-title\" }, spec.title) : null,\n h(\n \"div\",\n { className: \"caf-output-grid\" },\n items.map((item, i) =>\n h(\n \"div\",\n { key: item.label || i, className: item.big ? \"caf-stat caf-stat-big\" : \"caf-stat\" },\n h(\"span\", { className: \"caf-stat-label\" }, item.label),\n h(\"span\", { className: \"caf-stat-value\" }, formatValue(item.value, item.format)),\n item.hint ? h(\"small\", { className: \"caf-hint\" }, item.hint) : null\n )\n )\n )\n );\n}\n\nexport function TextBlock({ spec }) {\n const body = typeof spec.text === \"function\" ? spec.text() : spec.text;\n return h(\n \"div\",\n { className: \"caf-block caf-text\" },\n spec.title ? h(\"h2\", { className: \"caf-block-title\" }, spec.title) : null,\n h(\"p\", null, body)\n );\n}\n\nexport function ListBlock({ spec, ctx }) {\n const rows = (typeof spec.list === \"function\" ? spec.list(ctx.data) : spec.list) || [];\n if (!rows.length) {\n return h(\"div\", { className: \"caf-block caf-empty\" }, spec.empty || \"Nothing here yet.\");\n }\n const title = spec.title || ((r) => r.title ?? r.name ?? r.label ?? String(r));\n return h(\n \"div\",\n { className: \"caf-block caf-list\" },\n rows.map((row, i) =>\n h(\n \"button\",\n {\n key: row.id ?? i,\n className: \"caf-row\",\n type: \"button\",\n onClick: spec.onSelect ? () => spec.onSelect(row, ctx) : undefined,\n },\n h(\"span\", { className: \"caf-row-title\" }, title(row)),\n spec.subtitle ? h(\"span\", { className: \"caf-row-sub\" }, spec.subtitle(row)) : null\n )\n )\n );\n}\n\n// The escape hatch. Receives the same ctx every built-in block gets, so a\n// custom block keeps persistence, theming, navigation and the error boundary.\nexport function CustomBlock({ spec, ctx }) {\n const rendered = spec.custom(ctx);\n if (typeof rendered === \"string\") {\n return h(\"div\", { className: \"caf-block\", dangerouslySetInnerHTML: { __html: rendered } });\n }\n return h(\"div\", { className: \"caf-block\" }, rendered);\n}\n\nexport const BLOCKS = {\n fields: FieldsBlock,\n output: OutputBlock,\n text: TextBlock,\n list: ListBlock,\n custom: CustomBlock,\n};\n\nexport const BLOCK_NAMES = Object.keys(BLOCKS);\nexport { FIELD_TYPES };\n", "// records.js \u2014 the \"list of things\" layout: expenses, habits, notes, todos.\n//\n// The author declares what a record IS (the same field declarations the\n// fields block uses) and optionally what the collection summarises to. The\n// whole CRUD lifecycle \u2014 list, add, edit, delete, empty state, selection,\n// navigation \u2014 is framework-owned, so none of it can be half-built.\n//\n// Two deliberate choices keep the state model tiny:\n//\n// add-then-edit \"Add\" creates the record from field defaults and navigates\n// straight into it. There is no separate draft object, so a\n// half-typed record can't be lost \u2014 it already exists.\n// edit-in-place Detail fields write into the record directly through\n// update(), so persistence and re-render are the same\n// debounced path every other block uses.\n//\n// Which record is open lives in view state (screen \"record\", arg = id), never\n// in data \u2014 restoring it on reload is correct, and deleting the open record\n// simply falls back to the list.\n\nimport { createElement as h } from \"react\";\nimport { Field, formatValue } from \"./blocks.js\";\n\nexport function recordDefaults(fields) {\n const rec = {};\n for (const f of fields) {\n rec[f.key] = f.value !== undefined ? f.value : f.type === \"check\" ? false : \"\";\n }\n return rec;\n}\n\n// Collision-proof enough for a per-user list; no coordination needed.\nfunction makeId() {\n return \"r\" + Date.now().toString(36) + Math.random().toString(36).slice(2, 8);\n}\n\nfunction rowTitle(spec, rec) {\n if (spec.title) return spec.title(rec);\n // Default: the first text-ish field, which is what a human would label by.\n const f = spec.fields.find((f) => !f.type || f.type === \"text\" || f.type === \"textarea\" || f.type === \"select\");\n const v = f && rec[f.key];\n return v === \"\" || v === undefined || v === null ? \"(untitled)\" : String(v);\n}\n\nfunction Summary({ spec, records }) {\n if (!spec.summary) return null;\n const items = spec.summary(records) || [];\n if (!items.length) return null;\n return h(\n \"div\",\n { className: \"caf-block caf-output\" },\n h(\n \"div\",\n { className: \"caf-output-grid\" },\n items.map((item, i) =>\n h(\n \"div\",\n { key: item.label || i, className: item.big ? \"caf-stat caf-stat-big\" : \"caf-stat\" },\n h(\"span\", { className: \"caf-stat-label\" }, item.label),\n h(\"span\", { className: \"caf-stat-value\" }, formatValue(item.value, item.format))\n )\n )\n )\n );\n}\n\nfunction ListScreen({ spec, ctx }) {\n const label = spec.label || \"item\";\n let records = ctx.data.records;\n if (spec.sort) records = records.slice().sort(spec.sort);\n\n function add() {\n const rec = { id: makeId(), ...recordDefaults(spec.fields) };\n ctx.update((d) => {\n d.records = [...d.records, rec];\n });\n ctx.go(\"record\", rec.id);\n }\n\n return h(\n \"div\",\n { className: \"caf-block caf-list\" },\n h(\n \"div\",\n { className: \"caf-toolbar\" },\n h(\"span\", { className: \"caf-count\" }, `${records.length} ${label}${records.length === 1 ? \"\" : \"s\"}`),\n h(\"button\", { type: \"button\", className: \"caf-btn caf-btn-primary\", onClick: add }, `Add ${label}`)\n ),\n records.length === 0\n ? h(\"div\", { className: \"caf-empty\" }, spec.empty || `No ${label}s yet. Add the first one.`)\n : records.map((rec) =>\n h(\n \"button\",\n {\n key: rec.id,\n type: \"button\",\n className: \"caf-row\",\n onClick: () => ctx.go(\"record\", rec.id),\n },\n h(\"span\", { className: \"caf-row-title\" }, rowTitle(spec, rec)),\n spec.subtitle ? h(\"span\", { className: \"caf-row-sub\" }, spec.subtitle(rec)) : null\n )\n )\n );\n}\n\nfunction DetailScreen({ spec, ctx, record }) {\n const label = spec.label || \"item\";\n\n function remove() {\n ctx.update((d) => {\n d.records = d.records.filter((r) => r.id !== record.id);\n });\n ctx.back();\n }\n\n return h(\n \"div\",\n { className: \"caf-block caf-fields\" },\n h(\n \"div\",\n { className: \"caf-toolbar\" },\n h(\"button\", { type: \"button\", className: \"caf-btn\", onClick: ctx.back }, \"\u2039 Back\"),\n h(\"button\", { type: \"button\", className: \"caf-btn caf-btn-danger\", onClick: remove }, `Delete ${label}`)\n ),\n spec.fields.map((field) =>\n h(Field, {\n key: field.key,\n field,\n value: record[field.key],\n onChange: (v) =>\n ctx.update((d) => {\n const rec = d.records.find((r) => r.id === record.id);\n if (rec) rec[field.key] = v;\n }),\n })\n )\n );\n}\n\nexport function RecordsLayout({ spec, ctx }) {\n const rspec = spec.records;\n\n if (ctx.view.screen === \"record\") {\n const record = ctx.data.records.find((r) => r.id === ctx.view.arg);\n // The open record can vanish (deleted, or stale view state from an earlier\n // version of the data) \u2014 fall back to the list rather than a blank pane.\n if (record) {\n return h(\"div\", { className: \"caf-panel caf-panel-single\" }, h(DetailScreen, { spec: rspec, ctx, record }));\n }\n }\n return h(\n \"div\",\n { className: \"caf-panel caf-panel-single\" },\n h(Summary, { spec: rspec, records: ctx.data.records }),\n h(ListScreen, { spec: rspec, ctx })\n );\n}\n", "// app.js \u2014 createApp: the whole framework's entry point.\n//\n// Returns a React component, so an artifact is `export default createApp({\u2026})`\n// with no mounting ceremony.\n//\n// Lifecycle, and deliberately only four stages:\n// hydrate read data + view from storage, merge over declared defaults\n// mount first render already holding real data, so there's no flash\n// run update() -> batched notify -> render, persistence debounced apart\n// error a boundary per block: one broken block shows its error, the rest live\n\nimport { createElement as h, useState, useEffect, hasReact, getReact } from \"react\";\nimport { createAppState } from \"./appState.js\";\nimport { themeCss } from \"./theme.js\";\nimport { BLOCKS, BLOCK_NAMES } from \"./blocks.js\";\nimport { RecordsLayout } from \"./records.js\";\n\nconst LAYOUTS = [\"panel\", \"records\"];\nconst RESERVED = [\"title\", \"empty\", \"wide\", \"onSelect\", \"subtitle\"];\n\n// Frontier models still invent identifiers a few percent of the time, so an\n// unknown name has to fail loudly and name the alternatives rather than\n// silently rendering nothing \u2014 a blank pane is indistinguishable from a bug.\nfunction validate(spec) {\n const layout = spec.layout || \"panel\";\n if (!LAYOUTS.includes(layout)) {\n throw new Error(\n `claude-artifact-framework: unknown layout \"${layout}\". Valid layouts: ${LAYOUTS.join(\", \")}.`\n );\n }\n if (layout === \"records\") {\n const r = spec.records;\n if (!r || !Array.isArray(r.fields) || r.fields.length === 0) {\n throw new Error(\n 'claude-artifact-framework: layout \"records\" needs `records: { fields: [...] }` \u2014 the same field declarations the fields block uses.'\n );\n }\n const seen = new Set();\n for (const f of r.fields) {\n if (!f || !f.key) throw new Error(\"claude-artifact-framework: every records field needs a `key`.\");\n if (f.key === \"id\") throw new Error('claude-artifact-framework: \"id\" is reserved on records \u2014 the framework assigns it.');\n if (seen.has(f.key)) throw new Error(`claude-artifact-framework: duplicate records field key \"${f.key}\".`);\n seen.add(f.key);\n }\n return layout;\n }\n const blocks = spec.blocks || [];\n if (!Array.isArray(blocks)) {\n throw new Error(\"claude-artifact-framework: `blocks` must be an array.\");\n }\n blocks.forEach((block, i) => {\n if (!block || typeof block !== \"object\") {\n throw new Error(`claude-artifact-framework: blocks[${i}] must be an object like { fields: [...] }.`);\n }\n const keys = Object.keys(block).filter((k) => !RESERVED.includes(k));\n const known = keys.filter((k) => BLOCK_NAMES.includes(k));\n if (known.length === 0) {\n throw new Error(\n `claude-artifact-framework: blocks[${i}] has no recognised block type (found: ${\n keys.join(\", \") || \"nothing\"\n }). Valid block types: ${BLOCK_NAMES.join(\", \")}.`\n );\n }\n if (known.length > 1) {\n throw new Error(\n `claude-artifact-framework: blocks[${i}] declares more than one block type (${known.join(\n \", \"\n )}). Split them into separate entries of \\`blocks\\`.`\n );\n }\n });\n return layout;\n}\n\n// Fields declare their own initial value, so the data shape is derived from\n// the declaration instead of being restated in a separate object. That removes\n// the key as an invention point: it is written exactly once.\nfunction defaultsFrom(spec) {\n const data = { ...(spec.data || {}) };\n if ((spec.layout || \"panel\") === \"records\" && !Array.isArray(data.records)) {\n data.records = [];\n }\n for (const block of spec.blocks || []) {\n for (const field of block.fields || []) {\n if (field && field.key !== undefined && !(field.key in data)) {\n data[field.key] = field.value !== undefined ? field.value : field.type === \"check\" ? false : \"\";\n }\n }\n }\n return data;\n}\n\n// Built on first use, not at module scope: `extends React.Component` needs a\n// real React, and at load time the host may not have handed one over yet.\nlet BlockBoundary = null;\n\nfunction boundary(React) {\n if (!BlockBoundary) {\n BlockBoundary = class extends React.Component {\n constructor(props) {\n super(props);\n this.state = { error: null };\n }\n static getDerivedStateFromError(error) {\n return { error };\n }\n render() {\n if (this.state.error) {\n return h(\n \"div\",\n { className: \"caf-block caf-block-error\" },\n h(\"strong\", null, \"This section failed to render\"),\n h(\"code\", null, String(this.state.error.message || this.state.error))\n );\n }\n return this.props.children;\n }\n };\n }\n return BlockBoundary;\n}\n\nfunction Block({ block, ctx }) {\n const name = Object.keys(block).find((k) => BLOCK_NAMES.includes(k));\n const Component = BLOCKS[name];\n return h(boundary(ctx.React), null, h(Component, { spec: block, ctx }));\n}\n\nfunction Panel({ spec, ctx }) {\n return h(\n \"div\",\n { className: \"caf-panel\" },\n (spec.blocks || []).map((block, i) =>\n h(\n \"section\",\n { key: i, className: block.wide ? \"caf-slot caf-slot-wide\" : \"caf-slot\" },\n h(Block, { block, ctx })\n )\n )\n );\n}\n\nconst LAYOUT_COMPONENTS = { panel: Panel, records: RecordsLayout };\n\nexport function createApp(spec = {}) {\n const layout = validate(spec);\n const state = createAppState(defaultsFrom(spec));\n const css = themeCss(spec.theme && spec.theme.seed) + BASE_CSS;\n\n return function App() {\n if (!hasReact()) {\n throw new Error(\n \"claude-artifact-framework: React not found. Hand it over once, before rendering:\\n\\n\" +\n ' import React from \"react\";\\n' +\n \" ArtifactKit.useReact(React);\\n\"\n );\n }\n const [, force] = useState(0);\n useEffect(() => {\n const unsubscribe = state.subscribe(() => force((n) => n + 1));\n // Hydration can finish before this effect runs \u2014 its notify() then lands\n // on zero listeners and nothing ever re-renders. Re-check on subscribe,\n // so a mount that raced hydration still leaves the loading screen.\n if (state.isHydrated()) force((n) => n + 1);\n return unsubscribe;\n }, []);\n\n const ctx = {\n React: getReact(),\n data: state.getData(),\n view: state.getView(),\n update: state.update,\n go: state.go,\n back: state.back,\n };\n\n const Layout = LAYOUT_COMPONENTS[layout];\n\n return h(\n \"div\",\n { className: \"caf-root\" },\n h(\"style\", { dangerouslySetInnerHTML: { __html: css } }),\n h(\n \"header\",\n { className: \"caf-header\" },\n spec.title ? h(\"h1\", null, spec.title) : null,\n spec.subtitle ? h(\"p\", null, spec.subtitle) : null\n ),\n state.isHydrated()\n ? h(Layout, { spec, ctx })\n : h(\"div\", { className: \"caf-block caf-loading\" }, \"Loading\u2026\")\n );\n };\n}\n\nconst BASE_CSS = `\n.caf-root {\n --caf-radius: 10px;\n box-sizing: border-box;\n min-height: 100vh;\n padding: 2rem 1.25rem 4rem;\n background: var(--caf-bg);\n color: var(--caf-text);\n font-family: -apple-system, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.caf-root *, .caf-root *::before, .caf-root *::after { box-sizing: inherit; }\n.caf-header { max-width: 760px; margin: 0 auto 1.5rem; }\n.caf-header h1 { margin: 0; font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; text-wrap: balance; }\n.caf-header p { margin: 0.4rem 0 0; color: var(--caf-muted); font-size: 0.95rem; line-height: 1.5; }\n.caf-panel { max-width: 760px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }\n.caf-slot { grid-column: span 2; min-width: 0; }\n@media (min-width: 720px) { .caf-slot { grid-column: span 1; } .caf-slot-wide { grid-column: span 2; } }\n.caf-block {\n background: var(--caf-surface);\n border: 1px solid var(--caf-border);\n border-radius: var(--caf-radius);\n padding: 1.1rem;\n display: flex;\n flex-direction: column;\n gap: 0.8rem;\n height: 100%;\n}\n.caf-block-title { margin: 0; font-size: 0.95rem; font-weight: 650; }\n.caf-field { display: flex; flex-direction: column; gap: 0.3rem; }\n.caf-field label { font-size: 0.78rem; font-weight: 600; color: var(--caf-muted); letter-spacing: 0.02em; }\n.caf-field input, .caf-field select, .caf-field textarea {\n font: inherit; font-size: 0.95rem; padding: 0.5rem 0.6rem;\n border-radius: 7px; border: 1px solid var(--caf-border);\n background: var(--caf-sunken); color: var(--caf-text); width: 100%;\n}\n.caf-field input:focus-visible, .caf-field select:focus-visible, .caf-field textarea:focus-visible,\n.caf-row:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }\n.caf-field input[aria-invalid=\"true\"] { border-color: var(--caf-danger); }\n.caf-check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; }\n.caf-hint { color: var(--caf-muted); font-size: 0.75rem; }\n.caf-error { color: var(--caf-danger); font-size: 0.75rem; font-weight: 600; }\n.caf-output-grid { display: flex; flex-direction: column; gap: 0.7rem; }\n.caf-stat { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }\n.caf-stat-label { color: var(--caf-muted); font-size: 0.82rem; }\n.caf-stat-value { font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }\n.caf-stat-big { flex-direction: column; align-items: flex-start; gap: 0.15rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--caf-border); }\n.caf-stat-big .caf-stat-value { font-size: 1.9rem; font-weight: 680; letter-spacing: -0.02em; color: var(--caf-accent); }\n.caf-list { padding: 0.4rem; gap: 0; }\n.caf-row {\n font: inherit; text-align: left; cursor: pointer;\n display: flex; flex-direction: column; gap: 0.15rem;\n padding: 0.65rem 0.7rem; border: none; border-radius: 7px;\n background: transparent; color: inherit; width: 100%;\n}\n.caf-row:hover { background: var(--caf-sunken); }\n.caf-row-title { font-size: 0.92rem; font-weight: 550; }\n.caf-row-sub { font-size: 0.78rem; color: var(--caf-muted); }\n.caf-panel-single { grid-template-columns: 1fr; }\n.caf-panel-single .caf-slot, .caf-panel-single > * { grid-column: span 1; }\n.caf-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.3rem 0.3rem 0.5rem; }\n.caf-count { font-size: 0.8rem; color: var(--caf-muted); font-variant-numeric: tabular-nums; }\n.caf-btn {\n font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;\n padding: 0.45rem 0.8rem; border-radius: 7px;\n border: 1px solid var(--caf-border); background: var(--caf-sunken); color: var(--caf-text);\n}\n.caf-btn:hover { filter: brightness(0.97); }\n.caf-btn:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }\n.caf-btn-primary { background: var(--caf-accent); border-color: var(--caf-accent); color: var(--caf-accentText); }\n.caf-btn-danger { background: transparent; border-color: var(--caf-danger); color: var(--caf-danger); }\n.caf-empty, .caf-loading { color: var(--caf-muted); font-size: 0.9rem; text-align: center; padding: 1.6rem 1rem; }\n.caf-block-error { border-color: var(--caf-danger); gap: 0.4rem; }\n.caf-block-error strong { font-size: 0.9rem; color: var(--caf-danger); }\n.caf-block-error code { font-size: 0.78rem; color: var(--caf-muted); word-break: break-word; }\n`;\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "contrast", "createApp", "createPersistedStore", "createSharedStore", "createStore", "hasReact", "palette", "storage", "themeCss", "useReact", "available", "scope", "shared", "key", "fallback", "res", "value", "raw", "payload", "prefix", "storage", "makeStore", "initialState", "state", "subscribers", "get", "set", "next", "fn", "subscribe", "debounce", "ms", "timer", "args", "createStore", "createPersistedStore", "key", "debounceMs", "store", "persist", "value", "storage", "ready", "loaded", "createSharedStore", "pollMs", "applyingRemote", "poll", "remote", "React", "useReact", "instance", "hasReact", "getReact", "required", "createElement", "args", "useState", "useEffect", "Component", "React", "required", "DATA_KEY", "VIEW_KEY", "EMPTY_VIEW", "isPlainObject", "v", "mergeDefaults", "defaults", "stored", "out", "key", "debounce", "fn", "ms", "timer", "args", "createAppState", "debounceMs", "data", "structuredCloneish", "view", "hydrated", "listeners", "queued", "notify", "persistData", "storage", "persistView", "ready", "storedData", "storedView", "update", "result", "setView", "patch", "screen", "arg", "stack", "previous", "value", "k", "clamp", "n", "lo", "hi", "hexToRgb", "hex", "h", "c", "rgbToHex", "rgb", "v", "rgbToHsl", "r", "g", "b", "max", "min", "l", "d", "s", "hslToRgb", "q", "p", "channel", "t", "hsl", "luminance", "a", "contrast", "la", "lb", "accentAt", "against", "from", "step", "candidate", "palette", "seed", "rawSat", "sat", "tint", "lightSurface", "darkSurface", "vars", "scheme", "k", "themeCss", "formatValue", "value", "format", "n", "validateField", "field", "Field", "onChange", "error", "id", "numeric", "createElement", "e", "common", "toNumber", "control", "opt", "val", "label", "raw", "FieldsBlock", "spec", "ctx", "fields", "v", "d", "OutputBlock", "items", "item", "i", "TextBlock", "body", "ListBlock", "rows", "title", "r", "row", "CustomBlock", "rendered", "BLOCKS", "BLOCK_NAMES", "recordDefaults", "fields", "rec", "f", "makeId", "rowTitle", "spec", "v", "Summary", "records", "items", "createElement", "item", "i", "formatValue", "ListScreen", "ctx", "label", "add", "d", "DetailScreen", "record", "remove", "r", "field", "Field", "RecordsLayout", "rspec", "LAYOUTS", "RESERVED", "validate", "spec", "layout", "r", "seen", "f", "blocks", "block", "i", "keys", "k", "known", "BLOCK_NAMES", "defaultsFrom", "data", "field", "BlockBoundary", "boundary", "React", "props", "error", "createElement", "Block", "ctx", "name", "Component", "BLOCKS", "Panel", "LAYOUT_COMPONENTS", "RecordsLayout", "createApp", "state", "createAppState", "css", "themeCss", "BASE_CSS", "hasReact", "force", "useState", "useEffect", "unsubscribe", "n", "getReact", "Layout"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-artifact-framework",
3
- "version": "0.2.0",
3
+ "version": "0.3.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",