textmode.export.js 1.3.0 → 1.4.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.
Files changed (58) hide show
  1. package/README.md +1 -1
  2. package/dist/textmode.export.esm.js +1001 -880
  3. package/dist/textmode.export.umd.js +2 -2
  4. package/dist/types/exporters/base/LayerTarget.d.ts +46 -0
  5. package/dist/types/exporters/base/LayerTarget.d.ts.map +1 -0
  6. package/dist/types/exporters/base/index.d.ts +2 -0
  7. package/dist/types/exporters/base/index.d.ts.map +1 -1
  8. package/dist/types/exporters/gif/GIFExporter.d.ts +1 -1
  9. package/dist/types/exporters/gif/GIFExporter.d.ts.map +1 -1
  10. package/dist/types/exporters/gif/GIFRecorder.d.ts +1 -1
  11. package/dist/types/exporters/gif/GIFRecorder.d.ts.map +1 -1
  12. package/dist/types/exporters/json/JSONDataExtractor.d.ts +3 -4
  13. package/dist/types/exporters/json/JSONDataExtractor.d.ts.map +1 -1
  14. package/dist/types/exporters/json/JSONExporter.d.ts +12 -7
  15. package/dist/types/exporters/json/JSONExporter.d.ts.map +1 -1
  16. package/dist/types/exporters/json/index.d.ts +1 -1
  17. package/dist/types/exporters/json/index.d.ts.map +1 -1
  18. package/dist/types/exporters/json/types.d.ts +78 -15
  19. package/dist/types/exporters/json/types.d.ts.map +1 -1
  20. package/dist/types/exporters/svg/SVGContentGenerator.d.ts +1 -1
  21. package/dist/types/exporters/svg/SVGContentGenerator.d.ts.map +1 -1
  22. package/dist/types/exporters/svg/SVGExporter.d.ts.map +1 -1
  23. package/dist/types/exporters/svg/SVGPathGenerator.d.ts +1 -1
  24. package/dist/types/exporters/svg/SVGPathGenerator.d.ts.map +1 -1
  25. package/dist/types/exporters/svg/types.d.ts +3 -1
  26. package/dist/types/exporters/svg/types.d.ts.map +1 -1
  27. package/dist/types/exporters/txt/TXTExporter.d.ts.map +1 -1
  28. package/dist/types/exporters/txt/TXTExporter.test.d.ts +2 -0
  29. package/dist/types/exporters/txt/TXTExporter.test.d.ts.map +1 -0
  30. package/dist/types/exporters/txt/types.d.ts +3 -1
  31. package/dist/types/exporters/txt/types.d.ts.map +1 -1
  32. package/dist/types/exporters/video/VideoExporter.d.ts +1 -1
  33. package/dist/types/exporters/video/VideoExporter.d.ts.map +1 -1
  34. package/dist/types/exporters/video/VideoRecorder.d.ts +1 -1
  35. package/dist/types/exporters/video/VideoRecorder.d.ts.map +1 -1
  36. package/dist/types/index.d.ts +4 -3
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/overlay/blades/Blade.d.ts +2 -0
  39. package/dist/types/overlay/blades/Blade.d.ts.map +1 -1
  40. package/dist/types/overlay/blades/JSONBlade.d.ts +5 -0
  41. package/dist/types/overlay/blades/JSONBlade.d.ts.map +1 -1
  42. package/dist/types/overlay/blades/SVGBlade.d.ts +2 -0
  43. package/dist/types/overlay/blades/SVGBlade.d.ts.map +1 -1
  44. package/dist/types/overlay/blades/TextBlade.d.ts +2 -0
  45. package/dist/types/overlay/blades/TextBlade.d.ts.map +1 -1
  46. package/dist/types/overlay/components/inputs/LayerTargetSelect.d.ts +20 -0
  47. package/dist/types/overlay/components/inputs/LayerTargetSelect.d.ts.map +1 -0
  48. package/dist/types/overlay/core/OverlayController.d.ts +1 -0
  49. package/dist/types/overlay/core/OverlayController.d.ts.map +1 -1
  50. package/dist/types/overlay/formatRegistry.d.ts +2 -1
  51. package/dist/types/overlay/formatRegistry.d.ts.map +1 -1
  52. package/dist/types/overlay/formatRegistry.test.d.ts +2 -0
  53. package/dist/types/overlay/formatRegistry.test.d.ts.map +1 -0
  54. package/dist/types/overlay/index.d.ts +3 -1
  55. package/dist/types/overlay/index.d.ts.map +1 -1
  56. package/dist/types/types.d.ts +21 -18
  57. package/dist/types/types.d.ts.map +1 -1
  58. package/package.json +4 -3
