studiograph 1.3.48-next.261 → 1.3.48-next.263
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/prompts/system.md +2 -2
- package/dist/agent/skills/artifact-canvas/skill.md +25 -37
- package/dist/agent/skills/paged-documents/skill.md +74 -104
- package/dist/agent/tools/artifact-tools.js +1 -1
- package/dist/agent/tools/artifact-tools.js.map +1 -1
- package/dist/core/artifact-columns-css.d.ts +38 -0
- package/dist/core/artifact-columns-css.js +157 -0
- package/dist/core/artifact-columns-css.js.map +1 -0
- package/dist/core/artifact-frame-document.d.ts +57 -15
- package/dist/core/artifact-frame-document.js +396 -356
- package/dist/core/artifact-frame-document.js.map +1 -1
- package/dist/core/artifact-frame-model.d.ts +42 -1
- package/dist/core/artifact-frame-model.js +102 -1
- package/dist/core/artifact-frame-model.js.map +1 -1
- package/dist/mcp/tools.js +8 -8
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/routes/artifact-export-api.js +2 -3
- package/dist/server/routes/artifact-export-api.js.map +1 -1
- package/dist/server/routes/chat-turn-outcome.d.ts +36 -0
- package/dist/server/routes/chat-turn-outcome.js +17 -0
- package/dist/server/routes/chat-turn-outcome.js.map +1 -0
- package/dist/services/artifact-library-sources.d.ts +1 -6
- package/dist/services/artifact-library-sources.js +1 -9
- package/dist/services/artifact-library-sources.js.map +1 -1
- package/dist/services/artifact-render-export.d.ts +3 -3
- package/dist/services/artifact-render-export.js +57 -50
- package/dist/services/artifact-render-export.js.map +1 -1
- package/dist/web/_app/immutable/chunks/{Cg7m1gqN.js → 1Av0cjjM.js} +1 -1
- package/dist/web/_app/immutable/chunks/7C_XQ_V22.js +949 -0
- package/dist/web/_app/immutable/chunks/{Bpmx7Umc.js → 7dxFJmtT.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CR1JY_cb.js → B3TQ2v3O.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CZBW5wi82.js → BKJo_vcH2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{Cx5IiiDO2.js → BLjaRsry2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{snCOoD78.js → BWM7Fyds.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CQl_RUVN2.js → BZrDj1Yc2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{D0_Iu3Uj.js → B_EIjYsb.js} +1 -1
- package/dist/web/_app/immutable/chunks/{DaB0hU8_.js → BaVciYXp.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CQW66fYJ.js → BkWTUZUm.js} +1 -1
- package/dist/web/_app/immutable/chunks/{BU5TCj7m.js → BzEpkiVx.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CkivrILi.js → CFQ_EH_P.js} +1 -1
- package/dist/web/_app/immutable/chunks/CL_APTyv.js +1 -0
- package/dist/web/_app/immutable/chunks/{2z2ekE6D2.js → COK5qG3L2.js} +2 -2
- package/dist/web/_app/immutable/chunks/{BIeOkmiV.js → CRwWneZ-.js} +1 -1
- package/dist/web/_app/immutable/chunks/{1QRy7-wo.js → CW2H4JII.js} +1 -1
- package/dist/web/_app/immutable/chunks/{pPsy4008.js → CWeviCpk.js} +1 -1
- package/dist/web/_app/immutable/chunks/{DMFH9Cnt2.js → CXOqnNsj2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{oIZupUnz.js → CX_WuP2f.js} +1 -1
- package/dist/web/_app/immutable/chunks/{BIwe25Lk.js → CY5xLE5F.js} +1 -1
- package/dist/web/_app/immutable/chunks/{D-vvXTU3.js → CeUT6lMf.js} +2 -2
- package/dist/web/_app/immutable/chunks/{B5UH1FNe.js → CgmH6rPv.js} +3 -3
- package/dist/web/_app/immutable/chunks/{-Tbr-96c2.js → CkOWeGhc2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{K5YHt1WL2.js → CkPu5VTd2.js} +1 -1
- package/dist/web/_app/immutable/chunks/ClSRVrsW.js +1 -0
- package/dist/web/_app/immutable/chunks/{CcgYvk_3.js → Cmq7bKUh.js} +1 -1
- package/dist/web/_app/immutable/chunks/{F5xZdLlB.js → CnR_G-ce.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CuYL65Bn.js → CzSx91mJ.js} +1 -1
- package/dist/web/_app/immutable/chunks/D-a94Hdg.js +1 -0
- package/dist/web/_app/immutable/chunks/DAcMjPms.js +2 -0
- package/dist/web/_app/immutable/chunks/{B06uE1qJ.js → DC2fTKy0.js} +1 -1
- package/dist/web/_app/immutable/chunks/{atFSAfcd2.js → DDfqLzbz2.js} +2 -2
- package/dist/web/_app/immutable/chunks/{DhD1HF7R.js → DFLuHkej.js} +1 -1
- package/dist/web/_app/immutable/chunks/{PwUOTfSv.js → DOZR4-gy.js} +1 -1
- package/dist/web/_app/immutable/chunks/DO_V9Cgc.js +1 -0
- package/dist/web/_app/immutable/chunks/{Cxdio_Al.js → DPI7dnke.js} +3 -3
- package/dist/web/_app/immutable/chunks/{CG8YKaqc.js → DVcmIzo2.js} +1 -1
- package/dist/web/_app/immutable/chunks/DZ2Zr5zb.js +1 -0
- package/dist/web/_app/immutable/chunks/{ChS3kWO-.js → DiGsqyRs.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CKwV6HKc.js → DmzyKw-k.js} +1 -1
- package/dist/web/_app/immutable/chunks/Dvj33Rn2.js +1 -0
- package/dist/web/_app/immutable/chunks/{B9VQbssY.js → MDb5bFUr.js} +1 -1
- package/dist/web/_app/immutable/chunks/mYfi0ijf2.js +66 -0
- package/dist/web/_app/immutable/chunks/{CuatNdzp.js → nkOOikT2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{CLninaDG2.js → qU6V8dVT2.js} +2 -2
- package/dist/web/_app/immutable/chunks/{DtXJCaQc2.js → qtwjrlYo2.js} +1 -1
- package/dist/web/_app/immutable/chunks/{B3u4QMoU.js → vR5HiNz9.js} +1 -1
- package/dist/web/_app/immutable/chunks/{7l950wkn.js → xhwwouQZ.js} +1 -1
- package/dist/web/_app/immutable/chunks/{BBrP9GiZ.js → yKBXs2Vl.js} +1 -1
- package/dist/web/_app/immutable/chunks/{sUAtda6y2.js → zMLQbXeR2.js} +1 -1
- package/dist/web/_app/immutable/entry/{app.1tcNTKI-.js → app.CRvuxoVJ.js} +2 -2
- package/dist/web/_app/immutable/entry/start.CRSlQSAo.js +1 -0
- package/dist/web/_app/immutable/nodes/{0.v0W5DL7W.js → 0.DCtO9hJz.js} +2 -2
- package/dist/web/_app/immutable/nodes/{1.81Rb3Ith.js → 1.CU0Xk0hX.js} +1 -1
- package/dist/web/_app/immutable/nodes/{10.CAlZNFOq.js → 10.BQ_I0U3h.js} +1 -1
- package/dist/web/_app/immutable/nodes/{11.CCfUginI.js → 11.D8W7J9oj.js} +1 -1
- package/dist/web/_app/immutable/nodes/{12.BJLboAyk.js → 12.shu8hSiJ.js} +1 -1
- package/dist/web/_app/immutable/nodes/{13.Cz4UTl2G.js → 13.CqSie9pj.js} +1 -1
- package/dist/web/_app/immutable/nodes/15.CRTNtmaK.js +1 -0
- package/dist/web/_app/immutable/nodes/{16.BjohAUt9.js → 16.CLnfWtVJ.js} +1 -1
- package/dist/web/_app/immutable/nodes/{18.DsOT0tDo.js → 18.L6u3xca6.js} +1 -1
- package/dist/web/_app/immutable/nodes/{19.BiJWLOUT.js → 19.BfT4fpP2.js} +1 -1
- package/dist/web/_app/immutable/nodes/{2.Cd72nG2V.js → 2.Cywkr3cW.js} +4 -4
- package/dist/web/_app/immutable/nodes/{3.BIT9mm9r.js → 3.C5-yIMEM.js} +1 -1
- package/dist/web/_app/immutable/nodes/{4.Cn7r0Poe.js → 4.LWwxRkzM.js} +3 -3
- package/dist/web/_app/immutable/nodes/{5.CkJNdCZG.js → 5.CwRllvWS.js} +1 -1
- package/dist/web/_app/immutable/nodes/{6.1rbIRQgQ.js → 6.BcR9vQIF.js} +1 -1
- package/dist/web/_app/immutable/nodes/{7.w17Zl36i.js → 7.Bm0Ie3c3.js} +1 -1
- package/dist/web/_app/immutable/nodes/{8.DqTsYuU-.js → 8.Dj0JJcTw.js} +1 -1
- package/dist/web/_app/immutable/nodes/{9.BJhYZPfc.js → 9.9MiRRKIu.js} +1 -1
- package/dist/web/_app/version.json +1 -1
- package/dist/web/index.html +14 -14
- package/package.json +1 -2
- package/dist/web/_app/immutable/chunks/9Sn2PwSn2.js +0 -1025
- package/dist/web/_app/immutable/chunks/AFZSy-Vk.js +0 -2
- package/dist/web/_app/immutable/chunks/B4PrlkmE.js +0 -1
- package/dist/web/_app/immutable/chunks/C85NG5lS.js +0 -1
- package/dist/web/_app/immutable/chunks/CJbr-v9X.js +0 -1
- package/dist/web/_app/immutable/chunks/D4vfNy_f.js +0 -1
- package/dist/web/_app/immutable/chunks/DG7uGoZb2.js +0 -58
- package/dist/web/_app/immutable/chunks/DTOO9nUj.js +0 -1
- package/dist/web/_app/immutable/chunks/Dav8Lgyy2.js +0 -5
- package/dist/web/_app/immutable/chunks/DjXtgWTP.js +0 -1
- package/dist/web/_app/immutable/entry/start.BJMsySI1.js +0 -1
- package/dist/web/_app/immutable/nodes/15.D2mNE6C-.js +0 -1
- /package/dist/web/_app/immutable/chunks/{Oglnp7sm.js → Oglnp7sm2.js} +0 -0
|
@@ -0,0 +1,949 @@
|
|
|
1
|
+
import{B as e,Ft as t,G as n,Ht as r,I as i,J as a,K as o,P as s,Pt as c,R as l,S as u,T as d,V as f,Vt as p,W as m,X as h,Z as g,_,a as v,at as y,ct as b,d as ee,et as te,ft as ne,g as re,gt as x,ht as S,j as ie,mt as ae,n as oe,o as C,ot as w,p as se,pt as T,st as E,u as ce,v as D,vt as O,wt as k,x as le,xt as A,yt as j,z as ue}from"./FISIvbqq.js";import{t as M}from"./kNaey6uv.js";import"./xihTtKlq.js";import{R as de,o as fe,z as pe}from"./nqo2e2Yv.js";import{t as me}from"./BWM7Fyds.js";import{n as he}from"./BEyPhM3C.js";import{t as ge}from"./CgOgBK5j.js";import"./CWIHttTH.js";import{n as N,r as _e,t as P}from"./DAcMjPms.js";import{t as ve}from"./DIsSxB_C.js";import{i as ye,n as be,r as xe,t as Se}from"./DPLkAijI2.js";var Ce=f(`<title> </title>`),we=f(`<svg><!><path d="M27.34,12.06l-22-8A1,1,0,0,0,4.06,5.34l8,22A1,1,0,0,0,13,28h0a1,1,0,0,0,.93-.63l3.84-9.6,9.6-3.84a1,1,0,0,0,0-1.87Zm-10.71,4h0l-.4.16-.16.4h0L13,24.2,6.67,6.67,24.2,13Z"></path></svg>`);function Te(e,n){let a=v(n,[`children`,`$$slots`,`$$events`,`$$legacy`]),o=v(a,[`size`,`title`]);t(n,!1);let u=O(),d=O(),f=C(n,`size`,8,16),m=C(n,`title`,8,void 0);y(()=>(h(a),h(m())),()=>{j(u,a[`aria-label`]||a[`aria-labelledby`]||m())}),y(()=>(g(u),h(a)),()=>{j(d,{"aria-hidden":g(u)?void 0:!0,role:g(u)?`img`:void 0,focusable:Number(a.tabindex)===0?!0:void 0})}),w(),ce();var _=we();re(_,()=>({xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 32 32`,fill:`currentColor`,preserveAspectRatio:`xMidYMid meet`,width:f(),height:f(),...g(d),...o}));var b=T(_),ee=e=>{var t=Ce(),n=T(t,!0);r(t),E(()=>i(n,m())),l(e,t)};s(b,e=>{m()&&e(ee)}),p(),r(_),l(e,_),c()}var Ee=f(`<title> </title>`),De=f(`<svg><!><path d="M27.01 12 25.6 13.41 28.18 16 25.59 18.59 27.01 20 31.01 16 27.01 12z"></path><path d="M6.41 13.42 5 12 1 16 5 20 6.42 18.59 3.83 16 6.41 13.42z"></path><path d="M16 28.17 13.41 25.58 12 27 16 31 20 27 18.59 25.59 16 28.17z"></path><path d="M16 3.83 18.58 6.41 20 5 16 1 12 5 13.41 6.42 16 3.83z"></path><path d="M22,16a6,6,0,1,0-2.53,4.89l3.82,3.82,1.42-1.42-3.82-3.82A6,6,0,0,0,22,16Zm-6,4a4,4,0,1,1,4-4A4,4,0,0,1,16,20Z"></path></svg>`);function Oe(e,n){let a=v(n,[`children`,`$$slots`,`$$events`,`$$legacy`]),o=v(a,[`size`,`title`]);t(n,!1);let u=O(),d=O(),f=C(n,`size`,8,16),m=C(n,`title`,8,void 0);y(()=>(h(a),h(m())),()=>{j(u,a[`aria-label`]||a[`aria-labelledby`]||m())}),y(()=>(g(u),h(a)),()=>{j(d,{"aria-hidden":g(u)?void 0:!0,role:g(u)?`img`:void 0,focusable:Number(a.tabindex)===0?!0:void 0})}),w(),ce();var _=De();re(_,()=>({xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 32 32`,fill:`currentColor`,preserveAspectRatio:`xMidYMid meet`,width:f(),height:f(),...g(d),...o}));var b=T(_),ee=e=>{var t=Ee(),n=T(t,!0);r(t),E(()=>i(n,m())),l(e,t)};s(b,e=>{m()&&e(ee)}),p(5),r(_),l(e,_),c()}var ke=f(`<title> </title>`),F=f(`<svg><!><path d="M18,28A12,12,0,1,0,6,16v6.2L2.4,18.6,1,20l6,6,6-6-1.4-1.4L8,22.2V16H8A10,10,0,1,1,18,26Z"></path></svg>`);function Ae(e,n){let a=v(n,[`children`,`$$slots`,`$$events`,`$$legacy`]),o=v(a,[`size`,`title`]);t(n,!1);let u=O(),d=O(),f=C(n,`size`,8,16),m=C(n,`title`,8,void 0);y(()=>(h(a),h(m())),()=>{j(u,a[`aria-label`]||a[`aria-labelledby`]||m())}),y(()=>(g(u),h(a)),()=>{j(d,{"aria-hidden":g(u)?void 0:!0,role:g(u)?`img`:void 0,focusable:Number(a.tabindex)===0?!0:void 0})}),w(),ce();var _=F();re(_,()=>({xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 32 32`,fill:`currentColor`,preserveAspectRatio:`xMidYMid meet`,width:f(),height:f(),...g(d),...o}));var b=T(_),ee=e=>{var t=ke(),n=T(t,!0);r(t),E(()=>i(n,m())),l(e,t)};s(b,e=>{m()&&e(ee)}),p(),r(_),l(e,_),c()}var je=f(`<title> </title>`),I=f(`<svg><!><path d="M18 12 14 12 14 8 12 8 12 12 8 12 8 14 12 14 12 18 14 18 14 14 18 14 18 12z"></path><path d="M21.4479,20A10.856,10.856,0,0,0,24,13,11,11,0,1,0,13,24a10.856,10.856,0,0,0,7-2.5521L27.5859,29,29,27.5859ZM13,22a9,9,0,1,1,9-9A9.01,9.01,0,0,1,13,22Z"></path></svg>`);function Me(e,n){let a=v(n,[`children`,`$$slots`,`$$events`,`$$legacy`]),o=v(a,[`size`,`title`]);t(n,!1);let u=O(),d=O(),f=C(n,`size`,8,16),m=C(n,`title`,8,void 0);y(()=>(h(a),h(m())),()=>{j(u,a[`aria-label`]||a[`aria-labelledby`]||m())}),y(()=>(g(u),h(a)),()=>{j(d,{"aria-hidden":g(u)?void 0:!0,role:g(u)?`img`:void 0,focusable:Number(a.tabindex)===0?!0:void 0})}),w(),ce();var _=I();re(_,()=>({xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 32 32`,fill:`currentColor`,preserveAspectRatio:`xMidYMid meet`,width:f(),height:f(),...g(d),...o}));var b=T(_),ee=e=>{var t=je(),n=T(t,!0);r(t),E(()=>i(n,m())),l(e,t)};s(b,e=>{m()&&e(ee)}),p(2),r(_),l(e,_),c()}var L=f(`<title> </title>`),R=f(`<svg><!><path d="M8 12H18V14H8z"></path><path d="M21.4479,20A10.856,10.856,0,0,0,24,13,11,11,0,1,0,13,24a10.856,10.856,0,0,0,7-2.5521L27.5859,29,29,27.5859ZM13,22a9,9,0,1,1,9-9A9.01,9.01,0,0,1,13,22Z"></path></svg>`);function Ne(e,n){let a=v(n,[`children`,`$$slots`,`$$events`,`$$legacy`]),o=v(a,[`size`,`title`]);t(n,!1);let u=O(),d=O(),f=C(n,`size`,8,16),m=C(n,`title`,8,void 0);y(()=>(h(a),h(m())),()=>{j(u,a[`aria-label`]||a[`aria-labelledby`]||m())}),y(()=>(g(u),h(a)),()=>{j(d,{"aria-hidden":g(u)?void 0:!0,role:g(u)?`img`:void 0,focusable:Number(a.tabindex)===0?!0:void 0})}),w(),ce();var _=R();re(_,()=>({xmlns:`http://www.w3.org/2000/svg`,viewBox:`0 0 32 32`,fill:`currentColor`,preserveAspectRatio:`xMidYMid meet`,width:f(),height:f(),...g(d),...o}));var b=T(_),ee=e=>{var t=L(),n=T(t,!0);r(t),E(()=>i(n,m())),l(e,t)};s(b,e=>{m()&&e(ee)}),p(2),r(_),l(e,_),c()}var z=6,Pe=720,Fe=1280,Ie=800;function Le(e,t){return e.geometry.width===`fill`?Math.round(t?.width||Fe):e.geometry.width}function Re(e,t,n=Pe,r){if(e.geometry.height===`fill`)return Math.round(r?.height||Ie);if(e.geometry.height!==`auto`)return e.geometry.height;let i=t?.[e.id];return i&&i>0?Math.round(i):n}function ze(e,t={}){let n=t.gap??64,r=Math.max(1,t.maxColumns??z),i=e.length;if(i===0)return{rects:[],width:0,height:0,columns:0};let a=Math.min(r,Math.max(1,Math.ceil(Math.sqrt(i)))),o=Math.ceil(i/a),s=e.map(e=>Le(e,t.viewport)),c=e.map(e=>Re(e,t.measuredHeights,t.autoHeightFallback,t.viewport)),l=Array(a).fill(0),u=Array(o).fill(0);for(let e=0;e<i;e+=1){let t=e%a,n=Math.floor(e/a);l[t]=Math.max(l[t],s[e]),u[n]=Math.max(u[n],c[e])}let d=Array(a).fill(0);for(let e=1;e<a;e+=1)d[e]=d[e-1]+l[e-1]+n;let f=Array(o).fill(0);for(let e=1;e<o;e+=1)f[e]=f[e-1]+u[e-1]+n;let p=e.map((e,t)=>{let n=t%a,r=Math.floor(t/a),i=s[t],o=c[t],l=d[n],u=f[r];return{id:e.id,x:Math.round(l),y:Math.round(u),width:i,height:o}}),m=d[a-1]+l[a-1],h=f[o-1]+u[o-1];return{rects:p,width:Math.round(m),height:Math.round(h),columns:a}}function Be(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`)}function B(e){return Be(e).replace(/'/g,`'`)}function Ve(e){return e.replace(/<\/script/gi,`<\\/script`)}function He(e){return e.replace(/<\/style/gi,`<\\/style`)}function Ue(e){let t=new TextEncoder().encode(e),n=``,r=32768;for(let e=0;e<t.length;e+=r)n+=String.fromCharCode(...t.slice(e,e+r));return btoa(n)}var V=/(https?:\/\/[^\s"'()<>\/]+)?\/api\/assets\/([A-Za-z0-9._%-]+)\/([A-Za-z0-9._%-]+)(?![A-Za-z0-9._%/-])(\?[^\s"'()<>]*)?/g;function H(e){try{return decodeURIComponent(e)}catch{return e}}function We(e){return encodeURIComponent(e).replace(/[!~*'()]/g,e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`)}function Ge(e){let t=new Map;for(let n of e.matchAll(V)){let e=n[2],r=H(n[3]),i=`${e}/${r}`;t.has(i)||t.set(i,{key:i,assetId:e,filename:r})}return[...t.values()]}function Ke(e,t){let n=encodeURIComponent(t);return e.replace(V,(e,t,r,i,a)=>{let o=`${t??``}/api/assets/${r}/${i}`,s=a?a.slice(1).split(`&`).filter(e=>e&&!/^at=/i.test(e)):[];return s.push(`at=${n}`),`${o}?${s.join(`&`)}`})}function qe(e,t){return e.replace(V,(e,n,r,i)=>{let a=H(i);return t({key:`${r}/${a}`,assetId:r,filename:a},i)??e})}function Je(e,t){return e.replace(V,(e,n,r,i)=>`/api/share/${t}/asset/${r}/${i}`)}function Ye(e){return e.replace(/[&<>"']/g,e=>e===`&`?`&`:e===`<`?`<`:e===`>`?`>`:e===`"`?`"`:`'`)}function Xe(e){return`data:image/svg+xml,${We(`<svg xmlns="http://www.w3.org/2000/svg" width="640" height="360" viewBox="0 0 640 360"><rect width="640" height="360" fill="#f4f4f4"/><rect x="0.5" y="0.5" width="639" height="359" fill="none" stroke="#d0d0d0"/><g fill="#8a8a8a" font-family="system-ui, -apple-system, sans-serif" text-anchor="middle"><text x="320" y="168" font-size="15">Image not included in export</text><text x="320" y="196" font-size="13">${Ye(e.length>48?`${e.slice(0,45)}…`:e)}</text></g></svg>`)}`}function Ze(e,t=`./assets`,n={}){let r=t.replace(/\/+$/,``);return e.replace(V,(e,t,i,a)=>{let o=H(a);return!n.bundledKeys||n.bundledKeys.has(`${i}/${o}`)?`${r}/${i}/${a}`:Xe(o)})}function Qe(e){try{let t=new URL(e);return t.protocol!==`http:`&&t.protocol!==`https:`?null:t.origin}catch{return null}}var U=/^[A-Za-z0-9._-]+$/;function $e(e){return e.length>0&&U.test(e)}function et(e){switch(e.mode){case`token`:{let t=Qe(e.origin);return t?[`${t}/api/assets/`]:[]}case`share`:{let t=Qe(e.origin);return!t||!$e(e.shareToken)?[]:[`${t}/api/share/${e.shareToken}/asset/`]}case`relative`:return[`file:`];case`none`:return[]}}function tt(e={mode:`none`},t={}){let n=et(e),r=e=>n.length?`${e} ${n.join(` `)}`:e,i=t.allowBaseOrigin?Qe(t.allowBaseOrigin):null;return[`default-src 'none'`,i?`base-uri ${i}`:`base-uri 'none'`,`connect-src 'none'`,r(`font-src data: blob:`),`form-action 'none'`,`frame-src 'none'`,r(`img-src data: blob:`),r(`media-src data: blob:`),`object-src 'none'`,`script-src 'unsafe-inline' blob:`,`style-src 'unsafe-inline'`].join(`; `)}function nt(e,t={mode:`none`}){switch(t.mode){case`token`:return t.token?Ke(e,t.token):e;case`share`:return $e(t.shareToken)?Je(e,t.shareToken):e;case`relative`:return Ze(e,`./assets`,{bundledKeys:t.bundledKeys});case`none`:return e}}function rt(e,t={}){if(e.length===0)return``;let n=[];for(let r of e)if(r===`d3`||r===`motion`){let e=t[r];if(!e)continue;n.push(`<script data-artifact-library="${r}">\n${Ve(e)}\n<\/script>`)}let r=[];return e.includes(`three`)&&t.three&&r.push(`
|
|
2
|
+
const decodeLibrarySource = (base64) => {
|
|
3
|
+
const binary = atob(base64);
|
|
4
|
+
const bytes = new Uint8Array(binary.length);
|
|
5
|
+
for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
6
|
+
return new TextDecoder().decode(bytes);
|
|
7
|
+
};
|
|
8
|
+
const threeSource = decodeLibrarySource(${JSON.stringify(Ue(t.three))});
|
|
9
|
+
const threeCoreSource = ${t.threeCore?`decodeLibrarySource(${JSON.stringify(Ue(t.threeCore))})`:`''`};
|
|
10
|
+
const threeCoreUrl = threeCoreSource
|
|
11
|
+
? URL.createObjectURL(new Blob([threeCoreSource], { type: 'text/javascript' }))
|
|
12
|
+
: null;
|
|
13
|
+
const threeModuleSource = threeCoreUrl
|
|
14
|
+
? threeSource.replace(/from\\s*(['"])\\.\\/three\\.core\\.min\\.js\\1/g, 'from ' + JSON.stringify(threeCoreUrl))
|
|
15
|
+
: threeSource;
|
|
16
|
+
const threeUrl = URL.createObjectURL(new Blob([threeModuleSource], { type: 'text/javascript' }));
|
|
17
|
+
try {
|
|
18
|
+
window.THREE = await import(threeUrl);
|
|
19
|
+
} finally {
|
|
20
|
+
URL.revokeObjectURL(threeUrl);
|
|
21
|
+
if (threeCoreUrl) URL.revokeObjectURL(threeCoreUrl);
|
|
22
|
+
}
|
|
23
|
+
`),n.push(`<script data-artifact-libraries-ready>
|
|
24
|
+
window.__STUDIOGRAPH_ARTIFACT_LIBRARIES__ = ${JSON.stringify(e)};
|
|
25
|
+
window.__STUDIOGRAPH_ARTIFACT_LIBRARIES_READY__ = (async () => {
|
|
26
|
+
${r.join(`
|
|
27
|
+
`)}
|
|
28
|
+
return true;
|
|
29
|
+
})().catch((error) => {
|
|
30
|
+
console.error('Artifact library load failed', error);
|
|
31
|
+
throw error;
|
|
32
|
+
});
|
|
33
|
+
<\/script>`),n.join(`
|
|
34
|
+
`)}function it(){return`<script data-artifact-broken-image>${Ve(`
|
|
35
|
+
(() => {
|
|
36
|
+
var MESSAGE = 'Original asset is no longer available';
|
|
37
|
+
var GLYPH = [
|
|
38
|
+
'M16,30H8a2,2,0,0,1-2-2V4A2,2,0,0,1,8,2h10a1,1,0,0,1,.71.29l5,5A1,1,0,0,1,24,8v6H22V9H17a1,1,0,0,1-1-1V4H8V28h8Z',
|
|
39
|
+
'M24.5,29A2.5,2.5,0,1,1,27,26.5,2.5,2.5,0,0,1,24.5,29Zm0-3.5a1,1,0,1,0,1,1A1,1,0,0,0,24.5,25.5Z',
|
|
40
|
+
'M24.5,23a1,1,0,0,1-1-1V21a2.5,2.5,0,1,0-2.5-2.5,1,1,0,0,1-2,0A4.5,4.5,0,1,1,25,22.79V22A1,1,0,0,1,24.5,23Z'
|
|
41
|
+
];
|
|
42
|
+
var NS = 'http://www.w3.org/2000/svg';
|
|
43
|
+
function replace(img) {
|
|
44
|
+
try {
|
|
45
|
+
if (!img || img.tagName !== 'IMG' || img.hasAttribute('data-sg-broken')) return;
|
|
46
|
+
if (img.complete && img.naturalWidth > 0) return; // recovered (e.g. a retry swapped src)
|
|
47
|
+
img.setAttribute('data-sg-broken', '');
|
|
48
|
+
var cs = window.getComputedStyle ? getComputedStyle(img) : null;
|
|
49
|
+
var rect = img.getBoundingClientRect();
|
|
50
|
+
// getComputedStyle returns a USED px length ("695px") only for a laid-out
|
|
51
|
+
// element. Inside a display:none subtree — an INACTIVE FRAME in present /
|
|
52
|
+
// fullscreen mode — it returns the COMPUTED value verbatim ("100%"),
|
|
53
|
+
// which is not a pixel box; parseFloat("100%") === 100 would bake a bogus
|
|
54
|
+
// 100x100 footprint (the small glyph-only box seen in present mode). So
|
|
55
|
+
// accept a computed length ONLY when it is in px; it still dodges the
|
|
56
|
+
// collapsed broken-img rendered box and the "numeric width attr that CSS
|
|
57
|
+
// overrides" trap. Then a unitless pixel attribute, the rendered box, a
|
|
58
|
+
// default. A percentage means the image fills its slot — mirrored below.
|
|
59
|
+
var pxLen = function (cssVal) {
|
|
60
|
+
if (typeof cssVal === 'string' && /px$/.test(cssVal)) {
|
|
61
|
+
var c = parseFloat(cssVal);
|
|
62
|
+
if (isFinite(c) && c > 1) return Math.round(c);
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
};
|
|
66
|
+
var dim = function (cssVal, attr, rectVal, dflt) {
|
|
67
|
+
var c = pxLen(cssVal);
|
|
68
|
+
if (c != null) return c;
|
|
69
|
+
if (attr && /^\\s*\\d+(?:\\.\\d+)?\\s*$/.test(attr)) return parseFloat(attr);
|
|
70
|
+
if (rectVal > 1) return Math.round(rectVal);
|
|
71
|
+
return dflt;
|
|
72
|
+
};
|
|
73
|
+
var w = dim(cs && cs.width, img.getAttribute('width'), rect.width, 240);
|
|
74
|
+
var h = dim(cs && cs.height, img.getAttribute('height'), rect.height, 160);
|
|
75
|
+
// Fill case: the computed size is a percentage we could NOT resolve to px
|
|
76
|
+
// (the img lives in a display:none present-mode frame). Mirror the
|
|
77
|
+
// percentage onto the placeholder so it fills the same slot once the frame
|
|
78
|
+
// is revealed + self-fit-scaled, instead of the default box. w/h keep
|
|
79
|
+
// their defaults purely to select the large (glyph+label) tier, since a
|
|
80
|
+
// fill image is content-sized.
|
|
81
|
+
var fillW = (pxLen(cs && cs.width) == null && cs && /%$/.test(cs.width)) ? cs.width : null;
|
|
82
|
+
var fillH = (pxLen(cs && cs.height) == null && cs && /%$/.test(cs.height)) ? cs.height : null;
|
|
83
|
+
var radius = (cs && cs.borderRadius && cs.borderRadius !== '0px') ? cs.borderRadius : '4px';
|
|
84
|
+
// Degrade by available footprint so a tiny broken embed stays tiny instead
|
|
85
|
+
// of blowing out the layout with text it can't hold: large -> glyph +
|
|
86
|
+
// label; small -> glyph only; tiny -> just the box. The aria-label always
|
|
87
|
+
// carries the full message regardless of what is drawn.
|
|
88
|
+
var minDim = w < h ? w : h;
|
|
89
|
+
var showGlyph = minDim >= 40;
|
|
90
|
+
var showText = w >= 130 && h >= 70;
|
|
91
|
+
var pad = showText ? 12 : (showGlyph ? 6 : 0);
|
|
92
|
+
// Block-level images (incl. flex/grid items) get a block-level flex box so
|
|
93
|
+
// full-width layout and margin:auto centering survive; inline images stay
|
|
94
|
+
// inline-flex.
|
|
95
|
+
var disp = (cs && /^inline/.test(cs.display)) ? 'inline-flex' : 'flex';
|
|
96
|
+
var note = document.createElement('div');
|
|
97
|
+
note.setAttribute('data-sg-broken-image', '');
|
|
98
|
+
note.setAttribute('role', 'img');
|
|
99
|
+
var alt = (img.getAttribute('alt') || '').trim();
|
|
100
|
+
note.setAttribute('aria-label', alt ? alt + ' \\u2014 ' + MESSAGE : MESSAGE);
|
|
101
|
+
// width holds the footprint; the text tier uses min-height (not a fixed
|
|
102
|
+
// height) so the label can grow rather than clip, while the glyph/box
|
|
103
|
+
// tiers keep the exact footprint. overflow:hidden only rounds the corners
|
|
104
|
+
// (the grown/exact height always fits whatever is drawn).
|
|
105
|
+
var widthCss = 'width:' + (fillW || (w + 'px')) + ';';
|
|
106
|
+
var heightCss = fillH ? 'height:' + fillH + ';' : (showText ? 'min-height:' + h + 'px;' : 'height:' + h + 'px;');
|
|
107
|
+
note.style.cssText = 'box-sizing:border-box;display:' + disp + ';flex-direction:column;align-items:center;justify-content:center;gap:8px;' + widthCss + heightCss + 'padding:' + pad + 'px;background:rgba(128,128,128,0.12);border:1px solid rgba(128,128,128,0.25);border-radius:' + radius + ';color:rgba(120,120,120,0.95);font:500 13px/1.35 system-ui,-apple-system,sans-serif;text-align:center;overflow:hidden';
|
|
108
|
+
// Preserve the image's placement so a broken absolutely-positioned,
|
|
109
|
+
// floated, centered, or grid/flex-placed image keeps its slot instead of
|
|
110
|
+
// dropping into normal flow and shifting the whole artifact.
|
|
111
|
+
if (cs) {
|
|
112
|
+
var keep = ['position','top','right','bottom','left','transform','transformOrigin','float','marginTop','marginRight','marginBottom','marginLeft','verticalAlign','alignSelf','justifySelf','gridColumn','gridRow'];
|
|
113
|
+
for (var k = 0; k < keep.length; k++) {
|
|
114
|
+
var val = cs[keep[k]];
|
|
115
|
+
if (val && val !== 'auto' && val !== 'normal' && val !== 'static' && val !== 'none' && val !== '0px') {
|
|
116
|
+
try { note.style[keep[k]] = val; } catch (e) {}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (showGlyph) {
|
|
121
|
+
var svg = document.createElementNS(NS, 'svg');
|
|
122
|
+
svg.setAttribute('viewBox', '0 0 32 32');
|
|
123
|
+
svg.setAttribute('width', '20');
|
|
124
|
+
svg.setAttribute('height', '20');
|
|
125
|
+
svg.setAttribute('fill', 'currentColor');
|
|
126
|
+
svg.setAttribute('aria-hidden', 'true');
|
|
127
|
+
svg.style.cssText = 'flex:none;opacity:0.85';
|
|
128
|
+
for (var i = 0; i < GLYPH.length; i++) {
|
|
129
|
+
var p = document.createElementNS(NS, 'path');
|
|
130
|
+
p.setAttribute('d', GLYPH[i]);
|
|
131
|
+
svg.appendChild(p);
|
|
132
|
+
}
|
|
133
|
+
note.appendChild(svg);
|
|
134
|
+
}
|
|
135
|
+
if (showText) {
|
|
136
|
+
var label = document.createElement('span');
|
|
137
|
+
label.textContent = MESSAGE;
|
|
138
|
+
label.style.maxWidth = '100%';
|
|
139
|
+
note.appendChild(label);
|
|
140
|
+
}
|
|
141
|
+
var prevDisplay = img.style.display;
|
|
142
|
+
img.style.display = 'none';
|
|
143
|
+
if (img.parentNode) img.parentNode.insertBefore(note, img.nextSibling);
|
|
144
|
+
// Self-heal: if the same <img> later loads (an artifact's own onerror
|
|
145
|
+
// retry swapped src to a working URL), drop the placeholder and restore
|
|
146
|
+
// the image to its PRIOR inline display rather than leave a valid image
|
|
147
|
+
// hidden behind the note.
|
|
148
|
+
img.addEventListener('load', function onload() {
|
|
149
|
+
if (img.naturalWidth > 0) {
|
|
150
|
+
img.removeEventListener('load', onload);
|
|
151
|
+
if (note.parentNode) note.parentNode.removeChild(note);
|
|
152
|
+
img.style.display = prevDisplay;
|
|
153
|
+
img.removeAttribute('data-sg-broken');
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
} catch (e) {}
|
|
157
|
+
}
|
|
158
|
+
// Schedule on the window receiver (a detached rAF call can throw in strict
|
|
159
|
+
// contexts) and never let scheduling throw out of the capture listener.
|
|
160
|
+
function defer(fn) {
|
|
161
|
+
try { if (window.requestAnimationFrame) { window.requestAnimationFrame(fn); return; } } catch (e) {}
|
|
162
|
+
try { window.setTimeout(fn, 0); } catch (e) {}
|
|
163
|
+
}
|
|
164
|
+
document.addEventListener('error', function (e) {
|
|
165
|
+
var t = e && e.target;
|
|
166
|
+
// Defer a frame so an artifact's own onerror retry can swap src first; the
|
|
167
|
+
// load-time sweep below still inserts the note synchronously before a
|
|
168
|
+
// headless capture (which waits for load + rAF), so the export never races.
|
|
169
|
+
if (t && t.tagName === 'IMG') defer(function () { replace(t); });
|
|
170
|
+
}, true);
|
|
171
|
+
// Sweep images already broken before the listener registered (cached 404s, or
|
|
172
|
+
// the standalone tag running at body end after parse).
|
|
173
|
+
function sweep() {
|
|
174
|
+
try {
|
|
175
|
+
var imgs = document.querySelectorAll('img');
|
|
176
|
+
for (var i = 0; i < imgs.length; i++) {
|
|
177
|
+
var im = imgs[i];
|
|
178
|
+
if (im.complete && im.naturalWidth === 0 && im.getAttribute('src')) replace(im);
|
|
179
|
+
}
|
|
180
|
+
} catch (e) {}
|
|
181
|
+
}
|
|
182
|
+
// Run once now — catches images already parsed + broken when this tag
|
|
183
|
+
// executes (the standalone tag sits at body end, after the markup), so a
|
|
184
|
+
// user/library script running next sees the placeholder, not the raw broken
|
|
185
|
+
// img. Run again on load for cached 404s that completed before the capture
|
|
186
|
+
// listener registered.
|
|
187
|
+
sweep();
|
|
188
|
+
window.addEventListener('load', sweep);
|
|
189
|
+
})();`)}<\/script>`}var at=/[A-Za-z0-9_-]/,ot=/\s/;function st(e){let t=e=>e.toLowerCase();return e.replace(/(?<![\w-])position\s*:\s*running\([^)]*\)/gi,`display:none`).replace(/(?<![\w-])break-(inside|before|after)\s*:\s*avoid-page\b/gi,(e,n)=>`break-${t(n)}:avoid`).replace(/(?<![\w-])page-break-(before|after)\s*:\s*(?:always|left|right|recto|verso|page)\b/gi,(e,n)=>`break-${t(n)}:column`).replace(/(?<![\w-])page-break-(before|after)\s*:\s*avoid\b/gi,(e,n)=>`break-${t(n)}:avoid`).replace(/(?<![\w-])page-break-inside\s*:\s*avoid\b/gi,`break-inside:avoid`).replace(/(?<![\w-])break-(before|after)\s*:\s*(?:page|always|left|right|recto|verso)\b/gi,(e,n)=>`break-${t(n)}:column`)}function ct(e){if(!e)return e;let t=e.length,n=e=>e!==void 0&&at.test(e),r=e=>e!==void 0&&ot.test(e),i=``,a=``,o=()=>{a&&=(i+=st(a),``)},s=0;for(;s<t;){let c=e[s];if(c===`/`&&e[s+1]===`*`){o();let n=e.indexOf(`*/`,s+2),r=n===-1?t:n+2;i+=e.slice(s,r),s=r;continue}if(c===`"`||c===`'`){o();let n=s+1;for(;n<t;){if(e[n]===`\\`){n+=2;continue}if(e[n]===c){n++;break}n++}i+=e.slice(s,n),s=n;continue}if((c===`u`||c===`U`)&&e.slice(s,s+4).toLowerCase()===`url(`&&!n(e[s-1])){o();let n=s+4;for(;n<t&&r(e[n]);)n++;if(e[n]===`"`||e[n]===`'`){let i=e[n];for(n++;n<t;){if(e[n]===`\\`){n+=2;continue}if(e[n]===i){n++;break}n++}for(;n<t&&r(e[n]);)n++;e[n]===`)`&&n++}else for(;n<t;){if(e[n]===`\\`){n+=2;continue}if(e[n]===`)`){n++;break}n++}i+=e.slice(s,n),s=n;continue}a+=c,s++}return o(),i}var lt=2e3,ut=`#ffffff`,dt=`#fbfaf8`,ft=`#1c1a17`,pt=`${dt} radial-gradient(circle, rgba(20,18,16,0.11) 1px, transparent 1.2px) 0 0 / 14px 14px`,mt=`${ft} radial-gradient(circle, rgba(240,238,233,0.10) 1px, transparent 1.2px) 0 0 / 14px 14px`;function ht(e){return e===`dark`?mt:pt}var gt={light:`#1c1a18`,dark:`#f0eee9`},_t={light:`#6b675f`,dark:`#a8a39a`},vt={light:dt,dark:ft};function yt(e){return`--sg-ink:${gt[e]};--sg-ink-muted:${_t[e]};--sg-surface:${vt[e]};`}function bt(e,t,n){return t===`iframe`?`:root{${yt(e===`dark`?`dark`:`light`)}}`:n?`:root{${yt(`light`)}}\n@media (prefers-color-scheme: dark){:root{${yt(`dark`)}}}`:`:root{${yt(`light`)}}`}var xt=`#f4f2ef`,St=`#121110`;function Ct(e){if(e===void 0)return null;let t=e.trim();return t===`transparent`?`transparent`:t===`neutral`?ut:N(t)?t:null}function wt(e,t,n){return Ct(t??n??(e===`pages`||e===`app`?`neutral`:`transparent`))??`transparent`}function Tt(e){if(!e)return``;let t=Object.entries(e).map(([e,t])=>` ${e.startsWith(`--`)?e:`--${e.replace(/^-+/,``)}`}: ${He(t.replace(/[;{}]/g,` `))};`).join(`
|
|
190
|
+
`);return t?`<style data-artifact-tokens>:root {\n${t}\n}</style>`:``}function W(e){let t=e.shared?.files;return t?Object.entries(t).filter(([e])=>e.toLowerCase().endsWith(`.css`)).map(([e,t])=>`<style data-artifact-file="${B(e)}">\n${He(t)}\n</style>`).join(`
|
|
191
|
+
`):``}function Et(e,t,n){let r=t.rects.map((t,r)=>{let i=e.frames[r],a=i.geometry.height===`auto`?`min-height:${t.height}px;height:auto;`:`height:${t.height}px;`,o=i.layout===`whiteboard`?`background:${ht(n)};`:`background:${wt(i.layout,i.background,e.display?.background)};`;return`[data-sg-frame-id="${i.id}"]{left:${t.x}px;top:${t.y}px;width:${t.width}px;${a}${o}}`}).join(`
|
|
192
|
+
`);return`html,body{margin:0;padding:0;background:transparent;}
|
|
193
|
+
body{position:relative;width:${t.width}px;height:${t.height}px;overflow:hidden;}
|
|
194
|
+
[data-sg-frame]{position:absolute;box-sizing:border-box;overflow:hidden;}
|
|
195
|
+
${r}`}function Dt(e,t=!1){return e.frames.map((e,n)=>{let r=e.title||`Frame ${n+1}`,i=e.background?` data-sg-bg="${B(e.background)}"`:``,a=t&&n===0?` data-sg-present-active=""`:``;return`<section data-sg-frame data-sg-frame-id="${B(e.id)}" data-frame-index="${n}" data-frame-layout="${e.layout}"${i}${a} role="group" aria-label="${B(r)}">${e.content}</section>`}).join(`
|
|
196
|
+
`)}function Ot(e){let t=Object.entries(e.shared?.files??{}).filter(([e])=>/\.(m?js)$/i.test(e)).map(([e,t])=>({path:e,js:t,module:e.toLowerCase().endsWith(`.mjs`)}));return t.length===0?``:(e.libraries??[]).length===0?t.map(({path:e,js:t,module:n})=>`<script${n?` type="module"`:``} data-artifact-file="${B(e)}">\n${Ve(t)}\n<\/script>`).join(`
|
|
197
|
+
`):`<script data-artifact-user-scripts>
|
|
198
|
+
(async () => {
|
|
199
|
+
await (window.__STUDIOGRAPH_ARTIFACT_LIBRARIES_READY__ || Promise.resolve());
|
|
200
|
+
const scripts = ${Ve(JSON.stringify(t.map(e=>({path:e.path,js:e.js,kind:e.module?`module`:`classic`}))))};
|
|
201
|
+
for (const script of scripts) {
|
|
202
|
+
await new Promise((resolve, reject) => {
|
|
203
|
+
const url = URL.createObjectURL(new Blob([String(script.js) + '\\n//# sourceURL=studiograph-artifact://' + String(script.path)], { type: 'text/javascript' }));
|
|
204
|
+
if (script.kind === 'module') { import(url).then(resolve, reject); return; }
|
|
205
|
+
const element = document.createElement('script');
|
|
206
|
+
element.src = url; element.async = false;
|
|
207
|
+
element.onload = () => resolve(); element.onerror = () => reject(new Error('Could not load artifact script: ' + String(script.path)));
|
|
208
|
+
document.head.appendChild(element);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
})().catch((error) => { console.error('Artifact script error', error); throw error; });
|
|
212
|
+
<\/script>`}function kt(e,t,n=!1,r=!1){return`
|
|
213
|
+
(() => {
|
|
214
|
+
const artifactId = ${JSON.stringify(e)};
|
|
215
|
+
const surface = ${JSON.stringify(t)};
|
|
216
|
+
const fullBleed = ${JSON.stringify(n)};
|
|
217
|
+
const whiteboard = ${JSON.stringify(r)};
|
|
218
|
+
// A whiteboard pans/zooms in BOTH editor and present (it is a large pannable
|
|
219
|
+
// surface, not a stepped deck), so wheel AND hand-drag pan are forwarded to the
|
|
220
|
+
// host in either mode; elsewhere only the editor navigates. In a whiteboard
|
|
221
|
+
// present there is no pointer/hand toolbar, so the hand tool is the default —
|
|
222
|
+
// the surface pans on a plain drag. A whiteboard EDITOR keeps the pointer default
|
|
223
|
+
// (it has the Select / Pan toggle) and the host syncs the active tool.
|
|
224
|
+
const canNavigate = surface === 'editor' || whiteboard;
|
|
225
|
+
let tool = ${JSON.stringify(r&&t!==`editor`?`hand`:`pointer`)};
|
|
226
|
+
const send = (payload) => { try { parent.postMessage({ channel: 'studiograph-artifact', artifactId, ...payload }, '*'); } catch {} };
|
|
227
|
+
// Show the grab cursor over the canvas (the iframe content) whenever the hand
|
|
228
|
+
// tool is active — the host stage cursor doesn't reach inside the iframe. The
|
|
229
|
+
// pan handlers below swap to 'grabbing' while dragging.
|
|
230
|
+
const applyCursor = () => { try { document.body.style.cursor = (canNavigate && tool === 'hand') ? 'grab' : ''; } catch {} };
|
|
231
|
+
applyCursor();
|
|
232
|
+
const frames = () => Array.from(document.querySelectorAll('[data-sg-frame]'));
|
|
233
|
+
const cssEscape = (value) => (window.CSS && CSS.escape) ? CSS.escape(value) : String(value);
|
|
234
|
+
const frameById = (id) => document.querySelector('[data-sg-frame-id="' + cssEscape(id) + '"]');
|
|
235
|
+
|
|
236
|
+
// --- per-frame size reporting (auto frames; host reflows from these) ---
|
|
237
|
+
const measure = () => frames().map((el) => ({
|
|
238
|
+
id: el.getAttribute('data-sg-frame-id'),
|
|
239
|
+
width: el.offsetWidth,
|
|
240
|
+
height: Math.max(el.scrollHeight, el.offsetHeight),
|
|
241
|
+
}));
|
|
242
|
+
let sizeTimer = null;
|
|
243
|
+
const reportSizes = () => send({ type: 'frame-sizes', sizes: measure() });
|
|
244
|
+
const queueSizes = () => { if (sizeTimer) clearTimeout(sizeTimer); sizeTimer = setTimeout(reportSizes, 150); };
|
|
245
|
+
|
|
246
|
+
// --- apply host-computed layout rects + extent ---
|
|
247
|
+
// The host recomputes the analytic layout when an auto-height frame measures,
|
|
248
|
+
// then sends the new rects AND the new total extent. Frame width comes from
|
|
249
|
+
// the rect; auto frames keep height:auto (content-driven). The body is resized
|
|
250
|
+
// to the extent so a grown auto frame isn't clipped by the baked body box
|
|
251
|
+
// (the host resizes the iframe element to the same extent in lockstep).
|
|
252
|
+
const applyLayout = (rects, width, height) => {
|
|
253
|
+
for (const rect of (rects || [])) {
|
|
254
|
+
const el = frameById(rect.id);
|
|
255
|
+
if (!el) continue;
|
|
256
|
+
el.style.left = rect.x + 'px';
|
|
257
|
+
el.style.top = rect.y + 'px';
|
|
258
|
+
el.style.width = rect.width + 'px';
|
|
259
|
+
}
|
|
260
|
+
if (typeof width === 'number' && width > 0) document.body.style.width = width + 'px';
|
|
261
|
+
if (typeof height === 'number' && height > 0) document.body.style.height = height + 'px';
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
window.addEventListener('message', (event) => {
|
|
265
|
+
const data = event.data;
|
|
266
|
+
if (!data || data.channel !== 'studiograph-artifact-host' || data.artifactId !== artifactId) return;
|
|
267
|
+
if (data.type === 'apply-layout') applyLayout(data.rects, data.width, data.height);
|
|
268
|
+
if (data.type === 'set-tool' && (data.tool === 'pointer' || data.tool === 'hand')) { tool = data.tool; applyCursor(); }
|
|
269
|
+
if (data.type === 'clear-selection') clearSelection();
|
|
270
|
+
if (data.type === 'select-ancestor' && typeof data.index === 'number') selectAncestor(data.index);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
window.addEventListener('error', (event) => send({ status: 'error', message: String((event && event.message) || 'Artifact error') }));
|
|
274
|
+
window.addEventListener('unhandledrejection', (event) => send({ status: 'error', message: String((event && event.reason && event.reason.message) || (event && event.reason) || 'Artifact promise rejection') }));
|
|
275
|
+
// Observe frames for size changes. The observer is set up AFTER the body has
|
|
276
|
+
// parsed (frames exist) — at head-parse time querySelectorAll is empty — so
|
|
277
|
+
// async content growth (fonts, images, and document pagination, which only
|
|
278
|
+
// settles after load) is reported, not just the one-shot load measure.
|
|
279
|
+
let resizeObserver = null;
|
|
280
|
+
const observeFrames = () => {
|
|
281
|
+
try {
|
|
282
|
+
if (!resizeObserver) resizeObserver = new ResizeObserver(queueSizes);
|
|
283
|
+
else resizeObserver.disconnect();
|
|
284
|
+
for (const el of frames()) resizeObserver.observe(el);
|
|
285
|
+
} catch {}
|
|
286
|
+
};
|
|
287
|
+
// applyCursor() at init is a no-op (it runs in <head>, before <body> exists), so
|
|
288
|
+
// set the cursor again on load — otherwise a present whiteboard (default hand
|
|
289
|
+
// tool) shows the grab cursor only after the first pointer interaction.
|
|
290
|
+
window.addEventListener('load', () => { send({ status: 'ready' }); observeFrames(); reportSizes(); applyCursor(); });
|
|
291
|
+
try { if (document.fonts && document.fonts.ready) document.fonts.ready.then(() => { observeFrames(); reportSizes(); }); } catch {}
|
|
292
|
+
|
|
293
|
+
// --- selection (editor only) ---
|
|
294
|
+
const safeText = (value, limit = 160) => String(value || '').replace(/\\s+/g, ' ').trim().slice(0, limit);
|
|
295
|
+
// Content/interactive elements snap selection to themselves (a click on a
|
|
296
|
+
// heading's text selects the heading, on a button's label the button); any other
|
|
297
|
+
// element selects exactly as itself (see selectionTarget).
|
|
298
|
+
const specificContent = 'h1,h2,h3,h4,h5,h6,p,li,td,th,blockquote,figure,figcaption,label,svg,path,g,rect,circle,text,img,video,a,button,[role="button"]';
|
|
299
|
+
const selectorFor = (el) => {
|
|
300
|
+
if (!(el instanceof Element)) return '';
|
|
301
|
+
if (el.id) return '#' + cssEscape(el.id);
|
|
302
|
+
const parts = [];
|
|
303
|
+
let node = el;
|
|
304
|
+
while (node && node.nodeType === 1 && parts.length < 5 && !node.hasAttribute('data-sg-frame')) {
|
|
305
|
+
let part = node.tagName.toLowerCase();
|
|
306
|
+
const parent = node.parentElement;
|
|
307
|
+
if (parent) {
|
|
308
|
+
const twins = Array.from(parent.children).filter((child) => child.tagName === node.tagName);
|
|
309
|
+
if (twins.length > 1) part += ':nth-of-type(' + (twins.indexOf(node) + 1) + ')';
|
|
310
|
+
}
|
|
311
|
+
parts.unshift(part);
|
|
312
|
+
node = parent;
|
|
313
|
+
}
|
|
314
|
+
return parts.join(' > ');
|
|
315
|
+
};
|
|
316
|
+
const selected = new Map();
|
|
317
|
+
const clearSelection = (publish = true) => {
|
|
318
|
+
for (const entry of selected.values()) entry.el && entry.el.removeAttribute && entry.el.removeAttribute('data-sg-selected');
|
|
319
|
+
selected.clear();
|
|
320
|
+
if (publish) publishSelection();
|
|
321
|
+
};
|
|
322
|
+
// Human label for a breadcrumb segment: data-sg-name if authored, else a
|
|
323
|
+
// CSS-ish token (tag, tag#id, or tag.firstClass); the frame shows its name.
|
|
324
|
+
const labelFor = (el) => {
|
|
325
|
+
if (el.hasAttribute('data-sg-frame')) {
|
|
326
|
+
return el.getAttribute('data-sg-name') || ('Frame ' + ((parseInt(el.getAttribute('data-frame-index'), 10) || 0) + 1));
|
|
327
|
+
}
|
|
328
|
+
const name = el.getAttribute('data-sg-name');
|
|
329
|
+
if (name) return name;
|
|
330
|
+
const tag = el.tagName.toLowerCase();
|
|
331
|
+
if (el.id) return tag + '#' + el.id;
|
|
332
|
+
const cls = (el.getAttribute('class') || '').trim().split(/\\s+/).filter(Boolean)[0];
|
|
333
|
+
return cls ? tag + '.' + cls : tag;
|
|
334
|
+
};
|
|
335
|
+
// The selected element's ancestor chain within its frame: frame-first → el-last.
|
|
336
|
+
const ancestorChain = (el) => {
|
|
337
|
+
const frame = el.closest('[data-sg-frame]');
|
|
338
|
+
if (!frame) return [];
|
|
339
|
+
const chain = [];
|
|
340
|
+
let n = el;
|
|
341
|
+
while (n) { chain.unshift(n); if (n === frame) break; n = n.parentElement; }
|
|
342
|
+
return chain;
|
|
343
|
+
};
|
|
344
|
+
const publishSelection = () => {
|
|
345
|
+
const entries = Array.from(selected.values());
|
|
346
|
+
// Recompute each target's descriptor from the LIVE element so the rects reflect
|
|
347
|
+
// current geometry — a scroll/resize re-emit must carry where the element is NOW,
|
|
348
|
+
// not where it was when first selected (the targetId/selector stay stable, so the
|
|
349
|
+
// host repositions its overlay in place rather than treating it as a new target).
|
|
350
|
+
const targets = entries.map((entry) => { entry.target = descriptorFor(entry.el); return entry.target; });
|
|
351
|
+
// A single selection carries its ancestor labels for the host breadcrumb;
|
|
352
|
+
// a multi-selection has no single path.
|
|
353
|
+
const path = entries.length === 1 ? ancestorChain(entries[0].el).map(labelFor) : null;
|
|
354
|
+
send({ type: 'selection-change', primaryTargetId: (targets[targets.length - 1] || {}).targetId || '', targets, ...(path ? { path: path } : {}) });
|
|
355
|
+
if (targets.length === 0) send({ type: 'clear-selection' });
|
|
356
|
+
};
|
|
357
|
+
// Breadcrumb drill-out: re-select the ancestor at the given index of the current
|
|
358
|
+
// single selection's chain. The selected element itself (last) is a no-op.
|
|
359
|
+
const selectAncestor = (index) => {
|
|
360
|
+
const entries = Array.from(selected.values());
|
|
361
|
+
if (entries.length !== 1) return;
|
|
362
|
+
const chain = ancestorChain(entries[0].el);
|
|
363
|
+
const target = chain[index];
|
|
364
|
+
if (!(target instanceof Element) || target === entries[0].el) return;
|
|
365
|
+
clearSelection(false);
|
|
366
|
+
const t = descriptorFor(target);
|
|
367
|
+
target.setAttribute('data-sg-selected', 'true');
|
|
368
|
+
selected.set(t.targetId, { el: target, target: t });
|
|
369
|
+
publishSelection();
|
|
370
|
+
};
|
|
371
|
+
// Clip an element rect to a box (both in iframe viewport coords), returning the
|
|
372
|
+
// visible intersection as a plain {x,y,width,height}. A paginated document renders
|
|
373
|
+
// each page as a [data-sg-page-window] (overflow:hidden) onto ONE column of a single
|
|
374
|
+
// native multi-column flow; a block that fragments across a column (= page) boundary
|
|
375
|
+
// has a getBoundingClientRect spanning BOTH pages, and getBoundingClientRect ignores
|
|
376
|
+
// the window's clip — so a selection of it would draw ACROSS pages. Clipping to the
|
|
377
|
+
// page window keeps the overlay on the current page (its only visible part there).
|
|
378
|
+
const clipRectToBox = (rect, box) => {
|
|
379
|
+
const left = Math.max(rect.left, box.left);
|
|
380
|
+
const top = Math.max(rect.top, box.top);
|
|
381
|
+
const right = Math.min(rect.right, box.right);
|
|
382
|
+
const bottom = Math.min(rect.bottom, box.bottom);
|
|
383
|
+
return { x: left, y: top, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
|
|
384
|
+
};
|
|
385
|
+
const descriptorFor = (el) => {
|
|
386
|
+
const frame = el.closest('[data-sg-frame]');
|
|
387
|
+
// Only content inside a paginated page window is clipped; furniture and a bare
|
|
388
|
+
// frame/tile selection (not inside a window) keep their full rect.
|
|
389
|
+
const pageWindow = el.closest('[data-sg-page-window]');
|
|
390
|
+
const elRect = el.getBoundingClientRect();
|
|
391
|
+
const rect = pageWindow ? clipRectToBox(elRect, pageWindow.getBoundingClientRect()) : elRect;
|
|
392
|
+
const frameId = frame ? frame.getAttribute('data-sg-frame-id') : '';
|
|
393
|
+
// Never emit an empty selector (the host drops empty-selector targets): the
|
|
394
|
+
// frame element addresses by its frame id, anything else by its DOM path,
|
|
395
|
+
// falling back to the tag name.
|
|
396
|
+
const isFrame = el.hasAttribute('data-sg-frame');
|
|
397
|
+
const selector = isFrame
|
|
398
|
+
? '[data-sg-frame-id="' + frameId + '"]'
|
|
399
|
+
: (selectorFor(el) || el.tagName.toLowerCase());
|
|
400
|
+
return {
|
|
401
|
+
frameId,
|
|
402
|
+
frameIndex: frame ? Number(frame.getAttribute('data-frame-index')) : -1,
|
|
403
|
+
selector,
|
|
404
|
+
tagName: el.tagName.toLowerCase(),
|
|
405
|
+
text: safeText(el.textContent),
|
|
406
|
+
rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
|
|
407
|
+
targetId: (frameId || '') + '::' + selector,
|
|
408
|
+
};
|
|
409
|
+
};
|
|
410
|
+
const selectionTarget = (node) => {
|
|
411
|
+
if (!(node instanceof Element)) return null;
|
|
412
|
+
const frame = node.closest('[data-sg-frame]');
|
|
413
|
+
if (!frame) return null; // bare stage → clears the selection
|
|
414
|
+
const explicit = node.closest('[data-sg-selectable]');
|
|
415
|
+
if (explicit) return explicit;
|
|
416
|
+
// EVERYTHING is selectable. Snap a click that lands inside a meaningful
|
|
417
|
+
// content/interactive element up to that element (clicking a heading's text
|
|
418
|
+
// selects the heading; a button's label selects the button); otherwise select
|
|
419
|
+
// the EXACT element clicked — a structural wrapper (header bar, nav rail, logo)
|
|
420
|
+
// selects as itself, never silently collapsing to the whole frame. The frame is
|
|
421
|
+
// selected only by clicking its own bare background. Use the breadcrumb to drill
|
|
422
|
+
// OUT to a container.
|
|
423
|
+
const specific = node.closest(specificContent);
|
|
424
|
+
if (specific && specific !== frame && frame.contains(specific)) return specific;
|
|
425
|
+
return node;
|
|
426
|
+
};
|
|
427
|
+
window.addEventListener('click', (event) => {
|
|
428
|
+
if (surface !== 'editor' || tool !== 'pointer') return;
|
|
429
|
+
if (handleLinkClick(event)) { /* still select the link element */ }
|
|
430
|
+
const el = selectionTarget(event.target);
|
|
431
|
+
if (!(el instanceof Element)) { clearSelection(); return; }
|
|
432
|
+
const target = descriptorFor(el);
|
|
433
|
+
const additive = event.shiftKey || event.metaKey || event.ctrlKey;
|
|
434
|
+
if (!additive) clearSelection(false);
|
|
435
|
+
if (additive && selected.has(target.targetId)) {
|
|
436
|
+
const prev = selected.get(target.targetId);
|
|
437
|
+
prev && prev.el && prev.el.removeAttribute('data-sg-selected');
|
|
438
|
+
selected.delete(target.targetId);
|
|
439
|
+
} else {
|
|
440
|
+
el.setAttribute('data-sg-selected', 'true');
|
|
441
|
+
selected.set(target.targetId, { el, target });
|
|
442
|
+
}
|
|
443
|
+
publishSelection();
|
|
444
|
+
}, { capture: true });
|
|
445
|
+
window.addEventListener('keydown', (event) => {
|
|
446
|
+
if (surface !== 'editor' || event.key !== 'Escape' || selected.size === 0) return;
|
|
447
|
+
clearSelection();
|
|
448
|
+
event.preventDefault();
|
|
449
|
+
}, { capture: true });
|
|
450
|
+
|
|
451
|
+
// Selection chrome lives in the HOST overlay, positioned from element rects. A
|
|
452
|
+
// scroll (the page or any inner scroll container) moves those elements, so re-emit
|
|
453
|
+
// the selection with fresh rects while a selection exists — rAF-throttled, mirroring
|
|
454
|
+
// the pan/zoom flush — or the overlay would lag behind the content it frames.
|
|
455
|
+
// Capture-phase catches non-bubbling scroll events from nested scrollers; passive
|
|
456
|
+
// keeps scrolling smooth.
|
|
457
|
+
let selectionReflowFrame = null;
|
|
458
|
+
const flushSelectionReflow = () => { selectionReflowFrame = null; if (selected.size > 0) publishSelection(); };
|
|
459
|
+
window.addEventListener('scroll', () => {
|
|
460
|
+
if (selected.size === 0 || selectionReflowFrame !== null) return;
|
|
461
|
+
selectionReflowFrame = requestAnimationFrame(flushSelectionReflow);
|
|
462
|
+
}, { capture: true, passive: true });
|
|
463
|
+
|
|
464
|
+
// Swallow in-sandbox navigation (a relative/external href would blank the frame).
|
|
465
|
+
const handleLinkClick = (event) => {
|
|
466
|
+
if (event.defaultPrevented || event.button) return false;
|
|
467
|
+
const anchor = event.target instanceof Element ? event.target.closest('a[href]') : null;
|
|
468
|
+
if (!anchor) return false;
|
|
469
|
+
const href = anchor.getAttribute('href') || '';
|
|
470
|
+
if (!href || /^javascript:/i.test(href)) return false;
|
|
471
|
+
event.preventDefault();
|
|
472
|
+
if (href.charAt(0) === '#') {
|
|
473
|
+
try { const dest = document.getElementById(href.slice(1)); dest && dest.scrollIntoView({ block: 'start', behavior: 'smooth' }); } catch {}
|
|
474
|
+
}
|
|
475
|
+
return true;
|
|
476
|
+
};
|
|
477
|
+
// Non-editor surfaces (a present document scrolls like a PDF): swallow in-frame
|
|
478
|
+
// navigation here too, so a relative/external href can't blank the sandboxed
|
|
479
|
+
// frame, and an in-document #anchor smooth-scrolls to its section while reading.
|
|
480
|
+
// Editor runs handleLinkClick from its own click handler above.
|
|
481
|
+
window.addEventListener('click', (event) => {
|
|
482
|
+
if (surface === 'editor') return;
|
|
483
|
+
handleLinkClick(event);
|
|
484
|
+
}, { capture: true });
|
|
485
|
+
|
|
486
|
+
// --- pan/zoom forwarding (the host owns the transform) ---
|
|
487
|
+
let panDelta = null, panFrame = null, zoomDelta = null, zoomFrame = null;
|
|
488
|
+
const flushPan = () => { panFrame = null; if (!panDelta) return; const d = panDelta; panDelta = null; send({ type: 'pan-delta', dx: d.dx, dy: d.dy }); };
|
|
489
|
+
const queuePan = (dx, dy) => { panDelta = panDelta ? { dx: panDelta.dx + dx, dy: panDelta.dy + dy } : { dx, dy }; if (panFrame === null) panFrame = requestAnimationFrame(flushPan); };
|
|
490
|
+
const flushZoom = () => { zoomFrame = null; if (!zoomDelta) return; const z = zoomDelta; zoomDelta = null; send({ type: 'zoom-delta', delta: z.delta, x: z.x, y: z.y }); };
|
|
491
|
+
const queueZoom = (delta, x, y) => { zoomDelta = zoomDelta ? { delta: zoomDelta.delta + delta, x, y } : { delta, x, y }; if (zoomFrame === null) zoomFrame = requestAnimationFrame(flushZoom); };
|
|
492
|
+
window.addEventListener('wheel', (event) => {
|
|
493
|
+
if (!canNavigate || fullBleed) return; // full-bleed: let the app scroll natively
|
|
494
|
+
const unit = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? window.innerHeight : 1;
|
|
495
|
+
const dx = event.deltaX * unit, dy = event.deltaY * unit;
|
|
496
|
+
if (Math.abs(dx) < 0.01 && Math.abs(dy) < 0.01) return;
|
|
497
|
+
if (event.ctrlKey || event.metaKey) { queueZoom(dy, event.clientX, event.clientY); event.preventDefault(); return; }
|
|
498
|
+
queuePan(dx, dy);
|
|
499
|
+
event.preventDefault();
|
|
500
|
+
}, { capture: true, passive: false });
|
|
501
|
+
let panPointer = null;
|
|
502
|
+
window.addEventListener('pointerdown', (event) => {
|
|
503
|
+
if (!canNavigate || fullBleed || tool !== 'hand' || event.button !== 0) return;
|
|
504
|
+
panPointer = event.pointerId;
|
|
505
|
+
try { event.target.setPointerCapture && event.target.setPointerCapture(event.pointerId); } catch {}
|
|
506
|
+
try { document.body.style.cursor = 'grabbing'; } catch {}
|
|
507
|
+
send({ type: 'pan', phase: 'start', x: event.screenX, y: event.screenY });
|
|
508
|
+
event.preventDefault();
|
|
509
|
+
}, { capture: true });
|
|
510
|
+
window.addEventListener('pointermove', (event) => {
|
|
511
|
+
if (panPointer !== event.pointerId) return;
|
|
512
|
+
send({ type: 'pan', phase: 'move', x: event.screenX, y: event.screenY });
|
|
513
|
+
}, { capture: true });
|
|
514
|
+
const endPan = (event) => { if (panPointer !== event.pointerId) return; send({ type: 'pan', phase: 'end', x: event.screenX, y: event.screenY }); panPointer = null; applyCursor(); };
|
|
515
|
+
window.addEventListener('pointerup', endPan, { capture: true });
|
|
516
|
+
window.addEventListener('pointercancel', endPan, { capture: true });
|
|
517
|
+
// If capture is stolen mid-drag (system gesture, target removed), end the pan so
|
|
518
|
+
// the 'grabbing' cursor doesn't stick.
|
|
519
|
+
window.addEventListener('lostpointercapture', endPan, { capture: true });
|
|
520
|
+
})();`}function G(e){return`html,body{margin:0;padding:0;background:transparent;}
|
|
521
|
+
body{position:relative;margin:0;}
|
|
522
|
+
[data-sg-frame]{position:absolute;left:0 !important;top:0 !important;box-sizing:border-box;overflow:hidden;display:none;}
|
|
523
|
+
[data-sg-frame][data-sg-present-active]{display:block;}
|
|
524
|
+
${e.frames.map(t=>{let n=t.geometry.height===`auto`?`height:auto;`:`height:${t.geometry.height}px;`,r=`background:${wt(t.layout,t.background,e.display?.background)};`;return`[data-sg-frame-id="${t.id}"]{width:${t.geometry.width}px;${n}${r}}`}).join(`
|
|
525
|
+
`)}`}function At(e){return`
|
|
526
|
+
(() => {
|
|
527
|
+
const artifactId = ${JSON.stringify(e)};
|
|
528
|
+
const send = (payload) => { try { parent.postMessage({ channel: 'studiograph-artifact', artifactId, ...payload }, '*'); } catch {} };
|
|
529
|
+
const frames = () => Array.from(document.querySelectorAll('[data-sg-frame]'));
|
|
530
|
+
let active = 0;
|
|
531
|
+
const sendState = () => { const all = frames(); if (all.length) send({ type: 'frame-state', index: active, count: all.length }); };
|
|
532
|
+
const sendSizes = () => send({ type: 'frame-sizes', sizes: frames().map((el) => ({ id: el.getAttribute('data-sg-frame-id'), width: el.offsetWidth, height: Math.max(el.scrollHeight, el.offsetHeight) })) });
|
|
533
|
+
const setActive = (index) => {
|
|
534
|
+
const all = frames();
|
|
535
|
+
if (!all.length) return;
|
|
536
|
+
active = Math.max(0, Math.min(all.length - 1, Number.isFinite(index) ? Math.round(index) : 0));
|
|
537
|
+
all.forEach((el, i) => { const on = i === active; el.toggleAttribute('data-sg-present-active', on); el.setAttribute('aria-hidden', on ? 'false' : 'true'); });
|
|
538
|
+
sendState();
|
|
539
|
+
sendSizes();
|
|
540
|
+
};
|
|
541
|
+
const step = (dir) => { const all = frames(); if (all.length) setActive((active + dir + all.length) % all.length); };
|
|
542
|
+
window.addEventListener('message', (event) => {
|
|
543
|
+
const data = event.data;
|
|
544
|
+
if (!data || data.channel !== 'studiograph-artifact-host' || data.artifactId !== artifactId) return;
|
|
545
|
+
if (data.type === 'set-frame') setActive(Number(data.index));
|
|
546
|
+
if (data.type === 'reset-frames') setActive(0);
|
|
547
|
+
});
|
|
548
|
+
window.addEventListener('error', (event) => send({ status: 'error', message: String((event && event.message) || 'Artifact error') }));
|
|
549
|
+
window.addEventListener('keydown', (event) => {
|
|
550
|
+
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
|
551
|
+
if (event.key === 'ArrowRight' || event.key === 'PageDown' || event.key === ' ') { step(1); event.preventDefault(); return; }
|
|
552
|
+
if (event.key === 'ArrowLeft' || event.key === 'PageUp' || event.key === 'Backspace') { step(-1); event.preventDefault(); return; }
|
|
553
|
+
if (event.key === 'Home') { setActive(0); event.preventDefault(); return; }
|
|
554
|
+
if (event.key === 'End') { setActive(frames().length - 1); event.preventDefault(); return; }
|
|
555
|
+
});
|
|
556
|
+
// Navigation is via the host stepper controls + keyboard only — clicking a slide
|
|
557
|
+
// does NOT advance (the stepper is the clearer affordance; click-to-step was
|
|
558
|
+
// easy to trigger by accident). But pointer activity over the iframe (which the
|
|
559
|
+
// host can't see) must still re-reveal the auto-hiding controls: re-post the
|
|
560
|
+
// current frame-state (the host reveals on it) without changing the slide.
|
|
561
|
+
let activityRaf = null;
|
|
562
|
+
const signalActivity = () => { if (activityRaf !== null) return; activityRaf = requestAnimationFrame(() => { activityRaf = null; sendState(); }); };
|
|
563
|
+
window.addEventListener('pointermove', signalActivity, { passive: true });
|
|
564
|
+
window.addEventListener('click', signalActivity);
|
|
565
|
+
window.addEventListener('load', () => { send({ status: 'ready' }); setActive(0); });
|
|
566
|
+
try { if (document.fonts && document.fonts.ready) document.fonts.ready.then(sendSizes); } catch {}
|
|
567
|
+
})();`}function jt(e){return e.frames.length===1&&e.frames[0].layout!==`whiteboard`&&(e.frames[0].geometry.width===`fill`||e.frames[0].geometry.height===`fill`)}function Mt(e){let t=e.frames[0],n=wt(t.layout,t.background,e.display?.background),r=t.geometry.width;return`html,body{margin:0;padding:0;background:transparent;height:100%;}
|
|
568
|
+
body{position:relative;width:100%;height:100%;}
|
|
569
|
+
[data-sg-frame]{position:absolute;top:0;bottom:0;${typeof r==`number`?`left:50%;transform:translateX(-50%);width:${r}px;max-width:100%;`:`left:0;right:0;`}box-sizing:border-box;overflow:auto;background:${n};}`}function Nt(e){return e.frames.length>0&&e.frames.every(e=>e.layout===`pages`)}function Pt(e){return e.frames.length===1&&e.frames[0].layout===`whiteboard`}function Ft(e){let t=e.frames[0].geometry;return{width:typeof t.width==`number`?t.width:1280,height:typeof t.height==`number`?t.height:800}}function K(){return`.sg-bar{position:fixed;left:50%;bottom:16px;transform:translateX(-50%);display:flex;align-items:center;gap:3px;padding:4px;background:#fff;border:1px solid #e5e2dd;border-radius:8px;box-shadow:0 4px 16px rgba(0,0,0,0.08),0 1px 2px rgba(0,0,0,0.04);z-index:10;cursor:default;font:13px system-ui,-apple-system,sans-serif;}
|
|
570
|
+
.sg-bar-btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:6px;color:#6b675f;background:transparent;cursor:pointer;transition:background 0.15s,color 0.15s;}
|
|
571
|
+
.sg-bar-btn:hover{background:#f2efea;color:#1c1a18;}
|
|
572
|
+
.sg-bar-btn svg{width:16px;height:16px;display:block;}
|
|
573
|
+
.sg-bar-sep{width:1px;height:16px;background:#e5e2dd;margin:0 3px;}
|
|
574
|
+
.sg-bar-zoom,.sg-bar-count{display:flex;align-items:center;justify-content:flex-end;min-width:44px;padding:0 6px;color:#6b675f;font-variant-numeric:tabular-nums;}
|
|
575
|
+
.sg-bar-count{justify-content:center;min-width:54px;}`}function It(e){let{width:t,height:n}=Ft(e);return`html,body{margin:0;padding:0;height:100%;overflow:hidden;background:${xt};}
|
|
576
|
+
body{position:relative;cursor:grab;}
|
|
577
|
+
body.sg-grabbing{cursor:grabbing;}
|
|
578
|
+
[data-sg-frame]{position:absolute;left:0;top:0;width:${t}px;height:${n}px;transform-origin:0 0;box-sizing:border-box;overflow:hidden;background:${pt};}
|
|
579
|
+
@media (prefers-color-scheme: dark){
|
|
580
|
+
html,body{background:${St};}
|
|
581
|
+
[data-sg-frame]{background:${mt};}
|
|
582
|
+
}
|
|
583
|
+
${K()}`}var Lt={reset:`<path d="M18,28A12,12,0,1,0,6,16v6.2L2.4,18.6,1,20l6,6,6-6-1.4-1.4L8,22.2V16H8A10,10,0,1,1,18,26Z"/>`,zoomOut:`<path d="M8 12H18V14H8z"/><path d="M21.4479,20A10.856,10.856,0,0,0,24,13,11,11,0,1,0,13,24a10.856,10.856,0,0,0,7-2.5521L27.5859,29,29,27.5859ZM13,22a9,9,0,1,1,9-9A9.01,9.01,0,0,1,13,22Z"/>`,zoomIn:`<path d="M18 12 14 12 14 8 12 8 12 12 8 12 8 14 12 14 12 18 14 18 14 14 18 14 18 12z"/><path d="M21.4479,20A10.856,10.856,0,0,0,24,13,11,11,0,1,0,13,24a10.856,10.856,0,0,0,7-2.5521L27.5859,29,29,27.5859ZM13,22a9,9,0,1,1,9-9A9.01,9.01,0,0,1,13,22Z"/>`,chevronLeft:`<path d="M10 16 20 6 21.4 7.4 12.8 16 21.4 24.6 20 26z"/>`,chevronRight:`<path d="M22 16 12 26 10.6 24.6 19.2 16 10.6 7.4 12 6z"/>`},Rt=e=>`<svg viewBox="0 0 32 32" fill="currentColor" aria-hidden="true">${Lt[e]}</svg>`;function zt(){return`<div id="sg-wb-bar" class="sg-bar" role="toolbar" aria-label="Canvas controls"><button id="sg-wb-reset" class="sg-bar-btn" type="button" title="Reset view" aria-label="Reset view">${Rt(`reset`)}</button><span class="sg-bar-sep" aria-hidden="true"></span><button id="sg-wb-zoomout" class="sg-bar-btn" type="button" title="Zoom out" aria-label="Zoom out">${Rt(`zoomOut`)}</button><button id="sg-wb-zoomin" class="sg-bar-btn" type="button" title="Zoom in" aria-label="Zoom in">${Rt(`zoomIn`)}</button><span class="sg-bar-sep" aria-hidden="true"></span><span id="sg-wb-zoom" class="sg-bar-zoom">100%</span></div>`}function Bt(e,t){return`
|
|
584
|
+
(() => {
|
|
585
|
+
const W = ${e}, H = ${t}, MAXZOOM = 4;
|
|
586
|
+
// The runtime is injected in <head>, before the body parses, so the frame
|
|
587
|
+
// element is looked up lazily (capturing it at parse time would be null).
|
|
588
|
+
const elOf = () => document.querySelector('[data-sg-frame]');
|
|
589
|
+
let zoom = 1, x = 0, y = 0;
|
|
590
|
+
const vw = () => window.innerWidth, vh = () => window.innerHeight;
|
|
591
|
+
const cover = () => Math.max(vw() / W, vh() / H);
|
|
592
|
+
const clamp = (v, a, b) => Math.min(b, Math.max(a, v));
|
|
593
|
+
const clampPan = () => {
|
|
594
|
+
const w = W * zoom, h = H * zoom;
|
|
595
|
+
x = w >= vw() ? clamp(x, vw() - w, 0) : (vw() - w) / 2;
|
|
596
|
+
y = h >= vh() ? clamp(y, vh() - h, 0) : (vh() - h) / 2;
|
|
597
|
+
};
|
|
598
|
+
const label = () => { const l = document.getElementById('sg-wb-zoom'); if (l) l.textContent = Math.round(zoom * 100) + '%'; };
|
|
599
|
+
const apply = () => { const el = elOf(); if (el) el.style.transform = 'translate(' + x + 'px,' + y + 'px) scale(' + zoom + ')'; label(); };
|
|
600
|
+
// Open (and reset) at 100% centered; a canvas too small to cover the viewport
|
|
601
|
+
// at 1:1 scales up to the cover scale so no edge shows.
|
|
602
|
+
const fit = () => { zoom = Math.max(1, cover()); x = (vw() - W * zoom) / 2; y = (vh() - H * zoom) / 2; clampPan(); apply(); };
|
|
603
|
+
const setZoom = (nz, fx, fy) => {
|
|
604
|
+
// The cover scale is the min zoom; the max must be at least cover so the clamp
|
|
605
|
+
// never inverts (a small canvas can need >MAXZOOM just to cover the viewport).
|
|
606
|
+
const lo = cover(); nz = clamp(nz, lo, Math.max(MAXZOOM, lo));
|
|
607
|
+
fx = (fx == null) ? vw() / 2 : fx; fy = (fy == null) ? vh() / 2 : fy;
|
|
608
|
+
const ax = (fx - x) / zoom, ay = (fy - y) / zoom;
|
|
609
|
+
zoom = nz; x = fx - ax * zoom; y = fy - ay * zoom; clampPan(); apply();
|
|
610
|
+
};
|
|
611
|
+
let dragging = false, px = 0, py = 0;
|
|
612
|
+
window.addEventListener('pointerdown', (e) => {
|
|
613
|
+
if (e.button !== 0 || (e.target && e.target.closest && e.target.closest('#sg-wb-bar'))) return;
|
|
614
|
+
dragging = true; px = e.clientX; py = e.clientY; document.body.classList.add('sg-grabbing');
|
|
615
|
+
try { e.target.setPointerCapture && e.target.setPointerCapture(e.pointerId); } catch {}
|
|
616
|
+
});
|
|
617
|
+
window.addEventListener('pointermove', (e) => { if (!dragging) return; x += e.clientX - px; y += e.clientY - py; px = e.clientX; py = e.clientY; clampPan(); apply(); });
|
|
618
|
+
const end = () => { dragging = false; document.body.classList.remove('sg-grabbing'); };
|
|
619
|
+
window.addEventListener('pointerup', end); window.addEventListener('pointercancel', end); window.addEventListener('lostpointercapture', end);
|
|
620
|
+
window.addEventListener('wheel', (e) => {
|
|
621
|
+
e.preventDefault();
|
|
622
|
+
const unit = e.deltaMode === 1 ? 16 : e.deltaMode === 2 ? vh() : 1;
|
|
623
|
+
if (e.ctrlKey || e.metaKey) { setZoom(zoom * Math.exp(-e.deltaY * unit * 0.0015), e.clientX, e.clientY); return; }
|
|
624
|
+
x -= e.deltaX * unit; y -= e.deltaY * unit; clampPan(); apply();
|
|
625
|
+
}, { passive: false });
|
|
626
|
+
// Wire the toolbar + do the first fit once the DOM exists (the runtime runs in
|
|
627
|
+
// <head>, before the toolbar buttons parse).
|
|
628
|
+
const wire = () => {
|
|
629
|
+
const onBar = (id, fn) => { const b = document.getElementById(id); if (b) b.addEventListener('click', fn); };
|
|
630
|
+
onBar('sg-wb-zoomout', () => setZoom(zoom / 1.2));
|
|
631
|
+
onBar('sg-wb-zoomin', () => setZoom(zoom * 1.2));
|
|
632
|
+
onBar('sg-wb-reset', () => fit());
|
|
633
|
+
fit();
|
|
634
|
+
};
|
|
635
|
+
window.addEventListener('resize', fit);
|
|
636
|
+
if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', wire); else wire();
|
|
637
|
+
window.addEventListener('load', fit);
|
|
638
|
+
})();`}function Vt(){return`.sg-present{position:fixed;left:0;right:0;bottom:24px;display:flex;align-items:center;justify-content:center;pointer-events:none;opacity:0;transition:opacity 300ms ease;z-index:10;font:13px system-ui,-apple-system,sans-serif;}
|
|
639
|
+
.sg-present.visible{opacity:1;}
|
|
640
|
+
.sg-present-group{display:flex;align-items:center;gap:2px;padding:4px;background:rgba(30,30,30,0.85);border-radius:8px;pointer-events:auto;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);}
|
|
641
|
+
.sg-present-btn{width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:6px;color:rgba(255,255,255,0.6);background:transparent;cursor:pointer;transition:color 120ms,background 120ms;}
|
|
642
|
+
.sg-present-btn svg{width:16px;height:16px;display:block;}
|
|
643
|
+
.sg-present-btn:hover{background:rgba(255,255,255,0.1);color:#fff;}
|
|
644
|
+
.sg-present-count{height:32px;display:flex;align-items:center;justify-content:center;padding:0 8px;color:rgba(255,255,255,0.6);font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;user-select:none;}
|
|
645
|
+
.sg-present-reset{position:absolute;right:24px;}
|
|
646
|
+
.sg-present-restart{width:auto;gap:6px;padding:0 8px;font-weight:500;white-space:nowrap;}`}function Ht(e){return`html,body{margin:0;padding:0;height:100%;overflow:hidden;background:#4a4a4a;}
|
|
647
|
+
body{position:relative;}
|
|
648
|
+
[data-sg-frame]{position:absolute;left:0;top:0;transform-origin:0 0;box-sizing:border-box;overflow:hidden;display:none;}
|
|
649
|
+
[data-sg-frame][data-sg-present-active]{display:block;}
|
|
650
|
+
${e.frames.map(t=>{let n=typeof t.geometry.width==`number`?`${t.geometry.width}px`:`100%`,r=t.geometry.height===`auto`||t.geometry.height===`fill`?`height:auto;`:`height:${t.geometry.height}px;`,i=`background:${wt(t.layout,t.background,e.display?.background)};`;return`[data-sg-frame-id="${t.id}"]{width:${n};${r}${i}}`}).join(`
|
|
651
|
+
`)}
|
|
652
|
+
${Vt()}`}function Ut(){return`<div id="sg-present" class="sg-present"><div class="sg-present-group" role="group" aria-label="Slide navigation"><button id="sg-prev" class="sg-present-btn" type="button" title="Previous" aria-label="Previous">${Rt(`chevronLeft`)}</button><span id="sg-count" class="sg-present-count">1 / 1</span><button id="sg-next" class="sg-present-btn" type="button" title="Next" aria-label="Next">${Rt(`chevronRight`)}</button></div><div class="sg-present-group sg-present-reset"><button id="sg-restart" class="sg-present-btn sg-present-restart" type="button" title="Restart" aria-label="Restart">${Rt(`reset`)}<span>Restart</span></button></div></div>`}function Wt(){return`
|
|
653
|
+
(() => {
|
|
654
|
+
const MAX_SCALE = 6;
|
|
655
|
+
const frames = () => Array.prototype.slice.call(document.querySelectorAll('[data-sg-frame]'));
|
|
656
|
+
let active = 0, hideTimer = null;
|
|
657
|
+
const fitActive = () => {
|
|
658
|
+
const all = frames(); if (!all.length) return;
|
|
659
|
+
const el = all[active]; const fw = el.offsetWidth || 1, fh = el.offsetHeight || 1;
|
|
660
|
+
const pad = 48; const scale = Math.min((window.innerWidth - pad) / fw, (window.innerHeight - pad) / fh, MAX_SCALE);
|
|
661
|
+
const s = Math.max(0.05, scale);
|
|
662
|
+
el.style.transform = 'translate(' + ((window.innerWidth - fw * s) / 2) + 'px,' + ((window.innerHeight - fh * s) / 2) + 'px) scale(' + s + ')';
|
|
663
|
+
};
|
|
664
|
+
const updateCount = () => { const c = document.getElementById('sg-count'); if (c) c.textContent = (active + 1) + ' / ' + frames().length; };
|
|
665
|
+
const show = (i) => {
|
|
666
|
+
const all = frames(); if (!all.length) return;
|
|
667
|
+
active = ((i % all.length) + all.length) % all.length;
|
|
668
|
+
all.forEach((el, idx) => { el.toggleAttribute('data-sg-present-active', idx === active); el.setAttribute('aria-hidden', idx === active ? 'false' : 'true'); });
|
|
669
|
+
fitActive(); updateCount();
|
|
670
|
+
};
|
|
671
|
+
const step = (d) => show(active + d);
|
|
672
|
+
const reveal = () => { const c = document.getElementById('sg-present'); if (!c) return; c.classList.add('visible'); if (hideTimer) clearTimeout(hideTimer); hideTimer = setTimeout(() => c.classList.remove('visible'), 2500); };
|
|
673
|
+
const wire = () => {
|
|
674
|
+
const on = (id, fn) => { const b = document.getElementById(id); if (b) b.addEventListener('click', (e) => { e.stopPropagation(); fn(); reveal(); }); };
|
|
675
|
+
on('sg-prev', () => step(-1)); on('sg-next', () => step(1)); on('sg-restart', () => show(0));
|
|
676
|
+
show(0); reveal();
|
|
677
|
+
};
|
|
678
|
+
window.addEventListener('keydown', (e) => {
|
|
679
|
+
if (e.altKey || e.ctrlKey || e.metaKey) return;
|
|
680
|
+
// Don't hijack keys aimed at a focused control or text field: typing in a slide
|
|
681
|
+
// input must work, and Space on a focused button should activate it natively
|
|
682
|
+
// (not double-step). Mirrors the in-app present keyboard guard.
|
|
683
|
+
const t = e.target;
|
|
684
|
+
if (t && t.closest && t.closest('input,textarea,select,[contenteditable="true"],button,a[href],[role="button"]')) return;
|
|
685
|
+
if (e.key === 'ArrowRight' || e.key === 'PageDown' || e.key === ' ') { step(1); reveal(); e.preventDefault(); }
|
|
686
|
+
else if (e.key === 'ArrowLeft' || e.key === 'PageUp' || e.key === 'Backspace') { step(-1); reveal(); e.preventDefault(); }
|
|
687
|
+
else if (e.key === 'Home') { show(0); reveal(); e.preventDefault(); }
|
|
688
|
+
else if (e.key === 'End') { show(frames().length - 1); reveal(); e.preventDefault(); }
|
|
689
|
+
});
|
|
690
|
+
// Navigation is via the stepper controls + keyboard only — clicking a slide does
|
|
691
|
+
// NOT advance (the stepper is the clearer affordance). A click still reveals the
|
|
692
|
+
// auto-hiding controls.
|
|
693
|
+
window.addEventListener('click', reveal);
|
|
694
|
+
window.addEventListener('mousemove', reveal);
|
|
695
|
+
window.addEventListener('resize', fitActive);
|
|
696
|
+
if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', wire); else wire();
|
|
697
|
+
window.addEventListener('load', () => { show(active); reveal(); });
|
|
698
|
+
})();`}function Gt(e){let t=e.frames.map(t=>{let n=typeof t.geometry.width==`number`?`${t.geometry.width}px`:`100%`,r=typeof t.geometry.height==`number`?`min-height:${t.geometry.height}px;`:``,i=wt(t.layout,t.background,e.display?.background);return`[data-sg-frame-id="${t.id}"]:not([data-sg-page]){width:${n};max-width:100%;margin:0 auto 32px;${r}background:${i};box-shadow:0 6px 24px rgba(0,0,0,0.18);}`}).join(`
|
|
699
|
+
`);return`html,body{margin:0;padding:0;background:transparent;height:100%;}
|
|
700
|
+
body{box-sizing:border-box;min-height:100%;overflow:auto;padding:48px 0;}
|
|
701
|
+
[data-sg-frame]{position:relative;box-sizing:border-box;background:transparent;overflow:visible;}
|
|
702
|
+
[data-sg-frame][data-sg-page]{margin:0 auto 32px;overflow:hidden;box-shadow:0 6px 24px rgba(0,0,0,0.18);}
|
|
703
|
+
${Qt()}
|
|
704
|
+
${t}`}function Kt(e){return e.layout===`pages`&&typeof e.geometry.width==`number`&&typeof e.geometry.height==`number`}function qt(e){return e.frames.filter(Kt)}function Jt(e){return e.replace(/(<style\b[^>]*>)([\s\S]*?)(<\/style>)|(\sstyle\s*=\s*)("([^"]*)"|'([^']*)')/gi,(e,t,n,r,i,a,o,s)=>{if(t!==void 0)return t+ct(n)+r;let c=a[0],l=o===void 0?s:o;return i+c+ct(l)+c})}function Yt(e){let t=e.shared,n=t?.files,r=n&&Object.fromEntries(Object.entries(n).map(([e,t])=>[e,e.toLowerCase().endsWith(`.css`)?ct(t):t]));return{...e,...t?{shared:{...t,files:r,...t.head?{head:Jt(t.head)}:{}}}:{},frames:e.frames.map(e=>Kt(e)?{...e,content:Jt(e.content)}:e)}}function Xt(e){let t=e.pageMargins;return{top:t?.top??P.top,right:t?.right??P.right,bottom:t?.bottom??P.bottom,left:t?.left??P.left}}function Zt(){return`[data-sg-doc-flow] img{max-width:100%;height:auto;}
|
|
705
|
+
[data-sg-doc-flow] svg,[data-sg-doc-flow] video,[data-sg-doc-flow] canvas,[data-sg-doc-flow] table,[data-sg-doc-flow] pre{max-width:100%;}`}function Qt(){return`[data-sg-furniture]{position:absolute;font:12px var(--sg-furniture-font, system-ui, -apple-system, sans-serif);color:#374151;pointer-events:none;}`}function $t(){return Qt()}function q(e){let t=Xt(e),n=e.geometry.width,r=e.geometry.height,i=n-t.left-t.right,a=r-t.top-t.bottom,o=t.right+t.left+40;return{width:n,height:r,contentWidth:i,contentHeight:a,gap:o,pitch:i+o,margins:t}}function en(e,t,n,r,i,a){let o={};for(let t of e)o[t.id]={...q(t),title:t.title||`Document`,background:wt(t.layout,t.background,a),...t.furniture?{furniture:t.furniture}:{},...t.pageNumbers?{pageNumbers:t.pageNumbers}:{}};return`
|
|
706
|
+
(() => {
|
|
707
|
+
const artifactId = ${JSON.stringify(t)};
|
|
708
|
+
const renderId = ${JSON.stringify(r)};
|
|
709
|
+
const FRAME_GAP = 64;
|
|
710
|
+
const PROMOTE = ${JSON.stringify(n)};
|
|
711
|
+
const HOSTED_CANVAS = ${JSON.stringify(i)};
|
|
712
|
+
const DONE_ATTR = 'data-sg-paginated-done';
|
|
713
|
+
const PAGINATE = ${JSON.stringify(o)};
|
|
714
|
+
const cssEscape = (value) => (window.CSS && CSS.escape) ? CSS.escape(value) : String(value);
|
|
715
|
+
// Pick the page-position furniture variant: page 1 -> first (or middle), last
|
|
716
|
+
// page -> last (or middle), every other page -> middle.
|
|
717
|
+
const pickSlot = (slots, index, count) => index === 0
|
|
718
|
+
? (slots.first || slots.middle)
|
|
719
|
+
: (index === count - 1 ? (slots.last || slots.middle) : slots.middle);
|
|
720
|
+
const addRegion = (tile, html, region, margins, anchor, offset) => {
|
|
721
|
+
if (!html) return;
|
|
722
|
+
const el = document.createElement('div');
|
|
723
|
+
el.setAttribute('data-sg-furniture', '');
|
|
724
|
+
el.setAttribute('data-sg-furniture-region', region);
|
|
725
|
+
// left/right inset to the side margins so the band aligns to the content column.
|
|
726
|
+
el.style.left = margins.left + 'px';
|
|
727
|
+
el.style.right = margins.right + 'px';
|
|
728
|
+
el.innerHTML = html;
|
|
729
|
+
tile.appendChild(el);
|
|
730
|
+
// Two placements, by anchor:
|
|
731
|
+
// - 'page' (letterhead/masthead): pin to the page's OUTER edge — header at the
|
|
732
|
+
// top edge, footer at the bottom edge, offset px in — independent of margin
|
|
733
|
+
// depth, so a masthead rides high with a deep body margin (no content-padding
|
|
734
|
+
// hack). Height-independent.
|
|
735
|
+
// - 'content' (default, running header/footer): bottom-align the header to just
|
|
736
|
+
// above the content (within the top margin) / top-align the footer to just
|
|
737
|
+
// below it, from the MEASURED height so a tall band never overlaps the body.
|
|
738
|
+
// The default "Page N of M" counter is bottom-RIGHT, so a centered/left footer
|
|
739
|
+
// band clears it. If a margin is smaller than its furniture the author must grow
|
|
740
|
+
// pageMargins — out-of-flow furniture can't reserve space.
|
|
741
|
+
const GAP = 10, MIN_INSET = 8;
|
|
742
|
+
const place = () => {
|
|
743
|
+
if (anchor === 'page') {
|
|
744
|
+
// Pin to the page's outer edge, offset px in (default MIN_INSET).
|
|
745
|
+
const inset = (typeof offset === 'number') ? offset : MIN_INSET;
|
|
746
|
+
if (region === 'header') el.style.top = inset + 'px';
|
|
747
|
+
else el.style.bottom = inset + 'px';
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
// Content anchor: offset is the GAP between the band and the content edge
|
|
751
|
+
// (default GAP) — so it has effect on both anchors, per the model.
|
|
752
|
+
const gap = (typeof offset === 'number') ? offset : GAP;
|
|
753
|
+
const h = el.offsetHeight;
|
|
754
|
+
if (region === 'header') el.style.top = Math.max(MIN_INSET, margins.top - gap - h) + 'px';
|
|
755
|
+
else el.style.bottom = Math.max(MIN_INSET, margins.bottom - gap - h) + 'px';
|
|
756
|
+
};
|
|
757
|
+
place();
|
|
758
|
+
// A logo <img> without a fixed height measures 0 until it loads, which would
|
|
759
|
+
// mis-place a content-anchored band; re-place once each image settles (the render
|
|
760
|
+
// waits for network-idle, so the reposition lands before capture).
|
|
761
|
+
el.querySelectorAll('img').forEach((img) => { if (!img.complete) img.addEventListener('load', place); });
|
|
762
|
+
};
|
|
763
|
+
const addFurniture = (tile, furniture, index, count, margins) => {
|
|
764
|
+
if (furniture.header) addRegion(tile, pickSlot(furniture.header, index, count), 'header', margins, furniture.header.anchor, furniture.header.offset);
|
|
765
|
+
if (furniture.footer) addRegion(tile, pickSlot(furniture.footer, index, count), 'footer', margins, furniture.footer.anchor, furniture.footer.offset);
|
|
766
|
+
};
|
|
767
|
+
// The DEFAULT page number, bottom-right within the bottom margin (replaces the
|
|
768
|
+
// removed Paged.js @page{@bottom-right{counter(page)}} default). Baked as literal
|
|
769
|
+
// text per tile — no cross-tile counter() to keep — so every document keeps page
|
|
770
|
+
// numbers even when it declares no furniture.
|
|
771
|
+
const addPageNumber = (tile, index, count, margins, cfg) => {
|
|
772
|
+
cfg = cfg || {};
|
|
773
|
+
if (cfg.show === false) return;
|
|
774
|
+
if (cfg.showOnFirst === false && index === 0) return;
|
|
775
|
+
const startAt = (typeof cfg.startAt === 'number') ? cfg.startAt : 1;
|
|
776
|
+
const n = startAt + index;
|
|
777
|
+
const m = startAt + count - 1;
|
|
778
|
+
const format = (typeof cfg.format === 'string') ? cfg.format : 'Page {n} of {m}';
|
|
779
|
+
const text = format.replace(/\\{n\\}/g, String(n)).replace(/\\{m\\}/g, String(m));
|
|
780
|
+
if (!text) return;
|
|
781
|
+
const position = cfg.position || 'bottom-right';
|
|
782
|
+
const isTop = position.indexOf('top-') === 0;
|
|
783
|
+
const el = document.createElement('div');
|
|
784
|
+
el.setAttribute('data-sg-furniture', '');
|
|
785
|
+
el.setAttribute('data-sg-furniture-region', 'pagenum');
|
|
786
|
+
el.style.color = '#6b7280';
|
|
787
|
+
// Vertical: offset px from the nearer page edge, else centered in the band
|
|
788
|
+
// (the legacy default: bottom-right at about bottom-margin/2).
|
|
789
|
+
const band = isTop ? margins.top : margins.bottom;
|
|
790
|
+
const v = (typeof cfg.offset === 'number') ? cfg.offset : Math.max(8, Math.round(band / 2) - 8);
|
|
791
|
+
el.style[isTop ? 'top' : 'bottom'] = v + 'px';
|
|
792
|
+
// Horizontal: aligned to the content column's left/right edge, or centered
|
|
793
|
+
// WITHIN the content column (spanning left..right with text-align, like a
|
|
794
|
+
// furniture band) so it stays aligned under asymmetric margins.
|
|
795
|
+
if (position.indexOf('-left') >= 0) el.style.left = margins.left + 'px';
|
|
796
|
+
else if (position.indexOf('-right') >= 0) el.style.right = margins.right + 'px';
|
|
797
|
+
else { el.style.left = margins.left + 'px'; el.style.right = margins.right + 'px'; el.style.textAlign = 'center'; }
|
|
798
|
+
el.textContent = text;
|
|
799
|
+
tile.appendChild(el);
|
|
800
|
+
};
|
|
801
|
+
const compose = async () => {
|
|
802
|
+
const expansions = [];
|
|
803
|
+
// Frames whose composition THREW. Reported to the host so it can surface a
|
|
804
|
+
// non-blocking "couldn't paginate" hint instead of a clipped single page.
|
|
805
|
+
const failed = [];
|
|
806
|
+
// ALWAYS run on every exit path (success, per-frame throw, or top-level throw):
|
|
807
|
+
// mark the settle signal + post frame-pages, so a host-less render's wait
|
|
808
|
+
// resolves and the live host never holds the reveal forever.
|
|
809
|
+
const finish = () => {
|
|
810
|
+
try { document.documentElement.setAttribute(DONE_ATTR, ''); } catch {}
|
|
811
|
+
if (PROMOTE) {
|
|
812
|
+
try { parent.postMessage({ channel: 'studiograph-artifact', artifactId: artifactId, type: 'frame-pages', renderId: renderId, expansions: expansions, failed: failed }, '*'); } catch {}
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
try {
|
|
816
|
+
// Measure after fonts settle so column breaks match the final type. Fonts are
|
|
817
|
+
// inlined as data: URLs by the host, so this normally resolves immediately;
|
|
818
|
+
// TIME-BOX it so a slow font endpoint can't stall composition for seconds.
|
|
819
|
+
try {
|
|
820
|
+
if (document.fonts && document.fonts.ready) {
|
|
821
|
+
await Promise.race([document.fonts.ready, new Promise(function (r) { setTimeout(r, ${lt}); })]);
|
|
822
|
+
}
|
|
823
|
+
} catch {}
|
|
824
|
+
for (const id of Object.keys(PAGINATE)) {
|
|
825
|
+
const source = document.querySelector('[data-sg-frame-id="' + cssEscape(id) + '"]');
|
|
826
|
+
if (!source || !source.parentNode) continue;
|
|
827
|
+
const cfg = PAGINATE[id];
|
|
828
|
+
try {
|
|
829
|
+
const PW = cfg.width, PH = cfg.height, CW = cfg.contentWidth, CH = cfg.contentHeight;
|
|
830
|
+
const GAP = cfg.gap, PITCH = cfg.pitch, m = cfg.margins;
|
|
831
|
+
// Hoist inline <style>/<link> out of the flow into <head> so they apply
|
|
832
|
+
// ONCE (not duplicated per page clone) and don't sit inside the multicol
|
|
833
|
+
// flow. They were rewritten for columns at build time with the shared CSS.
|
|
834
|
+
source.querySelectorAll('style, link[rel="stylesheet"]').forEach((node) => document.head.appendChild(node));
|
|
835
|
+
const flowHtml = source.innerHTML;
|
|
836
|
+
// Two-pass deterministic geometry: multicol STRETCHES columns to fill the
|
|
837
|
+
// container, drifting positions, so pass 1 measures the page count at a
|
|
838
|
+
// wide width and pass 2 pins the flow to exactly n*CW+(n-1)*GAP (+ an
|
|
839
|
+
// explicit column-count) so columns are exactly CW. Measure the real
|
|
840
|
+
// content extent via a Range (stretched columns inflate scrollWidth and
|
|
841
|
+
// would invent phantom empty pages).
|
|
842
|
+
const master = document.createElement('div');
|
|
843
|
+
master.setAttribute('data-sg-measure', '');
|
|
844
|
+
// data-sg-doc-flow so the columnFlowResetCss media caps apply during the
|
|
845
|
+
// measure too (else a wide img/table overflows here and over-counts pages).
|
|
846
|
+
master.setAttribute('data-sg-doc-flow', '');
|
|
847
|
+
master.style.cssText = 'position:absolute;left:-99999px;top:0;visibility:hidden;height:' + CH + 'px;width:8000px;column-width:' + CW + 'px;column-gap:' + GAP + 'px;column-fill:auto;';
|
|
848
|
+
master.innerHTML = flowHtml;
|
|
849
|
+
document.body.appendChild(master);
|
|
850
|
+
const measure = () => {
|
|
851
|
+
const range = document.createRange();
|
|
852
|
+
range.selectNodeContents(master);
|
|
853
|
+
const right = range.getBoundingClientRect().right - master.getBoundingClientRect().left;
|
|
854
|
+
return Math.max(1, Math.ceil((right - 1) / PITCH));
|
|
855
|
+
};
|
|
856
|
+
let n = measure();
|
|
857
|
+
let exact = n * CW + (n - 1) * GAP;
|
|
858
|
+
master.style.width = exact + 'px';
|
|
859
|
+
master.style.columnCount = String(n);
|
|
860
|
+
n = measure();
|
|
861
|
+
exact = n * CW + (n - 1) * GAP;
|
|
862
|
+
document.body.removeChild(master);
|
|
863
|
+
const reported = [];
|
|
864
|
+
const startLeft = source.offsetLeft;
|
|
865
|
+
let cursorTop = source.offsetTop;
|
|
866
|
+
for (let i = 0; i < n; i++) {
|
|
867
|
+
const pid = id + '__p' + (i + 1);
|
|
868
|
+
const tile = document.createElement('section');
|
|
869
|
+
tile.setAttribute('data-sg-frame', '');
|
|
870
|
+
tile.setAttribute('data-sg-frame-id', pid);
|
|
871
|
+
tile.setAttribute('data-frame-layout', 'pages');
|
|
872
|
+
tile.setAttribute('data-sg-derived-from', id);
|
|
873
|
+
tile.setAttribute('data-sg-page', String(i + 1));
|
|
874
|
+
tile.setAttribute('role', 'group');
|
|
875
|
+
tile.setAttribute('aria-label', cfg.title + ' — page ' + (i + 1));
|
|
876
|
+
tile.style.width = PW + 'px';
|
|
877
|
+
tile.style.height = PH + 'px';
|
|
878
|
+
tile.style.background = cfg.background;
|
|
879
|
+
// PROMOTE (editor grid): place absolutely; the host's apply-layout
|
|
880
|
+
// refines with the same column math. Scroll modes leave the position to
|
|
881
|
+
// presentDocumentLayoutCss (margin:0 auto centering).
|
|
882
|
+
if (PROMOTE) { tile.style.left = startLeft + 'px'; tile.style.top = cursorTop + 'px'; cursorTop += PH + FRAME_GAP; }
|
|
883
|
+
const win = document.createElement('div');
|
|
884
|
+
win.setAttribute('data-sg-page-window', '');
|
|
885
|
+
win.style.cssText = 'position:absolute;overflow:hidden;top:' + m.top + 'px;left:' + m.left + 'px;width:' + CW + 'px;height:' + CH + 'px;';
|
|
886
|
+
const flow = document.createElement('div');
|
|
887
|
+
flow.setAttribute('data-sg-doc-flow', '');
|
|
888
|
+
flow.style.cssText = 'height:' + CH + 'px;width:' + exact + 'px;column-width:' + CW + 'px;column-gap:' + GAP + 'px;column-fill:auto;column-count:' + n + ';transform:translateX(' + (-i * PITCH) + 'px);';
|
|
889
|
+
flow.innerHTML = flowHtml;
|
|
890
|
+
// Clone hygiene: each tile holds a full clone of the flow, so author ids
|
|
891
|
+
// repeat across tiles. We do NOT strip them — the clones are IDENTICAL,
|
|
892
|
+
// so an SVG url(#grad)/href="#x" resolves to the first matching id (same
|
|
893
|
+
// gradient/anchor on every page); stripping would instead break a
|
|
894
|
+
// gradient's own def→fill reference WITHIN the clone. The host draws a11y
|
|
895
|
+
// from its own per-tile proxies, so duplicate ids don't reach the a11y tree.
|
|
896
|
+
win.appendChild(flow);
|
|
897
|
+
tile.appendChild(win);
|
|
898
|
+
addFurniture(tile, cfg.furniture || {}, i, n, m);
|
|
899
|
+
addPageNumber(tile, i, n, m, cfg.pageNumbers);
|
|
900
|
+
source.parentNode.insertBefore(tile, source);
|
|
901
|
+
reported.push({ id: pid, width: PW, height: PH });
|
|
902
|
+
}
|
|
903
|
+
source.parentNode.removeChild(source);
|
|
904
|
+
expansions.push({ sourceId: id, title: cfg.title, pages: reported });
|
|
905
|
+
} catch (error) {
|
|
906
|
+
console.error('Artifact column pagination failed for frame ' + id, error);
|
|
907
|
+
failed.push({ id: id, reason: String((error && error.message) || error) });
|
|
908
|
+
// Leave the source frame in place as an un-paginated single flow.
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
// A document's author CSS often sets a body background (the page color). The
|
|
913
|
+
// hoisted inline styles + the head shared CSS can paint the WHOLE hosted
|
|
914
|
+
// surface behind the tiles (the editor grid reads as a solid slab, present
|
|
915
|
+
// loses page separation). Re-assert the transparent canvas LAST so the tiles
|
|
916
|
+
// keep their own background and the gaps show the canvas. HOSTED_CANVAS only
|
|
917
|
+
// (host iframe: editor grid + live present); standalone export / PDF / PNG —
|
|
918
|
+
// where body IS the document backdrop — are untouched.
|
|
919
|
+
if (HOSTED_CANVAS) {
|
|
920
|
+
const canvasReset = document.createElement('style');
|
|
921
|
+
canvasReset.setAttribute('data-sg-canvas-reset', '');
|
|
922
|
+
canvasReset.textContent = 'html,body{background:transparent !important;}';
|
|
923
|
+
document.head.appendChild(canvasReset);
|
|
924
|
+
}
|
|
925
|
+
if (PROMOTE) {
|
|
926
|
+
// Renumber data-frame-index across all top-level frames in DOM order so
|
|
927
|
+
// selection's frameIndex stays consistent after the tiles replace the source.
|
|
928
|
+
Array.prototype.slice.call(document.querySelectorAll('[data-sg-frame]'))
|
|
929
|
+
.forEach((el, i) => el.setAttribute('data-frame-index', String(i)));
|
|
930
|
+
}
|
|
931
|
+
} finally {
|
|
932
|
+
finish();
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', () => { compose(); });
|
|
936
|
+
else compose();
|
|
937
|
+
})();`}function tn(e,t){let n=t.surface??(t.host===`iframe`?`editor`:`export`),r=n===`present`,i=jt(e),a=Pt(e),o=a&&n!==`editor`&&t.host===`iframe`,s=a&&t.host===`none`&&!!t.interactive,c=t.host===`none`&&!!t.interactive&&!a&&!i&&!Nt(e),l=r&&!i&&Nt(e),u=t.host===`none`&&!!t.interactive&&!i&&Nt(e),d=t.host===`none`&&!t.interactive&&!i&&Nt(e),f=l||u||d,p=ze(e.frames,{...t.layout,measuredHeights:t.measuredHeights}),m=tt(t.assets,t.baseHref?{allowBaseOrigin:t.baseHref}:void 0),h=e=>nt(e,t.assets),g=s?It(e):c?Ht(e):i?Mt(e):f?Gt(e):r&&!a?G(e):Et(e,p,t.host===`iframe`?t.colorScheme:void 0),_=s?Ft(e):null,v=s?Bt(_.width,_.height):c?Wt():r&&!l&&!a?At(e.artifactId):kt(e.artifactId,n,i,a),y=i?[]:qt(e),b=y.length>0&&(t.host===`iframe`||Nt(e))?y:[],ee=b.length?Yt(e):e,te=t.host===`iframe`&&!l,ne=[`<meta charset="utf-8">`,`<meta http-equiv="Content-Security-Policy" content="${m}">`,t.baseHref?`<base href="${B(t.baseHref)}">`:``,`<meta name="generator" content="Studiograph Artifact Canvas">`,`<title>${Be(e.title)}</title>`,ee.shared?.head??``,Tt(e.tokens),a?`<style data-artifact-whiteboard-tokens>${bt(t.colorScheme,t.host,s)}</style>`:``,W(ee),`<style data-artifact-frame-layout>\n${g}\n</style>`,o?`<style data-artifact-cursor>html,body{cursor:grab;}</style>`:``,b.length&&!f?`<style data-artifact-pagination>\n${$t()}\n</style>`:``,b.length?`<style data-artifact-columns-reset>\n${Zt()}\n</style>`:``,rt(e.libraries??[],t.librarySources),t.host===`iframe`||s||c?`<script data-artifact-runtime>${Ve(v)}<\/script>`:``].filter(Boolean).join(`
|
|
938
|
+
`),re=[Dt(ee,t.host===`none`&&r&&!f&&!a&&!i),s?zt():``,c?Ut():``,b.length?`<script data-artifact-pagination>${Ve(en(b,e.artifactId,te,t.renderId??``,t.host===`iframe`,e.display?.background))}<\/script>`:``,it(),Ot(e)].filter(Boolean).join(`
|
|
939
|
+
`);return h(`<!doctype html>
|
|
940
|
+
<html data-artifact-surface="${B(n)}">
|
|
941
|
+
<head>
|
|
942
|
+
${ne}
|
|
943
|
+
</head>
|
|
944
|
+
<body>
|
|
945
|
+
${re}
|
|
946
|
+
</body>
|
|
947
|
+
</html>`)}var nn={d3:()=>M(()=>import(`./CcWaWbrI2.js`),[],import.meta.url),motion:()=>M(()=>import(`./B9KfEsQw2.js`),[],import.meta.url),three:()=>M(()=>import(`./C1B4xDs0.js`),[],import.meta.url)},rn=()=>M(()=>import(`./rjjyuGhb.js`),[],import.meta.url),an={};async function on(e){let t={};for(let n of e)an[n]??=(await nn[n]()).default,t[n]=an[n],n===`three`&&(an.threeCore??=(await rn()).default,t.threeCore=an.threeCore);return t}var sn={otf:`font/otf`,ttf:`font/ttf`,woff:`font/woff`,woff2:`font/woff2`},cn=1500;function ln(e,t,n){return new Promise(r=>{let i=!1,a=e=>{i||(i=!0,clearTimeout(o),r(e))},o=setTimeout(()=>a(n),t);e.then(e=>a(e),()=>a(n))})}function un(e){return e.match(/\.(otf|ttf|woff2|woff)$/i)?.[1]?.toLowerCase()??null}var dn=new Map;function fn(e){let t=e.shared?.files;return t?Object.entries(t).filter(([e])=>e.toLowerCase().endsWith(`.css`)):[]}function pn(e){let t=new Map;for(let[,n]of fn(e))for(let e of Ge(n))un(e.filename)&&!t.has(e.key)&&t.set(e.key,e);return[...t.values()]}function mn(e){return pn(e).length>0}function hn(e){return e&&e.mode===`token`?e.token:null}function gn(e){let t=new Uint8Array(e),n=``,r=32768;for(let e=0;e<t.length;e+=r)n+=String.fromCharCode.apply(null,t.subarray(e,e+r));return btoa(n)}function _n(e,t){let n=dn.get(e.key);if(n)return n;let r=un(e.filename)??`otf`,i=`/api/assets/${e.assetId}/${We(e.filename)}`,a=t?Ke(i,t):i,o=(async()=>{try{let e=await fetch(a,{credentials:`include`});if(!e.ok)return null;let t=await e.arrayBuffer();return`data:${sn[r]??`font/otf`};base64,${gn(t)}`}catch{return null}})();return dn.set(e.key,o),o.then(t=>{t===null&&dn.delete(e.key)}),o}async function vn(e,t){let n=pn(e);if(n.length===0)return e;let r=hn(t),i=new Map;if(await Promise.all(n.map(async e=>{let t=await ln(_n(e,r),cn,null);t&&i.set(e.key,t)})),i.size===0)return e;let a={...e.shared?.files??{}};for(let[t,n]of fn(e))a[t]=qe(n,e=>i.get(e.key)??null);return{...e,shared:{...e.shared,files:a}}}function yn(e){return!!e.libraries?.length||xn(e)}function bn(e){return e.layout===`pages`&&typeof e.geometry.width==`number`&&typeof e.geometry.height==`number`}function xn(e){return e.frames.some(bn)}function Sn(e){return{host:`iframe`,surface:e.surface??`editor`,assets:e.assets,measuredHeights:e.measuredHeights,layout:e.layout,renderId:e.renderId,colorScheme:e.colorScheme}}function Cn(e,t={}){return tn(e,Sn(t))}async function wn(e,t={}){if(!yn(e))return Cn(e,t);let[n,r]=await Promise.all([e.libraries?.length?on(e.libraries):Promise.resolve(void 0),mn(e)?vn(e,t.assets):Promise.resolve(e)]);return tn(r,{...Sn(t),librarySources:n})}var Tn=1e6;function J(e){return typeof e!=`number`||!Number.isFinite(e)||Math.abs(e)>Tn?null:e}function Y(e,t){if(typeof e==`string`)return e.slice(0,t)}function En(e){if(!e||typeof e!=`object`)return null;let t=e,n=J(t.x),r=J(t.y),i=J(t.width),a=J(t.height);return n===null||r===null||i===null||a===null||i<0||a<0?null:{x:n,y:r,width:i,height:a}}function Dn(e){if(!e||typeof e!=`object`)return null;let t=e,n=En(t.rect),r=Y(t.selector,240),i=Y(t.tagName,40);if(!n||!r||!i)return null;let a=Y(t.frameId,120)??``,o=Y(t.text,240)??``,s=J(t.frameIndex);return{frameId:a,frameIndex:s!==null&&Number.isInteger(s)?s:-1,selector:r,tagName:i,text:o,rect:n,targetId:Y(t.targetId,280)||`${a}::${r}`.slice(0,280)}}function On(e,t){if(!e||typeof e!=`object`)return null;let n=e;if(n.channel!==`studiograph-artifact`||n.artifactId!==t)return null;if(n.type===`frame-sizes`){if(!Array.isArray(n.sizes))return null;let e=[];for(let t of n.sizes.slice(0,512)){if(!t||typeof t!=`object`)continue;let n=t,r=Y(n.id,128),i=J(n.width),a=J(n.height);!r||i===null||a===null||i<0||a<0||e.push({id:r,width:Math.round(i),height:Math.round(a)})}return{channel:`studiograph-artifact`,artifactId:t,type:`frame-sizes`,sizes:e}}if(n.type===`frame-pages`){if(!Array.isArray(n.expansions))return null;let e=[];for(let t of n.expansions.slice(0,64)){if(!t||typeof t!=`object`)continue;let n=t,r=Y(n.sourceId,128);if(!r||!Array.isArray(n.pages))continue;let i=Y(n.title,240)??``,a=[];for(let e of n.pages.slice(0,512)){if(!e||typeof e!=`object`)continue;let t=e,n=Y(t.id,160),r=J(t.width),i=J(t.height);!n||r===null||i===null||r<=0||i<=0||a.push({id:n,width:Math.round(r),height:Math.round(i)})}a.length&&e.push({sourceId:r,title:i,pages:a})}let r=Y(n.renderId,64),i=[];if(Array.isArray(n.failed))for(let e of n.failed.slice(0,64)){if(!e||typeof e!=`object`)continue;let t=e,n=Y(t.id,128);n&&i.push({id:n,reason:Y(t.reason,240)??``})}return{channel:`studiograph-artifact`,artifactId:t,type:`frame-pages`,...r?{renderId:r}:{},expansions:e,...i.length?{failed:i}:{}}}if(n.type===`selection-change`){if(!Array.isArray(n.targets))return null;let e=n.targets.slice(0,24).map(Dn).filter(e=>!!e),r=Array.isArray(n.path)?n.path.slice(0,24).map(e=>Y(e,60)).filter(e=>!!e):void 0;return{channel:`studiograph-artifact`,artifactId:t,type:`selection-change`,primaryTargetId:Y(n.primaryTargetId,280),targets:e,...r&&r.length?{path:r}:{}}}if(n.type===`clear-selection`)return{channel:`studiograph-artifact`,artifactId:t,type:`clear-selection`};if(n.type===`pan-delta`){let e=J(n.dx),r=J(n.dy);return e===null||r===null?null:{channel:`studiograph-artifact`,artifactId:t,type:`pan-delta`,dx:e,dy:r}}if(n.type===`zoom-delta`){let e=J(n.delta),r=J(n.x),i=J(n.y);return e===null||r===null||i===null?null:{channel:`studiograph-artifact`,artifactId:t,type:`zoom-delta`,delta:e,x:r,y:i}}if(n.type===`pan`){if(n.phase!==`start`&&n.phase!==`move`&&n.phase!==`end`)return null;let e=J(n.x),r=J(n.y);return e===null||r===null?null:{channel:`studiograph-artifact`,artifactId:t,type:`pan`,phase:n.phase,x:e,y:r}}if(n.type===`frame-state`){let e=J(n.index),r=J(n.count);return e===null||r===null||!Number.isInteger(e)||!Number.isInteger(r)||e<0||r<0?null:{channel:`studiograph-artifact`,artifactId:t,type:`frame-state`,index:e,count:r}}if(`type`in n||n.status!==`ready`&&n.status!==`error`)return null;let r={channel:`studiograph-artifact`,artifactId:t,status:n.status},i=Y(n.message,500);return i&&(r.message=i),r}async function kn(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,16)}var X={minZoom:.05,maxZoom:2,frameInset:32,framePadding:64,panInertiaImpulse:.08,panInertiaDecay:.84,panInertiaMaxVelocity:64,panInertiaStop:.08,panOverscanMin:32768,panOverscanViewportMultiplier:24};function Z(e,t,n){return Math.min(n,Math.max(t,e))}function An(e,t=X){return Math.min(t.maxZoom,Math.max(t.minZoom,Math.round(e*1e3)/1e3))}function jn(e,t,n,r=X){if(!n)return{x:r.frameInset,y:r.frameInset};let i=e.width*t,a=e.height*t;return{x:i+r.framePadding<=n.width?Math.max(r.frameInset,(n.width-i)/2):r.frameInset,y:a+r.framePadding<=n.height?Math.max(r.frameInset,(n.height-a)/2):r.frameInset}}function Mn(e,t,n=X){if(!t)return e.mode===`responsive`?.9:1;let r=Math.max(1,t.width-n.framePadding),i=Math.max(1,t.height-n.framePadding),a=Math.min(r/e.width,i/e.height);return An(Math.min(1,a),n)}function Nn(e,t,n,r=X){let i=jn(e,t,n,r),a=e.width*t,o=e.height*t,s=Math.max(r.panOverscanMin,n.width*r.panOverscanViewportMultiplier),c=Math.max(r.panOverscanMin,n.height*r.panOverscanViewportMultiplier);return{minX:-s-a-i.x,maxX:n.width+s-i.x,minY:-c-o-i.y,maxY:n.height+c-i.y}}function Pn(e,t,n,r,i,a=X){let o=Nn(n,r,i,a);return{x:Z(e,o.minX,o.maxX),y:Z(t,o.minY,o.maxY)}}function Fn(e,t){return e.width<=0||e.height<=0||t.width<=0||t.height<=0?1:Math.max(t.width/e.width,t.height/e.height)}function In(e,t,n,r,i){let a=(e,t,n)=>t>=n?Z(e,n-t,0):(n-t)/2;return{x:a(e,n.width*r,i.width),y:a(t,n.height*r,i.height)}}function Ln(e,t,n){let r=e.width*t,i=e.height*t;return{minX:r>=n.width?n.width-r:(n.width-r)/2,maxX:r>=n.width?0:(n.width-r)/2,minY:i>=n.height?n.height-i:(n.height-i)/2,maxY:i>=n.height?0:(n.height-i)/2}}function Rn(e,t,n){return{x:(n.width-e.width*t)/2,y:(n.height-e.height*t)/2}}function zn(e,t){return Math.max(1,Fn(e,t))}function Bn(e,t,n,r,i=X){return{velocityX:Z(e-n*i.panInertiaImpulse,-i.panInertiaMaxVelocity,i.panInertiaMaxVelocity),velocityY:Z(t-r*i.panInertiaImpulse,-i.panInertiaMaxVelocity,i.panInertiaMaxVelocity)}}function Vn(e,t,n=X){let r=e.velocityX*n.panInertiaDecay,i=e.velocityY*n.panInertiaDecay;if(Math.abs(r)<n.panInertiaStop&&Math.abs(i)<n.panInertiaStop)return{...e,velocityX:0,velocityY:0,active:!1};let a=Z(e.panX+r,t.minX,t.maxX),o=Z(e.panY+i,t.minY,t.maxY);Math.abs(a-e.panX)<.001&&(r=0),Math.abs(o-e.panY)<.001&&(i=0);let s=Math.abs(r)>=n.panInertiaStop||Math.abs(i)>=n.panInertiaStop;return{panX:a,panY:o,velocityX:r,velocityY:i,active:s}}function Hn(){return{front:`a`,a:{srcdoc:``,token:0},b:{srcdoc:``,token:0},pending:0}}var Un=e=>e===`a`?`b`:`a`,Q=(e,t)=>t===`a`?e.a:e.b;function Wn(e,t,n){return t===`a`?{...e,a:n}:{...e,b:n}}function Gn(e,t){if(t===``){if(Q(e,e.front).srcdoc===``)return{state:e,target:null,initial:!1};let t=e.pending+1;return{state:{...Wn(e,e.front,{srcdoc:``,token:t}),pending:t},target:e.front,initial:!0}}if(Q(e,e.front).srcdoc===t)return{state:e,target:null,initial:!1};let n=Un(e.front);if(Q(e,n).srcdoc===t&&Q(e,n).token===e.pending)return{state:e,target:null,initial:!1};let r=Q(e,e.front).srcdoc===``,i=r?e.front:n,a=e.pending+1;return{state:{...Wn(e,i,{srcdoc:t,token:a}),pending:a},target:i,initial:r}}function Kn(e,t){if(t===e.front||Q(e,t).srcdoc===``||Q(e,t).token!==e.pending)return{state:e,flipped:!1,dispose:null};let n=e.front;return{state:{...e,front:t},flipped:!0,dispose:n}}function qn(e,t){return e.front===t||Q(e,t).srcdoc===``||Q(e,t).token===e.pending?e:Wn(e,t,{...Q(e,t),srcdoc:``})}function Jn(e,t){return e?.status===`error`&&t.status===`ready`?e:{status:t.status,message:t.status===`error`?t.message??`Artifact error`:null}}var Yn=e(`<div class="fc-toolbar-pair svelte-1vhlljx" aria-label="Canvas tool"><button type="button" title="Select" aria-label="Select"><!></button> <button type="button" title="Pan" aria-label="Pan"><!></button></div>`),Xn=e(`<div class="fc-toolbar svelte-1vhlljx"><!> <button type="button" class="fc-tool-btn svelte-1vhlljx" title="Reset view" aria-label="Reset view"><!></button> <div class="fc-toolbar-sep svelte-1vhlljx" aria-hidden="true"></div> <div class="fc-toolbar-pair svelte-1vhlljx" aria-label="Zoom"><button type="button" class="fc-tool-btn svelte-1vhlljx" title="Zoom out" aria-label="Zoom out"><!></button> <button type="button" class="fc-tool-btn svelte-1vhlljx" title="Zoom in" aria-label="Zoom in"><!></button></div> <span class="fc-zoom svelte-1vhlljx"> </span></div>`),Zn=e(`<button type="button" class="fc-breadcrumb-up svelte-1vhlljx"><!> <span class="fc-breadcrumb-text svelte-1vhlljx"> </span></button>`),Qn=e(`<span class="fc-breadcrumb-seg fc-breadcrumb-current svelte-1vhlljx"> </span>`),$n=e(`<span class="fc-breadcrumb-seg fc-breadcrumb-current svelte-1vhlljx" aria-current="true"><span class="fc-breadcrumb-text svelte-1vhlljx"> </span></span>`),er=e(`<nav class="fc-breadcrumb svelte-1vhlljx" aria-label="Selection"><div class="fc-breadcrumb-path svelte-1vhlljx"><!></div> <span class="fc-breadcrumb-sep fc-breadcrumb-sep-end svelte-1vhlljx" aria-hidden="true"></span> <button type="button" class="fc-breadcrumb-clear svelte-1vhlljx" title="Clear selection" aria-label="Clear selection"><!></button></nav>`),tr=e(`<div class="fc-loading svelte-1vhlljx" role="status" aria-label="Loading artifact"><!></div>`),nr=e(`<div class="fc-paginate-hint svelte-1vhlljx" role="status">This document couldn’t be paginated — showing a single page.</div>`),rr=e(`<div class="fc-card svelte-1vhlljx"></div>`),ir=e(`<iframe sandbox="allow-scripts"></iframe> <iframe sandbox="allow-scripts"></iframe>`,1),ar=e(`<div class="fc-pulse svelte-1vhlljx"></div>`),or=e(`<div></div>`),sr=e(`<input class="fc-label fc-label-input svelte-1vhlljx"/>`),cr=e(`<button type="button" tabindex="-1"><span class="fc-label-num svelte-1vhlljx"> </span> <span class="fc-label-text svelte-1vhlljx"> </span></button>`),lr=e(`<!> <!> <!>`,1),ur=e(`<div class="fc-selection svelte-1vhlljx"></div>`),dr=e(`<div class="fc-proxy svelte-1vhlljx" role="option"></div>`),fr=e(`<div class="fc-a11y svelte-1vhlljx" role="listbox" aria-label="Artifact frames" tabindex="-1"></div>`),pr=e(`<div><div class="fc-present-group svelte-1vhlljx" aria-label="Frame navigation"><button type="button" class="fc-present-btn svelte-1vhlljx" title="Previous frame" aria-label="Previous frame"><!></button> <span class="fc-present-count svelte-1vhlljx"> </span> <button type="button" class="fc-present-btn svelte-1vhlljx" title="Next frame" aria-label="Next frame"><!></button></div> <div class="fc-present-group fc-present-reset svelte-1vhlljx" aria-label="Restart"><button type="button" class="fc-present-btn fc-present-restart svelte-1vhlljx" title="Restart" aria-label="Restart"><!> <span class="svelte-1vhlljx">Restart</span></button></div></div>`),mr=e(`<div class="fc svelte-1vhlljx"><div role="region" aria-label="Artifact canvas"><!> <!> <!> <!> <div><!> <!></div> <div aria-hidden="true"><!> <!></div> <!> <!></div></div>`),hr=e(`<div class="fc svelte-1vhlljx"><div class="fc-stage svelte-1vhlljx"><div class="fc-message svelte-1vhlljx" role="alert"><p class="svelte-1vhlljx">Artifact body could not be rendered.</p> <p class="fc-message-hint svelte-1vhlljx">Ask the agent to recreate this artifact.</p></div></div></div>`);function $(e,f){t(f,!0);let m=C(f,`showToolbar`,3,!0),h=C(f,`mode`,3,`editor`),v={rects:[],width:0,height:0,columns:0},y=X.frameInset,re=2400,w=A(void 0),ce=A(null);function O(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)|0;return(t>>>0).toString(36)}let M=A(1),N=A(0),P=A(0),Ce=A(!1),we=null,Ee=A(`pointer`),De=A(null),ke=A(null),F=A(x(Hn())),je=A(x({a:null,b:null})),I=A(x({a:{},b:{}})),L=A(x({a:{},b:{}})),R=A(x({a:!1,b:!1})),z=A(x({a:!1,b:!1})),Pe={a:``,b:``},Fe=null,Ie=0,Be=A(`loading`),B=A(!1),Ve=null,He=()=>typeof document<`u`&&document.documentElement.getAttribute(`data-theme`)===`dark`?`dark`:`light`,Ue=A(x(He())),V=A(x([])),H=A(x([])),We=A(x(new Set)),Ke=new Map,qe={},Je=A(0),Ye=A(0),Xe=A(x({})),Ze=A(!0),Qe=null,U=A(null),$e=A(0),et=0,tt=A(!1),nt=0,rt=0,it=0,at=0,ot=null,st=0,ct=0,lt=null,ut=0,dt=null,ft=A(null),pt=A(``),mt=A(null),ht=null,gt=null,_t=A(0),vt=A(null),yt=null,bt=null,xt=0,St=``;b(()=>{f.content!==St&&(St=f.content,j(vt,null),yt=null,bt=null,xt++)});let Ct=k(()=>g(vt)??f.content),wt=Promise.resolve();function Tt(e){wt=wt.then(e,e).catch(()=>{})}let W=k(()=>{try{let e=_e(JSON.parse(g(Ct)));return e.ok?e.bundle:null}catch{return null}}),Et=k(()=>(g($e),g(U)?{width:g(U).clientWidth,height:g(U).clientHeight}:{width:1280,height:800})),Dt=k(()=>!!g(W)&&jt(g(W))),Ot=k(()=>h()===`present`&&!!g(W)&&!g(Dt)&&Nt(g(W))),kt=k(()=>g(Dt)||g(Ot)),G=k(()=>!!g(W)&&Pt(g(W))),At=k(()=>h()===`editor`&&!g(G)&&g(V).length>0),Mt=k(()=>g(H).length>=2?g(H).slice(0,-1).map((e,t)=>({label:e,index:t})).reverse():[]),Ft=k(()=>g(G)&&h()===`present`?`hand`:g(Ee)),K=k(()=>!g(kt)&&(h()===`editor`||g(G))),It=k(()=>h()===`editor`&&!!f.repo&&!!f.entityId&&!f.versionCommit&&!g(Dt));function Lt(e,t){let n=[];for(let r of e){let e=t[r.id],i=e&&bn(r)?e.pages.filter(e=>e.id.startsWith(`${r.id}__p`)).slice(0,500):[];i.length?i.forEach((t,i)=>{n.push({...r,id:t.id,title:`${r.title||e.title||`Document`} · ${i+1}`,geometry:{...r.geometry},content:``,furniture:void 0})}):n.push(r)}return n}let Rt=k(()=>g(W)?Lt(g(W).frames,g(L).a):[]),zt=k(()=>g(W)?Lt(g(W).frames,g(L).b):[]),Bt=k(()=>g(F).front===`a`?g(Rt):g(zt)),Vt=k(()=>g(F).front===`a`?g(z).a:g(z).b),Ht=k(()=>g(W)?ze(g(Rt),{measuredHeights:g(I).a,viewport:g(Et)}):v),Ut=k(()=>g(W)?ze(g(zt),{measuredHeights:g(I).b,viewport:g(Et)}):v),Wt=k(()=>g(F).front===`a`?g(Ht):g(Ut)),Gt=k(()=>({width:g(Wt).width,height:g(Wt).height})),Kt=k(()=>g(F).a.srcdoc!==``||g(F).b.srcdoc!==``),qt=k(()=>g(Wt).rects.length),Jt=k(()=>g(G)?Fn(g(Gt),g(Et)):X.minZoom),Yt=k(()=>g(G)?g(Jt):X.minZoom),Xt=k(()=>g(G)?Math.max(X.maxZoom,g(Jt)):X.maxZoom),Zt=k(()=>Z(g(Ye),0,Math.max(0,g(qt)-1))),Qt=k(()=>{let e=g(Bt)[g(Zt)];return e?{width:Le(e,g(Et)),height:Re(e,g(Xe),void 0,g(Et))}:{width:1,height:1}}),$t=k(()=>{if(g($e),h()!==`present`||!g(U))return{scale:1,tx:0,ty:0};let{width:e,height:t}=g(Qt),n=Z(Math.min((g(U).clientWidth-48)/e,(g(U).clientHeight-48)/t),.05,6);return{scale:n,tx:(g(U).clientWidth-e*n)/2,ty:(g(U).clientHeight-t*n)/2}}),q=k(()=>g(kt)?1:g(K)?g(M):g($t).scale),en=k(()=>(g($e),g(G)||g(kt)?{x:0,y:0}:g(U)?jn(g(Gt),g(q),{width:g(U).clientWidth,height:g(U).clientHeight}):{x:y,y})),tn=k(()=>g(kt)?0:g(en).x+g(N)),nn=k(()=>g(kt)?0:g(en).y+g(P)),rn=k(()=>g(kt)?`translate(0px, 0px) scale(1)`:g(K)?`translate(${g(tn)}px, ${g(nn)}px) scale(${g(q)})`:`translate(${g($t).tx}px, ${g($t).ty}px) scale(${g($t).scale})`),an=e=>g(kt)?{width:g(Et).width,height:g(Et).height}:g(K)?{width:e.width,height:e.height}:{width:g(Qt).width,height:g(Qt).height},on=k(()=>h()===`editor`&&!!g(W)&&!g(B)&&g(Be)!==`error`),sn=k(()=>`${Math.round(g(q)*100)}%`),cn=k(()=>g(W)?.display?.background??`neutral`),ln=k(()=>{if(g($e),!g(W)||g(G))return[];let e=g(W).display?.background??`neutral`;return g(Wt).rects.map((t,n)=>{let r=g(Bt)[n];return{id:t.id,index:n,label:r?.title||`Frame ${n+1}`,transparent:(r?.background??e)===`transparent`,selected:g(V).some(e=>e.frameId===t.id&&wr(e)),cx:t.x,cy:t.y,cw:t.width,ch:t.height,left:g(tn)+t.x*g(q),top:g(nn)+t.y*g(q),width:t.width*g(q),height:t.height*g(q),pulsing:g(We).has(t.id)}})}),un=k(()=>(g($e),!g(W)||h()!==`editor`||g(V).length===0?[]:g(V).filter(e=>!wr(e)).map(e=>({key:e.targetId,left:g(tn)+e.rect.x*g(q),top:g(nn)+e.rect.y*g(q),width:Math.max(1,e.rect.width*g(q)),height:Math.max(1,e.rect.height*g(q))})))),dn=()=>f.shareToken?{mode:`share`,shareToken:f.shareToken,origin:window.location.origin}:f.repo&&f.entityId?{mode:`token`,token:g(w)??null,origin:window.location.origin}:{mode:`none`},fn=k(()=>Ge(f.content).length>0);b(()=>{if(!f.repo||!f.entityId||!g(fn)){j(w,void 0),j(ce,null);return}let e=f.versionCommit??O(f.content),t=f.repo,n=f.entityId,r=f.versionCommit,i=!1;return he(t,n,{version:e,commit:r}).then(t=>{i||(j(w,t,!0),j(ce,e,!0))}).catch(()=>{i||(j(w,void 0),j(ce,e,!0))}),()=>{i=!0}});let pn=k(()=>!f.shareToken&&!!f.repo&&!!f.entityId&&g(fn)&&g(ce)!==(f.versionCommit??O(f.content)));b(()=>{if(!g(W))return;j(Be,`loading`);let e=f.viewKey??g(W).artifactId;e!==ht&&(j(F,Hn(),!0),j(je,{a:null,b:null},!0),j(I,{a:{},b:{}},!0),j(L,{a:{},b:{}},!0),j(R,{a:!1,b:!1},!0),j(z,{a:!1,b:!1},!0),Fe&&=(clearTimeout(Fe),null),ht=e,j(N,0),j(P,0),j(Ce,!1),we=null,j(Ye,0),j(Xe,{},!0),j(Ze,!0),Q(),j(Je,0),j(We,new Set,!0),qe={},j(B,h()!==`editor`),ni(),Qr(),si(),vn(),j(M,te(()=>mn()),!0))}),b(()=>{if(!g(G)||!g(U))return;g($e);let e=g(Gt),t={width:g(U).clientWidth,height:g(U).clientHeight};t.width<=0||t.height<=0||te(()=>{if(g(Ce)){let n=Fn(e,t),r=Z(g(M),n,Math.max(X.maxZoom,n));r!==g(M)&&j(M,r,!0);let i=In(g(N),g(P),e,g(M),t);j(N,i.x,!0),j(P,i.y,!0)}else{let n=zn(e,t);j(M,n,!0);let r=Rn(e,n,t);j(N,r.x,!0),j(P,r.y,!0)}})}),b(()=>{let e=g(W),t=++Ie;if(!e){Br(``);return}if(g(pn))return;let n=String(t),r={surface:h()===`present`?`present`:`editor`,assets:dn(),renderId:n,colorScheme:g(G)?g(Ue):void 0};if(!yn(e)){Br(Cn(e,r),n);return}let i=!1;return wn(e,r).then(r=>{!i&&Ie===t&&g(W)?.artifactId===e.artifactId&&Br(r,n)}).catch(e=>{i||(j(Be,`error`),console.error(`Artifact resources failed to load`,e))}),()=>{i=!0}}),b(()=>{let e=f.content;gt!==null&&e!==gt&&(j(_t,g(_t)+1),Q(!0)),gt=e}),b(()=>{if(typeof document>`u`)return;j(Ue,He(),!0);let e=new MutationObserver(()=>{j(Ue,He(),!0)});return e.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),()=>e.disconnect()}),b(()=>{if(!g(U))return;let e=new ResizeObserver(()=>{et+=1,j($e,et,!0)});return e.observe(g(U)),et+=1,j($e,et,!0),()=>e.disconnect()}),b(()=>()=>{ni(),Qr(),_i(),vn(),Fe&&clearTimeout(Fe),Qe&&clearTimeout(Qe);for(let e of Ke.values())clearTimeout(e);Ke.clear()});function mn(){if(!g(U))return 1;let e={width:g(U).clientWidth,height:g(U).clientHeight};return Mn(g(Gt),e)}function hn(){h()!==`editor`||g(G)||(j(M,mn(),!0),j(N,0),j(P,0),j(Ce,!1),ni(),Qr())}function gn(){if(ni(),Qr(),g(G)){j(Ce,!1);let e=Gr();if(e){let t=zn(g(Gt),e);j(M,t,!0);let n=Rn(g(Gt),t,e);j(N,n.x,!0),j(P,n.y,!0)}return}hn()}function _n(){g(B)||(vn(),g(Ce)||hn(),j(B,!0))}function vn(){Ve&&=(clearTimeout(Ve),null)}function xn(){if(h()!==`editor`||g(B)||!g(Kt))return;vn();let e=Sn(g(F).front)?4e3:1200;Ve=setTimeout(()=>{Ve=null,_n()},e)}function Sn(e){return!g(W)||g(R)[e]?!1:g(W).frames.some(bn)}function Tn(){if(!g(B)){if(Sn(g(F).front)){xn();return}_n()}}function J(e){if(!g(W))return;let t=ze(Lt(g(W).frames,g(L)[e]),{measuredHeights:g(I)[e],viewport:g(Et)});if(Ur(e,{type:`apply-layout`,rects:t.rects.map(e=>({id:e.id,x:e.x,y:e.y,width:e.width})),width:t.width,height:t.height}),e===g(F).front){if(!g(Ce)){hn();return}En(t)}}function Y(){if(!g(U))return null;let e=g(q)||1,t=(g(U).clientWidth/2-g(tn))/e,n=(g(U).clientHeight/2-g(nn))/e,r=null,i=1/0;for(let e of g(Wt).rects){if(t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height)return e.id;let a=e.x+e.width/2-t,o=e.y+e.height/2-n,s=a*a+o*o;s<i&&(i=s,r=e.id)}return r}function En(e){let t=we;if(!t||!g(U))return;let n=e.rects.find(e=>e.id===t);if(!n)return;we=null;let r={width:g(U).clientWidth,height:g(U).clientHeight},i=g(q)||1,a=jn({width:e.width,height:e.height},i,r);j(N,r.width/2-a.x-(n.x+n.width/2)*i),j(P,r.height/2-a.y-(n.y+n.height/2)*i),ni(),Qr()}function Dn(e,t){if(!g(W))return;let n={...g(L)[e]};for(let e of t){let t=g(W).frames.find(t=>t.id===e.sourceId);!t||t.layout!==`pages`||(n[e.sourceId]=e)}j(L,e===`a`?{...g(L),a:n}:{...g(L),b:n},!0),j(R,e===`a`?{...g(R),a:!0}:{...g(R),b:!0},!0),h()===`editor`?J(e):Ur(e,{type:`set-frame`,index:g(Zt)}),e===g(F).front&&Tn()}b(()=>{h()!==`editor`||g(B)||!g(Kt)||Ve||xn()});function Un(e){g(Ee)!==e&&(j(Ee,e,!0),Wr({type:`set-tool`,tool:e}),si(),ni(),Qr())}function Q(e=!1){j(V,[],!0),j(H,[],!0),me.setSelectedArtifactTarget(null),yr([]),e&&Wr({type:`clear-selection`})}let Wn,$=null,gr;function _r(e){gr?.abort(),gr=new AbortController,e(gr.signal).catch(()=>{})}function vr(e,t){$&&$.repo===e&&$.id===t&&($=null),_r(n=>fe(e,t,n))}function yr(e,t,n){if(h()!==`editor`||!f.repo||!f.entityId)return;let r=f.repo,i=f.entityId;Wn&&clearTimeout(Wn),Wn=setTimeout(()=>{if(e.length===0){vr(r,i);return}$={repo:r,id:i};let a={targets:e.map(e=>({frameId:e.frameId,frameIndex:e.frameIndex,selector:e.selector,tagName:e.tagName,text:e.text})),...n?{primaryTargetId:n}:{},...t&&t.length?{path:t}:{}};_r(e=>pe(r,i,a,e))},300)}b(()=>{let e=f.repo,t=f.entityId;te(()=>{if($&&($.repo!==e||$.id!==t)){let e=$;vr(e.repo,e.id)}})}),oe(()=>{if(Wn&&clearTimeout(Wn),$){let e=$;vr(e.repo,e.id)}});function br(e){e<0||e>=g(H).length-1||Wr({type:`select-ancestor`,index:e})}function xr(e){let t=e.text?.trim();return`- ${[t?t.length>60?`${t.slice(0,57)}...`:t:e.tagName,e.frameId?`frame=${e.frameId}`:e.frameIndex>=0?`frame=${e.frameIndex+1}`:null,e.selector?`selector=${e.selector}`:null,t?`text="${t}"`:null,`${Math.round(e.rect.width)}x${Math.round(e.rect.height)}`].filter(Boolean).join(` · `)}`}function Sr(e,t,n){if(!g(W)||h()!==`editor`)return;if(j(V,e,!0),j(H,e.length===1&&t?t:[],!0),yr(e,g(H),n),e.length===0){me.setSelectedArtifactTarget(null);return}let r=`${e.length} selected\n${e.map(xr).join(`
|
|
948
|
+
`)}`.slice(0,1600);me.setSelectedArtifactTarget(r)}let Cr=e=>`[data-sg-frame-id="${e}"]`,wr=e=>e.selector===Cr(e.frameId);function Tr(e){if(!g(W)||h()!==`editor`)return;let t=g(Wt).rects[e],n=g(Bt)[e];!t||!n||Sr([{frameId:n.id,frameIndex:e,selector:Cr(n.id),tagName:`section`,text:n.title??``,rect:{x:t.x,y:t.y,width:t.width,height:t.height},targetId:`${n.id}::${Cr(n.id)}`}])}async function Er(e,t,n,r,i,a,o,s){if(e===xt)try{let o=await de(r,i,yt??await kn(t),a);if(e!==xt)return;yt=o.hash,bt=n}catch(t){e===xt&&(xt++,j(vt,bt,!0),bt===null&&(yt=null));let n=t?.status;ge.error(n===409?o:s)}}function Dr(e){let t=g(Bt)[e]?.id;return!t||!g(W)?null:g(W).frames.some(e=>e.id===t)?t:null}function Or(e){if(!g(It)||!g(W))return;let t=Dr(e);t&&(j(ft,e,!0),j(pt,g(W).frames.find(e=>e.id===t)?.title??``,!0))}function kr(){j(ft,null),j(pt,``)}b(()=>{g(ft)!==null&&g(mt)&&(g(mt).focus(),g(mt).select())});function Ar(){let e=g(ft);if(e===null||!g(W)||!f.repo||!f.entityId){kr();return}let t=Dr(e),n=t?g(W).frames.find(e=>e.id===t):void 0;if(!t||!n){kr();return}let r=g(pt).trim(),i=n.title??``;if(j(ft,null),j(pt,``),r===i)return;let a=g(W).frames.map(e=>e.id===t?(()=>{let t={...e};return r?t.title=r:delete t.title,t})():e),o=f.content,s=JSON.stringify({...g(W),frames:a},null,2)+`
|
|
949
|
+
`;j(vt,s);let c=f.repo,l=f.entityId,u=xt;Tt(()=>Er(u,o,s,c,l,[{op:`set_frame_meta`,frameId:t,title:r}],`This artifact changed elsewhere — the rename was not applied.`,`Could not rename the frame.`))}function jr(e){e.key===`Enter`?(e.preventDefault(),Ar()):e.key===`Escape`&&(e.preventDefault(),kr())}function Mr(){if(!g(W))return;let e={};for(let t of g(W).frames)e[t.id]=O(t.content);let t=typeof window<`u`&&window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches;if(Object.keys(qe).length>0&&!t)for(let[t,n]of Object.entries(e))qe[t]!==n&&Nr(t);qe=e}function Nr(e){let t=new Set(g(We));t.add(e),j(We,t,!0);let n=Ke.get(e);n&&clearTimeout(n),Ke.set(e,setTimeout(()=>{let t=new Set(g(We));t.delete(e),j(We,t,!0),Ke.delete(e)},re))}function Pr(e){return e&&g(De)?.contentWindow===e?`a`:e&&g(ke)?.contentWindow===e?`b`:null}function Fr(e){let t=g(W);if(!t)return;let n=Pr(e.source);if(!n)return;let r=On(e.data,t.artifactId);if(r){if(!(`type`in r)){Rr(n,Jn(g(je)[n],{status:r.status,message:r.message})),n===g(F).front&&zr(n);return}if(r.type===`frame-sizes`){h()===`present`?Ir(r.sizes):Lr(n,r.sizes);return}if(r.type===`frame-pages`){if(r.renderId&&r.renderId!==Pe[n])return;Dn(n,r.expansions);let e=!!(r.failed&&r.failed.length>0);j(z,n===`a`?{...g(z),a:e}:{...g(z),b:e},!0);return}if(n===g(F).front){if(r.type===`frame-state`){j(Ye,Z(r.index,0,Math.max(0,r.count-1)),!0),xi();return}if(r.type===`selection-change`){Sr(r.targets,r.path,r.primaryTargetId);return}if(r.type===`clear-selection`){Q();return}if(r.type===`pan-delta`){ti(r.dx,r.dy,{inertial:!0});return}if(r.type===`zoom-delta`){Zr(r.delta,qr(r.x,r.y));return}if(r.type===`pan`){ci(r.phase,r.x,r.y);return}}}}function Ir(e){let t={...g(Xe)},n=!1;for(let r of e)r.height>0&&t[r.id]!==r.height&&(t[r.id]=r.height,n=!0);n&&j(Xe,t,!0)}function Lr(e,t){if(!g(W))return;let n=new Set(g(W).frames.filter(e=>e.geometry.height===`auto`).map(e=>e.id)),r={...g(I)[e]},i=!1;for(let e of t)n.has(e.id)&&r[e.id]!==e.height&&(r[e.id]=e.height,i=!0);i&&(j(I,e===`a`?{...g(I),a:r}:{...g(I),b:r},!0),J(e))}function Rr(e,t){j(je,e===`a`?{...g(je),a:t}:{...g(je),b:t},!0)}function zr(e){let t=e===`a`?g(je).a:g(je).b;j(Be,t?t.status:`ready`,!0),g(B)||(g(Be)===`error`?_n():Tn())}function Br(e,t=``){we=h()===`editor`&&g(B)&&g(Ce)&&e!==``&&Object.keys(g(L)[g(F).front]??{}).length>0?Y():null;let n=Gn(g(F),e);if(n.target===null){e!==``&&zr(g(F).front);return}Rr(n.target,null),j(I,n.target===`a`?{...g(I),a:{}}:{...g(I),b:{}},!0),j(L,n.target===`a`?{...g(L),a:{}}:{...g(L),b:{}},!0),j(R,n.target===`a`?{...g(R),a:!1}:{...g(R),b:!1},!0),j(z,n.target===`a`?{...g(z),a:!1}:{...g(z),b:!1},!0),Pe=n.target===`a`?{...Pe,a:t}:{...Pe,b:t},j(F,n.state,!0)}function Vr(e){let t=Kn(g(F),e);j(F,t.state,!0),t.flipped?(zr(e),Wr({type:`set-tool`,tool:g(Ft)}),Mr(),Tn(),g(R)[e]&&J(e),t.dispose&&Hr(t.dispose)):e===t.state.front&&(t.state.front===`a`?t.state.a:t.state.b).srcdoc!==``&&(zr(e),Wr({type:`set-tool`,tool:g(Ft)}),Mr(),Tn())}function Hr(e){Fe&&clearTimeout(Fe),Fe=setTimeout(()=>{Fe=null;let t=qn(g(F),e),n=t!==g(F);j(F,t,!0),n&&(Rr(e,null),j(I,e===`a`?{...g(I),a:{}}:{...g(I),b:{}},!0),j(L,e===`a`?{...g(L),a:{}}:{...g(L),b:{}},!0),j(R,e===`a`?{...g(R),a:!1}:{...g(R),b:!1},!0),j(z,e===`a`?{...g(z),a:!1}:{...g(z),b:!1},!0))},280)}function Ur(e,t){let n=g(W),r=g(e===`a`?De:ke);!n||!r?.contentWindow||r.contentWindow.postMessage({channel:`studiograph-artifact-host`,artifactId:n.artifactId,...t},`*`)}function Wr(e){Ur(g(F).front,e)}function Gr(){return g(U)?{width:g(U).clientWidth,height:g(U).clientHeight}:null}function Kr(e,t){let n=Gr();return!n||!g(K)?{x:e,y:t}:g(G)?In(e,t,g(Gt),g(M),n):Pn(e,t,g(Gt),g(M),n)}function qr(e,t){return g(K)?{x:g(tn)+e*g(M),y:g(nn)+t*g(M)}:null}function Jr(){return g(U)?{x:g(U).clientWidth/2,y:g(U).clientHeight/2}:null}function Yr(e,t=Jr()){let n=An(e,{minZoom:g(Yt),maxZoom:g(Xt)});if(Math.abs(n-g(M))<5e-4)return;j(Ce,!0);let r=Gr();if(!r||!g(K)||!t){j(M,n,!0);return}let i=e=>g(G)?{x:0,y:0}:jn(g(Gt),e,r),a=i(g(M)),o=(t.x-a.x-g(N))/g(M),s=(t.y-a.y-g(P))/g(M),c=i(n);j(M,n,!0);let l=Kr(t.x-c.x-o*n,t.y-c.y-s*n);j(N,l.x,!0),j(P,l.y,!0)}function Xr(e,t=Jr()){Yr(g(M)*Math.exp(-e*.006),t)}function Zr(e,t=Jr()){g(K)&&(ni(),Xr(e,t),ei(e,t))}function Qr(){lt!==null&&(cancelAnimationFrame(lt),lt=null),ut=0,dt=null}function $r(){if(ut*=.86,Math.abs(ut)<.08||g(M)<=g(Yt)||g(M)>=X.maxZoom||!g(K)){Qr();return}Xr(ut,dt),lt=requestAnimationFrame($r)}function ei(e,t){g(K)&&(dt=t,ut=Z(ut+e*.16,-18,18),lt===null&&(lt=requestAnimationFrame($r)))}function ti(e,t,n={}){if(!g(K))return;j(Ce,!0);let r=Kr(g(N)-e,g(P)-t);j(N,r.x,!0),j(P,r.y,!0),n.inertial&&ii(e,t)}function ni(){ot!==null&&(cancelAnimationFrame(ot),ot=null),st=0,ct=0}function ri(){let e=Gr();if(!g(K)||!e){ni();return}let t=Vn({panX:g(N),panY:g(P),velocityX:st,velocityY:ct},g(G)?Ln(g(Gt),g(M),e):Nn(g(Gt),g(M),e));if(j(N,t.panX,!0),j(P,t.panY,!0),st=t.velocityX,ct=t.velocityY,!t.active){ni();return}ot=requestAnimationFrame(ri)}function ii(e,t){let n=Bn(st,ct,e,t);st=n.velocityX,ct=n.velocityY,ot===null&&(ot=requestAnimationFrame(ri))}function ai(e,t){ni(),Qr(),j(tt,!0),nt=e,rt=t,it=g(N),at=g(P)}function oi(e,t){if(!g(tt))return;let n=Kr(it+(e-nt),at+(t-rt));j(N,n.x,!0),j(P,n.y,!0),j(Ce,!0)}function si(){j(tt,!1)}function ci(e,t,n){!g(K)||g(Ft)!==`hand`||(e===`start`?ai(t,n):e===`move`?oi(t,n):si())}let li=null,ui=null,di=null,fi=null;function pi(e){let t=e.deltaMode===1?16:e.deltaMode===2?g(U)?.clientHeight??window.innerHeight:1;return{dx:e.deltaX*t,dy:e.deltaY*t}}function mi(e){if(!g(K))return;let t=pi(e);if(!(Math.abs(t.dx)<.01&&Math.abs(t.dy)<.01)){if(e.ctrlKey||e.metaKey){di=di?{delta:di.delta+t.dy,clientX:e.clientX,clientY:e.clientY}:{delta:t.dy,clientX:e.clientX,clientY:e.clientY},fi===null&&(fi=requestAnimationFrame(gi)),e.preventDefault();return}li=li?{dx:li.dx+t.dx,dy:li.dy+t.dy}:{dx:t.dx,dy:t.dy},ui===null&&(ui=requestAnimationFrame(hi)),e.preventDefault()}}function hi(){if(ui=null,!li)return;let e=li;li=null,ti(e.dx,e.dy,{inertial:!0})}function gi(){if(fi=null,!di)return;let e=di;di=null;let t=g(U)?.getBoundingClientRect();Zr(e.delta,t?{x:e.clientX-t.left,y:e.clientY-t.top}:null)}function _i(){ui!==null&&(cancelAnimationFrame(ui),ui=null),li=null,fi!==null&&(cancelAnimationFrame(fi),fi=null),di=null}function vi(e){let t=e.target;h()===`editor`&&!t?.closest(`.fc-viewport`)&&!t?.closest(`.fc-toolbar`)&&Q(!0),!(!g(K)||g(Ft)!==`hand`||e.button!==0)&&(ai(e.clientX,e.clientY),e.currentTarget.setPointerCapture(e.pointerId),e.preventDefault())}function yi(e){h()===`present`&&xi(),oi(e.clientX,e.clientY),g(tt)&&e.preventDefault()}function bi(e){if(!g(tt))return;let t=e.currentTarget;t.hasPointerCapture(e.pointerId)&&t.releasePointerCapture(e.pointerId),si()}function xi(){h()===`present`&&(j(Ze,!0),Qe&&clearTimeout(Qe),Qe=setTimeout(()=>{j(Ze,!1),Qe=null},2500))}function Si(e){h()!==`present`||g(qt)<=1||(Wr({type:`set-frame`,index:(g(Zt)+e+g(qt))%g(qt)}),xi())}function Ci(e){h()===`present`&&(Wr({type:`set-frame`,index:Z(Math.round(e),0,Math.max(0,g(qt)-1))}),xi())}b(()=>{h()===`present`&&g(W)&&xi()});function wi(e){if(h()===`editor`&&e.key===`Escape`&&g(V).length>0){Q(!0),e.preventDefault();return}h()!==`present`||g(Ot)||g(qt)<=1||e.target?.closest(`input,textarea,select,[contenteditable="true"]`)||e.altKey||e.ctrlKey||e.metaKey||(e.key===`ArrowRight`||e.key===`PageDown`||e.key===` `?(Si(1),e.preventDefault()):e.key===`ArrowLeft`||e.key===`PageUp`?(Si(-1),e.preventDefault()):e.key===`Home`?(Ci(0),e.preventDefault()):e.key===`End`&&(Ci(g(qt)-1),e.preventDefault()))}function Ti(e){if(!g(W)||h()!==`editor`)return;let t=g(Wt).rects.length,n=Math.max(1,g(Wt).columns),r=g(Je);if(e.key===`ArrowRight`)r=Math.min(t-1,g(Je)+1);else if(e.key===`ArrowLeft`)r=Math.max(0,g(Je)-1);else if(e.key===`ArrowDown`)r=Math.min(t-1,g(Je)+n);else if(e.key===`ArrowUp`)r=Math.max(0,g(Je)-n);else if(e.key===`Enter`||e.key===` `){Tr(g(Je)),e.preventDefault();return}else return;e.preventDefault(),j(Je,r,!0),document.getElementById(`fc-proxy-${r}`)?.focus()}var Ei=ue();o(`message`,ne,Fr),o(`keydown`,ne,wi);var Di=ae(Ei),Oi=e=>{var t=mr(),c=T(t);let f;var v=T(c),y=e=>{var t=Xn(),a=T(t),c=e=>{var t=Yn(),i=T(t);let a;Te(T(i),{size:16}),r(i);var o=S(i,2);let s;Oe(T(o),{size:16}),r(o),r(t),E(()=>{a=u(i,1,`fc-tool-btn svelte-1vhlljx`,null,a,{active:g(Ft)===`pointer`}),D(i,`aria-pressed`,g(Ft)===`pointer`),s=u(o,1,`fc-tool-btn svelte-1vhlljx`,null,s,{active:g(Ft)===`hand`}),D(o,`aria-pressed`,g(Ft)===`hand`)}),n(`click`,i,()=>Un(`pointer`)),n(`click`,o,()=>Un(`hand`)),l(e,t)};s(a,e=>{h()===`editor`&&e(c)});var d=S(a,2);Ae(T(d),{size:16}),r(d);var f=S(d,4),p=T(f);Ne(T(p),{size:16}),r(p);var m=S(p,2);Me(T(m),{size:16}),r(m),r(f);var _=S(f,2),v=T(_,!0);r(_),r(t),E(()=>i(v,g(sn))),n(`pointerdown`,t,e=>e.stopPropagation()),o(`wheel`,t,e=>e.stopPropagation()),n(`click`,d,gn),n(`click`,p,()=>Yr(g(M)-.1)),n(`click`,m,()=>Yr(g(M)+.1)),l(e,t)};s(v,e=>{m()&&!g(Dt)&&(h()===`editor`||g(G))&&!g(At)&&e(y)});var b=S(v,2),te=e=>{var t=er(),a=T(t),c=T(a),u=e=>{var t=ue();ie(ae(t),17,()=>g(Mt),e=>e.index,(e,t)=>{var a=Zn(),o=T(a);be(o,{size:16});var s=S(o,2),c=T(s,!0);r(s),d(s,e=>Se?.(e)),r(a),E(()=>{D(a,`title`,`Select ${g(t).label}`),i(c,g(t).label)}),n(`click`,a,()=>br(g(t).index)),l(e,a)}),l(e,t)},f=e=>{var t=Qn(),n=T(t);r(t),E(()=>i(n,`${g(V).length??``} selected`)),l(e,t)},p=e=>{var t=$n(),n=T(t),a=T(n,!0);r(n),d(n,e=>Se?.(e)),r(t),E(()=>i(a,g(H)[g(H).length-1])),l(e,t)};s(c,e=>{g(H).length>=2?e(u):g(H).length===0?e(f,1):e(p,-1)}),r(a);var m=S(a,4);ye(T(m),{size:14}),r(m),r(t),n(`pointerdown`,t,e=>e.stopPropagation()),o(`wheel`,t,e=>e.stopPropagation()),n(`click`,m,()=>Q(!0)),l(e,t)};s(b,e=>{g(At)&&e(te)});var ne=S(b,2),x=e=>{var t=tr();ve(T(t),{size:28}),r(t),l(e,t)};s(ne,e=>{g(on)&&e(x)});var oe=S(ne,2),C=e=>{l(e,nr())};s(oe,e=>{g(Vt)&&g(B)&&h()===`editor`&&e(C)});var w=S(oe,2);let ce,O;var k=T(w),A=e=>{var t=ue();ie(ae(t),17,()=>g(ln),e=>e.id,(e,t)=>{var n=ue(),r=ae(n),i=e=>{var n=rr();let r;E(()=>r=le(n,``,r,{left:`${g(t).cx}px`,top:`${g(t).cy}px`,width:`${g(t).cw}px`,height:`${g(t).ch}px`})),l(e,n)};s(r,e=>{g(t).transparent||e(i)}),l(e,n)}),l(e,t)};s(k,e=>{h()===`editor`&&!g(Dt)&&e(A)});var de=S(k,2),fe=e=>{var t=ir(),n=ae(t);let r,i;ee(n,e=>j(De,e),()=>g(De));var s=S(n,2);let c,d;ee(s,e=>j(ke,e),()=>g(ke)),E((e,t)=>{D(n,`title`,g(W).title),r=u(n,1,`fc-frame svelte-1vhlljx`,null,r,{"is-back":g(F).front!==`a`}),D(n,`aria-hidden`,g(F).front!==`a`),D(n,`srcdoc`,g(F).a.srcdoc),i=le(n,``,i,e),D(s,`title`,g(W).title),c=u(s,1,`fc-frame svelte-1vhlljx`,null,c,{"is-back":g(F).front!==`b`}),D(s,`aria-hidden`,g(F).front!==`b`),D(s,`srcdoc`,g(F).b.srcdoc),d=le(s,``,d,t)},[()=>({width:`${Math.max(1,an(g(Ht)).width)}px`,height:`${Math.max(1,an(g(Ht)).height)}px`}),()=>({width:`${Math.max(1,an(g(Ut)).width)}px`,height:`${Math.max(1,an(g(Ut)).height)}px`})]),o(`load`,n,()=>Vr(`a`)),a(n),o(`load`,s,()=>Vr(`b`)),a(s),l(e,t)};s(de,e=>{g(Kt)&&e(fe)}),r(w);var pe=S(w,2);let me;var he=T(pe);ie(he,17,()=>g(ln),e=>e.id,(e,t)=>{var a=lr(),c=ae(a),d=e=>{var n=ar();let r;E(()=>r=le(n,``,r,{"--fc-pulse-ms":`${re}ms`,left:`${g(t).left}px`,top:`${g(t).top}px`,width:`${g(t).width}px`,height:`${g(t).height}px`})),l(e,n)};s(c,e=>{g(t).pulsing&&e(d)});var f=S(c,2),p=e=>{var n=or();let r,i;E(()=>{r=u(n,1,`fc-frame-border svelte-1vhlljx`,null,r,{selected:g(t).selected}),i=le(n,``,i,{left:`${g(t).left}px`,top:`${g(t).top}px`,width:`${g(t).width}px`,height:`${g(t).height}px`})}),l(e,n)};s(f,e=>{h()===`editor`&&!g(Dt)&&(g(t).transparent||g(t).selected)&&e(p)});var m=S(f,2),v=e=>{var a=ue(),c=ae(a),d=e=>{var r=sr();_(r);let i;ee(r,e=>j(mt,e),()=>g(mt)),E(e=>{D(r,`aria-label`,`Rename frame ${g(t).index+1}`),i=le(r,``,i,e)},[()=>({left:`${g(t).left}px`,top:`${g(t).top}px`,"max-width":`${Math.max(60,g(t).width)}px`})]),n(`pointerdown`,r,e=>e.stopPropagation()),n(`keydown`,r,jr),o(`blur`,r,()=>Ar()),se(r,()=>g(pt),e=>j(pt,e)),l(e,r)},f=e=>{var a=cr();let o,s;var c=T(a),d=T(c,!0);r(c);var f=S(c,2),p=T(f,!0);r(f),r(a),E(e=>{o=u(a,1,`fc-label svelte-1vhlljx`,null,o,{selected:g(t).selected}),D(a,`title`,g(It)?`Double-click to rename · click to select ${g(t).label}`:`Select ${g(t).label}`),s=le(a,``,s,e),i(d,g(t).index+1),i(p,g(t).label)},[()=>({left:`${g(t).left}px`,top:`${g(t).top}px`,"max-width":`${Math.max(60,g(t).width)}px`})]),n(`pointerdown`,a,e=>e.stopPropagation()),n(`click`,a,()=>Tr(g(t).index)),n(`dblclick`,a,e=>{e.stopPropagation(),e.preventDefault(),Or(g(t).index)}),l(e,a)};s(c,e=>{g(ft)===g(t).index?e(d):e(f,-1)}),l(e,a)};s(m,e=>{h()===`editor`&&!g(Dt)&&e(v)}),l(e,a)}),ie(S(he,2),17,()=>g(un),e=>e.key,(e,t)=>{var n=ur();let r;E(()=>r=le(n,``,r,{left:`${g(t).left}px`,top:`${g(t).top}px`,width:`${g(t).width}px`,height:`${g(t).height}px`})),l(e,n)}),r(pe);var ge=S(pe,2),N=e=>{var t=fr();ie(t,21,()=>g(ln),e=>e.id,(e,t)=>{var n=dr();let r;E(e=>{D(n,`id`,`fc-proxy-${g(t).index}`),D(n,`aria-selected`,e),D(n,`aria-label`,`Frame ${g(t).index+1} of ${g(ln).length}: ${g(t).label}`),D(n,`tabindex`,g(t).index===g(Je)?0:-1),r=le(n,``,r,{left:`${g(t).left}px`,top:`${g(t).top}px`,width:`${g(t).width}px`,height:`${g(t).height}px`})},[()=>g(V).some(e=>e.frameId===g(t).id)]),o(`focus`,n,()=>j(Je,g(t).index,!0)),l(e,n)}),r(t),n(`keydown`,t,Ti),l(e,t)};s(ge,e=>{h()===`editor`&&!g(Dt)&&g(ln).length>0&&e(N)});var _e=S(ge,2),P=e=>{var t=pr();let a;var s=T(t),c=T(s);be(T(c),{size:16}),r(c);var d=S(c,2),f=T(d);r(d);var m=S(d,2);xe(T(m),{size:16}),r(m),r(s);var h=S(s,2),_=T(h);Ae(T(_),{size:16}),p(2),r(_),r(h),r(t),E(()=>{a=u(t,1,`fc-present-controls svelte-1vhlljx`,null,a,{visible:g(Ze)}),i(f,`${g(Zt)+1} / ${g(qt)??``}`)}),n(`pointerdown`,t,e=>e.stopPropagation()),n(`pointermove`,t,xi),o(`wheel`,t,e=>e.stopPropagation()),n(`click`,c,()=>Si(-1)),n(`click`,m,()=>Si(1)),n(`click`,_,()=>Ci(0)),l(e,t)};s(_e,e=>{h()===`present`&&!g(Ot)&&g(qt)>1&&e(P)}),r(c),ee(c,e=>j(U,e),()=>g(U)),r(t),E(e=>{f=u(c,1,`fc-stage svelte-1vhlljx`,null,f,{panning:g(tt),"hand-tool":g(Ft)===`hand`,whiteboard:g(G)}),D(c,`data-mode`,h()),D(c,`data-background`,g(cn)),ce=u(w,1,`fc-viewport svelte-1vhlljx`,null,ce,{revealing:!g(B)&&h()===`editor`}),O=le(w,``,O,e),me=u(pe,1,`fc-overlay svelte-1vhlljx`,null,me,{revealing:!g(B)&&h()===`editor`})},[()=>({width:`${Math.max(1,an(g(Wt)).width)}px`,height:`${Math.max(1,an(g(Wt)).height)}px`,transform:g(rn)})]),n(`pointerdown`,c,vi),n(`pointermove`,c,yi),n(`pointerup`,c,bi),o(`pointercancel`,c,bi),o(`lostpointercapture`,c,bi),o(`wheel`,c,mi),l(e,t)},ki=e=>{var t=hr(),n=T(t);r(t),E(()=>D(n,`data-mode`,h())),l(e,t)};s(Di,e=>{g(W)?e(Oi):e(ki,-1)}),l(e,Ei),c()}m([`pointerdown`,`pointermove`,`pointerup`,`click`,`keydown`,`dblclick`]);export{tn as n,$ as t};
|