claude-artifact-framework 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,17 @@
1
- var ArtifactKit=(()=>{var K=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Fe=Object.prototype.hasOwnProperty;var Pe=(e,a)=>{for(var t in a)K(e,t,{get:a[t],enumerable:!0})},He=(e,a,t,r)=>{if(a&&typeof a=="object"||typeof a=="function")for(let o of Ve(a))!Fe.call(e,o)&&o!==t&&K(e,o,{get:()=>a[o],enumerable:!(r=Ie(a,o))||r.enumerable});return e};var Ke=e=>He(K({},"__esModule",{value:!0}),e);var Ot={};Pe(Ot,{contrast:()=>W,createApp:()=>Be,createPersistedStore:()=>fe,createSharedStore:()=>de,createStore:()=>le,hasReact:()=>_,palette:()=>Q,storage:()=>w,themeCss:()=>I,useReact:()=>ue});function L(){return typeof window<"u"&&typeof window.storage=="object"&&window.storage!==null}function ie(e){return{async get(a,t=void 0){if(!L())return t;try{let r=await window.storage.get(a,e);if(r?.value===void 0||r?.value===null)return t;try{return JSON.parse(r.value)}catch{return r.value}}catch{return t}},async set(a,t,{raw:r=!1}={}){if(!L())throw new Error("window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)");let o=r?t:JSON.stringify(t);if(typeof o!="string")throw new Error("window.storage only accepts strings \u2014 the value must be JSON-serializable");return window.storage.set(a,o,e)},async delete(a){if(L())try{await window.storage.delete(a,e)}catch{}},async list(a){if(!L())return[];try{return(await window.storage.list(a,e))?.keys||[]}catch{return[]}}}}var w={...ie(!1),shared:ie(!0),available:L};function Y(e){let a=e,t=new Set;function r(){return a}function o(i){a=typeof i=="function"?i(a):i,t.forEach(c=>c(a))}function s(i){return t.add(i),()=>t.delete(i)}return{get:r,set:o,subscribe:s}}function ce(e,a){let t;return(...r)=>{clearTimeout(t),t=setTimeout(()=>e(...r),a)}}function le(e){return Y(e)}function fe(e,a,{debounceMs:t=300}={}){let r=Y(a),o=ce(i=>w.set(e,i),t),s=w.get(e,a).then(i=>r.set(i));return r.subscribe(o),{...r,ready:s}}function de(e,a,{pollMs:t=2e3,debounceMs:r=300}={}){let o=Y(a),s=ce(d=>w.shared.set(e,d),r),i=!1;o.subscribe(d=>{i||s(d)});async function c(){let d=await w.shared.get(e,a);JSON.stringify(d)!==JSON.stringify(o.get())&&(i=!0,o.set(d),i=!1)}let f=c(),l=setInterval(c,t);return{...o,ready:f,stop:()=>clearInterval(l)}}var j=typeof globalThis<"u"?globalThis.React:void 0;function ue(e){return j=e,e}function _(){return!!j}function me(){return R()}function R(){if(!j)throw new Error(`claude-artifact-framework: React not found. Hand it over once, before createApp:
1
+ var ArtifactKit=(()=>{var Y=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Pe=Object.getOwnPropertyNames;var He=Object.prototype.hasOwnProperty;var Ke=(e,t)=>{for(var a in t)Y(e,a,{get:t[a],enumerable:!0})},Ye=(e,t,a,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Pe(t))!He.call(e,o)&&o!==a&&Y(e,o,{get:()=>t[o],enumerable:!(r=Fe(t,o))||r.enumerable});return e};var Je=e=>Ye(Y({},"__esModule",{value:!0}),e);var Lt={};Ke(Lt,{contrast:()=>X,createApp:()=>De,createPersistedStore:()=>de,createSharedStore:()=>ue,createStore:()=>fe,hasReact:()=>_,palette:()=>Q,storage:()=>w,themeCss:()=>D,useReact:()=>me});function L(){return typeof window<"u"&&typeof window.storage=="object"&&window.storage!==null}function ce(e){return{async get(t,a=void 0){if(!L())return a;try{let r=await window.storage.get(t,e);if(r?.value===void 0||r?.value===null)return a;try{return JSON.parse(r.value)}catch{return r.value}}catch{return a}},async set(t,a,{raw:r=!1}={}){if(!L())throw new Error("window.storage is not available (is this a Code Artifact rather than a published Chat Artifact?)");let o=r?a:JSON.stringify(a);if(typeof o!="string")throw new Error("window.storage only accepts strings \u2014 the value must be JSON-serializable");return window.storage.set(t,o,e)},async delete(t){if(L())try{await window.storage.delete(t,e)}catch{}},async list(t){if(!L())return[];try{return(await window.storage.list(t,e))?.keys||[]}catch{return[]}}}}var w={...ce(!1),shared:ce(!0),available:L};function J(e){let t=e,a=new Set;function r(){return t}function o(i){t=typeof i=="function"?i(t):i,a.forEach(c=>c(t))}function s(i){return a.add(i),()=>a.delete(i)}return{get:r,set:o,subscribe:s}}function le(e,t){let a;return(...r)=>{clearTimeout(a),a=setTimeout(()=>e(...r),t)}}function fe(e){return J(e)}function de(e,t,{debounceMs:a=300}={}){let r=J(t),o=le(i=>w.set(e,i),a),s=w.get(e,t).then(i=>r.set(i));return r.subscribe(o),{...r,ready:s}}function ue(e,t,{pollMs:a=2e3,debounceMs:r=300}={}){let o=J(t),s=le(d=>w.shared.set(e,d),r),i=!1;o.subscribe(d=>{i||s(d)});async function c(){let d=await w.shared.get(e,t);JSON.stringify(d)!==JSON.stringify(o.get())&&(i=!0,o.set(d),i=!1)}let f=c(),l=setInterval(c,a);return{...o,ready:f,stop:()=>clearInterval(l)}}var j=typeof globalThis<"u"?globalThis.React:void 0;function me(e){return j=e,e}function _(){return!!j}function pe(){return O()}function O(){if(!j)throw new Error(`claude-artifact-framework: React not found. Hand it over once, before createApp:
2
2
 
3
3
  import React from "react";
4
4
  ArtifactKit.useReact(React);
5
- `);return j}var n=(...e)=>R().createElement(...e),k=(...e)=>R().useState(...e),S=(...e)=>R().useEffect(...e);var pe=(...e)=>R().useRef(...e),Bt=j&&j.Component||class{render(){return R()}};var J="caf:data",be="caf:viewer",he="caf:view",ge={screen:null,arg:null,stack:[],step:0,selected:null,tabs:{},collapsed:{}};function z(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function q(e,a){if(!z(e)||!z(a))return a===void 0?e:a;let t={...e};for(let r of Object.keys(a))t[r]=z(e[r])?q(e[r],a[r]):a[r];return t}function ye(e,a){let t;return(...r)=>{clearTimeout(t),t=setTimeout(()=>e(...r),a)}}function we(e,{debounceMs:a=400,shared:t=!1,pollMs:r=2500}={}){let o=t?w.shared:w,s=U(e),i={...ge},c=!1,f=null,l=0,d=0,m=new Set,h=!1;function u(){h||(h=!0,Promise.resolve().then(()=>{h=!1;for(let p of m)p()}))}let b=ye(()=>{let p=l;Promise.resolve(o.set(J,s)).then(()=>{d=Math.max(d,p)}).catch(()=>{})},a),v=ye(()=>w.set(he,i),a);t&&setInterval(async()=>{if(!(!c||l>d))try{let p=await o.get(J,void 0);p!==void 0&&JSON.stringify(p)!==JSON.stringify(s)&&(s=q(e,p),u())}catch{}},r);let A=(async()=>{let[p,y,$]=await Promise.all([o.get(J,void 0),w.get(he,void 0),w.get(be,void 0)]);typeof $=="string"&&$?f=$:(f="v"+Math.random().toString(36).slice(2,10)+Math.random().toString(36).slice(2,6),w.set(be,f).catch?.(()=>{})),p!==void 0&&(s=q(e,p)),y!==void 0&&(i={...ge,...y}),c=!0,u()})();function x(p){let y=p(s);y!==void 0&&(s=y),s={...s},l++,b(),u()}function T(p){i={...i,...p},v(),u()}return{ready:A,isHydrated:()=>c,getViewerId:()=>f,getData:()=>s,getView:()=>i,update:x,setView:T,go(p,y){T({stack:[...i.stack,{screen:i.screen,arg:i.arg}],screen:p,arg:y})},back(){let p=i.stack.slice(),y=p.pop()||{screen:null,arg:null};T({stack:p,screen:y.screen,arg:y.arg})},subscribe(p){return m.add(p),()=>m.delete(p)}}}function U(e){if(Array.isArray(e))return e.map(U);if(z(e)){let a={};for(let t of Object.keys(e))a[t]=U(e[t]);return a}return e}function C(e,a,t){return Math.min(t,Math.max(a,e))}function D(e){let a=String(e).replace("#","").trim();a.length===3&&(a=a.split("").map(r=>r+r).join(""));let t=parseInt(a,16);return Number.isFinite(t)?[t>>16&255,t>>8&255,t&255]:[59,110,246]}function Ye(e){return"#"+e.map(a=>C(Math.round(a),0,255).toString(16).padStart(2,"0")).join("")}function ve([e,a,t]){e/=255,a/=255,t/=255;let r=Math.max(e,a,t),o=Math.min(e,a,t),s=(r+o)/2,i=r-o,c=0,f=0;return i&&(f=s>.5?i/(2-r-o):i/(r+o),r===e?c=(a-t)/i+(a<t?6:0):r===a?c=(t-e)/i+2:c=(e-a)/i+4,c/=6),[c*360,f*100,s*100]}function Je(e,a,t){if(e=(e%360+360)%360/360,a=C(a,0,100)/100,t=C(t,0,100)/100,!a)return[t*255,t*255,t*255];let r=t<.5?t*(1+a):t+a-t*a,o=2*t-r,s=i=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?o+(r-o)*6*i:i<1/2?r:i<2/3?o+(r-o)*(2/3-i)*6:o);return[s(e+1/3)*255,s(e)*255,s(e-1/3)*255]}function g(e,a,t){return Ye(Je(e,a,t))}function ke(e){let a=e.map(t=>(t/=255,t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)));return .2126*a[0]+.7152*a[1]+.0722*a[2]}function W(e,a){let t=ke(D(e)),r=ke(D(a));return(Math.max(t,r)+.05)/(Math.min(t,r)+.05)}function E(e,a,t,r,o,s){for(let i=o;i>=4&&i<=96;i+=s){let c=g(e,a,i);if(W(c,t)>=r)return c}return g(e,a,s<0?24:82)}function Q(e="#3b6ef6"){let[a,t]=ve(D(e)),r=C(t,30,88),o=C(r*.1,3,9),s=g(a,o*.4,100),i=g(a,o*1.4,13);return{light:{bg:g(a,o,96.5),surface:s,sunken:g(a,o,93),border:g(a,o,86),text:g(a,o*1.6,11),muted:g(a,o*1.2,41),accent:E(a,r,"#ffffff",4.5,54,-2),accentText:"#ffffff",danger:E(2,68,"#ffffff",4.5,54,-2),ok:E(148,62,"#ffffff",4.5,44,-2),warn:E(38,88,"#ffffff",4.5,44,-2)},dark:{bg:g(a,o*1.5,9),surface:i,sunken:g(a,o*1.5,7),border:g(a,o*1.3,24),text:g(a,o*.6,95),muted:g(a,o*.8,66),accent:E(a,C(r,40,80),i,4.5,62,2),accentText:g(a,o*2,8),danger:E(2,70,i,4.5,62,2),ok:E(148,55,i,4.5,62,2),warn:E(38,80,i,4.5,62,2)}}}function B(e){return Object.entries(e).map(([a,t])=>`--caf-${a}: ${t};`).join("")}function I(e){let a=Q(e);return`
6
- :root { ${B(a.light)} }
7
- @media (prefers-color-scheme: dark) { :root { ${B(a.dark)} } }
8
- :root[data-theme="dark"] { ${B(a.dark)} }
9
- :root[data-theme="light"] { ${B(a.light)} }
10
- `}function xe(e,a){let[t,r]=ve(D(e||"#3b6ef6")),o=C(r,45,70);return Array.from({length:a},(s,i)=>g((t+i*137.5)%360,o,52))}var G=["system","greeting","placeholder","tools","model","maxTokens"],qe="claude-sonnet-4-6",Ue=8;async function We({model:e,maxTokens:a,system:t,messages:r,onText:o}){let s=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:e,max_tokens:a,system:t,messages:r,stream:!0})});if(!s.ok||!s.body){let d="";try{let m=await s.json();d=m&&m.error&&m.error.message||JSON.stringify(m)}catch{d=await s.text().catch(()=>"")}throw new Error(`HTTP ${s.status}${d?": "+d:""}`)}let i=s.body.getReader(),c=new TextDecoder,f="",l="";for(;;){let{done:d,value:m}=await i.read();if(d)break;l+=c.decode(m,{stream:!0});let h=l.split(`
11
- `);l=h.pop();for(let u of h)if(u.startsWith("data: "))try{let b=JSON.parse(u.slice(6));b.type==="content_block_delta"&&b.delta&&b.delta.text&&(f+=b.delta.text,o&&o(f))}catch{}}return f}function Qe(e){let a=e.match(/```tool_call\s*\n?([\s\S]*?)```/);if(!a)return null;try{let t=JSON.parse(a[1]);return Array.isArray(t)&&t.length?t:null}catch{return null}}function Ne(e){return e.replace(/```tool_call\s*\n?[\s\S]*?```/,"").trim()}function Xe(e){return`
5
+ `);return j}var n=(...e)=>O().createElement(...e),k=(...e)=>O().useState(...e),E=(...e)=>O().useEffect(...e);var he=(...e)=>O().useRef(...e),It=j&&j.Component||class{render(){return O()}};var q="caf:data",be="caf:viewer",ge="caf:view",ye={screen:null,arg:null,stack:[],step:0,selected:null,tabs:{},collapsed:{}};function z(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function U(e,t){if(!z(e)||!z(t))return t===void 0?e:t;let a={...e};for(let r of Object.keys(t))a[r]=z(e[r])?U(e[r],t[r]):t[r];return a}function we(e,t){let a;return(...r)=>{clearTimeout(a),a=setTimeout(()=>e(...r),t)}}function ke(e,{debounceMs:t=400,shared:a=!1,pollMs:r=2500}={}){let o=a?w.shared:w,s=W(e),i={...ye},c=!1,f=null,l=0,d=0,u=new Set,b=!1;function m(){b||(b=!0,Promise.resolve().then(()=>{b=!1;for(let h of u)h()}))}let p=we(()=>{let h=l;Promise.resolve(o.set(q,s)).then(()=>{d=Math.max(d,h)}).catch(()=>{})},t),N=we(()=>w.set(ge,i),t);a&&setInterval(async()=>{if(!(!c||l>d))try{let h=await o.get(q,void 0);h!==void 0&&JSON.stringify(h)!==JSON.stringify(s)&&(s=U(e,h),m())}catch{}},r);let v=(async()=>{let[h,y,A]=await Promise.all([o.get(q,void 0),w.get(ge,void 0),w.get(be,void 0)]);typeof A=="string"&&A?f=A:(f="v"+Math.random().toString(36).slice(2,10)+Math.random().toString(36).slice(2,6),w.set(be,f).catch?.(()=>{})),h!==void 0&&(s=U(e,h)),y!==void 0&&(i={...ye,...y}),c=!0,m()})();function T(h){let y=h(s);y!==void 0&&(s=y),s={...s},l++,p(),m()}function x(h){i={...i,...h},N(),m()}return{ready:v,isHydrated:()=>c,getViewerId:()=>f,getData:()=>s,getView:()=>i,update:T,setView:x,go(h,y){x({stack:[...i.stack,{screen:i.screen,arg:i.arg}],screen:h,arg:y})},back(){let h=i.stack.slice(),y=h.pop()||{screen:null,arg:null};x({stack:h,screen:y.screen,arg:y.arg})},subscribe(h){return u.add(h),()=>u.delete(h)}}}function W(e){if(Array.isArray(e))return e.map(W);if(z(e)){let t={};for(let a of Object.keys(e))t[a]=W(e[a]);return t}return e}function C(e,t,a){return Math.min(a,Math.max(t,e))}function I(e){let t=String(e).replace("#","").trim();t.length===3&&(t=t.split("").map(r=>r+r).join(""));let a=parseInt(t,16);return Number.isFinite(a)?[a>>16&255,a>>8&255,a&255]:[59,110,246]}function qe(e){return"#"+e.map(t=>C(Math.round(t),0,255).toString(16).padStart(2,"0")).join("")}function xe([e,t,a]){e/=255,t/=255,a/=255;let r=Math.max(e,t,a),o=Math.min(e,t,a),s=(r+o)/2,i=r-o,c=0,f=0;return i&&(f=s>.5?i/(2-r-o):i/(r+o),r===e?c=(t-a)/i+(t<a?6:0):r===t?c=(a-e)/i+2:c=(e-t)/i+4,c/=6),[c*360,f*100,s*100]}function Ue(e,t,a){if(e=(e%360+360)%360/360,t=C(t,0,100)/100,a=C(a,0,100)/100,!t)return[a*255,a*255,a*255];let r=a<.5?a*(1+t):a+t-a*t,o=2*a-r,s=i=>(i<0&&(i+=1),i>1&&(i-=1),i<1/6?o+(r-o)*6*i:i<1/2?r:i<2/3?o+(r-o)*(2/3-i)*6:o);return[s(e+1/3)*255,s(e)*255,s(e-1/3)*255]}function g(e,t,a){return qe(Ue(e,t,a))}function ve(e){let t=e.map(a=>(a/=255,a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)));return .2126*t[0]+.7152*t[1]+.0722*t[2]}function X(e,t){let a=ve(I(e)),r=ve(I(t));return(Math.max(a,r)+.05)/(Math.min(a,r)+.05)}function $(e,t,a,r,o,s){for(let i=o;i>=4&&i<=96;i+=s){let c=g(e,t,i);if(X(c,a)>=r)return c}return g(e,t,s<0?24:82)}function Q(e="#3b6ef6"){let[t,a]=xe(I(e)),r=C(a,30,88),o=C(r*.1,3,9),s=g(t,o*.4,100),i=g(t,o*1.4,13);return{light:{bg:g(t,o,96.5),surface:s,sunken:g(t,o,93),border:g(t,o,86),text:g(t,o*1.6,11),muted:g(t,o*1.2,41),accent:$(t,r,"#ffffff",4.5,54,-2),accentText:"#ffffff",danger:$(2,68,"#ffffff",4.5,54,-2),ok:$(148,62,"#ffffff",4.5,44,-2),warn:$(38,88,"#ffffff",4.5,44,-2)},dark:{bg:g(t,o*1.5,9),surface:i,sunken:g(t,o*1.5,7),border:g(t,o*1.3,24),text:g(t,o*.6,95),muted:g(t,o*.8,66),accent:$(t,C(r,40,80),i,4.5,62,2),accentText:g(t,o*2,8),danger:$(2,70,i,4.5,62,2),ok:$(148,55,i,4.5,62,2),warn:$(38,80,i,4.5,62,2)}}}function B(e){return Object.entries(e).map(([t,a])=>`--caf-${t}: ${a};`).join("")}function D(e){let t=Q(e);return`
6
+ :root { ${B(t.light)} }
7
+ @media (prefers-color-scheme: dark) { :root { ${B(t.dark)} } }
8
+ :root[data-theme="dark"] { ${B(t.dark)} }
9
+ :root[data-theme="light"] { ${B(t.light)} }
10
+ `}function Ne(e,t){let[a,r]=xe(I(e||"#3b6ef6")),o=C(r,45,70);return Array.from({length:t},(s,i)=>g((a+i*137.5)%360,o,52))}var Z=["system","greeting","placeholder","tools","model","maxTokens"],We="claude-sonnet-4-6",Xe=8;async function Qe({model:e,maxTokens:t,system:a,messages:r,onText:o}){let s=await fetch("https://api.anthropic.com/v1/messages",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:e,max_tokens:t,system:a,messages:r,stream:!0})});if(!s.ok||!s.body){let d="";try{let u=await s.json();d=u&&u.error&&u.error.message||JSON.stringify(u)}catch{d=await s.text().catch(()=>"")}throw new Error(`HTTP ${s.status}${d?": "+d:""}`)}let i=s.body.getReader(),c=new TextDecoder,f="",l="";for(;;){let{done:d,value:u}=await i.read();if(d)break;l+=c.decode(u,{stream:!0});let b=l.split(`
11
+ `);l=b.pop();for(let m of b)if(m.startsWith("data: "))try{let p=JSON.parse(m.slice(6));p.type==="content_block_delta"&&p.delta&&p.delta.text&&(f+=p.delta.text,o&&o(f))}catch{}}return f}function Ge(e){let t=e.match(/```tool_call\s*\n?([\s\S]*?)```/);if(!t)return null;try{let a=JSON.parse(t[1]);return Array.isArray(a)&&a.length?a:null}catch{return null}}function Se(e){return e.replace(/```tool_call\s*\n?[\s\S]*?```/,"").trim()}function Ze(e){return`
12
12
 
13
13
  You have tools available:
14
- ${Object.entries(e).map(([t,r])=>`- ${t}: ${r.description}
14
+ ${Object.entries(e).map(([a,r])=>`- ${a}: ${r.description}
15
15
  Input: ${JSON.stringify(r.input||{})}`).join(`
16
16
  `)}
17
17
 
@@ -21,17 +21,21 @@ This environment does not support native function calling. To use a tool, reply
21
21
  [{ "name": "tool_name", "input": { "param": "value" } }]
22
22
  \`\`\`
23
23
 
24
- You may include several calls in one array. NEVER invent a tool's result \u2014 emit the pure tool_call block and wait for the real result, which arrives in the next message tagged [TOOL_RESULT]. When you have everything you need, answer in natural language with no tool_call block.`}function Ge(e,a,t){return e.map(r=>{let o=a[r.name];if(!o)return{name:r.name,error:`unknown tool "${r.name}". Valid tools: ${Object.keys(a).join(", ")}`};try{let s=o.run(r.input||{},t);return{name:r.name,result:s===void 0?{ok:!0}:s}}catch(s){return{name:r.name,error:String(s&&s.message||s)}}})}var Se=e=>String(e).replace(/[&<>"]/g,a=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"})[a]);function X(e){let a=[],t=String(e).replace(/```[a-z]*\n?([\s\S]*?)```/g,(r,o)=>(a.push(o.replace(/\n$/,"")),"\0"+(a.length-1)+"\0"));return t=Se(t),t=t.replace(/`([^`]+)`/g,"<code>$1</code>"),t=t.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),t=t.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),t=t.replace(/^#{1,3} (.+)$/gm,'<strong class="caf-md-h">$1</strong>'),t=t.replace(/^[-•*] (.+)$/gm,'<span class="caf-md-li">$1</span>'),t=t.replace(/^\d+\. (.+)$/gm,'<span class="caf-md-li caf-md-num">$1</span>'),t=t.replace(/\n/g,"<br>"),t=t.replace(/\u0000(\d+)\u0000/g,(r,o)=>'<pre class="caf-code">'+Se(a[Number(o)])+"</pre>"),t}function Ze({m:e}){return e.role==="tools"?n("div",{className:"caf-msg-tools"},`used: ${e.tools.join(", ")}`):e.role==="error"?n("div",{className:"caf-msg caf-msg-error"},n("strong",null,"The call failed"),n("span",null,e.content),n("span",{className:"caf-hint"},"Your message is kept \u2014 send again to retry.")):e.role==="user"?n("div",{className:"caf-msg caf-msg-user"},e.content):n("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:X(e.content)}})}function Z({cfg:e,ctx:a}){let t=e,[r,o]=k(""),[s,i]=k(!1),[c,f]=k(null),l=pe(null),d=a.data.chat||{api:[],log:[]},m=d.log||[];S(()=>{l.current&&l.current.scrollIntoView({block:"end"})},[m.length,c]);async function h(){let u=r.trim();if(!u||s)return;o(""),i(!0);let b=[...d.api||[],{role:"user",content:u}],v=[...m,{role:"user",content:u}],A=()=>a.update(x=>{x.chat={api:b,log:v}});A();try{let x=(typeof t.system=="function"?t.system(a.data):t.system||"")+(t.tools?Xe(t.tools):"");for(let T=0;T<Ue;T++){let p=await We({model:t.model||qe,maxTokens:t.maxTokens||2e3,system:x,messages:b,onText:H=>f(Ne(H))});b=[...b,{role:"assistant",content:p}];let y=Ne(p),$=t.tools?Qe(p):null;if(!$){v=[...v,{role:"assistant",content:y||p}],A();break}let De=Ge($,t.tools,a);y&&(v=[...v,{role:"assistant",content:y}]),v=[...v,{role:"tools",tools:$.map(H=>H.name)}],b=[...b,{role:"user",content:`[TOOL_RESULT]
25
- ${JSON.stringify(De)}
24
+ You may include several calls in one array. NEVER invent a tool's result \u2014 emit the pure tool_call block and wait for the real result, which arrives in the next message tagged [TOOL_RESULT]. When you have everything you need, answer in natural language with no tool_call block.`}function et(e,t,a){return e.map(r=>{let o=t[r.name];if(!o)return{name:r.name,error:`unknown tool "${r.name}". Valid tools: ${Object.keys(t).join(", ")}`};try{let s=o.run(r.input||{},a);return{name:r.name,result:s===void 0?{ok:!0}:s}}catch(s){return{name:r.name,error:String(s&&s.message||s)}}})}var Ee=e=>String(e).replace(/[&<>"]/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"})[t]);function G(e){let t=[],a=String(e).replace(/```[a-z]*\n?([\s\S]*?)```/g,(r,o)=>(t.push(o.replace(/\n$/,"")),"\0"+(t.length-1)+"\0"));return a=Ee(a),a=a.replace(/`([^`]+)`/g,"<code>$1</code>"),a=a.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),a=a.replace(/(^|[^*])\*([^*\n]+)\*/g,"$1<em>$2</em>"),a=a.replace(/^#{1,3} (.+)$/gm,'<strong class="caf-md-h">$1</strong>'),a=a.replace(/^[-•*] (.+)$/gm,'<span class="caf-md-li">$1</span>'),a=a.replace(/^\d+\. (.+)$/gm,'<span class="caf-md-li caf-md-num">$1</span>'),a=a.replace(/\n/g,"<br>"),a=a.replace(/\u0000(\d+)\u0000/g,(r,o)=>'<pre class="caf-code">'+Ee(t[Number(o)])+"</pre>"),a}function tt({m:e}){return e.role==="tools"?n("div",{className:"caf-msg-tools"},`used: ${e.tools.join(", ")}`):e.role==="error"?n("div",{className:"caf-msg caf-msg-error"},n("strong",null,"The call failed"),n("span",null,e.content),n("span",{className:"caf-hint"},"Your message is kept \u2014 send again to retry.")):e.role==="user"?n("div",{className:"caf-msg caf-msg-user"},e.content):n("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:G(e.content)}})}function ee({cfg:e,ctx:t,title:a}){let r=e,[o,s]=k(""),[i,c]=k(!1),[f,l]=k(null),d=he(null),u=t.data.chat||{api:[],log:[]},b=u.log||[];E(()=>{d.current&&d.current.scrollIntoView({block:"end"})},[b.length,f]);async function m(){let p=o.trim();if(!p||i)return;s(""),c(!0);let N=[...u.api||[],{role:"user",content:p}],v=[...b,{role:"user",content:p}],T=()=>t.update(x=>{x.chat={api:N,log:v}});T();try{let x=(typeof r.system=="function"?r.system(t.data):r.system||"")+(r.tools?Ze(r.tools):"");for(let h=0;h<Xe;h++){let y=await Qe({model:r.model||We,maxTokens:r.maxTokens||2e3,system:x,messages:N,onText:K=>l(Se(K))});N=[...N,{role:"assistant",content:y}];let A=Se(y),H=r.tools?Ge(y):null;if(!H){v=[...v,{role:"assistant",content:A||y}],T();break}let Ve=et(H,r.tools,t);A&&(v=[...v,{role:"assistant",content:A}]),v=[...v,{role:"tools",tools:H.map(K=>K.name)}],N=[...N,{role:"user",content:`[TOOL_RESULT]
25
+ ${JSON.stringify(Ve)}
26
26
  [/TOOL_RESULT]
27
27
 
28
- Continue with this information. If you have everything you need, answer in natural language without further tool_call.`}],A(),f(null)}}catch(x){v=[...v,{role:"error",content:String(x&&x.message||x)}],A()}finally{f(null),i(!1)}}return n("div",{className:"caf-chat-panel"},n("div",{className:"caf-block caf-chat-log"},t.greeting?n("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:X(t.greeting)}}):null,m.map((u,b)=>n(Ze,{key:b,m:u})),c!==null?n("div",{className:"caf-msg caf-msg-assistant caf-msg-live",dangerouslySetInnerHTML:{__html:X(c||"\u2026")}}):null,s&&c===null?n("div",{className:"caf-msg-tools"},"thinking\u2026"):null,n("div",{ref:l})),n("div",{className:"caf-chat-input"},n("input",{value:r,placeholder:t.placeholder||"Message\u2026",disabled:s,enterKeyHint:"send",onChange:u=>o(u.target.value),onKeyDown:u=>{u.key==="Enter"&&(u.preventDefault(),h())},"aria-label":"Message"}),n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:s||!r.trim(),onClick:h},"Send")))}function Ee({spec:e,ctx:a}){return n("div",{className:"caf-panel caf-panel-single"},n(Z,{cfg:e.chat,ctx:a}))}var ee=["text","textarea","number","money","percent","check","date","select","file"];function N(e,a){if(e==null||e==="")return"\u2014";let t=Number(e);switch(a){case"money":return Number.isFinite(t)?t.toLocaleString(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2}):String(e);case"percent":return Number.isFinite(t)?`${t.toLocaleString(void 0,{maximumFractionDigits:2})}%`:String(e);case"number":return Number.isFinite(t)?t.toLocaleString(void 0,{maximumFractionDigits:2}):String(e);case"date":return e instanceof Date?e.toLocaleDateString():String(e);default:return String(e)}}function te(e,a){if(e.required&&(a===""||a===null||a===void 0))return"Required";if(a===""||a===null||a===void 0)return null;if(e.type==="number"||e.type==="money"||e.type==="percent"){let t=Number(a);if(!Number.isFinite(t))return"Must be a number";if(e.min!==void 0&&t<e.min)return`Must be at least ${e.min}`;if(e.max!==void 0&&t>e.max)return`Must be at most ${e.max}`}return null}function O({field:e,value:a,onChange:t,data:r}){let o=te(e,a),s=`caf-f-${e.key}`,i=e.type==="number"||e.type==="money"||e.type==="percent";if(e.type==="file")return n("div",{className:"caf-field"},n("label",{htmlFor:s},e.label||e.key),n("input",{id:s,type:"file",accept:e.accept,onChange:l=>t(l.target.files&&l.target.files[0]?l.target.files[0]:null)}),a&&a.name?n("small",{className:"caf-hint"},`${a.name} (${Math.round((a.size||0)/1024)} KB)${a.stale?" \u2014 re-pick after reload":""}`):e.hint?n("small",{className:"caf-hint"},e.hint):null);if(e.type==="check")return n("label",{className:"caf-check"},n("input",{id:s,type:"checkbox",checked:!!a,onChange:l=>t(l.target.checked)}),n("span",null,e.label||e.key));let c={id:s,value:a??"","aria-invalid":o?"true":void 0,onChange:l=>t(i?et(l.target.value):l.target.value)},f;if(e.type==="textarea")f=n("textarea",{...c,rows:e.rows||3});else if(e.type==="select"){let l=typeof e.options=="function"?e.options(r)||[]:e.options||[];f=n("select",c,n("option",{value:""},e.placeholder||"Select\u2026"),l.map(d=>{let m=typeof d=="string"?d:d.value,h=typeof d=="string"?d:d.label;return n("option",{key:m,value:m},h)}))}else f=n("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});return n("div",{className:"caf-field"},n("label",{htmlFor:s},e.label||e.key),f,e.hint&&!o?n("small",{className:"caf-hint"},e.hint):null,o?n("small",{className:"caf-error"},o):null)}function et(e){if(e==="")return"";let a=Number(e);return Number.isFinite(a)?a:e}function ae(e,a,t,r,o){if(t.type==="file"){e.files[a]=r||null;let s=r?{name:r.name,size:r.size,type:r.type}:null;e.update(i=>o(i,s));return}e.update(s=>o(s,r))}function tt({spec:e,ctx:a}){let t=e.fields||[];return n("div",{className:"caf-block caf-fields"},e.title?n("h2",{className:"caf-block-title"},e.title):null,t.map(r=>n(O,{key:r.key,field:r,data:a.data,value:a.data[r.key],onChange:o=>ae(a,r.key,r,o,(s,i)=>{s[r.key]=i})})))}function at({spec:e,ctx:a}){let t=typeof e.output=="function"?e.output(a.data):e.output||[];return t.length?n("div",{className:"caf-block caf-output"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-output-grid"},t.map((r,o)=>n("div",{key:r.label||o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},N(r.value,r.format)),r.hint?n("small",{className:"caf-hint"},r.hint):null)))):n("div",{className:"caf-block caf-empty"},e.empty||"Nothing to show yet.")}function rt({spec:e,ctx:a}){let t=typeof e.text=="function"?e.text(a.data):e.text;return n("div",{className:"caf-block caf-text"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("p",null,t))}function nt({spec:e,ctx:a}){let t=(typeof e.list=="function"?e.list(a.data):e.list)||[],r=typeof e.title=="string"?e.title:null,o=typeof e.title=="function"?e.title:s=>s.title??s.name??s.label??s.text??String(s);return t.length?n("div",{className:"caf-block caf-list"},r?n("h2",{className:"caf-block-title"},r):null,t.map((s,i)=>n("button",{key:s.id??i,className:"caf-row",type:"button",onClick:e.onSelect?()=>e.onSelect(s,a):void 0},n("span",{className:"caf-row-title"},o(s)),e.subtitle?n("span",{className:"caf-row-sub"},e.subtitle(s)):null))):n("div",{className:"caf-block caf-empty"},e.empty||"Nothing here yet.")}var $e=["bar","line","donut"];function ot({spec:e,ctx:a}){let t=typeof e.chart=="function"?e.chart(a.data):e.chart,r=t&&t.items||[];if(!r.length)return n("div",{className:"caf-block caf-empty"},e.empty||"No data to chart yet.");let o=t.type||"bar";if(!$e.includes(o))throw new Error(`unknown chart type "${o}". Valid types: ${$e.join(", ")}.`);let s=a.colors(r.length),i=o==="bar"?st(r,t,s):o==="line"?it(r,t):ct(r,t,s);return n("div",{className:"caf-block caf-chart"},e.title?n("h2",{className:"caf-block-title"},e.title):null,i)}function st(e,a,t){let r=Math.max(...e.map(o=>Number(o.value)||0),0)||1;return n("div",{className:"caf-bars"},e.map((o,s)=>n("div",{key:o.label??s,className:"caf-bar-row"},n("span",{className:"caf-bar-label"},o.label),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill",style:{width:`${Math.max(2,(Number(o.value)||0)/r*100)}%`,background:t[s]}})),n("span",{className:"caf-bar-value"},N(o.value,a.format)))))}function it(e,a){let t=e.map(d=>Number(d.value)||0),r=Math.min(...t),s=Math.max(...t)-r||1,i=100,c=36,f=t.map((d,m)=>[t.length===1?i/2:m/(t.length-1)*i,c-3-(d-r)/s*(c-6)]),l=f[f.length-1];return n("div",{className:"caf-line"},n("svg",{viewBox:`0 0 ${i} ${c}`,className:"caf-line-svg",preserveAspectRatio:"none","aria-hidden":"true"},[.25,.5,.75].map(d=>n("line",{key:d,x1:0,x2:i,y1:c*d,y2:c*d,className:"caf-line-grid"})),n("polyline",{points:f.map(d=>d.join(",")).join(" "),className:"caf-line-path"}),n("circle",{cx:l[0],cy:l[1],r:1.6,className:"caf-line-dot"})),n("div",{className:"caf-line-meta"},n("span",{className:"caf-hint"},String(e[0].label??"")),n("span",{className:"caf-line-last"},N(t[t.length-1],a.format)),n("span",{className:"caf-hint"},String(e[e.length-1].label??""))))}function ct(e,a,t){let r=e.reduce((c,f)=>c+(Number(f.value)||0),0)||1,o=15.9155,s=25,i=e.map((c,f)=>{let l=(Number(c.value)||0)/r*100,d=n("circle",{key:c.label??f,cx:21,cy:21,r:o,className:"caf-donut-seg",stroke:t[f],strokeDasharray:`${l} ${100-l}`,strokeDashoffset:s});return s-=l,d});return n("div",{className:"caf-donut"},n("svg",{viewBox:"0 0 42 42",className:"caf-donut-svg","aria-hidden":"true"},i),n("div",{className:"caf-donut-legend"},e.map((c,f)=>n("div",{key:c.label??f,className:"caf-legend-row"},n("span",{className:"caf-legend-swatch",style:{background:t[f]}}),n("span",{className:"caf-legend-label"},c.label),n("span",{className:"caf-legend-value"},N(c.value,a.format))))))}function lt({spec:e,ctx:a}){let t=e.timer||{},r=Math.max(1,Math.round((t.minutes||0)*60+(t.seconds||0))||300),[o,s]=k(r),[i,c]=k(!1);S(()=>{if(!i)return;let m=setInterval(()=>s(h=>Math.max(0,h-1)),1e3);return()=>clearInterval(m)},[i]),S(()=>{o===0&&i&&(c(!1),typeof t.onDone=="function"&&a.update(m=>t.onDone(m)))},[o,i]);let f=String(Math.floor(o/60)).padStart(2,"0"),l=String(o%60).padStart(2,"0"),d=o===0;return n("div",{className:"caf-block caf-timer"},e.title?n("h2",{className:"caf-block-title"},e.title):null,t.label?n("span",{className:"caf-hint"},t.label):null,n("div",{className:d?"caf-timer-time caf-timer-done":"caf-timer-time"},d?t.doneText||"Done!":`${f}:${l}`),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill caf-timer-fill",style:{width:`${o/r*100}%`}})),n("div",{className:"caf-timer-controls"},n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:d,onClick:()=>c(m=>!m)},i?"Pause":"Start"),n("button",{type:"button",className:"caf-btn",onClick:()=>{c(!1),s(r)}},"Reset")))}function ft({spec:e,ctx:a}){let r=(e.actions||[]).filter(o=>!o.when||o.when(a.data,a.viewerId));return n("div",{className:"caf-block caf-actions"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-actions-row"},r.map(o=>n("button",{key:o.label,type:"button",className:o.kind==="danger"?"caf-btn caf-btn-danger":o.kind==="primary"?"caf-btn caf-btn-primary":"caf-btn",onClick:()=>a.update(s=>o.run(s,a.viewerId))},o.label))))}function dt({spec:e,ctx:a}){let t=e.custom(a),r=e.fill?"caf-block caf-block-fill":"caf-block";return typeof t=="string"?n("div",{className:r,dangerouslySetInnerHTML:{__html:t}}):n("div",{className:r},t)}var re={fields:tt,output:at,text:rt,list:nt,chart:ot,timer:lt,actions:ft,chat:({spec:e,ctx:a})=>n(Z,{cfg:e.chat,ctx:a}),custom:dt},V=Object.keys(re);function Ce(e){return Object.entries(e.compute||{}).map(([a,t])=>[a,typeof t=="function"?{value:t}:t])}function ne(e,a){if(!e.compute)return a;let t={...a};for(let[r,o]of Ce(e))try{t[r]=o.value(a)}catch{t[r]=void 0}return t}function Ae(e){let a={};for(let t of e)a[t.key]=t.value!==void 0?t.value:t.type==="check"?!1:"";return a}function Te(){return"r"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function ut(e,a){if(e.title)return e.title(a);let t=e.fields.find(o=>!o.type||o.type==="text"||o.type==="textarea"||o.type==="select"),r=t&&a[t.key];return r===""||r===void 0||r===null?"(untitled)":String(r)}function mt({spec:e,records:a}){if(!e.summary)return null;let t=e.summary(a)||[];return t.length?n("div",{className:"caf-block caf-output"},n("div",{className:"caf-output-grid"},t.map((r,o)=>n("div",{key:r.label||o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},N(r.value,r.format)))))):null}function pt({spec:e,ctx:a}){let t=e.label||"item",[r,o]=k(""),s=a.data.records.map(l=>ne(e,l));e.sort&&(s=s.slice().sort(e.sort));let i=s.length,c=r.trim().toLowerCase();e.search&&c&&(s=s.filter(l=>e.fields.some(d=>String(l[d.key]??"").toLowerCase().includes(c))));function f(){let l={id:Te(),...Ae(e.fields)};e.items&&(l.items=[]),a.update(d=>{d.records=[...d.records,l]}),a.go("record",l.id)}return n("div",{className:"caf-block caf-list"},n("div",{className:"caf-toolbar"},n("span",{className:"caf-count"},e.search&&c?`${s.length} of ${i}`:`${i} ${t}${i===1?"":"s"}`),n("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:f},`Add ${t}`)),e.search?n("input",{className:"caf-search",value:r,placeholder:`Search ${t}s\u2026`,"aria-label":"Search",onChange:l=>o(l.target.value)}):null,e.search&&c&&s.length===0&&i>0?n("div",{className:"caf-empty"},`Nothing matches "${r}".`):null,s.length===0?n("div",{className:"caf-empty"},e.empty||`No ${t}s yet. Add the first one.`):s.map(l=>n("div",{key:l.id,className:"caf-row-wrap"},n("button",{type:"button",className:"caf-row",onClick:()=>a.go("record",l.id)},n("span",{className:"caf-row-title"},ut(e,l)),e.subtitle?n("span",{className:"caf-row-sub"},e.subtitle(l)):null),e.actions?n("div",{className:"caf-row-actions"},e.actions.filter(d=>!d.when||d.when(l,a.viewerId)).map(d=>n("button",{key:d.label,type:"button",className:d.kind==="danger"?"caf-btn caf-btn-danger caf-btn-sm":"caf-btn caf-btn-sm",onClick:()=>a.update(m=>{let h=m.records.find(u=>u.id===l.id);h&&d.run(h,m,a.viewerId)})},d.label))):null)))}function bt({spec:e,ctx:a,record:t}){let r=e.label||"item";function o(){a.update(s=>{s.records=s.records.filter(i=>i.id!==t.id)}),a.back()}return n("div",{className:"caf-block caf-fields"},n("div",{className:"caf-toolbar"},n("button",{type:"button",className:"caf-btn",onClick:a.back},"\u2039 Back"),n("button",{type:"button",className:"caf-btn caf-btn-danger",onClick:o},`Delete ${r}`)),e.fields.map(s=>n(O,{key:s.key,field:s,data:a.data,value:t[s.key],onChange:i=>a.update(c=>{let f=c.records.find(l=>l.id===t.id);f&&(f[s.key]=i)})})),e.items?n(ht,{spec:e,ctx:a,record:t}):null,e.compute?n("div",{className:"caf-output-grid caf-computed"},Ce(e).map(([s,i])=>{let c=ne(e,t);return n("div",{key:s,className:"caf-stat"},n("span",{className:"caf-stat-label"},i.label||s),n("span",{className:"caf-stat-value"},N(c[s],i.format)))})):null)}function ht({spec:e,ctx:a,record:t}){let r=e.items,o=r.label||"item";function s(c){a.update(f=>{let l=f.records.find(d=>d.id===t.id);l&&(Array.isArray(l.items)||(l.items=[]),c(l))})}let i=Array.isArray(t.items)?t.items:[];return n("div",{className:"caf-items"},n("div",{className:"caf-toolbar"},n("span",{className:"caf-count"},`${i.length} ${o}${i.length===1?"":"s"}`),n("button",{type:"button",className:"caf-btn caf-btn-sm",onClick:()=>s(c=>c.items.push({id:Te(),...Ae(r.fields)}))},`Add ${o}`)),i.length===0?n("div",{className:"caf-empty caf-empty-sm"},r.empty||`No ${o}s yet.`):i.map(c=>n("div",{key:c.id,className:"caf-item-row"},r.fields.map(f=>n(O,{key:f.key,field:f,data:a.data,value:c[f.key],onChange:l=>s(d=>{let m=d.items.find(h=>h.id===c.id);m&&(m[f.key]=l)})})),n("button",{type:"button",className:"caf-btn caf-btn-danger caf-btn-sm caf-item-remove","aria-label":`Remove ${o}`,onClick:()=>s(f=>{f.items=f.items.filter(l=>l.id!==c.id)})},"\u2715"))))}function je({spec:e,ctx:a}){let t=e.records;if(a.view.screen==="record"){let r=a.data.records.find(o=>o.id===a.view.arg);if(r)return n("div",{className:"caf-panel caf-panel-single"},n(bt,{spec:t,ctx:a,record:r}))}return n("div",{className:"caf-panel caf-panel-single"},n(mt,{spec:t,records:a.data.records.map(r=>ne(t,r))}),n(pt,{spec:t,ctx:a}))}function gt(e,a){return(e.fields||[]).some(t=>te(t,a[t.key])!==null)}function yt({step:e,ctx:a}){let t=e.result(a.data)||[];return n("div",{className:"caf-block caf-output"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-output-grid"},t.map((r,o)=>n("div",{key:r.label??o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},N(r.value,r.format)),r.hint?n("small",{className:"caf-hint"},r.hint):null))),n("div",{className:"caf-step-nav"},n("button",{type:"button",className:"caf-btn",onClick:()=>a.setStep(0)},"Start over")))}function Re({spec:e,ctx:a}){let t=e.steps,r=Math.min(Math.max(a.view.step||0,0),t.length-1),o=t[r],s=typeof o.result=="function",i=r===t.length-1;return n("div",{className:"caf-panel caf-panel-single"},n("div",{className:"caf-steps-progress"},n("span",{className:"caf-hint"},s?"Result":`Step ${r+1} of ${t.length}`),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill caf-steps-fill",style:{width:`${(r+1)/t.length*100}%`}}))),s?n(yt,{step:o,ctx:a}):n("div",{className:"caf-block caf-fields"},o.title?n("h2",{className:"caf-block-title"},o.title):null,o.text?n("p",{className:"caf-step-text"},typeof o.text=="function"?o.text(a.data):o.text):null,(o.fields||[]).map(c=>n(O,{key:c.key,field:c,data:a.data,value:a.data[c.key],onChange:f=>ae(a,c.key,c,f,(l,d)=>{l[c.key]=d})})),n("div",{className:"caf-step-nav"},r>0?n("button",{type:"button",className:"caf-btn",onClick:()=>a.setStep(r-1)},"\u2039 Back"):n("span"),i?null:n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:gt(o,a.data),onClick:()=>a.setStep(r+1)},"Next \u203A"))))}var Oe=["panel","records","steps","chat","workspace"],wt=["title","empty","wide","onSelect","subtitle","when","collapsible","fill"],Le=["title","subtitle","theme","layout","blocks","records","steps","chat","data","shared","main","sidebar","libs"];function F(e,a){for(let t of e||[]){if(!t||!t.key)throw new Error(`claude-artifact-framework: every field in ${a} needs a \`key\`.`);if(t.type!==void 0&&!ee.includes(t.type))throw new Error(`claude-artifact-framework: field "${t.key}" in ${a} has unknown type "${t.type}". Valid types: ${ee.join(", ")}.`);if(t.type==="select"&&t.options!==void 0&&!Array.isArray(t.options)&&typeof t.options!="function")throw new Error(`claude-artifact-framework: field "${t.key}" in ${a}: \`options\` must be an array or a function of data returning one.`)}}function _e(e,a){if(!e||typeof e.system!="string"&&typeof e.system!="function")throw new Error(`claude-artifact-framework: ${a} needs \`{ system: "..." }\` (a string or a function of data).`);let t=Object.keys(e).filter(r=>!G.includes(r));if(t.length)throw new Error(`claude-artifact-framework: ${a} has unknown keys (${t.join(", ")}). Valid keys: ${G.join(", ")}.`);for(let[r,o]of Object.entries(e.tools||{}))if(!o||typeof o.description!="string"||typeof o.run!="function")throw new Error(`claude-artifact-framework: chat tool "${r}" needs a \`description\` string and a \`run(input, ctx)\` function.`)}var Me=["label","run","when","kind"];function ze(e,a){if(!Array.isArray(e))throw new Error(`claude-artifact-framework: ${a} must be an array of { label, run }.`);e.forEach((t,r)=>{if(!t||typeof t.label!="string"||typeof t.run!="function")throw new Error(`claude-artifact-framework: ${a}[${r}] needs a \`label\` string and a \`run\` function.`);let o=Object.keys(t).filter(s=>!Me.includes(s));if(o.length)throw new Error(`claude-artifact-framework: ${a}[${r}] has unknown keys (${o.join(", ")}). Valid keys: ${Me.join(", ")}.`)})}function M(e){if(!Array.isArray(e))throw new Error("claude-artifact-framework: `blocks` must be an array.");e.forEach((a,t)=>{if(!a||typeof a!="object")throw new Error(`claude-artifact-framework: blocks[${t}] must be an object like { fields: [...] }.`);let r=Object.keys(a).filter(s=>!wt.includes(s)),o=r.filter(s=>V.includes(s)||s==="tabs");if(o.length===0)throw new Error(`claude-artifact-framework: blocks[${t}] has no recognised block type (found: ${r.join(", ")||"nothing"}). Valid block types: ${V.join(", ")}.`);if(o.length>1)throw new Error(`claude-artifact-framework: blocks[${t}] declares more than one block type (${o.join(", ")}). Split them into separate entries of \`blocks\`.`);if(F(a.fields,`blocks[${t}]`),o[0]==="actions"&&ze(a.actions,`blocks[${t}].actions`),o[0]==="chat"&&_e(a.chat,`blocks[${t}].chat`),o[0]==="tabs"){let s=a.tabs;if(!Array.isArray(s)||s.length===0)throw new Error(`claude-artifact-framework: blocks[${t}].tabs needs an array of { label, blocks: [...] }.`);s.forEach((i,c)=>{if(!i||typeof i.label!="string"||!Array.isArray(i.blocks)||i.blocks.length===0)throw new Error(`claude-artifact-framework: tabs[${c}] needs a \`label\` string and a non-empty \`blocks\` array.`);if(i.blocks.some(f=>f&&f.tabs))throw new Error("claude-artifact-framework: tabs cannot nest inside tabs.");M(i.blocks)})}if(a.when!==void 0&&typeof a.when!="function")throw new Error(`claude-artifact-framework: blocks[${t}].when must be a function of data returning true/false.`);if(a.fill!==void 0&&o[0]!=="custom")throw new Error(`claude-artifact-framework: \`fill\` is only valid on custom blocks \u2014 blocks[${t}] is "${o[0]}".`)})}function kt(e){let a=Object.keys(e).filter(r=>!Le.includes(r));if(a.length)throw new Error(`claude-artifact-framework: unknown top-level keys (${a.join(", ")}). Valid keys: ${Le.join(", ")}.`);if(e.libs!==void 0&&(!Array.isArray(e.libs)||e.libs.some(r=>typeof r!="string"||!/^https?:\/\//.test(r))))throw new Error("claude-artifact-framework: `libs` must be an array of https:// script URLs.");let t=e.layout||"panel";if(!Oe.includes(t))throw new Error(`claude-artifact-framework: unknown layout "${t}". Valid layouts: ${Oe.join(", ")}.`);if(t==="steps"){let r=e.steps;if(!Array.isArray(r)||r.length===0)throw new Error('claude-artifact-framework: layout "steps" needs `steps: [...]` with at least one step.');let o=["title","text","fields","result"],s=new Set;return r.forEach((i,c)=>{if(!i||typeof i!="object")throw new Error(`claude-artifact-framework: steps[${c}] must be an object.`);let f=Object.keys(i).filter(l=>!o.includes(l));if(f.length)throw new Error(`claude-artifact-framework: steps[${c}] has unknown keys (${f.join(", ")}). Valid keys: ${o.join(", ")}.`);if(!i.fields&&!i.text&&!i.result)throw new Error(`claude-artifact-framework: steps[${c}] needs \`fields\`, \`text\`, or \`result\`.`);F(i.fields,`steps[${c}]`);for(let l of i.fields||[]){if(s.has(l.key))throw new Error(`claude-artifact-framework: field key "${l.key}" appears in more than one step \u2014 keys share one data pool and must be unique.`);s.add(l.key)}}),t}if(t==="chat")return _e(e.chat,"chat"),t;if(t==="workspace"){if(!Array.isArray(e.main)||e.main.length===0)throw new Error('claude-artifact-framework: layout "workspace" needs `main: [...]` (an array of blocks). `sidebar: [...]` is optional.');if(M(e.main),e.sidebar!==void 0){if(!Array.isArray(e.sidebar))throw new Error("claude-artifact-framework: workspace `sidebar` must be an array of blocks.");M(e.sidebar)}if(se([...e.main,...e.sidebar||[]]).filter(o=>o&&o.chat).length>1)throw new Error("claude-artifact-framework: only one chat block per app \u2014 the conversation persists under data.chat and there is exactly one.");return t}if(t==="records"){let r=e.records;if(!r||!Array.isArray(r.fields)||r.fields.length===0)throw new Error('claude-artifact-framework: layout "records" needs `records: { fields: [...] }` \u2014 the same field declarations the fields block uses.');let o=["label","fields","title","subtitle","sort","summary","empty","search","compute","items","actions"],s=Object.keys(r).filter(c=>!o.includes(c));if(s.length)throw new Error(`claude-artifact-framework: records has unknown keys (${s.join(", ")}). Valid keys: ${o.join(", ")}.`);if(F(r.fields,"records"),r.fields.some(c=>c.type==="file")||r.items&&r.items.fields.some(c=>c.type==="file"))throw new Error("claude-artifact-framework: `file` fields live in the flat data pool (panel blocks or steps) \u2014 they are not supported inside records or items.");let i=new Set;for(let c of r.fields){if(c.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on records \u2014 the framework assigns it.');if(i.has(c.key))throw new Error(`claude-artifact-framework: duplicate records field key "${c.key}".`);i.add(c.key)}if(e.blocks&&M(e.blocks),r.actions&&ze(r.actions,"records.actions"),r.items){let c=["label","fields","empty"],f=Object.keys(r.items).filter(l=>!c.includes(l));if(f.length)throw new Error(`claude-artifact-framework: records.items has unknown keys (${f.join(", ")}). Valid keys: ${c.join(", ")}.`);if(!Array.isArray(r.items.fields)||r.items.fields.length===0)throw new Error("claude-artifact-framework: records.items needs `fields: [...]` \u2014 the same field declarations as everywhere else.");F(r.items.fields,"records.items");for(let l of r.items.fields)if(l.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on items \u2014 the framework assigns it.');if(i.has("items")||r.fields.some(l=>l.key==="items"))throw new Error('claude-artifact-framework: a records field cannot be named "items" when `items` is declared \u2014 that key holds the child collection.')}for(let[c,f]of Object.entries(r.compute||{})){if(i.has(c)||c==="id"||r.items&&c==="items")throw new Error(`claude-artifact-framework: compute key "${c}" collides with a field key \u2014 computed values are derived, never stored.`);if(typeof f!="function"&&typeof(f&&f.value)!="function")throw new Error(`claude-artifact-framework: compute "${c}" must be a function of the record, or { label, format, value: (r) => ... }.`)}return t}return M(e.blocks||[]),t}function se(e){let a=[];for(let t of e||[])if(a.push(t),t&&Array.isArray(t.tabs))for(let r of t.tabs)a.push(...se(r.blocks));return a}function vt(e){let a={...e.data||{}};(e.layout||"panel")==="records"&&!Array.isArray(a.records)&&(a.records=[]);let t=se([...e.blocks||[],...e.main||[],...e.sidebar||[]]);((e.layout||"panel")==="chat"||t.some(o=>o&&o.chat))&&!a.chat&&(a.chat={api:[],log:[]});for(let o of[...t,...e.steps||[]])for(let s of o.fields||[])s&&s.key!==void 0&&!(s.key in a)&&(a[s.key]=s.value!==void 0?s.value:s.type==="check"?!1:"");return a}var oe=null;function xt(e){return oe||(oe=class extends e.Component{constructor(a){super(a),this.state={error:null}}static getDerivedStateFromError(a){return{error:a}}render(){return this.state.error?n("div",{className:"caf-block caf-block-error"},n("strong",null,"This section failed to render"),n("code",null,String(this.state.error.message||this.state.error))):this.props.children}}),oe}function Nt({spec:e,ctx:a}){let t=e.tabs,r=t.map(i=>i.label).join("|"),o=a.view.tabs?a.view.tabs[r]:void 0,s=Math.min(o===void 0?0:o,t.length-1);return n("div",{className:"caf-tabs"},n("div",{className:"caf-tabbar",role:"tablist"},t.map((i,c)=>n("button",{key:i.label,type:"button",role:"tab","aria-selected":c===s,className:c===s?"caf-tab caf-tab-active":"caf-tab",onClick:()=>a.setTab(r,c)},i.label))),n("div",{className:"caf-tabs-body"},t[s].blocks.map((i,c)=>n(P,{key:s+":"+c,block:i,ctx:a}))))}var St={...re,tabs:Nt},Et=[...V,"tabs"];function P({block:e,ctx:a}){if(typeof e.when=="function"&&!e.when(a.data))return null;let t=Object.keys(e).find(c=>Et.includes(c)),r=St[t],o=n(xt(a.React),null,n(r,{spec:e.collapsible?{...e,title:void 0}:e,ctx:a}));if(!e.collapsible)return o;let s=typeof e.title=="string"&&e.title?e.title:t,i=a.view.collapsed&&s in a.view.collapsed?a.view.collapsed[s]:e.collapsible==="collapsed";return n("div",{className:"caf-collapse"},n("button",{type:"button",className:"caf-collapse-head","aria-expanded":!i,onClick:()=>a.toggleCollapsed(s,!i)},n("span",null,e.title||t),n("span",{className:i?"caf-chevron caf-chevron-closed":"caf-chevron"},"\u25BE")),i?null:n("div",{className:"caf-collapse-body"},o))}function $t({spec:e,ctx:a}){return n("div",{className:"caf-panel"},(e.blocks||[]).map((t,r)=>n("section",{key:r,className:t.wide?"caf-slot caf-slot-wide":"caf-slot"},n(P,{block:t,ctx:a}))))}function Ct({spec:e,ctx:a}){let t=a.view.screen==="record"&&(a.data.records||[]).some(r=>r.id===a.view.arg);return n("div",null,n(je,{spec:e,ctx:a}),!t&&Array.isArray(e.blocks)&&e.blocks.length?n("div",{className:"caf-panel caf-records-blocks"},e.blocks.map((r,o)=>n("section",{key:o,className:r.wide?"caf-slot caf-slot-wide":"caf-slot"},n(P,{block:r,ctx:a})))):null)}function At({spec:e,ctx:a}){let t=r=>(r||[]).map((o,s)=>n("section",{key:s,className:"caf-ws-slot"},n(P,{block:o,ctx:a})));return n("div",{className:"caf-workspace"},n("div",{className:"caf-ws-main"},t(e.main)),e.sidebar&&e.sidebar.length?n("div",{className:"caf-ws-side"},t(e.sidebar)):null)}var Tt={panel:$t,records:Ct,steps:Re,chat:Ee,workspace:At};function jt(e){return new Promise((a,t)=>{let r=document.querySelector(`script[src="${e}"]`);if(r){if(r.dataset.cafReady==="1")return a();r.addEventListener("load",a),r.addEventListener("error",()=>t(new Error(`failed to load ${e}`)));return}let o=document.createElement("script");o.src=e,o.onload=()=>{o.dataset.cafReady="1",a()},o.onerror=()=>t(new Error(`failed to load ${e}`)),document.head.appendChild(o)})}function Be(e={}){let a=kt(e),t=we(vt(e),{shared:!!e.shared}),r=I(e.theme&&e.theme.seed)+Rt,o={};return function(){if(!_())throw new Error(`claude-artifact-framework: React not found. Hand it over once, before rendering:
28
+ Continue with this information. If you have everything you need, answer in natural language without further tool_call.`}],T(),l(null)}}catch(x){v=[...v,{role:"error",content:String(x&&x.message||x)}],T()}finally{l(null),c(!1)}}return n("div",{className:"caf-chat-panel"},n("div",{className:"caf-block caf-chat-log"},a?n("h2",{className:"caf-block-title"},a):null,r.greeting?n("div",{className:"caf-msg caf-msg-assistant",dangerouslySetInnerHTML:{__html:G(r.greeting)}}):null,b.map((p,N)=>n(tt,{key:N,m:p})),f!==null?n("div",{className:"caf-msg caf-msg-assistant caf-msg-live",dangerouslySetInnerHTML:{__html:G(f||"\u2026")}}):null,i&&f===null?n("div",{className:"caf-msg-tools"},"thinking\u2026"):null,n("div",{ref:d})),n("div",{className:"caf-chat-input"},n("input",{value:o,placeholder:r.placeholder||"Message\u2026",disabled:i,enterKeyHint:"send",onChange:p=>s(p.target.value),onKeyDown:p=>{p.key==="Enter"&&(p.preventDefault(),m())},"aria-label":"Message"}),n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:i||!o.trim(),onClick:m},"Send")))}function $e({spec:e,ctx:t}){return n("div",{className:"caf-panel caf-panel-single"},n(ee,{cfg:e.chat,ctx:t}))}var te=["text","textarea","number","money","percent","check","date","select","file"];function S(e,t){if(e==null||e==="")return"\u2014";let a=Number(e);switch(t){case"money":return Number.isFinite(a)?a.toLocaleString(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2}):String(e);case"percent":return Number.isFinite(a)?`${a.toLocaleString(void 0,{maximumFractionDigits:2})}%`:String(e);case"number":return Number.isFinite(a)?a.toLocaleString(void 0,{maximumFractionDigits:2}):String(e);case"date":return e instanceof Date?e.toLocaleDateString():String(e);default:return String(e)}}function ae(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 a=Number(t);if(!Number.isFinite(a))return"Must be a number";if(e.min!==void 0&&a<e.min)return`Must be at least ${e.min}`;if(e.max!==void 0&&a>e.max)return`Must be at most ${e.max}`}return null}function R({field:e,value:t,onChange:a,data:r}){let o=ae(e,t),s=`caf-f-${e.key}`,i=e.type==="number"||e.type==="money"||e.type==="percent";if(e.type==="file")return n("div",{className:"caf-field"},n("label",{htmlFor:s},e.label||e.key),n("input",{id:s,type:"file",accept:e.accept,onChange:l=>a(l.target.files&&l.target.files[0]?l.target.files[0]:null)}),t&&t.name?n("small",{className:"caf-hint"},`${t.name} (${Math.round((t.size||0)/1024)} KB)${t.stale?" \u2014 re-pick after reload":""}`):e.hint?n("small",{className:"caf-hint"},e.hint):null);if(e.type==="check")return n("label",{className:"caf-check"},n("input",{id:s,type:"checkbox",checked:!!t,onChange:l=>a(l.target.checked)}),n("span",null,e.label||e.key));let c={id:s,value:t??"","aria-invalid":o?"true":void 0,onChange:l=>a(i?at(l.target.value):l.target.value)},f;if(e.type==="textarea")f=n("textarea",{...c,rows:e.rows||3});else if(e.type==="select"){let l=typeof e.options=="function"?e.options(r)||[]:e.options||[];f=n("select",c,n("option",{value:""},e.placeholder||"Select\u2026"),l.map(d=>{let u=typeof d=="string"?d:d.value,b=typeof d=="string"?d:d.label;return n("option",{key:u,value:u},b)}))}else f=n("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});return n("div",{className:"caf-field"},n("label",{htmlFor:s},e.label||e.key),f,e.hint&&!o?n("small",{className:"caf-hint"},e.hint):null,o?n("small",{className:"caf-error"},o):null)}function at(e){if(e==="")return"";let t=Number(e);return Number.isFinite(t)?t:e}function re(e,t,a,r,o){if(a.type==="file"){e.files[t]=r||null;let s=r?{name:r.name,size:r.size,type:r.type}:null;e.update(i=>o(i,s));return}e.update(s=>o(s,r))}function rt({spec:e,ctx:t}){let a=e.fields||[];return n("div",{className:"caf-block caf-fields"},e.title?n("h2",{className:"caf-block-title"},e.title):null,a.map(r=>n(R,{key:r.key,field:r,data:t.data,value:t.data[r.key],onChange:o=>re(t,r.key,r,o,(s,i)=>{s[r.key]=i})})))}function nt({spec:e,ctx:t}){let a=typeof e.output=="function"?e.output(t.data):e.output||[];return a.length?n("div",{className:"caf-block caf-output"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-output-grid"},a.map((r,o)=>n("div",{key:r.label||o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},S(r.value,r.format)),r.hint?n("small",{className:"caf-hint"},r.hint):null)))):n("div",{className:"caf-block caf-empty"},e.empty||"Nothing to show yet.")}function ot({spec:e,ctx:t}){let a=typeof e.text=="function"?e.text(t.data):e.text;return n("div",{className:"caf-block caf-text"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("p",null,a))}function st({spec:e,ctx:t}){let a=(typeof e.list=="function"?e.list(t.data):e.list)||[],r=typeof e.title=="string"?e.title:null,o=typeof e.title=="function"?e.title:s=>s.title??s.name??s.label??s.text??String(s);return a.length?n("div",{className:"caf-block caf-list"},r?n("h2",{className:"caf-block-title"},r):null,a.map((s,i)=>n("button",{key:s.id??i,className:"caf-row",type:"button",onClick:e.onSelect?()=>e.onSelect(s,t):void 0},n("span",{className:"caf-row-title"},o(s)),e.subtitle?n("span",{className:"caf-row-sub"},e.subtitle(s)):null))):n("div",{className:"caf-block caf-empty"},e.empty||"Nothing here yet.")}var Ae=["bar","line","donut"];function it({spec:e,ctx:t}){let a=typeof e.chart=="function"?e.chart(t.data):e.chart,r=a&&a.items||[];if(!r.length)return n("div",{className:"caf-block caf-empty"},e.empty||"No data to chart yet.");let o=a.type||"bar";if(!Ae.includes(o))throw new Error(`unknown chart type "${o}". Valid types: ${Ae.join(", ")}.`);let s=t.colors(r.length),i=o==="bar"?ct(r,a,s):o==="line"?lt(r,a):ft(r,a,s);return n("div",{className:"caf-block caf-chart"},e.title?n("h2",{className:"caf-block-title"},e.title):null,i)}function ct(e,t,a){let r=Math.max(...e.map(o=>Number(o.value)||0),0)||1;return n("div",{className:"caf-bars"},e.map((o,s)=>n("div",{key:o.label??s,className:"caf-bar-row"},n("span",{className:"caf-bar-label"},o.label),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill",style:{width:`${Math.max(2,(Number(o.value)||0)/r*100)}%`,background:a[s]}})),n("span",{className:"caf-bar-value"},S(o.value,t.format)))))}function lt(e,t){let a=e.map(d=>Number(d.value)||0),r=Math.min(...a),s=Math.max(...a)-r||1,i=100,c=36,f=a.map((d,u)=>[a.length===1?i/2:u/(a.length-1)*i,c-3-(d-r)/s*(c-6)]),l=f[f.length-1];return n("div",{className:"caf-line"},n("svg",{viewBox:`0 0 ${i} ${c}`,className:"caf-line-svg",preserveAspectRatio:"none","aria-hidden":"true"},[.25,.5,.75].map(d=>n("line",{key:d,x1:0,x2:i,y1:c*d,y2:c*d,className:"caf-line-grid"})),n("polyline",{points:f.map(d=>d.join(",")).join(" "),className:"caf-line-path"}),n("circle",{cx:l[0],cy:l[1],r:1.6,className:"caf-line-dot"})),n("div",{className:"caf-line-meta"},n("span",{className:"caf-hint"},String(e[0].label??"")),n("span",{className:"caf-line-last"},S(a[a.length-1],t.format)),n("span",{className:"caf-hint"},String(e[e.length-1].label??""))))}function ft(e,t,a){let r=e.reduce((c,f)=>c+(Number(f.value)||0),0)||1,o=15.9155,s=25,i=e.map((c,f)=>{let l=(Number(c.value)||0)/r*100,d=n("circle",{key:c.label??f,cx:21,cy:21,r:o,className:"caf-donut-seg",stroke:a[f],strokeDasharray:`${l} ${100-l}`,strokeDashoffset:s});return s-=l,d});return n("div",{className:"caf-donut"},n("svg",{viewBox:"0 0 42 42",className:"caf-donut-svg","aria-hidden":"true"},i),n("div",{className:"caf-donut-legend"},e.map((c,f)=>n("div",{key:c.label??f,className:"caf-legend-row"},n("span",{className:"caf-legend-swatch",style:{background:a[f]}}),n("span",{className:"caf-legend-label"},c.label),n("span",{className:"caf-legend-value"},S(c.value,t.format))))))}function dt({spec:e,ctx:t}){let a=e.timer||{},r=Math.max(1,Math.round((a.minutes||0)*60+(a.seconds||0))||300),[o,s]=k(r),[i,c]=k(!1);E(()=>{if(!i)return;let u=setInterval(()=>s(b=>Math.max(0,b-1)),1e3);return()=>clearInterval(u)},[i]),E(()=>{o===0&&i&&(c(!1),typeof a.onDone=="function"&&t.update(u=>a.onDone(u)))},[o,i]);let f=String(Math.floor(o/60)).padStart(2,"0"),l=String(o%60).padStart(2,"0"),d=o===0;return n("div",{className:"caf-block caf-timer"},e.title?n("h2",{className:"caf-block-title"},e.title):null,a.label?n("span",{className:"caf-hint"},a.label):null,n("div",{className:d?"caf-timer-time caf-timer-done":"caf-timer-time"},d?a.doneText||"Done!":`${f}:${l}`),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill caf-timer-fill",style:{width:`${o/r*100}%`}})),n("div",{className:"caf-timer-controls"},n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:d,onClick:()=>c(u=>!u)},i?"Pause":"Start"),n("button",{type:"button",className:"caf-btn",onClick:()=>{c(!1),s(r)}},"Reset")))}function ut({spec:e,ctx:t}){let r=(e.actions||[]).filter(o=>!o.when||o.when(t.data,t.viewerId));return n("div",{className:"caf-block caf-actions"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-actions-row"},r.map(o=>n("button",{key:o.label,type:"button",className:o.kind==="danger"?"caf-btn caf-btn-danger":o.kind==="primary"?"caf-btn caf-btn-primary":"caf-btn",onClick:()=>t.update(s=>o.run(s,t.viewerId))},o.label))))}function mt({spec:e,ctx:t}){let a=e.custom(t),r=e.fill?"caf-block caf-block-fill":"caf-block";return typeof a=="string"?n("div",{className:r,dangerouslySetInnerHTML:{__html:a}}):n("div",{className:r},a)}var ne={fields:rt,output:nt,text:ot,list:st,chart:it,timer:dt,actions:ut,chat:({spec:e,ctx:t})=>n(ee,{cfg:e.chat,ctx:t,title:e.title}),custom:mt},V=Object.keys(ne);function Ce(e){return Object.entries(e.compute||{}).map(([t,a])=>[t,typeof a=="function"?{value:a}:a])}function oe(e,t){if(!e.compute)return t;let a={...t};for(let[r,o]of Ce(e))try{a[r]=o.value(t)}catch{a[r]=void 0}return a}function Te(e){let t={};for(let a of e)t[a.key]=a.value!==void 0?a.value:a.type==="check"?!1:"";return t}function je(){return"r"+Date.now().toString(36)+Math.random().toString(36).slice(2,8)}function pt(e,t){if(e.title)return e.title(t);let a=e.fields.find(o=>!o.type||o.type==="text"||o.type==="textarea"||o.type==="select"),r=a&&t[a.key];return r===""||r===void 0||r===null?"(untitled)":String(r)}function ht({spec:e,records:t}){if(!e.summary)return null;let a=e.summary(t)||[];return a.length?n("div",{className:"caf-block caf-output"},n("div",{className:"caf-output-grid"},a.map((r,o)=>n("div",{key:r.label||o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},S(r.value,r.format)))))):null}function bt({spec:e,ctx:t}){let a=e.label||"item",[r,o]=k(""),s=t.data.records.map(l=>oe(e,l));e.sort&&(s=s.slice().sort(e.sort));let i=s.length,c=r.trim().toLowerCase();e.search&&c&&(s=s.filter(l=>e.fields.some(d=>String(l[d.key]??"").toLowerCase().includes(c))));function f(){let l={id:je(),...Te(e.fields)};e.items&&(l.items=[]),t.update(d=>{d.records=[...d.records,l]}),t.go("record",l.id)}return n("div",{className:"caf-block caf-list"},n("div",{className:"caf-toolbar"},n("span",{className:"caf-count"},e.search&&c?`${s.length} of ${i}`:`${i} ${a}${i===1?"":"s"}`),n("button",{type:"button",className:"caf-btn caf-btn-primary",onClick:f},`Add ${a}`)),e.search?n("input",{className:"caf-search",value:r,placeholder:`Search ${a}s\u2026`,"aria-label":"Search",onChange:l=>o(l.target.value)}):null,e.search&&c&&s.length===0&&i>0?n("div",{className:"caf-empty"},`Nothing matches "${r}".`):null,s.length===0?n("div",{className:"caf-empty"},e.empty||`No ${a}s yet. Add the first one.`):s.map(l=>n("div",{key:l.id,className:"caf-row-wrap"},n("button",{type:"button",className:"caf-row",onClick:()=>t.go("record",l.id)},n("span",{className:"caf-row-title"},pt(e,l)),e.subtitle?n("span",{className:"caf-row-sub"},e.subtitle(l)):null),e.actions?n("div",{className:"caf-row-actions"},e.actions.filter(d=>!d.when||d.when(l,t.viewerId)).map(d=>n("button",{key:d.label,type:"button",className:d.kind==="danger"?"caf-btn caf-btn-danger caf-btn-sm":"caf-btn caf-btn-sm",onClick:()=>t.update(u=>{let b=u.records.find(m=>m.id===l.id);b&&d.run(b,u,t.viewerId)})},d.label))):null)))}function gt({spec:e,ctx:t,record:a}){let r=e.label||"item";function o(){t.update(s=>{s.records=s.records.filter(i=>i.id!==a.id)}),t.back()}return n("div",{className:"caf-block caf-fields"},n("div",{className:"caf-toolbar"},n("button",{type:"button",className:"caf-btn",onClick:t.back},"\u2039 Back"),n("button",{type:"button",className:"caf-btn caf-btn-danger",onClick:o},`Delete ${r}`)),e.fields.map(s=>n(R,{key:s.key,field:s,data:t.data,value:a[s.key],onChange:i=>t.update(c=>{let f=c.records.find(l=>l.id===a.id);f&&(f[s.key]=i)})})),e.items?n(yt,{spec:e,ctx:t,record:a}):null,e.compute?n("div",{className:"caf-output-grid caf-computed"},Ce(e).map(([s,i])=>{let c=oe(e,a);return n("div",{key:s,className:"caf-stat"},n("span",{className:"caf-stat-label"},i.label||s),n("span",{className:"caf-stat-value"},S(c[s],i.format)))})):null)}function yt({spec:e,ctx:t,record:a}){let r=e.items,o=r.label||"item";function s(c){t.update(f=>{let l=f.records.find(d=>d.id===a.id);l&&(Array.isArray(l.items)||(l.items=[]),c(l))})}let i=Array.isArray(a.items)?a.items:[];return n("div",{className:"caf-items"},n("div",{className:"caf-toolbar"},n("span",{className:"caf-count"},`${i.length} ${o}${i.length===1?"":"s"}`),n("button",{type:"button",className:"caf-btn caf-btn-sm",onClick:()=>s(c=>c.items.push({id:je(),...Te(r.fields)}))},`Add ${o}`)),i.length===0?n("div",{className:"caf-empty caf-empty-sm"},r.empty||`No ${o}s yet.`):i.map(c=>n("div",{key:c.id,className:"caf-item-row"},r.fields.map(f=>n(R,{key:f.key,field:f,data:t.data,value:c[f.key],onChange:l=>s(d=>{let u=d.items.find(b=>b.id===c.id);u&&(u[f.key]=l)})})),n("button",{type:"button",className:"caf-btn caf-btn-danger caf-btn-sm caf-item-remove","aria-label":`Remove ${o}`,onClick:()=>s(f=>{f.items=f.items.filter(l=>l.id!==c.id)})},"\u2715"))))}function Oe({spec:e,ctx:t}){let a=e.records;if(t.view.screen==="record"){let r=t.data.records.find(o=>o.id===t.view.arg);if(r)return n("div",{className:"caf-panel caf-panel-single"},n(gt,{spec:a,ctx:t,record:r}))}return n("div",{className:"caf-panel caf-panel-single"},n(ht,{spec:a,records:t.data.records.map(r=>oe(a,r))}),n(bt,{spec:a,ctx:t}))}function wt(e,t){return(e.fields||[]).some(a=>ae(a,t[a.key])!==null)}function kt({step:e,ctx:t}){let a=e.result(t.data)||[];return n("div",{className:"caf-block caf-output"},e.title?n("h2",{className:"caf-block-title"},e.title):null,n("div",{className:"caf-output-grid"},a.map((r,o)=>n("div",{key:r.label??o,className:r.big?"caf-stat caf-stat-big":"caf-stat"},n("span",{className:"caf-stat-label"},r.label),n("span",{className:"caf-stat-value"},S(r.value,r.format)),r.hint?n("small",{className:"caf-hint"},r.hint):null))),n("div",{className:"caf-step-nav"},n("button",{type:"button",className:"caf-btn",onClick:()=>t.setStep(0)},"Start over")))}function Re({spec:e,ctx:t}){let a=e.steps,r=Math.min(Math.max(t.view.step||0,0),a.length-1),o=a[r],s=typeof o.result=="function",i=r===a.length-1;return n("div",{className:"caf-panel caf-panel-single"},n("div",{className:"caf-steps-progress"},n("span",{className:"caf-hint"},s?"Result":`Step ${r+1} of ${a.length}`),n("div",{className:"caf-bar-track"},n("div",{className:"caf-bar-fill caf-steps-fill",style:{width:`${(r+1)/a.length*100}%`}}))),s?n(kt,{step:o,ctx:t}):n("div",{className:"caf-block caf-fields"},o.title?n("h2",{className:"caf-block-title"},o.title):null,o.text?n("p",{className:"caf-step-text"},typeof o.text=="function"?o.text(t.data):o.text):null,(o.fields||[]).map(c=>n(R,{key:c.key,field:c,data:t.data,value:t.data[c.key],onChange:f=>re(t,c.key,c,f,(l,d)=>{l[c.key]=d})})),n("div",{className:"caf-step-nav"},r>0?n("button",{type:"button",className:"caf-btn",onClick:()=>t.setStep(r-1)},"\u2039 Back"):n("span"),i?null:n("button",{type:"button",className:"caf-btn caf-btn-primary",disabled:wt(o,t.data),onClick:()=>t.setStep(r+1)},"Next \u203A"))))}var Le=["panel","records","steps","chat","workspace"],vt=["title","empty","wide","onSelect","subtitle","when","collapsible","fill"],Me=["title","subtitle","theme","layout","blocks","records","steps","chat","data","shared","main","sidebar","libs"];function F(e,t){for(let a of e||[]){if(!a||!a.key)throw new Error(`claude-artifact-framework: every field in ${t} needs a \`key\`.`);if(a.type!==void 0&&!te.includes(a.type))throw new Error(`claude-artifact-framework: field "${a.key}" in ${t} has unknown type "${a.type}". Valid types: ${te.join(", ")}.`);if(a.type==="select"&&a.options!==void 0&&!Array.isArray(a.options)&&typeof a.options!="function")throw new Error(`claude-artifact-framework: field "${a.key}" in ${t}: \`options\` must be an array or a function of data returning one.`)}}function ze(e,t){if(!e||typeof e.system!="string"&&typeof e.system!="function")throw new Error(`claude-artifact-framework: ${t} needs \`{ system: "..." }\` (a string or a function of data).`);let a=Object.keys(e).filter(r=>!Z.includes(r));if(a.length)throw new Error(`claude-artifact-framework: ${t} has unknown keys (${a.join(", ")}). Valid keys: ${Z.join(", ")}.`);for(let[r,o]of Object.entries(e.tools||{}))if(!o||typeof o.description!="string"||typeof o.run!="function")throw new Error(`claude-artifact-framework: chat tool "${r}" needs a \`description\` string and a \`run(input, ctx)\` function.`)}var _e=["label","run","when","kind"];function Be(e,t){if(!Array.isArray(e))throw new Error(`claude-artifact-framework: ${t} must be an array of { label, run }.`);e.forEach((a,r)=>{if(!a||typeof a.label!="string"||typeof a.run!="function")throw new Error(`claude-artifact-framework: ${t}[${r}] needs a \`label\` string and a \`run\` function.`);let o=Object.keys(a).filter(s=>!_e.includes(s));if(o.length)throw new Error(`claude-artifact-framework: ${t}[${r}] has unknown keys (${o.join(", ")}). Valid keys: ${_e.join(", ")}.`)})}function M(e){if(!Array.isArray(e))throw new Error("claude-artifact-framework: `blocks` must be an array.");e.forEach((t,a)=>{if(!t||typeof t!="object")throw new Error(`claude-artifact-framework: blocks[${a}] must be an object like { fields: [...] }.`);let r=Object.keys(t).filter(s=>!vt.includes(s)),o=r.filter(s=>V.includes(s)||s==="tabs");if(o.length===0)throw new Error(`claude-artifact-framework: blocks[${a}] has no recognised block type (found: ${r.join(", ")||"nothing"}). Valid block types: ${V.join(", ")}.`);if(o.length>1)throw new Error(`claude-artifact-framework: blocks[${a}] declares more than one block type (${o.join(", ")}). Split them into separate entries of \`blocks\`.`);if(F(t.fields,`blocks[${a}]`),o[0]==="actions"&&Be(t.actions,`blocks[${a}].actions`),o[0]==="chat"&&ze(t.chat,`blocks[${a}].chat`),o[0]==="tabs"){let s=t.tabs;if(!Array.isArray(s)||s.length===0)throw new Error(`claude-artifact-framework: blocks[${a}].tabs needs an array of { label, blocks: [...] }.`);s.forEach((i,c)=>{if(!i||typeof i.label!="string"||!Array.isArray(i.blocks)||i.blocks.length===0)throw new Error(`claude-artifact-framework: tabs[${c}] needs a \`label\` string and a non-empty \`blocks\` array.`);if(i.blocks.some(f=>f&&f.tabs))throw new Error("claude-artifact-framework: tabs cannot nest inside tabs.");M(i.blocks)})}if(t.when!==void 0&&typeof t.when!="function")throw new Error(`claude-artifact-framework: blocks[${a}].when must be a function of data returning true/false.`);if(t.fill!==void 0&&o[0]!=="custom")throw new Error(`claude-artifact-framework: \`fill\` is only valid on custom blocks \u2014 blocks[${a}] is "${o[0]}".`)})}function xt(e){let t=Object.keys(e).filter(r=>!Me.includes(r));if(t.length)throw new Error(`claude-artifact-framework: unknown top-level keys (${t.join(", ")}). Valid keys: ${Me.join(", ")}.`);if(e.libs!==void 0&&(!Array.isArray(e.libs)||e.libs.some(r=>typeof r!="string"||!/^https?:\/\//.test(r))))throw new Error("claude-artifact-framework: `libs` must be an array of https:// script URLs.");let a=e.layout||"panel";if(!Le.includes(a))throw new Error(`claude-artifact-framework: unknown layout "${a}". Valid layouts: ${Le.join(", ")}.`);if(a==="steps"){let r=e.steps;if(!Array.isArray(r)||r.length===0)throw new Error('claude-artifact-framework: layout "steps" needs `steps: [...]` with at least one step.');let o=["title","text","fields","result"],s=new Set;return r.forEach((i,c)=>{if(!i||typeof i!="object")throw new Error(`claude-artifact-framework: steps[${c}] must be an object.`);let f=Object.keys(i).filter(l=>!o.includes(l));if(f.length)throw new Error(`claude-artifact-framework: steps[${c}] has unknown keys (${f.join(", ")}). Valid keys: ${o.join(", ")}.`);if(!i.fields&&!i.text&&!i.result)throw new Error(`claude-artifact-framework: steps[${c}] needs \`fields\`, \`text\`, or \`result\`.`);F(i.fields,`steps[${c}]`);for(let l of i.fields||[]){if(s.has(l.key))throw new Error(`claude-artifact-framework: field key "${l.key}" appears in more than one step \u2014 keys share one data pool and must be unique.`);s.add(l.key)}}),a}if(a==="chat")return ze(e.chat,"chat"),a;if(a==="workspace"){if(!Array.isArray(e.main)||e.main.length===0)throw new Error('claude-artifact-framework: layout "workspace" needs `main: [...]` (an array of blocks). `sidebar: [...]` is optional.');if(M(e.main),e.sidebar!==void 0){if(!Array.isArray(e.sidebar))throw new Error("claude-artifact-framework: workspace `sidebar` must be an array of blocks.");M(e.sidebar)}if(ie([...e.main,...e.sidebar||[]]).filter(o=>o&&o.chat).length>1)throw new Error("claude-artifact-framework: only one chat block per app \u2014 the conversation persists under data.chat and there is exactly one.");return a}if(a==="records"){let r=e.records;if(!r||!Array.isArray(r.fields)||r.fields.length===0)throw new Error('claude-artifact-framework: layout "records" needs `records: { fields: [...] }` \u2014 the same field declarations the fields block uses.');let o=["label","fields","title","subtitle","sort","summary","empty","search","compute","items","actions"],s=Object.keys(r).filter(c=>!o.includes(c));if(s.length)throw new Error(`claude-artifact-framework: records has unknown keys (${s.join(", ")}). Valid keys: ${o.join(", ")}.`);if(F(r.fields,"records"),r.fields.some(c=>c.type==="file")||r.items&&r.items.fields.some(c=>c.type==="file"))throw new Error("claude-artifact-framework: `file` fields live in the flat data pool (panel blocks or steps) \u2014 they are not supported inside records or items.");let i=new Set;for(let c of r.fields){if(c.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on records \u2014 the framework assigns it.');if(i.has(c.key))throw new Error(`claude-artifact-framework: duplicate records field key "${c.key}".`);i.add(c.key)}if(e.blocks&&M(e.blocks),r.actions&&Be(r.actions,"records.actions"),r.items){let c=["label","fields","empty"],f=Object.keys(r.items).filter(l=>!c.includes(l));if(f.length)throw new Error(`claude-artifact-framework: records.items has unknown keys (${f.join(", ")}). Valid keys: ${c.join(", ")}.`);if(!Array.isArray(r.items.fields)||r.items.fields.length===0)throw new Error("claude-artifact-framework: records.items needs `fields: [...]` \u2014 the same field declarations as everywhere else.");F(r.items.fields,"records.items");for(let l of r.items.fields)if(l.key==="id")throw new Error('claude-artifact-framework: "id" is reserved on items \u2014 the framework assigns it.');if(i.has("items")||r.fields.some(l=>l.key==="items"))throw new Error('claude-artifact-framework: a records field cannot be named "items" when `items` is declared \u2014 that key holds the child collection.')}for(let[c,f]of Object.entries(r.compute||{})){if(i.has(c)||c==="id"||r.items&&c==="items")throw new Error(`claude-artifact-framework: compute key "${c}" collides with a field key \u2014 computed values are derived, never stored.`);if(typeof f!="function"&&typeof(f&&f.value)!="function")throw new Error(`claude-artifact-framework: compute "${c}" must be a function of the record, or { label, format, value: (r) => ... }.`)}return a}return M(e.blocks||[]),a}function ie(e){let t=[];for(let a of e||[])if(t.push(a),a&&Array.isArray(a.tabs))for(let r of a.tabs)t.push(...ie(r.blocks));return t}function Nt(e){let t={...e.data||{}};(e.layout||"panel")==="records"&&!Array.isArray(t.records)&&(t.records=[]);let a=ie([...e.blocks||[],...e.main||[],...e.sidebar||[]]);((e.layout||"panel")==="chat"||a.some(o=>o&&o.chat))&&!t.chat&&(t.chat={api:[],log:[]});for(let o of[...a,...e.steps||[]])for(let s of o.fields||[])s&&s.key!==void 0&&!(s.key in t)&&(t[s.key]=s.value!==void 0?s.value:s.type==="check"?!1:"");return t}var se=null;function St(e){return se||(se=class extends e.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?n("div",{className:"caf-block caf-block-error"},n("strong",null,"This section failed to render"),n("code",null,String(this.state.error.message||this.state.error))):this.props.children}}),se}function Et({spec:e,ctx:t}){let a=e.tabs,r=a.map(i=>i.label).join("|"),o=t.view.tabs?t.view.tabs[r]:void 0,s=Math.min(o===void 0?0:o,a.length-1);return n("div",{className:"caf-tabs"},n("div",{className:"caf-tabbar",role:"tablist"},a.map((i,c)=>n("button",{key:i.label,type:"button",role:"tab","aria-selected":c===s,className:c===s?"caf-tab caf-tab-active":"caf-tab",onClick:()=>t.setTab(r,c)},i.label))),n("div",{className:"caf-tabs-body"},a[s].blocks.map((i,c)=>n(P,{key:s+":"+c,block:i,ctx:t}))))}var $t={...ne,tabs:Et},At=[...V,"tabs"];function P({block:e,ctx:t}){if(typeof e.when=="function"&&!e.when(t.data))return null;let a=Object.keys(e).find(c=>At.includes(c)),r=$t[a],o=n(St(t.React),null,n(r,{spec:e.collapsible?{...e,title:void 0}:e,ctx:t}));if(!e.collapsible)return o;let s=typeof e.title=="string"&&e.title?e.title:a,i=t.view.collapsed&&s in t.view.collapsed?t.view.collapsed[s]:e.collapsible==="collapsed";return n("div",{className:"caf-collapse"},n("button",{type:"button",className:"caf-collapse-head","aria-expanded":!i,onClick:()=>t.toggleCollapsed(s,!i)},n("span",null,e.title||a),n("span",{className:i?"caf-chevron caf-chevron-closed":"caf-chevron"},"\u25BE")),i?null:n("div",{className:"caf-collapse-body"},o))}function Ct({spec:e,ctx:t}){return n("div",{className:"caf-panel"},(e.blocks||[]).map((a,r)=>n("section",{key:r,className:a.wide||a.collapsible?"caf-slot caf-slot-wide":"caf-slot"},n(P,{block:a,ctx:t}))))}function Tt({spec:e,ctx:t}){let a=t.view.screen==="record"&&(t.data.records||[]).some(r=>r.id===t.view.arg);return n("div",null,n(Oe,{spec:e,ctx:t}),!a&&Array.isArray(e.blocks)&&e.blocks.length?n("div",{className:"caf-panel caf-records-blocks"},e.blocks.map((r,o)=>n("section",{key:o,className:r.wide||r.collapsible?"caf-slot caf-slot-wide":"caf-slot"},n(P,{block:r,ctx:t})))):null)}function jt({spec:e,ctx:t}){let a=r=>(r||[]).map((o,s)=>n("section",{key:s,className:"caf-ws-slot"},n(P,{block:o,ctx:t})));return n("div",{className:"caf-workspace"},n("div",{className:"caf-ws-main"},a(e.main)),e.sidebar&&e.sidebar.length?n("div",{className:"caf-ws-side"},a(e.sidebar)):null)}var Ot={panel:Ct,records:Tt,steps:Re,chat:$e,workspace:jt};function Ie(e){return new Promise((t,a)=>{let r=document.querySelector(`script[src="${e}"]`);if(r){if(r.dataset.cafReady==="1")return t();r.addEventListener("load",t),r.addEventListener("error",()=>a(new Error(`failed to load ${e}`)));return}let o=document.createElement("script");o.src=e,o.onload=()=>{o.dataset.cafReady="1",t()},o.onerror=()=>{let s=e.match(/^(https:\/\/cdn\.jsdelivr\.net\/npm\/(?:@[^/]+\/)?[^/]+)\/.+/);s&&s[1]!==e?Ie(s[1]).then(t,()=>a(new Error(`failed to load ${e} (also tried package default ${s[1]})`))):a(new Error(`failed to load ${e}`))},document.head.appendChild(o)})}function De(e={}){let t=xt(e),a=ke(Nt(e),{shared:!!e.shared}),r=D(e.theme&&e.theme.seed)+Rt,o={};return function(){if(!_())throw new Error(`claude-artifact-framework: React not found. Hand it over once, before rendering:
29
29
 
30
30
  import React from "react";
31
31
  ArtifactKit.useReact(React);
32
- `);let[,i]=k(0),[c,f]=k(e.libs&&e.libs.length?"loading":"ready"),[l,d]=k(null);S(()=>{!e.libs||!e.libs.length||Promise.all(e.libs.map(jt)).then(()=>f("ready"),u=>{d(String(u&&u.message||u)),f("error")})},[]),S(()=>{let u=t.subscribe(()=>i(b=>b+1));return t.isHydrated()&&i(b=>b+1),u},[]);let m={React:me(),data:t.getData(),view:t.getView(),update:t.update,go:t.go,back:t.back,setStep:u=>t.setView({step:u}),files:o,viewerId:t.getViewerId(),setTab:(u,b)=>t.setView({tabs:{...t.getView().tabs,[u]:b}}),toggleCollapsed:(u,b)=>t.setView({collapsed:{...t.getView().collapsed,[u]:b}}),colors:u=>xe(e.theme&&e.theme.seed,u)},h=Tt[a];return n("div",{className:"caf-root"},n("style",{dangerouslySetInnerHTML:{__html:r}}),n("header",{className:"caf-header"},e.title?n("h1",null,e.title):null,e.subtitle?n("p",null,e.subtitle):null),c==="error"?n("div",{className:"caf-block caf-block-error"},n("strong",null,"A library failed to load"),n("code",null,l)):!t.isHydrated()||c==="loading"?n("div",{className:"caf-block caf-loading"},c==="loading"?"Loading libraries\u2026":"Loading\u2026"):n(h,{spec:e,ctx:m}))}}var Rt=`
32
+ `);let[,i]=k(0),[c,f]=k(e.libs&&e.libs.length?"loading":"ready"),[l,d]=k(null);E(()=>{!e.libs||!e.libs.length||Promise.all(e.libs.map(Ie)).then(()=>f("ready"),m=>{d(String(m&&m.message||m)),f("error")})},[]),E(()=>{let m=a.subscribe(()=>i(p=>p+1));return a.isHydrated()&&i(p=>p+1),m},[]);let u={React:pe(),data:a.getData(),view:a.getView(),update:a.update,go:a.go,back:a.back,setStep:m=>a.setView({step:m}),files:o,viewerId:a.getViewerId(),setTab:(m,p)=>a.setView({tabs:{...a.getView().tabs,[m]:p}}),toggleCollapsed:(m,p)=>a.setView({collapsed:{...a.getView().collapsed,[m]:p}}),colors:m=>Ne(e.theme&&e.theme.seed,m)},b=Ot[t];return n("div",{className:`caf-root caf-layout-${t}`},n("style",{dangerouslySetInnerHTML:{__html:r}}),n("header",{className:"caf-header"},e.title?n("h1",null,e.title):null,e.subtitle?n("p",null,e.subtitle):null),c==="error"?n("div",{className:"caf-block caf-block-error"},n("strong",null,"A library failed to load"),n("code",null,l)):!a.isHydrated()||c==="loading"?n("div",{className:"caf-block caf-loading"},c==="loading"?"Loading libraries\u2026":"Loading\u2026"):n(b,{spec:e,ctx:u}))}}var Rt=`
33
33
  .caf-root {
34
34
  --caf-radius: 10px;
35
+ --caf-control-radius: 7px; /* one radius for every control: buttons, inputs, rows */
36
+ --caf-btn-pad-y: 0.45rem;
37
+ --caf-btn-pad-x: 0.8rem;
38
+ --caf-num-primary: 2.1rem; /* the one size for a block's dominant number */
35
39
  box-sizing: border-box;
36
40
  min-height: 100vh;
37
41
  padding: 2rem 1.25rem 4rem;
@@ -42,9 +46,12 @@ Continue with this information. If you have everything you need, answer in natur
42
46
  }
43
47
  .caf-root *, .caf-root *::before, .caf-root *::after { box-sizing: inherit; }
44
48
  .caf-header { max-width: 760px; margin: 0 auto 1.5rem; }
49
+ /* One left axis per screen: the header adopts the workspace's wider container. */
50
+ .caf-layout-workspace .caf-header { max-width: 1200px; }
45
51
  .caf-header h1 { margin: 0; font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; text-wrap: balance; }
46
52
  .caf-header p { margin: 0.4rem 0 0; color: var(--caf-muted); font-size: 0.95rem; line-height: 1.5; }
47
- .caf-panel { max-width: 760px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
53
+ /* Between-card air must beat within-card padding (1.1rem), or groups dissolve. */
54
+ .caf-panel { max-width: 760px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 1.75rem 1rem; }
48
55
  .caf-slot { grid-column: span 2; min-width: 0; }
49
56
  @media (min-width: 720px) { .caf-slot { grid-column: span 1; } .caf-slot-wide { grid-column: span 2; } }
50
57
  .caf-block {
@@ -57,12 +64,14 @@ Continue with this information. If you have everything you need, answer in natur
57
64
  gap: 0.8rem;
58
65
  height: 100%;
59
66
  }
60
- .caf-block-title { margin: 0; font-size: 0.95rem; font-weight: 650; }
67
+ .caf-block-title { margin: 0; font-size: 0.78rem; font-weight: 650; text-transform: uppercase; letter-spacing: 0.06em; color: var(--caf-muted); }
61
68
  .caf-field { display: flex; flex-direction: column; gap: 0.3rem; }
62
- .caf-field label { font-size: 0.78rem; font-weight: 600; color: var(--caf-muted); letter-spacing: 0.02em; }
69
+ /* A full size+weight step below .caf-block-title \u2014 the uppercase alone was
70
+ not enough to tell "card title" from "field label" at a glance. */
71
+ .caf-field label { font-size: 0.68rem; font-weight: 500; color: var(--caf-muted); }
63
72
  .caf-field input, .caf-field select, .caf-field textarea {
64
73
  font: inherit; font-size: 0.95rem; padding: 0.5rem 0.6rem;
65
- border-radius: 7px; border: 1px solid var(--caf-border);
74
+ border-radius: var(--caf-control-radius); border: 1px solid var(--caf-border);
66
75
  background: var(--caf-sunken); color: var(--caf-text); width: 100%;
67
76
  }
68
77
  .caf-field input:focus-visible, .caf-field select:focus-visible, .caf-field textarea:focus-visible,
@@ -71,17 +80,21 @@ Continue with this information. If you have everything you need, answer in natur
71
80
  .caf-check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; }
72
81
  .caf-hint { color: var(--caf-muted); font-size: 0.75rem; }
73
82
  .caf-error { color: var(--caf-danger); font-size: 0.75rem; font-weight: 600; }
74
- .caf-output-grid { display: flex; flex-direction: column; gap: 0.7rem; }
75
- .caf-stat { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
76
- .caf-stat-label { color: var(--caf-muted); font-size: 0.82rem; }
77
- .caf-stat-value { font-size: 1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
78
- .caf-stat-big { flex-direction: column; align-items: flex-start; gap: 0.15rem; padding-bottom: 0.4rem; border-bottom: 1px solid var(--caf-border); }
79
- .caf-stat-big .caf-stat-value { font-size: 1.9rem; font-weight: 680; letter-spacing: -0.02em; color: var(--caf-accent); }
83
+ .caf-output-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 0.9rem 1.1rem; }
84
+ /* Every stat shares one axis: label above value, both flush left. */
85
+ .caf-stat { display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem; }
86
+ .caf-stat-label { color: var(--caf-muted); font-size: 0.78rem; font-weight: 600; letter-spacing: 0.02em; }
87
+ .caf-stat-value { font-size: 1.05rem; font-weight: 650; font-variant-numeric: tabular-nums; }
88
+ .caf-stat-big { grid-column: 1 / -1; }
89
+ /* The divider exists to separate the hero from stats below it \u2014 alone in the
90
+ grid it would be an orphaned rule, so it only renders when followed. */
91
+ .caf-stat-big:not(:last-child) { padding-bottom: 0.5rem; border-bottom: 1px solid var(--caf-border); }
92
+ .caf-stat-big .caf-stat-value { font-size: var(--caf-num-primary); font-weight: 700; letter-spacing: -0.02em; color: var(--caf-accent); line-height: 1.15; }
80
93
  .caf-list { padding: 0.4rem; gap: 0; }
81
94
  .caf-row {
82
95
  font: inherit; text-align: left; cursor: pointer;
83
96
  display: flex; flex-direction: column; gap: 0.15rem;
84
- padding: 0.65rem 0.7rem; border: none; border-radius: 7px;
97
+ padding: 0.65rem 0.7rem; border: none; border-radius: var(--caf-control-radius);
85
98
  background: transparent; color: inherit; width: 100%;
86
99
  }
87
100
  .caf-row:hover { background: var(--caf-sunken); }
@@ -89,12 +102,15 @@ Continue with this information. If you have everything you need, answer in natur
89
102
  .caf-row-sub { font-size: 0.78rem; color: var(--caf-muted); }
90
103
  .caf-panel-single { grid-template-columns: 1fr; }
91
104
  .caf-panel-single .caf-slot, .caf-panel-single > * { grid-column: span 1; }
92
- .caf-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.3rem 0.3rem 0.5rem; }
105
+ /* Bottom padding matches the inter-row rhythm so the toolbar doesn't sit
106
+ closer to the first row than rows sit to each other. */
107
+ .caf-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.3rem 0.3rem 0.75rem; }
93
108
  .caf-count { font-size: 0.8rem; color: var(--caf-muted); font-variant-numeric: tabular-nums; }
94
109
  .caf-btn {
95
110
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
96
- padding: 0.45rem 0.8rem; border-radius: 7px;
97
- border: 1px solid var(--caf-border); background: var(--caf-sunken); color: var(--caf-text);
111
+ padding: var(--caf-btn-pad-y) var(--caf-btn-pad-x); border-radius: var(--caf-control-radius);
112
+ border: 1px solid var(--caf-border); background: var(--caf-surface); color: var(--caf-text);
113
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
98
114
  }
99
115
  .caf-btn:hover { filter: brightness(0.97); }
100
116
  .caf-btn:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
@@ -113,16 +129,19 @@ Continue with this information. If you have everything you need, answer in natur
113
129
  .caf-line-meta { display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; }
114
130
  .caf-line-last { font-weight: 650; font-variant-numeric: tabular-nums; color: var(--caf-accent); }
115
131
  .caf-donut { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }
116
- .caf-donut-svg { width: 110px; height: 110px; flex: none; transform: rotate(0.001deg); }
132
+ /* -3px optical correction: a circle beside flush-left text reads indented. */
133
+ .caf-donut-svg { width: 110px; height: 110px; flex: none; transform: rotate(0.001deg); margin-left: -3px; }
117
134
  .caf-donut-seg { fill: none; stroke-width: 6; }
118
- .caf-donut-legend { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; flex: 1; }
135
+ /* Capped width keeps each value NEXT TO its label in wide cards \u2014 the pair
136
+ must read as a pair regardless of container width. */
137
+ .caf-donut-legend { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; flex: 1; max-width: 260px; }
119
138
  .caf-legend-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.84rem; }
120
139
  .caf-legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
121
140
  .caf-legend-label { color: var(--caf-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
122
141
  .caf-legend-value { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
123
142
  .caf-timer { align-items: center; text-align: center; }
124
143
  .caf-timer .caf-bar-track { width: 100%; }
125
- .caf-timer-time { font-size: 2.6rem; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
144
+ .caf-timer-time { font-size: var(--caf-num-primary); font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; color: var(--caf-accent); }
126
145
  .caf-timer-done { color: var(--caf-accent); }
127
146
  .caf-timer-fill { transition: width 0.9s linear; }
128
147
  .caf-timer-controls { display: flex; gap: 0.6rem; }
@@ -139,8 +158,11 @@ Continue with this information. If you have everything you need, answer in natur
139
158
  .caf-msg-tools { align-self: flex-start; font-size: 0.74rem; color: var(--caf-muted); padding: 0.15rem 0.55rem; border: 1px solid var(--caf-border); border-radius: 999px; }
140
159
  .caf-msg-error { align-self: stretch; max-width: none; display: flex; flex-direction: column; gap: 0.2rem; background: transparent; border: 1px solid var(--caf-danger); }
141
160
  .caf-msg-error strong { color: var(--caf-danger); font-size: 0.85rem; }
142
- .caf-chat-input { display: flex; gap: 0.6rem; margin-top: 0.8rem; }
143
- .caf-chat-input input { flex: 1; font: inherit; font-size: 0.95rem; padding: 0.55rem 0.7rem; border-radius: 8px; border: 1px solid var(--caf-border); background: var(--caf-surface); color: var(--caf-text); }
161
+ .caf-chat-input {
162
+ display: flex; gap: 0.6rem; margin-top: 1rem; padding: 0.6rem;
163
+ background: var(--caf-surface); border: 1px solid var(--caf-border); border-radius: var(--caf-radius);
164
+ }
165
+ .caf-chat-input input { flex: 1; font: inherit; font-size: 0.95rem; padding: 0.55rem 0.7rem; border-radius: var(--caf-control-radius); border: 1px solid var(--caf-border); background: var(--caf-sunken); color: var(--caf-text); }
144
166
  .caf-chat-input input:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
145
167
  .caf-search {
146
168
  font: inherit; font-size: 0.9rem; width: 100%;
@@ -154,7 +176,7 @@ Continue with this information. If you have everything you need, answer in natur
154
176
  .caf-row-wrap { display: flex; align-items: center; gap: 0.4rem; }
155
177
  .caf-row-wrap .caf-row { flex: 1; min-width: 0; }
156
178
  .caf-row-actions { display: flex; gap: 0.35rem; flex: none; padding-right: 0.3rem; }
157
- .caf-btn-sm { font-size: 0.78rem; padding: 0.3rem 0.6rem; border-radius: 6px; }
179
+ .caf-btn-sm { font-size: 0.78rem; padding: calc(var(--caf-btn-pad-y) * 0.67) calc(var(--caf-btn-pad-x) * 0.75); }
158
180
  .caf-items { display: flex; flex-direction: column; gap: 0.5rem; border-top: 1px solid var(--caf-border); padding-top: 0.7rem; }
159
181
  .caf-item-row { display: flex; align-items: flex-end; gap: 0.5rem; }
160
182
  .caf-item-row .caf-field { flex: 1; min-width: 0; }
@@ -186,22 +208,29 @@ Continue with this information. If you have everything you need, answer in natur
186
208
  }
187
209
  .caf-tab:hover { color: var(--caf-text); }
188
210
  .caf-tab:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: -2px; }
189
- .caf-tab-active { color: var(--caf-accent); border-bottom-color: var(--caf-accent); }
211
+ /* :hover on the active tab must not win the specificity race and mute it. */
212
+ .caf-tab-active, .caf-tab-active:hover { color: var(--caf-accent); border-bottom-color: var(--caf-accent); }
190
213
  .caf-tabs-body { display: flex; flex-direction: column; gap: 0.8rem; }
191
214
  .caf-collapse { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
192
215
  .caf-collapse-head {
193
- font: inherit; font-size: 0.95rem; font-weight: 650; cursor: pointer;
216
+ /* Same treatment as .caf-block-title: a collapsible header IS a card title. */
217
+ font: inherit; font-size: 0.78rem; font-weight: 650; text-transform: uppercase;
218
+ letter-spacing: 0.06em; color: var(--caf-muted); cursor: pointer;
194
219
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
195
- padding: 0.7rem 1rem; border: 1px solid var(--caf-border); border-radius: var(--caf-radius);
196
- background: var(--caf-surface); color: var(--caf-text); width: 100%; text-align: left;
220
+ padding: 0.7rem 1.1rem; border: 1px solid var(--caf-border); border-radius: var(--caf-radius);
221
+ background: var(--caf-surface); width: 100%; text-align: left;
197
222
  }
223
+ .caf-collapse-head { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
224
+ .caf-collapse-head:hover { filter: brightness(0.97); }
198
225
  .caf-collapse-head:focus-visible { outline: 2px solid var(--caf-accent); outline-offset: 1px; }
199
- .caf-chevron { transition: transform 0.15s ease; color: var(--caf-muted); }
226
+ /* Accent chevron: the one interaction cue that distinguishes a collapsible
227
+ header from a static card title without breaking their shared typography. */
228
+ .caf-chevron { transition: transform 0.15s ease; color: var(--caf-accent); }
200
229
  .caf-chevron-closed { transform: rotate(-90deg); }
201
230
  .caf-block-fill { border: none; background: transparent; padding: 0; overflow: auto; min-height: 320px; }
202
231
  .caf-empty, .caf-loading { color: var(--caf-muted); font-size: 0.9rem; text-align: center; padding: 1.6rem 1rem; }
203
232
  .caf-block-error { border-color: var(--caf-danger); gap: 0.4rem; }
204
233
  .caf-block-error strong { font-size: 0.9rem; color: var(--caf-danger); }
205
234
  .caf-block-error code { font-size: 0.78rem; color: var(--caf-muted); word-break: break-word; }
206
- `;return Ke(Ot);})();
235
+ `;return Je(Lt);})();
207
236
  //# sourceMappingURL=index.global.js.map