@@ -1,2 +1,2 @@
1
- (function(G,R){typeof exports=="object"&&typeof module<"u"?R(exports):typeof define=="function"&&define.amd?define(["exports"],R):R((G=typeof globalThis<"u"?globalThis:G||self).TextmodeExport={})})(this,function(G){"use strict";var Br=Object.defineProperty;var Ir=(G,R,j)=>R in G?Br(G,R,{enumerable:!0,configurable:!0,writable:!0,value:j}):G[R]=j;var p=(G,R,j)=>Ir(G,typeof R!="symbol"?R+"":R,j);class R{$extractFramebufferData(r){return{characterPixels:r.readPixels(0),primaryColorPixels:r.readPixels(1),secondaryColorPixels:r.readPixels(2)}}$getEncodedCharacterValue(r,e){return r[e]+(r[e+1]<<8)}$getCharacterIndex(r,e){return this.$getEncodedCharacterValue(r,e)}$extractCellTransform(r,e){const t=r[e+2],a=r[e+3]/255;return{isInverted:!!(1&t),flipHorizontal:!!(2&t),flipVertical:!!(4&t),rotation:Math.round(360*a*100)/100}}}class j{$downloadFile(r,e){try{const t=this._sanitizeFilename(e),a=URL.createObjectURL(r),o=document.createElement("a");o.href=a,o.download=t,o.style.display="none",o.rel="noopener",document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(a)}catch(t){console.error("[textmode-export] Failed to download file:",t)}}_sanitizeFilename(r){if(!r)return this._generateDefaultFilename();const e=r.trim();return e?e.replace(/[<>:"/\\|?*]/g,"_").replace(/\s+/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").substring(0,255)||this._generateDefaultFilename():this._generateDefaultFilename()}_generateDefaultFilename(){return`textmode-export-${new Date().toISOString().slice(0,19).replace(/:/g,"-")}`}}const Ee=new WeakMap;function ht(l){return Math.round(255*l[0])+(Math.round(255*l[1])<<8)}function ce(l,r){let e=Ee.get(l);if(!e){e=new Map;for(const t of l.characters)e.set(ht(t.color),t);Ee.set(l,e)}return e.get(r)}function te(l,r){return{r:l[r],g:l[r+1],b:l[r+2],a:l[r+3]}}class mt extends R{_calculateCellPosition(r,e,t){return{x:r,y:e,cellX:r*t.cellWidth,cellY:e*t.cellHeight}}$extractSVGCellData(r,e){const t=[];let a=0;for(let o=0;o<e.rows;o++)for(let n=0;n<e.cols;n++){const d=4*a,s=this.$getEncodedCharacterValue(r.characterPixels,d);let h=te(r.primaryColorPixels,d),i=te(r.secondaryColorPixels,d);const c=this.$extractCellTransform(r.characterPixels,d);if(c.isInverted){const f=h;h=i,i=f}const u=this._calculateCellPosition(n,o,e);t.push({encodedGlyphSlot:s,primaryColor:h,secondaryColor:i,transform:c,position:u}),a++}return t}}class ft{_createGlyphPath(r,e,t,a,o){const n=o/r.head.unitsPerEm;return{getBoundingBox:()=>({x1:t+e.xMin*n,y1:a+-e.yMax*n,x2:t+e.xMax*n,y2:a+-e.yMin*n}),toSVG:()=>this._glyphToSVGPath(e,t,a,n)}}_glyphToSVGPath(r,e,t,a){if(!r||!r.xs)return"";const{xs:o,ys:n,endPts:d,flags:s}=r;if(!(o&&n&&d&&s))return"";let h="",i=0;for(let c=0;c<d.length;c++){const u=d[c];if(!(u<i)){if(u>=i){const f=e+o[i]*a,y=t-n[i]*a;h+=`M${f.toFixed(2)},${y.toFixed(2)}`;let m=i+1;for(;m<=u;)if(1&s[m]){const v=e+o[m]*a,C=t-n[m]*a;h+=`L${v.toFixed(2)},${C.toFixed(2)}`,m++}else{const v=e+o[m]*a,C=t-n[m]*a,x=m+1>u?i:m+1;if(1&s[x]){const b=e+o[x]*a,B=t-n[x]*a;h+=`Q${v.toFixed(2)},${C.toFixed(2)} ${b.toFixed(2)},${B.toFixed(2)}`,m=x+1}else{const b=(v+(e+o[x]*a))/2,B=(C+(t-n[x]*a))/2;h+=`Q${v.toFixed(2)},${C.toFixed(2)} ${b.toFixed(2)},${B.toFixed(2)}`,m=x}}h+="Z"}i=u+1}}return h}$generatePositionedCharacterPath(r,e,t,a,o,n,d,s){if(!s)return null;const h=e.font,i=d/h.head.unitsPerEm,c=t+(o-s.advanceWidth*i)/2,u=a+h.hhea.ascender*i;return this._createGlyphPath(h,s,c,u,d).toSVG()||null}}class gt{constructor(){p(this,"_pathGenerator");this._pathGenerator=new ft}$generateSVGHeader(r){const{width:e,height:t}=r;return`<?xml version="1.0" encoding="UTF-8"?><svg width="${e}" height="${t}" viewBox="0 0 ${e} ${t}" xmlns="http://www.w3.org/2000/svg"><title>textmode.js sketch</title>`}$generateSVGFooter(){return"</g></svg>"}_generateTransformAttribute(r,e){const{transform:t,position:a}=r;if(!t.flipHorizontal&&!t.flipVertical&&!t.rotation)return"";const o=a.cellX+e.cellWidth/2,n=a.cellY+e.cellHeight/2,d=[];if(t.flipHorizontal||t.flipVertical){const s=t.flipHorizontal?-1:1,h=t.flipVertical?-1:1;d.push(`translate(${o} ${n})scale(${s} ${h})translate(${-o} ${-n})`)}return t.rotation&&d.push(`rotate(${t.rotation} ${o} ${n})`),` transform="${d.join(" ")}"`}_generateCellBackground(r,e,t){if(!t.includeBackgroundRectangles||r.secondaryColor.a===0)return"";const{position:a}=r,{r:o,g:n,b:d,a:s}=r.secondaryColor,h=`rgba(${o},${n},${d},${s/255})`;return t.drawMode==="stroke"?`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" stroke="${h}" fill="none" stroke-width="${t.strokeWidth}"/>`:`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" fill="${h}"/>`}_generateCharacterPath(r,e,t,a){const o=ce(t,r.encodedGlyphSlot);if(!o)return"";const n=this._pathGenerator.$generatePositionedCharacterPath(o.character,t,r.position.cellX,r.position.cellY,e.cellWidth,e.cellHeight,t.fontSize,o.glyphData);if(!n)return"";const{r:d,g:s,b:h,a:i}=r.primaryColor,c=`rgba(${d},${s},${h},${i/255})`;return a.drawMode==="stroke"?`<path d="${n}" stroke="${c}" stroke-width="${a.strokeWidth}" fill="none"/>`:`<path d="${n}" fill="${c}"/>`}$generateCellContent(r,e,t,a){const o=[],n=this._generateCellBackground(r,e,a);n&&o.push(n);const d=this._generateCharacterPath(r,e,t,a);if(d){const s=this._generateTransformAttribute(r,e);o.push(s?`<g${s}>${d}</g>`:d)}return o.join("")}$generateSVGContent(r,e,t,a){const o=[this.$generateSVGHeader(e),'<g id="ascii-cells">'];for(const n of r)o.push(this.$generateCellContent(n,e,t,a));return o.push(this.$generateSVGFooter()),o.join("")}$optimizeSVGContent(r){return r.replace(/\s+/g," ").replace(/> </g,"><")}}class Be{_applyDefaultOptions(r){return{includeBackgroundRectangles:r.includeBackgroundRectangles??!0,drawMode:r.drawMode??"fill",strokeWidth:r.strokeWidth??1,filename:r.filename}}$generateSVG(r,e={}){const t=new mt,a=new gt,o=t.$extractSVGCellData(t.$extractFramebufferData(r.layers.base.drawFramebuffer),r.grid),n=a.$generateSVGContent(o,r.grid,r.font,this._applyDefaultOptions(e));return a.$optimizeSVGContent(n)}$saveSVG(r,e={}){new j().$downloadFile(new Blob([this.$generateSVG(r,e)],{type:"image/svg+xml;charset=utf-8"}),e.filename)}}const ue={png:"image/png",jpg:"image/jpeg",webp:"image/webp"},bt=".png",vt=".jpg",xt=".webp";class Ie{_applyDefaultOptions(r){return{format:r.format??"png",scale:Math.abs(r.scale??1),filename:r.filename}}_validateOptions(r){if(!(r.format in ue))throw new Error(`Saving '${r.format}' files is not supported`)}async $generateImageBlob(r,e){const t=r,a=document.createElement("canvas"),o=a.getContext("2d"),n=Math.round(t.width*e.scale),d=Math.round(t.height*e.scale);return a.width=n,a.height=d,o.imageSmoothingEnabled=!1,o.clearRect(0,0,n,d),o.drawImage(t,0,0,t.width,t.height,0,0,n,d),await new Promise((s,h)=>{a.toBlob(i=>{i?s(i):h(new Error(`Failed to generate ${e.format.toUpperCase()} blob`))},ue[e.format])})}async $saveImage(r,e={}){const t=this._applyDefaultOptions(e);this._validateOptions(t);const a=await this.$generateImageBlob(r,t);new j().$downloadFile(a,t.filename)}async $copyImageToClipboard(r,e={}){if(typeof navigator>"u"||!navigator.clipboard||typeof navigator.clipboard.write!="function")throw new Error("Clipboard API is not available in this environment");const t=this._applyDefaultOptions(e);this._validateOptions(t);const a=await this.$generateImageBlob(r,t),o=new ClipboardItem({[ue[t.format]]:a});await navigator.clipboard.write([o])}}class Se{_applyDefaultOptions(r){return{preserveTrailingSpaces:r.preserveTrailingSpaces??!1,emptyCharacter:r.emptyCharacter??" ",filename:r.filename}}_createTXTContent(r,e){var s;const t=new R,a=r.layers.base.drawFramebuffer,o=t.$extractFramebufferData(a),n=[];let d=0;for(let h=0;h<r.grid.rows;h++){let i="";for(let c=0;c<r.grid.cols;c++){const u=4*d,f=t.$getEncodedCharacterValue(o.characterPixels,u);i+=((s=ce(r.font,f))==null?void 0:s.character)||e.emptyCharacter,d++}e.preserveTrailingSpaces||(i=i.trimEnd()),n.push(i)}return n.join(`
2
- `)}$generateTXT(r,e={}){return this._createTXTContent(r,this._applyDefaultOptions(e))}$saveTXT(r,e={}){const t=this._applyDefaultOptions(e),a=this._createTXTContent(r,t),o=new Blob([a],{type:"text/plain;charset=utf-8"});new j().$downloadFile(o,t.filename)}}class yt{constructor(){p(this,"_canvas");p(this,"_ctx")}async $record(r,e,t,a){const o=Math.max(1,Math.round(e.frameRate)),n=Math.round(1e3/o),d=Math.max(1,Math.round(e.frameCount));return await new Promise((s,h)=>{const i=[];let c,u=0,f=!1;const y=()=>{c&&(c(),c=void 0)},m=C=>{f||(f=!0,y(),s(C))},v=()=>{if(u>=d)m(i);else try{const C=e.scale,x=Math.max(1,Math.round(r.width*C)),b=Math.max(1,Math.round(r.height*C));this._canvas||(this._canvas=document.createElement("canvas")),this._canvas.width===x&&this._canvas.height===b||(this._canvas.width=x,this._canvas.height=b),this._ctx||(this._ctx=this._canvas.getContext("2d"));const B=this._ctx;B.imageSmoothingEnabled=!1,B.clearRect(0,0,x,b),B.drawImage(r,0,0,r.width,r.height,0,0,x,b);const P={imageData:B.getImageData(0,0,x,b),width:x,height:b,delayMs:n};i.push(P),u+=1,a==null||a({state:"recording",frameIndex:u,totalFrames:d}),u>=d&&m(i)}catch(C){(x=>{if(f)return;f=!0,y();const b=x instanceof Error?x.message:"GIF recording failed";a==null||a({state:"error",message:b}),h(x instanceof Error?x:new Error(String(x)))})(C)}};c=t(()=>{v()}),a==null||a({state:"recording",frameIndex:0,totalFrames:d})})}}var Me,re,$e=Object.defineProperty,wt=(Me=l=>{function r(c,u,f){return .29889531*c+.58662247*u+.11448223*f}function e(c,u,f){return .59597799*c-.2741761*u-.32180189*f}function t(c,u,f){return .21147017*c-.52261711*u+.31114694*f}function a(c,u){let f=c[0]-u[0],y=c[1]-u[1],m=c[2]-u[2],v=o(c)-o(u);return f*f*.5053+y*y*.299+m*m*.1957+v*v}function o(c){return c[3]!=null?c[3]:255}function n(c,u){return Math.sqrt(a(c,u))}function d(c,u){let[f,y,m]=c,[v,C,x]=u,b=r(f,y,m)-r(v,C,x),B=e(f,y,m)-e(v,C,x),P=t(f,y,m)-t(v,C,x),S=o(c)-o(u);return b*b*.5053+B*B*.299+P*P*.1957+S*S}function s(c,u){return Math.sqrt(d(c,u))}function h(c,u){var f,y=0;for(f=0;f<c.length;f++){let m=c[f]-u[f];y+=m*m}return y}function i(c,u){return Math.sqrt(h(c,u))}$e(l,"__esModule",{value:!0}),((c,u)=>{for(var f in u)$e(c,f,{get:u[f],enumerable:!0})})(l,{colorDifferenceRGBToYIQ:()=>s,colorDifferenceRGBToYIQSquared:()=>d,colorDifferenceYIQ:()=>n,colorDifferenceYIQSquared:()=>a,euclideanDistance:()=>i,euclideanDistanceSquared:()=>h})},()=>(re||Me((re={exports:{}}).exports,re),re.exports)),_t=59;function Fe(l=256){let r=0,e=new Uint8Array(l);return{get buffer(){return e.buffer},reset(){r=0},bytesView:()=>e.subarray(0,r),bytes:()=>e.slice(0,r),writeByte(a){t(r+1),e[r]=a,r++},writeBytes(a,o=0,n=a.length){t(r+n);for(let d=0;d<n;d++)e[r++]=a[d+o]},writeBytesView(a,o=0,n=a.byteLength){t(r+n),e.set(a.subarray(o,o+n),r),r+=n}};function t(a){var o=e.length;if(o>=a)return;a=Math.max(a,o*(o<1048576?2:1.125)>>>0),o!=0&&(a=Math.max(a,256));let n=e;e=new Uint8Array(a),r>0&&e.set(n.subarray(0,r),0)}}var Ct=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],kt=function(l,r,e,t,a,o,n,d){a=a||Fe(512),o=o||new Uint8Array(256),n=n||new Int32Array(5003),d=d||new Int32Array(5003);let s=n.length,h=Math.max(2,t);o.fill(0),d.fill(0),$();let i=0,c=0,u=h+1,f=u,y=!1,m=f,v=O(m),C=1<<u-1,x=C+1,b=C+2,B=0,P=e[0],S=0;for(let w=s;w<65536;w*=2)++S;S=8-S,a.writeByte(h),V(C);for(let w=1;w<e.length;w++)D(e[w]);return V(P),V(x),a.writeByte(0),a.bytesView();function k(w){o[B++]=w,B>=254&&E()}function $(){n.fill(-1)}function D(w){let A=(w<<12)+P,g=w<<S^P;if(n[g]===A)P=d[g];else{if(n[g]>=0){let _=g===0?1:s-g;do if(g-=_,g<0&&(g+=s),n[g]===A)return void(P=d[g]);while(n[g]>=0)}V(P),P=w,b<4096?(d[g]=b++,n[g]=A):($(),b=C+2,y=!0,V(C))}}function E(){B>0&&(a.writeByte(B),a.writeBytesView(o,0,B),B=0)}function O(w){return(1<<w)-1}function V(w){for(i&=Ct[c],c>0?i|=w<<c:i=w,c+=m;c>=8;)k(255&i),i>>=8,c-=8;if((b>v||y)&&(y?(m=f,v=O(m),y=!1):(++m,v=m==12?4096:O(m))),w==x){for(;c>0;)k(255&i),i>>=8,c-=8;E()}}};function Le(l,r,e){return l<<8&63488|r<<2&992|e>>3&31}function Pe(l,r,e,t){return l>>4|240&r|(240&e)<<4|(240&t)<<8}function Oe(l,r,e){return l>>4<<8|r>>4<<4|e>>4}function ae(l,r,e){return l<r?r:l>e?e:l}function oe(l){return l*l}function Ve(l,r,e){for(var t=0,a=1e100,o=l[r],n=o.cnt,d=(o.ac,o.rc),s=o.gc,h=o.bc,i=o.fw;i!=0;i=l[i].fw){var c=l[i].cnt,u=n*c/(n+c);if(!(u>=a)){var f=0;!((f+=u*oe(l[i].rc-d))>=a)&&!((f+=u*oe(l[i].gc-s))>=a)&&!((f+=u*oe(l[i].bc-h))>=a)&&(a=f,t=i)}}o.err=a,o.nn=t}function pe(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function Et(l,r,e){let{format:t="rgb565",clearAlpha:a=!0,clearAlphaColor:o=0,clearAlphaThreshold:n=0,oneBitAlpha:d=!1}=e||{},s=e.useSqrt!==!1,h=t==="rgba4444",i=(function(w,A){let g=new Array(A==="rgb444"?4096:65536),_=w.length;if(A==="rgba4444")for(let M=0;M<_;++M){let F=w[M],L=F>>24&255,N=F>>16&255,I=F>>8&255,T=255&F,U=Pe(T,I,N,L),q=U in g?g[U]:g[U]=pe();q.rc+=T,q.gc+=I,q.bc+=N,q.ac+=L,q.cnt++}else if(A==="rgb444")for(let M=0;M<_;++M){let F=w[M],L=F>>16&255,N=F>>8&255,I=255&F,T=Oe(I,N,L),U=T in g?g[T]:g[T]=pe();U.rc+=I,U.gc+=N,U.bc+=L,U.cnt++}else for(let M=0;M<_;++M){let F=w[M],L=F>>16&255,N=F>>8&255,I=255&F,T=Le(I,N,L),U=T in g?g[T]:g[T]=pe();U.rc+=I,U.gc+=N,U.bc+=L,U.cnt++}return g})(l,t),c=i.length,u=c-1,f=new Uint32Array(c+1);for(var y=0,m=0;m<i.length;++m){let w=i[m];if(w!=null){var v=1/w.cnt;h&&(w.ac*=v),w.rc*=v,w.gc*=v,w.bc*=v,i[y++]=w}}for(oe(r)/y<.022&&(s=!1),m=0;m<y-1;++m)i[m].fw=m+1,i[m+1].bk=m,s&&(i[m].cnt=Math.sqrt(i[m].cnt));var C,x,b;for(s&&(i[m].cnt=Math.sqrt(i[m].cnt)),m=0;m<y;++m){Ve(i,m);var B=i[m].err;for(x=++f[0];x>1&&!(i[C=f[b=x>>1]].err<=B);x=b)f[x]=C;f[x]=m}var P=y-r;for(m=0;m<P;){for(var S;;){var k=f[1];if((S=i[k]).tm>=S.mtm&&i[S.nn].mtm<=S.tm)break;for(S.mtm==u?k=f[1]=f[f[0]--]:(Ve(i,k),S.tm=m),B=i[k].err,x=1;(b=x+x)<=f[0]&&(b<f[0]&&i[f[b]].err>i[f[b+1]].err&&b++,!(B<=i[C=f[b]].err));x=b)f[x]=C;f[x]=k}var $=i[S.nn],D=S.cnt,E=$.cnt;v=1/(D+E),h&&(S.ac=v*(D*S.ac+E*$.ac)),S.rc=v*(D*S.rc+E*$.rc),S.gc=v*(D*S.gc+E*$.gc),S.bc=v*(D*S.bc+E*$.bc),S.cnt+=$.cnt,S.mtm=++m,i[$.bk].fw=$.fw,i[$.fw].bk=$.bk,$.mtm=u}let O=[];var V=0;for(m=0;;++V){let w=ae(Math.round(i[m].rc),0,255),A=ae(Math.round(i[m].gc),0,255),g=ae(Math.round(i[m].bc),0,255),_=255;h&&(_=ae(Math.round(i[m].ac),0,255),d&&(_=_<=(typeof d=="number"?d:127)?0:255),a&&_<=n&&(w=A=g=o,_=0));let M=h?[w,A,g,_]:[w,A,g];if(Bt(O,M)||O.push(M),(m=i[m].fw)==0)break}return O}function Bt(l,r){for(let e=0;e<l.length;e++){let t=l[e],a=t[0]===r[0]&&t[1]===r[1]&&t[2]===r[2],o=!(t.length>=4&&r.length>=4)||t[3]===r[3];if(a&&o)return!0}return!1}function It(l,r,e){let t=(e=e||"rgb565")==="rgb444"?4096:65536,a=new Uint8Array(l.length),o=new Array(t);if(e==="rgba4444")for(let n=0;n<l.length;n++){let d,s=l[n],h=s>>24&255,i=s>>16&255,c=s>>8&255,u=255&s,f=Pe(u,c,i,h);o[f]!=null?d=o[f]:(d=St(u,c,i,h,r),o[f]=d),a[n]=d}else for(let n=0;n<l.length;n++){let d,s=l[n],h=s>>16&255,i=s>>8&255,c=255&s,u=e==="rgb444"?Oe(c,i,h):Le(c,i,h);o[u]!=null?d=o[u]:(d=Mt(c,i,h,r),o[u]=d),a[n]=d}return a}function St(l,r,e,t,a){let o=0,n=1e100;for(let d=0;d<a.length;d++){let s=a[d],h=s[0],i=s[1],c=s[2],u=Q(s[3]-t);u>n||(u+=Q(h-l),!(u>n)&&(u+=Q(i-r),!(u>n)&&(u+=Q(c-e),!(u>n)&&(n=u,o=d))))}return o}function Mt(l,r,e,t){let a=0,o=1e100;for(let n=0;n<t.length;n++){let d=t[n],s=d[0],h=d[1],i=d[2],c=Q(s-l);c>o||(c+=Q(h-r),!(c>o)&&(c+=Q(i-e),!(c>o)&&(o=c,a=n)))}return a}function Q(l){return l*l}function $t(l={}){let{initialCapacity:r=4096,auto:e=!0}=l,t=Fe(r),a=new Uint8Array(256),o=new Int32Array(5003),n=new Int32Array(5003),d=!1;return{reset(){t.reset(),d=!1},finish(){t.writeByte(_t)},bytes:()=>t.bytes(),bytesView:()=>t.bytesView(),get buffer(){return t.buffer},get stream(){return t},writeHeader:s,writeFrame(h,i,c,u={}){let{transparent:f=!1,transparentIndex:y=0,delay:m=0,palette:v=null,repeat:C=0,colorDepth:x=8,dispose:b=-1}=u,B=!1;if(e?d||(B=!0,s(),d=!0):B=!!u.first,i=Math.max(0,Math.floor(i)),c=Math.max(0,Math.floor(c)),B){if(!v)throw new Error("First frame must include a { palette } option");(function(k,$,D,E,O=8){let V=1,w=0,A=he(E.length)-1,g=V<<7|O-1<<4|w<<3|A;J(k,$),J(k,D),k.writeBytes([g,0,0])})(t,i,c,v,x),De(t,v),C>=0&&(function(k,$){k.writeByte(33),k.writeByte(255),k.writeByte(11),Ae(k,"NETSCAPE2.0"),k.writeByte(3),k.writeByte(1),J(k,$),k.writeByte(0)})(t,C)}let P=Math.round(m/10);(function(k,$,D,E,O){var V,w;k.writeByte(33),k.writeByte(249),k.writeByte(4),O<0&&(O=0,E=!1),E?(V=1,w=2):(V=0,w=0),$>=0&&(w=7&$),w<<=2,k.writeByte(0|w|0|V),J(k,D),k.writeByte(O||0),k.writeByte(0)})(t,b,P,f,y);let S=!!v&&!B;(function(k,$,D,E){if(k.writeByte(44),J(k,0),J(k,0),J(k,$),J(k,D),E){let O=0,V=0,w=he(E.length)-1;k.writeByte(128|O|V|w)}else k.writeByte(0)})(t,i,c,S?v:null),S&&De(t,v),(function(k,$,D,E,O=8,V,w,A){kt(D,E,$,O,k,V,w,A)})(t,h,i,c,x,a,o,n)}};function s(){Ae(t,"GIF89a")}}function De(l,r){let e=1<<he(r.length);for(let t=0;t<e;t++){let a=[0,0,0];t<r.length&&(a=r[t]),l.writeByte(a[0]),l.writeByte(a[1]),l.writeByte(a[2])}}function J(l,r){l.writeByte(255&r),l.writeByte(r>>8&255)}function Ae(l,r){for(var e=0;e<r.length;e++)l.writeByte(r.charCodeAt(e))}function he(l){return Math.max(Math.ceil(Math.log2(l)),1)}wt();class Ft{constructor(r,e){p(this,"_recorder");p(this,"_textmodifier");p(this,"_registerPostDrawHook");this._recorder=new yt,this._textmodifier=r,this._registerPostDrawHook=e}async $saveGIF(r={}){const e=this._textmodifier.canvas,t=this._applyDefaultOptions(r),a=r.onProgress;try{const o=await this._recorder.$record(e,t,this._registerPostDrawHook,a),n=$t(),{repeat:d}=r;for(let i=0;i<o.length;i++){const c=o[i],{width:u,height:f,imageData:y,delayMs:m}=c,v=new Uint32Array(y.data.buffer),C=Et(v,256,{}),x=It(v,C);n.writeFrame(x,u,f,{palette:C,delay:m,repeat:i===0?d:-1}),i%2!=0&&i!==o.length-1||(a==null||a({state:"encoding",frameIndex:i+1,totalFrames:o.length}),await new Promise(b=>setTimeout(b,0)))}n.finish();const s=n.bytes(),h=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);new j().$downloadFile(new Blob([h],{type:"image/gif"}),t.filename),a==null||a({state:"completed",totalFrames:t.frameCount})}catch(o){throw a==null||a({state:"error",message:o instanceof Error?o.message:"GIF export failed"}),o}}_applyDefaultOptions(r){const e=Math.abs(Math.round(r.frameCount??300)),t=Math.abs(r.frameRate??60),a=Math.abs(r.scale??1),o=Math.max(-1,Math.round(r.repeat??0));return{filename:r.filename,frameCount:e,frameRate:t,scale:a,repeat:o}}}function Lt(l){return l&&l.__esModule&&Object.prototype.hasOwnProperty.call(l,"default")?l.default:l}var Ne,Ue={exports:{}};function Pt(){return Ne||(Ne=1,(function(l){(function(){function r(s,h){return(function(i){if(typeof i!="string"||!i.match(/^data:image\/webp;base64,/i))throw new Error("Failed to decode WebP Base64 URL");return window.atob(i.substring(23))})(typeof s=="string"&&/^data:image\/webp/.test(s)?s:s.toDataURL("image/webp",h))}function e(s){return(s.charCodeAt(0)|s.charCodeAt(1)<<8|s.charCodeAt(2)<<16|s.charCodeAt(3)<<24)>>>0}function t(s){let h=s.indexOf("VP8",12);if(h===-1)throw new Error("Bad image format, does this browser support WebP?");let i=!1;for(;h<s.length-8;){let c,u;switch(u=s.substring(h,h+4),h+=4,c=e(s.substring(h,h+4)),h+=4,u){case"VP8 ":return{frame:s.substring(h,h+c),hasAlpha:i};case"ALPH":i=!0}h+=c,1&c&&h++}throw new Error("Failed to find VP8 keyframe in WebP image, is this image mistakenly encoded in the Lossless WebP format?")}function a(s){this.value=s}function o(s){this.value=s}function n(s,h,i){if(Array.isArray(i))for(let c=0;c<i.length;c++)n(s,h,i[c]);else if(typeof i=="string")s.writeString(i);else if(i instanceof Uint8Array)s.writeBytes(i);else{if(!i.id)throw new Error("Bad EBML datatype "+typeof i.data);if(i.offset=s.pos+h,s.writeUnsignedIntBE(i.id),Array.isArray(i.data)){let c,u,f;i.size===-1?s.writeByte(255):i.size===-2?(c=s.pos,s.writeBytes([15,255,255,255,255])):(c=s.pos,s.writeBytes([0,0,0,0])),u=s.pos,i.dataOffset=u+h,n(s,h,i.data),i.size!==-1&&i.size!==-2&&(f=s.pos,i.size=f-u,s.seek(c),s.writeEBMLVarIntWidth(i.size,4),s.seek(f))}else if(typeof i.data=="string")s.writeEBMLVarInt(i.data.length),i.dataOffset=s.pos+h,s.writeString(i.data);else if(typeof i.data=="number")i.size||(i.size=s.measureUnsignedInt(i.data)),s.writeEBMLVarInt(i.size),i.dataOffset=s.pos+h,s.writeUnsignedIntBE(i.data,i.size);else if(i.data instanceof o)s.writeEBMLVarInt(8),i.dataOffset=s.pos+h,s.writeDoubleBE(i.data.value);else if(i.data instanceof a)s.writeEBMLVarInt(4),i.dataOffset=s.pos+h,s.writeFloatBE(i.data.value);else{if(!(i.data instanceof Uint8Array))throw new Error("Bad EBML datatype "+typeof i.data);s.writeEBMLVarInt(i.data.byteLength),i.dataOffset=s.pos+h,s.writeBytes(i.data)}}}let d=function(s,h){return function(i){let c,u,f=!1,y=0,m=0,v=null,C=null,x=null,b=[],B=0,P=0,S={quality:.95,transparent:!1,alphaQuality:void 0,fileWriter:null,fd:null,frameDuration:null,frameRate:null},k={Cues:{id:new Uint8Array([28,83,187,107]),positionEBML:null},SegmentInfo:{id:new Uint8Array([21,73,169,102]),positionEBML:null},Tracks:{id:new Uint8Array([22,84,174,107]),positionEBML:null}},$={id:17545,data:new o(0)},D=[],E=new h(i.fileWriter||i.fd);function O(g){return g-c.dataOffset}function V(){u=(function(){let L={id:21420,size:5,data:0},N={id:290298740,data:[]};for(let I in k){let T=k[I];T.positionEBML=Object.create(L),N.data.push({id:19899,data:[{id:21419,data:T.id},T.positionEBML]})}return N})();let g={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:"webm-writer-js"},{id:22337,data:"webm-writer-js"},$]},_=[{id:176,data:y},{id:186,data:m}];i.transparent&&_.push({id:21440,data:1});let M={id:374648427,data:[{id:174,data:[{id:215,data:1},{id:29637,data:1},{id:156,data:0},{id:2274716,data:"und"},{id:134,data:"V_VP8"},{id:2459272,data:"VP8"},{id:131,data:1},{id:224,data:_}]}]};c={id:408125543,size:-2,data:[u,g,M]};let F=new s(256);n(F,E.pos,[{id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:"webm"},{id:17031,data:2},{id:17029,data:2}]},c]),E.write(F.getAsDataArray()),k.SegmentInfo.positionEBML.data=O(g.offset),k.Tracks.positionEBML.data=O(M.offset),f=!0}function w(g){return g.alpha?(function(_){let M,F,L=new s(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return L.writeEBMLVarInt(_.trackNumber),L.writeU16BE(_.timecode),L.writeByte(0),M={id:161,data:[L.getAsDataArray(),_.frame]},F={id:30113,data:[{id:166,data:[{id:238,data:1},{id:165,data:_.alpha}]}]},{id:160,data:[M,F]}})(g):(function(_){let M=new s(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return M.writeEBMLVarInt(_.trackNumber),M.writeU16BE(_.timecode),M.writeByte(128),{id:163,data:[M.getAsDataArray(),_.frame]}})(g)}function A(){if(b.length===0)return;let g=0;for(let I=0;I<b.length;I++)g+=b[I].frame.length+(b[I].alpha?b[I].alpha.length:0);let _=new s(g+64*b.length),M=(function(I){return{id:524531317,data:[{id:231,data:Math.round(I.timecode)}]}})({timecode:Math.round(B)});for(let I=0;I<b.length;I++)M.data.push(w(b[I]));var F,L,N;n(_,E.pos,M),E.write(_.getAsDataArray()),F=1,L=Math.round(B),N=M.offset,D.push({id:187,data:[{id:179,data:L},{id:183,data:[{id:247,data:F},{id:241,data:O(N)}]}]}),b=[],B+=P,P=0}this.addFrame=function(g,_,M){f||(y=g.width||0,m=g.height||0,V());let F,L=t(r(g,i.quality)),N=null;F=M||(typeof _=="number"?_:i.frameDuration),i.transparent&&(_ instanceof HTMLCanvasElement||typeof _=="string"?N=_:L.hasAlpha&&(N=(function(I){v!==null&&v.width===I.width&&v.height===I.height||(v=document.createElement("canvas"),v.width=I.width,v.height=I.height,C=v.getContext("2d"),x=C.createImageData(v.width,v.height));let T=I.getContext("2d").getImageData(0,0,I.width,I.height).data,U=x.data,q=0,Er=I.width*I.height*4;for(let Ce=3;Ce<Er;Ce+=4){let ke=T[Ce];U[q++]=ke,U[q++]=ke,U[q++]=ke,U[q++]=255}return C.putImageData(x,0,0),v})(g))),(function(I){I.trackNumber=1,I.timecode=Math.round(P),b.push(I),P+=I.duration,P>=5e3&&A()})({frame:L.frame,duration:F,alpha:N?t(r(N,i.alphaQuality)).frame:null})},this.complete=function(){return f||V(),A(),(function(){let g={id:475249515,data:D},_=new s(16+32*D.length);n(_,E.pos,g),E.write(_.getAsDataArray()),k.Cues.positionEBML.data=O(g.offset)})(),(function(){let g=new s(u.size),_=E.pos;n(g,u.dataOffset,u.data),E.seek(u.dataOffset),E.write(g.getAsDataArray()),E.seek(_)})(),(function(){let g=new s(8),_=E.pos;g.writeDoubleBE(B),E.seek($.dataOffset),E.write(g.getAsDataArray()),E.seek(_)})(),(function(){let g=new s(10),_=E.pos;g.writeUnsignedIntBE(c.id),g.writeEBMLVarIntWidth(E.pos-c.dataOffset,5),E.seek(c.offset),E.write(g.getAsDataArray()),E.seek(_)})(),E.complete("video/webm")},this.getWrittenSize=function(){return E.length},i=(function(g,_){let M={};return[g,_].forEach(function(F){for(let L in F)Object.prototype.hasOwnProperty.call(F,L)&&(M[L]=F[L])}),M})(S,i||{}),(function(){if(!i.frameDuration){if(!i.frameRate)throw new Error("Missing required frameDuration or frameRate setting");i.frameDuration=1e3/i.frameRate}i.quality=Math.max(Math.min(i.quality,.99999),0),i.alphaQuality===void 0?i.alphaQuality=i.quality:i.alphaQuality=Math.max(Math.min(i.alphaQuality,.99999),0)})()}};l.exports=d})()})(Ue)),Ue.exports}var Te,Re={exports:{}};function Ot(){return Te||(Te=1,(function(l){(function(){let r=function(e){this.data=new Uint8Array(e),this.pos=0};r.prototype.seek=function(e){this.pos=e},r.prototype.writeBytes=function(e){for(let t=0;t<e.length;t++)this.data[this.pos++]=e[t]},r.prototype.writeByte=function(e){this.data[this.pos++]=e},r.prototype.writeU8=r.prototype.writeByte,r.prototype.writeU16BE=function(e){this.data[this.pos++]=e>>8,this.data[this.pos++]=e},r.prototype.writeDoubleBE=function(e){let t=new Uint8Array(new Float64Array([e]).buffer);for(let a=t.length-1;a>=0;a--)this.writeByte(t[a])},r.prototype.writeFloatBE=function(e){let t=new Uint8Array(new Float32Array([e]).buffer);for(let a=t.length-1;a>=0;a--)this.writeByte(t[a])},r.prototype.writeString=function(e){for(let t=0;t<e.length;t++)this.data[this.pos++]=e.charCodeAt(t)},r.prototype.writeEBMLVarIntWidth=function(e,t){switch(t){case 1:this.writeU8(128|e);break;case 2:this.writeU8(64|e>>8),this.writeU8(e);break;case 3:this.writeU8(32|e>>16),this.writeU8(e>>8),this.writeU8(e);break;case 4:this.writeU8(16|e>>24),this.writeU8(e>>16),this.writeU8(e>>8),this.writeU8(e);break;case 5:this.writeU8(8|e/4294967296&7),this.writeU8(e>>24),this.writeU8(e>>16),this.writeU8(e>>8),this.writeU8(e);break;default:throw new Error("Bad EBML VINT size "+t)}},r.prototype.measureEBMLVarInt=function(e){if(e<127)return 1;if(e<16383)return 2;if(e<2097151)return 3;if(e<268435455)return 4;if(e<34359738367)return 5;throw new Error("EBML VINT size not supported "+e)},r.prototype.writeEBMLVarInt=function(e){this.writeEBMLVarIntWidth(e,this.measureEBMLVarInt(e))},r.prototype.writeUnsignedIntBE=function(e,t){switch(t===void 0&&(t=this.measureUnsignedInt(e)),t){case 5:this.writeU8(Math.floor(e/4294967296));case 4:this.writeU8(e>>24);case 3:this.writeU8(e>>16);case 2:this.writeU8(e>>8);case 1:this.writeU8(e);break;default:throw new Error("Bad UINT size "+t)}},r.prototype.measureUnsignedInt=function(e){return e<256?1:e<65536?2:e<1<<24?3:e<4294967296?4:5},r.prototype.getAsDataArray=function(){if(this.pos<this.data.byteLength)return this.data.subarray(0,this.pos);if(this.pos==this.data.byteLength)return this.data;throw new Error("ArrayBufferDataStream's pos lies beyond end of buffer")},l.exports=r})()})(Re)),Re.exports}var ze,Ge,je,He={exports:{}};function Vt(){return ze||(ze=1,(function(l){(function(){let r=function(e){return function(t){let a=[],o=Promise.resolve(),n=null,d=null;function s(c){return new Promise(function(u,f){let y=new FileReader;y.addEventListener("loadend",function(){u(y.result)}),y.readAsArrayBuffer(c)})}function h(c){return new Promise(function(u,f){c instanceof Uint8Array?u(c):c instanceof ArrayBuffer||ArrayBuffer.isView(c)?u(new Uint8Array(c)):c instanceof Blob?u(s(c).then(function(y){return new Uint8Array(y)})):u(s(new Blob([c])).then(function(y){return new Uint8Array(y)}))})}function i(c){let u=c.byteLength||c.length||c.size;if(!Number.isInteger(u))throw new Error("Failed to determine size of element");return u}t&&t.constructor.name==="FileWriter"?n=t:e&&t&&(d=t),this.pos=0,this.length=0,this.seek=function(c){if(c<0)throw new Error("Offset may not be negative");if(isNaN(c))throw new Error("Offset may not be NaN");if(c>this.length)throw new Error("Seeking beyond the end of file is not allowed");this.pos=c},this.write=function(c){let u={offset:this.pos,data:c,length:i(c)},f=u.offset>=this.length;this.pos+=u.length,this.length=Math.max(this.length,this.pos),o=o.then(function(){if(d)return new Promise(function(y,m){h(u.data).then(function(v){let C=0,x=Buffer.from(v.buffer),b=function(B,P,S){C+=P,C>=S.length?y():e.write(d,S,C,S.length-C,u.offset+C,b)};e.write(d,x,0,x.length,u.offset,b)})});if(n)return new Promise(function(y,m){n.onwriteend=y,n.seek(u.offset),n.write(new Blob([u.data]))});if(!f)for(let y=0;y<a.length;y++){let m=a[y];if(!(u.offset+u.length<=m.offset||u.offset>=m.offset+m.length)){if(u.offset<m.offset||u.offset+u.length>m.offset+m.length)throw new Error("Overwrite crosses blob boundaries");return u.offset==m.offset&&u.length==m.length?void(m.data=u.data):h(m.data).then(function(v){return m.data=v,h(u.data)}).then(function(v){u.data=v,m.data.set(u.data,u.offset-m.offset)})}}a.push(u)})},this.complete=function(c){return o=d||n?o.then(function(){return null}):o.then(function(){let u=[];for(let f=0;f<a.length;f++)u.push(a[f].data);return new Blob(u,{type:c})}),o}}};l.exports=r})()})(He)),He.exports}function Dt(){return je?Ge:(je=1,Ge=Pt()(Ot(),Vt()(null)))}const At=Lt(Dt());class Nt{async $record(r,e,t,a){const o=Math.max(1,Math.round(e.frameRate)),n=Math.max(1,Math.round(e.frameCount)),d=new At({quality:e.quality,alphaQuality:e.transparent?e.quality:void 0,transparent:e.transparent,frameRate:o}),s=this._createSnapshotSurface();return await new Promise((h,i)=>{let c,u="capturing",f=!1,y=0;const m=()=>{c&&(c(),c=void 0)},v=()=>{a==null||a({state:"recording",frameIndex:y,totalFrames:n})},C=b=>{if(f)return;f=!0,m();const B=b instanceof Error?b.message:"WEBM export failed";a==null||a({state:"error",message:B}),i(b instanceof Error?b:new Error(String(b)))},x=()=>{u!=="capturing"||f||(u="encoding",m(),d.complete().then(b=>{(B=>{f||(f=!0,a==null||a({state:"completed",frameIndex:Math.min(n,y),totalFrames:n}),h(B))})(b)}).catch(C))};c=t(()=>{(()=>{if(u==="capturing")if(y>=n)x();else try{const b=s(r);d.addFrame(b),y+=1,v(),y>=n&&x()}catch(b){C(b)}})()}),v()})}_createSnapshotSurface(){let r=null,e=null;return t=>{const a=Math.max(1,t.width),o=Math.max(1,t.height),n=((d,s)=>(r||(r=document.createElement("canvas")),r.width!==d||r.height!==s?(r.width=d,r.height=s,e=r.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)):e||(e=r.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)),e?r:null))(a,o);return n&&e?(e.clearRect(0,0,a,o),e.drawImage(t,0,0,a,o),n):t}}}class Ut{constructor(r,e){p(this,"_recorder");p(this,"_textmodifier");p(this,"_registerPostDrawHook");this._recorder=new Nt,this._textmodifier=r,this._registerPostDrawHook=e}async $saveWEBM(r={}){var a;const e=this._textmodifier.canvas,t=this._applyDefaultOptions(r);try{const o=await this._recorder.$record(e,t,this._registerPostDrawHook,r.onProgress);new j().$downloadFile(o,t.filename)}catch(o){throw(a=r.onProgress)==null||a.call(r,{state:"error",message:o instanceof Error?o.message:"WEBM export failed"}),o}}_applyDefaultOptions(r){return{filename:r.filename,frameRate:Math.abs(Math.round(r.frameRate??60)),frameCount:Math.abs(Math.round(r.frameCount??300)),quality:Math.abs(Math.min(Math.max(r.quality??1,0),1)),transparent:!!r.transparent,debugLogging:!!r.debugLogging}}}class Tt extends R{$extractCellData(r){var n;const e=r.layers.base.drawFramebuffer,t=this.$extractFramebufferData(e),a=[];let o=0;for(let d=0;d<r.grid.rows;d++)for(let s=0;s<r.grid.cols;s++){const h=4*o,i=this.$getEncodedCharacterValue(t.characterPixels,h),c=this.$extractCellTransform(t.characterPixels,h),u=((n=ce(r.font,i))==null?void 0:n.character)??" ";a.push({x:s,y:d,character:u,foreground:te(t.primaryColorPixels,h),background:te(t.secondaryColorPixels,h),transform:{invert:c.isInverted,flipX:c.flipHorizontal,flipY:c.flipVertical,rotation:c.rotation}}),o++}return a}}const We="1.2.1";class me{_applyDefaultOptions(r){return{pretty:r.pretty??!0,colorMode:r.colorMode??"hex",includeMetadata:r.includeMetadata??!0,filename:r.filename}}_formatColor(r,e){return e==="rgba"?{...r}:`#${[r.r,r.g,r.b,r.a].map(t=>t.toString(16).padStart(2,"0")).join("")}`}_createObjectRowsCells(r,e,t){const a=[];for(let o=0;o<e.grid.rows;o++){const n=o*e.grid.cols,d=r.slice(n,n+e.grid.cols).map(s=>({x:s.x,y:s.y,character:s.character,foreground:this._formatColor(s.foreground,t),background:this._formatColor(s.background,t),transform:{...s.transform}}));a.push(d)}return{encoding:"object-rows-v1",rows:a}}$generateJSONData(r,e={}){const t=this._applyDefaultOptions(e),a=new Tt().$extractCellData(r),o=this._createObjectRowsCells(a,r,t.colorMode);return{$schema:"https://textmode.art/schemas/textmode-layer-1.0.schema.json",format:"textmode.layer",formatVersion:"1.0.0",...t.includeMetadata?{metadata:{createdAt:new Date().toISOString(),generator:{name:"textmode.export.js",version:We}}}:{},canvas:{width:r.grid.width,height:r.grid.height},grid:{cols:r.grid.cols,rows:r.grid.rows,cellWidth:r.grid.cellWidth,cellHeight:r.grid.cellHeight},layer:{id:"base",cells:o}}}$generateJSONString(r,e={}){const t=this._applyDefaultOptions(e),a=this.$generateJSONData(r,t),o=typeof t.pretty=="number"?t.pretty:t.pretty?2:0;return JSON.stringify(a,null,o)}$saveJSON(r,e={}){const t=this._applyDefaultOptions(e);new j().$downloadFile(new Blob([this.$generateJSONString(r,t)],{type:"application/json;charset=utf-8"}),t.filename)}}const Rt="textmode-export-overlay",H="textmode-export-overlay__stack",fe="textmode-export-overlay__stack--dense",qe="textmode-export-overlay__stack--compact",Je="textmode-export-overlay__section",zt="textmode-export-overlay__header",Gt="textmode-export-overlay__header-title-row",jt="textmode-export-overlay__header-links",Ht="textmode-export-overlay__row",Xe="textmode-export-overlay__label",Qe="textmode-export-overlay__field",Ye="textmode-export-overlay__field--compact",Ze="textmode-export-overlay__field--dense",Ke="textmode-export-overlay__field--full",et="textmode-export-overlay__field--channel",tt="textmode-export-overlay__input",Wt="textmode-export-overlay__checkbox",rt="textmode-export-overlay__muted",qt="textmode-export-overlay__status",Jt="textmode-export-overlay__status--gif",Xt="textmode-export-overlay__status--video",Qt="textmode-export-overlay__status-title",Yt="textmode-export-overlay__status-value",Zt="textmode-export-overlay__divider",Kt="textmode-export-overlay__title",er="textmode-export-overlay__button",ge="textmode-export-overlay__button--primary",be="textmode-export-overlay__button--secondary",at="textmode-export-overlay__button--full",tr="textmode-export-overlay__support-link",rr="textmode-export-overlay__support-icon",ar="textmode-export-overlay__link-icon";class W{constructor(){p(this,"element");p(this,"mounted",!1);p(this,"destroyed",!1)}mount(r){if(this.destroyed)throw new Error("Cannot mount a destroyed component");if(this.mounted)return;const e=this.render();r.appendChild(e),this.element=e,this.onMount(),this.mounted=!0}unmount(){this.mounted&&this.element&&(this._onUnmount(),this.element.remove(),this.element=void 0,this.mounted=!1)}destroy(){this.destroyed||(this.unmount(),this._onDestroy(),this.destroyed=!0)}update(r){this.mounted&&this.onUpdate(r)}onMount(){}_onUnmount(){}_onDestroy(){}onUpdate(r){}get root(){if(!this.element)throw new Error("Component is not mounted yet");return this.element}isMounted(){return this.mounted}}const Z=class Z extends W{render(){const r=document.createElement("div");r.classList.add(H,fe,zt);const e=document.createElement("div");e.classList.add(Gt);const t=document.createElement("strong");t.textContent="textmode.export.js",t.classList.add(Kt);const a=document.createElement("div");a.classList.add(jt);const o=this._createLink("https://github.com/humanbydefinition/textmode.export.js","View repository on GitHub",ar,[{d:"M0 0h24v24H0z",fill:"none",stroke:"none"},{d:"M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5"}]),n=this._createLink("https://code.textmode.art/docs/support","Support textmode.export.js",rr,[{d:"M0 0h24v24H0z",fill:"none",stroke:"none"},{d:"M3 14c.83 .642 2.077 1.017 3.5 1c1.423 .017 2.67 -.358 3.5 -1c.83 -.642 2.077 -1.017 3.5 -1c1.423 -.017 2.67 .358 3.5 1"},{d:"M8 3a2.4 2.4 0 0 0 -1 2a2.4 2.4 0 0 0 1 2"},{d:"M12 3a2.4 2.4 0 0 0 -1 2a2.4 2.4 0 0 0 1 2"},{d:"M3 10h14v5a6 6 0 0 1 -6 6h-2a6 6 0 0 1 -6 -6v-5z"},{d:"M16.746 16.726a3 3 0 1 0 .252 -5.555"}]);a.appendChild(o),a.appendChild(n),e.appendChild(t),e.appendChild(a);const d=document.createElement("div");return d.classList.add(Zt),r.appendChild(e),r.appendChild(d),r}_createLink(r,e,t,a){const o=document.createElement("a");return o.href=r,o.target="_blank",o.rel="noopener noreferrer",o.classList.add(tr),o.setAttribute("aria-label",e),o.appendChild(this._createIcon(t,a)),o}_createIcon(r,e){const t=document.createElementNS(Z._iconNamespace,"svg");t.setAttribute("xmlns",Z._iconNamespace),t.setAttribute("width","18"),t.setAttribute("height","18"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.setAttribute("stroke","currentColor"),t.setAttribute("stroke-width","2"),t.setAttribute("stroke-linecap","round"),t.setAttribute("stroke-linejoin","round"),t.classList.add(r);for(const a of e){const o=document.createElementNS(Z._iconNamespace,"path");for(const[n,d]of Object.entries(a))o.setAttribute(n,d);t.appendChild(o)}return t}};p(Z,"_iconNamespace","http://www.w3.org/2000/svg");let ve=Z;class z extends W{constructor(e){super();p(this,"props");this.props=e}render(){const e=document.createElement("div");e.classList.add(Qe),this.applyVariant(e,this.props.variant);const t=document.createElement("label");if(t.classList.add(Xe),t.textContent=this.props.label,this.props.labelFor&&(t.htmlFor=this.props.labelFor),e.appendChild(t),this.props.description){const a=document.createElement("span");a.classList.add(rt),a.textContent=this.props.description,e.appendChild(a)}return e}attachControl(e){this.root.appendChild(e)}update(e){this.props=e,super.update(e)}onUpdate(e){const t=this.root;for(;t.firstChild;)t.removeChild(t.firstChild);this.props=e,t.classList.add(Qe),this.applyVariant(t,e.variant);const a=document.createElement("label");if(a.classList.add(Xe),a.textContent=e.label,e.labelFor&&(a.htmlFor=e.labelFor),t.appendChild(a),e.description){const o=document.createElement("span");o.classList.add(rt),o.textContent=e.description,t.appendChild(o)}}applyVariant(e,t){switch(e.classList.remove(Ye,Ze,Ke,et),t){case"compact":e.classList.add(Ye);break;case"dense":e.classList.add(Ze);break;case"full":e.classList.add(Ke);break;case"channel":e.classList.add(et)}}}class ie extends W{constructor(e){super();p(this,"props");p(this,"select");p(this,"handleChange",()=>{this.props.defaultValue=this.select.value});this.props=e}render(){return this.select=document.createElement("select"),this.select.classList.add(tt),this.props.id&&(this.select.id=this.props.id),this.populateOptions(),this.select.addEventListener("change",this.handleChange),this.select}get selectElement(){return this.select}get value(){return this.select.value}set value(e){this.select&&(this.select.value=e),this.props.defaultValue=e}_onUnmount(){this.select.removeEventListener("change",this.handleChange)}onUpdate(e){this.props=e,this.populateOptions(),e.defaultValue&&(this.select.value=e.defaultValue)}update(e){this.props={...this.props,...e},this.select&&(e.id&&(this.select.id=e.id),e.options&&this.populateOptions(),e.defaultValue!==void 0&&(this.select.value=e.defaultValue))}populateOptions(){if(this.select){this.select.innerHTML="";for(const e of this.props.options){const t=document.createElement("option");t.value=e.value,t.textContent=e.label,this.select.appendChild(t)}this.props.defaultValue&&(this.select.value=this.props.defaultValue)}}}class ot extends W{constructor(e){super();p(this,"props");p(this,"button");this.props=e}render(){return this.button=document.createElement("button"),this.button.type="button",this.button.textContent=this.props.label,this.button.classList.add(er),this.props.variant==="secondary"?this.button.classList.add(be):this.button.classList.add(ge),this.props.fullWidth&&this.button.classList.add(at),this.button.disabled=!!this.props.disabled,this.button}get buttonElement(){return this.button}setLabel(e){this.props.label=e,this.button.textContent=e}setDisabled(e){this.props.disabled=e,this.button.disabled=e}onUpdate(e){this.props=e,this.button.textContent=e.label,this.button.disabled=!!e.disabled,e.variant==="secondary"?(this.button.classList.add(be),this.button.classList.remove(ge)):(this.button.classList.add(ge),this.button.classList.remove(be)),this.button.classList.toggle(at,!!e.fullWidth)}}class or{constructor(r){p(this,"api");this.api=r}async $copy(r,e){switch(r){case"txt":{const t=this.api.toString(e);await navigator.clipboard.writeText(t);break}case"json":{const t=this.api.toJSONString(e);await navigator.clipboard.writeText(t);break}case"svg":{const t=this.api.toSVG(e);await navigator.clipboard.writeText(t);break}case"image":await this.api.copyCanvas(e);break;default:throw new Error(`Clipboard not supported for ${r}`)}}}class ir{constructor(r,e){p(this,"api");p(this,"events");this.api=r,this.events=e}async $requestExport(r,e,t={}){this.events.$emit("export:request",{format:r});try{const a={onGIFProgress:t.onGIFProgress?o=>{var n;(n=t.onGIFProgress)==null||n.call(t,o),this.events.$emit("export:progress",{format:r,progress:o})}:r==="gif"?o=>this.events.$emit("export:progress",{format:r,progress:o}):void 0,onVideoProgress:t.onVideoProgress?o=>{var n;(n=t.onVideoProgress)==null||n.call(t,o),this.events.$emit("export:progress",{format:r,progress:o})}:r==="video"?o=>this.events.$emit("export:progress",{format:r,progress:o}):void 0};await this._execute(r,e,a),this.events.$emit("export:success",{format:r})}catch(a){throw this.events.$emit("export:error",{format:r,error:a}),a}}_execute(r,e,t){switch(r){case"txt":return Promise.resolve(this.api.saveStrings(e));case"json":return Promise.resolve(this.api.saveJSON(e));case"image":return this.api.saveCanvas(e);case"svg":return Promise.resolve(this.api.saveSVG(e));case"gif":{const a={...e,onProgress:t.onGIFProgress};return this.api.saveGIF(a)}case"video":{const a={...e,onProgress:t.onVideoProgress};return this.api.saveWEBM(a)}}}}class nr{constructor(r,e){p(this,"modifier");p(this,"overlay");p(this,"animationFrameId",null);p(this,"handleUpdate");p(this,"bound",!1);this.modifier=r,this.overlay=e,this.handleUpdate=()=>this.scheduleUpdate()}scheduleUpdate(){this.animationFrameId!==null&&cancelAnimationFrame(this.animationFrameId),this.animationFrameId=requestAnimationFrame(()=>this.update())}bind(){this.bound||(window.addEventListener("resize",this.handleUpdate),window.addEventListener("scroll",this.handleUpdate,!0),this.bound=!0,this.handleUpdate())}update(){this.animationFrameId=null;const r=this.modifier.canvas.getBoundingClientRect();this.overlay.style.top=`${r.top+window.scrollY+8}px`,this.overlay.style.left=`${r.left+window.scrollX+8}px`}dispose(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.bound&&(window.removeEventListener("resize",this.handleUpdate),window.removeEventListener("scroll",this.handleUpdate,!0),this.bound=!1)}}const K="textmode-export-number-input",sr=`${K}__field`,lr=`${K}__controls`,dr=`${K}__control`,it=`${K}__display`,ne=`${it}--visible`,nt=l=>{const r=document.createElement("button");return r.type="button",r.className=dr,r.textContent=l>0?"▲":"▼",r};class X extends W{constructor(e){super();p(this,"props");p(this,"input");p(this,"display");p(this,"incrementButton");p(this,"decrementButton");p(this,"suppressClickAfterPointer",new WeakMap);p(this,"holdTimeoutId");p(this,"holdIntervalId");p(this,"activePointerId");p(this,"disabledObserver");this.props=e}render(){const e=document.createElement("div");e.className=K,this.input=document.createElement("input"),this.input.type="number",this.input.value=this.props.defaultValue,Object.assign(this.input,this.props.attributes),this.input.className=sr,this.display=document.createElement("div"),this.display.className=it;const t=document.createElement("div");return t.className=lr,this.incrementButton=nt(1),this.decrementButton=nt(-1),t.appendChild(this.incrementButton),t.appendChild(this.decrementButton),e.appendChild(this.input),e.appendChild(this.display),e.appendChild(t),this.bindStepControls(),this.bindHoldBehavior(),this.bindInputListeners(),this.observeDisabledState(e),this.updateDisplay(),e}get inputElement(){return this.input}get value(){return this.input.value}set value(e){this.input.value=e,this.updateDisplay()}refresh(){this.updateDisplay()}_onDestroy(){var e;this.clearHoldTimers(),(e=this.disabledObserver)==null||e.disconnect()}bindStepControls(){const e=n=>()=>{if(this.input.disabled)return;const d=this.input.value,s=this.input.getAttribute("step");if(s&&s!=="any")n>0?this.input.stepUp():this.input.stepDown();else{const i=n>0?1:-1,c=Number.parseFloat(this.input.value||"0"),u=Number.isFinite(c)?c+i:i;this.input.value=String(u)}var h;this.input.value!==d&&((h=this.input).dispatchEvent(new Event("input",{bubbles:!0})),h.dispatchEvent(new Event("change",{bubbles:!0}))),this.updateDisplay(),this.input.focus({preventScroll:!0})},t=e(1),a=e(-1),o=(n,d)=>s=>{if(this.suppressClickAfterPointer.get(n))return this.suppressClickAfterPointer.set(n,!1),void s.preventDefault();d()};this.incrementButton.addEventListener("click",o(this.incrementButton,t)),this.decrementButton.addEventListener("click",o(this.decrementButton,a))}bindHoldBehavior(){const e=(t,a)=>{const o=a>0?()=>this.incrementButton.click():()=>this.decrementButton.click();t.addEventListener("pointerdown",s=>{if(s.button===0){s.preventDefault(),this.suppressClickAfterPointer.set(t,!0),this.activePointerId=s.pointerId;try{t.setPointerCapture(s.pointerId)}catch{}o(),this.holdTimeoutId=window.setTimeout(()=>{this.holdIntervalId=window.setInterval(o,80)},380)}});const n=()=>{if(this.activePointerId!==void 0){try{t.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}},d=()=>{this.clearHoldTimers(),n()};t.addEventListener("pointerup",d),t.addEventListener("pointerleave",d),t.addEventListener("pointercancel",d)};e(this.incrementButton,1),e(this.decrementButton,-1)}bindInputListeners(){const e=()=>{this.props.defaultValue=this.input.value,this.updateDisplay()};this.input.addEventListener("input",e),this.input.addEventListener("change",e)}observeDisabledState(e){const t=()=>{const a=this.input.disabled;this.incrementButton.disabled=a,this.decrementButton.disabled=a,e.classList.toggle("is-disabled",a),a?(this.display.classList.remove(ne),this.input.style.removeProperty("color"),this.input.style.removeProperty("caretColor")):this.updateDisplay()};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(t),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),t()}updateDisplay(){const e=this.props.formatDisplay;if(!e)return this.display.textContent="",this.display.classList.remove(ne),this.input.style.removeProperty("color"),void this.input.style.removeProperty("caretColor");const t=this.input.value,a=Number.parseFloat(t),o=e(Number.isFinite(a)?a:Number.NaN,t,this.input);o?(this.display.textContent=o,this.display.classList.add(ne),this.input.style.color="transparent",this.input.style.caretColor="#f8fafc"):(this.display.textContent="",this.display.classList.remove(ne),this.input.style.removeProperty("color"),this.input.style.removeProperty("caretColor"))}clearHoldTimers(){this.holdTimeoutId!==void 0&&(window.clearTimeout(this.holdTimeoutId),this.holdTimeoutId=void 0),this.holdIntervalId!==void 0&&(window.clearInterval(this.holdIntervalId),this.holdIntervalId=void 0)}}class ee extends W{constructor(e="stack",t=[]){super();p(this,"variant");p(this,"additionalClasses");this.variant=e,this.additionalClasses=t}render(){const e=document.createElement("div"),t=[this.variant==="stack"?H:void 0,this.variant==="stackDense"?fe:void 0,this.variant==="stackCompact"?qe:void 0,this.variant==="row"?Ht:void 0,this.variant==="section"?Je:void 0,...this.additionalClasses].filter(Boolean);return e.classList.add(...t),e}}const st={neutral:"textmode-export-overlay__status-value--neutral",active:"textmode-export-overlay__status-value--active",alert:"textmode-export-overlay__status-value--alert"};class lt extends W{constructor(e){super();p(this,"props");p(this,"container");p(this,"messageElement");this.props=e}render(){this.container=document.createElement("div"),this.container.classList.add(qt),this.props.context==="gif"?this.container.classList.add(Jt):this.props.context==="video"&&this.container.classList.add(Xt);const e=document.createElement("span");return e.classList.add(Qt),e.textContent=this.props.title,this.messageElement=document.createElement("span"),this.messageElement.classList.add(Yt),this.messageElement.textContent=this.props.message,this.applyVariant(this.props.variant??"neutral"),this.container.appendChild(e),this.container.appendChild(this.messageElement),this.container}setMessage(e,t="neutral"){this.messageElement.textContent=e,this.applyVariant(t)}onUpdate(e){this.props=e,this.setMessage(e.message,e.variant??"neutral")}applyVariant(e){this.messageElement.classList.remove(...Object.values(st)),this.messageElement.classList.add(st[e])}}class Y extends W{constructor(e){super();p(this,"_config");p(this,"_managedComponents",new Set);this._config=e}_manageComponent(e){return this._managedComponents.add(e),e}_onUnmount(){for(const e of this._managedComponents)e.unmount()}_onDestroy(){for(const e of this._managedComponents)e.destroy();this._managedComponents.clear()}}const dt=300,ct=60,ut=1,cr=0;class xe extends Y{constructor(e){super(e);p(this,"frameCountInput",this._manageComponent(new X({defaultValue:String(dt),attributes:{min:"1",max:"600",step:"1"}})));p(this,"frameRateInput",this._manageComponent(new X({defaultValue:String(ct),attributes:{min:"1",max:"60",step:"1"}})));p(this,"scaleInput",this._manageComponent(new X({defaultValue:String(ut),attributes:{min:"0.1",max:"8",step:"0.1"}})));p(this,"repeatInput",this._manageComponent(new X({defaultValue:"0",attributes:{min:"0",max:"50",step:"1"},formatDisplay:(e,t)=>Number.isFinite(e)?e===0?"∞":null:t.trim()===""?null:t})));p(this,"status",this._manageComponent(new lt({title:"status",message:"ready to record",variant:"neutral",context:"gif"})));p(this,"recordingState","idle")}render(){const e=document.createElement("div");e.classList.add(H);const t=new ee("row");t.mount(e);const a=new z({label:"number of frames",labelFor:"textmode-export-gif-frame-count",variant:"dense"});a.mount(t.root),this.frameCountInput.mount(a.root),this.frameCountInput.inputElement.id="textmode-export-gif-frame-count";const o=new z({label:"frame rate (fps)",labelFor:"textmode-export-gif-frame-rate",variant:"dense"});o.mount(t.root),this.frameRateInput.mount(o.root),this.frameRateInput.inputElement.id="textmode-export-gif-frame-rate";const n=new ee("row");n.mount(e);const d=new z({label:"scale",labelFor:"textmode-export-gif-scale",variant:"dense"});d.mount(n.root),this.scaleInput.mount(d.root),this.scaleInput.inputElement.id="textmode-export-gif-scale";const s=new z({label:"loop count",labelFor:"textmode-export-gif-repeat",variant:"dense"});return s.mount(n.root),this.repeatInput.mount(s.root),this.repeatInput.inputElement.id="textmode-export-gif-repeat",this.status.mount(e),e}getOptions(){const e=this._config.defaultOptions??{};return{frameCount:this.safeParseInt(this.frameCountInput.value,e.frameCount??300),frameRate:this.safeParseInt(this.frameRateInput.value,e.frameRate??60),scale:this.safeParseFloat(this.scaleInput.value,e.scale??1),repeat:this.safeParseInt(this.repeatInput.value,e.repeat??0)}}reset(){this.recordingState="idle",this.applyDefaults(),this.setRecordingState("idle")}validate(){const e=Number.parseInt(this.frameCountInput.value,10),t=Number.parseInt(this.frameRateInput.value,10),a=Number.parseFloat(this.scaleInput.value);return Number.isFinite(e)&&e>0&&Number.isFinite(t)&&t>0&&Number.isFinite(a)&&a>0}isRecording(){return this.recordingState==="recording"||this.recordingState==="encoding"}setRecordingState(e,t){this.recordingState=e;const a=e==="recording"||e==="encoding";switch(this.frameCountInput.inputElement.disabled=a,this.frameRateInput.inputElement.disabled=a,this.scaleInput.inputElement.disabled=a,this.repeatInput.inputElement.disabled=a,e){case"recording":if(t!=null&&t.totalFrames){const o=t.frameIndex??0;this.status.setMessage(`recording ${o}/${t.totalFrames}`,"active")}else this.status.setMessage("recording…","active");break;case"encoding":if(t!=null&&t.totalFrames){const o=t.frameIndex??0;this.status.setMessage(`encoding ${o}/${t.totalFrames}`,"active")}else this.status.setMessage("encoding…","active");break;case"completed":this.status.setMessage("GIF saved successfully","active");break;case"error":this.status.setMessage((t==null?void 0:t.message)??"failed to export GIF","alert");break;default:this.status.setMessage("ready to record","neutral")}}handleProgress(e){if(e.state!=="recording"&&e.state!=="encoding"||!e.totalFrames)e.state==="completed"?this.status.setMessage("GIF saved successfully","active"):e.state==="error"&&this.status.setMessage(e.message??"failed to export GIF","alert");else{const t=e.state==="recording"?"recording":"encoding";this.status.setMessage(`${t} ${e.frameIndex??0}/${e.totalFrames}`,"active")}}applyDefaults(){const e=this._config.defaultOptions??{},t=e.frameCount??dt,a=e.frameRate??ct,o=e.scale??ut,n=e.repeat??cr;this.frameCountInput.value=String(t),this.frameRateInput.value=String(a),this.scaleInput.value=String(o),this.repeatInput.value=String(n),this.frameCountInput.refresh(),this.frameRateInput.refresh(),this.scaleInput.refresh(),this.repeatInput.refresh()}safeParseInt(e,t){const a=Number.parseInt(e,10);return Number.isFinite(a)?a:t}safeParseFloat(e,t){const a=Number.parseFloat(e);return Number.isFinite(a)?a:t}}const se="textmode-export-range-input",ur=`${se}__field`,pr=`${se}__tooltip`,ye=`${se}__tooltip--visible`,le=(l,r)=>{if(typeof l!="string"||l.length===0)return r;const e=Number.parseFloat(l);return Number.isFinite(e)?e:r};class hr extends W{constructor(e){super();p(this,"props");p(this,"input");p(this,"tooltip");p(this,"hoverActive",!1);p(this,"focusActive",!1);p(this,"pointerActive",!1);p(this,"suppressFocusFromPointer",!1);p(this,"activePointerId");p(this,"disabledObserver");p(this,"resizeObserver");this.props=e}render(){const e=document.createElement("div");return e.className=se,this.input=document.createElement("input"),this.input.type="range",this.input.value=this.props.defaultValue,Object.assign(this.input,this.props.attributes),this.input.className=ur,this.tooltip=document.createElement("div"),this.tooltip.className=pr,e.appendChild(this.input),e.appendChild(this.tooltip),this.bindEvents(e),this.updateTooltip(),this.syncDisabledState(e),e}get inputElement(){return this.input}get value(){return this.input.value}set value(e){this.input.value=e,this.updateTooltip()}_onDestroy(){var e,t;(e=this.disabledObserver)==null||e.disconnect(),(t=this.resizeObserver)==null||t.disconnect()}bindEvents(e){this.input.addEventListener("pointerenter",()=>{this.hoverActive=!0,this.refreshTooltipVisibility()}),this.input.addEventListener("pointerleave",()=>{this.hoverActive=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("focus",()=>{let a=!1;try{a=this.input.matches(":focus-visible")}catch{a=!this.suppressFocusFromPointer}this.suppressFocusFromPointer||!a||this.input.disabled?this.focusActive=!1:this.focusActive=!0,this.suppressFocusFromPointer=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("blur",()=>{this.focusActive=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("pointerdown",a=>{this.pointerActive=!0,this.suppressFocusFromPointer=!0,this.hoverActive=!0,this.refreshTooltipVisibility();try{this.input.setPointerCapture(a.pointerId),this.activePointerId=a.pointerId}catch{this.activePointerId=void 0}});const t=()=>{this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.hoverActive=this.input.matches(":hover"),this.releasePointerCapture(),this.refreshTooltipVisibility()};this.input.addEventListener("pointerup",t),this.input.addEventListener("pointercancel",t),this.input.addEventListener("lostpointercapture",t),this.input.addEventListener("input",()=>{(this.hoverActive||this.focusActive||this.pointerActive)&&this.updateTooltip(),this.props.defaultValue=this.input.value}),this.input.addEventListener("change",()=>{this.pointerActive||this.updateTooltip(),this.props.defaultValue=this.input.value}),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(()=>{this.tooltip.classList.contains(ye)&&this.updateTooltipPosition()}),this.resizeObserver.observe(e))}refreshTooltipVisibility(){const e=(this.hoverActive||this.focusActive||this.pointerActive)&&!this.input.disabled;e&&this.updateTooltip(),this.tooltip.classList.toggle(ye,e)}syncDisabledState(e){const t=()=>{const a=this.input.disabled;e.classList.toggle("is-disabled",a),a&&(this.hoverActive=!1,this.focusActive=!1,this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.releasePointerCapture(),this.tooltip.classList.remove(ye))};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(t),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),t()}releasePointerCapture(){if(this.activePointerId!==void 0){try{this.input.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}}updateTooltip(){this.updateTooltipContent(),this.updateTooltipPosition()}updateTooltipContent(){const e=this.props.formatValue??(a=>`${a}`),t=this.getCurrentValue();this.tooltip.textContent=e(t,this.input)}updateTooltipPosition(){const e=this.getMin(),t=this.getMax(),a=((d,s,h)=>Math.min(h,Math.max(s,d)))(this.getCurrentValue(),e,t),o=t-e,n=o===0?0:(a-e)/o;this.tooltip.style.left=100*n+"%"}getMin(){return le(this.input.min,0)}getMax(){return le(this.input.max,100)}getCurrentValue(){return le(this.input.value,le(this.props.defaultValue,0))}}function mr(l){return`${(function(e){if(!Number.isFinite(e))return"default quality";const t=Math.max(0,Math.min(1,e));return t>=.995?"near-lossless":t>=.98?"maximum detail":t>=.88?"ultra quality":t>=.7?"high quality":t>=.5?"balanced":t>=.25?"compact":t>=.1?"lightweight":"draft"})(l)} (quality ≈ ${l.toFixed(3)})`}class we extends Y{constructor(e){super(e);p(this,"frameRateInput",this._manageComponent(new X({defaultValue:String(60),attributes:{min:String(1),max:String(60),step:"1"},formatDisplay:e=>Number.isFinite(e)?`${e} fps`:null})));p(this,"frameCountInput",this._manageComponent(new X({defaultValue:String(480),attributes:{min:String(1),max:String(3600),step:"1"}})));p(this,"qualityInput",this._manageComponent(new hr({defaultValue:String(.7),attributes:{min:String(0),max:String(1),step:"0.001"},formatValue:e=>mr(e)})));p(this,"status",this._manageComponent(new lt({title:"status",message:"ready to record",variant:"neutral",context:"video"})));p(this,"recordingState","idle")}render(){const e=document.createElement("div");e.classList.add(H);const t=new ee("row");t.mount(e);const a=new z({label:"number of frames",labelFor:"textmode-export-video-frame-count",variant:"compact"});a.mount(t.root),this.frameCountInput.mount(a.root),this.frameCountInput.inputElement.id="textmode-export-video-frame-count";const o=new z({label:"frame rate (fps)",labelFor:"textmode-export-video-frame-rate",variant:"compact"});o.mount(t.root),this.frameRateInput.mount(o.root),this.frameRateInput.inputElement.id="textmode-export-video-frame-rate";const n=new z({label:"quality",labelFor:"textmode-export-video-quality",variant:"full"});return n.mount(e),this.qualityInput.mount(n.root),this.qualityInput.inputElement.id="textmode-export-video-quality",this.status.mount(e),e}getOptions(){const e=this._config.defaultOptions??{},t=Number.parseInt(this.frameCountInput.value,10),a=Number.parseFloat(this.frameRateInput.value),o=Number.parseFloat(this.qualityInput.value);return{frameCount:Number.isFinite(t)?t:e.frameCount??480,frameRate:Number.isFinite(a)?a:e.frameRate??60,quality:Number.isFinite(o)?o:e.quality??.7}}reset(){this.recordingState="idle",this.applyDefaults(),this.status.setMessage("ready to record","neutral")}validate(){const e=Number.parseInt(this.frameCountInput.value,10),t=Number.parseFloat(this.frameRateInput.value);return Number.isFinite(e)&&e>=1&&Number.isFinite(t)&&t>=1}isRecording(){return this.recordingState==="recording"}setRecordingState(e,t){this.recordingState=e;const a=e==="recording";this.frameCountInput.inputElement.disabled=a,this.frameRateInput.inputElement.disabled=a,this.qualityInput.inputElement.disabled=a,this.syncStatus(e,t)}handleProgress(e){this.syncStatus(e.state,e)}syncStatus(e,t){switch(e){case"recording":{const a=(t==null?void 0:t.frameIndex)??0,o=(t==null?void 0:t.totalFrames)??this.resolvePlannedFrameCount();if(o){const n=Math.min(Math.max(0,Math.round(a)),o);this.status.setMessage(`recording ${n}/${o} frames`,"active")}else this.status.setMessage(`recording ${Math.max(0,Math.round(a))} frames`,"active");break}case"completed":this.status.setMessage("saved to disk","active");break;case"error":this.status.setMessage(t!=null&&t.message?`error: ${t.message}`:"recording failed","alert");break;default:this.status.setMessage("ready to record","neutral")}}resolvePlannedFrameCount(){const e=Number.parseInt(this.frameCountInput.value,10);return Number.isFinite(e)&&e>0?Math.round(e):void 0}applyDefaults(){const e=this._config.defaultOptions??{},t=e.frameCount??480,a=e.frameRate??60,o=e.quality??.7;this.frameCountInput.value=String(t),this.frameRateInput.value=String(a),this.qualityInput.value=String(o),this.frameCountInput.refresh(),this.frameRateInput.refresh()}}class fr{constructor(r,e,t,a,o){p(this,"_textmodifier");p(this,"_state");p(this,"_events");p(this,"_exportService");p(this,"_clipboardService");p(this,"_definitions");p(this,"_formats",new Map);p(this,"_eventUnsubscribers",[]);p(this,"_shadowHost");p(this,"_shadowRoot");p(this,"_overlayElement");p(this,"_optionsContainer");p(this,"_copyButtonContainer");p(this,"_positionService");p(this,"_header",new ve);p(this,"_formatField",new z({label:"export format",labelFor:"textmode-export-format",variant:"full"}));p(this,"_formatSelect",new ie({id:"textmode-export-format",options:[]}));p(this,"_exportButton",new ot({label:"download file",fullWidth:!0,variant:"primary"}));p(this,"_copyButton",new ot({label:"copy to clipboard",fullWidth:!0,variant:"primary"}));p(this,"_currentFormat");p(this,"_currentBlade");p(this,"_handleFormatSelectChange",()=>{this._handleFormatChange(this._formatSelect.value)});p(this,"_handleExportClickSafe",()=>{this._handleExportClick().catch(r=>{console.error("[textmode-export] Export failed",r)})});p(this,"_handleCopyClickSafe",()=>{this._handleCopyClick().catch(r=>{console.error("[textmode-export] Copy failed",r)})});this._textmodifier=r,this._state=t,this._events=a,this._exportService=new ir(e,a),this._clipboardService=new or(e),this._definitions=o,this._currentFormat=t.snapshot.format,this._initializeFormatMap(),this._registerEventHandlers()}$mount(){this._createOverlay(),this._renderStaticContent(),this._positionService=new nr(this._textmodifier,this._shadowHost),this._positionService.bind(),this._switchFormat(this._currentFormat)}show(){this._shadowHost&&(this._shadowHost.style.display="")}hide(){this._shadowHost&&(this._shadowHost.style.display="none")}toggle(){this.isVisible()?this.hide():this.show()}isVisible(){return!!this._shadowHost&&this._shadowHost.style.display!=="none"}$dispose(){var r,e;this._formatSelect.isMounted()&&this._formatSelect.selectElement.removeEventListener("change",this._handleFormatSelectChange),this._exportButton.isMounted()&&this._exportButton.buttonElement.removeEventListener("click",this._handleExportClickSafe),this._copyButton.isMounted()&&this._copyButton.buttonElement.removeEventListener("click",this._handleCopyClickSafe);for(const t of this._eventUnsubscribers)t();this._eventUnsubscribers.length=0,this._events.$clear();for(const t of this._formats.values())t.blade.destroy();this._formats.clear(),this._currentBlade=void 0,(r=this._shadowHost)!=null&&r.isConnected&&this._shadowHost.remove(),(e=this._positionService)==null||e.dispose()}_initializeFormatMap(){for(const r of this._definitions){const e=r.createBlade();this._formats.set(r.format,{definition:r,blade:e,initialized:!1})}}_createOverlay(){this._shadowHost=document.createElement("div"),this._shadowHost.dataset.plugin="textmode-export-overlay-host",this._shadowHost.style.cssText="position: absolute; top: 0; left: 0; pointer-events: none; z-index: 2147483647;",this._shadowRoot=this._shadowHost.attachShadow({mode:"open"});const r=document.createElement("style");r.textContent=`@layer textmode-export-overlay{.textmode-export-overlay{--overlay-bg: rgba(20, 20, 20, .8);--overlay-surface: rgba(40, 40, 40, .9);--overlay-border: rgba(255, 255, 255, .14);--overlay-border-strong: rgba(255, 255, 255, .2);--overlay-border-focus: rgba(160, 160, 160, .6);--overlay-focus-shadow: 0 0 0 1px rgba(140, 140, 140, .28);--overlay-text: #ffffff;--overlay-muted: rgba(200, 200, 200, .74);--overlay-radius: .75rem;--overlay-stack-gap: .55rem;position:absolute;top:0;left:0;display:flex;flex-direction:column;gap:var(--overlay-stack-gap);min-width:236px;max-width:236px;padding:.65rem .8rem;background:var(--overlay-bg);color:var(--overlay-text);border-radius:var(--overlay-radius);border:1px solid var(--overlay-border);box-shadow:0 12px 28px #0000004d;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:.82rem;line-height:1.35;pointer-events:auto;z-index:2147483647}.textmode-export-overlay *{box-sizing:border-box}.textmode-export-overlay__header{display:flex;flex-direction:column;gap:.4rem}.textmode-export-overlay__header-title-row{display:flex;align-items:center;justify-content:space-between;gap:.4rem}.textmode-export-overlay__header-links{display:inline-flex;align-items:center;gap:.3rem}.textmode-export-overlay__support-link{display:inline-flex;align-items:center;justify-content:center;padding:.2rem;border-radius:.45rem;border:1px solid transparent;color:#d7d7d7d1;background:transparent;text-decoration:none;line-height:0;transition:background .18s ease,color .18s ease,transform .18s ease,border-color .18s ease}.textmode-export-overlay__support-link:hover{color:#fff;background:#5a5a5a4d;border-color:#c8c8c824}.textmode-export-overlay__support-link:focus-visible{outline:none;border-color:var(--overlay-border-focus);box-shadow:var(--overlay-focus-shadow)}.textmode-export-overlay__support-icon,.textmode-export-overlay__link-icon{display:block;width:1rem;height:1rem}.textmode-export-overlay__stack{display:flex;flex-direction:column;gap:var(--overlay-stack-gap)}.textmode-export-overlay__stack--dense{gap:.3rem}.textmode-export-overlay__stack--compact{gap:.45rem}.textmode-export-overlay__section{display:flex;flex-direction:column;gap:.4rem}.textmode-export-overlay__title{font-size:.92rem;font-weight:600}.textmode-export-overlay__divider{width:100%;height:1px;background:#ffffff29;margin-top:.25rem}.textmode-export-overlay__label{font-weight:500;opacity:.9}.textmode-export-overlay__checkbox{display:flex;align-items:center;gap:.5rem}.textmode-export-overlay__checkbox input[type=checkbox]{width:1rem;height:1rem;accent-color:rgba(100,100,100,.9)}.textmode-export-overlay__row{display:flex;gap:.6rem;flex-wrap:wrap;align-items:flex-start;width:100%}.textmode-export-overlay__field{display:flex;flex-direction:column;gap:.3rem;flex:1 1 120px;min-width:120px}.textmode-export-overlay__field--compact{flex:1 1 100px;min-width:100px}.textmode-export-overlay__field--dense{flex:1 1 90px;min-width:90px}.textmode-export-overlay__field--channel{flex:1 1 0;min-width:0}.textmode-export-overlay__field--full{width:100%;flex:1 1 100%}.textmode-export-overlay__input,.textmode-export-overlay select.textmode-export-overlay__input,.textmode-export-overlay input.textmode-export-overlay__input{width:100%;padding:.35rem .5rem;border-radius:.4rem;border:1px solid var(--overlay-border-strong);background:var(--overlay-surface);color:var(--overlay-text);font:inherit;line-height:1.35;transition:border-color .18s ease,box-shadow .18s ease,background .18s ease}.textmode-export-overlay select.textmode-export-overlay__input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgba(200, 200, 200, 0.74)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .5rem center;background-size:1rem;padding-right:2rem}.textmode-export-overlay__input:focus{outline:none;border-color:var(--overlay-border-focus);box-shadow:var(--overlay-focus-shadow);background:#2d2f42eb}.textmode-export-overlay__input::placeholder{color:var(--overlay-muted);opacity:.7}.textmode-export-overlay__muted{font-size:.75rem;opacity:.7;display:block}.textmode-export-overlay__button{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;border-radius:.45rem;border:none;font-weight:600;padding:.45rem .7rem;cursor:pointer;transition:background .2s ease,transform .2s ease,box-shadow .2s ease}.textmode-export-overlay__button--primary{background:#505050;color:#fff}.textmode-export-overlay__button--secondary{background:#606060;color:#fff}.textmode-export-overlay__button--full{width:100%}.textmode-export-overlay__button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 7px 18px #00000073}.textmode-export-overlay__button--primary:hover:not(:disabled){background:#404040}.textmode-export-overlay__button--secondary:hover:not(:disabled){background:#4a4a4a}.textmode-export-overlay__button:disabled{cursor:default;opacity:.55;transform:none;box-shadow:none}.textmode-export-overlay__status{display:flex;flex-direction:column;gap:.25rem;padding:.45rem .55rem;border-radius:.45rem;border:1px solid rgba(110,110,110,.22);background:#4646462e}.textmode-export-overlay__status--gif{background:#5050501f;border-color:#78787840}.textmode-export-overlay__status--video{background:#4646461f;border-color:#6e6e6e40}.textmode-export-overlay__status-title{font-weight:600;font-size:.75rem;opacity:.85;text-transform:uppercase;letter-spacing:.04em}.textmode-export-overlay__status-value{font-size:.82rem;color:#dedede;transition:color .18s ease}.textmode-export-overlay__status-value--neutral{color:#cfcfcf}.textmode-export-overlay__status-value--active{color:#f5f5f5}.textmode-export-overlay__status-value--alert{color:#b8b8b8}.textmode-export-number-input,.textmode-export-overlay .textmode-export-number-input{display:flex;align-items:stretch;width:100%;background:var(--overlay-surface);border:1px solid var(--overlay-border-strong);border-radius:.4rem;overflow:hidden;transition:border-color .18s ease,box-shadow .18s ease,background .18s ease;position:relative}.textmode-export-number-input:focus-within{border-color:var(--overlay-border-focus);box-shadow:var(--overlay-focus-shadow)}.textmode-export-number-input.is-disabled{opacity:.55}.textmode-export-number-input__field{flex:1 1 auto;min-width:0;border:none;background:transparent;color:var(--overlay-text);font:inherit;padding:.35rem .5rem;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.textmode-export-number-input__field::-webkit-outer-spin-button,.textmode-export-number-input__field::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.textmode-export-number-input__field:focus{outline:none}.textmode-export-number-input__controls{display:flex;flex-direction:column;border-left:1px solid rgba(255,255,255,.12);min-width:1.6rem}.textmode-export-number-input__control{display:flex;align-items:center;justify-content:center;width:100%;flex:1;border:none;background:#32323299;color:#d0d0d0;font-size:.68rem;line-height:1;cursor:pointer;transition:background .15s ease,color .15s ease;padding:0}.textmode-export-number-input__control:hover:not(:disabled){background:#5a5a5ad9;color:#fff}.textmode-export-number-input__control:disabled{cursor:default;opacity:.4;background:#28282880;color:#c8c8c866}.textmode-export-number-input:focus-within .textmode-export-number-input__control{background:#3c3c3cbf;color:#e8e8e8}.textmode-export-number-input__display{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;padding:.4rem .55rem;pointer-events:none;color:#f8fafc;opacity:0;transition:opacity .14s ease}.textmode-export-number-input__display--visible{opacity:1}.textmode-export-range-input{position:relative;width:100%}.textmode-export-range-input.is-disabled{opacity:.55}.textmode-export-range-input__field{width:100%;height:1.4rem;padding:0;margin:0;background:transparent;cursor:pointer;-moz-appearance:none;appearance:none;-webkit-appearance:none}.textmode-export-range-input__field::-webkit-slider-thumb{width:12px;height:12px;margin-top:-3.5px;-webkit-appearance:none;border-radius:50%;background:#a0a0a0;border:2px solid #303030;box-shadow:0 0 0 2px #00000059}.textmode-export-range-input__field::-webkit-slider-runnable-track{height:5px;border-radius:999px;background:linear-gradient(90deg,#8c8c8cd9,#646464a6)}.textmode-export-range-input__field::-moz-range-thumb{width:12px;height:12px;border-radius:50%;background:#a0a0a0;border:2px solid #303030;margin-top:-3.5px}.textmode-export-range-input__field::-moz-range-track{height:5px;border-radius:999px;background:linear-gradient(90deg,#8c8c8cd9,#646464a6)}.textmode-export-range-input__tooltip{position:absolute;top:-1.5rem;left:0;transform:translate(-50%);padding:.2rem .35rem;border-radius:.35rem;background:#1e1e1ee0;color:#f8fafc;font-size:.68rem;line-height:1;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.textmode-export-range-input__tooltip--visible{opacity:1}}`,this._shadowRoot.appendChild(r),this._overlayElement=document.createElement("div"),this._overlayElement.dataset.plugin="textmode-export-overlay",this._overlayElement.classList.add(Rt,H),this._shadowRoot.appendChild(this._overlayElement),document.body.appendChild(this._shadowHost)}_renderStaticContent(){this._header.mount(this._overlayElement);const r=document.createElement("div");r.classList.add(Je),this._overlayElement.appendChild(r),this._formatField.mount(r),this._prepareFormatOptions(),this._formatSelect.mount(this._formatField.root),this._formatSelect.selectElement.addEventListener("change",this._handleFormatSelectChange),this._optionsContainer=document.createElement("div"),this._optionsContainer.classList.add(H,qe),this._overlayElement.appendChild(this._optionsContainer),this._exportButton.mount(this._overlayElement),this._exportButton.buttonElement.addEventListener("click",this._handleExportClickSafe),this._copyButtonContainer=document.createElement("div"),this._copyButtonContainer.classList.add(H,fe),this._overlayElement.appendChild(this._copyButtonContainer),this._copyButton.mount(this._copyButtonContainer),this._copyButton.buttonElement.dataset.defaultLabel="copy to clipboard",this._copyButton.buttonElement.addEventListener("click",this._handleCopyClickSafe)}_prepareFormatOptions(){const r=this._definitions.map(e=>({value:e.format,label:e.label}));this._formatSelect.update({options:r,defaultValue:this._currentFormat})}_registerEventHandlers(){this._eventUnsubscribers.push(this._events.$on("export:request",({format:r})=>{r===this._currentFormat&&(this._state.$set({isBusy:!0,error:void 0}),this._updateExportButton())}),this._events.$on("export:success",({format:r})=>{if(r===this._currentFormat){const e={isBusy:!1};r==="gif"&&(e.gifProgress=void 0),r==="video"&&(e.videoProgress=void 0),this._state.$set(e),this._updateExportButton()}}),this._events.$on("export:error",({format:r,error:e})=>{r===this._currentFormat&&(this._state.$set({isBusy:!1,error:e}),this._updateExportButton())}),this._events.$on("export:progress",({format:r,progress:e})=>{var t,a;if(e){if(r==="gif"&&((t=this._currentBlade)==null?void 0:t.blade)instanceof xe){const o=e;this._state.$set({gifProgress:o}),this._currentBlade.blade.handleProgress(o)}else if(r==="video"&&((a=this._currentBlade)==null?void 0:a.blade)instanceof we){const o=e;this._state.$set({videoProgress:o}),this._currentBlade.blade.handleProgress(o)}this._updateExportButton()}}))}_handleFormatChange(r){this._currentFormat=r,this._state.$set({format:r}),this._switchFormat(r),this._events.$emit("format:change",{format:r})}_switchFormat(r){var t;const e=this._formats.get(r);if(!e)throw new Error(`Unknown export format: ${r}`);this._currentBlade&&this._currentBlade.blade.unmount(),this._optionsContainer.innerHTML="",e.blade.mount(this._optionsContainer),e.initialized||(e.blade.reset(),e.initialized=!0),this._currentBlade=e,this._formatSelect.value=r,this._updateCopyButtonState(),this._updateExportButton(),(t=this._positionService)==null||t.scheduleUpdate()}_updateCopyButtonState(){var e;const r=((e=this._currentBlade)==null?void 0:e.definition.supportsClipboard)??!1;this._copyButtonContainer.style.display=r?"flex":"none",this._copyButton.setDisabled(!r)}async _handleExportClick(){if(!this._currentBlade)return;const r=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions();if(this._currentBlade.blade.validate()){if(r==="gif"){const t=this._currentBlade.blade;if(t.isRecording())return;t.setRecordingState("recording");try{await this._exportService.$requestExport("gif",e,{onGIFProgress:a=>{t.setRecordingState(a.state,a)}})}catch(a){throw t.setRecordingState("error"),a}return void window.setTimeout(()=>{t.setRecordingState("idle"),this._updateExportButton()},1600)}if(r==="video"){const t=this._currentBlade.blade;if(t.isRecording())return;t.setRecordingState("recording");try{await this._exportService.$requestExport("video",e,{onVideoProgress:a=>{t.setRecordingState(a.state,a)}})}catch(a){throw t.setRecordingState("error"),a}return void window.setTimeout(()=>{t.setRecordingState("idle"),this._updateExportButton()},1600)}this._exportButton.setDisabled(!0),this._exportButton.setLabel("exporting…");try{await this._exportService.$requestExport(r,e)}finally{this._exportButton.setDisabled(!1),this._exportButton.setLabel("download file")}}else console.warn("[textmode-export] Export options failed validation")}async _handleCopyClick(){if(!this._currentBlade||!this._currentBlade.definition.supportsClipboard)return;const r=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions(),t=this._copyButton.buttonElement.dataset.defaultLabel??"copy to clipboard";this._copyButton.setDisabled(!0),this._copyButton.setLabel("copying…");try{switch(r){case"txt":await this._clipboardService.$copy("txt",e);break;case"json":await this._clipboardService.$copy("json",e);break;case"svg":await this._clipboardService.$copy("svg",e);break;case"image":await this._clipboardService.$copy("image",e);break;default:return}this._copyButton.setLabel("copied!")}catch(a){console.error("[textmode-export] Failed to copy to clipboard",a),this._copyButton.setLabel("copy failed!")}finally{window.setTimeout(()=>{this._copyButton.setLabel(t),this._copyButton.setDisabled(!1)},1200)}}_updateExportButton(){if(!this._currentBlade)return;const r=this._currentBlade.definition.format;if(r==="gif"&&this._currentBlade.blade instanceof xe){const t=this._currentBlade.blade,a=this._state.snapshot.gifProgress;if(t.isRecording())if(this._exportButton.setDisabled(!0),a==null?void 0:a.totalFrames){const o=a.frameIndex??0,n=a.state==="encoding"?"encoding":"recording";this._exportButton.setLabel(`${n} ${o}/${a.totalFrames}`)}else{const o=(a==null?void 0:a.state)==="encoding"?"encoding":"recording";this._exportButton.setLabel(`${o}…`)}else this._exportButton.setDisabled(!1),this._exportButton.setLabel("start recording");return}if(r==="video"&&this._currentBlade.blade instanceof we){const t=this._currentBlade.blade,a=this._state.snapshot.videoProgress;if(t.isRecording())if(this._exportButton.setDisabled(!0),a==null?void 0:a.totalFrames){const o=a.frameIndex??0;this._exportButton.setLabel(`recording ${o}/${a.totalFrames} frames`)}else this._exportButton.setLabel("recording…");else this._exportButton.setDisabled(!1),this._exportButton.setLabel("start recording");return}const e=this._state.snapshot.isBusy;this._exportButton.setDisabled(e),this._exportButton.setLabel(e?"exporting…":"download file")}}class gr{constructor(){p(this,"_listeners",{})}_getPool(r){const e=this._listeners[r];if(e)return e;const t=new Set;return this._listeners[r]=t,t}$on(r,e){const t=this._getPool(r);return t.add(e),()=>{t.delete(e),t.size===0&&delete this._listeners[r]}}$emit(r,e){const t=this._listeners[r];if(t)for(const a of[...t])try{a(e)}catch(o){console.error("[textmode-export] Event handler failed",o)}}$clear(){for(const r of Object.keys(this._listeners))delete this._listeners[r]}}class br{constructor(r){p(this,"_state");p(this,"_listeners",new Set);this._state=r}get snapshot(){return Object.freeze({...this._state})}$set(r){this._state=Object.assign({},this._state,r);const e=this.snapshot;for(const t of[...this._listeners])try{t(e)}catch(a){console.error("[textmode-export] State listener failed",a)}}$subscribe(r){return this._listeners.add(r),r(this.snapshot),()=>{this._listeners.delete(r)}}$reset(r){this._state=r;const e=this.snapshot;for(const t of[...this._listeners])t(e)}}class de extends W{constructor(e){super();p(this,"props");p(this,"checkbox");p(this,"labelElement");p(this,"handleChange",()=>{this.props.defaultChecked=this.checkbox.checked});this.props=e}render(){this.labelElement=document.createElement("label"),this.labelElement.classList.add(Wt),this.checkbox=document.createElement("input"),this.checkbox.type="checkbox",this.props.id&&(this.checkbox.id=this.props.id),this.checkbox.checked=!!this.props.defaultChecked,this.checkbox.addEventListener("change",this.handleChange);const e=document.createElement("span");return e.textContent=this.props.label,this.labelElement.htmlFor=this.props.id??"",this.labelElement.appendChild(this.checkbox),this.labelElement.appendChild(e),this.labelElement}get inputElement(){return this.checkbox}get checked(){return this.checkbox.checked}set checked(e){this.checkbox.checked=e}_onUnmount(){this.checkbox.removeEventListener("change",this.handleChange)}onUpdate(e){this.props=e,e.id&&(this.checkbox.id=e.id,this.labelElement.htmlFor=e.id),this.checkbox.checked=!!e.defaultChecked,this.labelElement.lastElementChild&&(this.labelElement.lastElementChild.textContent=e.label)}}class vr extends W{constructor(e){super();p(this,"props");p(this,"input");p(this,"handleInput",()=>{this.props.defaultValue=this.input.value});this.props=e}render(){return this.input=document.createElement("input"),this.input.type="text",this.input.classList.add(tt),this.props.id&&(this.input.id=this.props.id),this.props.maxLength!==void 0&&(this.input.maxLength=this.props.maxLength),this.props.defaultValue!==void 0&&(this.input.value=this.props.defaultValue),this.input.addEventListener("input",this.handleInput),this.input}get inputElement(){return this.input}get value(){return this.input.value}set value(e){this.input.value=e}_onUnmount(){this.input.removeEventListener("input",this.handleInput)}onUpdate(e){this.props=e,e.id&&(this.input.id=e.id),e.maxLength!==void 0&&(this.input.maxLength=e.maxLength),e.defaultValue!==void 0&&(this.input.value=e.defaultValue)}}class xr extends Y{constructor(e){super(e);p(this,"trailingSpaces",this._manageComponent(new de({label:"preserve trailing spaces",defaultChecked:!1})));p(this,"emptyCharacter",this._manageComponent(new vr({id:"textmode-export-empty-character",defaultValue:" ",maxLength:1})))}render(){const e=document.createElement("div");e.classList.add(H),this.trailingSpaces.mount(e);const t=new z({label:"empty character",labelFor:"textmode-export-empty-character",variant:"full"});return t.mount(e),this.emptyCharacter.mount(t.root),e}getOptions(){const e=this._config.defaultOptions??{},t=this.emptyCharacter.value||e.emptyCharacter||" ";return{preserveTrailingSpaces:this.trailingSpaces.checked,emptyCharacter:t}}reset(){this.applyDefaults()}validate(){return this.emptyCharacter.value.length<=1}applyDefaults(){const e=this._config.defaultOptions??{};this.trailingSpaces.checked=e.preserveTrailingSpaces??!1,this.emptyCharacter.value=e.emptyCharacter??" "}}class yr extends Y{constructor(e){super(e);p(this,"prettyPrint",this._manageComponent(new de({id:"textmode-export-json-pretty",label:"pretty print",defaultChecked:!0})));p(this,"includeMetadata",this._manageComponent(new de({id:"textmode-export-json-metadata",label:"include metadata",defaultChecked:!0})));p(this,"colorMode",this._manageComponent(new ie({id:"textmode-export-json-color-mode",options:[{value:"hex",label:"hex"},{value:"rgba",label:"rgba"}],defaultValue:"hex"})))}render(){const e=document.createElement("div");e.classList.add(H),this.prettyPrint.mount(e),this.includeMetadata.mount(e);const t=new z({label:"color mode",labelFor:"textmode-export-json-color-mode",variant:"full"});return t.mount(e),this.colorMode.mount(t.root),e}getOptions(){return{pretty:this.prettyPrint.checked,includeMetadata:this.includeMetadata.checked,colorMode:this.colorMode.value}}reset(){this.applyDefaults()}validate(){return!0}applyDefaults(){const e=this._config.defaultOptions??{};this.prettyPrint.checked=typeof e.pretty=="number"?e.pretty>0:e.pretty??!0,this.includeMetadata.checked=e.includeMetadata??!0,this.colorMode.value=e.colorMode??"hex"}}class wr extends Y{constructor(e){super(e);p(this,"formatSelect",this._manageComponent(new ie({id:"textmode-export-image-format",options:[{value:"png",label:`PNG (${bt})`},{value:"jpg",label:`JPG (${vt})`},{value:"webp",label:`WEBP (${xt})`}],defaultValue:"png"})));p(this,"scaleInput",this._manageComponent(new X({defaultValue:"1",attributes:{min:"0.1",step:"0.1"}})))}render(){const e=document.createElement("div");e.classList.add(H);const t=new ee("row");t.mount(e);const a=new z({label:"image format",labelFor:"textmode-export-image-format",variant:"compact"});a.mount(t.root),this.formatSelect.mount(a.root);const o=new z({label:"scale",labelFor:"textmode-export-image-scale",variant:"dense"});return o.mount(t.root),this.scaleInput.mount(o.root),this.scaleInput.inputElement.id="textmode-export-image-scale",e}getOptions(){var t;const e=Number.parseFloat(this.scaleInput.value);return{format:this.formatSelect.value,scale:Number.isFinite(e)?e:((t=this._config.defaultOptions)==null?void 0:t.scale)??1}}reset(){this.applyDefaults(),this.scaleInput.refresh()}validate(){const e=Number.parseFloat(this.scaleInput.value);return Number.isFinite(e)&&e>0}applyDefaults(){const e=this._config.defaultOptions??{};this.formatSelect.value=e.format??"png";const t=e.scale??1;this.scaleInput.value=String(t)}}class _r extends Y{constructor(e){super(e);p(this,"includeBackground",this._manageComponent(new de({id:"textmode-export-svg-include-backgrounds",label:"include cell backgrounds",defaultChecked:!0})));p(this,"drawMode",this._manageComponent(new ie({id:"textmode-export-svg-draw-mode",options:[{value:"fill",label:"fill"},{value:"stroke",label:"stroke"}],defaultValue:"fill"})));p(this,"strokeWidth",this._manageComponent(new X({defaultValue:"1",attributes:{min:"0",step:"0.1"}})))}render(){const e=document.createElement("div");e.classList.add(H),this.includeBackground.mount(e);const t=new ee("row");t.mount(e);const a=new z({label:"draw mode",labelFor:"textmode-export-svg-draw-mode",variant:"compact"});a.mount(t.root),this.drawMode.mount(a.root);const o=new z({label:"stroke width",labelFor:"textmode-export-svg-stroke-width",variant:"compact"});return o.mount(t.root),this.strokeWidth.mount(o.root),this.strokeWidth.inputElement.id="textmode-export-svg-stroke-width",this.drawMode.selectElement.addEventListener("change",()=>this.updateStrokeControls()),this.updateStrokeControls(),e}getOptions(){return{includeBackgroundRectangles:this.includeBackground.checked,drawMode:this.drawMode.value,strokeWidth:Number.parseFloat(this.strokeWidth.value)}}reset(){this.applyDefaults(),this.updateStrokeControls()}validate(){const e=Number.parseFloat(this.strokeWidth.value);return this.drawMode.value!=="stroke"||Number.isFinite(e)&&e>=0}updateStrokeControls(){const e=this.drawMode.value==="stroke";this.strokeWidth.inputElement.disabled=!e,this.strokeWidth.refresh()}applyDefaults(){const e=this._config.defaultOptions??{};this.includeBackground.checked=e.includeBackgroundRectangles??!0,this.drawMode.value=e.drawMode??"fill";const t=e.strokeWidth??1;this.strokeWidth.value=String(t),this.strokeWidth.refresh()}}const Cr=[{format:"txt",label:"plain text (.txt)",supportsClipboard:!0,createBlade:()=>new xr({format:"txt",label:"plain text (.txt)",supportsClipboard:!0,defaultOptions:{preserveTrailingSpaces:!1,emptyCharacter:" "}})},{format:"json",label:"layer data (.json)",supportsClipboard:!0,createBlade:()=>new yr({format:"json",label:"layer data (.json)",supportsClipboard:!0,defaultOptions:{pretty:!0,includeMetadata:!0,colorMode:"hex"}})},{format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,createBlade:()=>new wr({format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,defaultOptions:{format:"png",scale:1}})},{format:"svg",label:"vector (.svg)",supportsClipboard:!0,createBlade:()=>new _r({format:"svg",label:"vector (.svg)",supportsClipboard:!0,defaultOptions:{includeBackgroundRectangles:!0,drawMode:"fill",strokeWidth:1}})},{format:"gif",label:"animated GIF (.gif)",supportsClipboard:!1,createBlade:()=>new xe({format:"gif",label:"animated GIF (.gif)",supportsClipboard:!1,defaultOptions:{frameCount:300,frameRate:60,scale:1,repeat:0}})},{format:"video",label:"video (.webm)",supportsClipboard:!1,createBlade:()=>new we({format:"video",label:"video (.webm)",supportsClipboard:!1,defaultOptions:{frameCount:480,frameRate:60,quality:.7}})}];function kr(l,r){var d;const e=Cr,t=(d=e[0])==null?void 0:d.format,a=new br((s=>({format:s,isBusy:!1}))(t)),o=new gr,n=new fr(l,r,a,o,e);return n.$mount(),n}const _e={name:"textmode.export",version:We,async install(l,r){const e={saveCanvas:async(d={})=>new Ie().$saveImage(l.canvas,d),copyCanvas:async(d={})=>new Ie().$copyImageToClipboard(l.canvas,d),saveSVG:(d={})=>{new Be().$saveSVG(l,d)},saveStrings:(d={})=>{new Se().$saveTXT(l,d)},toSVG:(d={})=>new Be().$generateSVG(l,d),toString:(d={})=>new Se().$generateTXT(l,d),toJSON:(d={})=>new me().$generateJSONData(l,d),toJSONString:(d={})=>new me().$generateJSONString(l,d),saveJSON:(d={})=>{new me().$saveJSON(l,d)},saveGIF:async(d={})=>new Ft(l,r.registerPostDrawHook).$saveGIF(d),saveWEBM:async(d={})=>new Ut(l,r.registerPostDrawHook).$saveWEBM(d)},t=kr(l,e),a={show:()=>t.show(),hide:()=>t.hide(),toggle:()=>t.toggle(),isVisible:()=>t.isVisible()},o={...e,exportOverlay:a},n=l;Object.assign(n,o),n._exportOverlayController=t},async uninstall(l){const r=l,e=r._exportOverlayController;e==null||e.$dispose(),delete r._exportOverlayController;const t=["exportOverlay","saveCanvas","copyCanvas","saveSVG","saveStrings","toSVG","toString","toJSON","toJSONString","saveJSON","saveGIF","saveWEBM"];for(const a of t)delete r[a]}},pt=(l={})=>{const r=l.overlay??!0,e={..._e},t=e.install;return e.install=async(a,o)=>{var d;const n=a;await t.call(e,n,o),r||((d=n.exportOverlay)==null||d.hide())},e};typeof window<"u"&&(window.ExportPlugin=_e,window.createTextmodeExportPlugin=pt),G.ExportPlugin=_e,G.createTextmodeExportPlugin=pt,Object.defineProperty(G,Symbol.toStringTag,{value:"Module"})});
1
+ (function(j,z){typeof exports=="object"&&typeof module<"u"?z(exports):typeof define=="function"&&define.amd?define(["exports"],z):z((j=typeof globalThis<"u"?globalThis:j||self).TextmodeExport={})})(this,function(j){"use strict";var $r=Object.defineProperty;var Lr=(j,z,H)=>z in j?$r(j,z,{enumerable:!0,configurable:!0,writable:!0,value:H}):j[z]=H;var h=(j,z,H)=>Lr(j,typeof z!="symbol"?z+"":z,H);class z{$extractFramebufferData(r){return{characterPixels:r.readPixels(0),primaryColorPixels:r.readPixels(1),secondaryColorPixels:r.readPixels(2)}}$getEncodedCharacterValue(r,e){return r[e]+(r[e+1]<<8)}$getCharacterIndex(r,e){return this.$getEncodedCharacterValue(r,e)}$extractCellTransform(r,e){const t=r[e+2],a=r[e+3]/255;return{isInverted:!!(1&t),flipHorizontal:!!(2&t),flipVertical:!!(4&t),rotation:Math.round(360*a*100)/100}}}class H{$downloadFile(r,e){try{const t=this._sanitizeFilename(e),a=URL.createObjectURL(r),i=document.createElement("a");i.href=a,i.download=t,i.style.display="none",i.rel="noopener",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(a)}catch(t){console.error("[textmode-export] Failed to download file:",t)}}_sanitizeFilename(r){if(!r)return this._generateDefaultFilename();const e=r.trim();return e?e.replace(/[<>:"/\\|?*]/g,"_").replace(/\s+/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").substring(0,255)||this._generateDefaultFilename():this._generateDefaultFilename()}_generateDefaultFilename(){return`textmode-export-${new Date().toISOString().slice(0,19).replace(/:/g,"-")}`}}const Ie=new WeakMap;function yt(l){return Math.round(255*l[0])+(Math.round(255*l[1])<<8)}function ue(l,r){let e=Ie.get(l);if(!e){e=new Map;for(const t of l.characters)e.set(yt(t.color),t);Ie.set(l,e)}return e.get(r)}function Me(l,r){const e=l==="base"?"Base layer":`Layer ${Number.parseInt(l.replace("layer-",""),10)}`;return r._visible===!1?`${e} (hidden)`:e}function Se(l){return[{id:"base",layer:l.layers.base},...l.layers.all.map((r,e)=>({id:`layer-${e+1}`,layer:r}))].map(({id:r,layer:e})=>({id:r,label:Me(r,e),layer:e}))}function re(l,r){const e=r??l.layers.base,t=(function(d,s){if(s===d.layers.base)return"base";const p=d.layers.all.indexOf(s);if(p>=0)return`layer-${p+1}`;throw new Error("[textmode-export] Cannot export a layer that is not managed by this Textmodifier instance.")})(l,e),a=e.grid,i=e.font,n=e.drawFramebuffer;if(!a||!n)throw new Error("[textmode-export] Cannot export an uninitialized layer.");return{id:t,label:Me(t,e),layer:e,grid:a,font:i,drawFramebuffer:n}}function ae(l,r){return{r:l[r],g:l[r+1],b:l[r+2],a:l[r+3]}}class xt extends z{_calculateCellPosition(r,e,t){return{x:r,y:e,cellX:r*t.cellWidth,cellY:e*t.cellHeight}}$extractSVGCellData(r,e){const t=[];let a=0;for(let i=0;i<e.rows;i++)for(let n=0;n<e.cols;n++){const d=4*a,s=this.$getEncodedCharacterValue(r.characterPixels,d);let p=ae(r.primaryColorPixels,d),o=ae(r.secondaryColorPixels,d);const c=this.$extractCellTransform(r.characterPixels,d);if(c.isInverted){const f=p;p=o,o=f}const u=this._calculateCellPosition(n,i,e);t.push({encodedGlyphSlot:s,primaryColor:p,secondaryColor:o,transform:c,position:u}),a++}return t}}class wt{_createGlyphPath(r,e,t,a,i){const n=i/r.head.unitsPerEm;return{getBoundingBox:()=>({x1:t+e.xMin*n,y1:a+-e.yMax*n,x2:t+e.xMax*n,y2:a+-e.yMin*n}),toSVG:()=>this._glyphToSVGPath(e,t,a,n)}}_glyphToSVGPath(r,e,t,a){if(!r||!r.xs)return"";const{xs:i,ys:n,endPts:d,flags:s}=r;if(!(i&&n&&d&&s))return"";let p="",o=0;for(let c=0;c<d.length;c++){const u=d[c];if(!(u<o)){if(u>=o){const f=e+i[o]*a,x=t-n[o]*a;p+=`M${f.toFixed(2)},${x.toFixed(2)}`;let m=o+1;for(;m<=u;)if(1&s[m]){const v=e+i[m]*a,C=t-n[m]*a;p+=`L${v.toFixed(2)},${C.toFixed(2)}`,m++}else{const v=e+i[m]*a,C=t-n[m]*a,y=m+1>u?o:m+1;if(1&s[y]){const b=e+i[y]*a,B=t-n[y]*a;p+=`Q${v.toFixed(2)},${C.toFixed(2)} ${b.toFixed(2)},${B.toFixed(2)}`,m=y+1}else{const b=(v+(e+i[y]*a))/2,B=(C+(t-n[y]*a))/2;p+=`Q${v.toFixed(2)},${C.toFixed(2)} ${b.toFixed(2)},${B.toFixed(2)}`,m=y}}p+="Z"}o=u+1}}return p}$generatePositionedCharacterPath(r,e,t,a,i,n,d,s){if(!s)return null;const p=e.font,o=d/p.head.unitsPerEm,c=t+(i-s.advanceWidth*o)/2,u=a+p.hhea.ascender*o;return this._createGlyphPath(p,s,c,u,d).toSVG()||null}}class _t{constructor(){h(this,"_pathGenerator");this._pathGenerator=new wt}$generateSVGHeader(r){const{width:e,height:t}=r;return`<?xml version="1.0" encoding="UTF-8"?><svg width="${e}" height="${t}" viewBox="0 0 ${e} ${t}" xmlns="http://www.w3.org/2000/svg"><title>textmode.js sketch</title>`}$generateSVGFooter(){return"</g></svg>"}_generateTransformAttribute(r,e){const{transform:t,position:a}=r;if(!t.flipHorizontal&&!t.flipVertical&&!t.rotation)return"";const i=a.cellX+e.cellWidth/2,n=a.cellY+e.cellHeight/2,d=[];if(t.flipHorizontal||t.flipVertical){const s=t.flipHorizontal?-1:1,p=t.flipVertical?-1:1;d.push(`translate(${i} ${n})scale(${s} ${p})translate(${-i} ${-n})`)}return t.rotation&&d.push(`rotate(${t.rotation} ${i} ${n})`),` transform="${d.join(" ")}"`}_generateCellBackground(r,e,t){if(!t.includeBackgroundRectangles||r.secondaryColor.a===0)return"";const{position:a}=r,{r:i,g:n,b:d,a:s}=r.secondaryColor,p=`rgba(${i},${n},${d},${s/255})`;return t.drawMode==="stroke"?`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" stroke="${p}" fill="none" stroke-width="${t.strokeWidth}"/>`:`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" fill="${p}"/>`}_generateCharacterPath(r,e,t,a){const i=ue(t,r.encodedGlyphSlot);if(!i)return"";const n=this._pathGenerator.$generatePositionedCharacterPath(i.character,t,r.position.cellX,r.position.cellY,e.cellWidth,e.cellHeight,t.fontSize,i.glyphData);if(!n)return"";const{r:d,g:s,b:p,a:o}=r.primaryColor,c=`rgba(${d},${s},${p},${o/255})`;return a.drawMode==="stroke"?`<path d="${n}" stroke="${c}" stroke-width="${a.strokeWidth}" fill="none"/>`:`<path d="${n}" fill="${c}"/>`}$generateCellContent(r,e,t,a){const i=[],n=this._generateCellBackground(r,e,a);n&&i.push(n);const d=this._generateCharacterPath(r,e,t,a);if(d){const s=this._generateTransformAttribute(r,e);i.push(s?`<g${s}>${d}</g>`:d)}return i.join("")}$generateSVGContent(r,e,t,a){const i=[this.$generateSVGHeader(e),'<g id="ascii-cells">'];for(const n of r)i.push(this.$generateCellContent(n,e,t,a));return i.push(this.$generateSVGFooter()),i.join("")}$optimizeSVGContent(r){return r.replace(/\s+/g," ").replace(/> </g,"><")}}class Fe{_applyDefaultOptions(r){return{includeBackgroundRectangles:r.includeBackgroundRectangles??!0,drawMode:r.drawMode??"fill",strokeWidth:r.strokeWidth??1,filename:r.filename,layer:r.layer}}$generateSVG(r,e={}){const t=new xt,a=new _t,i=this._applyDefaultOptions(e),n=re(r,i.layer),d=t.$extractSVGCellData(t.$extractFramebufferData(n.drawFramebuffer),n.grid),s=a.$generateSVGContent(d,n.grid,n.font,i);return a.$optimizeSVGContent(s)}$saveSVG(r,e={}){new H().$downloadFile(new Blob([this.$generateSVG(r,e)],{type:"image/svg+xml;charset=utf-8"}),e.filename)}}const pe={png:"image/png",jpg:"image/jpeg",webp:"image/webp"},Ct=".png",Et=".jpg",kt=".webp";class $e{_applyDefaultOptions(r){return{format:r.format??"png",scale:Math.abs(r.scale??1),filename:r.filename}}_validateOptions(r){if(!(r.format in pe))throw new Error(`Saving '${r.format}' files is not supported`)}async $generateImageBlob(r,e){const t=r,a=document.createElement("canvas"),i=a.getContext("2d"),n=Math.round(t.width*e.scale),d=Math.round(t.height*e.scale);return a.width=n,a.height=d,i.imageSmoothingEnabled=!1,i.clearRect(0,0,n,d),i.drawImage(t,0,0,t.width,t.height,0,0,n,d),await new Promise((s,p)=>{a.toBlob(o=>{o?s(o):p(new Error(`Failed to generate ${e.format.toUpperCase()} blob`))},pe[e.format])})}async $saveImage(r,e={}){const t=this._applyDefaultOptions(e);this._validateOptions(t);const a=await this.$generateImageBlob(r,t);new H().$downloadFile(a,t.filename)}async $copyImageToClipboard(r,e={}){if(typeof navigator>"u"||!navigator.clipboard||typeof navigator.clipboard.write!="function")throw new Error("Clipboard API is not available in this environment");const t=this._applyDefaultOptions(e);this._validateOptions(t);const a=await this.$generateImageBlob(r,t),i=new ClipboardItem({[pe[t.format]]:a});await navigator.clipboard.write([i])}}class Le{_applyDefaultOptions(r){return{preserveTrailingSpaces:r.preserveTrailingSpaces??!1,emptyCharacter:r.emptyCharacter??" ",filename:r.filename,layer:r.layer}}_createTXTContent(r,e){var s;const t=new z,a=re(r,e.layer),i=t.$extractFramebufferData(a.drawFramebuffer),n=[];let d=0;for(let p=0;p<a.grid.rows;p++){let o="";for(let c=0;c<a.grid.cols;c++){const u=4*d,f=t.$getEncodedCharacterValue(i.characterPixels,u);o+=((s=ue(a.font,f))==null?void 0:s.character)||e.emptyCharacter,d++}e.preserveTrailingSpaces||(o=o.trimEnd()),n.push(o)}return n.join(`
2
+ `)}$generateTXT(r,e={}){return this._createTXTContent(r,this._applyDefaultOptions(e))}$saveTXT(r,e={}){const t=this._applyDefaultOptions(e),a=this._createTXTContent(r,t),i=new Blob([a],{type:"text/plain;charset=utf-8"});new H().$downloadFile(i,t.filename)}}class Bt{constructor(){h(this,"_canvas");h(this,"_ctx")}async $record(r,e,t,a){const i=Math.max(1,Math.round(e.frameRate)),n=Math.round(1e3/i),d=Math.max(1,Math.round(e.frameCount));return await new Promise((s,p)=>{const o=[];let c,u=0,f=!1;const x=()=>{c&&(c(),c=void 0)},m=C=>{f||(f=!0,x(),s(C))},v=()=>{if(u>=d)m(o);else try{const C=e.scale,y=Math.max(1,Math.round(r.width*C)),b=Math.max(1,Math.round(r.height*C));this._canvas||(this._canvas=document.createElement("canvas")),this._canvas.width===y&&this._canvas.height===b||(this._canvas.width=y,this._canvas.height=b),this._ctx||(this._ctx=this._canvas.getContext("2d"));const B=this._ctx;B.imageSmoothingEnabled=!1,B.clearRect(0,0,y,b),B.drawImage(r,0,0,r.width,r.height,0,0,y,b);const P={imageData:B.getImageData(0,0,y,b),width:y,height:b,delayMs:n};o.push(P),u+=1,a==null||a({state:"recording",frameIndex:u,totalFrames:d}),u>=d&&m(o)}catch(C){(y=>{if(f)return;f=!0,x();const b=y instanceof Error?y.message:"GIF recording failed";a==null||a({state:"error",message:b}),p(y instanceof Error?y:new Error(String(y)))})(C)}};c=t(()=>{v()}),a==null||a({state:"recording",frameIndex:0,totalFrames:d})})}}var Pe,ie,Ve=Object.defineProperty,It=(Pe=l=>{function r(c,u,f){return .29889531*c+.58662247*u+.11448223*f}function e(c,u,f){return .59597799*c-.2741761*u-.32180189*f}function t(c,u,f){return .21147017*c-.52261711*u+.31114694*f}function a(c,u){let f=c[0]-u[0],x=c[1]-u[1],m=c[2]-u[2],v=i(c)-i(u);return f*f*.5053+x*x*.299+m*m*.1957+v*v}function i(c){return c[3]!=null?c[3]:255}function n(c,u){return Math.sqrt(a(c,u))}function d(c,u){let[f,x,m]=c,[v,C,y]=u,b=r(f,x,m)-r(v,C,y),B=e(f,x,m)-e(v,C,y),P=t(f,x,m)-t(v,C,y),M=i(c)-i(u);return b*b*.5053+B*B*.299+P*P*.1957+M*M}function s(c,u){return Math.sqrt(d(c,u))}function p(c,u){var f,x=0;for(f=0;f<c.length;f++){let m=c[f]-u[f];x+=m*m}return x}function o(c,u){return Math.sqrt(p(c,u))}Ve(l,"__esModule",{value:!0}),((c,u)=>{for(var f in u)Ve(c,f,{get:u[f],enumerable:!0})})(l,{colorDifferenceRGBToYIQ:()=>s,colorDifferenceRGBToYIQSquared:()=>d,colorDifferenceYIQ:()=>n,colorDifferenceYIQSquared:()=>a,euclideanDistance:()=>o,euclideanDistanceSquared:()=>p})},()=>(ie||Pe((ie={exports:{}}).exports,ie),ie.exports)),Mt=59;function Oe(l=256){let r=0,e=new Uint8Array(l);return{get buffer(){return e.buffer},reset(){r=0},bytesView:()=>e.subarray(0,r),bytes:()=>e.slice(0,r),writeByte(a){t(r+1),e[r]=a,r++},writeBytes(a,i=0,n=a.length){t(r+n);for(let d=0;d<n;d++)e[r++]=a[d+i]},writeBytesView(a,i=0,n=a.byteLength){t(r+n),e.set(a.subarray(i,i+n),r),r+=n}};function t(a){var i=e.length;if(i>=a)return;a=Math.max(a,i*(i<1048576?2:1.125)>>>0),i!=0&&(a=Math.max(a,256));let n=e;e=new Uint8Array(a),r>0&&e.set(n.subarray(0,r),0)}}var St=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],Ft=function(l,r,e,t,a,i,n,d){a=a||Oe(512),i=i||new Uint8Array(256),n=n||new Int32Array(5003),d=d||new Int32Array(5003);let s=n.length,p=Math.max(2,t);i.fill(0),d.fill(0),F();let o=0,c=0,u=p+1,f=u,x=!1,m=f,v=V(m),C=1<<u-1,y=C+1,b=C+2,B=0,P=e[0],M=0;for(let w=s;w<65536;w*=2)++M;M=8-M,a.writeByte(p),O(C);for(let w=1;w<e.length;w++)T(e[w]);return O(P),O(y),a.writeByte(0),a.bytesView();function E(w){i[B++]=w,B>=254&&k()}function F(){n.fill(-1)}function T(w){let D=(w<<12)+P,g=w<<M^P;if(n[g]===D)P=d[g];else{if(n[g]>=0){let _=g===0?1:s-g;do if(g-=_,g<0&&(g+=s),n[g]===D)return void(P=d[g]);while(n[g]>=0)}O(P),P=w,b<4096?(d[g]=b++,n[g]=D):(F(),b=C+2,x=!0,O(C))}}function k(){B>0&&(a.writeByte(B),a.writeBytesView(i,0,B),B=0)}function V(w){return(1<<w)-1}function O(w){for(o&=St[c],c>0?o|=w<<c:o=w,c+=m;c>=8;)E(255&o),o>>=8,c-=8;if((b>v||x)&&(x?(m=f,v=V(m),x=!1):(++m,v=m==12?4096:V(m))),w==y){for(;c>0;)E(255&o),o>>=8,c-=8;k()}}};function Te(l,r,e){return l<<8&63488|r<<2&992|e>>3&31}function De(l,r,e,t){return l>>4|240&r|(240&e)<<4|(240&t)<<8}function Ae(l,r,e){return l>>4<<8|r>>4<<4|e>>4}function oe(l,r,e){return l<r?r:l>e?e:l}function ne(l){return l*l}function Ne(l,r,e){for(var t=0,a=1e100,i=l[r],n=i.cnt,d=(i.ac,i.rc),s=i.gc,p=i.bc,o=i.fw;o!=0;o=l[o].fw){var c=l[o].cnt,u=n*c/(n+c);if(!(u>=a)){var f=0;!((f+=u*ne(l[o].rc-d))>=a)&&!((f+=u*ne(l[o].gc-s))>=a)&&!((f+=u*ne(l[o].bc-p))>=a)&&(a=f,t=o)}}i.err=a,i.nn=t}function he(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function $t(l,r,e){let{format:t="rgb565",clearAlpha:a=!0,clearAlphaColor:i=0,clearAlphaThreshold:n=0,oneBitAlpha:d=!1}=e||{},s=e.useSqrt!==!1,p=t==="rgba4444",o=(function(w,D){let g=new Array(D==="rgb444"?4096:65536),_=w.length;if(D==="rgba4444")for(let S=0;S<_;++S){let $=w[S],L=$>>24&255,A=$>>16&255,I=$>>8&255,R=255&$,N=De(R,I,A,L),q=N in g?g[N]:g[N]=he();q.rc+=R,q.gc+=I,q.bc+=A,q.ac+=L,q.cnt++}else if(D==="rgb444")for(let S=0;S<_;++S){let $=w[S],L=$>>16&255,A=$>>8&255,I=255&$,R=Ae(I,A,L),N=R in g?g[R]:g[R]=he();N.rc+=I,N.gc+=A,N.bc+=L,N.cnt++}else for(let S=0;S<_;++S){let $=w[S],L=$>>16&255,A=$>>8&255,I=255&$,R=Te(I,A,L),N=R in g?g[R]:g[R]=he();N.rc+=I,N.gc+=A,N.bc+=L,N.cnt++}return g})(l,t),c=o.length,u=c-1,f=new Uint32Array(c+1);for(var x=0,m=0;m<o.length;++m){let w=o[m];if(w!=null){var v=1/w.cnt;p&&(w.ac*=v),w.rc*=v,w.gc*=v,w.bc*=v,o[x++]=w}}for(ne(r)/x<.022&&(s=!1),m=0;m<x-1;++m)o[m].fw=m+1,o[m+1].bk=m,s&&(o[m].cnt=Math.sqrt(o[m].cnt));var C,y,b;for(s&&(o[m].cnt=Math.sqrt(o[m].cnt)),m=0;m<x;++m){Ne(o,m);var B=o[m].err;for(y=++f[0];y>1&&!(o[C=f[b=y>>1]].err<=B);y=b)f[y]=C;f[y]=m}var P=x-r;for(m=0;m<P;){for(var M;;){var E=f[1];if((M=o[E]).tm>=M.mtm&&o[M.nn].mtm<=M.tm)break;for(M.mtm==u?E=f[1]=f[f[0]--]:(Ne(o,E),M.tm=m),B=o[E].err,y=1;(b=y+y)<=f[0]&&(b<f[0]&&o[f[b]].err>o[f[b+1]].err&&b++,!(B<=o[C=f[b]].err));y=b)f[y]=C;f[y]=E}var F=o[M.nn],T=M.cnt,k=F.cnt;v=1/(T+k),p&&(M.ac=v*(T*M.ac+k*F.ac)),M.rc=v*(T*M.rc+k*F.rc),M.gc=v*(T*M.gc+k*F.gc),M.bc=v*(T*M.bc+k*F.bc),M.cnt+=F.cnt,M.mtm=++m,o[F.bk].fw=F.fw,o[F.fw].bk=F.bk,F.mtm=u}let V=[];var O=0;for(m=0;;++O){let w=oe(Math.round(o[m].rc),0,255),D=oe(Math.round(o[m].gc),0,255),g=oe(Math.round(o[m].bc),0,255),_=255;p&&(_=oe(Math.round(o[m].ac),0,255),d&&(_=_<=(typeof d=="number"?d:127)?0:255),a&&_<=n&&(w=D=g=i,_=0));let S=p?[w,D,g,_]:[w,D,g];if(Lt(V,S)||V.push(S),(m=o[m].fw)==0)break}return V}function Lt(l,r){for(let e=0;e<l.length;e++){let t=l[e],a=t[0]===r[0]&&t[1]===r[1]&&t[2]===r[2],i=!(t.length>=4&&r.length>=4)||t[3]===r[3];if(a&&i)return!0}return!1}function Pt(l,r,e){let t=(e=e||"rgb565")==="rgb444"?4096:65536,a=new Uint8Array(l.length),i=new Array(t);if(e==="rgba4444")for(let n=0;n<l.length;n++){let d,s=l[n],p=s>>24&255,o=s>>16&255,c=s>>8&255,u=255&s,f=De(u,c,o,p);i[f]!=null?d=i[f]:(d=Vt(u,c,o,p,r),i[f]=d),a[n]=d}else for(let n=0;n<l.length;n++){let d,s=l[n],p=s>>16&255,o=s>>8&255,c=255&s,u=e==="rgb444"?Ae(c,o,p):Te(c,o,p);i[u]!=null?d=i[u]:(d=Ot(c,o,p,r),i[u]=d),a[n]=d}return a}function Vt(l,r,e,t,a){let i=0,n=1e100;for(let d=0;d<a.length;d++){let s=a[d],p=s[0],o=s[1],c=s[2],u=J(s[3]-t);u>n||(u+=J(p-l),!(u>n)&&(u+=J(o-r),!(u>n)&&(u+=J(c-e),!(u>n)&&(n=u,i=d))))}return i}function Ot(l,r,e,t){let a=0,i=1e100;for(let n=0;n<t.length;n++){let d=t[n],s=d[0],p=d[1],o=d[2],c=J(s-l);c>i||(c+=J(p-r),!(c>i)&&(c+=J(o-e),!(c>i)&&(i=c,a=n)))}return a}function J(l){return l*l}function Tt(l={}){let{initialCapacity:r=4096,auto:e=!0}=l,t=Oe(r),a=new Uint8Array(256),i=new Int32Array(5003),n=new Int32Array(5003),d=!1;return{reset(){t.reset(),d=!1},finish(){t.writeByte(Mt)},bytes:()=>t.bytes(),bytesView:()=>t.bytesView(),get buffer(){return t.buffer},get stream(){return t},writeHeader:s,writeFrame(p,o,c,u={}){let{transparent:f=!1,transparentIndex:x=0,delay:m=0,palette:v=null,repeat:C=0,colorDepth:y=8,dispose:b=-1}=u,B=!1;if(e?d||(B=!0,s(),d=!0):B=!!u.first,o=Math.max(0,Math.floor(o)),c=Math.max(0,Math.floor(c)),B){if(!v)throw new Error("First frame must include a { palette } option");(function(E,F,T,k,V=8){let O=1,w=0,D=me(k.length)-1,g=O<<7|V-1<<4|w<<3|D;X(E,F),X(E,T),E.writeBytes([g,0,0])})(t,o,c,v,y),Ue(t,v),C>=0&&(function(E,F){E.writeByte(33),E.writeByte(255),E.writeByte(11),Re(E,"NETSCAPE2.0"),E.writeByte(3),E.writeByte(1),X(E,F),E.writeByte(0)})(t,C)}let P=Math.round(m/10);(function(E,F,T,k,V){var O,w;E.writeByte(33),E.writeByte(249),E.writeByte(4),V<0&&(V=0,k=!1),k?(O=1,w=2):(O=0,w=0),F>=0&&(w=7&F),w<<=2,E.writeByte(0|w|0|O),X(E,T),E.writeByte(V||0),E.writeByte(0)})(t,b,P,f,x);let M=!!v&&!B;(function(E,F,T,k){if(E.writeByte(44),X(E,0),X(E,0),X(E,F),X(E,T),k){let V=0,O=0,w=me(k.length)-1;E.writeByte(128|V|O|w)}else E.writeByte(0)})(t,o,c,M?v:null),M&&Ue(t,v),(function(E,F,T,k,V=8,O,w,D){Ft(T,k,F,V,E,O,w,D)})(t,p,o,c,y,a,i,n)}};function s(){Re(t,"GIF89a")}}function Ue(l,r){let e=1<<me(r.length);for(let t=0;t<e;t++){let a=[0,0,0];t<r.length&&(a=r[t]),l.writeByte(a[0]),l.writeByte(a[1]),l.writeByte(a[2])}}function X(l,r){l.writeByte(255&r),l.writeByte(r>>8&255)}function Re(l,r){for(var e=0;e<r.length;e++)l.writeByte(r.charCodeAt(e))}function me(l){return Math.max(Math.ceil(Math.log2(l)),1)}It();class Dt{constructor(r,e){h(this,"_recorder");h(this,"_textmodifier");h(this,"_registerPostDrawHook");this._recorder=new Bt,this._textmodifier=r,this._registerPostDrawHook=e}async $saveGIF(r={}){const e=this._textmodifier.canvas,t=this._applyDefaultOptions(r),a=r.onProgress;try{const i=await this._recorder.$record(e,t,this._registerPostDrawHook,a),n=Tt(),{repeat:d}=r;for(let o=0;o<i.length;o++){const c=i[o],{width:u,height:f,imageData:x,delayMs:m}=c,v=new Uint32Array(x.data.buffer),C=$t(v,256,{}),y=Pt(v,C);n.writeFrame(y,u,f,{palette:C,delay:m,repeat:o===0?d:-1}),o%2!=0&&o!==i.length-1||(a==null||a({state:"encoding",frameIndex:o+1,totalFrames:i.length}),await new Promise(b=>setTimeout(b,0)))}n.finish();const s=n.bytes(),p=s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength);new H().$downloadFile(new Blob([p],{type:"image/gif"}),t.filename),a==null||a({state:"completed",totalFrames:t.frameCount})}catch(i){throw a==null||a({state:"error",message:i instanceof Error?i.message:"GIF export failed"}),i}}_applyDefaultOptions(r){const e=Math.abs(Math.round(r.frameCount??300)),t=Math.abs(r.frameRate??60),a=Math.abs(r.scale??1),i=Math.max(-1,Math.round(r.repeat??0));return{filename:r.filename,frameCount:e,frameRate:t,scale:a,repeat:i}}}function At(l){return l&&l.__esModule&&Object.prototype.hasOwnProperty.call(l,"default")?l.default:l}var ze,je={exports:{}};function Nt(){return ze||(ze=1,(function(l){(function(){function r(s,p){return(function(o){if(typeof o!="string"||!o.match(/^data:image\/webp;base64,/i))throw new Error("Failed to decode WebP Base64 URL");return window.atob(o.substring(23))})(typeof s=="string"&&/^data:image\/webp/.test(s)?s:s.toDataURL("image/webp",p))}function e(s){return(s.charCodeAt(0)|s.charCodeAt(1)<<8|s.charCodeAt(2)<<16|s.charCodeAt(3)<<24)>>>0}function t(s){let p=s.indexOf("VP8",12);if(p===-1)throw new Error("Bad image format, does this browser support WebP?");let o=!1;for(;p<s.length-8;){let c,u;switch(u=s.substring(p,p+4),p+=4,c=e(s.substring(p,p+4)),p+=4,u){case"VP8 ":return{frame:s.substring(p,p+c),hasAlpha:o};case"ALPH":o=!0}p+=c,1&c&&p++}throw new Error("Failed to find VP8 keyframe in WebP image, is this image mistakenly encoded in the Lossless WebP format?")}function a(s){this.value=s}function i(s){this.value=s}function n(s,p,o){if(Array.isArray(o))for(let c=0;c<o.length;c++)n(s,p,o[c]);else if(typeof o=="string")s.writeString(o);else if(o instanceof Uint8Array)s.writeBytes(o);else{if(!o.id)throw new Error("Bad EBML datatype "+typeof o.data);if(o.offset=s.pos+p,s.writeUnsignedIntBE(o.id),Array.isArray(o.data)){let c,u,f;o.size===-1?s.writeByte(255):o.size===-2?(c=s.pos,s.writeBytes([15,255,255,255,255])):(c=s.pos,s.writeBytes([0,0,0,0])),u=s.pos,o.dataOffset=u+p,n(s,p,o.data),o.size!==-1&&o.size!==-2&&(f=s.pos,o.size=f-u,s.seek(c),s.writeEBMLVarIntWidth(o.size,4),s.seek(f))}else if(typeof o.data=="string")s.writeEBMLVarInt(o.data.length),o.dataOffset=s.pos+p,s.writeString(o.data);else if(typeof o.data=="number")o.size||(o.size=s.measureUnsignedInt(o.data)),s.writeEBMLVarInt(o.size),o.dataOffset=s.pos+p,s.writeUnsignedIntBE(o.data,o.size);else if(o.data instanceof i)s.writeEBMLVarInt(8),o.dataOffset=s.pos+p,s.writeDoubleBE(o.data.value);else if(o.data instanceof a)s.writeEBMLVarInt(4),o.dataOffset=s.pos+p,s.writeFloatBE(o.data.value);else{if(!(o.data instanceof Uint8Array))throw new Error("Bad EBML datatype "+typeof o.data);s.writeEBMLVarInt(o.data.byteLength),o.dataOffset=s.pos+p,s.writeBytes(o.data)}}}let d=function(s,p){return function(o){let c,u,f=!1,x=0,m=0,v=null,C=null,y=null,b=[],B=0,P=0,M={quality:.95,transparent:!1,alphaQuality:void 0,fileWriter:null,fd:null,frameDuration:null,frameRate:null},E={Cues:{id:new Uint8Array([28,83,187,107]),positionEBML:null},SegmentInfo:{id:new Uint8Array([21,73,169,102]),positionEBML:null},Tracks:{id:new Uint8Array([22,84,174,107]),positionEBML:null}},F={id:17545,data:new i(0)},T=[],k=new p(o.fileWriter||o.fd);function V(g){return g-c.dataOffset}function O(){u=(function(){let L={id:21420,size:5,data:0},A={id:290298740,data:[]};for(let I in E){let R=E[I];R.positionEBML=Object.create(L),A.data.push({id:19899,data:[{id:21419,data:R.id},R.positionEBML]})}return A})();let g={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:"webm-writer-js"},{id:22337,data:"webm-writer-js"},F]},_=[{id:176,data:x},{id:186,data:m}];o.transparent&&_.push({id:21440,data:1});let S={id:374648427,data:[{id:174,data:[{id:215,data:1},{id:29637,data:1},{id:156,data:0},{id:2274716,data:"und"},{id:134,data:"V_VP8"},{id:2459272,data:"VP8"},{id:131,data:1},{id:224,data:_}]}]};c={id:408125543,size:-2,data:[u,g,S]};let $=new s(256);n($,k.pos,[{id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:"webm"},{id:17031,data:2},{id:17029,data:2}]},c]),k.write($.getAsDataArray()),E.SegmentInfo.positionEBML.data=V(g.offset),E.Tracks.positionEBML.data=V(S.offset),f=!0}function w(g){return g.alpha?(function(_){let S,$,L=new s(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return L.writeEBMLVarInt(_.trackNumber),L.writeU16BE(_.timecode),L.writeByte(0),S={id:161,data:[L.getAsDataArray(),_.frame]},$={id:30113,data:[{id:166,data:[{id:238,data:1},{id:165,data:_.alpha}]}]},{id:160,data:[S,$]}})(g):(function(_){let S=new s(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return S.writeEBMLVarInt(_.trackNumber),S.writeU16BE(_.timecode),S.writeByte(128),{id:163,data:[S.getAsDataArray(),_.frame]}})(g)}function D(){if(b.length===0)return;let g=0;for(let I=0;I<b.length;I++)g+=b[I].frame.length+(b[I].alpha?b[I].alpha.length:0);let _=new s(g+64*b.length),S=(function(I){return{id:524531317,data:[{id:231,data:Math.round(I.timecode)}]}})({timecode:Math.round(B)});for(let I=0;I<b.length;I++)S.data.push(w(b[I]));var $,L,A;n(_,k.pos,S),k.write(_.getAsDataArray()),$=1,L=Math.round(B),A=S.offset,T.push({id:187,data:[{id:179,data:L},{id:183,data:[{id:247,data:$},{id:241,data:V(A)}]}]}),b=[],B+=P,P=0}this.addFrame=function(g,_,S){f||(x=g.width||0,m=g.height||0,O());let $,L=t(r(g,o.quality)),A=null;$=S||(typeof _=="number"?_:o.frameDuration),o.transparent&&(_ instanceof HTMLCanvasElement||typeof _=="string"?A=_:L.hasAlpha&&(A=(function(I){v!==null&&v.width===I.width&&v.height===I.height||(v=document.createElement("canvas"),v.width=I.width,v.height=I.height,C=v.getContext("2d"),y=C.createImageData(v.width,v.height));let R=I.getContext("2d").getImageData(0,0,I.width,I.height).data,N=y.data,q=0,Fr=I.width*I.height*4;for(let ke=3;ke<Fr;ke+=4){let Be=R[ke];N[q++]=Be,N[q++]=Be,N[q++]=Be,N[q++]=255}return C.putImageData(y,0,0),v})(g))),(function(I){I.trackNumber=1,I.timecode=Math.round(P),b.push(I),P+=I.duration,P>=5e3&&D()})({frame:L.frame,duration:$,alpha:A?t(r(A,o.alphaQuality)).frame:null})},this.complete=function(){return f||O(),D(),(function(){let g={id:475249515,data:T},_=new s(16+32*T.length);n(_,k.pos,g),k.write(_.getAsDataArray()),E.Cues.positionEBML.data=V(g.offset)})(),(function(){let g=new s(u.size),_=k.pos;n(g,u.dataOffset,u.data),k.seek(u.dataOffset),k.write(g.getAsDataArray()),k.seek(_)})(),(function(){let g=new s(8),_=k.pos;g.writeDoubleBE(B),k.seek(F.dataOffset),k.write(g.getAsDataArray()),k.seek(_)})(),(function(){let g=new s(10),_=k.pos;g.writeUnsignedIntBE(c.id),g.writeEBMLVarIntWidth(k.pos-c.dataOffset,5),k.seek(c.offset),k.write(g.getAsDataArray()),k.seek(_)})(),k.complete("video/webm")},this.getWrittenSize=function(){return k.length},o=(function(g,_){let S={};return[g,_].forEach(function($){for(let L in $)Object.prototype.hasOwnProperty.call($,L)&&(S[L]=$[L])}),S})(M,o||{}),(function(){if(!o.frameDuration){if(!o.frameRate)throw new Error("Missing required frameDuration or frameRate setting");o.frameDuration=1e3/o.frameRate}o.quality=Math.max(Math.min(o.quality,.99999),0),o.alphaQuality===void 0?o.alphaQuality=o.quality:o.alphaQuality=Math.max(Math.min(o.alphaQuality,.99999),0)})()}};l.exports=d})()})(je)),je.exports}var Ge,He={exports:{}};function Ut(){return Ge||(Ge=1,(function(l){(function(){let r=function(e){this.data=new Uint8Array(e),this.pos=0};r.prototype.seek=function(e){this.pos=e},r.prototype.writeBytes=function(e){for(let t=0;t<e.length;t++)this.data[this.pos++]=e[t]},r.prototype.writeByte=function(e){this.data[this.pos++]=e},r.prototype.writeU8=r.prototype.writeByte,r.prototype.writeU16BE=function(e){this.data[this.pos++]=e>>8,this.data[this.pos++]=e},r.prototype.writeDoubleBE=function(e){let t=new Uint8Array(new Float64Array([e]).buffer);for(let a=t.length-1;a>=0;a--)this.writeByte(t[a])},r.prototype.writeFloatBE=function(e){let t=new Uint8Array(new Float32Array([e]).buffer);for(let a=t.length-1;a>=0;a--)this.writeByte(t[a])},r.prototype.writeString=function(e){for(let t=0;t<e.length;t++)this.data[this.pos++]=e.charCodeAt(t)},r.prototype.writeEBMLVarIntWidth=function(e,t){switch(t){case 1:this.writeU8(128|e);break;case 2:this.writeU8(64|e>>8),this.writeU8(e);break;case 3:this.writeU8(32|e>>16),this.writeU8(e>>8),this.writeU8(e);break;case 4:this.writeU8(16|e>>24),this.writeU8(e>>16),this.writeU8(e>>8),this.writeU8(e);break;case 5:this.writeU8(8|e/4294967296&7),this.writeU8(e>>24),this.writeU8(e>>16),this.writeU8(e>>8),this.writeU8(e);break;default:throw new Error("Bad EBML VINT size "+t)}},r.prototype.measureEBMLVarInt=function(e){if(e<127)return 1;if(e<16383)return 2;if(e<2097151)return 3;if(e<268435455)return 4;if(e<34359738367)return 5;throw new Error("EBML VINT size not supported "+e)},r.prototype.writeEBMLVarInt=function(e){this.writeEBMLVarIntWidth(e,this.measureEBMLVarInt(e))},r.prototype.writeUnsignedIntBE=function(e,t){switch(t===void 0&&(t=this.measureUnsignedInt(e)),t){case 5:this.writeU8(Math.floor(e/4294967296));case 4:this.writeU8(e>>24);case 3:this.writeU8(e>>16);case 2:this.writeU8(e>>8);case 1:this.writeU8(e);break;default:throw new Error("Bad UINT size "+t)}},r.prototype.measureUnsignedInt=function(e){return e<256?1:e<65536?2:e<1<<24?3:e<4294967296?4:5},r.prototype.getAsDataArray=function(){if(this.pos<this.data.byteLength)return this.data.subarray(0,this.pos);if(this.pos==this.data.byteLength)return this.data;throw new Error("ArrayBufferDataStream's pos lies beyond end of buffer")},l.exports=r})()})(He)),He.exports}var We,qe,Xe,Ye={exports:{}};function Rt(){return We||(We=1,(function(l){(function(){let r=function(e){return function(t){let a=[],i=Promise.resolve(),n=null,d=null;function s(c){return new Promise(function(u,f){let x=new FileReader;x.addEventListener("loadend",function(){u(x.result)}),x.readAsArrayBuffer(c)})}function p(c){return new Promise(function(u,f){c instanceof Uint8Array?u(c):c instanceof ArrayBuffer||ArrayBuffer.isView(c)?u(new Uint8Array(c)):c instanceof Blob?u(s(c).then(function(x){return new Uint8Array(x)})):u(s(new Blob([c])).then(function(x){return new Uint8Array(x)}))})}function o(c){let u=c.byteLength||c.length||c.size;if(!Number.isInteger(u))throw new Error("Failed to determine size of element");return u}t&&t.constructor.name==="FileWriter"?n=t:e&&t&&(d=t),this.pos=0,this.length=0,this.seek=function(c){if(c<0)throw new Error("Offset may not be negative");if(isNaN(c))throw new Error("Offset may not be NaN");if(c>this.length)throw new Error("Seeking beyond the end of file is not allowed");this.pos=c},this.write=function(c){let u={offset:this.pos,data:c,length:o(c)},f=u.offset>=this.length;this.pos+=u.length,this.length=Math.max(this.length,this.pos),i=i.then(function(){if(d)return new Promise(function(x,m){p(u.data).then(function(v){let C=0,y=Buffer.from(v.buffer),b=function(B,P,M){C+=P,C>=M.length?x():e.write(d,M,C,M.length-C,u.offset+C,b)};e.write(d,y,0,y.length,u.offset,b)})});if(n)return new Promise(function(x,m){n.onwriteend=x,n.seek(u.offset),n.write(new Blob([u.data]))});if(!f)for(let x=0;x<a.length;x++){let m=a[x];if(!(u.offset+u.length<=m.offset||u.offset>=m.offset+m.length)){if(u.offset<m.offset||u.offset+u.length>m.offset+m.length)throw new Error("Overwrite crosses blob boundaries");return u.offset==m.offset&&u.length==m.length?void(m.data=u.data):p(m.data).then(function(v){return m.data=v,p(u.data)}).then(function(v){u.data=v,m.data.set(u.data,u.offset-m.offset)})}}a.push(u)})},this.complete=function(c){return i=d||n?i.then(function(){return null}):i.then(function(){let u=[];for(let f=0;f<a.length;f++)u.push(a[f].data);return new Blob(u,{type:c})}),i}}};l.exports=r})()})(Ye)),Ye.exports}function zt(){return Xe?qe:(Xe=1,qe=Nt()(Ut(),Rt()(null)))}const jt=At(zt());class Gt{async $record(r,e,t,a){const i=Math.max(1,Math.round(e.frameRate)),n=Math.max(1,Math.round(e.frameCount)),d=new jt({quality:e.quality,alphaQuality:e.transparent?e.quality:void 0,transparent:e.transparent,frameRate:i}),s=this._createSnapshotSurface();return await new Promise((p,o)=>{let c,u="capturing",f=!1,x=0;const m=()=>{c&&(c(),c=void 0)},v=()=>{a==null||a({state:"recording",frameIndex:x,totalFrames:n})},C=b=>{if(f)return;f=!0,m();const B=b instanceof Error?b.message:"WEBM export failed";a==null||a({state:"error",message:B}),o(b instanceof Error?b:new Error(String(b)))},y=()=>{u!=="capturing"||f||(u="encoding",m(),d.complete().then(b=>{(B=>{f||(f=!0,a==null||a({state:"completed",frameIndex:Math.min(n,x),totalFrames:n}),p(B))})(b)}).catch(C))};c=t(()=>{(()=>{if(u==="capturing")if(x>=n)y();else try{const b=s(r);d.addFrame(b),x+=1,v(),x>=n&&y()}catch(b){C(b)}})()}),v()})}_createSnapshotSurface(){let r=null,e=null;return t=>{const a=Math.max(1,t.width),i=Math.max(1,t.height),n=((d,s)=>(r||(r=document.createElement("canvas")),r.width!==d||r.height!==s?(r.width=d,r.height=s,e=r.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)):e||(e=r.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)),e?r:null))(a,i);return n&&e?(e.clearRect(0,0,a,i),e.drawImage(t,0,0,a,i),n):t}}}class Ht{constructor(r,e){h(this,"_recorder");h(this,"_textmodifier");h(this,"_registerPostDrawHook");this._recorder=new Gt,this._textmodifier=r,this._registerPostDrawHook=e}async $saveWEBM(r={}){var a;const e=this._textmodifier.canvas,t=this._applyDefaultOptions(r);try{const i=await this._recorder.$record(e,t,this._registerPostDrawHook,r.onProgress);new H().$downloadFile(i,t.filename)}catch(i){throw(a=r.onProgress)==null||a.call(r,{state:"error",message:i instanceof Error?i.message:"WEBM export failed"}),i}}_applyDefaultOptions(r){return{filename:r.filename,frameRate:Math.abs(Math.round(r.frameRate??60)),frameCount:Math.abs(Math.round(r.frameCount??300)),quality:Math.abs(Math.min(Math.max(r.quality??1,0),1)),transparent:!!r.transparent,debugLogging:!!r.debugLogging}}}class Wt extends z{$extractCellData(r){var d;const e=this.$extractFramebufferData(r.drawFramebuffer),t=[],a=r.grid,i=r.font;let n=0;for(let s=0;s<a.rows;s++)for(let p=0;p<a.cols;p++){const o=4*n,c=this.$getEncodedCharacterValue(e.characterPixels,o),u=this.$extractCellTransform(e.characterPixels,o),f=((d=ue(i,c))==null?void 0:d.character)??" ";t.push({x:p,y:s,character:f,foreground:ae(e.primaryColorPixels,o),background:ae(e.secondaryColorPixels,o),transform:{invert:u.isInverted,flipX:u.flipHorizontal,flipY:u.flipVertical,rotation:u.rotation}}),n++}return t}}const Je="1.2.1",Qe="textmode.document",Ze="2.0.0";class fe{_applyDefaultOptions(r){return{target:r.target??"selected",pretty:r.pretty??!0,colorMode:r.colorMode??"hex",includeMetadata:r.includeMetadata??!0,filename:r.filename,layer:r.layer}}_createMetadata(r){return r.includeMetadata?{createdAt:new Date().toISOString(),generator:{name:"textmode.export.js",version:Je}}:void 0}_formatColor(r,e){return e==="rgba"?{...r}:`#${[r.r,r.g,r.b,r.a].map(t=>t.toString(16).padStart(2,"0")).join("")}`}_createObjectRowsCells(r,e,t,a){const i=[];for(let n=0;n<t;n++){const d=n*e,s=r.slice(d,d+e).map(p=>({x:p.x,y:p.y,character:p.character,foreground:this._formatColor(p.foreground,a),background:this._formatColor(p.background,a),transform:{...p.transform}}));i.push(s)}return{encoding:"object-rows-v1",rows:i}}_createLayerGrid(r){return{cols:r.grid.cols,rows:r.grid.rows,cellWidth:r.grid.cellWidth,cellHeight:r.grid.cellHeight}}_createLayerCells(r,e){const t=new Wt().$extractCellData(r);return this._createObjectRowsCells(t,r.grid.cols,r.grid.rows,e.colorMode)}_createStackLayer(r,e){return{id:r.id,visible:r.visible,opacity:r.opacity,blendMode:r.blendMode,offsetX:r.offsetX,offsetY:r.offsetY,rotationZ:r.rotationZ,grid:this._createLayerGrid(r),cells:this._createLayerCells(r,e)}}$generateJSONData(r,e={}){const t=this._applyDefaultOptions(e),a=this._createMetadata(t);if(t.target==="all"){const n=(function(s){return[s.layers.base,...s.layers.all].map(p=>{const o=p;return{...re(s,p),visible:o._visible??!0,opacity:o._opacity??1,blendMode:o._blendMode??"normal",offsetX:o._offsetX??0,offsetY:o._offsetY??0,rotationZ:o._rotation??0}})})(r),d=n[0].grid;return{format:Qe,formatVersion:Ze,target:"all",...a?{metadata:a}:{},canvas:{width:d.width,height:d.height},layers:n.map(s=>this._createStackLayer(s,t))}}const i=re(r,t.layer);return{format:Qe,formatVersion:Ze,target:"selected",...a?{metadata:a}:{},canvas:{width:i.grid.width,height:i.grid.height},grid:this._createLayerGrid(i),layer:{id:i.id,cells:this._createLayerCells(i,t)}}}$generateJSONString(r,e={}){const t=this._applyDefaultOptions(e),a=this.$generateJSONData(r,t),i=typeof t.pretty=="number"?t.pretty:t.pretty?2:0;return JSON.stringify(a,null,i)}$saveJSON(r,e={}){const t=this._applyDefaultOptions(e);new H().$downloadFile(new Blob([this.$generateJSONString(r,t)],{type:"application/json;charset=utf-8"}),t.filename)}}const qt="textmode-export-overlay",W="textmode-export-overlay__stack",ge="textmode-export-overlay__stack--dense",Ke="textmode-export-overlay__stack--compact",et="textmode-export-overlay__section",Xt="textmode-export-overlay__header",Yt="textmode-export-overlay__header-title-row",Jt="textmode-export-overlay__header-links",Qt="textmode-export-overlay__row",tt="textmode-export-overlay__label",rt="textmode-export-overlay__field",at="textmode-export-overlay__field--compact",it="textmode-export-overlay__field--dense",ot="textmode-export-overlay__field--full",nt="textmode-export-overlay__field--channel",st="textmode-export-overlay__input",Zt="textmode-export-overlay__checkbox",lt="textmode-export-overlay__muted",Kt="textmode-export-overlay__status",er="textmode-export-overlay__status--gif",tr="textmode-export-overlay__status--video",rr="textmode-export-overlay__status-title",ar="textmode-export-overlay__status-value",ir="textmode-export-overlay__divider",or="textmode-export-overlay__title",nr="textmode-export-overlay__button",be="textmode-export-overlay__button--primary",ve="textmode-export-overlay__button--secondary",dt="textmode-export-overlay__button--full",sr="textmode-export-overlay__support-link",lr="textmode-export-overlay__support-icon",dr="textmode-export-overlay__link-icon";class G{constructor(){h(this,"element");h(this,"mounted",!1);h(this,"destroyed",!1)}mount(r){if(this.destroyed)throw new Error("Cannot mount a destroyed component");if(this.mounted)return;const e=this.render();r.appendChild(e),this.element=e,this.onMount(),this.mounted=!0}unmount(){this.mounted&&this.element&&(this._onUnmount(),this.element.remove(),this.element=void 0,this.mounted=!1)}destroy(){this.destroyed||(this.unmount(),this._onDestroy(),this.destroyed=!0)}update(r){this.mounted&&this.onUpdate(r)}onMount(){}_onUnmount(){}_onDestroy(){}onUpdate(r){}get root(){if(!this.element)throw new Error("Component is not mounted yet");return this.element}isMounted(){return this.mounted}}const K=class K extends G{render(){const r=document.createElement("div");r.classList.add(W,ge,Xt);const e=document.createElement("div");e.classList.add(Yt);const t=document.createElement("strong");t.textContent="textmode.export.js",t.classList.add(or);const a=document.createElement("div");a.classList.add(Jt);const i=this._createLink("https://github.com/humanbydefinition/textmode.export.js","View repository on GitHub",dr,[{d:"M0 0h24v24H0z",fill:"none",stroke:"none"},{d:"M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5"}]),n=this._createLink("https://code.textmode.art/docs/support","Support textmode.export.js",lr,[{d:"M0 0h24v24H0z",fill:"none",stroke:"none"},{d:"M3 14c.83 .642 2.077 1.017 3.5 1c1.423 .017 2.67 -.358 3.5 -1c.83 -.642 2.077 -1.017 3.5 -1c1.423 -.017 2.67 .358 3.5 1"},{d:"M8 3a2.4 2.4 0 0 0 -1 2a2.4 2.4 0 0 0 1 2"},{d:"M12 3a2.4 2.4 0 0 0 -1 2a2.4 2.4 0 0 0 1 2"},{d:"M3 10h14v5a6 6 0 0 1 -6 6h-2a6 6 0 0 1 -6 -6v-5z"},{d:"M16.746 16.726a3 3 0 1 0 .252 -5.555"}]);a.appendChild(i),a.appendChild(n),e.appendChild(t),e.appendChild(a);const d=document.createElement("div");return d.classList.add(ir),r.appendChild(e),r.appendChild(d),r}_createLink(r,e,t,a){const i=document.createElement("a");return i.href=r,i.target="_blank",i.rel="noopener noreferrer",i.classList.add(sr),i.setAttribute("aria-label",e),i.appendChild(this._createIcon(t,a)),i}_createIcon(r,e){const t=document.createElementNS(K._iconNamespace,"svg");t.setAttribute("xmlns",K._iconNamespace),t.setAttribute("width","18"),t.setAttribute("height","18"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.setAttribute("stroke","currentColor"),t.setAttribute("stroke-width","2"),t.setAttribute("stroke-linecap","round"),t.setAttribute("stroke-linejoin","round"),t.classList.add(r);for(const a of e){const i=document.createElementNS(K._iconNamespace,"path");for(const[n,d]of Object.entries(a))i.setAttribute(n,d);t.appendChild(i)}return t}};h(K,"_iconNamespace","http://www.w3.org/2000/svg");let ye=K;class U extends G{constructor(e){super();h(this,"props");this.props=e}render(){const e=document.createElement("div");e.classList.add(rt),this.applyVariant(e,this.props.variant);const t=document.createElement("label");if(t.classList.add(tt),t.textContent=this.props.label,this.props.labelFor&&(t.htmlFor=this.props.labelFor),e.appendChild(t),this.props.description){const a=document.createElement("span");a.classList.add(lt),a.textContent=this.props.description,e.appendChild(a)}return e}attachControl(e){this.root.appendChild(e)}update(e){this.props=e,super.update(e)}onUpdate(e){const t=this.root;for(;t.firstChild;)t.removeChild(t.firstChild);this.props=e,t.classList.add(rt),this.applyVariant(t,e.variant);const a=document.createElement("label");if(a.classList.add(tt),a.textContent=e.label,e.labelFor&&(a.htmlFor=e.labelFor),t.appendChild(a),e.description){const i=document.createElement("span");i.classList.add(lt),i.textContent=e.description,t.appendChild(i)}}applyVariant(e,t){switch(e.classList.remove(at,it,ot,nt),t){case"compact":e.classList.add(at);break;case"dense":e.classList.add(it);break;case"full":e.classList.add(ot);break;case"channel":e.classList.add(nt)}}}class Q extends G{constructor(e){super();h(this,"props");h(this,"select");h(this,"handleChange",()=>{this.props.defaultValue=this.select.value});this.props=e}render(){return this.select=document.createElement("select"),this.select.classList.add(st),this.props.id&&(this.select.id=this.props.id),this.populateOptions(),this.select.addEventListener("change",this.handleChange),this.select}get selectElement(){return this.select}get value(){return this.select.value}set value(e){this.select&&(this.select.value=e),this.props.defaultValue=e}_onUnmount(){this.select.removeEventListener("change",this.handleChange)}onUpdate(e){this.props=e,this.populateOptions(),e.defaultValue&&(this.select.value=e.defaultValue)}update(e){this.props={...this.props,...e},this.select&&(e.id&&(this.select.id=e.id),e.options&&this.populateOptions(),e.defaultValue!==void 0&&(this.select.value=e.defaultValue))}populateOptions(){if(this.select){this.select.innerHTML="";for(const e of this.props.options){const t=document.createElement("option");t.value=e.value,t.textContent=e.label,this.select.appendChild(t)}this.props.defaultValue&&(this.select.value=this.props.defaultValue)}}}class ct extends G{constructor(e){super();h(this,"props");h(this,"button");this.props=e}render(){return this.button=document.createElement("button"),this.button.type="button",this.button.textContent=this.props.label,this.button.classList.add(nr),this.props.variant==="secondary"?this.button.classList.add(ve):this.button.classList.add(be),this.props.fullWidth&&this.button.classList.add(dt),this.button.disabled=!!this.props.disabled,this.button}get buttonElement(){return this.button}setLabel(e){this.props.label=e,this.button.textContent=e}setDisabled(e){this.props.disabled=e,this.button.disabled=e}onUpdate(e){this.props=e,this.button.textContent=e.label,this.button.disabled=!!e.disabled,e.variant==="secondary"?(this.button.classList.add(ve),this.button.classList.remove(be)):(this.button.classList.add(be),this.button.classList.remove(ve)),this.button.classList.toggle(dt,!!e.fullWidth)}}class cr{constructor(r){h(this,"api");this.api=r}async $copy(r,e){switch(r){case"txt":{const t=this.api.toString(e);await navigator.clipboard.writeText(t);break}case"json":{const t=this.api.toJSONString(e);await navigator.clipboard.writeText(t);break}case"svg":{const t=this.api.toSVG(e);await navigator.clipboard.writeText(t);break}case"image":await this.api.copyCanvas(e);break;default:throw new Error(`Clipboard not supported for ${r}`)}}}class ur{constructor(r,e){h(this,"api");h(this,"events");this.api=r,this.events=e}async $requestExport(r,e,t={}){this.events.$emit("export:request",{format:r});try{const a={onGIFProgress:t.onGIFProgress?i=>{var n;(n=t.onGIFProgress)==null||n.call(t,i),this.events.$emit("export:progress",{format:r,progress:i})}:r==="gif"?i=>this.events.$emit("export:progress",{format:r,progress:i}):void 0,onVideoProgress:t.onVideoProgress?i=>{var n;(n=t.onVideoProgress)==null||n.call(t,i),this.events.$emit("export:progress",{format:r,progress:i})}:r==="video"?i=>this.events.$emit("export:progress",{format:r,progress:i}):void 0};await this._execute(r,e,a),this.events.$emit("export:success",{format:r})}catch(a){throw this.events.$emit("export:error",{format:r,error:a}),a}}_execute(r,e,t){switch(r){case"txt":return Promise.resolve(this.api.saveStrings(e));case"json":return Promise.resolve(this.api.saveJSON(e));case"image":return this.api.saveCanvas(e);case"svg":return Promise.resolve(this.api.saveSVG(e));case"gif":{const a={...e,onProgress:t.onGIFProgress};return this.api.saveGIF(a)}case"video":{const a={...e,onProgress:t.onVideoProgress};return this.api.saveWEBM(a)}}}}class pr{constructor(r,e){h(this,"modifier");h(this,"overlay");h(this,"animationFrameId",null);h(this,"handleUpdate");h(this,"bound",!1);this.modifier=r,this.overlay=e,this.handleUpdate=()=>this.scheduleUpdate()}scheduleUpdate(){this.animationFrameId!==null&&cancelAnimationFrame(this.animationFrameId),this.animationFrameId=requestAnimationFrame(()=>this.update())}bind(){this.bound||(window.addEventListener("resize",this.handleUpdate),window.addEventListener("scroll",this.handleUpdate,!0),this.bound=!0,this.handleUpdate())}update(){this.animationFrameId=null;const r=this.modifier.canvas.getBoundingClientRect();this.overlay.style.top=`${r.top+window.scrollY+8}px`,this.overlay.style.left=`${r.left+window.scrollX+8}px`}dispose(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.bound&&(window.removeEventListener("resize",this.handleUpdate),window.removeEventListener("scroll",this.handleUpdate,!0),this.bound=!1)}}const ee="textmode-export-number-input",hr=`${ee}__field`,mr=`${ee}__controls`,fr=`${ee}__control`,ut=`${ee}__display`,se=`${ut}--visible`,pt=l=>{const r=document.createElement("button");return r.type="button",r.className=fr,r.textContent=l>0?"▲":"▼",r};class Y extends G{constructor(e){super();h(this,"props");h(this,"input");h(this,"display");h(this,"incrementButton");h(this,"decrementButton");h(this,"suppressClickAfterPointer",new WeakMap);h(this,"holdTimeoutId");h(this,"holdIntervalId");h(this,"activePointerId");h(this,"disabledObserver");this.props=e}render(){const e=document.createElement("div");e.className=ee,this.input=document.createElement("input"),this.input.type="number",this.input.value=this.props.defaultValue,Object.assign(this.input,this.props.attributes),this.input.className=hr,this.display=document.createElement("div"),this.display.className=ut;const t=document.createElement("div");return t.className=mr,this.incrementButton=pt(1),this.decrementButton=pt(-1),t.appendChild(this.incrementButton),t.appendChild(this.decrementButton),e.appendChild(this.input),e.appendChild(this.display),e.appendChild(t),this.bindStepControls(),this.bindHoldBehavior(),this.bindInputListeners(),this.observeDisabledState(e),this.updateDisplay(),e}get inputElement(){return this.input}get value(){return this.input.value}set value(e){this.input.value=e,this.updateDisplay()}refresh(){this.updateDisplay()}_onDestroy(){var e;this.clearHoldTimers(),(e=this.disabledObserver)==null||e.disconnect()}bindStepControls(){const e=n=>()=>{if(this.input.disabled)return;const d=this.input.value,s=this.input.getAttribute("step");if(s&&s!=="any")n>0?this.input.stepUp():this.input.stepDown();else{const o=n>0?1:-1,c=Number.parseFloat(this.input.value||"0"),u=Number.isFinite(c)?c+o:o;this.input.value=String(u)}var p;this.input.value!==d&&((p=this.input).dispatchEvent(new Event("input",{bubbles:!0})),p.dispatchEvent(new Event("change",{bubbles:!0}))),this.updateDisplay(),this.input.focus({preventScroll:!0})},t=e(1),a=e(-1),i=(n,d)=>s=>{if(this.suppressClickAfterPointer.get(n))return this.suppressClickAfterPointer.set(n,!1),void s.preventDefault();d()};this.incrementButton.addEventListener("click",i(this.incrementButton,t)),this.decrementButton.addEventListener("click",i(this.decrementButton,a))}bindHoldBehavior(){const e=(t,a)=>{const i=a>0?()=>this.incrementButton.click():()=>this.decrementButton.click();t.addEventListener("pointerdown",s=>{if(s.button===0){s.preventDefault(),this.suppressClickAfterPointer.set(t,!0),this.activePointerId=s.pointerId;try{t.setPointerCapture(s.pointerId)}catch{}i(),this.holdTimeoutId=window.setTimeout(()=>{this.holdIntervalId=window.setInterval(i,80)},380)}});const n=()=>{if(this.activePointerId!==void 0){try{t.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}},d=()=>{this.clearHoldTimers(),n()};t.addEventListener("pointerup",d),t.addEventListener("pointerleave",d),t.addEventListener("pointercancel",d)};e(this.incrementButton,1),e(this.decrementButton,-1)}bindInputListeners(){const e=()=>{this.props.defaultValue=this.input.value,this.updateDisplay()};this.input.addEventListener("input",e),this.input.addEventListener("change",e)}observeDisabledState(e){const t=()=>{const a=this.input.disabled;this.incrementButton.disabled=a,this.decrementButton.disabled=a,e.classList.toggle("is-disabled",a),a?(this.display.classList.remove(se),this.input.style.removeProperty("color"),this.input.style.removeProperty("caretColor")):this.updateDisplay()};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(t),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),t()}updateDisplay(){const e=this.props.formatDisplay;if(!e)return this.display.textContent="",this.display.classList.remove(se),this.input.style.removeProperty("color"),void this.input.style.removeProperty("caretColor");const t=this.input.value,a=Number.parseFloat(t),i=e(Number.isFinite(a)?a:Number.NaN,t,this.input);i?(this.display.textContent=i,this.display.classList.add(se),this.input.style.color="transparent",this.input.style.caretColor="#f8fafc"):(this.display.textContent="",this.display.classList.remove(se),this.input.style.removeProperty("color"),this.input.style.removeProperty("caretColor"))}clearHoldTimers(){this.holdTimeoutId!==void 0&&(window.clearTimeout(this.holdTimeoutId),this.holdTimeoutId=void 0),this.holdIntervalId!==void 0&&(window.clearInterval(this.holdIntervalId),this.holdIntervalId=void 0)}}class te extends G{constructor(e="stack",t=[]){super();h(this,"variant");h(this,"additionalClasses");this.variant=e,this.additionalClasses=t}render(){const e=document.createElement("div"),t=[this.variant==="stack"?W:void 0,this.variant==="stackDense"?ge:void 0,this.variant==="stackCompact"?Ke:void 0,this.variant==="row"?Qt:void 0,this.variant==="section"?et:void 0,...this.additionalClasses].filter(Boolean);return e.classList.add(...t),e}}const ht={neutral:"textmode-export-overlay__status-value--neutral",active:"textmode-export-overlay__status-value--active",alert:"textmode-export-overlay__status-value--alert"};class mt extends G{constructor(e){super();h(this,"props");h(this,"container");h(this,"messageElement");this.props=e}render(){this.container=document.createElement("div"),this.container.classList.add(Kt),this.props.context==="gif"?this.container.classList.add(er):this.props.context==="video"&&this.container.classList.add(tr);const e=document.createElement("span");return e.classList.add(rr),e.textContent=this.props.title,this.messageElement=document.createElement("span"),this.messageElement.classList.add(ar),this.messageElement.textContent=this.props.message,this.applyVariant(this.props.variant??"neutral"),this.container.appendChild(e),this.container.appendChild(this.messageElement),this.container}setMessage(e,t="neutral"){this.messageElement.textContent=e,this.applyVariant(t)}onUpdate(e){this.props=e,this.setMessage(e.message,e.variant??"neutral")}applyVariant(e){this.messageElement.classList.remove(...Object.values(ht)),this.messageElement.classList.add(ht[e])}}class Z extends G{constructor(e){super();h(this,"_config");h(this,"_managedComponents",new Set);this._config=e}_manageComponent(e){return this._managedComponents.add(e),e}_onUnmount(){for(const e of this._managedComponents)e.unmount()}_onDestroy(){for(const e of this._managedComponents)e.destroy();this._managedComponents.clear()}}const ft=300,gt=60,bt=1,gr=0;class xe extends Z{constructor(e){super(e);h(this,"frameCountInput",this._manageComponent(new Y({defaultValue:String(ft),attributes:{min:"1",max:"600",step:"1"}})));h(this,"frameRateInput",this._manageComponent(new Y({defaultValue:String(gt),attributes:{min:"1",max:"60",step:"1"}})));h(this,"scaleInput",this._manageComponent(new Y({defaultValue:String(bt),attributes:{min:"0.1",max:"8",step:"0.1"}})));h(this,"repeatInput",this._manageComponent(new Y({defaultValue:"0",attributes:{min:"0",max:"50",step:"1"},formatDisplay:(e,t)=>Number.isFinite(e)?e===0?"∞":null:t.trim()===""?null:t})));h(this,"status",this._manageComponent(new mt({title:"status",message:"ready to record",variant:"neutral",context:"gif"})));h(this,"recordingState","idle")}render(){const e=document.createElement("div");e.classList.add(W);const t=new te("row");t.mount(e);const a=new U({label:"number of frames",labelFor:"textmode-export-gif-frame-count",variant:"dense"});a.mount(t.root),this.frameCountInput.mount(a.root),this.frameCountInput.inputElement.id="textmode-export-gif-frame-count";const i=new U({label:"frame rate (fps)",labelFor:"textmode-export-gif-frame-rate",variant:"dense"});i.mount(t.root),this.frameRateInput.mount(i.root),this.frameRateInput.inputElement.id="textmode-export-gif-frame-rate";const n=new te("row");n.mount(e);const d=new U({label:"scale",labelFor:"textmode-export-gif-scale",variant:"dense"});d.mount(n.root),this.scaleInput.mount(d.root),this.scaleInput.inputElement.id="textmode-export-gif-scale";const s=new U({label:"loop count",labelFor:"textmode-export-gif-repeat",variant:"dense"});return s.mount(n.root),this.repeatInput.mount(s.root),this.repeatInput.inputElement.id="textmode-export-gif-repeat",this.status.mount(e),e}getOptions(){const e=this._config.defaultOptions??{};return{frameCount:this.safeParseInt(this.frameCountInput.value,e.frameCount??300),frameRate:this.safeParseInt(this.frameRateInput.value,e.frameRate??60),scale:this.safeParseFloat(this.scaleInput.value,e.scale??1),repeat:this.safeParseInt(this.repeatInput.value,e.repeat??0)}}reset(){this.recordingState="idle",this.applyDefaults(),this.setRecordingState("idle")}validate(){const e=Number.parseInt(this.frameCountInput.value,10),t=Number.parseInt(this.frameRateInput.value,10),a=Number.parseFloat(this.scaleInput.value);return Number.isFinite(e)&&e>0&&Number.isFinite(t)&&t>0&&Number.isFinite(a)&&a>0}isRecording(){return this.recordingState==="recording"||this.recordingState==="encoding"}setRecordingState(e,t){this.recordingState=e;const a=e==="recording"||e==="encoding";switch(this.frameCountInput.inputElement.disabled=a,this.frameRateInput.inputElement.disabled=a,this.scaleInput.inputElement.disabled=a,this.repeatInput.inputElement.disabled=a,e){case"recording":if(t!=null&&t.totalFrames){const i=t.frameIndex??0;this.status.setMessage(`recording ${i}/${t.totalFrames}`,"active")}else this.status.setMessage("recording…","active");break;case"encoding":if(t!=null&&t.totalFrames){const i=t.frameIndex??0;this.status.setMessage(`encoding ${i}/${t.totalFrames}`,"active")}else this.status.setMessage("encoding…","active");break;case"completed":this.status.setMessage("GIF saved successfully","active");break;case"error":this.status.setMessage((t==null?void 0:t.message)??"failed to export GIF","alert");break;default:this.status.setMessage("ready to record","neutral")}}handleProgress(e){if(e.state!=="recording"&&e.state!=="encoding"||!e.totalFrames)e.state==="completed"?this.status.setMessage("GIF saved successfully","active"):e.state==="error"&&this.status.setMessage(e.message??"failed to export GIF","alert");else{const t=e.state==="recording"?"recording":"encoding";this.status.setMessage(`${t} ${e.frameIndex??0}/${e.totalFrames}`,"active")}}applyDefaults(){const e=this._config.defaultOptions??{},t=e.frameCount??ft,a=e.frameRate??gt,i=e.scale??bt,n=e.repeat??gr;this.frameCountInput.value=String(t),this.frameRateInput.value=String(a),this.scaleInput.value=String(i),this.repeatInput.value=String(n),this.frameCountInput.refresh(),this.frameRateInput.refresh(),this.scaleInput.refresh(),this.repeatInput.refresh()}safeParseInt(e,t){const a=Number.parseInt(e,10);return Number.isFinite(a)?a:t}safeParseFloat(e,t){const a=Number.parseFloat(e);return Number.isFinite(a)?a:t}}const le="textmode-export-range-input",br=`${le}__field`,vr=`${le}__tooltip`,we=`${le}__tooltip--visible`,de=(l,r)=>{if(typeof l!="string"||l.length===0)return r;const e=Number.parseFloat(l);return Number.isFinite(e)?e:r};class yr extends G{constructor(e){super();h(this,"props");h(this,"input");h(this,"tooltip");h(this,"hoverActive",!1);h(this,"focusActive",!1);h(this,"pointerActive",!1);h(this,"suppressFocusFromPointer",!1);h(this,"activePointerId");h(this,"disabledObserver");h(this,"resizeObserver");this.props=e}render(){const e=document.createElement("div");return e.className=le,this.input=document.createElement("input"),this.input.type="range",this.input.value=this.props.defaultValue,Object.assign(this.input,this.props.attributes),this.input.className=br,this.tooltip=document.createElement("div"),this.tooltip.className=vr,e.appendChild(this.input),e.appendChild(this.tooltip),this.bindEvents(e),this.updateTooltip(),this.syncDisabledState(e),e}get inputElement(){return this.input}get value(){return this.input.value}set value(e){this.input.value=e,this.updateTooltip()}_onDestroy(){var e,t;(e=this.disabledObserver)==null||e.disconnect(),(t=this.resizeObserver)==null||t.disconnect()}bindEvents(e){this.input.addEventListener("pointerenter",()=>{this.hoverActive=!0,this.refreshTooltipVisibility()}),this.input.addEventListener("pointerleave",()=>{this.hoverActive=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("focus",()=>{let a=!1;try{a=this.input.matches(":focus-visible")}catch{a=!this.suppressFocusFromPointer}this.suppressFocusFromPointer||!a||this.input.disabled?this.focusActive=!1:this.focusActive=!0,this.suppressFocusFromPointer=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("blur",()=>{this.focusActive=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("pointerdown",a=>{this.pointerActive=!0,this.suppressFocusFromPointer=!0,this.hoverActive=!0,this.refreshTooltipVisibility();try{this.input.setPointerCapture(a.pointerId),this.activePointerId=a.pointerId}catch{this.activePointerId=void 0}});const t=()=>{this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.hoverActive=this.input.matches(":hover"),this.releasePointerCapture(),this.refreshTooltipVisibility()};this.input.addEventListener("pointerup",t),this.input.addEventListener("pointercancel",t),this.input.addEventListener("lostpointercapture",t),this.input.addEventListener("input",()=>{(this.hoverActive||this.focusActive||this.pointerActive)&&this.updateTooltip(),this.props.defaultValue=this.input.value}),this.input.addEventListener("change",()=>{this.pointerActive||this.updateTooltip(),this.props.defaultValue=this.input.value}),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(()=>{this.tooltip.classList.contains(we)&&this.updateTooltipPosition()}),this.resizeObserver.observe(e))}refreshTooltipVisibility(){const e=(this.hoverActive||this.focusActive||this.pointerActive)&&!this.input.disabled;e&&this.updateTooltip(),this.tooltip.classList.toggle(we,e)}syncDisabledState(e){const t=()=>{const a=this.input.disabled;e.classList.toggle("is-disabled",a),a&&(this.hoverActive=!1,this.focusActive=!1,this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.releasePointerCapture(),this.tooltip.classList.remove(we))};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(t),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),t()}releasePointerCapture(){if(this.activePointerId!==void 0){try{this.input.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}}updateTooltip(){this.updateTooltipContent(),this.updateTooltipPosition()}updateTooltipContent(){const e=this.props.formatValue??(a=>`${a}`),t=this.getCurrentValue();this.tooltip.textContent=e(t,this.input)}updateTooltipPosition(){const e=this.getMin(),t=this.getMax(),a=((d,s,p)=>Math.min(p,Math.max(s,d)))(this.getCurrentValue(),e,t),i=t-e,n=i===0?0:(a-e)/i;this.tooltip.style.left=100*n+"%"}getMin(){return de(this.input.min,0)}getMax(){return de(this.input.max,100)}getCurrentValue(){return de(this.input.value,de(this.props.defaultValue,0))}}function xr(l){return`${(function(e){if(!Number.isFinite(e))return"default quality";const t=Math.max(0,Math.min(1,e));return t>=.995?"near-lossless":t>=.98?"maximum detail":t>=.88?"ultra quality":t>=.7?"high quality":t>=.5?"balanced":t>=.25?"compact":t>=.1?"lightweight":"draft"})(l)} (quality ≈ ${l.toFixed(3)})`}class _e extends Z{constructor(e){super(e);h(this,"frameRateInput",this._manageComponent(new Y({defaultValue:String(60),attributes:{min:String(1),max:String(60),step:"1"},formatDisplay:e=>Number.isFinite(e)?`${e} fps`:null})));h(this,"frameCountInput",this._manageComponent(new Y({defaultValue:String(480),attributes:{min:String(1),max:String(3600),step:"1"}})));h(this,"qualityInput",this._manageComponent(new yr({defaultValue:String(.7),attributes:{min:String(0),max:String(1),step:"0.001"},formatValue:e=>xr(e)})));h(this,"status",this._manageComponent(new mt({title:"status",message:"ready to record",variant:"neutral",context:"video"})));h(this,"recordingState","idle")}render(){const e=document.createElement("div");e.classList.add(W);const t=new te("row");t.mount(e);const a=new U({label:"number of frames",labelFor:"textmode-export-video-frame-count",variant:"compact"});a.mount(t.root),this.frameCountInput.mount(a.root),this.frameCountInput.inputElement.id="textmode-export-video-frame-count";const i=new U({label:"frame rate (fps)",labelFor:"textmode-export-video-frame-rate",variant:"compact"});i.mount(t.root),this.frameRateInput.mount(i.root),this.frameRateInput.inputElement.id="textmode-export-video-frame-rate";const n=new U({label:"quality",labelFor:"textmode-export-video-quality",variant:"full"});return n.mount(e),this.qualityInput.mount(n.root),this.qualityInput.inputElement.id="textmode-export-video-quality",this.status.mount(e),e}getOptions(){const e=this._config.defaultOptions??{},t=Number.parseInt(this.frameCountInput.value,10),a=Number.parseFloat(this.frameRateInput.value),i=Number.parseFloat(this.qualityInput.value);return{frameCount:Number.isFinite(t)?t:e.frameCount??480,frameRate:Number.isFinite(a)?a:e.frameRate??60,quality:Number.isFinite(i)?i:e.quality??.7}}reset(){this.recordingState="idle",this.applyDefaults(),this.status.setMessage("ready to record","neutral")}validate(){const e=Number.parseInt(this.frameCountInput.value,10),t=Number.parseFloat(this.frameRateInput.value);return Number.isFinite(e)&&e>=1&&Number.isFinite(t)&&t>=1}isRecording(){return this.recordingState==="recording"}setRecordingState(e,t){this.recordingState=e;const a=e==="recording";this.frameCountInput.inputElement.disabled=a,this.frameRateInput.inputElement.disabled=a,this.qualityInput.inputElement.disabled=a,this.syncStatus(e,t)}handleProgress(e){this.syncStatus(e.state,e)}syncStatus(e,t){switch(e){case"recording":{const a=(t==null?void 0:t.frameIndex)??0,i=(t==null?void 0:t.totalFrames)??this.resolvePlannedFrameCount();if(i){const n=Math.min(Math.max(0,Math.round(a)),i);this.status.setMessage(`recording ${n}/${i} frames`,"active")}else this.status.setMessage(`recording ${Math.max(0,Math.round(a))} frames`,"active");break}case"completed":this.status.setMessage("saved to disk","active");break;case"error":this.status.setMessage(t!=null&&t.message?`error: ${t.message}`:"recording failed","alert");break;default:this.status.setMessage("ready to record","neutral")}}resolvePlannedFrameCount(){const e=Number.parseInt(this.frameCountInput.value,10);return Number.isFinite(e)&&e>0?Math.round(e):void 0}applyDefaults(){const e=this._config.defaultOptions??{},t=e.frameCount??480,a=e.frameRate??60,i=e.quality??.7;this.frameCountInput.value=String(t),this.frameRateInput.value=String(a),this.qualityInput.value=String(i),this.frameCountInput.refresh(),this.frameRateInput.refresh()}}class wr{constructor(r,e,t,a,i){h(this,"_textmodifier");h(this,"_state");h(this,"_events");h(this,"_exportService");h(this,"_clipboardService");h(this,"_definitions");h(this,"_formats",new Map);h(this,"_eventUnsubscribers",[]);h(this,"_shadowHost");h(this,"_shadowRoot");h(this,"_overlayElement");h(this,"_optionsContainer");h(this,"_copyButtonContainer");h(this,"_positionService");h(this,"_header",new ye);h(this,"_formatField",new U({label:"export format",labelFor:"textmode-export-format",variant:"full"}));h(this,"_formatSelect",new Q({id:"textmode-export-format",options:[]}));h(this,"_exportButton",new ct({label:"download file",fullWidth:!0,variant:"primary"}));h(this,"_copyButton",new ct({label:"copy to clipboard",fullWidth:!0,variant:"primary"}));h(this,"_currentFormat");h(this,"_currentBlade");h(this,"_handleFormatSelectChange",()=>{this._handleFormatChange(this._formatSelect.value)});h(this,"_handleExportClickSafe",()=>{this._handleExportClick().catch(r=>{console.error("[textmode-export] Export failed",r)})});h(this,"_handleCopyClickSafe",()=>{this._handleCopyClick().catch(r=>{console.error("[textmode-export] Copy failed",r)})});this._textmodifier=r,this._state=t,this._events=a,this._exportService=new ur(e,a),this._clipboardService=new cr(e),this._definitions=i,this._currentFormat=t.snapshot.format,this._initializeFormatMap(),this._registerEventHandlers()}$mount(){this._createOverlay(),this._renderStaticContent(),this._positionService=new pr(this._textmodifier,this._shadowHost),this._positionService.bind(),this._switchFormat(this._currentFormat)}show(){this._shadowHost&&(this.refreshLayerTargets(),this._shadowHost.style.display="")}hide(){this._shadowHost&&(this._shadowHost.style.display="none")}toggle(){this.isVisible()?this.hide():this.show()}isVisible(){return!!this._shadowHost&&this._shadowHost.style.display!=="none"}refreshLayerTargets(){this._currentBlade&&typeof this._currentBlade.blade.refreshLayerTargets=="function"&&this._currentBlade.blade.refreshLayerTargets()}$dispose(){var r,e;this._formatSelect.isMounted()&&this._formatSelect.selectElement.removeEventListener("change",this._handleFormatSelectChange),this._exportButton.isMounted()&&this._exportButton.buttonElement.removeEventListener("click",this._handleExportClickSafe),this._copyButton.isMounted()&&this._copyButton.buttonElement.removeEventListener("click",this._handleCopyClickSafe);for(const t of this._eventUnsubscribers)t();this._eventUnsubscribers.length=0,this._events.$clear();for(const t of this._formats.values())t.blade.destroy();this._formats.clear(),this._currentBlade=void 0,(r=this._shadowHost)!=null&&r.isConnected&&this._shadowHost.remove(),(e=this._positionService)==null||e.dispose()}_initializeFormatMap(){for(const r of this._definitions){const e=r.createBlade();this._formats.set(r.format,{definition:r,blade:e,initialized:!1})}}_createOverlay(){this._shadowHost=document.createElement("div"),this._shadowHost.dataset.plugin="textmode-export-overlay-host",this._shadowHost.style.cssText="position: absolute; top: 0; left: 0; pointer-events: none; z-index: 2147483647;",this._shadowRoot=this._shadowHost.attachShadow({mode:"open"});const r=document.createElement("style");r.textContent=`@layer textmode-export-overlay{.textmode-export-overlay{--overlay-bg: rgba(20, 20, 20, .8);--overlay-surface: rgba(40, 40, 40, .9);--overlay-border: rgba(255, 255, 255, .14);--overlay-border-strong: rgba(255, 255, 255, .2);--overlay-border-focus: rgba(160, 160, 160, .6);--overlay-focus-shadow: 0 0 0 1px rgba(140, 140, 140, .28);--overlay-text: #ffffff;--overlay-muted: rgba(200, 200, 200, .74);--overlay-radius: .75rem;--overlay-stack-gap: .55rem;position:absolute;top:0;left:0;display:flex;flex-direction:column;gap:var(--overlay-stack-gap);min-width:236px;max-width:236px;padding:.65rem .8rem;background:var(--overlay-bg);color:var(--overlay-text);border-radius:var(--overlay-radius);border:1px solid var(--overlay-border);box-shadow:0 12px 28px #0000004d;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:.82rem;line-height:1.35;pointer-events:auto;z-index:2147483647}.textmode-export-overlay *{box-sizing:border-box}.textmode-export-overlay__header{display:flex;flex-direction:column;gap:.4rem}.textmode-export-overlay__header-title-row{display:flex;align-items:center;justify-content:space-between;gap:.4rem}.textmode-export-overlay__header-links{display:inline-flex;align-items:center;gap:.3rem}.textmode-export-overlay__support-link{display:inline-flex;align-items:center;justify-content:center;padding:.2rem;border-radius:.45rem;border:1px solid transparent;color:#d7d7d7d1;background:transparent;text-decoration:none;line-height:0;transition:background .18s ease,color .18s ease,transform .18s ease,border-color .18s ease}.textmode-export-overlay__support-link:hover{color:#fff;background:#5a5a5a4d;border-color:#c8c8c824}.textmode-export-overlay__support-link:focus-visible{outline:none;border-color:var(--overlay-border-focus);box-shadow:var(--overlay-focus-shadow)}.textmode-export-overlay__support-icon,.textmode-export-overlay__link-icon{display:block;width:1rem;height:1rem}.textmode-export-overlay__stack{display:flex;flex-direction:column;gap:var(--overlay-stack-gap)}.textmode-export-overlay__stack--dense{gap:.3rem}.textmode-export-overlay__stack--compact{gap:.45rem}.textmode-export-overlay__section{display:flex;flex-direction:column;gap:.4rem}.textmode-export-overlay__title{font-size:.92rem;font-weight:600}.textmode-export-overlay__divider{width:100%;height:1px;background:#ffffff29;margin-top:.25rem}.textmode-export-overlay__label{font-weight:500;opacity:.9}.textmode-export-overlay__checkbox{display:flex;align-items:center;gap:.5rem}.textmode-export-overlay__checkbox input[type=checkbox]{width:1rem;height:1rem;accent-color:rgba(100,100,100,.9)}.textmode-export-overlay__row{display:flex;gap:.6rem;flex-wrap:wrap;align-items:flex-start;width:100%}.textmode-export-overlay__field{display:flex;flex-direction:column;gap:.3rem;flex:1 1 120px;min-width:120px}.textmode-export-overlay__field--compact{flex:1 1 100px;min-width:100px}.textmode-export-overlay__field--dense{flex:1 1 90px;min-width:90px}.textmode-export-overlay__field--channel{flex:1 1 0;min-width:0}.textmode-export-overlay__field--full{width:100%;flex:1 1 100%}.textmode-export-overlay__input,.textmode-export-overlay select.textmode-export-overlay__input,.textmode-export-overlay input.textmode-export-overlay__input{width:100%;padding:.35rem .5rem;border-radius:.4rem;border:1px solid var(--overlay-border-strong);background:var(--overlay-surface);color:var(--overlay-text);font:inherit;line-height:1.35;transition:border-color .18s ease,box-shadow .18s ease,background .18s ease}.textmode-export-overlay select.textmode-export-overlay__input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='rgba(200, 200, 200, 0.74)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right .5rem center;background-size:1rem;padding-right:2rem}.textmode-export-overlay__input:focus{outline:none;border-color:var(--overlay-border-focus);box-shadow:var(--overlay-focus-shadow);background:#2d2f42eb}.textmode-export-overlay__input::placeholder{color:var(--overlay-muted);opacity:.7}.textmode-export-overlay__muted{font-size:.75rem;opacity:.7;display:block}.textmode-export-overlay__button{display:inline-flex;align-items:center;justify-content:center;gap:.35rem;border-radius:.45rem;border:none;font-weight:600;padding:.45rem .7rem;cursor:pointer;transition:background .2s ease,transform .2s ease,box-shadow .2s ease}.textmode-export-overlay__button--primary{background:#505050;color:#fff}.textmode-export-overlay__button--secondary{background:#606060;color:#fff}.textmode-export-overlay__button--full{width:100%}.textmode-export-overlay__button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 7px 18px #00000073}.textmode-export-overlay__button--primary:hover:not(:disabled){background:#404040}.textmode-export-overlay__button--secondary:hover:not(:disabled){background:#4a4a4a}.textmode-export-overlay__button:disabled{cursor:default;opacity:.55;transform:none;box-shadow:none}.textmode-export-overlay__status{display:flex;flex-direction:column;gap:.25rem;padding:.45rem .55rem;border-radius:.45rem;border:1px solid rgba(110,110,110,.22);background:#4646462e}.textmode-export-overlay__status--gif{background:#5050501f;border-color:#78787840}.textmode-export-overlay__status--video{background:#4646461f;border-color:#6e6e6e40}.textmode-export-overlay__status-title{font-weight:600;font-size:.75rem;opacity:.85;text-transform:uppercase;letter-spacing:.04em}.textmode-export-overlay__status-value{font-size:.82rem;color:#dedede;transition:color .18s ease}.textmode-export-overlay__status-value--neutral{color:#cfcfcf}.textmode-export-overlay__status-value--active{color:#f5f5f5}.textmode-export-overlay__status-value--alert{color:#b8b8b8}.textmode-export-number-input,.textmode-export-overlay .textmode-export-number-input{display:flex;align-items:stretch;width:100%;background:var(--overlay-surface);border:1px solid var(--overlay-border-strong);border-radius:.4rem;overflow:hidden;transition:border-color .18s ease,box-shadow .18s ease,background .18s ease;position:relative}.textmode-export-number-input:focus-within{border-color:var(--overlay-border-focus);box-shadow:var(--overlay-focus-shadow)}.textmode-export-number-input.is-disabled{opacity:.55}.textmode-export-number-input__field{flex:1 1 auto;min-width:0;border:none;background:transparent;color:var(--overlay-text);font:inherit;padding:.35rem .5rem;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.textmode-export-number-input__field::-webkit-outer-spin-button,.textmode-export-number-input__field::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.textmode-export-number-input__field:focus{outline:none}.textmode-export-number-input__controls{display:flex;flex-direction:column;border-left:1px solid rgba(255,255,255,.12);min-width:1.6rem}.textmode-export-number-input__control{display:flex;align-items:center;justify-content:center;width:100%;flex:1;border:none;background:#32323299;color:#d0d0d0;font-size:.68rem;line-height:1;cursor:pointer;transition:background .15s ease,color .15s ease;padding:0}.textmode-export-number-input__control:hover:not(:disabled){background:#5a5a5ad9;color:#fff}.textmode-export-number-input__control:disabled{cursor:default;opacity:.4;background:#28282880;color:#c8c8c866}.textmode-export-number-input:focus-within .textmode-export-number-input__control{background:#3c3c3cbf;color:#e8e8e8}.textmode-export-number-input__display{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;padding:.4rem .55rem;pointer-events:none;color:#f8fafc;opacity:0;transition:opacity .14s ease}.textmode-export-number-input__display--visible{opacity:1}.textmode-export-range-input{position:relative;width:100%}.textmode-export-range-input.is-disabled{opacity:.55}.textmode-export-range-input__field{width:100%;height:1.4rem;padding:0;margin:0;background:transparent;cursor:pointer;-moz-appearance:none;appearance:none;-webkit-appearance:none}.textmode-export-range-input__field::-webkit-slider-thumb{width:12px;height:12px;margin-top:-3.5px;-webkit-appearance:none;border-radius:50%;background:#a0a0a0;border:2px solid #303030;box-shadow:0 0 0 2px #00000059}.textmode-export-range-input__field::-webkit-slider-runnable-track{height:5px;border-radius:999px;background:linear-gradient(90deg,#8c8c8cd9,#646464a6)}.textmode-export-range-input__field::-moz-range-thumb{width:12px;height:12px;border-radius:50%;background:#a0a0a0;border:2px solid #303030;margin-top:-3.5px}.textmode-export-range-input__field::-moz-range-track{height:5px;border-radius:999px;background:linear-gradient(90deg,#8c8c8cd9,#646464a6)}.textmode-export-range-input__tooltip{position:absolute;top:-1.5rem;left:0;transform:translate(-50%);padding:.2rem .35rem;border-radius:.35rem;background:#1e1e1ee0;color:#f8fafc;font-size:.68rem;line-height:1;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.textmode-export-range-input__tooltip--visible{opacity:1}}`,this._shadowRoot.appendChild(r),this._overlayElement=document.createElement("div"),this._overlayElement.dataset.plugin="textmode-export-overlay",this._overlayElement.classList.add(qt,W),this._shadowRoot.appendChild(this._overlayElement),document.body.appendChild(this._shadowHost)}_renderStaticContent(){this._header.mount(this._overlayElement);const r=document.createElement("div");r.classList.add(et),this._overlayElement.appendChild(r),this._formatField.mount(r),this._prepareFormatOptions(),this._formatSelect.mount(this._formatField.root),this._formatSelect.selectElement.addEventListener("change",this._handleFormatSelectChange),this._optionsContainer=document.createElement("div"),this._optionsContainer.classList.add(W,Ke),this._overlayElement.appendChild(this._optionsContainer),this._exportButton.mount(this._overlayElement),this._exportButton.buttonElement.addEventListener("click",this._handleExportClickSafe),this._copyButtonContainer=document.createElement("div"),this._copyButtonContainer.classList.add(W,ge),this._overlayElement.appendChild(this._copyButtonContainer),this._copyButton.mount(this._copyButtonContainer),this._copyButton.buttonElement.dataset.defaultLabel="copy to clipboard",this._copyButton.buttonElement.addEventListener("click",this._handleCopyClickSafe)}_prepareFormatOptions(){const r=this._definitions.map(e=>({value:e.format,label:e.label}));this._formatSelect.update({options:r,defaultValue:this._currentFormat})}_registerEventHandlers(){this._eventUnsubscribers.push(this._events.$on("export:request",({format:r})=>{r===this._currentFormat&&(this._state.$set({isBusy:!0,error:void 0}),this._updateExportButton())}),this._events.$on("export:success",({format:r})=>{if(r===this._currentFormat){const e={isBusy:!1};r==="gif"&&(e.gifProgress=void 0),r==="video"&&(e.videoProgress=void 0),this._state.$set(e),this._updateExportButton()}}),this._events.$on("export:error",({format:r,error:e})=>{r===this._currentFormat&&(this._state.$set({isBusy:!1,error:e}),this._updateExportButton())}),this._events.$on("export:progress",({format:r,progress:e})=>{var t,a;if(e){if(r==="gif"&&((t=this._currentBlade)==null?void 0:t.blade)instanceof xe){const i=e;this._state.$set({gifProgress:i}),this._currentBlade.blade.handleProgress(i)}else if(r==="video"&&((a=this._currentBlade)==null?void 0:a.blade)instanceof _e){const i=e;this._state.$set({videoProgress:i}),this._currentBlade.blade.handleProgress(i)}this._updateExportButton()}}))}_handleFormatChange(r){this._currentFormat=r,this._state.$set({format:r}),this._switchFormat(r),this._events.$emit("format:change",{format:r})}_switchFormat(r){var t;const e=this._formats.get(r);if(!e)throw new Error(`Unknown export format: ${r}`);this._currentBlade&&this._currentBlade.blade.unmount(),this._optionsContainer.innerHTML="",e.blade.mount(this._optionsContainer),e.initialized||(e.blade.reset(),e.initialized=!0),this._currentBlade=e,this._formatSelect.value=r,this.refreshLayerTargets(),this._updateCopyButtonState(),this._updateExportButton(),(t=this._positionService)==null||t.scheduleUpdate()}_updateCopyButtonState(){var e;const r=((e=this._currentBlade)==null?void 0:e.definition.supportsClipboard)??!1;this._copyButtonContainer.style.display=r?"flex":"none",this._copyButton.setDisabled(!r)}async _handleExportClick(){if(!this._currentBlade)return;const r=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions();if(this._currentBlade.blade.validate()){if(r==="gif"){const t=this._currentBlade.blade;if(t.isRecording())return;t.setRecordingState("recording");try{await this._exportService.$requestExport("gif",e,{onGIFProgress:a=>{t.setRecordingState(a.state,a)}})}catch(a){throw t.setRecordingState("error"),a}return void window.setTimeout(()=>{t.setRecordingState("idle"),this._updateExportButton()},1600)}if(r==="video"){const t=this._currentBlade.blade;if(t.isRecording())return;t.setRecordingState("recording");try{await this._exportService.$requestExport("video",e,{onVideoProgress:a=>{t.setRecordingState(a.state,a)}})}catch(a){throw t.setRecordingState("error"),a}return void window.setTimeout(()=>{t.setRecordingState("idle"),this._updateExportButton()},1600)}this._exportButton.setDisabled(!0),this._exportButton.setLabel("exporting…");try{await this._exportService.$requestExport(r,e)}finally{this._exportButton.setDisabled(!1),this._exportButton.setLabel("download file")}}else console.warn("[textmode-export] Export options failed validation")}async _handleCopyClick(){if(!this._currentBlade||!this._currentBlade.definition.supportsClipboard)return;const r=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions(),t=this._copyButton.buttonElement.dataset.defaultLabel??"copy to clipboard";this._copyButton.setDisabled(!0),this._copyButton.setLabel("copying…");try{switch(r){case"txt":await this._clipboardService.$copy("txt",e);break;case"json":await this._clipboardService.$copy("json",e);break;case"svg":await this._clipboardService.$copy("svg",e);break;case"image":await this._clipboardService.$copy("image",e);break;default:return}this._copyButton.setLabel("copied!")}catch(a){console.error("[textmode-export] Failed to copy to clipboard",a),this._copyButton.setLabel("copy failed!")}finally{window.setTimeout(()=>{this._copyButton.setLabel(t),this._copyButton.setDisabled(!1)},1200)}}_updateExportButton(){if(!this._currentBlade)return;const r=this._currentBlade.definition.format;if(r==="gif"&&this._currentBlade.blade instanceof xe){const t=this._currentBlade.blade,a=this._state.snapshot.gifProgress;if(t.isRecording())if(this._exportButton.setDisabled(!0),a==null?void 0:a.totalFrames){const i=a.frameIndex??0,n=a.state==="encoding"?"encoding":"recording";this._exportButton.setLabel(`${n} ${i}/${a.totalFrames}`)}else{const i=(a==null?void 0:a.state)==="encoding"?"encoding":"recording";this._exportButton.setLabel(`${i}…`)}else this._exportButton.setDisabled(!1),this._exportButton.setLabel("start recording");return}if(r==="video"&&this._currentBlade.blade instanceof _e){const t=this._currentBlade.blade,a=this._state.snapshot.videoProgress;if(t.isRecording())if(this._exportButton.setDisabled(!0),a==null?void 0:a.totalFrames){const i=a.frameIndex??0;this._exportButton.setLabel(`recording ${i}/${a.totalFrames} frames`)}else this._exportButton.setLabel("recording…");else this._exportButton.setDisabled(!1),this._exportButton.setLabel("start recording");return}const e=this._state.snapshot.isBusy;this._exportButton.setDisabled(e),this._exportButton.setLabel(e?"exporting…":"download file")}}class _r{constructor(){h(this,"_listeners",{})}_getPool(r){const e=this._listeners[r];if(e)return e;const t=new Set;return this._listeners[r]=t,t}$on(r,e){const t=this._getPool(r);return t.add(e),()=>{t.delete(e),t.size===0&&delete this._listeners[r]}}$emit(r,e){const t=this._listeners[r];if(t)for(const a of[...t])try{a(e)}catch(i){console.error("[textmode-export] Event handler failed",i)}}$clear(){for(const r of Object.keys(this._listeners))delete this._listeners[r]}}class Cr{constructor(r){h(this,"_state");h(this,"_listeners",new Set);this._state=r}get snapshot(){return Object.freeze({...this._state})}$set(r){this._state=Object.assign({},this._state,r);const e=this.snapshot;for(const t of[...this._listeners])try{t(e)}catch(a){console.error("[textmode-export] State listener failed",a)}}$subscribe(r){return this._listeners.add(r),r(this.snapshot),()=>{this._listeners.delete(r)}}$reset(r){this._state=r;const e=this.snapshot;for(const t of[...this._listeners])t(e)}}class ce extends G{constructor(e){super();h(this,"props");h(this,"checkbox");h(this,"labelElement");h(this,"handleChange",()=>{this.props.defaultChecked=this.checkbox.checked});this.props=e}render(){this.labelElement=document.createElement("label"),this.labelElement.classList.add(Zt),this.checkbox=document.createElement("input"),this.checkbox.type="checkbox",this.props.id&&(this.checkbox.id=this.props.id),this.checkbox.checked=!!this.props.defaultChecked,this.checkbox.addEventListener("change",this.handleChange);const e=document.createElement("span");return e.textContent=this.props.label,this.labelElement.htmlFor=this.props.id??"",this.labelElement.appendChild(this.checkbox),this.labelElement.appendChild(e),this.labelElement}get inputElement(){return this.checkbox}get checked(){return this.checkbox.checked}set checked(e){this.checkbox.checked=e}_onUnmount(){this.checkbox.removeEventListener("change",this.handleChange)}onUpdate(e){this.props=e,e.id&&(this.checkbox.id=e.id,this.labelElement.htmlFor=e.id),this.checkbox.checked=!!e.defaultChecked,this.labelElement.lastElementChild&&(this.labelElement.lastElementChild.textContent=e.label)}}class Er extends G{constructor(e){super();h(this,"props");h(this,"input");h(this,"handleInput",()=>{this.props.defaultValue=this.input.value});this.props=e}render(){return this.input=document.createElement("input"),this.input.type="text",this.input.classList.add(st),this.props.id&&(this.input.id=this.props.id),this.props.maxLength!==void 0&&(this.input.maxLength=this.props.maxLength),this.props.defaultValue!==void 0&&(this.input.value=this.props.defaultValue),this.input.addEventListener("input",this.handleInput),this.input}get inputElement(){return this.input}get value(){return this.input.value}set value(e){this.input.value=e}_onUnmount(){this.input.removeEventListener("input",this.handleInput)}onUpdate(e){this.props=e,e.id&&(this.input.id=e.id),e.maxLength!==void 0&&(this.input.maxLength=e.maxLength),e.defaultValue!==void 0&&(this.input.value=e.defaultValue)}}class Ce extends G{constructor(e){super();h(this,"provider");h(this,"field");h(this,"select");this.provider=e.provider,this.field=new U({label:"layer",labelFor:e.id,variant:"full"}),this.select=new Q({id:e.id,options:[],defaultValue:e.provider.getDefaultId()})}render(){const e=document.createElement("div");return this.field.mount(e),this.refresh(),this.select.mount(this.field.root),e}get layer(){const e=this.provider.getLayerById(this.select.value);if(e)return e;const t=this.provider.getDefaultId();return this.select.value=t,this.provider.getLayerById(t)}setDisabled(e){this.select.selectElement.disabled=e}refresh(){const e=this.provider.getOptions(),t=this.select.isMounted()?this.select.value:this.provider.getDefaultId(),a=e.some(i=>i.id===t)?t:this.provider.getDefaultId();this.select.update({options:e.map(i=>({value:i.id,label:i.label})),defaultValue:a}),this.select.value=a}_onUnmount(){this.select.unmount(),this.field.unmount()}_onDestroy(){this.select.destroy(),this.field.destroy()}}class kr extends Z{constructor(e){super(e);h(this,"layerTarget");h(this,"trailingSpaces",this._manageComponent(new ce({label:"preserve trailing spaces",defaultChecked:!1})));h(this,"emptyCharacter",this._manageComponent(new Er({id:"textmode-export-empty-character",defaultValue:" ",maxLength:1})));e.layerTargetProvider&&(this.layerTarget=this._manageComponent(new Ce({id:"textmode-export-txt-layer",provider:e.layerTargetProvider})))}render(){var a;const e=document.createElement("div");e.classList.add(W),(a=this.layerTarget)==null||a.mount(e),this.trailingSpaces.mount(e);const t=new U({label:"empty character",labelFor:"textmode-export-empty-character",variant:"full"});return t.mount(e),this.emptyCharacter.mount(t.root),e}getOptions(){var a;const e=this._config.defaultOptions??{},t=this.emptyCharacter.value||e.emptyCharacter||" ";return{layer:(a=this.layerTarget)==null?void 0:a.layer,preserveTrailingSpaces:this.trailingSpaces.checked,emptyCharacter:t}}reset(){this.applyDefaults()}validate(){return this.emptyCharacter.value.length<=1}refreshLayerTargets(){var e;(e=this.layerTarget)==null||e.refresh()}applyDefaults(){const e=this._config.defaultOptions??{};this.trailingSpaces.checked=e.preserveTrailingSpaces??!1,this.emptyCharacter.value=e.emptyCharacter??" "}}class Br extends Z{constructor(e){super(e);h(this,"layerTarget");h(this,"layerTargetContainer");h(this,"target",this._manageComponent(new Q({id:"textmode-export-json-target",options:[{value:"selected",label:"selected layer"},{value:"all",label:"all layers"}],defaultValue:"selected"})));h(this,"prettyPrint",this._manageComponent(new ce({id:"textmode-export-json-pretty",label:"pretty print",defaultChecked:!0})));h(this,"includeMetadata",this._manageComponent(new ce({id:"textmode-export-json-metadata",label:"include metadata",defaultChecked:!0})));h(this,"colorMode",this._manageComponent(new Q({id:"textmode-export-json-color-mode",options:[{value:"hex",label:"hex"},{value:"rgba",label:"rgba"}],defaultValue:"hex"})));e.layerTargetProvider&&(this.layerTarget=this._manageComponent(new Ce({id:"textmode-export-json-layer",provider:e.layerTargetProvider})))}render(){const e=document.createElement("div");e.classList.add(W);const t=new U({label:"target",labelFor:"textmode-export-json-target",variant:"full"});t.mount(e),this.target.mount(t.root),this.target.selectElement.addEventListener("change",()=>this.updateLayerTargetVisibility()),this.layerTarget&&(this.layerTargetContainer=document.createElement("div"),this.layerTarget.mount(this.layerTargetContainer),e.appendChild(this.layerTargetContainer)),this.prettyPrint.mount(e),this.includeMetadata.mount(e);const a=new U({label:"color mode",labelFor:"textmode-export-json-color-mode",variant:"full"});return a.mount(e),this.colorMode.mount(a.root),this.updateLayerTargetVisibility(),e}getOptions(){var t;const e=this.target.value;return{target:e,layer:e==="selected"?(t=this.layerTarget)==null?void 0:t.layer:void 0,pretty:this.prettyPrint.checked,includeMetadata:this.includeMetadata.checked,colorMode:this.colorMode.value}}reset(){this.applyDefaults()}validate(){return!0}refreshLayerTargets(){var e;(e=this.layerTarget)==null||e.refresh()}applyDefaults(){const e=this._config.defaultOptions??{};this.target.value=e.target??"selected",this.prettyPrint.checked=typeof e.pretty=="number"?e.pretty>0:e.pretty??!0,this.includeMetadata.checked=e.includeMetadata??!0,this.colorMode.value=e.colorMode??"hex",this.updateLayerTargetVisibility()}updateLayerTargetVisibility(){var t;const e=this.target.value==="selected";this.layerTargetContainer&&(this.layerTargetContainer.style.display=e?"":"none"),(t=this.layerTarget)==null||t.setDisabled(!e)}}class Ir extends Z{constructor(e){super(e);h(this,"formatSelect",this._manageComponent(new Q({id:"textmode-export-image-format",options:[{value:"png",label:`PNG (${Ct})`},{value:"jpg",label:`JPG (${Et})`},{value:"webp",label:`WEBP (${kt})`}],defaultValue:"png"})));h(this,"scaleInput",this._manageComponent(new Y({defaultValue:"1",attributes:{min:"0.1",step:"0.1"}})))}render(){const e=document.createElement("div");e.classList.add(W);const t=new te("row");t.mount(e);const a=new U({label:"image format",labelFor:"textmode-export-image-format",variant:"compact"});a.mount(t.root),this.formatSelect.mount(a.root);const i=new U({label:"scale",labelFor:"textmode-export-image-scale",variant:"dense"});return i.mount(t.root),this.scaleInput.mount(i.root),this.scaleInput.inputElement.id="textmode-export-image-scale",e}getOptions(){var t;const e=Number.parseFloat(this.scaleInput.value);return{format:this.formatSelect.value,scale:Number.isFinite(e)?e:((t=this._config.defaultOptions)==null?void 0:t.scale)??1}}reset(){this.applyDefaults(),this.scaleInput.refresh()}validate(){const e=Number.parseFloat(this.scaleInput.value);return Number.isFinite(e)&&e>0}applyDefaults(){const e=this._config.defaultOptions??{};this.formatSelect.value=e.format??"png";const t=e.scale??1;this.scaleInput.value=String(t)}}class Mr extends Z{constructor(e){super(e);h(this,"layerTarget");h(this,"includeBackground",this._manageComponent(new ce({id:"textmode-export-svg-include-backgrounds",label:"include cell backgrounds",defaultChecked:!0})));h(this,"drawMode",this._manageComponent(new Q({id:"textmode-export-svg-draw-mode",options:[{value:"fill",label:"fill"},{value:"stroke",label:"stroke"}],defaultValue:"fill"})));h(this,"strokeWidth",this._manageComponent(new Y({defaultValue:"1",attributes:{min:"0",step:"0.1"}})));e.layerTargetProvider&&(this.layerTarget=this._manageComponent(new Ce({id:"textmode-export-svg-layer",provider:e.layerTargetProvider})))}render(){var n;const e=document.createElement("div");e.classList.add(W),(n=this.layerTarget)==null||n.mount(e),this.includeBackground.mount(e);const t=new te("row");t.mount(e);const a=new U({label:"draw mode",labelFor:"textmode-export-svg-draw-mode",variant:"compact"});a.mount(t.root),this.drawMode.mount(a.root);const i=new U({label:"stroke width",labelFor:"textmode-export-svg-stroke-width",variant:"compact"});return i.mount(t.root),this.strokeWidth.mount(i.root),this.strokeWidth.inputElement.id="textmode-export-svg-stroke-width",this.drawMode.selectElement.addEventListener("change",()=>this.updateStrokeControls()),this.updateStrokeControls(),e}getOptions(){var e;return{layer:(e=this.layerTarget)==null?void 0:e.layer,includeBackgroundRectangles:this.includeBackground.checked,drawMode:this.drawMode.value,strokeWidth:Number.parseFloat(this.strokeWidth.value)}}reset(){this.applyDefaults(),this.updateStrokeControls()}validate(){const e=Number.parseFloat(this.strokeWidth.value);return this.drawMode.value!=="stroke"||Number.isFinite(e)&&e>=0}refreshLayerTargets(){var e;(e=this.layerTarget)==null||e.refresh()}updateStrokeControls(){const e=this.drawMode.value==="stroke";this.strokeWidth.inputElement.disabled=!e,this.strokeWidth.refresh()}applyDefaults(){const e=this._config.defaultOptions??{};this.includeBackground.checked=e.includeBackgroundRectangles??!0,this.drawMode.value=e.drawMode??"fill";const t=e.strokeWidth??1;this.strokeWidth.value=String(t),this.strokeWidth.refresh()}}function Sr(l,r,e){var s;const t=(function(p){return[{format:"txt",label:"plain text (.txt)",supportsClipboard:!0,createBlade:()=>new kr({format:"txt",label:"plain text (.txt)",supportsClipboard:!0,defaultOptions:{preserveTrailingSpaces:!1,emptyCharacter:" "},layerTargetProvider:p})},{format:"json",label:"document data (.json)",supportsClipboard:!0,createBlade:()=>new Br({format:"json",label:"document data (.json)",supportsClipboard:!0,defaultOptions:{target:"selected",pretty:!0,includeMetadata:!0,colorMode:"hex"},layerTargetProvider:p})},{format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,createBlade:()=>new Ir({format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,defaultOptions:{format:"png",scale:1}})},{format:"svg",label:"vector (.svg)",supportsClipboard:!0,createBlade:()=>new Mr({format:"svg",label:"vector (.svg)",supportsClipboard:!0,defaultOptions:{includeBackgroundRectangles:!0,drawMode:"fill",strokeWidth:1},layerTargetProvider:p})},{format:"gif",label:"animated GIF (.gif)",supportsClipboard:!1,createBlade:()=>new xe({format:"gif",label:"animated GIF (.gif)",supportsClipboard:!1,defaultOptions:{frameCount:300,frameRate:60,scale:1,repeat:0}})},{format:"video",label:"video (.webm)",supportsClipboard:!1,createBlade:()=>new _e({format:"video",label:"video (.webm)",supportsClipboard:!1,defaultOptions:{frameCount:480,frameRate:60,quality:.7}})}]})(e),a=(s=t[0])==null?void 0:s.format,i=new Cr((p=>({format:p,isBusy:!1}))(a)),n=new _r,d=new wr(l,r,i,n,t);return d.$mount(),d}const Ee={name:"textmode.export",version:Je,async install(l,r){const e={saveCanvas:async(d={})=>new $e().$saveImage(l.canvas,d),copyCanvas:async(d={})=>new $e().$copyImageToClipboard(l.canvas,d),saveSVG:(d={})=>{new Fe().$saveSVG(l,d)},saveStrings:(d={})=>{new Le().$saveTXT(l,d)},toSVG:(d={})=>new Fe().$generateSVG(l,d),toString:(d={})=>new Le().$generateTXT(l,d),toJSON:(d={})=>new fe().$generateJSONData(l,d),toJSONString:(d={})=>new fe().$generateJSONString(l,d),saveJSON:(d={})=>{new fe().$saveJSON(l,d)},saveGIF:async(d={})=>new Dt(l,r.registerPostDrawHook).$saveGIF(d),saveWEBM:async(d={})=>new Ht(l,r.registerPostDrawHook).$saveWEBM(d)},t=Sr(l,e,(function(d){return{getOptions:()=>Se(d),getLayerById:s=>{var p;return(p=Se(d).find(o=>o.id===s))==null?void 0:p.layer},getDefaultId:()=>"base"}})(l));r.registerPostDrawHook(()=>{t.isVisible()&&t.refreshLayerTargets()});const a={show:()=>t.show(),hide:()=>t.hide(),toggle:()=>t.toggle(),isVisible:()=>t.isVisible()},i={...e,exportOverlay:a},n=l;Object.assign(n,i),n._exportOverlayController=t},async uninstall(l){const r=l,e=r._exportOverlayController;e==null||e.$dispose(),delete r._exportOverlayController;const t=["exportOverlay","saveCanvas","copyCanvas","saveSVG","saveStrings","toSVG","toString","toJSON","toJSONString","saveJSON","saveGIF","saveWEBM"];for(const a of t)delete r[a]}},vt=(l={})=>{const r=l.overlay??!0,e={...Ee},t=e.install;return e.install=async(a,i)=>{var d;const n=a;await t.call(e,n,i),r||((d=n.exportOverlay)==null||d.hide())},e};typeof window<"u"&&(window.ExportPlugin=Ee,window.createTextmodeExportPlugin=vt),j.ExportPlugin=Ee,j.createTextmodeExportPlugin=vt,Object.defineProperty(j,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,46 @@
1
+ import type { Textmodifier, TextmodeFramebuffer, TextmodeGrid } from 'textmode.js';
2
+ import type { TextmodeFont, TextmodeTileset } from 'textmode.js';
3
+ import type { TextmodeLayer } from 'textmode.js';
4
+ /**
5
+ * Shared option for exporters that read layer framebuffer data.
6
+ */
7
+ export interface LayerExportOptions {
8
+ /**
9
+ * Layer to export.
10
+ *
11
+ * Defaults to `textmodifier.layers.base`.
12
+ */
13
+ layer?: TextmodeLayer;
14
+ }
15
+ export interface ResolvedLayerExportTarget {
16
+ id: string;
17
+ label: string;
18
+ layer: TextmodeLayer;
19
+ grid: TextmodeGrid;
20
+ font: TextmodeFont | TextmodeTileset;
21
+ drawFramebuffer: TextmodeFramebuffer;
22
+ }
23
+ export interface ResolvedLayerStackExportTarget extends ResolvedLayerExportTarget {
24
+ visible: boolean;
25
+ opacity: number;
26
+ blendMode: string;
27
+ offsetX: number;
28
+ offsetY: number;
29
+ rotationZ: number;
30
+ }
31
+ export interface LayerTargetOption {
32
+ id: string;
33
+ label: string;
34
+ layer: TextmodeLayer;
35
+ }
36
+ export interface LayerTargetProvider {
37
+ getOptions(): LayerTargetOption[];
38
+ getLayerById(id: string): TextmodeLayer | undefined;
39
+ getDefaultId(): string;
40
+ }
41
+ export declare function getLayerTargetOptions(textmodifier: Textmodifier): LayerTargetOption[];
42
+ export declare function createLayerTargetProvider(textmodifier: Textmodifier): LayerTargetProvider;
43
+ export declare function getLayerTargetId(textmodifier: Textmodifier, layer: TextmodeLayer): string;
44
+ export declare function resolveLayerExportTarget(textmodifier: Textmodifier, layer?: TextmodeLayer): ResolvedLayerExportTarget;
45
+ export declare function resolveLayerStackExportTargets(textmodifier: Textmodifier): ResolvedLayerStackExportTarget[];
46
+ //# sourceMappingURL=LayerTarget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LayerTarget.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/LayerTarget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,YAAY,GAAG,eAAe,CAAC;IACrC,eAAe,EAAE,mBAAmB,CAAC;CACrC;AAED,MAAM,WAAW,8BAA+B,SAAQ,yBAAyB;IAChF,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IACnC,UAAU,IAAI,iBAAiB,EAAE,CAAC;IAClC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACpD,YAAY,IAAI,MAAM,CAAC;CACvB;AAQD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,YAAY,GAAG,iBAAiB,EAAE,CAWrF;AAED,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,YAAY,GAAG,mBAAmB,CAMzF;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CAWzF;AAED,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,yBAAyB,CAmBrH;AAED,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,YAAY,GAAG,8BAA8B,EAAE,CAwB3G"}
@@ -1,4 +1,6 @@
1
1
  export { DataExtractor } from './DataExtractor';
2
2
  export { FileHandler } from './FileHandler';
3
3
  export { getEncodedGlyphValueFromColor, resolveGlyphByEncodedValue } from './CharacterResolver';
4
+ export { createLayerTargetProvider, getLayerTargetId, getLayerTargetOptions, resolveLayerExportTarget, resolveLayerStackExportTargets, } from './LayerTarget';
5
+ export type { LayerExportOptions, LayerTargetOption, LayerTargetProvider, ResolvedLayerExportTarget, ResolvedLayerStackExportTarget, } from './LayerTarget';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EACN,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,8BAA8B,GAC9B,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,8BAA8B,GAC9B,MAAM,eAAe,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { Textmodifier } from 'textmode.js';
2
- import type { TextmodePluginContext } from 'textmode.js/plugins';
2
+ import type { TextmodePluginContext } from 'textmode.js';
3
3
  import type { GIFExportOptions } from './types';
4
4
  /**
5
5
  * Main GIF exporter for the textmode.js library.
@@ -1 +1 @@
1
- {"version":3,"file":"GIFExporter.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/GIFExporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,KAAK,EAAE,gBAAgB,EAAwB,MAAM,SAAS,CAAC;AAItE;;;;GAIG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAgD;IAEtF;;;;;OAKG;gBACS,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,sBAAsB,CAAC;IAM3G;;;;OAIG;IACU,QAAQ,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4DpE;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CAc5B"}
1
+ {"version":3,"file":"GIFExporter.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/GIFExporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,KAAK,EAAE,gBAAgB,EAAwB,MAAM,SAAS,CAAC;AAItE;;;;GAIG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAgD;IAEtF;;;;;OAKG;gBACS,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,sBAAsB,CAAC;IAM3G;;;;OAIG;IACU,QAAQ,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4DpE;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CAc5B"}
@@ -1,4 +1,4 @@
1
- import type { TextmodePluginContext } from 'textmode.js/plugins';
1
+ import type { TextmodePluginContext } from 'textmode.js';
2
2
  import type { GIFExportProgress, GIFFrame, GIFGenerationOptions } from './types';
3
3
  /**
4
4
  * Records frames from a canvas for GIF generation.
@@ -1 +1 @@
1
- {"version":3,"file":"GIFRecorder.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/GIFRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEjF;;;GAGG;AACH,qBAAa,WAAW;IACvB,wCAAwC;IACxC,OAAO,CAAC,OAAO,CAAC,CAAoB;IAEpC,4CAA4C;IAC5C,OAAO,CAAC,IAAI,CAAC,CAA2B;IAExC;;;;;;;;;OASG;IACU,OAAO,CACnB,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,oBAAoB,EAC7B,oBAAoB,EAAE,qBAAqB,CAAC,sBAAsB,CAAC,EACnE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GAChD,OAAO,CAAC,QAAQ,EAAE,CAAC;CAoItB"}
1
+ {"version":3,"file":"GIFRecorder.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/GIFRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEjF;;;GAGG;AACH,qBAAa,WAAW;IACvB,wCAAwC;IACxC,OAAO,CAAC,OAAO,CAAC,CAAoB;IAEpC,4CAA4C;IAC5C,OAAO,CAAC,IAAI,CAAC,CAA2B;IAExC;;;;;;;;;OASG;IACU,OAAO,CACnB,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,oBAAoB,EAC7B,oBAAoB,EAAE,qBAAqB,CAAC,sBAAsB,CAAC,EACnE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GAChD,OAAO,CAAC,QAAQ,EAAE,CAAC;CAoItB"}