framefields 2.15.0 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,36 +1,27 @@
1
- async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width),i=Math.round(t.width*r),s=Math.round(t.height*r),o=document.createElement("canvas");o.width=i,o.height=s;let a=o.getContext("2d");if(!a)throw new Error("no 2D canvas to draw the note's picture");a.drawImage(t,0,0,i,s),t.close();let l=Math.max(3,i/400),p=f=>{for(let[m,x]of[[l+5,"rgba(0,0,0,0.5)"],[l+2.5,"#fff"],[l,"#3b82f6"]])a.lineWidth=m,a.strokeStyle=x,f()},{x:c,y:h}=e;if(e.w!=null&&e.h!=null){let{w:f,h:m}=e;p(()=>a.strokeRect(c*i,h*s,f*i,m*s))}else{let f=Math.max(16,i/40);p(()=>{a.beginPath(),a.arc(c*i,h*s,f,0,Math.PI*2),a.stroke()}),a.fillStyle="#3b82f6",a.beginPath(),a.arc(c*i,h*s,l,0,Math.PI*2),a.fill()}return o.toDataURL("image/jpeg",.88)}function v(n,e){let t=n/e,r=Math.floor(t/60);return`${r}:${(t-r*60).toFixed(2).padStart(5,"0")}`}function _(n,e){return Math.max(0,Math.min(e-1,Math.round(n)))}function le(n,e){return e>1?n/(e-1)*100:0}function pe(n,e,t){let r=/[#&]t=([\d.]+)/.exec(n);if(r)return _(Number(r[1])*e,t);let i=/[#&]frame=(\d+)/.exec(n);return i?_(Number(i[1]),t):null}function Me(n,e){return n>0?`#t=${Number((n/e).toFixed(3))}`:""}var Pt=[.5,1,2,5,10,15,30,60,120,300,600];function _e(n,e){if(n<=0)return[];let r=(Pt.find(s=>s/n*e>=80)??1200)/5,i=[];for(let s=0;s*r<=n+1e-6;s++){let o=s*r,a=s%5===0,l=o/n*e,p={left:o/n*100,major:a};if(a&&l<e-34){let c=Math.floor(o/60),h=Math.round((o-c*60)*10)/10;p.label=`${c}:${h<10?"0":""}${h}`}i.push(p)}return i}function U(n,e){return n.frame-e.frame||n.id-e.id}function Ce(n,e,t){let r=[];return[...n].sort(U).map(i=>{let s=le(i.frame,e),o=s/100*t,a=r.findIndex(l=>o-l>=16);return a<0&&(a=r.length<3?r.length:2),r[a]=o,{note:i,lane:a,left:s}})}function M(n){return`${Math.round(n*100)}%`}function At(n){return n.w!=null&&n.h!=null?`area ${M(n.x)},${M(n.y)} to ${M(n.x+n.w)},${M(n.y+n.h)}`:`spot ${M(n.x)},${M(n.y)}`}function Te(n,e,t){let r=[`Notes on the preview of ${JSON.stringify(n)}:`];for(let i of e.filter(s=>!s.done).sort(U))r.push(`- Note ${i.id} at ${v(i.frame,t)} (frame ${i.frame}), ${At(i)}: ${i.text}${i.image?` [picture: ${i.image}]`:""}`);return r.join(`
2
- `)}function Ne(n){return n?n.split("/").slice(-2).join("/"):""}var z=class{constructor(e=()=>Number.POSITIVE_INFINITY,t=()=>performance.now()){this.cap=e;this.now=t}cap;now;#e=null;#t=null;#i=[];#r=null;read(){if(this.#e===null)return{state:"paused",fps:this.#r};let e=this.now(),t=Math.min(2e3,e-this.#e);return this.#i=this.#i.filter(r=>r>e-2e3),t<1e3?{state:"measuring",fps:null}:{state:"playing",fps:Math.min(this.cap(),this.#i.length*1e3/t)}}start(){this.#e=this.now(),this.#t=null,this.#i=[]}stop(){if(this.#e===null)return;let e=this.read();this.#r=e.state==="playing"?e.fps:null,this.#e=null,this.#i=[]}record(e){this.#e===null||e===this.#t||(this.#t=e,this.#i.push(this.now()))}};function Et(n){if(n instanceof Error||typeof n=="object"&&n&&"message"in n){let{message:e,stack:t}=n,r=String(e);if(typeof t=="string"&&t.includes(r))return t.split(`
1
+ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width),i=Math.round(t.width*r),s=Math.round(t.height*r),o=document.createElement("canvas");o.width=i,o.height=s;let a=o.getContext("2d");if(!a)throw new Error("no 2D canvas to draw the note's picture");a.drawImage(t,0,0,i,s),t.close();let l=Math.max(3,i/400),p=f=>{for(let[m,b]of[[l+5,"rgba(0,0,0,0.5)"],[l+2.5,"#fff"],[l,"#3b82f6"]])a.lineWidth=m,a.strokeStyle=b,f()},{x:h,y:d}=e;if(e.w!=null&&e.h!=null){let{w:f,h:m}=e;p(()=>a.strokeRect(h*i,d*s,f*i,m*s))}else{let f=Math.max(16,i/40);p(()=>{a.beginPath(),a.arc(h*i,d*s,f,0,Math.PI*2),a.stroke()}),a.fillStyle="#3b82f6",a.beginPath(),a.arc(h*i,d*s,l,0,Math.PI*2),a.fill()}return o.toDataURL("image/jpeg",.88)}function v(n,e){let t=n/e,r=Math.floor(t/60);return`${r}:${(t-r*60).toFixed(2).padStart(5,"0")}`}function _(n,e){return Math.max(0,Math.min(e-1,Math.round(n)))}function de(n,e){return e>1?n/(e-1)*100:0}function pe(n,e,t){let r=/[#&]t=([\d.]+)/.exec(n);if(r)return _(Number(r[1])*e,t);let i=/[#&]frame=(\d+)/.exec(n);return i?_(Number(i[1]),t):null}function _e(n,e){return n>0?`#t=${Number((n/e).toFixed(3))}`:""}var Ct=[.5,1,2,5,10,15,30,60,120,300,600];function Ce(n,e){if(n<=0)return[];let r=(Ct.find(s=>s/n*e>=80)??1200)/5,i=[];for(let s=0;s*r<=n+1e-6;s++){let o=s*r,a=s%5===0,l=o/n*e,p={left:o/n*100,major:a};if(a&&l<e-34){let h=Math.floor(o/60),d=Math.round((o-h*60)*10)/10;p.label=`${h}:${d<10?"0":""}${d}`}i.push(p)}return i}function z(n,e){return n.frame-e.frame||n.id-e.id}function Te(n,e,t){let r=[];return[...n].sort(z).map(i=>{let s=de(i.frame,e),o=s/100*t,a=r.findIndex(l=>o-l>=16);return a<0&&(a=r.length<3?r.length:2),r[a]=o,{note:i,lane:a,left:s}})}function S(n){return`${Math.round(n*100)}%`}function Tt(n){return n.w!=null&&n.h!=null?`area ${S(n.x)},${S(n.y)} to ${S(n.x+n.w)},${S(n.y+n.h)}`:`spot ${S(n.x)},${S(n.y)}`}function Ne(n,e,t){let r=[`Notes on the preview of ${JSON.stringify(n)}:`];for(let i of e.filter(s=>!s.done).sort(z))r.push(`- Note ${i.id} at ${v(i.frame,t)} (frame ${i.frame}), ${Tt(i)}: ${i.text}${i.image?` [picture: ${i.image}]`:""}`);return r.join(`
2
+ `)}function Re(n,e,t,r){return n==="frames"?{now:String(e),end:String(t)}:{now:v(e,r),end:v(t,r)}}var F=class{constructor(e=()=>Number.POSITIVE_INFINITY,t=()=>performance.now()){this.cap=e;this.now=t}cap;now;#e=null;#t=null;#i=[];#r=null;read(){if(this.#e===null)return{state:"paused",fps:this.#r};let e=this.now(),t=Math.min(2e3,e-this.#e);return this.#i=this.#i.filter(r=>r>e-2e3),t<1e3?{state:"measuring",fps:null}:{state:"playing",fps:Math.min(this.cap(),this.#i.length*1e3/t)}}start(){this.#e=this.now(),this.#t=null,this.#i=[]}stop(){if(this.#e===null)return;let e=this.read();this.#r=e.state==="playing"?e.fps:null,this.#e=null,this.#i=[]}record(e){this.#e===null||e===this.#t||(this.#t=e,this.#i.push(this.now()))}};function Nt(n){if(n instanceof Error||typeof n=="object"&&n&&"message"in n){let{message:e,stack:t}=n,r=String(e);if(typeof t=="string"&&t.includes(r))return t.split(`
3
3
  `).slice(0,4).join(`
4
- `);if(r)return r}return typeof n=="string"?n:String(n)}function Re(n){let e=new Set;return(t,r)=>{let i=r.map(Et).join(" ").trim(),s=t+i.replace(/\d+/g,"#");!i||e.has(s)||e.size>100||(e.add(s),n({level:t,message:i.slice(0,4e3)}))}}function Le(n,e){let t=n.error.bind(n),r=n.warn.bind(n);n.error=(...i)=>{t(...i),e("error",i)},n.warn=(...i)=>{r(...i),typeof i[0]=="string"&&i[0].startsWith("[framefields]")&&e("warning",i)}}var He="/@framefields/player.js";async function he(n){let e=await n;if(!e.ok)throw new Error(`HTTP ${e.status}`);return await e.json()}function Oe(n,e,t=!1){return fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e),keepalive:t})}function Be(){return{meta:()=>he(fetch("/meta")),listNotes:async()=>{let n=await he(fetch("/@framefields/notes"));return Array.isArray(n)?n:[]},changeNote:n=>he(Oe("/@framefields/notes",n)),log(n){Oe("/@framefields/log",n,!0).catch(()=>{})},mixAudio(){fetch("/audio/mix",{method:"POST"}).catch(()=>{})},async audio(){let n=await fetch("/audio");if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.arrayBuffer()},events(n){let e=new EventSource("/events"),t=r=>JSON.parse(r.data);return e.addEventListener("hello",r=>n.hello(t(r).session)),e.addEventListener("error",()=>n.lost()),e.addEventListener("notes",r=>n.notes(t(r))),e.addEventListener("audio",r=>n.audio(t(r))),()=>e.close()}}}var C=1200,De=.001;var F={mixing:"Mixing audio",loading:"Loading audio",ready:"Audio ready",none:"No audio",error:"Audio failed"},b=2,St=4,Mt=64;function _t(){let n;try{n=new Worker(He,{type:"module"})}catch{return null}let e=new Map,t=0,r=null,i=o=>{r??=o;for(let a of e.values())a.reject(r);e.clear()},s=new Promise((o,a)=>{n.onmessage=l=>{let p=l.data;if("ready"in p){if(p.ready)o();else{let h=new Error(p.error);a(h),i(h)}return}let c=e.get(p.id);c&&(e.delete(p.id),"error"in p?c.reject(new Error(p.error)):c.resolve(p.mix))},n.onerror=l=>{let p=new Error(l.message||"the mixing worker failed");a(p),i(p)}});return s.catch(()=>{}),{async mix(o,a){if(await s,r)throw r;return new Promise((l,p)=>{let c=++t;e.set(c,{resolve:l,reject:p}),n.postMessage({id:c,range:o,chain:a})})},stop(){n.terminate(),i(new Error("stopped"))}}}var de=class{constructor(e,t){this.player=e;this.total=Math.max(1,Math.ceil(t/b))}player;worker=_t();blocks=new Map;order=[];pending=new Map;queue=[];busy=!1;seen=new Set;peak=0;gain=1;fill=0;filling=!1;total;mix(e,t){let r=this.worker;return r?r.mix(e,t).catch(i=>(this.worker&&(console.warn("The soundtrack's mixing worker failed, so the page mixes it:",i),this.worker.stop(),this.worker=null),this.player.mixAudio(e,t))):this.player.mixAudio(e,t)}};function Ie(n,e){let t=new Float32Array(n.length);for(let r=0;r<n.length;r++){let i=Math.tanh(n[r]*e);t[r]=Number.isNaN(i)?0:i}return t}var q=class{constructor(e){this.host=e}host;mode="browser";state="mixing";error="";buffer=null;peaks=null;peaksVersion=0;muted=!1;volume=.9;#e=null;#t=null;#i=null;#r=null;#s=null;#o=null;get usable(){return this.state==="ready"&&(!!this.buffer||!!this.#r)}get durationSec(){return this.buffer?this.buffer.duration:null}get mixed(){let e=this.#r;if(!e)return null;let t=0;for(let r of e.blocks.values())r.exact&&t++;return{blocks:e.seen.size,of:e.total,exact:t}}get mixer(){return this.#r?this.#r.worker?"worker":"page":this.mode==="server"?"server":null}attach(e,t){this.#o=e,this.mode==="browser"&&this.#f(e,t)}load(e,t){if(e?.state==="browser"){this.mode="browser",this.#n("mixing"),this.#o&&this.#f(this.#o,t);return}if(this.mode="server",this.stopClock(),this.buffer=null,this.#l(null),e?.state!=="ready"){this.#n(e?.state??"none",e?.state==="error"?e.error:"");return}this.#l(e.peaks),this.#n("loading");let r=this.#c();this.host.server.audio().then(i=>r.decodeAudioData(i)).then(i=>{this.buffer=i,this.#n("ready")},i=>this.#n("error",String(i?.message??i)))}async ready(e){let t=this.#r;!t||this.state==="none"||(await this.#d(t,this.#p(e),!0).catch(()=>{}),this.#r&&this.state==="mixing"&&this.#n("ready"))}get waitsBeforePlay(){return!!this.#r&&this.state!=="none"}setMuted(e){this.muted=e,this.#h()}setVolume(e){this.volume=e,this.muted=e===0,this.#h()}startClock(e,t){let r=this.#e;if(this.#r&&r&&this.state==="ready")return this.#k(this.#r,r,e/t);if(this.buffer&&r&&this.#t){r.resume();let s=r.createBufferSource();s.buffer=this.buffer,s.connect(this.#t);let o=r.currentTime+.06,a=e/t;return a<this.buffer.duration&&s.start(o,a),this.#i=s,()=>Math.max(0,r.currentTime-o)}let i=performance.now();return()=>(performance.now()-i)/1e3}stopClock(){this.#m();let e=this.#i;if(e){try{e.stop()}catch{}e.disconnect(),this.#i=null}}#n(e,t=""){this.state=e,this.error=t,this.host.changed()}#l(e){this.peaks=e,this.peaksVersion++}#a(){let e=this.host.film();return e?e.frameCount/e.fps:0}#p(e){let t=this.host.film()?.fps??30;return Math.floor(e/t/b)}#c(){if(this.#e)return this.#e;let e=window.AudioContext??window.webkitAudioContext,t=new e;return this.#t=t.createGain(),this.#t.connect(t.destination),this.#e=t,this.#h(),t}#h(){this.#t&&(this.#t.gain.value=this.muted?0:this.volume),this.host.changed()}#f(e,t){this.#r?.worker?.stop(),this.stopClock(),this.buffer=null,this.#l(new Array(C).fill(0));let r=new de(e,this.#a());this.#r=r,this.#c(),this.#n("mixing"),this.#d(r,this.#p(t),!0).then(()=>{this.#r===r&&this.state==="mixing"&&this.#n("ready")},()=>{})}#d(e,t,r){let i=e.blocks.get(t);if(i)return Promise.resolve(i);let s=e.pending.get(t);if(s)return r&&Ct(e,t),s;let o=je(e,t,t===e.fill?"fill":"play",r,!0);return this.#u(e),o}#u(e){if(e.busy||this.#r!==e||!e.queue.length&&(!e.filling&&e.fill<e.total&&je(e,e.fill,"fill",!1,!e.pending.has(e.fill)),!e.queue.length))return;e.busy=!0;let t=e.queue.shift(),r=this.#a(),i={startSec:t.i*b,endSec:Math.min(r,(t.i+1)*b)};e.mix(i,t.chain).then(s=>{this.#r===e&&this.#y(e,t.i,s),t.chain==="fill"&&(e.fill=t.i+1,e.filling=!1),t.resolve(e.blocks.get(t.i))},s=>{t.chain==="fill"&&(e.filling=!1),t.reject(s),this.#w(e,s)}).then(()=>{t.own&&e.pending.delete(t.i),e.busy=!1,this.#u(e)})}#y(e,t,r){let i={left:r.left,right:r.right,sampleRate:r.sampleRate,exact:r.exact},s=e.blocks.get(t);if(!s||!s.exact||i.exact)for(e.blocks.set(t,i),e.order.push(t);e.order.length>Mt;)e.blocks.delete(e.order.shift());if(!e.seen.has(t)){if(e.seen.add(t),e.peak=Math.max(e.peak,r.peak),this.#g(t,i),e.seen.size<e.total){this.host.changed();return}e.gain=e.peak>.95?.92/e.peak:1,e.peak<De?this.#n("none"):this.host.changed()}}#g(e,t){let r=this.peaks;if(!r)return;let i=this.#a(),s=Math.floor(e*b/i*C),o=Math.min(C,Math.ceil(Math.min(i,(e+1)*b)/i*C)),a=i/C*t.sampleRate,l=e*b*t.sampleRate;for(let p=s;p<o;p++){let c=Math.max(0,Math.floor(p*a-l)),h=Math.min(t.left.length,Math.floor((p+1)*a-l)),f=r[p];for(let m=c;m<h;m++)f=Math.max(f,Math.abs(t.left[m]),Math.abs(t.right[m]));r[p]=Math.min(1,f)}this.peaksVersion++}#w(e,t){this.#r===e&&(e.worker?.stop(),this.#r=null,this.stopClock(),console.warn("Mixing the soundtrack in the browser failed, so the preview server mixes it:",t),this.mode="server",this.#n("mixing"),this.host.server.mixAudio())}#k(e,t,r){t.resume();let i={t0:r,startAt:t.currentTime+.08,next:Math.floor(r/b),sources:[],timer:void 0};this.#s=i;let s=()=>{if(this.#s!==i||this.#r!==e)return;let o=t.currentTime-i.startAt+i.t0;for(;i.next<e.total&&i.next*b<o+St;){let a=e.blocks.get(i.next);if(!a){this.#d(e,i.next,!0).then(s,()=>{});return}this.#$(t,i,i.next,a,e.gain),i.next++}};return i.timer=setInterval(s,250),s(),()=>Math.max(0,t.currentTime-i.startAt)}#$(e,t,r,i,s){if(!this.#t)return;let o=e.createBuffer(2,i.left.length,i.sampleRate);o.copyToChannel(Ie(i.left,s),0),o.copyToChannel(Ie(i.right,s),1);let a=e.createBufferSource();a.buffer=o,a.connect(this.#t);let l=t.startAt+(r*b-t.t0),p=Math.max(l,e.currentTime+.02),c=p-l;c>=o.duration||(a.start(p,c),t.sources.push(a),a.onended=()=>{t.sources=t.sources.filter(h=>h!==a)})}#m(){let e=this.#s;if(this.#s=null,!!e){clearInterval(e.timer);for(let t of e.sources){try{t.stop()}catch{}t.disconnect()}}}};function je(n,e,t,r,i){t==="fill"&&(n.filling=!0);let s=new Promise((o,a)=>{let l={i:e,chain:t,own:i,resolve:o,reject:a};r?n.queue.unshift(l):n.queue.push(l)});return i?n.pending.set(e,s):s.catch(()=>{}),s}function Ct(n,e){let t=n.queue.findIndex(r=>r.i===e);t>0&&n.queue.unshift(n.queue.splice(t,1)[0])}function Tt(n,e,t){return t&&t.w>.01&&t.h>.01?{frame:n,...t,text:""}:{frame:n,x:e.x,y:e.y,text:""}}var ce=n=>new Promise(e=>setTimeout(e,n)),W=class extends EventTarget{meta=null;player=null;pageState="loading";error=null;frame=0;playing=!1;stalled=!1;offline=!1;fps={state:"paused",fps:null};notesOn=!1;notes=[];draft=null;openId=null;saving=!1;saveError=!1;panelOpen=!1;toastText="";toastOn=!1;soundtrack;report;server;#e;#t;#i;#r=null;#s=!1;#o=0;#n;#l=0;#a=new Set;#p=[];#c;#h;#f=new AbortController;#d=!1;constructor(e={}){super(),this.server=e.server??Be(),this.#e=e.win??window,this.#t=e.embedder!==void 0?e.embedder:this.#e.parent!==this.#e?this.#e.parent:null,this.report=Re(t=>this.server.log(t)),this.#i=new z(()=>this.meta?.fps??1/0),this.soundtrack=new q({server:this.server,film:()=>this.meta,changed:()=>this.changed()})}get lastFrame(){return(this.meta?.frameCount??1)-1}get buffering(){return this.pageState!=="error"&&(this.#s||this.stalled)}noteById(e){return this.notes.find(t=>t.id===e)}get openCount(){return this.notes.filter(e=>!e.done).length}get canNote(){return this.notesOn&&!!this.player&&!this.playing}changed(){this.#d||(this.#d=!0,queueMicrotask(()=>{this.#d=!1,this.dispatchEvent(new Event("change"))}))}subscribe(e){return this.addEventListener("change",e),()=>this.removeEventListener("change",e)}async start(){let e=this.#e,t=this.#f.signal,r=this.server.events({hello:l=>this.#w(l),lost:()=>this.#k(),notes:l=>this.#S(l),audio:l=>this.#$(l)});t.addEventListener("abort",r);let i={signal:t};e.addEventListener("framefields:player",()=>{this.meta&&this.#u()},i),e.addEventListener("error",l=>{this.player?this.report("error",[l.error??l.message]):this.showError(l.error??l.message)},i),e.addEventListener("unhandledrejection",l=>this.report("error",[l.reason]),i),e.addEventListener("hashchange",()=>this.#_(),i),e.document.addEventListener("visibilitychange",()=>{e.document.hidden&&this.playing&&this.pause()},i),e.framefieldsPreview=this.api();let s=await this.server.meta(),{audio:o,...a}=s;this.#r=a.session,this.meta=a,e.document.title=`${a.title} \xB7 preview`,this.notesOn=!!a.notesDir,this.#N(),this.soundtrack.load(o,this.frame),this.#m(pe(e.location.hash,a.fps,a.frameCount)??0),this.#s=!0,this.#u()}close(){this.#f.abort(),this.#b()}#u(){let e=this.#e.framefieldsPlayer;e&&e.then(t=>{this.player=t,this.soundtrack.attach(t,this.frame),this.changed(),this.#P(this.frame).then(()=>this.#y())},t=>{this.showError(t),this.#e.document.documentElement.dataset.preview="error",this.#g(t instanceof Error?t:new Error(String(t)))})}#y(){this.pageState="ready",this.#e.document.documentElement.dataset.preview="ready",this.#g(),this.#v(),this.changed(),this.#t?.postMessage({type:"framefields-preview:ready",seekByHash:!0},"*")}whenReady(){return this.player?Promise.resolve():this.pageState==="error"?Promise.reject(new Error(this.error??"the preview failed")):new Promise((e,t)=>this.#p.push([e,t]))}#g(e){for(let[t,r]of this.#p.splice(0))e?r(e):t()}showError(e){this.report("error",[e]),this.pageState="error",this.error=String(e?.message??e),this.changed()}#w(e){if(this.#r&&e!==this.#r){this.#e.location.reload();return}this.offline=!1,this.changed()}#k(){this.meta&&(this.playing&&(this.#b(),this.#A()),this.offline=!0,this.changed())}#$(e){this.meta&&this.soundtrack.load(e,this.frame)}#m(e){this.frame=e,this.changed()}#P(e){this.#m(e);let t=this.player;return t?(this.#s=!0,t.render(e).then(()=>{this.#s=!1,this.changed()})):Promise.resolve()}seek(e){this.#b();let t=this.#P(_(e,this.meta?.frameCount??1));return this.#A(),this.#v(),t}step(e){return this.seek(this.frame+e)}#A(){if(!this.meta)return;let{location:e,history:t}=this.#e,r=Me(this.frame,this.meta.fps)||e.pathname+e.search;try{t.replaceState(null,"",r)}catch{}}#_(){let e=this.meta;if(!e)return;let t=pe(this.#e.location.hash,e.fps,e.frameCount);t!==null&&(this.playing&&this.pause(),t!==this.frame&&this.seek(t))}#v(){clearTimeout(this.#n),this.#l++,!(!this.player?.hasVision||this.playing)&&(this.#n=setTimeout(()=>{this.#C()},1e3))}async#C(){let e=this.player,t=this.meta;if(!e||!t)return;let r=++this.#l,i=Math.min(this.lastFrame,this.frame+Math.round(t.fps*20));for(let s=this.frame+1;s<=i&&r===this.#l&&!this.playing;s++)if(!this.#a.has(s)){if(!await e.warm(s)){this.#v();return}this.#a.add(s),await ce(0)}}play(){if(this.playing||!this.player)return;this.playing=!0,clearTimeout(this.#n),this.#l++;let e=++this.#o,t=()=>this.playing&&e===this.#o;this.openId!=null&&this.closePop(),this.draft&&!this.draft.text.trim()&&this.cancelDraft(),this.frame>=this.lastFrame&&(this.frame=0),this.changed(),this.#T(this.player,t).catch(r=>this.report("error",[r])).finally(()=>{e===this.#o&&this.playing&&this.pause()})}pause(){this.#b(),this.#A(),this.#P(this.frame).then(()=>this.#v())}togglePlay(){this.playing?this.pause():this.play()}#b(){this.playing=!1,this.soundtrack.stopClock(),this.stalled=!1,this.#i.stop(),clearInterval(this.#h),this.#h=void 0,this.#E()}#E(){this.fps=this.#i.read(),this.changed()}#x(e){this.stalled=e,this.changed()}async#T(e,t){let r=this.meta?.fps??30;if(this.#i.start(),this.#E(),this.#h=setInterval(()=>this.#E(),500),this.soundtrack.waitsBeforePlay){if(this.#x(!0),await this.soundtrack.ready(this.frame),!t())return;this.#x(!1)}if(this.soundtrack.state==="loading"){for(this.#x(!0);t()&&this.soundtrack.state==="loading";)await ce(50);if(!t())return;this.#x(!1)}let i=this.frame,s=this.soundtrack.startClock(i,r),o=-1;for(;t();){let a=Math.min(this.lastFrame,i+Math.floor(s()*r));if(a===o){await ce(4);continue}this.#m(a);let l=await e.render(a,{cache:!1});if(!t()||(o=l,this.#i.record(l),l>=this.lastFrame))return}}#N(){this.notesOn&&this.server.listNotes().then(e=>this.#S(e),()=>{})}#S(e){this.notes=e,this.openId!=null&&!this.noteById(this.openId)&&this.closePop(),this.changed()}#M(e){let t=this.notes.findIndex(r=>r.id===e.id);t>=0?this.notes[t]=e:this.notes.push(e),this.changed()}beginDraft(e,t){this.openId=null,this.saveError=!1,this.draft=Tt(this.frame,e,t),this.changed()}setDraftText(e){this.draft&&(this.draft.text=e,this.changed())}cancelDraft(){this.draft&&(this.draft=null,this.closePop())}async saveDraft(){let e=this.draft,t=this.meta,r=e?.text.trim();if(!e||!t||!r||this.saving)return!1;this.saving=!0,this.saveError=!1,this.changed();try{let i;try{this.player&&(i=await Se(this.player,e))}catch(o){this.report("warning",["[framefields] no picture for the note:",o])}let s=await this.server.changeNote({op:"add",note:{frame:e.frame,time:e.frame/t.fps,x:e.x,y:e.y,w:e.w,h:e.h,text:r,image:i}});return this.draft===e&&(this.draft=null),this.closePop(),this.#M(s),this.toast(`Note ${s.id} saved`),!0}catch{return this.saveError=!0,!1}finally{this.saving=!1,this.changed()}}openCard(e){this.noteById(e)&&(this.draft&&this.cancelDraft(),this.openId=e,this.changed())}closePop(){this.openId=null,this.changed()}setDone(e,t){this.server.changeNote({op:"update",id:e,done:t}).then(r=>this.#M(r),()=>this.toast("Couldn't save. Is the preview running?"))}removeNote(e){this.server.changeNote({op:"remove",id:e}).then(()=>{this.notes=this.notes.filter(t=>t.id!==e),this.closePop()},()=>this.toast("Couldn't delete. Is the preview running?"))}goToNote(e){let t=this.noteById(e);t&&(this.panelOpen=!1,this.seek(t.frame).then(()=>this.openCard(e)))}setPanel(e){this.panelOpen=e,this.changed()}toast(e){this.toastText=e,this.toastOn=!0,clearTimeout(this.#c),this.#c=setTimeout(()=>{this.toastOn=!1,this.changed()},2200),this.changed()}api(){return{seek:async e=>(await this.whenReady(),this.seek(Number(e)*(this.meta?.fps??30))),seekFrame:async e=>(await this.whenReady(),this.seek(e)),play:async()=>{await this.whenReady(),this.play()},pause:()=>{this.playing&&this.pause()},notes:()=>this.notes.slice(),state:()=>this.snapshot()}}snapshot(){let e=this.meta,t=this.#i.read().fps;return{state:this.pageState,error:this.pageState==="error"?this.error:null,frame:this.frame,time:e?Number((this.frame/e.fps).toFixed(3)):0,playing:this.playing,buffering:this.stalled,audio:this.soundtrack.state,audioMixed:this.soundtrack.mixed,audioMixer:this.soundtrack.mixer,connected:!this.offline,playbackFps:t==null?null:Number(t.toFixed(1)),renderMs:this.player?Math.round(this.player.lastRenderMs):null,meta:e&&{title:e.title,width:e.width,height:e.height,fps:e.fps,frameCount:e.frameCount,duration:Number((this.lastFrame/e.fps).toFixed(3))}}}};var V=globalThis,X=V.ShadowRoot&&(V.ShadyCSS===void 0||V.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,ze=Symbol(),Ue=new WeakMap,K=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==ze)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(X&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=Ue.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&Ue.set(t,e))}return e}toString(){return this.cssText}},qe=n=>new K(typeof n=="string"?n:n+"",void 0,ze);var Fe=(n,e)=>{if(X)n.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(let t of e){let r=document.createElement("style"),i=V.litNonce;i!==void 0&&r.setAttribute("nonce",i),r.textContent=t.cssText,n.appendChild(r)}},ue=X?n=>n:n=>n instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return qe(t)})(n):n;var{is:Nt,defineProperty:Rt,getOwnPropertyDescriptor:Lt,getOwnPropertyNames:Ot,getOwnPropertySymbols:Ht,getPrototypeOf:Bt}=Object,J=globalThis,We=J.trustedTypes,Dt=We?We.emptyScript:"",It=J.reactiveElementPolyfillSupport,L=(n,e)=>n,fe={toAttribute(n,e){switch(e){case Boolean:n=n?Dt:null;break;case Object:case Array:n=n==null?n:JSON.stringify(n)}return n},fromAttribute(n,e){let t=n;switch(e){case Boolean:t=n!==null;break;case Number:t=n===null?null:Number(n);break;case Object:case Array:try{t=JSON.parse(n)}catch{t=null}}return t}},Ke=(n,e)=>!Nt(n,e),Ve={attribute:!0,type:String,converter:fe,reflect:!1,useDefault:!1,hasChanged:Ke};Symbol.metadata??=Symbol("metadata"),J.litPropertyMetadata??=new WeakMap;var y=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=Ve){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){let r=Symbol(),i=this.getPropertyDescriptor(e,r,t);i!==void 0&&Rt(this.prototype,e,i)}}static getPropertyDescriptor(e,t,r){let{get:i,set:s}=Lt(this.prototype,e)??{get(){return this[t]},set(o){this[t]=o}};return{get:i,set(o){let a=i?.call(this);s?.call(this,o),this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??Ve}static _$Ei(){if(this.hasOwnProperty(L("elementProperties")))return;let e=Bt(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(L("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(L("properties"))){let t=this.properties,r=[...Ot(t),...Ht(t)];for(let i of r)this.createProperty(i,t[i])}let e=this[Symbol.metadata];if(e!==null){let t=litPropertyMetadata.get(e);if(t!==void 0)for(let[r,i]of t)this.elementProperties.set(r,i)}this._$Eh=new Map;for(let[t,r]of this.elementProperties){let i=this._$Eu(t,r);i!==void 0&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let i of r)t.unshift(ue(i))}else e!==void 0&&t.push(ue(e));return t}static _$Eu(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),this.renderRoot!==void 0&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){let e=new Map,t=this.constructor.elementProperties;for(let r of t.keys())this.hasOwnProperty(r)&&(e.set(r,this[r]),delete this[r]);e.size>0&&(this._$Ep=e)}createRenderRoot(){let e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Fe(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$ET(e,t){let r=this.constructor.elementProperties.get(e),i=this.constructor._$Eu(e,r);if(i!==void 0&&r.reflect===!0){let s=(r.converter?.toAttribute!==void 0?r.converter:fe).toAttribute(t,r.type);this._$Em=e,s==null?this.removeAttribute(i):this.setAttribute(i,s),this._$Em=null}}_$AK(e,t){let r=this.constructor,i=r._$Eh.get(e);if(i!==void 0&&this._$Em!==i){let s=r.getPropertyOptions(i),o=typeof s.converter=="function"?{fromAttribute:s.converter}:s.converter?.fromAttribute!==void 0?s.converter:fe;this._$Em=i;let a=o.fromAttribute(t,s.type);this[i]=a??this._$Ej?.get(i)??a,this._$Em=null}}requestUpdate(e,t,r,i=!1,s){if(e!==void 0){let o=this.constructor;if(i===!1&&(s=this[e]),r??=o.getPropertyOptions(e),!((r.hasChanged??Ke)(s,t)||r.useDefault&&r.reflect&&s===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,r))))return;this.C(e,t,r)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(e,t,{useDefault:r,reflect:i,wrapped:s},o){r&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),s!==!0||o!==void 0)||(this._$AL.has(e)||(this.hasUpdated||r||(t=void 0),this._$AL.set(e,t)),i===!0&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[i,s]of this._$Ep)this[i]=s;this._$Ep=void 0}let r=this.constructor.elementProperties;if(r.size>0)for(let[i,s]of r){let{wrapped:o}=s,a=this[i];o!==!0||this._$AL.has(i)||a===void 0||this.C(i,void 0,s,a)}}let e=!1,t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(r=>r.hostUpdate?.()),this.update(t)):this._$EM()}catch(r){throw e=!1,this._$EM(),r}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(e){}firstUpdated(e){}};y.elementStyles=[],y.shadowRootOptions={mode:"open"},y[L("elementProperties")]=new Map,y[L("finalized")]=new Map,It?.({ReactiveElement:y}),(J.reactiveElementVersions??=[]).push("2.1.2");var we=globalThis,Xe=n=>n,Y=we.trustedTypes,Je=Y?Y.createPolicy("lit-html",{createHTML:n=>n}):void 0,tt="$lit$",k=`lit$${Math.random().toFixed(9).slice(2)}$`,rt="?"+k,jt=`<${rt}>`,E=document,H=()=>E.createComment(""),B=n=>n===null||typeof n!="object"&&typeof n!="function",ke=Array.isArray,Ut=n=>ke(n)||typeof n?.[Symbol.iterator]=="function",me=`[
5
- \f\r]`,O=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Ye=/-->/g,Ge=/>/g,P=RegExp(`>|${me}(?:([^\\s"'>=/]+)(${me}*=${me}*(?:[^
6
- \f\r"'\`<>=]|("|')|))|$)`,"g"),Ze=/'/g,Qe=/"/g,it=/^(?:script|style|textarea|title)$/i,$e=n=>(e,...t)=>({_$litType$:n,strings:e,values:t}),d=$e(1),nt=$e(2),_r=$e(3),w=Symbol.for("lit-noChange"),u=Symbol.for("lit-nothing"),et=new WeakMap,A=E.createTreeWalker(E,129);function st(n,e){if(!ke(n)||!n.hasOwnProperty("raw"))throw Error("invalid template strings array");return Je!==void 0?Je.createHTML(e):e}var zt=(n,e)=>{let t=n.length-1,r=[],i,s=e===2?"<svg>":e===3?"<math>":"",o=O;for(let a=0;a<t;a++){let l=n[a],p,c,h=-1,f=0;for(;f<l.length&&(o.lastIndex=f,c=o.exec(l),c!==null);)f=o.lastIndex,o===O?c[1]==="!--"?o=Ye:c[1]!==void 0?o=Ge:c[2]!==void 0?(it.test(c[2])&&(i=RegExp("</"+c[2],"g")),o=P):c[3]!==void 0&&(o=P):o===P?c[0]===">"?(o=i??O,h=-1):c[1]===void 0?h=-2:(h=o.lastIndex-c[2].length,p=c[1],o=c[3]===void 0?P:c[3]==='"'?Qe:Ze):o===Qe||o===Ze?o=P:o===Ye||o===Ge?o=O:(o=P,i=void 0);let m=o===P&&n[a+1].startsWith("/>")?" ":"";s+=o===O?l+jt:h>=0?(r.push(p),l.slice(0,h)+tt+l.slice(h)+k+m):l+k+(h===-2?a:m)}return[st(n,s+(n[t]||"<?>")+(e===2?"</svg>":e===3?"</math>":"")),r]},D=class n{constructor({strings:e,_$litType$:t},r){let i;this.parts=[];let s=0,o=0,a=e.length-1,l=this.parts,[p,c]=zt(e,t);if(this.el=n.createElement(p,r),A.currentNode=this.el.content,t===2||t===3){let h=this.el.content.firstChild;h.replaceWith(...h.childNodes)}for(;(i=A.nextNode())!==null&&l.length<a;){if(i.nodeType===1){if(i.hasAttributes())for(let h of i.getAttributeNames())if(h.endsWith(tt)){let f=c[o++],m=i.getAttribute(h).split(k),x=/([.?@])?(.*)/.exec(f);l.push({type:1,index:s,name:x[2],strings:m,ctor:x[1]==="."?ve:x[1]==="?"?be:x[1]==="@"?xe:N}),i.removeAttribute(h)}else h.startsWith(k)&&(l.push({type:6,index:s}),i.removeAttribute(h));if(it.test(i.tagName)){let h=i.textContent.split(k),f=h.length-1;if(f>0){i.textContent=Y?Y.emptyScript:"";for(let m=0;m<f;m++)i.append(h[m],H()),A.nextNode(),l.push({type:2,index:++s});i.append(h[f],H())}}}else if(i.nodeType===8)if(i.data===rt)l.push({type:2,index:s});else{let h=-1;for(;(h=i.data.indexOf(k,h+1))!==-1;)l.push({type:7,index:s}),h+=k.length-1}s++}}static createElement(e,t){let r=E.createElement("template");return r.innerHTML=e,r}};function T(n,e,t=n,r){if(e===w)return e;let i=r!==void 0?t._$Co?.[r]:t._$Cl,s=B(e)?void 0:e._$litDirective$;return i?.constructor!==s&&(i?._$AO?.(!1),s===void 0?i=void 0:(i=new s(n),i._$AT(n,t,r)),r!==void 0?(t._$Co??=[])[r]=i:t._$Cl=i),i!==void 0&&(e=T(n,i._$AS(n,e.values),i,r)),e}var ge=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:r}=this._$AD,i=(e?.creationScope??E).importNode(t,!0);A.currentNode=i;let s=A.nextNode(),o=0,a=0,l=r[0];for(;l!==void 0;){if(o===l.index){let p;l.type===2?p=new I(s,s.nextSibling,this,e):l.type===1?p=new l.ctor(s,l.name,l.strings,this,e):l.type===6&&(p=new ye(s,this,e)),this._$AV.push(p),l=r[++a]}o!==l?.index&&(s=A.nextNode(),o++)}return A.currentNode=E,i}p(e){let t=0;for(let r of this._$AV)r!==void 0&&(r.strings!==void 0?(r._$AI(e,r,t),t+=r.strings.length-2):r._$AI(e[t])),t++}},I=class n{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,r,i){this.type=2,this._$AH=u,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=r,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=T(this,e,t),B(e)?e===u||e==null||e===""?(this._$AH!==u&&this._$AR(),this._$AH=u):e!==this._$AH&&e!==w&&this._(e):e._$litType$!==void 0?this.$(e):e.nodeType!==void 0?this.T(e):Ut(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==u&&B(this._$AH)?this._$AA.nextSibling.data=e:this.T(E.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:r}=e,i=typeof r=="number"?this._$AC(e):(r.el===void 0&&(r.el=D.createElement(st(r.h,r.h[0]),this.options)),r);if(this._$AH?._$AD===i)this._$AH.p(t);else{let s=new ge(i,this),o=s.u(this.options);s.p(t),this.T(o),this._$AH=s}}_$AC(e){let t=et.get(e.strings);return t===void 0&&et.set(e.strings,t=new D(e)),t}k(e){ke(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,r,i=0;for(let s of e)i===t.length?t.push(r=new n(this.O(H()),this.O(H()),this,this.options)):r=t[i],r._$AI(s),i++;i<t.length&&(this._$AR(r&&r._$AB.nextSibling,i),t.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let r=Xe(e).nextSibling;Xe(e).remove(),e=r}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},N=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,r,i,s){this.type=1,this._$AH=u,this._$AN=void 0,this.element=e,this.name=t,this._$AM=i,this.options=s,r.length>2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=u}_$AI(e,t=this,r,i){let s=this.strings,o=!1;if(s===void 0)e=T(this,e,t,0),o=!B(e)||e!==this._$AH&&e!==w,o&&(this._$AH=e);else{let a=e,l,p;for(e=s[0],l=0;l<s.length-1;l++)p=T(this,a[r+l],t,l),p===w&&(p=this._$AH[l]),o||=!B(p)||p!==this._$AH[l],p===u?e=u:e!==u&&(e+=(p??"")+s[l+1]),this._$AH[l]=p}o&&!i&&this.j(e)}j(e){e===u?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??"")}},ve=class extends N{constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===u?void 0:e}},be=class extends N{constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==u)}},xe=class extends N{constructor(e,t,r,i,s){super(e,t,r,i,s),this.type=5}_$AI(e,t=this){if((e=T(this,e,t,0)??u)===w)return;let r=this._$AH,i=e===u&&r!==u||e.capture!==r.capture||e.once!==r.once||e.passive!==r.passive,s=e!==u&&(r===u||i);i&&this.element.removeEventListener(this.name,this,r),s&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},ye=class{constructor(e,t,r){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(e){T(this,e)}};var qt=we.litHtmlPolyfillSupport;qt?.(D,I),(we.litHtmlVersions??=[]).push("3.3.3");var ot=(n,e,t)=>{let r=t?.renderBefore??e,i=r._$litPart$;if(i===void 0){let s=t?.renderBefore??null;r._$litPart$=i=new I(e.insertBefore(H(),s),s,void 0,t??{})}return i._$AI(n),i};var Pe=globalThis,$=class extends y{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=ot(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return w}};$._$litElement$=!0,$.finalized=!0,Pe.litElementHydrateSupport?.({LitElement:$});var Ft=Pe.litElementPolyfillSupport;Ft?.({LitElement:$});(Pe.litElementVersions??=[]).push("4.2.2");var g=class extends ${static properties={app:{attribute:!1}};#e;createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.#t()}disconnectedCallback(){super.disconnectedCallback(),this.#e?.(),this.#e=void 0}willUpdate(e){e.has("app")&&this.#t()}#t(){this.#e?.(),this.#e=this.app?.subscribe(()=>this.requestUpdate())}};var at=nt`<g fill="none" stroke="currentColor" stroke-linecap="round"><path d="M184 56H86q-30 0-30 30v98M328 56h98q30 0 30 30v98M184 456H86q-30 0-30-30v-98M328 456h98q30 0 30-30v-98" stroke-width="34" stroke-linejoin="round"/><path d="M176 182v148m0-148c0 74 60 74 100 74" stroke-width="28"/></g><g fill="currentColor"><circle cx="176" cy="172" r="32"/><circle cx="176" cy="340" r="32"/><path d="M284 200l78 56-78 56z" stroke="currentColor" stroke-width="34" stroke-linejoin="round"/></g>`,R=d`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 8.5l3 3 6-7"/></svg>`,G=d`<svg viewBox="0 0 16 16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>`,lt=d`<svg viewBox="0 0 16 16" fill="currentColor"><path d="M3 3h1.6v10H3zM13 3.6v8.8a.6.6 0 0 1-.92.5L5.8 8.5a.6.6 0 0 1 0-1l6.28-4.4a.6.6 0 0 1 .92.5z"/></svg>`,pt=d`<svg viewBox="0 0 16 16" fill="currentColor"><path d="M11.4 3H13v10h-1.6zM3 3.6v8.8a.6.6 0 0 0 .92.5l6.28-4.4a.6.6 0 0 0 0-1L3.92 3.1A.6.6 0 0 0 3 3.6z"/></svg>`,ht=d`<svg viewBox="0 0 16 16" fill="currentColor"><path d="M4.5 2.9v10.2a.7.7 0 0 0 1.06.6l8.1-5.1a.7.7 0 0 0 0-1.2l-8.1-5.1a.7.7 0 0 0-1.06.6z"/></svg>`,dt=d`<svg viewBox="0 0 16 16" fill="currentColor"><rect x="3.5" y="2.5" width="3.2" height="11" rx=".8"/><rect x="9.3" y="2.5" width="3.2" height="11" rx=".8"/></svg>`,ct=d`<svg class="spin" viewBox="0 0 50 50" aria-hidden="true"><circle cx="25" cy="25" r="18"/></svg>`,ut=d`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"><path d="M3 2.75h10a1.25 1.25 0 0 1 1.25 1.25v6.5A1.25 1.25 0 0 1 13 11.75H7.5L4.5 14v-2.25H3A1.25 1.25 0 0 1 1.75 10.5V4A1.25 1.25 0 0 1 3 2.75z"/></svg>`,ft=d`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4"><rect x="5.25" y="5.25" width="8" height="8" rx="1.5"/><path d="M10.75 3.5V3.25a1.5 1.5 0 0 0-1.5-1.5h-5.5a1.5 1.5 0 0 0-1.5 1.5v5.5a1.5 1.5 0 0 0 1.5 1.5H4"/></svg>`,mt=d`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6h2.2L8 3.2v9.6L4.7 10H2.5z" fill="currentColor" stroke="none"/><path d="M10.6 5.6a3.4 3.4 0 0 1 0 4.8M12.4 3.9a5.8 5.8 0 0 1 0 8.2"/></svg>`,gt=d`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"><path d="M2.5 6h2.2L8 3.2v9.6L4.7 10H2.5z" fill="currentColor" stroke="none"/><path d="M10.5 6l3.5 4M14 6l-3.5 4"/></svg>`,vt=d`<svg viewBox="0 0 50 50"><circle cx="25" cy="25" r="20"/></svg>`;var Z=class extends g{render(){let t=this.app?.meta;return d`<header class="top">
7
- <svg class="logo" viewBox="0 0 512 512" aria-label="framefields" role="img">${at}</svg>
8
- <span class="sep" aria-hidden="true"></span>
4
+ `);if(r)return r}return typeof n=="string"?n:String(n)}function Le(n){let e=new Set;return(t,r)=>{let i=r.map(Nt).join(" ").trim(),s=t+i.replace(/\d+/g,"#");!i||e.has(s)||e.size>100||(e.add(s),n({level:t,message:i.slice(0,4e3)}))}}function Oe(n,e){let t=n.error.bind(n),r=n.warn.bind(n);n.error=(...i)=>{t(...i),e("error",i)},n.warn=(...i)=>{r(...i),typeof i[0]=="string"&&i[0].startsWith("[framefields]")&&e("warning",i)}}var Be="/@framefields/player.js";async function he(n){let e=await n;if(!e.ok)throw new Error(`HTTP ${e.status}`);return await e.json()}function Ie(n,e,t=!1){return fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e),keepalive:t})}function je(){return{meta:()=>he(fetch("/meta")),listNotes:async()=>{let n=await he(fetch("/@framefields/notes"));return Array.isArray(n)?n:[]},changeNote:n=>he(Ie("/@framefields/notes",n)),log(n){Ie("/@framefields/log",n,!0).catch(()=>{})},mixAudio(){fetch("/audio/mix",{method:"POST"}).catch(()=>{})},async audio(){let n=await fetch("/audio");if(!n.ok)throw new Error(`HTTP ${n.status}`);return n.arrayBuffer()},events(n){let e=new EventSource("/events"),t=r=>JSON.parse(r.data);return e.addEventListener("hello",r=>n.hello(t(r).session)),e.addEventListener("error",()=>n.lost()),e.addEventListener("notes",r=>n.notes(t(r))),e.addEventListener("audio",r=>n.audio(t(r))),()=>e.close()}}}var C=1200,He=.001;var W={mixing:"Mixing audio",loading:"Loading audio",ready:"Audio ready",none:"No audio",error:"Audio failed"},w=2,Rt=4,Lt=64;function Ot(){let n;try{n=new Worker(Be,{type:"module"})}catch{return null}let e=new Map,t=0,r=null,i=o=>{r??=o;for(let a of e.values())a.reject(r);e.clear()},s=new Promise((o,a)=>{n.onmessage=l=>{let p=l.data;if("ready"in p){if(p.ready)o();else{let d=new Error(p.error);a(d),i(d)}return}let h=e.get(p.id);h&&(e.delete(p.id),"error"in p?h.reject(new Error(p.error)):h.resolve(p.mix))},n.onerror=l=>{let p=new Error(l.message||"the mixing worker failed");a(p),i(p)}});return s.catch(()=>{}),{async mix(o,a){if(await s,r)throw r;return new Promise((l,p)=>{let h=++t;e.set(h,{resolve:l,reject:p}),n.postMessage({id:h,range:o,chain:a})})},stop(){n.terminate(),i(new Error("stopped"))}}}var ce=class{constructor(e,t){this.player=e;this.total=Math.max(1,Math.ceil(t/w))}player;worker=Ot();blocks=new Map;order=[];pending=new Map;queue=[];busy=!1;seen=new Set;peak=0;gain=1;fill=0;filling=!1;total;mix(e,t){let r=this.worker;return r?r.mix(e,t).catch(i=>(this.worker&&(console.warn("The soundtrack's mixing worker failed, so the page mixes it:",i),this.worker.stop(),this.worker=null),this.player.mixAudio(e,t))):this.player.mixAudio(e,t)}};function De(n,e){let t=new Float32Array(n.length);for(let r=0;r<n.length;r++){let i=Math.tanh(n[r]*e);t[r]=Number.isNaN(i)?0:i}return t}var q=class{constructor(e){this.host=e}host;mode="browser";state="mixing";error="";buffer=null;peaks=null;peaksVersion=0;muted=!1;volume=.9;#e=null;#t=null;#i=null;#r=null;#s=null;#o=null;get usable(){return this.state==="ready"&&(!!this.buffer||!!this.#r)}get durationSec(){return this.buffer?this.buffer.duration:null}get mixed(){let e=this.#r;if(!e)return null;let t=0;for(let r of e.blocks.values())r.exact&&t++;return{blocks:e.seen.size,of:e.total,exact:t}}get mixer(){return this.#r?this.#r.worker?"worker":"page":this.mode==="server"?"server":null}attach(e,t){this.#o=e,this.mode==="browser"&&this.#p(e,t)}load(e,t){if(e?.state==="browser"){this.mode="browser",this.#n("mixing"),this.#o&&this.#p(this.#o,t);return}if(this.mode="server",this.stopClock(),this.buffer=null,this.#a(null),e?.state!=="ready"){this.#n(e?.state??"none",e?.state==="error"?e.error:"");return}this.#a(e.peaks),this.#n("loading");let r=this.#c();this.host.server.audio().then(i=>r.decodeAudioData(i)).then(i=>{this.buffer=i,this.#n("ready")},i=>this.#n("error",String(i?.message??i)))}async ready(e){let t=this.#r;!t||this.state==="none"||(await this.#d(t,this.#m(e),!0).catch(()=>{}),this.#r&&this.state==="mixing"&&this.#n("ready"))}get waitsBeforePlay(){return!!this.#r&&this.state!=="none"}setMuted(e){this.muted=e,this.#u()}setVolume(e){this.volume=e,this.muted=e===0,this.#u()}startClock(e,t){let r=this.#e;if(this.#r&&r&&this.state==="ready")return this.#f(this.#r,r,e/t);if(this.buffer&&r&&this.#t){r.resume();let s=r.createBufferSource();s.buffer=this.buffer,s.connect(this.#t);let o=r.currentTime+.06,a=e/t;return a<this.buffer.duration&&s.start(o,a),this.#i=s,()=>Math.max(0,r.currentTime-o)}let i=performance.now();return()=>(performance.now()-i)/1e3}stopClock(){this.#$();let e=this.#i;if(e){try{e.stop()}catch{}e.disconnect(),this.#i=null}}#n(e,t=""){this.state=e,this.error=t,this.host.changed()}#a(e){this.peaks=e,this.peaksVersion++}#l(){let e=this.host.film();return e?e.frameCount/e.fps:0}#m(e){let t=this.host.film()?.fps??30;return Math.floor(e/t/w)}#c(){if(this.#e)return this.#e;let e=window.AudioContext??window.webkitAudioContext,t=new e;return this.#t=t.createGain(),this.#t.connect(t.destination),this.#e=t,this.#u(),t}#u(){this.#t&&(this.#t.gain.value=this.muted?0:this.volume),this.host.changed()}#p(e,t){this.#r?.worker?.stop(),this.stopClock(),this.buffer=null,this.#a(new Array(C).fill(0));let r=new ce(e,this.#l());this.#r=r,this.#c(),this.#n("mixing"),this.#d(r,this.#m(t),!0).then(()=>{this.#r===r&&this.state==="mixing"&&this.#n("ready")},()=>{})}#d(e,t,r){let i=e.blocks.get(t);if(i)return Promise.resolve(i);let s=e.pending.get(t);if(s)return r&&It(e,t),s;let o=Ue(e,t,t===e.fill?"fill":"play",r,!0);return this.#h(e),o}#h(e){if(e.busy||this.#r!==e||!e.queue.length&&(!e.filling&&e.fill<e.total&&Ue(e,e.fill,"fill",!1,!e.pending.has(e.fill)),!e.queue.length))return;e.busy=!0;let t=e.queue.shift(),r=this.#l(),i={startSec:t.i*w,endSec:Math.min(r,(t.i+1)*w)};e.mix(i,t.chain).then(s=>{this.#r===e&&this.#v(e,t.i,s),t.chain==="fill"&&(e.fill=t.i+1,e.filling=!1),t.resolve(e.blocks.get(t.i))},s=>{t.chain==="fill"&&(e.filling=!1),t.reject(s),this.#g(e,s)}).then(()=>{t.own&&e.pending.delete(t.i),e.busy=!1,this.#h(e)})}#v(e,t,r){let i={left:r.left,right:r.right,sampleRate:r.sampleRate,exact:r.exact},s=e.blocks.get(t);if(!s||!s.exact||i.exact)for(e.blocks.set(t,i),e.order.push(t);e.order.length>Lt;)e.blocks.delete(e.order.shift());if(!e.seen.has(t)){if(e.seen.add(t),e.peak=Math.max(e.peak,r.peak),this.#b(t,i),e.seen.size<e.total){this.host.changed();return}e.gain=e.peak>.95?.92/e.peak:1,e.peak<He?this.#n("none"):this.host.changed()}}#b(e,t){let r=this.peaks;if(!r)return;let i=this.#l(),s=Math.floor(e*w/i*C),o=Math.min(C,Math.ceil(Math.min(i,(e+1)*w)/i*C)),a=i/C*t.sampleRate,l=e*w*t.sampleRate;for(let p=s;p<o;p++){let h=Math.max(0,Math.floor(p*a-l)),d=Math.min(t.left.length,Math.floor((p+1)*a-l)),f=r[p];for(let m=h;m<d;m++)f=Math.max(f,Math.abs(t.left[m]),Math.abs(t.right[m]));r[p]=Math.min(1,f)}this.peaksVersion++}#g(e,t){this.#r===e&&(e.worker?.stop(),this.#r=null,this.stopClock(),console.warn("Mixing the soundtrack in the browser failed, so the preview server mixes it:",t),this.mode="server",this.#n("mixing"),this.host.server.mixAudio())}#f(e,t,r){t.resume();let i={t0:r,startAt:t.currentTime+.08,next:Math.floor(r/w),sources:[],timer:void 0};this.#s=i;let s=()=>{if(this.#s!==i||this.#r!==e)return;let o=t.currentTime-i.startAt+i.t0;for(;i.next<e.total&&i.next*w<o+Rt;){let a=e.blocks.get(i.next);if(!a){this.#d(e,i.next,!0).then(s,()=>{});return}this.#k(t,i,i.next,a,e.gain),i.next++}};return i.timer=setInterval(s,250),s(),()=>Math.max(0,t.currentTime-i.startAt)}#k(e,t,r,i,s){if(!this.#t)return;let o=e.createBuffer(2,i.left.length,i.sampleRate);o.copyToChannel(De(i.left,s),0),o.copyToChannel(De(i.right,s),1);let a=e.createBufferSource();a.buffer=o,a.connect(this.#t);let l=t.startAt+(r*w-t.t0),p=Math.max(l,e.currentTime+.02),h=p-l;h>=o.duration||(a.start(p,h),t.sources.push(a),a.onended=()=>{t.sources=t.sources.filter(d=>d!==a)})}#$(){let e=this.#s;if(this.#s=null,!!e){clearInterval(e.timer);for(let t of e.sources){try{t.stop()}catch{}t.disconnect()}}}};function Ue(n,e,t,r,i){t==="fill"&&(n.filling=!0);let s=new Promise((o,a)=>{let l={i:e,chain:t,own:i,resolve:o,reject:a};r?n.queue.unshift(l):n.queue.push(l)});return i?n.pending.set(e,s):s.catch(()=>{}),s}function It(n,e){let t=n.queue.findIndex(r=>r.i===e);t>0&&n.queue.unshift(n.queue.splice(t,1)[0])}function Bt(n,e,t){return t&&t.w>.01&&t.h>.01?{frame:n,...t,text:""}:{frame:n,x:e.x,y:e.y,text:""}}var ue=n=>new Promise(e=>setTimeout(e,n)),V=class extends EventTarget{embedded;meta=null;player=null;pageState="loading";error=null;frame=0;playing=!1;stalled=!1;offline=!1;fps={state:"paused",fps:null};notesOn=!1;notes=[];draft=null;openId=null;saving=!1;saveError=!1;panelOpen=!1;toastText="";toastOn=!1;soundtrack;report;server;#e;#t;#i=null;#r=!1;#s=0;#o;#n=0;#a=new Set;#l=[];#m;#c;#u=new AbortController;#p=!1;constructor(e={}){super(),this.server=e.server??je(),this.#e=e.win??window,this.embedded=e.embedded??new URLSearchParams(this.#e.location.search).get("embed")==="1",this.report=Le(t=>this.server.log(t)),this.#t=new F(()=>this.meta?.fps??1/0),this.soundtrack=new q({server:this.server,film:()=>this.meta,changed:()=>this.changed()})}get lastFrame(){return(this.meta?.frameCount??1)-1}get buffering(){return this.pageState!=="error"&&(this.#r||this.stalled)}noteById(e){return this.notes.find(t=>t.id===e)}get openCount(){return this.notes.filter(e=>!e.done).length}get canNote(){return this.notesOn&&!!this.player&&!this.playing}changed(){this.#p||(this.#p=!0,queueMicrotask(()=>{this.#p=!1,this.dispatchEvent(new Event("change"))}))}subscribe(e){return this.addEventListener("change",e),()=>this.removeEventListener("change",e)}on(e,t){let r=i=>t(i.detail);return this.addEventListener(e,r),()=>this.removeEventListener(e,r)}#d(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t}))}get position(){let e=this.meta?.fps??30;return{frame:this.frame,time:Number((this.frame/e).toFixed(3)),playing:this.playing}}#h(){this.#d("position",this.position)}async start(){let e=this.#e,t=this.#u.signal,r=this.server.events({hello:l=>this.#$(l),lost:()=>this.#C(),notes:l=>this.#S(l),audio:l=>this.#T(l)});t.addEventListener("abort",r);let i={signal:t};e.addEventListener("framefields:player",()=>{this.meta&&this.#v()},i),e.addEventListener("error",l=>{this.player?this.report("error",[l.error??l.message]):this.showError(l.error??l.message)},i),e.addEventListener("unhandledrejection",l=>this.report("error",[l.reason]),i),e.addEventListener("hashchange",()=>this.#N(),i),e.document.addEventListener("visibilitychange",()=>{e.document.hidden&&this.playing&&this.pause()},i),e.framefieldsPreview=this.api();let s=await this.server.meta(),{audio:o,...a}=s;this.#i=a.session,this.meta=a,e.document.title=`${a.title} \xB7 preview`,this.notesOn=!!a.notesDir,this.#O(),this.soundtrack.load(o,this.frame),this.#P(pe(e.location.hash,a.fps,a.frameCount)??0),this.#r=!0,this.#v()}close(){this.#u.abort(),this.#y()}#v(){let e=this.#e.framefieldsPlayer;e&&e.then(t=>{this.player=t,t.onFrameError=(r,i)=>this.#k(r,i),this.soundtrack.attach(t,this.frame),this.changed(),this.#E(this.frame).then(()=>this.#b())},t=>{this.showError(t),this.#e.document.documentElement.dataset.preview="error",this.#g(t instanceof Error?t:new Error(String(t)))})}#b(){this.pageState="ready",this.#e.document.documentElement.dataset.preview="ready",this.#g(),this.#w(),this.changed(),this.#d("ready",void 0)}whenReady(){return this.player?Promise.resolve():this.pageState==="error"?Promise.reject(new Error(this.error??"the preview failed")):new Promise((e,t)=>this.#l.push([e,t]))}#g(e){for(let[t,r]of this.#l.splice(0))e?r(e):t()}showError(e){this.report("error",[e]),this.pageState="error",this.error=String(e?.message??e),this.changed(),this.#d("build",{status:"error",message:this.error})}#f=new Set;#k(e,t){let r=`frame ${e}: ${String(t?.message??t)}`,i=r.replace(/\d+/g,"#");this.#f.has(i)||this.#f.size>100||(this.#f.add(i),this.#d("build",{status:"error",message:r}))}#$(e){if(this.#i&&e!==this.#i){this.#d("build",{status:"building"}),this.#e.location.reload();return}this.offline=!1,this.changed()}#C(){this.meta&&(this.playing&&(this.#y(),this.#A()),this.offline=!0,this.changed())}#T(e){this.meta&&this.soundtrack.load(e,this.frame)}#P(e){this.frame=e,this.changed()}#E(e){this.#P(e);let t=this.player;return t?(this.#r=!0,t.render(e).then(()=>{this.#r=!1,this.changed()})):Promise.resolve()}seek(e){this.#y();let t=this.#E(_(e,this.meta?.frameCount??1));return this.#A(),this.#w(),t.then(()=>this.#h())}step(e){return this.seek(this.frame+e)}#A(){if(!this.meta)return;let{location:e,history:t}=this.#e,r=_e(this.frame,this.meta.fps)||e.pathname+e.search;try{t.replaceState(null,"",r)}catch{}}#N(){let e=this.meta;if(!e)return;let t=pe(this.#e.location.hash,e.fps,e.frameCount);t!==null&&(this.playing&&this.pause(),t!==this.frame&&this.seek(t))}#w(){clearTimeout(this.#o),this.#n++,!(!this.player?.hasVision||this.playing)&&(this.#o=setTimeout(()=>{this.#R()},1e3))}async#R(){let e=this.player,t=this.meta;if(!e||!t)return;let r=++this.#n,i=Math.min(this.lastFrame,this.frame+Math.round(t.fps*20));for(let s=this.frame+1;s<=i&&r===this.#n&&!this.playing;s++)if(!this.#a.has(s)){if(!await e.warm(s)){this.#w();return}this.#a.add(s),await ue(0)}}play(){if(this.playing||!this.player)return;this.playing=!0,clearTimeout(this.#o),this.#n++;let e=++this.#s,t=()=>this.playing&&e===this.#s;this.openId!=null&&this.closePop(),this.draft&&!this.draft.text.trim()&&this.cancelDraft(),this.frame>=this.lastFrame&&(this.frame=0),this.changed(),this.#h(),this.#L(this.player,t).catch(r=>this.report("error",[r])).finally(()=>{e===this.#s&&this.playing&&this.pause()})}pause(){this.#y(),this.#A(),this.#E(this.frame).then(()=>this.#w())}togglePlay(){this.playing?this.pause():this.play()}#y(){let e=this.playing;this.playing=!1,this.soundtrack.stopClock(),this.stalled=!1,this.#t.stop(),clearInterval(this.#c),this.#c=void 0,this.#M(),e&&this.#h()}#M(){this.fps=this.#t.read(),this.changed()}#x(e){this.stalled=e,this.changed()}async#L(e,t){let r=this.meta?.fps??30;if(this.#t.start(),this.#M(),this.#c=setInterval(()=>this.#M(),500),this.soundtrack.waitsBeforePlay){if(this.#x(!0),await this.soundtrack.ready(this.frame),!t())return;this.#x(!1)}if(this.soundtrack.state==="loading"){for(this.#x(!0);t()&&this.soundtrack.state==="loading";)await ue(50);if(!t())return;this.#x(!1)}let i=this.frame,s=this.soundtrack.startClock(i,r),o=-1;for(;t();){let a=Math.min(this.lastFrame,i+Math.floor(s()*r));if(a===o){await ue(4);continue}this.#P(a),this.#h();let l=await e.render(a,{cache:!1});if(!t()||(o=l,this.#t.record(l),l>=this.lastFrame))return}}#O(){this.notesOn&&this.server.listNotes().then(e=>this.#S(e),()=>{})}#S(e){this.notes=e,this.openId!=null&&!this.noteById(this.openId)&&this.closePop(),this.changed()}#_(e){let t=this.notes.findIndex(r=>r.id===e.id);t>=0?this.notes[t]=e:this.notes.push(e),this.changed()}beginDraft(e,t){this.openId=null,this.saveError=!1,this.draft=Bt(this.frame,e,t),this.changed()}setDraftText(e){this.draft&&(this.draft.text=e,this.changed())}cancelDraft(){this.draft&&(this.draft=null,this.closePop())}async saveDraft(){let e=this.draft,t=this.meta,r=e?.text.trim();if(!e||!t||!r||this.saving)return!1;this.saving=!0,this.saveError=!1,this.changed();try{let i;try{this.player&&(i=await Se(this.player,e))}catch(o){this.report("warning",["[framefields] no picture for the note:",o])}let s=await this.server.changeNote({op:"add",note:{frame:e.frame,time:e.frame/t.fps,x:e.x,y:e.y,w:e.w,h:e.h,text:r,image:i}});return this.draft===e&&(this.draft=null),this.closePop(),this.#_(s),this.toast(`Note ${s.id} saved`),!0}catch{return this.saveError=!0,!1}finally{this.saving=!1,this.changed()}}openCard(e){this.noteById(e)&&(this.draft&&this.cancelDraft(),this.openId=e,this.changed())}closePop(){this.openId=null,this.changed()}setDone(e,t){this.server.changeNote({op:"update",id:e,done:t}).then(r=>this.#_(r),()=>this.toast("Couldn't save. Is the preview running?"))}removeNote(e){this.server.changeNote({op:"remove",id:e}).then(()=>{this.notes=this.notes.filter(t=>t.id!==e),this.closePop()},()=>this.toast("Couldn't delete. Is the preview running?"))}goToNote(e){let t=this.noteById(e);t&&(this.panelOpen=!1,this.seek(t.frame).then(()=>this.openCard(e)))}setPanel(e){this.panelOpen=e,this.changed()}toast(e){this.toastText=e,this.toastOn=!0,clearTimeout(this.#m),this.#m=setTimeout(()=>{this.toastOn=!1,this.changed()},2200),this.changed()}key({key:e,shiftKey:t=!1}){if(!this.meta||!this.player)return!1;let r=Math.round(this.meta.fps);switch(e){case"ArrowLeft":case"ArrowRight":{let i=(t?r:1)*(e==="ArrowLeft"?-1:1);return this.step(i),!0}case" ":return this.togglePlay(),!0;case"Home":return this.seek(0),!0;case"End":return this.seek(this.lastFrame),!0;default:return!1}}api(){return{seek:async e=>(await this.whenReady(),this.seek(Number(e)*(this.meta?.fps??30))),seekFrame:async e=>(await this.whenReady(),this.seek(e)),play:async()=>{await this.whenReady(),this.play()},pause:()=>{this.playing&&this.pause()},notes:()=>this.notes.slice(),state:()=>this.snapshot()}}snapshot(){let e=this.meta,t=this.#t.read().fps;return{state:this.pageState,error:this.pageState==="error"?this.error:null,frame:this.frame,time:e?Number((this.frame/e.fps).toFixed(3)):0,playing:this.playing,buffering:this.stalled,audio:this.soundtrack.state,audioMixed:this.soundtrack.mixed,audioMixer:this.soundtrack.mixer,connected:!this.offline,playbackFps:t==null?null:Number(t.toFixed(1)),renderMs:this.player?Math.round(this.player.lastRenderMs):null,meta:e&&{title:e.title,width:e.width,height:e.height,fps:e.fps,frameCount:e.frameCount,duration:Number((this.lastFrame/e.fps).toFixed(3))}}}};var jt=new Set(["seek","seekFrame","play","pause","state"]);function ze(n){if(typeof n!="object"||n===null)return null;let e=n;return e.type!=="framefields-preview:command"||typeof e.id!="string"||typeof e.command!="string"||!jt.has(e.command)||e.command==="seek"&&!Number.isFinite(e.time)||e.command==="seekFrame"&&!Number.isFinite(e.frame)?null:e}var Dt=250;function Fe(n,e,{win:t=window,now:r=()=>performance.now()}={}){let i=d=>e.postMessage(d,"*"),s=null,o=Number.NEGATIVE_INFINITY,a=n.on("ready",()=>{let d=n.meta;d&&i({type:"framefields-preview:ready",protocol:1,seekByHash:!0,meta:{title:d.title,width:d.width,height:d.height,fps:d.fps,frames:d.frameCount,duration:Number(((d.frameCount-1)/d.fps).toFixed(3))}})}),l=n.on("position",d=>{let f=s&&s.frame===d.frame&&s.playing===d.playing,m=d.playing&&s?.playing&&r()-o<Dt;f||m||(s=d,o=r(),i({type:"framefields-preview:state",...d}))}),p=n.on("build",d=>i({type:"framefields-preview:build",...d})),h=d=>{if(d.source!==e)return;let f=ze(d.data);f&&Ut(n,f).then(i)};return t.addEventListener("message",h),()=>{a(),l(),p(),t.removeEventListener("message",h)}}async function Ut(n,e){let{id:t}=e;try{switch(e.command){case"seek":await n.whenReady(),await n.seek(e.time*(n.meta?.fps??30));break;case"seekFrame":await n.whenReady(),await n.seek(e.frame);break;case"play":await n.whenReady(),n.play();break;case"pause":n.playing&&n.pause();break;case"state":break}return{type:"framefields-preview:reply",id:t,ok:!0,state:n.position}}catch(r){return{type:"framefields-preview:reply",id:t,ok:!1,error:String(r?.message??r)}}}var K=globalThis,J=K.ShadowRoot&&(K.ShadyCSS===void 0||K.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,We=Symbol(),qe=new WeakMap,X=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==We)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(J&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=qe.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&qe.set(t,e))}return e}toString(){return this.cssText}},Ve=n=>new X(typeof n=="string"?n:n+"",void 0,We);var Ke=(n,e)=>{if(J)n.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(let t of e){let r=document.createElement("style"),i=K.litNonce;i!==void 0&&r.setAttribute("nonce",i),r.textContent=t.cssText,n.appendChild(r)}},fe=J?n=>n:n=>n instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return Ve(t)})(n):n;var{is:zt,defineProperty:Ft,getOwnPropertyDescriptor:qt,getOwnPropertyNames:Wt,getOwnPropertySymbols:Vt,getPrototypeOf:Kt}=Object,Y=globalThis,Xe=Y.trustedTypes,Xt=Xe?Xe.emptyScript:"",Jt=Y.reactiveElementPolyfillSupport,O=(n,e)=>n,me={toAttribute(n,e){switch(e){case Boolean:n=n?Xt:null;break;case Object:case Array:n=n==null?n:JSON.stringify(n)}return n},fromAttribute(n,e){let t=n;switch(e){case Boolean:t=n!==null;break;case Number:t=n===null?null:Number(n);break;case Object:case Array:try{t=JSON.parse(n)}catch{t=null}}return t}},Ye=(n,e)=>!zt(n,e),Je={attribute:!0,type:String,converter:me,reflect:!1,useDefault:!1,hasChanged:Ye};Symbol.metadata??=Symbol("metadata"),Y.litPropertyMetadata??=new WeakMap;var y=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=Je){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){let r=Symbol(),i=this.getPropertyDescriptor(e,r,t);i!==void 0&&Ft(this.prototype,e,i)}}static getPropertyDescriptor(e,t,r){let{get:i,set:s}=qt(this.prototype,e)??{get(){return this[t]},set(o){this[t]=o}};return{get:i,set(o){let a=i?.call(this);s?.call(this,o),this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??Je}static _$Ei(){if(this.hasOwnProperty(O("elementProperties")))return;let e=Kt(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(O("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(O("properties"))){let t=this.properties,r=[...Wt(t),...Vt(t)];for(let i of r)this.createProperty(i,t[i])}let e=this[Symbol.metadata];if(e!==null){let t=litPropertyMetadata.get(e);if(t!==void 0)for(let[r,i]of t)this.elementProperties.set(r,i)}this._$Eh=new Map;for(let[t,r]of this.elementProperties){let i=this._$Eu(t,r);i!==void 0&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let i of r)t.unshift(fe(i))}else e!==void 0&&t.push(fe(e));return t}static _$Eu(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),this.renderRoot!==void 0&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){let e=new Map,t=this.constructor.elementProperties;for(let r of t.keys())this.hasOwnProperty(r)&&(e.set(r,this[r]),delete this[r]);e.size>0&&(this._$Ep=e)}createRenderRoot(){let e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Ke(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$ET(e,t){let r=this.constructor.elementProperties.get(e),i=this.constructor._$Eu(e,r);if(i!==void 0&&r.reflect===!0){let s=(r.converter?.toAttribute!==void 0?r.converter:me).toAttribute(t,r.type);this._$Em=e,s==null?this.removeAttribute(i):this.setAttribute(i,s),this._$Em=null}}_$AK(e,t){let r=this.constructor,i=r._$Eh.get(e);if(i!==void 0&&this._$Em!==i){let s=r.getPropertyOptions(i),o=typeof s.converter=="function"?{fromAttribute:s.converter}:s.converter?.fromAttribute!==void 0?s.converter:me;this._$Em=i;let a=o.fromAttribute(t,s.type);this[i]=a??this._$Ej?.get(i)??a,this._$Em=null}}requestUpdate(e,t,r,i=!1,s){if(e!==void 0){let o=this.constructor;if(i===!1&&(s=this[e]),r??=o.getPropertyOptions(e),!((r.hasChanged??Ye)(s,t)||r.useDefault&&r.reflect&&s===this._$Ej?.get(e)&&!this.hasAttribute(o._$Eu(e,r))))return;this.C(e,t,r)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(e,t,{useDefault:r,reflect:i,wrapped:s},o){r&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,o??t??this[e]),s!==!0||o!==void 0)||(this._$AL.has(e)||(this.hasUpdated||r||(t=void 0),this._$AL.set(e,t)),i===!0&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[i,s]of this._$Ep)this[i]=s;this._$Ep=void 0}let r=this.constructor.elementProperties;if(r.size>0)for(let[i,s]of r){let{wrapped:o}=s,a=this[i];o!==!0||this._$AL.has(i)||a===void 0||this.C(i,void 0,s,a)}}let e=!1,t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(r=>r.hostUpdate?.()),this.update(t)):this._$EM()}catch(r){throw e=!1,this._$EM(),r}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(e){}firstUpdated(e){}};y.elementStyles=[],y.shadowRootOptions={mode:"open"},y[O("elementProperties")]=new Map,y[O("finalized")]=new Map,Jt?.({ReactiveElement:y}),(Y.reactiveElementVersions??=[]).push("2.1.2");var ke=globalThis,Ge=n=>n,G=ke.trustedTypes,Ze=G?G.createPolicy("lit-html",{createHTML:n=>n}):void 0,nt="$lit$",k=`lit$${Math.random().toFixed(9).slice(2)}$`,st="?"+k,Yt=`<${st}>`,M=document,B=()=>M.createComment(""),j=n=>n===null||typeof n!="object"&&typeof n!="function",$e=Array.isArray,Gt=n=>$e(n)||typeof n?.[Symbol.iterator]=="function",ve=`[
5
+ \f\r]`,I=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Qe=/-->/g,et=/>/g,E=RegExp(`>|${ve}(?:([^\\s"'>=/]+)(${ve}*=${ve}*(?:[^
6
+ \f\r"'\`<>=]|("|')|))|$)`,"g"),tt=/'/g,rt=/"/g,ot=/^(?:script|style|textarea|title)$/i,Pe=n=>(e,...t)=>({_$litType$:n,strings:e,values:t}),c=Pe(1),at=Pe(2),qr=Pe(3),x=Symbol.for("lit-noChange"),u=Symbol.for("lit-nothing"),it=new WeakMap,A=M.createTreeWalker(M,129);function lt(n,e){if(!$e(n)||!n.hasOwnProperty("raw"))throw Error("invalid template strings array");return Ze!==void 0?Ze.createHTML(e):e}var Zt=(n,e)=>{let t=n.length-1,r=[],i,s=e===2?"<svg>":e===3?"<math>":"",o=I;for(let a=0;a<t;a++){let l=n[a],p,h,d=-1,f=0;for(;f<l.length&&(o.lastIndex=f,h=o.exec(l),h!==null);)f=o.lastIndex,o===I?h[1]==="!--"?o=Qe:h[1]!==void 0?o=et:h[2]!==void 0?(ot.test(h[2])&&(i=RegExp("</"+h[2],"g")),o=E):h[3]!==void 0&&(o=E):o===E?h[0]===">"?(o=i??I,d=-1):h[1]===void 0?d=-2:(d=o.lastIndex-h[2].length,p=h[1],o=h[3]===void 0?E:h[3]==='"'?rt:tt):o===rt||o===tt?o=E:o===Qe||o===et?o=I:(o=E,i=void 0);let m=o===E&&n[a+1].startsWith("/>")?" ":"";s+=o===I?l+Yt:d>=0?(r.push(p),l.slice(0,d)+nt+l.slice(d)+k+m):l+k+(d===-2?a:m)}return[lt(n,s+(n[t]||"<?>")+(e===2?"</svg>":e===3?"</math>":"")),r]},H=class n{constructor({strings:e,_$litType$:t},r){let i;this.parts=[];let s=0,o=0,a=e.length-1,l=this.parts,[p,h]=Zt(e,t);if(this.el=n.createElement(p,r),A.currentNode=this.el.content,t===2||t===3){let d=this.el.content.firstChild;d.replaceWith(...d.childNodes)}for(;(i=A.nextNode())!==null&&l.length<a;){if(i.nodeType===1){if(i.hasAttributes())for(let d of i.getAttributeNames())if(d.endsWith(nt)){let f=h[o++],m=i.getAttribute(d).split(k),b=/([.?@])?(.*)/.exec(f);l.push({type:1,index:s,name:b[2],strings:m,ctor:b[1]==="."?be:b[1]==="?"?we:b[1]==="@"?ye:N}),i.removeAttribute(d)}else d.startsWith(k)&&(l.push({type:6,index:s}),i.removeAttribute(d));if(ot.test(i.tagName)){let d=i.textContent.split(k),f=d.length-1;if(f>0){i.textContent=G?G.emptyScript:"";for(let m=0;m<f;m++)i.append(d[m],B()),A.nextNode(),l.push({type:2,index:++s});i.append(d[f],B())}}}else if(i.nodeType===8)if(i.data===st)l.push({type:2,index:s});else{let d=-1;for(;(d=i.data.indexOf(k,d+1))!==-1;)l.push({type:7,index:s}),d+=k.length-1}s++}}static createElement(e,t){let r=M.createElement("template");return r.innerHTML=e,r}};function T(n,e,t=n,r){if(e===x)return e;let i=r!==void 0?t._$Co?.[r]:t._$Cl,s=j(e)?void 0:e._$litDirective$;return i?.constructor!==s&&(i?._$AO?.(!1),s===void 0?i=void 0:(i=new s(n),i._$AT(n,t,r)),r!==void 0?(t._$Co??=[])[r]=i:t._$Cl=i),i!==void 0&&(e=T(n,i._$AS(n,e.values),i,r)),e}var ge=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:r}=this._$AD,i=(e?.creationScope??M).importNode(t,!0);A.currentNode=i;let s=A.nextNode(),o=0,a=0,l=r[0];for(;l!==void 0;){if(o===l.index){let p;l.type===2?p=new D(s,s.nextSibling,this,e):l.type===1?p=new l.ctor(s,l.name,l.strings,this,e):l.type===6&&(p=new xe(s,this,e)),this._$AV.push(p),l=r[++a]}o!==l?.index&&(s=A.nextNode(),o++)}return A.currentNode=M,i}p(e){let t=0;for(let r of this._$AV)r!==void 0&&(r.strings!==void 0?(r._$AI(e,r,t),t+=r.strings.length-2):r._$AI(e[t])),t++}},D=class n{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,r,i){this.type=2,this._$AH=u,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=r,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=T(this,e,t),j(e)?e===u||e==null||e===""?(this._$AH!==u&&this._$AR(),this._$AH=u):e!==this._$AH&&e!==x&&this._(e):e._$litType$!==void 0?this.$(e):e.nodeType!==void 0?this.T(e):Gt(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==u&&j(this._$AH)?this._$AA.nextSibling.data=e:this.T(M.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:r}=e,i=typeof r=="number"?this._$AC(e):(r.el===void 0&&(r.el=H.createElement(lt(r.h,r.h[0]),this.options)),r);if(this._$AH?._$AD===i)this._$AH.p(t);else{let s=new ge(i,this),o=s.u(this.options);s.p(t),this.T(o),this._$AH=s}}_$AC(e){let t=it.get(e.strings);return t===void 0&&it.set(e.strings,t=new H(e)),t}k(e){$e(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,r,i=0;for(let s of e)i===t.length?t.push(r=new n(this.O(B()),this.O(B()),this,this.options)):r=t[i],r._$AI(s),i++;i<t.length&&(this._$AR(r&&r._$AB.nextSibling,i),t.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let r=Ge(e).nextSibling;Ge(e).remove(),e=r}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},N=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,r,i,s){this.type=1,this._$AH=u,this._$AN=void 0,this.element=e,this.name=t,this._$AM=i,this.options=s,r.length>2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=u}_$AI(e,t=this,r,i){let s=this.strings,o=!1;if(s===void 0)e=T(this,e,t,0),o=!j(e)||e!==this._$AH&&e!==x,o&&(this._$AH=e);else{let a=e,l,p;for(e=s[0],l=0;l<s.length-1;l++)p=T(this,a[r+l],t,l),p===x&&(p=this._$AH[l]),o||=!j(p)||p!==this._$AH[l],p===u?e=u:e!==u&&(e+=(p??"")+s[l+1]),this._$AH[l]=p}o&&!i&&this.j(e)}j(e){e===u?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??"")}},be=class extends N{constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===u?void 0:e}},we=class extends N{constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==u)}},ye=class extends N{constructor(e,t,r,i,s){super(e,t,r,i,s),this.type=5}_$AI(e,t=this){if((e=T(this,e,t,0)??u)===x)return;let r=this._$AH,i=e===u&&r!==u||e.capture!==r.capture||e.once!==r.once||e.passive!==r.passive,s=e!==u&&(r===u||i);i&&this.element.removeEventListener(this.name,this,r),s&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},xe=class{constructor(e,t,r){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(e){T(this,e)}};var Qt=ke.litHtmlPolyfillSupport;Qt?.(H,D),(ke.litHtmlVersions??=[]).push("3.3.3");var dt=(n,e,t)=>{let r=t?.renderBefore??e,i=r._$litPart$;if(i===void 0){let s=t?.renderBefore??null;r._$litPart$=i=new D(e.insertBefore(B(),s),s,void 0,t??{})}return i._$AI(n),i};var Ee=globalThis,$=class extends y{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=dt(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return x}};$._$litElement$=!0,$.finalized=!0,Ee.litElementHydrateSupport?.({LitElement:$});var er=Ee.litElementPolyfillSupport;er?.({LitElement:$});(Ee.litElementVersions??=[]).push("4.2.2");var g=class extends ${static properties={app:{attribute:!1}};#e;createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.#t()}disconnectedCallback(){super.disconnectedCallback(),this.#e?.(),this.#e=void 0}willUpdate(e){e.has("app")&&this.#t()}#t(){this.#e?.(),this.#e=this.app?.subscribe(()=>this.requestUpdate())}};var pt=at`<g fill="none" stroke="currentColor" stroke-linecap="round"><path d="M184 56H86q-30 0-30 30v98M328 56h98q30 0 30 30v98M184 456H86q-30 0-30-30v-98M328 456h98q30 0 30-30v-98" stroke-width="34" stroke-linejoin="round"/><path d="M176 182v148m0-148c0 74 60 74 100 74" stroke-width="28"/></g><g fill="currentColor"><circle cx="176" cy="172" r="32"/><circle cx="176" cy="340" r="32"/><path d="M284 200l78 56-78 56z" stroke="currentColor" stroke-width="34" stroke-linejoin="round"/></g>`,R=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 8.5l3 3 6-7"/></svg>`,Z=c`<svg viewBox="0 0 16 16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>`,ht=c`<svg viewBox="0 0 16 16" fill="currentColor"><path d="M3 3h1.6v10H3zM13 3.6v8.8a.6.6 0 0 1-.92.5L5.8 8.5a.6.6 0 0 1 0-1l6.28-4.4a.6.6 0 0 1 .92.5z"/></svg>`,ct=c`<svg viewBox="0 0 16 16" fill="currentColor"><path d="M11.4 3H13v10h-1.6zM3 3.6v8.8a.6.6 0 0 0 .92.5l6.28-4.4a.6.6 0 0 0 0-1L3.92 3.1A.6.6 0 0 0 3 3.6z"/></svg>`,ut=c`<svg viewBox="0 0 16 16" fill="currentColor"><path d="M4.5 2.9v10.2a.7.7 0 0 0 1.06.6l8.1-5.1a.7.7 0 0 0 0-1.2l-8.1-5.1a.7.7 0 0 0-1.06.6z"/></svg>`,ft=c`<svg viewBox="0 0 16 16" fill="currentColor"><rect x="3.5" y="2.5" width="3.2" height="11" rx=".8"/><rect x="9.3" y="2.5" width="3.2" height="11" rx=".8"/></svg>`,mt=c`<svg class="spin" viewBox="0 0 50 50" aria-hidden="true"><circle cx="25" cy="25" r="18"/></svg>`,vt=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"><path d="M3 2.75h10a1.25 1.25 0 0 1 1.25 1.25v6.5A1.25 1.25 0 0 1 13 11.75H7.5L4.5 14v-2.25H3A1.25 1.25 0 0 1 1.75 10.5V4A1.25 1.25 0 0 1 3 2.75z"/></svg>`,gt=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4"><rect x="5.25" y="5.25" width="8" height="8" rx="1.5"/><path d="M10.75 3.5V3.25a1.5 1.5 0 0 0-1.5-1.5h-5.5a1.5 1.5 0 0 0-1.5 1.5v5.5a1.5 1.5 0 0 0 1.5 1.5H4"/></svg>`,bt=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 6h2.2L8 3.2v9.6L4.7 10H2.5z" fill="currentColor" stroke="none"/><path d="M10.6 5.6a3.4 3.4 0 0 1 0 4.8M12.4 3.9a5.8 5.8 0 0 1 0 8.2"/></svg>`,wt=c`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"><path d="M2.5 6h2.2L8 3.2v9.6L4.7 10H2.5z" fill="currentColor" stroke="none"/><path d="M10.5 6l3.5 4M14 6l-3.5 4"/></svg>`,yt=c`<svg viewBox="0 0 50 50"><circle cx="25" cy="25" r="20"/></svg>`;function Me(n){return n?.offline?c`<span
7
+ class="chip"
8
+ data-state="offline"
9
+ role="status"
10
+ aria-live="polite"
11
+ title="The preview command isn't running. This tab reconnects when it starts again."
12
+ ><span class="dot"></span><span>Preview stopped</span></span
13
+ >`:u}var Q=class extends g{render(){let e=this.app,t=e?.meta;return c`<header class="top">
14
+ <svg class="logo" viewBox="0 0 512 512" aria-label="framefields" role="img">${pt}</svg>
9
15
  <h1>${t?.title??"framefields preview"}</h1>
10
16
  <span class="grow"></span>
11
17
  <span class="spec tnum"
12
18
  >${t?`${t.width}\xD7${t.height} \xB7 ${t.fps} fps \xB7 ${v(t.frameCount-1,t.fps)}`:""}</span
13
19
  >
14
- ${this.#e()}
15
- </header>`}#e(){let e=this.app,t=e?.soundtrack;if(e?.offline)return d`<span
16
- class="chip"
17
- data-state="offline"
18
- role="status"
19
- aria-live="polite"
20
- title="The preview command isn't running. This tab reconnects when it starts again."
21
- ><span class="dot"></span><span>Preview stopped</span></span
22
- >`;let r=t?.state??"mixing",i=r==="mixing"||r==="loading";return d`<span
23
- class="chip"
24
- data-state=${r}
25
- role="status"
26
- aria-live="polite"
27
- title=${t?.error??""}
28
- ><span class=${i?"spinner":"dot"}></span
29
- ><span>${F[r]}</span></span
30
- >`}};var Q=class extends g{#e=null;#t=new ResizeObserver(()=>this.#a());connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this.#a)}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("resize",this.#a),this.#t.disconnect()}get#i(){let e=this.app;if(e)return e.draft?e.draft:e.openId==null?void 0:e.noteById(e.openId)}render(){let e=this.app,t=this.#i,r=e?.meta?e.draft?this.#r(e.draft,e.meta.fps):t?this.#s(t,e.meta.fps):u:u;return d`<div class="pop ${t?"on":""}" role="dialog" aria-label="Note">
20
+ ${Me(e)}
21
+ </header>`}};var ee=class extends g{#e=null;#t=new ResizeObserver(()=>this.#l());connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this.#l)}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("resize",this.#l),this.#t.disconnect()}get#i(){let e=this.app;if(e)return e.draft?e.draft:e.openId==null?void 0:e.noteById(e.openId)}render(){let e=this.app,t=this.#i,r=e?.meta?e.draft?this.#r(e.draft,e.meta.fps):t?this.#s(t,e.meta.fps):u:u;return c`<div class="pop ${t?"on":""}" role="dialog" aria-label="Note">
31
22
  ${r}
32
- </div>`}updated(){let e=this.#l();e&&this.#t.observe(e),this.#a();let t=this.app?.draft??null;t&&t!==this.#e&&this.querySelector("textarea")?.focus(),this.#e=t}#r(e,t){let r=this.app;if(!r)return u;let i=r.saving?"Saving\u2026":r.saveError?"Couldn't save. Is the preview running?":"Enter to add";return d`<div class="pop-head">
33
- <span class="badge">+</span>
23
+ </div>`}updated(){let e=this.#a();e&&this.#t.observe(e),this.#l();let t=this.app?.draft??null;t&&t!==this.#e&&this.querySelector("textarea")?.focus(),this.#e=t}#r(e,t){let r=this.app;if(!r)return u;let i=r.saving?"Saving\u2026":r.saveError?"Couldn't save. Is the preview running?":"Enter to add";return c`<div class="pop-head">
24
+ <span class="badge new">+</span>
34
25
  <span class="tnum"
35
26
  >${v(e.frame,t)} · ${e.w!=null?"area":"spot"}</span
36
27
  >
@@ -54,7 +45,7 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
54
45
  >
55
46
  Add note
56
47
  </button>
57
- </div>`}#s(e,t){let r=this.app;return r?d`<div class="pop-head">
48
+ </div>`}#s(e,t){let r=this.app;return r?c`<div class="pop-head">
58
49
  <span class="badge ${e.done?"done":""}">${e.id}</span>
59
50
  <span class="tnum grow">${v(e.frame,t)} · frame ${e.frame}</span>
60
51
  <button
@@ -63,7 +54,7 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
63
54
  aria-label="Close"
64
55
  @click=${()=>r.closePop()}
65
56
  >
66
- ${G}
57
+ ${Z}
67
58
  </button>
68
59
  </div>
69
60
  <div class="pop-text">${e.text}</div>
@@ -75,7 +66,7 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
75
66
  <button class="btn danger" @click=${()=>r.removeNote(e.id)}>
76
67
  Delete
77
68
  </button>
78
- </div>`:u}#o=e=>{let t=e.target;this.app?.setDraftText(t.value),t.style.height="auto",t.style.height=`${Math.min(180,t.scrollHeight)}px`};#n=e=>{e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),this.app?.saveDraft()),e.key==="Escape"&&(e.preventDefault(),this.app?.cancelDraft())};#l(){return this.closest("ff-preview")?.querySelector("ff-stage .stage")??null}#a=()=>{let e=this.querySelector(".pop"),t=this.#l(),r=this.#i;if(!e||!t||!r)return;let i=t.getBoundingClientRect(),s=(r.w??0)*i.width,o=(r.h??0)*i.height,a=i.left+r.x*i.width+s,l=i.top+r.y*i.height+o,p=e.offsetWidth,c=e.offsetHeight,h=16,f=a+h+p<=innerWidth-8?a+h:a-h-p-s,m=l+h+c<=innerHeight-8?l+h/2:l-c-h/2-o;e.style.left=`${Math.max(8,Math.min(innerWidth-p-8,f))}px`,e.style.top=`${Math.max(8,Math.min(innerHeight-c-8,m))}px`}};var ee=class extends g{#e=!1;render(){let e=this.app;if(!e)return d``;let t=e.meta?.fps??30,r=[...e.notes].sort(U);return d`<div
69
+ </div>`:u}#o=e=>{let t=e.target;this.app?.setDraftText(t.value),t.style.height="auto",t.style.height=`${Math.min(180,t.scrollHeight)}px`};#n=e=>{e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),this.app?.saveDraft()),e.key==="Escape"&&(e.preventDefault(),this.app?.cancelDraft())};#a(){return this.closest("ff-preview")?.querySelector("ff-stage .stage")??null}#l=()=>{let e=this.querySelector(".pop"),t=this.#a(),r=this.#i;if(!e||!t||!r)return;let i=t.getBoundingClientRect(),s=(r.w??0)*i.width,o=(r.h??0)*i.height,a=i.left+r.x*i.width+s,l=i.top+r.y*i.height+o,p=e.offsetWidth,h=e.offsetHeight,d=16,f=a+d+p<=innerWidth-8?a+d:a-d-p-s,m=l+d+h<=innerHeight-8?l+d/2:l-h-d/2-o;e.style.left=`${Math.max(8,Math.min(innerWidth-p-8,f))}px`,e.style.top=`${Math.max(8,Math.min(innerHeight-h-8,m))}px`}};var te=class extends g{#e=!1;render(){let e=this.app;if(!e)return c``;let t=e.meta?.fps??30,r=[...e.notes].sort(z);return c`<div
79
70
  class="notes-panel ${e.panelOpen?"on":""}"
80
71
  role="dialog"
81
72
  aria-label="Notes"
@@ -89,7 +80,7 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
89
80
  ?disabled=${e.openCount===0}
90
81
  @click=${this.#t}
91
82
  >
92
- ${ft}<span>${this.#e?"Copied":"Copy"}</span>
83
+ ${gt}<span>${this.#e?"Copied":"Copy"}</span>
93
84
  </button>
94
85
  <button
95
86
  class="btn x-btn"
@@ -97,11 +88,11 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
97
88
  aria-label="Close"
98
89
  @click=${()=>e.setPanel(!1)}
99
90
  >
100
- ${G}
91
+ ${Z}
101
92
  </button>
102
93
  </div>
103
94
  <div class="np-list">
104
- ${r.length?r.map(i=>{let s=i.done?"Reopen":"Mark done";return d`<div
95
+ ${r.length?r.map(i=>{let s=i.done?"Reopen":"Mark done";return c`<div
105
96
  class="note-row ${i.done?"done":""}"
106
97
  @click=${()=>e.goToNote(i.id)}
107
98
  >
@@ -120,25 +111,21 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
120
111
  >
121
112
  ${R}
122
113
  </button>
123
- </div>`}):d`<div class="np-empty">
114
+ </div>`}):c`<div class="np-empty">
124
115
  Pause and click the picture to pin a note to that spot and
125
116
  moment. Drag to mark an area.
126
117
  </div>`}
127
118
  </div>
128
- <div class="np-foot">
129
- Saved in ${Ne(e.meta?.notesDir??null)} with a picture of each
130
- spot. Ask your agent to go through them.
131
- </div>
132
- </div>`}#t=async()=>{let e=this.app;if(!e?.meta)return;let t=Te(e.meta.title,e.notes,e.meta.fps);try{await navigator.clipboard.writeText(t)}catch{let r=document.createElement("textarea");r.value=t,document.body.append(r),r.select();let i=document.execCommand("copy");if(r.remove(),!i)return}this.#e=!0,this.requestUpdate(),setTimeout(()=>{this.#e=!1,this.requestUpdate()},1600)}};var te=class extends g{connectedCallback(){super.connectedCallback(),document.addEventListener("pointerdown",this.#e),document.addEventListener("keydown",this.#t)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("pointerdown",this.#e),document.removeEventListener("keydown",this.#t)}render(){let e=this.app;return d`<ff-header .app=${e}></ff-header>
119
+ </div>`}#t=async()=>{let e=this.app;if(!e?.meta)return;let t=Ne(e.meta.title,e.notes,e.meta.fps);try{await navigator.clipboard.writeText(t)}catch{let r=document.createElement("textarea");r.value=t,document.body.append(r),r.select();let i=document.execCommand("copy");if(r.remove(),!i)return}this.#e=!0,this.requestUpdate(),setTimeout(()=>{this.#e=!1,this.requestUpdate()},1600)}};var tr="input, textarea, select, [contenteditable]",re=class extends g{connectedCallback(){super.connectedCallback(),document.addEventListener("pointerdown",this.#e),document.addEventListener("keydown",this.#t)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("pointerdown",this.#e),document.removeEventListener("keydown",this.#t)}render(){let e=this.app;return document.documentElement.toggleAttribute("data-embed",!!e?.embedded),c`${e?.embedded?u:c`<ff-header .app=${e}></ff-header>`}
133
120
  <main class="player" aria-label="Player">
134
121
  <ff-stage .app=${e}></ff-stage>
135
122
  <ff-transport .app=${e}></ff-transport>
136
123
  <ff-timeline .app=${e}></ff-timeline>
137
124
  </main>
138
- <ff-note-editor .app=${e}></ff-note-editor>`}#e=e=>{let t=this.app,r=e.target;if(!t||!r)return;let i=this.querySelector(".pop"),s=this.querySelector("ff-stage"),o=!!i?.contains(r)||!!s?.contains(r);i?.classList.contains("on")&&!o&&!r.closest(".note-mark, .note-row")&&(t.openId!=null?t.closePop():t.draft&&!t.draft.text.trim()&&t.cancelDraft());let a=this.querySelector(".notes-panel"),l=this.querySelector(".notes-btn");t.panelOpen&&!a?.contains(r)&&!l?.contains(r)&&t.setPanel(!1)};#t=e=>{e.key!=="Escape"||!this.app||(this.app.openId!=null&&this.app.closePop(),this.app.setPanel(!1))}};var bt={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},xt=n=>(...e)=>({_$litDirective$:n,values:e}),re=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,r){this._$Ct=e,this._$AM=t,this._$Ci=r}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};var yt="important",Wt=" !"+yt,S=xt(class extends re{constructor(n){if(super(n),n.type!==bt.ATTRIBUTE||n.name!=="style"||n.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(n){return Object.keys(n).reduce((e,t)=>{let r=n[t];return r==null?e:e+`${t=t.includes("-")?t:t.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${r};`},"")}update(n,[e]){let{style:t}=n.element;if(this.ft===void 0)return this.ft=new Set(Object.keys(e)),this.render(e);for(let r of this.ft)e[r]==null&&(this.ft.delete(r),r.includes("-")?t.removeProperty(r):t[r]=null);for(let r in e){let i=e[r];if(i!=null){this.ft.add(r);let s=typeof i=="string"&&i.endsWith(Wt);r.includes("-")||s?t.setProperty(r,s?i.slice(0,-11):i,s?yt:""):t[r]=i}}return w}});var Vt=6,ie=n=>S({left:`${n.x*100}%`,top:`${n.y*100}%`,width:n.w==null?void 0:`${n.w*100}%`,height:n.h==null?void 0:`${n.h*100}%`}),ne=class extends g{#e=null;render(){let e=this.app,t=e?.meta,r=["stage",e?.canNote?"can-note":"",e&&e.notes.length===0&&!e.draft?"hint":""].join(" "),i=t?{"--ar":`${t.width} / ${t.height}`,"--ar-n":String(t.width/t.height)}:{},s=this.#e?.area;return d`<div class="stage-wrap">
125
+ <ff-note-editor .app=${e}></ff-note-editor>`}#e=e=>{let t=this.app,r=e.target;if(!t||!r)return;let i=this.querySelector(".pop"),s=this.querySelector("ff-stage"),o=!!i?.contains(r)||!!s?.contains(r);i?.classList.contains("on")&&!o&&!r.closest(".note-mark, .note-row")&&(t.openId!=null?t.closePop():t.draft&&!t.draft.text.trim()&&t.cancelDraft());let a=this.querySelector(".notes-panel"),l=this.querySelector(".notes-btn");t.panelOpen&&!a?.contains(r)&&!l?.contains(r)&&t.setPanel(!1)};#t=e=>{let t=this.app;if(!t)return;if(e.key==="Escape"){t.openId!=null&&t.closePop(),t.setPanel(!1);return}let r=e.target;e.metaKey||e.ctrlKey||e.altKey||r?.closest(tr)||r?.closest("button")&&(e.key===" "||e.key==="Enter")||t.key(e)&&e.preventDefault()}};var xt={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},kt=n=>(...e)=>({_$litDirective$:n,values:e}),ie=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,r){this._$Ct=e,this._$AM=t,this._$Ci=r}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};var $t="important",rr=" !"+$t,ne=kt(class extends ie{constructor(n){if(super(n),n.type!==xt.ATTRIBUTE||n.name!=="style"||n.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(n){return Object.keys(n).reduce((e,t)=>{let r=n[t];return r==null?e:e+`${t=t.includes("-")?t:t.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${r};`},"")}update(n,[e]){let{style:t}=n.element;if(this.ft===void 0)return this.ft=new Set(Object.keys(e)),this.render(e);for(let r of this.ft)e[r]==null&&(this.ft.delete(r),r.includes("-")?t.removeProperty(r):t[r]=null);for(let r in e){let i=e[r];if(i!=null){this.ft.add(r);let s=typeof i=="string"&&i.endsWith(rr);r.includes("-")||s?t.setProperty(r,s?i.slice(0,-11):i,s?$t:""):t[r]=i}}return x}});var ir=6,se=n=>ne({left:`${n.x*100}%`,top:`${n.y*100}%`,width:n.w==null?void 0:`${n.w*100}%`,height:n.h==null?void 0:`${n.h*100}%`}),oe=class extends g{#e=null;render(){let e=this.app,t=e?.meta,r=["stage",e?.canNote?"can-note":"",e&&e.notes.length===0&&!e.draft?"hint":""].join(" "),i=t?{"--ar":`${t.width} / ${t.height}`,"--ar-n":String(t.width/t.height)}:{},s=this.#e?.area;return c`<div class="stage-wrap">
139
126
  <div
140
127
  class=${r}
141
- style=${S(i)}
128
+ style=${ne(i)}
142
129
  @pointerdown=${this.#r}
143
130
  @pointermove=${this.#s}
144
131
  @pointerup=${this.#o}
@@ -151,7 +138,7 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
151
138
  <div class="overlay">${this.#t()}</div>
152
139
  <div
153
140
  class="marquee"
154
- style=${s?ie(s):S({display:"none"})}
141
+ style=${s?se(s):ne({display:"none"})}
155
142
  ></div>
156
143
  <div class="stage-hint">Click to pin a note · drag to mark an area</div>
157
144
  <div class="toast ${e?.toastOn?"on":""}" role="status" aria-live="polite">
@@ -162,86 +149,92 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
162
149
  role="status"
163
150
  aria-label="Loading"
164
151
  >
165
- ${vt}
152
+ ${yt}
166
153
  </div>
167
154
  </div>
168
- </div>`}get picture(){return this.querySelector(".stage")}#t(){let e=this.app;if(!e?.meta||e.playing)return u;let t=e.notes.filter(r=>r.frame===e.frame);return e.draft&&e.draft.frame===e.frame&&t.push(e.draft),t.map(r=>{let i="done"in r&&r.done,s=r.w!=null?d`<div class="area ${i?"done":""}" style=${ie(r)}></div>`:u;if(!("id"in r))return d`${s}<button
155
+ </div>`}get picture(){return this.querySelector(".stage")}#t(){let e=this.app;if(!e?.meta||e.playing)return u;let t=e.notes.filter(r=>r.frame===e.frame);return e.draft&&e.draft.frame===e.frame&&t.push(e.draft),t.map(r=>{let i="done"in r&&r.done,s=r.w!=null?c`<div class="area ${i?"done":""}" style=${se(r)}></div>`:u;if(!("id"in r))return c`${s}<button
169
156
  class="pin draft"
170
- style=${ie({x:r.x,y:r.y})}
157
+ style=${se({x:r.x,y:r.y})}
171
158
  aria-label="New note"
172
- ></button>`;let o=["pin",i?"done":"",r.id===e.openId?"active":""];return d`${s}<button
159
+ ></button>`;let o=["pin",i?"done":"",r.id===e.openId?"active":""];return c`${s}<button
173
160
  class=${o.join(" ")}
174
- style=${ie({x:r.x,y:r.y})}
161
+ style=${se({x:r.x,y:r.y})}
175
162
  title=${r.text}
176
163
  aria-label="Note ${r.id}"
177
164
  @click=${a=>{a.stopPropagation(),e.openCard(r.id)}}
178
165
  >
179
166
  ${i?R:String(r.id)}
180
- </button>`})}#i(e){let t=e.currentTarget.getBoundingClientRect();return{x:Math.min(1,Math.max(0,(e.clientX-t.left)/t.width)),y:Math.min(1,Math.max(0,(e.clientY-t.top)/t.height))}}#r=e=>{let t=this.app,r=e.target;if(e.button!==0||!t?.player||r.closest(".pin"))return;if(t.playing){t.pause();return}if(!t.notesOn)return;if(t.draft?.text.trim()){this.closest("ff-preview")?.querySelector(".pop textarea")?.focus();return}t.cancelDraft();let i=this.#i(e);this.#e={...i,cx:e.clientX,cy:e.clientY,area:null},e.currentTarget.setPointerCapture(e.pointerId),e.preventDefault()};#s=e=>{let t=this.#e;if(!t||!t.area&&Math.hypot(e.clientX-t.cx,e.clientY-t.cy)<Vt)return;let r=this.#i(e);t.area={x:Math.min(t.x,r.x),y:Math.min(t.y,r.y),w:Math.abs(r.x-t.x),h:Math.abs(r.y-t.y)},this.requestUpdate()};#o=()=>{let e=this.#e;e&&(this.#e=null,this.app?.beginDraft({x:e.x,y:e.y},e.area))};#n=()=>{this.#e=null,this.requestUpdate()}};var Kt=3,se=class extends g{#e=800;#t=null;#i=!1;#r="";#s=new ResizeObserver(()=>{let e=this.#o()?.clientWidth;e&&e!==this.#e&&(this.#e=e,this.requestUpdate()),this.#a(!0)});connectedCallback(){super.connectedCallback(),this.updateComplete.then(()=>{let e=this.#o();e&&this.#s.observe(e)})}disconnectedCallback(){super.disconnectedCallback(),this.#s.disconnect()}render(){let e=this.app,t=e?.meta,r=t?.frameCount??1,i=t?.fps??30,s=this.#t===null?null:this.#p(this.#t/Math.max(1,this.#e));return d`<div
167
+ </button>`})}#i(e){let t=e.currentTarget.getBoundingClientRect();return{x:Math.min(1,Math.max(0,(e.clientX-t.left)/t.width)),y:Math.min(1,Math.max(0,(e.clientY-t.top)/t.height))}}#r=e=>{let t=this.app,r=e.target;if(e.button!==0||!t?.player||r.closest(".pin"))return;if(t.playing){t.pause();return}if(!t.notesOn)return;if(t.draft?.text.trim()){this.closest("ff-preview")?.querySelector(".pop textarea")?.focus();return}t.cancelDraft();let i=this.#i(e);this.#e={...i,cx:e.clientX,cy:e.clientY,area:null},e.currentTarget.setPointerCapture(e.pointerId),e.preventDefault()};#s=e=>{let t=this.#e;if(!t||!t.area&&Math.hypot(e.clientX-t.cx,e.clientY-t.cy)<ir)return;let r=this.#i(e);t.area={x:Math.min(t.x,r.x),y:Math.min(t.y,r.y),w:Math.abs(r.x-t.x),h:Math.abs(r.y-t.y)},this.requestUpdate()};#o=()=>{let e=this.#e;e&&(this.#e=null,this.app?.beginDraft({x:e.x,y:e.y},e.area))};#n=()=>{this.#e=null,this.requestUpdate()}};function Pt(n,e,t,r=2){if(!n.length||e<=0||t<=0)return"";let i=t/2,s=Math.max(0,i-2),o=[];for(let h=0;h<e+r;h+=r){let d=Math.min(h,e),f=Math.floor(d/e*n.length),m=Math.max(f+1,Math.ceil(Math.min(e,d+r)/e*n.length)),b=0;for(let P=f;P<Math.min(m,n.length);P++)b=Math.max(b,n[P]??0);if(o.push([d,Math.max(.5,Math.min(1,b)*s)]),d===e)break}let a=h=>Math.round(h*100)/100,l=o.map(([h,d])=>`L${a(h)} ${a(i-d)}`).join(""),p=o.reverse().map(([h,d])=>`L${a(h)} ${a(i+d)}`).join("");return`M0 ${a(i)}${l}${p}Z`}var nr=64,ae=class extends g{#e=800;#t=null;#i=!1;#r="";#s=new ResizeObserver(()=>{let e=this.#a()?.clientWidth;e&&e!==this.#e&&(this.#e=e,this.requestUpdate()),this.#p(!0)});#o=window.matchMedia?.("(prefers-color-scheme: light)");#n=()=>this.#p(!0);connectedCallback(){super.connectedCallback(),this.#o?.addEventListener("change",this.#n),this.updateComplete.then(()=>{let e=this.#a();e&&this.#s.observe(e)})}disconnectedCallback(){super.disconnectedCallback(),this.#s.disconnect(),this.#o?.removeEventListener("change",this.#n)}render(){let e=this.app,t=e?.meta,r=t?.frameCount??1,i=t?.fps??30,s=e?.frame??0,o=de(s,r),a=(r-1)/i;return c`<div
181
168
  class="timeline"
169
+ role="slider"
170
+ tabindex="0"
182
171
  aria-label="Timeline"
183
- @pointerdown=${this.#h}
184
- @pointermove=${this.#f}
185
- @pointerleave=${this.#d}
186
- @pointerup=${this.#u}
187
- @pointercancel=${this.#u}
172
+ aria-valuemin="0"
173
+ aria-valuemax=${a.toFixed(3)}
174
+ aria-valuenow=${(s/i).toFixed(3)}
175
+ aria-valuetext="${v(s,i)}, frame ${s}"
176
+ @pointerdown=${this.#v}
177
+ @pointermove=${this.#b}
178
+ @pointerleave=${this.#g}
179
+ @pointerup=${this.#f}
180
+ @pointercancel=${this.#f}
188
181
  >
189
- <div class="tl-inner">
182
+ <div class="tl-inner" style="--track-w:${this.#e}px">
190
183
  <div class="ruler">
191
- ${t?_e((r-1)/i,this.#e).map(o=>d`<div
192
- class="tick ${o.major?"major":""}"
193
- style="left:${o.left}%"
184
+ ${t?Ce(a,this.#e).map(l=>c`<div
185
+ class="tick ${l.major?"major":""}"
186
+ style="left:${l.left}%"
194
187
  >
195
- ${o.label?d`<span>${o.label}</span>`:u}
188
+ ${l.label?c`<span>${l.label}</span>`:u}
196
189
  </div>`):u}
197
190
  </div>
198
- <div class="note-marks">${this.#n()}</div>
199
- <div class="wave-lane">
200
- <canvas></canvas>
201
- ${this.#l()}
191
+ ${this.#c()}
192
+ <div class="wave">
193
+ <canvas class="wave-base"></canvas>
194
+ <div class="wave-played" style="width:${o}%">
195
+ <canvas></canvas>
196
+ </div>
197
+ ${this.#u()}
202
198
  </div>
203
- <div
204
- class="hover-line"
205
- style=${S(this.#t===null?{}:{display:"block",left:`${this.#t}px`})}
206
- ></div>
207
- <div
208
- class="hover-time"
209
- style=${S(this.#t===null?{}:{display:"block",left:`${this.#t}px`})}
210
- >
211
- ${s===null?"":v(s,i)}
199
+ ${this.#m(i)}
200
+ <div class="playhead" style="left:${o}%"></div>
201
+ <div class="playhead-time" style="left:${this.#l(o/100*this.#e)}px">
202
+ ${v(s,i)}
212
203
  </div>
213
- <div
214
- class="playhead"
215
- style="left:${le(e?.frame??0,r)}%"
216
- ></div>
217
204
  </div>
218
- </div>`}updated(){this.#a(!1)}#o(){return this.querySelector(".tl-inner")}#n(){let e=this.app,t=e?.meta;return!e||!t?u:Ce(e.notes,t.frameCount,this.#e).map(({note:r,lane:i,left:s})=>d`<button
219
- class="note-mark ${r.done?"done":""} ${i?"stacked":""}"
220
- style="left:${s}%;top:${4+i*15}px"
221
- title="${r.id} · ${v(r.frame,t.fps)} · ${r.text}"
222
- @pointerdown=${o=>o.stopPropagation()}
223
- @click=${o=>{o.stopPropagation(),e.goToNote(r.id)}}
224
- >
225
- ${r.id}
226
- </button>`)}#l(){let e=this.app?.soundtrack.state??"mixing";if(e==="ready")return u;let t=e==="mixing"||e==="loading",r=e==="none"?"No audio in this composition":e==="error"?"Audio could not be mixed":F[e];return d`<div class="wave-state ${t?"shimmer":""}">
227
- ${t?d`<span class="spinner"></span>`:u}${r}
228
- </div>`}#a(e){let t=this.app,r=this.querySelector(".wave-lane canvas");if(!t||!r)return;let i=t.soundtrack,s=window.devicePixelRatio||1,o=r.clientWidth,a=r.clientHeight,l=`${i.peaksVersion}:${o}x${a}@${s}:${t.meta?.frameCount}:${i.durationSec}`;if(!e&&l===this.#r)return;this.#r=l,r.width=Math.round(o*s),r.height=Math.round(a*s);let p=r.getContext("2d");if(!p)return;p.setTransform(s,0,0,s,0,0),p.clearRect(0,0,o,a);let c=i.peaks,h=t.meta;if(!c?.length||!h)return;let f=Math.max(1e-6,(h.frameCount-1)/h.fps),m=i.durationSec??f,x=Math.min(1,m/f)*o,kt=a/2;p.fillStyle=getComputedStyle(document.documentElement).getPropertyValue("--wave").trim();for(let j=0;j<x;j+=Kt){let $t=Math.max(c[Math.floor(j/x*c.length)]||0,.015),Ee=Math.max(1,Math.sqrt($t)*(a-8));p.fillRect(j,kt-Ee/2,2,Ee)}}#p(e){let t=this.app?.meta?.frameCount??1;return _(Math.min(1,Math.max(0,e))*(t-1),t)}#c(e){let t=this.#o()?.getBoundingClientRect();return t?(e-t.left)/t.width:0}#h=e=>{!this.app?.meta||e.button!==0||(e.currentTarget.setPointerCapture(e.pointerId),this.#i=!0,this.app.seek(this.#p(this.#c(e.clientX))))};#f=e=>{let t=this.app;if(!t?.meta)return;let r=this.#o()?.getBoundingClientRect();if(!r)return;this.#t=Math.min(r.width,Math.max(0,e.clientX-r.left));let i=this.#p(this.#c(e.clientX));this.#i&&i!==t.frame&&t.seek(i),this.requestUpdate()};#d=()=>{this.#t=null,this.requestUpdate()};#u=()=>{this.#i=!1}};var oe=class extends g{render(){let e=this.app,t=e?.meta?.fps??30,r=!!e?.playing,i=e?.soundtrack,s=!!i?.usable,o=!!i?.muted,a=r?"Pause":"Play",l=o?"Unmute":"Mute";return d`<div class="transport">
205
+ </div>`}updated(){this.#p(!1)}#a(){return this.querySelector(".tl-inner")}#l(e){let t=nr/2;return Math.max(t,Math.min(Math.max(t,this.#e-t),e))}#m(e){let t=this.#t;if(t===null||this.#i)return u;let r=this.#d(t/Math.max(1,this.#e));return c`<div class="hover-line" style="left:${t}px"></div>
206
+ <div class="hover-time" style="left:${this.#l(t)}px">
207
+ ${v(r,e)}
208
+ </div>`}#c(){let e=this.app,t=e?.meta;if(!e?.notesOn||!t)return u;let r=Te(e.notes,t.frameCount,this.#e),i=Math.max(1,...r.map(s=>s.lane+1));return c`<div class="marks" style="--lanes:${i}">
209
+ ${r.map(({note:s,lane:o,left:a})=>{let l=["note-mark",s.done?"done":"",s.id===e.openId?"active":""];return c`<button
210
+ class=${l.join(" ")}
211
+ style="left:${a}%;top:${o*20}px"
212
+ title="${s.id} · ${v(s.frame,t.fps)} · ${s.text}"
213
+ aria-label="Note ${s.id} at ${v(s.frame,t.fps)}"
214
+ @pointerdown=${p=>p.stopPropagation()}
215
+ @click=${p=>{p.stopPropagation(),e.goToNote(s.id)}}
216
+ >
217
+ ${s.id}
218
+ </button>`})}
219
+ </div>`}#u(){let e=this.app?.soundtrack.state??"mixing";if(e==="ready")return u;let t=e==="mixing"||e==="loading",r=e==="none"?"No audio in this composition":e==="error"?"Audio could not be mixed":W[e];return c`<div class="wave-state ${t?"shimmer":""}">
220
+ ${t?c`<span class="spinner"></span>`:u}${r}
221
+ </div>`}#p(e){let t=this.app,r=this.querySelector(".wave-base"),i=this.querySelector(".wave-played canvas");if(!t||!r||!i)return;let s=t.soundtrack,o=window.devicePixelRatio||1,a=this.#e,l=r.clientHeight,p=`${s.peaksVersion}:${a}x${l}@${o}:${t.meta?.frameCount}:${s.durationSec}`;if(!e&&p===this.#r)return;this.#r=p;let h=t.meta,d=s.peaks,f=h?Math.max(1e-6,(h.frameCount-1)/h.fps):1,m=Math.min(1,(s.durationSec??f)/f)*a,b=getComputedStyle(this);for(let[P,_t]of[[r,b.getPropertyValue("--wave")],[i,b.getPropertyValue("--wave-played")]]){P.width=Math.round(a*o),P.height=Math.round(l*o);let L=P.getContext("2d");L&&(L.setTransform(o,0,0,o,0,0),L.clearRect(0,0,a,l),!(!d?.length||!h)&&(L.fillStyle=_t.trim(),L.fill(new Path2D(Pt(d,m,l)))))}}#d(e){let t=this.app?.meta?.frameCount??1;return _(Math.min(1,Math.max(0,e))*(t-1),t)}#h(e){let t=this.#a()?.getBoundingClientRect();return t?(e-t.left)/t.width:0}#v=e=>{!this.app?.meta||e.button!==0||(e.currentTarget.setPointerCapture(e.pointerId),this.#i=!0,this.app.seek(this.#d(this.#h(e.clientX))))};#b=e=>{let t=this.app;if(!t?.meta)return;let r=this.#a()?.getBoundingClientRect();if(!r)return;this.#t=Math.min(r.width,Math.max(0,e.clientX-r.left));let i=this.#d(this.#h(e.clientX));this.#i&&i!==t.frame&&t.seek(i),this.requestUpdate()};#g=()=>{this.#t=null,this.requestUpdate()};#f=()=>{this.#i=!1,this.requestUpdate()}};var Et="framefields-preview:";function At(n,e,t){try{let r=localStorage.getItem(Et+n);return e.find(i=>i===r)??t}catch{return t}}function Mt(n,e){try{localStorage.setItem(Et+n,e)}catch{}}var sr=["time","frames"],le=class extends g{#e=At("position",sr,"time");render(){let e=this.app,t=!!e?.playing,r=t?"Pause":"Play";return c`<div class="transport">
229
222
  <button
230
223
  class="icon-btn"
231
224
  title="Previous frame"
232
225
  aria-label="Previous frame"
233
226
  @click=${()=>e?.step(-1)}
234
227
  >
235
- ${lt}
228
+ ${ht}
236
229
  </button>
237
230
  <button
238
231
  class="play-btn ${e?.stalled?"loading":""}"
239
- title=${a}
240
- aria-label=${a}
232
+ title=${r}
233
+ aria-label=${r}
241
234
  ?disabled=${!e?.player}
242
235
  @click=${()=>e?.togglePlay()}
243
236
  >
244
- ${r?dt:ht}${ct}
237
+ ${t?ft:ut}${mt}
245
238
  </button>
246
239
  <button
247
240
  class="icon-btn"
@@ -249,49 +242,55 @@ async function Se(n,e){let t=await n.snapshot(e.frame),r=Math.min(1,1600/t.width
249
242
  aria-label="Next frame"
250
243
  @click=${()=>e?.step(1)}
251
244
  >
252
- ${pt}
245
+ ${ct}
253
246
  </button>
254
- <div class="timecode tnum">
255
- <span>${v(e?.frame??0,t)}</span><span class="dim">/</span
256
- ><span class="dim">${v(e?.lastFrame??0,t)}</span>
257
- <span class="frame">frame ${e?.frame??0}</span>
258
- </div>
259
- ${this.#e()}
247
+ ${this.#t()} ${this.#i()}
260
248
  <span class="grow"></span>
261
- ${e?.notesOn?this.#t():u}
249
+ ${e?.embedded?Me(e):u}
250
+ ${e?.notesOn?this.#r():u}
262
251
  <ff-notes-panel .app=${e}></ff-notes-panel>
263
- <button
264
- class="icon-btn"
265
- title=${l}
266
- aria-label=${l}
267
- ?disabled=${!s}
268
- @click=${()=>i?.setMuted(!i.muted)}
269
- >
270
- ${o?gt:mt}
271
- </button>
272
- <input
273
- class="slider"
274
- type="range"
275
- min="0"
276
- max="1"
277
- step="0.01"
278
- .value=${String(i?.volume??.9)}
279
- aria-label="Volume"
280
- ?disabled=${!s}
281
- @input=${p=>i?.setVolume(Number(p.target.value))}
282
- />
283
- </div>`}#e(){let e=this.app,t=e?.fps;if(!t||t.state==="paused"&&t.fps===null)return u;let r=(t.state==="paused"?"Frame rate the last playback reached":"Frame rate playback reaches")+(e?.meta?`; the film runs at ${e.meta.fps} fps`:"");return d`<span class="fps tnum" role="status" title=${r}
252
+ ${this.#s()}
253
+ </div>`}get positionMode(){return this.#e}#t(){let e=this.app,t=e?.meta?.fps??30,r=e?.frame??0,i=e?.lastFrame??0,{now:s,end:o}=Re(this.#e,r,i,t),a=this.#e==="time"?"frames":"time",l=`${this.#e==="time"?`Time ${s} of ${o}`:`Frame ${s} of ${o}`}. Click to show ${a}.`;return c`<button
254
+ class="position tnum"
255
+ title="Click to show ${a}"
256
+ aria-label=${l}
257
+ @click=${()=>{this.#e=a,Mt("position",a),this.requestUpdate()}}
258
+ >
259
+ <span class="now">${s}</span><span class="dim"> / ${o}</span>
260
+ </button>`}#i(){let e=this.app,t=e?.fps;if(!t||t.state==="paused"&&t.fps===null)return u;let r=(t.state==="paused"?"Frame rate the last playback reached":"Frame rate playback reaches")+(e?.meta?`; the film runs at ${e.meta.fps} fps`:"");return c`<span class="fps tnum" role="status" title=${r}
284
261
  >${t.fps===null?"\u2026 fps":`${t.fps.toFixed(1)} fps`}</span
285
- >`}#t(){let e=this.app;if(!e)return u;let t=e.openCount;return d`<button
262
+ >`}#r(){let e=this.app;if(!e)return u;let t=e.openCount,r=`Notes: ${t} open of ${e.notes.length}`;return c`<button
286
263
  class="btn notes-btn"
287
- title="${t} open of ${e.notes.length}"
264
+ title=${r}
265
+ aria-label=${r}
288
266
  aria-haspopup="dialog"
289
267
  aria-expanded=${String(e.panelOpen)}
290
268
  @click=${()=>e.setPanel(!e.panelOpen)}
291
269
  >
292
- ${ut} Notes
270
+ ${vt}
293
271
  <span class="badge ${t>0?"open":""}">${t||e.notes.length}</span>
294
- </button>`}};var Xt={"ff-header":Z,"ff-stage":ne,"ff-transport":oe,"ff-timeline":se,"ff-notes-panel":ee,"ff-note-editor":Q,"ff-preview":te};function wt(n=customElements){for(let[e,t]of Object.entries(Xt))n.get(e)||n.define(e,t)}wt();var ae=new W;Le(console,ae.report);var Jt=document.querySelector("ff-preview")??document.body.appendChild(document.createElement("ff-preview"));Jt.app=ae;ae.start().catch(n=>ae.showError(n));
272
+ </button>`}#s(){let e=this.app?.soundtrack;if(!e)return u;let t=e.usable,r=e.muted,i=e.state==="none"?"No audio in this composition":e.state==="error"?`Audio failed${e.error?`: ${e.error}`:""}`:null,s=i??(t?r?"Unmute":"Mute":`${W[e.state]}\u2026`),o=(r?0:e.volume)*100;return c`<div class="volume ${t?"usable":""} ${i?"problem":""}">
273
+ <button
274
+ class="icon-btn"
275
+ title=${s}
276
+ aria-label=${s}
277
+ aria-disabled=${String(!t)}
278
+ @click=${()=>{t&&e.setMuted(!e.muted)}}
279
+ >
280
+ ${i||r?wt:bt}
281
+ </button>
282
+ ${t?c`<span class="slider-wrap"><input
283
+ class="slider"
284
+ type="range"
285
+ min="0"
286
+ max="1"
287
+ step="0.01"
288
+ .value=${String(e.volume)}
289
+ style="--level:${o}%"
290
+ aria-label="Volume"
291
+ @input=${a=>e.setVolume(Number(a.target.value))}
292
+ /></span>`:u}
293
+ </div>`}};var or={"ff-header":Q,"ff-stage":oe,"ff-transport":le,"ff-timeline":ae,"ff-notes-panel":te,"ff-note-editor":ee,"ff-preview":re};function St(n=customElements){for(let[e,t]of Object.entries(or))n.get(e)||n.define(e,t)}St();var U=new V;Oe(console,U.report);window.parent!==window&&Fe(U,window.parent);var ar=document.querySelector("ff-preview")??document.body.appendChild(document.createElement("ff-preview"));ar.app=U;U.start().catch(n=>U.showError(n));
295
294
  /*! Bundled license information:
296
295
 
297
296
  @lit/reactive-element/css-tag.js: