textmode.export.js 1.2.0 → 1.2.2

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 (83) hide show
  1. package/README.md +170 -166
  2. package/dist/textmode.export.esm.js +522 -483
  3. package/dist/textmode.export.umd.js +2 -2
  4. package/dist/types/exporters/base/DataExtractor.d.ts +2 -1
  5. package/dist/types/exporters/base/DataExtractor.d.ts.map +1 -1
  6. package/dist/types/exporters/base/FileHandler.d.ts +3 -0
  7. package/dist/types/exporters/base/FileHandler.d.ts.map +1 -1
  8. package/dist/types/exporters/gif/GIFExporter.d.ts +6 -2
  9. package/dist/types/exporters/gif/GIFExporter.d.ts.map +1 -1
  10. package/dist/types/exporters/gif/GIFRecorder.d.ts +3 -3
  11. package/dist/types/exporters/gif/GIFRecorder.d.ts.map +1 -1
  12. package/dist/types/exporters/gif/types.d.ts +2 -2
  13. package/dist/types/exporters/gif/types.d.ts.map +1 -1
  14. package/dist/types/exporters/image/ImageExporter.d.ts +7 -2
  15. package/dist/types/exporters/image/ImageExporter.d.ts.map +1 -1
  16. package/dist/types/exporters/image/index.d.ts +1 -1
  17. package/dist/types/exporters/image/index.d.ts.map +1 -1
  18. package/dist/types/exporters/image/types.d.ts.map +1 -1
  19. package/dist/types/exporters/svg/SVGContentGenerator.d.ts +10 -1
  20. package/dist/types/exporters/svg/SVGContentGenerator.d.ts.map +1 -1
  21. package/dist/types/exporters/svg/SVGDataExtractor.d.ts +3 -1
  22. package/dist/types/exporters/svg/SVGDataExtractor.d.ts.map +1 -1
  23. package/dist/types/exporters/svg/SVGExporter.d.ts +3 -0
  24. package/dist/types/exporters/svg/SVGExporter.d.ts.map +1 -1
  25. package/dist/types/exporters/svg/SVGPathGenerator.d.ts +8 -4
  26. package/dist/types/exporters/svg/SVGPathGenerator.d.ts.map +1 -1
  27. package/dist/types/exporters/svg/index.d.ts +1 -1
  28. package/dist/types/exporters/svg/index.d.ts.map +1 -1
  29. package/dist/types/exporters/svg/types.d.ts.map +1 -1
  30. package/dist/types/exporters/txt/TXTExporter.d.ts +4 -0
  31. package/dist/types/exporters/txt/TXTExporter.d.ts.map +1 -1
  32. package/dist/types/exporters/txt/index.d.ts.map +1 -1
  33. package/dist/types/exporters/txt/types.d.ts.map +1 -1
  34. package/dist/types/exporters/video/VideoExporter.d.ts +6 -2
  35. package/dist/types/exporters/video/VideoExporter.d.ts.map +1 -1
  36. package/dist/types/exporters/video/VideoRecorder.d.ts +3 -3
  37. package/dist/types/exporters/video/VideoRecorder.d.ts.map +1 -1
  38. package/dist/types/exporters/video/index.d.ts +1 -1
  39. package/dist/types/exporters/video/index.d.ts.map +1 -1
  40. package/dist/types/exporters/video/types.d.ts +2 -2
  41. package/dist/types/exporters/video/types.d.ts.map +1 -1
  42. package/dist/types/index.d.ts +82 -20
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/dist/types/overlay/blades/Blade.d.ts +6 -1
  45. package/dist/types/overlay/blades/Blade.d.ts.map +1 -1
  46. package/dist/types/overlay/blades/GIFBlade.d.ts.map +1 -1
  47. package/dist/types/overlay/blades/ImageBlade.d.ts.map +1 -1
  48. package/dist/types/overlay/blades/SVGBlade.d.ts.map +1 -1
  49. package/dist/types/overlay/blades/TextBlade.d.ts.map +1 -1
  50. package/dist/types/overlay/blades/VideoBlade.d.ts.map +1 -1
  51. package/dist/types/overlay/components/actions/Button.d.ts.map +1 -1
  52. package/dist/types/overlay/components/base/Component.d.ts.map +1 -1
  53. package/dist/types/overlay/components/base/Container.d.ts.map +1 -1
  54. package/dist/types/overlay/components/base/Field.d.ts.map +1 -1
  55. package/dist/types/overlay/components/display/Header.d.ts.map +1 -1
  56. package/dist/types/overlay/components/display/StatusDisplay.d.ts.map +1 -1
  57. package/dist/types/overlay/components/inputs/CheckboxInput.d.ts.map +1 -1
  58. package/dist/types/overlay/components/inputs/NumberInput.d.ts.map +1 -1
  59. package/dist/types/overlay/components/inputs/RangeInput.d.ts.map +1 -1
  60. package/dist/types/overlay/components/inputs/SelectInput.d.ts.map +1 -1
  61. package/dist/types/overlay/components/inputs/TextInput.d.ts.map +1 -1
  62. package/dist/types/overlay/core/EventBus.d.ts +1 -0
  63. package/dist/types/overlay/core/EventBus.d.ts.map +1 -1
  64. package/dist/types/overlay/core/OverlayController.d.ts +4 -0
  65. package/dist/types/overlay/core/OverlayController.d.ts.map +1 -1
  66. package/dist/types/overlay/core/StateManager.d.ts.map +1 -1
  67. package/dist/types/overlay/formatRegistry.d.ts.map +1 -1
  68. package/dist/types/overlay/index.d.ts +1 -0
  69. package/dist/types/overlay/index.d.ts.map +1 -1
  70. package/dist/types/overlay/models/FormatDefinition.d.ts +3 -3
  71. package/dist/types/overlay/models/FormatDefinition.d.ts.map +1 -1
  72. package/dist/types/overlay/models/OverlayEvents.d.ts.map +1 -1
  73. package/dist/types/overlay/models/OverlayState.d.ts.map +1 -1
  74. package/dist/types/overlay/services/ClipboardService.d.ts +7 -2
  75. package/dist/types/overlay/services/ClipboardService.d.ts.map +1 -1
  76. package/dist/types/overlay/services/ExportService.d.ts.map +1 -1
  77. package/dist/types/overlay/services/PositionService.d.ts.map +1 -1
  78. package/dist/types/overlay/types.d.ts.map +1 -1
  79. package/dist/types/types.d.ts +99 -0
  80. package/dist/types/types.d.ts.map +1 -1
  81. package/dist/types/utils/pixels.d.ts +1 -0
  82. package/dist/types/utils/pixels.d.ts.map +1 -1
  83. package/package.json +115 -72
@@ -1,2 +1,2 @@
1
- (function(Q,j){typeof exports=="object"&&typeof module<"u"?j(exports):typeof define=="function"&&define.amd?define(["exports"],j):j((Q=typeof globalThis<"u"?globalThis:Q||self).TextmodeExport={})})(this,function(Q){"use strict";class j{$extractFramebufferData(t){return{characterPixels:t.readPixels(0),primaryColorPixels:t.readPixels(1),secondaryColorPixels:t.readPixels(2)}}$getCharacterIndex(t,e){return t[e]+(t[e+1]<<8)}}class X{$downloadFile(t,e){try{const r=this._sanitizeFilename(e),a=URL.createObjectURL(t),i=document.createElement("a");i.href=a,i.download=r,i.style.display="none",i.rel="noopener",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(a)}catch(r){console.error("[textmode-export] Failed to download file:",r)}}_sanitizeFilename(t){if(!t)return this._generateDefaultFilename();const e=t.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,"-")}`}}function vt(c,t){return{r:c[t],g:c[t+1],b:c[t+2],a:c[t+3]}}class ne extends j{_extractTransformData(t,e){const r=t[e+2],a=!!(1&r),i=!!(2&r),n=!!(4&r),u=t[e+3]/255;return{isInverted:a,flipHorizontal:i,flipVertical:n,rotation:Math.round(360*u*100)/100}}_calculateCellPosition(t,e,r){return{x:t,y:e,cellX:t*r.cellWidth,cellY:e*r.cellHeight}}$extractSVGCellData(t,e){const r=[];let a=0;for(let i=0;i<e.rows;i++)for(let n=0;n<e.cols;n++){const u=4*a,l=this.$getCharacterIndex(t.characterPixels,u);let h=vt(t.primaryColorPixels,u),o=vt(t.secondaryColorPixels,u);const s=this._extractTransformData(t.characterPixels,u);if(s.isInverted){const m=h;h=o,o=m}const d=this._calculateCellPosition(n,i,e);r.push({charIndex:l,primaryColor:h,secondaryColor:o,transform:s,position:d}),a++}return r}}class se{_createGlyphPath(t,e,r,a,i){const n=i/t.head.unitsPerEm;return{getBoundingBox:()=>({x1:r+e.xMin*n,y1:a+-e.yMax*n,x2:r+e.xMax*n,y2:a+-e.yMin*n}),toSVG:()=>this._glyphToSVGPath(e,r,a,n)}}_glyphToSVGPath(t,e,r,a){if(!t||!t.xs)return"";const{xs:i,ys:n,endPts:u,flags:l}=t;if(!(i&&n&&u&&l))return"";let h="",o=0;for(let s=0;s<u.length;s++){const d=u[s];if(!(d<o)){if(d>=o){const m=e+i[o]*a,y=r-n[o]*a;h+=`M${m.toFixed(2)},${y.toFixed(2)}`;let p=o+1;for(;p<=d;)if(1&l[p]){const b=e+i[p]*a,E=r-n[p]*a;h+=`L${b.toFixed(2)},${E.toFixed(2)}`,p++}else{const b=e+i[p]*a,E=r-n[p]*a;let x=p+1>d?o:p+1;if(1&l[x]){const g=e+i[x]*a,k=r-n[x]*a;h+=`Q${b.toFixed(2)},${E.toFixed(2)} ${g.toFixed(2)},${k.toFixed(2)}`,p=x+1}else{const g=(b+(e+i[x]*a))/2,k=(E+(r-n[x]*a))/2;h+=`Q${b.toFixed(2)},${E.toFixed(2)} ${g.toFixed(2)},${k.toFixed(2)}`,p=x}}h+="Z"}o=d+1}}return h}_generateCharacterPath(t,e,r,a,i){const n=e.characterMap.get(t).glyphData;return n?this._createGlyphPath(e.font,n,r,a,i):null}$generatePositionedCharacterPath(t,e,r,a,i,n,u,l){if(!l)return null;const h=u/e.font.head.unitsPerEm,o=r+(i-l.advanceWidth*h)/2,s=a+(n+.7*u)/2,d=this._generateCharacterPath(t,e,o,s,u);return d&&d.toSVG()||null}}class le{_pathGenerator;constructor(){this._pathGenerator=new se}$generateSVGHeader(t){const{width:e,height:r}=t;return`<?xml version="1.0" encoding="UTF-8"?><svg width="${e}" height="${r}" viewBox="0 0 ${e} ${r}" xmlns="http://www.w3.org/2000/svg"><title>textmode.js sketch</title>`}$generateSVGFooter(){return"</g></svg>"}_generateTransformAttribute(t,e){const{transform:r,position:a}=t;if(!r.flipHorizontal&&!r.flipVertical&&!r.rotation)return"";const i=a.cellX+e.cellWidth/2,n=a.cellY+e.cellHeight/2,u=[];if(r.flipHorizontal||r.flipVertical){const l=r.flipHorizontal?-1:1,h=r.flipVertical?-1:1;u.push(`translate(${i} ${n})scale(${l} ${h})translate(${-i} ${-n})`)}return r.rotation&&u.push(`rotate(${r.rotation} ${i} ${n})`),` transform="${u.join(" ")}"`}_generateCellBackground(t,e,r){if(!r.includeBackgroundRectangles||t.secondaryColor.a===0)return"";const{position:a}=t,{r:i,g:n,b:u,a:l}=t.secondaryColor,h=`rgba(${i},${n},${u},${l/255})`;return r.drawMode==="stroke"?`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" stroke="${h}" fill="none" stroke-width="${r.strokeWidth}"/>`:`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" fill="${h}"/>`}_generateCharacterPath(t,e,r,a){const i=r.characters[t.charIndex];if(!i)return"";const n=this._pathGenerator.$generatePositionedCharacterPath(i.character,r,t.position.cellX,t.position.cellY,e.cellWidth,e.cellHeight,r.fontSize,i.glyphData);if(!n)return"";const{r:u,g:l,b:h,a:o}=t.primaryColor,s=`rgba(${u},${l},${h},${o/255})`;return a.drawMode==="stroke"?`<path d="${n}" stroke="${s}" stroke-width="${a.strokeWidth}" fill="none"/>`:`<path d="${n}" fill="${s}"/>`}$generateCellContent(t,e,r,a){const i=[],n=this._generateCellBackground(t,e,a);n&&i.push(n);const u=this._generateCharacterPath(t,e,r,a);if(u){const l=this._generateTransformAttribute(t,e);i.push(l?`<g${l}>${u}</g>`:u)}return i.join("")}$generateSVGContent(t,e,r,a){const i=[this.$generateSVGHeader(e),'<g id="ascii-cells">'];for(const n of t)i.push(this.$generateCellContent(n,e,r,a));return i.push(this.$generateSVGFooter()),i.join("")}$optimizeSVGContent(t){return t.replace(/<path[^>]*d=""[^>]*\/>/g,"").replace(/\s+/g," ").replace(/> </g,"><")}}class xt{_applyDefaultOptions(t){return{includeBackgroundRectangles:t.includeBackgroundRectangles??!0,drawMode:t.drawMode??"fill",strokeWidth:t.strokeWidth??1,filename:t.filename}}$generateSVG(t,e={}){const r=new ne,a=new le,i=r.$extractSVGCellData(r.$extractFramebufferData(t.layers.base.drawFramebuffer),t.grid),n=a.$generateSVGContent(i,t.grid,t.font,this._applyDefaultOptions(e));return a.$optimizeSVGContent(n)}$saveSVG(t,e={}){new X().$downloadFile(new Blob([this.$generateSVG(t,e)],{type:"image/svg+xml;charset=utf-8"}),e.filename)}}const nt={png:"image/png",jpg:"image/jpeg",webp:"image/webp"},de=".png",ce=".jpg",ue=".webp";class yt{_applyDefaultOptions(t){return{format:t.format??"png",scale:Math.abs(t.scale??1),filename:t.filename}}_validateOptions(t){if(!(t.format in nt))throw new Error(`Saving '${t.format}' files is not supported`)}async $generateImageBlob(t,e){const r=t,a=document.createElement("canvas"),i=a.getContext("2d"),n=Math.round(r.width*e.scale),u=Math.round(r.height*e.scale);return a.width=n,a.height=u,i.imageSmoothingEnabled=!1,i.clearRect(0,0,n,u),i.drawImage(r,0,0,r.width,r.height,0,0,n,u),await new Promise((l,h)=>{a.toBlob(o=>{o?l(o):h(new Error(`Failed to generate ${e.format.toUpperCase()} blob`))},nt[e.format])})}async $saveImage(t,e={}){const r=this._applyDefaultOptions(e);this._validateOptions(r);const a=await this.$generateImageBlob(t,r);new X().$downloadFile(a,r.filename)}async $copyImageToClipboard(t,e={}){if(typeof navigator>"u"||!navigator.clipboard||typeof navigator.clipboard.write!="function")throw new Error("Clipboard API is not available in this environment");const r=this._applyDefaultOptions(e);this._validateOptions(r);const a=await this.$generateImageBlob(t,r),i=new ClipboardItem({[nt[r.format]]:a});await navigator.clipboard.write([i])}}class _t{_applyDefaultOptions(t){return{preserveTrailingSpaces:t.preserveTrailingSpaces??!1,emptyCharacter:t.emptyCharacter??" ",filename:t.filename}}_createTXTContent(t,e){const r=new j;console.log(t);let a=r.$extractFramebufferData(t.layers.base.drawFramebuffer);const i=[];let n=0;for(let l=0;l<t.grid.rows;l++){const h=[];for(let o=0;o<t.grid.cols;o++){const s=4*n,d=r.$getCharacterIndex(a.characterPixels,s),m=t.font.characters[d]?.character||e.emptyCharacter;h.push(m),n++}i.push(h)}const u=[];for(const l of i){let h=l.join("");e.preserveTrailingSpaces||(h=h.replace(/\s+$/,"")),u.push(h)}return u.join(`
2
- `)}$generateTXT(t,e={}){return this._createTXTContent(t,this._applyDefaultOptions(e))}$saveTXT(t,e={}){const r=this._applyDefaultOptions(e),a=this._createTXTContent(t,r),i=new Blob([a],{type:"text/plain;charset=utf-8"});new X().$downloadFile(i,r.filename)}}class pe{_canvas;_ctx;async $record(t,e,r,a){const i=Math.max(1,Math.round(e.frameRate)),n=Math.round(1e3/i),u=Math.max(1,Math.round(e.frameCount));return await new Promise((l,h)=>{const o=[];let s,d=0,m=!1;const y=()=>{s&&(s(),s=void 0)},p=E=>{m||(m=!0,y(),l(E))},b=()=>{if(d>=u)p(o);else try{const E=e.scale,x=Math.max(1,Math.round(t.width*E)),g=Math.max(1,Math.round(t.height*E));this._canvas||(this._canvas=document.createElement("canvas")),this._canvas.width===x&&this._canvas.height===g||(this._canvas.width=x,this._canvas.height=g),this._ctx||(this._ctx=this._canvas.getContext("2d"));const k=this._ctx;k.imageSmoothingEnabled=!1,k.clearRect(0,0,x,g),k.drawImage(t,0,0,t.width,t.height,0,0,x,g);const S={imageData:k.getImageData(0,0,x,g),width:x,height:g,delayMs:n};o.push(S),d+=1,a?.({state:"recording",frameIndex:d,totalFrames:u}),d>=u&&p(o)}catch(E){(x=>{if(m)return;m=!0,y();const g=x instanceof Error?x.message:"GIF recording failed";a?.({state:"error",message:g}),h(x instanceof Error?x:new Error(String(x)))})(E)}};s=r(()=>{b()}),a?.({state:"recording",frameIndex:0,totalFrames:u})})}}var wt,tt,Ct=Object.defineProperty,he=(wt=c=>{function t(s,d,m){return .29889531*s+.58662247*d+.11448223*m}function e(s,d,m){return .59597799*s-.2741761*d-.32180189*m}function r(s,d,m){return .21147017*s-.52261711*d+.31114694*m}function a(s,d){let m=s[0]-d[0],y=s[1]-d[1],p=s[2]-d[2],b=i(s)-i(d);return m*m*.5053+y*y*.299+p*p*.1957+b*b}function i(s){return s[3]!=null?s[3]:255}function n(s,d){return Math.sqrt(a(s,d))}function u(s,d){let[m,y,p]=s,[b,E,x]=d,g=t(m,y,p)-t(b,E,x),k=e(m,y,p)-e(b,E,x),S=r(m,y,p)-r(b,E,x),B=i(s)-i(d);return g*g*.5053+k*k*.299+S*S*.1957+B*B}function l(s,d){return Math.sqrt(u(s,d))}function h(s,d){var m,y=0;for(m=0;m<s.length;m++){let p=s[m]-d[m];y+=p*p}return y}function o(s,d){return Math.sqrt(h(s,d))}Ct(c,"__esModule",{value:!0}),((s,d)=>{for(var m in d)Ct(s,m,{get:d[m],enumerable:!0})})(c,{colorDifferenceRGBToYIQ:()=>l,colorDifferenceRGBToYIQSquared:()=>u,colorDifferenceYIQ:()=>n,colorDifferenceYIQSquared:()=>a,euclideanDistance:()=>o,euclideanDistanceSquared:()=>h})},()=>(tt||wt((tt={exports:{}}).exports,tt),tt.exports)),me=59;function Et(c=256){let t=0,e=new Uint8Array(c);return{get buffer(){return e.buffer},reset(){t=0},bytesView:()=>e.subarray(0,t),bytes:()=>e.slice(0,t),writeByte(a){r(t+1),e[t]=a,t++},writeBytes(a,i=0,n=a.length){r(t+n);for(let u=0;u<n;u++)e[t++]=a[u+i]},writeBytesView(a,i=0,n=a.byteLength){r(t+n),e.set(a.subarray(i,i+n),t),t+=n}};function r(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),t>0&&e.set(n.subarray(0,t),0)}}var fe=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],ge=function(c,t,e,r,a,i,n,u){a=a||Et(512),i=i||new Uint8Array(256),n=n||new Int32Array(5003),u=u||new Int32Array(5003);let l=n.length,h=Math.max(2,r);i.fill(0),u.fill(0),F();let o=0,s=0,d=h+1,m=d,y=!1,p=m,b=$(p),E=1<<d-1,x=E+1,g=E+2,k=0,S=e[0],B=0;for(let v=l;v<65536;v*=2)++B;B=8-B,a.writeByte(h),A(E);for(let v=1;v<e.length;v++)L(e[v]);return A(S),A(x),a.writeByte(0),a.bytesView();function C(v){i[k++]=v,k>=254&&w()}function F(){n.fill(-1)}function L(v){let V=(v<<12)+S,f=v<<B^S;if(n[f]===V)S=u[f];else{if(n[f]>=0){let _=f===0?1:l-f;do if(f-=_,f<0&&(f+=l),n[f]===V)return void(S=u[f]);while(n[f]>=0)}A(S),S=v,g<4096?(u[f]=g++,n[f]=V):(F(),g=E+2,y=!0,A(E))}}function w(){k>0&&(a.writeByte(k),a.writeBytesView(i,0,k),k=0)}function $(v){return(1<<v)-1}function A(v){for(o&=fe[s],s>0?o|=v<<s:o=v,s+=p;s>=8;)C(255&o),o>>=8,s-=8;if((g>b||y)&&(y?(p=m,b=$(p),y=!1):(++p,b=p==12?4096:$(p))),v==x){for(;s>0;)C(255&o),o>>=8,s-=8;w()}}};function kt(c,t,e){return c<<8&63488|t<<2&992|e>>3&31}function Bt(c,t,e,r){return c>>4|240&t|(240&e)<<4|(240&r)<<8}function It(c,t,e){return c>>4<<8|t>>4<<4|e>>4}function et(c,t,e){return c<t?t:c>e?e:c}function rt(c){return c*c}function Ft(c,t,e){for(var r=0,a=1e100,i=c[t],n=i.cnt,u=(i.ac,i.rc),l=i.gc,h=i.bc,o=i.fw;o!=0;o=c[o].fw){var s=c[o].cnt,d=n*s/(n+s);if(!(d>=a)){var m=0;!((m+=d*rt(c[o].rc-u))>=a)&&!((m+=d*rt(c[o].gc-l))>=a)&&!((m+=d*rt(c[o].bc-h))>=a)&&(a=m,r=o)}}i.err=a,i.nn=r}function st(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function be(c,t,e){let{format:r="rgb565",clearAlpha:a=!0,clearAlphaColor:i=0,clearAlphaThreshold:n=0,oneBitAlpha:u=!1}=e||{},l=e.useSqrt!==!1,h=r==="rgba4444",o=(function(v,V){let f=new Array(V==="rgb444"?4096:65536),_=v.length;if(V==="rgba4444")for(let M=0;M<_;++M){let P=v[M],D=P>>24&255,O=P>>16&255,I=P>>8&255,T=255&P,U=Bt(T,I,O,D),G=U in f?f[U]:f[U]=st();G.rc+=T,G.gc+=I,G.bc+=O,G.ac+=D,G.cnt++}else if(V==="rgb444")for(let M=0;M<_;++M){let P=v[M],D=P>>16&255,O=P>>8&255,I=255&P,T=It(I,O,D),U=T in f?f[T]:f[T]=st();U.rc+=I,U.gc+=O,U.bc+=D,U.cnt++}else for(let M=0;M<_;++M){let P=v[M],D=P>>16&255,O=P>>8&255,I=255&P,T=kt(I,O,D),U=T in f?f[T]:f[T]=st();U.rc+=I,U.gc+=O,U.bc+=D,U.cnt++}return f})(c,r),s=o.length,d=s-1,m=new Uint32Array(s+1);for(var y=0,p=0;p<o.length;++p){let v=o[p];if(v!=null){var b=1/v.cnt;h&&(v.ac*=b),v.rc*=b,v.gc*=b,v.bc*=b,o[y++]=v}}for(rt(t)/y<.022&&(l=!1),p=0;p<y-1;++p)o[p].fw=p+1,o[p+1].bk=p,l&&(o[p].cnt=Math.sqrt(o[p].cnt));var E,x,g;for(l&&(o[p].cnt=Math.sqrt(o[p].cnt)),p=0;p<y;++p){Ft(o,p);var k=o[p].err;for(x=++m[0];x>1&&!(o[E=m[g=x>>1]].err<=k);x=g)m[x]=E;m[x]=p}var S=y-t;for(p=0;p<S;){for(var B;;){var C=m[1];if((B=o[C]).tm>=B.mtm&&o[B.nn].mtm<=B.tm)break;for(B.mtm==d?C=m[1]=m[m[0]--]:(Ft(o,C),B.tm=p),k=o[C].err,x=1;(g=x+x)<=m[0]&&(g<m[0]&&o[m[g]].err>o[m[g+1]].err&&g++,!(k<=o[E=m[g]].err));x=g)m[x]=E;m[x]=C}var F=o[B.nn],L=B.cnt,w=F.cnt;b=1/(L+w),h&&(B.ac=b*(L*B.ac+w*F.ac)),B.rc=b*(L*B.rc+w*F.rc),B.gc=b*(L*B.gc+w*F.gc),B.bc=b*(L*B.bc+w*F.bc),B.cnt+=F.cnt,B.mtm=++p,o[F.bk].fw=F.fw,o[F.fw].bk=F.bk,F.mtm=d}let $=[];var A=0;for(p=0;;++A){let v=et(Math.round(o[p].rc),0,255),V=et(Math.round(o[p].gc),0,255),f=et(Math.round(o[p].bc),0,255),_=255;h&&(_=et(Math.round(o[p].ac),0,255),u&&(_=_<=(typeof u=="number"?u:127)?0:255),a&&_<=n&&(v=V=f=i,_=0));let M=h?[v,V,f,_]:[v,V,f];if(ve($,M)||$.push(M),(p=o[p].fw)==0)break}return $}function ve(c,t){for(let e=0;e<c.length;e++){let r=c[e],a=r[0]===t[0]&&r[1]===t[1]&&r[2]===t[2],i=!(r.length>=4&&t.length>=4)||r[3]===t[3];if(a&&i)return!0}return!1}function xe(c,t,e,r,a){let i=0,n=1e100;for(let u=0;u<a.length;u++){let l=a[u],h=l[0],o=l[1],s=l[2],d=H(l[3]-r);d>n||(d+=H(h-c),!(d>n)&&(d+=H(o-t),!(d>n)&&(d+=H(s-e),!(d>n)&&(n=d,i=u))))}return i}function ye(c,t,e,r){let a=0,i=1e100;for(let n=0;n<r.length;n++){let u=r[n],l=u[0],h=u[1],o=u[2],s=H(l-c);s>i||(s+=H(h-t),!(s>i)&&(s+=H(o-e),!(s>i)&&(i=s,a=n)))}return a}function H(c){return c*c}function _e(c={}){let{initialCapacity:t=4096,auto:e=!0}=c,r=Et(t),a=new Uint8Array(256),i=new Int32Array(5003),n=new Int32Array(5003),u=!1;return{reset(){r.reset(),u=!1},finish(){r.writeByte(me)},bytes:()=>r.bytes(),bytesView:()=>r.bytesView(),get buffer(){return r.buffer},get stream(){return r},writeHeader:l,writeFrame(h,o,s,d={}){let{transparent:m=!1,transparentIndex:y=0,delay:p=0,palette:b=null,repeat:E=0,colorDepth:x=8,dispose:g=-1}=d,k=!1;if(e?u||(k=!0,l(),u=!0):k=!!d.first,o=Math.max(0,Math.floor(o)),s=Math.max(0,Math.floor(s)),k){if(!b)throw new Error("First frame must include a { palette } option");(function(C,F,L,w,$=8){let A=1,v=0,V=lt(w.length)-1,f=A<<7|$-1<<4|v<<3|V;W(C,F),W(C,L),C.writeBytes([f,0,0])})(r,o,s,b,x),Mt(r,b),E>=0&&(function(C,F){C.writeByte(33),C.writeByte(255),C.writeByte(11),$t(C,"NETSCAPE2.0"),C.writeByte(3),C.writeByte(1),W(C,F),C.writeByte(0)})(r,E)}let S=Math.round(p/10);(function(C,F,L,w,$){var A,v;C.writeByte(33),C.writeByte(249),C.writeByte(4),$<0&&($=0,w=!1),w?(A=1,v=2):(A=0,v=0),F>=0&&(v=7&F),v<<=2,C.writeByte(0|v|0|A),W(C,L),C.writeByte($||0),C.writeByte(0)})(r,g,S,m,y);let B=!!b&&!k;(function(C,F,L,w){if(C.writeByte(44),W(C,0),W(C,0),W(C,F),W(C,L),w){let $=0,A=0,v=lt(w.length)-1;C.writeByte(128|$|A|v)}else C.writeByte(0)})(r,o,s,B?b:null),B&&Mt(r,b),(function(C,F,L,w,$=8,A,v,V){ge(L,w,F,$,C,A,v,V)})(r,h,o,s,x,a,i,n)}};function l(){$t(r,"GIF89a")}}function Mt(c,t){let e=1<<lt(t.length);for(let r=0;r<e;r++){let a=[0,0,0];r<t.length&&(a=t[r]),c.writeByte(a[0]),c.writeByte(a[1]),c.writeByte(a[2])}}function W(c,t){c.writeByte(255&t),c.writeByte(t>>8&255)}function $t(c,t){for(var e=0;e<t.length;e++)c.writeByte(t.charCodeAt(e))}function lt(c){return Math.max(Math.ceil(Math.log2(c)),1)}he();class we{_recorder;_textmodifier;_registerPostDrawHook;constructor(t,e){this._recorder=new pe,this._textmodifier=t,this._registerPostDrawHook=e}async $saveGIF(t={}){const e=this._textmodifier.canvas,r=this._applyDefaultOptions(t),a=t.onProgress;try{const i=await this._recorder.$record(e,r,this._registerPostDrawHook,a),n=_e(),{repeat:u}=t;i.forEach((o,s)=>{const{width:d,height:m,imageData:y,delayMs:p}=o,b=new Uint32Array(y.data.buffer.slice(0)),E=be(b,256,{}),x=(function(g,k,S){let B=(S=S||"rgb565")==="rgb444"?4096:65536,C=new Uint8Array(g.length),F=new Array(B);if(S==="rgba4444")for(let L=0;L<g.length;L++){let w,$=g[L],A=$>>24&255,v=$>>16&255,V=$>>8&255,f=255&$,_=Bt(f,V,v,A);F[_]!=null?w=F[_]:(w=xe(f,V,v,A,k),F[_]=w),C[L]=w}else for(let L=0;L<g.length;L++){let w,$=g[L],A=$>>16&255,v=$>>8&255,V=255&$,f=S==="rgb444"?It(V,v,A):kt(V,v,A);F[f]!=null?w=F[f]:(w=ye(V,v,A,k),F[f]=w),C[L]=w}return C})(b,E);n.writeFrame(x,d,m,{palette:E,delay:p,repeat:s===0?u:-1})}),n.finish();const l=n.bytes(),h=l.buffer.slice(l.byteOffset,l.byteOffset+l.byteLength);new X().$downloadFile(new Blob([h],{type:"image/gif"}),r.filename),a?.({state:"completed",totalFrames:r.frameCount})}catch(i){throw a?.({state:"error",message:i instanceof Error?i.message:"GIF export failed"}),i}}_applyDefaultOptions(t){const e=Math.abs(Math.round(t.frameCount??300)),r=Math.abs(t.frameRate??60),a=Math.abs(t.scale??1),i=Math.max(-1,Math.round(t.repeat??0));return{filename:t.filename,frameCount:e,frameRate:r,scale:a,repeat:i}}}function Ce(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var St,Lt={exports:{}};function Ee(){return St||(St=1,(function(c){(function(){function t(l,h){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 l=="string"&&/^data:image\/webp/.test(l)?l:l.toDataURL("image/webp",h))}function e(l){return(l.charCodeAt(0)|l.charCodeAt(1)<<8|l.charCodeAt(2)<<16|l.charCodeAt(3)<<24)>>>0}function r(l){let h=l.indexOf("VP8",12);if(h===-1)throw new Error("Bad image format, does this browser support WebP?");let o=!1;for(;h<l.length-8;){let s,d;switch(d=l.substring(h,h+4),h+=4,s=e(l.substring(h,h+4)),h+=4,d){case"VP8 ":return{frame:l.substring(h,h+s),hasAlpha:o};case"ALPH":o=!0}h+=s,1&s&&h++}throw new Error("Failed to find VP8 keyframe in WebP image, is this image mistakenly encoded in the Lossless WebP format?")}function a(l){this.value=l}function i(l){this.value=l}function n(l,h,o){if(Array.isArray(o))for(let s=0;s<o.length;s++)n(l,h,o[s]);else if(typeof o=="string")l.writeString(o);else if(o instanceof Uint8Array)l.writeBytes(o);else{if(!o.id)throw new Error("Bad EBML datatype "+typeof o.data);if(o.offset=l.pos+h,l.writeUnsignedIntBE(o.id),Array.isArray(o.data)){let s,d,m;o.size===-1?l.writeByte(255):o.size===-2?(s=l.pos,l.writeBytes([15,255,255,255,255])):(s=l.pos,l.writeBytes([0,0,0,0])),d=l.pos,o.dataOffset=d+h,n(l,h,o.data),o.size!==-1&&o.size!==-2&&(m=l.pos,o.size=m-d,l.seek(s),l.writeEBMLVarIntWidth(o.size,4),l.seek(m))}else if(typeof o.data=="string")l.writeEBMLVarInt(o.data.length),o.dataOffset=l.pos+h,l.writeString(o.data);else if(typeof o.data=="number")o.size||(o.size=l.measureUnsignedInt(o.data)),l.writeEBMLVarInt(o.size),o.dataOffset=l.pos+h,l.writeUnsignedIntBE(o.data,o.size);else if(o.data instanceof i)l.writeEBMLVarInt(8),o.dataOffset=l.pos+h,l.writeDoubleBE(o.data.value);else if(o.data instanceof a)l.writeEBMLVarInt(4),o.dataOffset=l.pos+h,l.writeFloatBE(o.data.value);else{if(!(o.data instanceof Uint8Array))throw new Error("Bad EBML datatype "+typeof o.data);l.writeEBMLVarInt(o.data.byteLength),o.dataOffset=l.pos+h,l.writeBytes(o.data)}}}let u=function(l,h){return function(o){let s,d,m=!1,y=0,p=0,b=null,E=null,x=null,g=[],k=0,S=0,B={quality:.95,transparent:!1,alphaQuality:void 0,fileWriter:null,fd:null,frameDuration:null,frameRate:null},C={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)},L=[],w=new h(o.fileWriter||o.fd);function $(f){return f-s.dataOffset}function A(){d=(function(){let D={id:21420,size:5,data:0},O={id:290298740,data:[]};for(let I in C){let T=C[I];T.positionEBML=Object.create(D),O.data.push({id:19899,data:[{id:21419,data:T.id},T.positionEBML]})}return O})();let f={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:"webm-writer-js"},{id:22337,data:"webm-writer-js"},F]},_=[{id:176,data:y},{id:186,data:p}];o.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:_}]}]};s={id:408125543,size:-2,data:[d,f,M]};let P=new l(256);n(P,w.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}]},s]),w.write(P.getAsDataArray()),C.SegmentInfo.positionEBML.data=$(f.offset),C.Tracks.positionEBML.data=$(M.offset),m=!0}function v(f){return f.alpha?(function(_){let M,P,D=new l(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return D.writeEBMLVarInt(_.trackNumber),D.writeU16BE(_.timecode),D.writeByte(0),M={id:161,data:[D.getAsDataArray(),_.frame]},P={id:30113,data:[{id:166,data:[{id:238,data:1},{id:165,data:_.alpha}]}]},{id:160,data:[M,P]}})(f):(function(_){let M=new l(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]}})(f)}function V(){if(g.length===0)return;let f=0;for(let I=0;I<g.length;I++)f+=g[I].frame.length+(g[I].alpha?g[I].alpha.length:0);let _=new l(f+64*g.length),M=(function(I){return{id:524531317,data:[{id:231,data:Math.round(I.timecode)}]}})({timecode:Math.round(k)});for(let I=0;I<g.length;I++)M.data.push(v(g[I]));var P,D,O;n(_,w.pos,M),w.write(_.getAsDataArray()),P=1,D=Math.round(k),O=M.offset,L.push({id:187,data:[{id:179,data:D},{id:183,data:[{id:247,data:P},{id:241,data:$(O)}]}]}),g=[],k+=S,S=0}this.addFrame=function(f,_,M){m||(y=f.width||0,p=f.height||0,A());let P,D=r(t(f,o.quality)),O=null;P=M||(typeof _=="number"?_:o.frameDuration),o.transparent&&(_ instanceof HTMLCanvasElement||typeof _=="string"?O=_:D.hasAlpha&&(O=(function(I){b!==null&&b.width===I.width&&b.height===I.height||(b=document.createElement("canvas"),b.width=I.width,b.height=I.height,E=b.getContext("2d"),x=E.createImageData(b.width,b.height));let T=I.getContext("2d").getImageData(0,0,I.width,I.height).data,U=x.data,G=0,mr=I.width*I.height*4;for(let gt=3;gt<mr;gt+=4){let bt=T[gt];U[G++]=bt,U[G++]=bt,U[G++]=bt,U[G++]=255}return E.putImageData(x,0,0),b})(f))),(function(I){I.trackNumber=1,I.timecode=Math.round(S),g.push(I),S+=I.duration,S>=5e3&&V()})({frame:D.frame,duration:P,alpha:O?r(t(O,o.alphaQuality)).frame:null})},this.complete=function(){return m||A(),V(),(function(){let f={id:475249515,data:L},_=new l(16+32*L.length);n(_,w.pos,f),w.write(_.getAsDataArray()),C.Cues.positionEBML.data=$(f.offset)})(),(function(){let f=new l(d.size),_=w.pos;n(f,d.dataOffset,d.data),w.seek(d.dataOffset),w.write(f.getAsDataArray()),w.seek(_)})(),(function(){let f=new l(8),_=w.pos;f.writeDoubleBE(k),w.seek(F.dataOffset),w.write(f.getAsDataArray()),w.seek(_)})(),(function(){let f=new l(10),_=w.pos;f.writeUnsignedIntBE(s.id),f.writeEBMLVarIntWidth(w.pos-s.dataOffset,5),w.seek(s.offset),w.write(f.getAsDataArray()),w.seek(_)})(),w.complete("video/webm")},this.getWrittenSize=function(){return w.length},o=(function(f,_){let M={};return[f,_].forEach(function(P){for(let D in P)Object.prototype.hasOwnProperty.call(P,D)&&(M[D]=P[D])}),M})(B,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)})()}};c.exports=u})()})(Lt)),Lt.exports}var Pt,At={exports:{}};function ke(){return Pt||(Pt=1,(function(c){(function(){let t=function(e){this.data=new Uint8Array(e),this.pos=0};t.prototype.seek=function(e){this.pos=e},t.prototype.writeBytes=function(e){for(let r=0;r<e.length;r++)this.data[this.pos++]=e[r]},t.prototype.writeByte=function(e){this.data[this.pos++]=e},t.prototype.writeU8=t.prototype.writeByte,t.prototype.writeU16BE=function(e){this.data[this.pos++]=e>>8,this.data[this.pos++]=e},t.prototype.writeDoubleBE=function(e){let r=new Uint8Array(new Float64Array([e]).buffer);for(let a=r.length-1;a>=0;a--)this.writeByte(r[a])},t.prototype.writeFloatBE=function(e){let r=new Uint8Array(new Float32Array([e]).buffer);for(let a=r.length-1;a>=0;a--)this.writeByte(r[a])},t.prototype.writeString=function(e){for(let r=0;r<e.length;r++)this.data[this.pos++]=e.charCodeAt(r)},t.prototype.writeEBMLVarIntWidth=function(e,r){switch(r){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 "+r)}},t.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)},t.prototype.writeEBMLVarInt=function(e){this.writeEBMLVarIntWidth(e,this.measureEBMLVarInt(e))},t.prototype.writeUnsignedIntBE=function(e,r){switch(r===void 0&&(r=this.measureUnsignedInt(e)),r){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 "+r)}},t.prototype.measureUnsignedInt=function(e){return e<256?1:e<65536?2:e<1<<24?3:e<4294967296?4:5},t.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")},c.exports=t})()})(At)),At.exports}var Vt,Dt,Ot,Ut={exports:{}};function Be(){return Vt||(Vt=1,(function(c){(function(){let t=function(e){return function(r){let a=[],i=Promise.resolve(),n=null,u=null;function l(s){return new Promise(function(d,m){let y=new FileReader;y.addEventListener("loadend",function(){d(y.result)}),y.readAsArrayBuffer(s)})}function h(s){return new Promise(function(d,m){s instanceof Uint8Array?d(s):s instanceof ArrayBuffer||ArrayBuffer.isView(s)?d(new Uint8Array(s)):s instanceof Blob?d(l(s).then(function(y){return new Uint8Array(y)})):d(l(new Blob([s])).then(function(y){return new Uint8Array(y)}))})}function o(s){let d=s.byteLength||s.length||s.size;if(!Number.isInteger(d))throw new Error("Failed to determine size of element");return d}r&&r.constructor.name==="FileWriter"?n=r:e&&r&&(u=r),this.pos=0,this.length=0,this.seek=function(s){if(s<0)throw new Error("Offset may not be negative");if(isNaN(s))throw new Error("Offset may not be NaN");if(s>this.length)throw new Error("Seeking beyond the end of file is not allowed");this.pos=s},this.write=function(s){let d={offset:this.pos,data:s,length:o(s)},m=d.offset>=this.length;this.pos+=d.length,this.length=Math.max(this.length,this.pos),i=i.then(function(){if(u)return new Promise(function(y,p){h(d.data).then(function(b){let E=0,x=Buffer.from(b.buffer),g=function(k,S,B){E+=S,E>=B.length?y():e.write(u,B,E,B.length-E,d.offset+E,g)};e.write(u,x,0,x.length,d.offset,g)})});if(n)return new Promise(function(y,p){n.onwriteend=y,n.seek(d.offset),n.write(new Blob([d.data]))});if(!m)for(let y=0;y<a.length;y++){let p=a[y];if(!(d.offset+d.length<=p.offset||d.offset>=p.offset+p.length)){if(d.offset<p.offset||d.offset+d.length>p.offset+p.length)throw new Error("Overwrite crosses blob boundaries");return d.offset==p.offset&&d.length==p.length?void(p.data=d.data):h(p.data).then(function(b){return p.data=b,h(d.data)}).then(function(b){d.data=b,p.data.set(d.data,d.offset-p.offset)})}}a.push(d)})},this.complete=function(s){return i=u||n?i.then(function(){return null}):i.then(function(){let d=[];for(let m=0;m<a.length;m++)d.push(a[m].data);return new Blob(d,{type:s})}),i}}};c.exports=t})()})(Ut)),Ut.exports}function Ie(){return Ot?Dt:(Ot=1,Dt=Ee()(ke(),Be()(null)))}const Fe=Ce(Ie());class Me{async $record(t,e,r,a){const i=Math.max(1,Math.round(e.frameRate)),n=Math.max(1,Math.round(e.frameCount)),u=new Fe({quality:e.quality,alphaQuality:e.transparent?e.quality:void 0,transparent:e.transparent,frameRate:i}),l=this._createSnapshotSurface();return await new Promise((h,o)=>{let s,d="capturing",m=!1,y=0;const p=()=>{s&&(s(),s=void 0)},b=()=>{a?.({state:"recording",frameIndex:y,totalFrames:n})},E=g=>{if(m)return;m=!0,p();const k=g instanceof Error?g.message:"WEBM export failed";a?.({state:"error",message:k}),o(g instanceof Error?g:new Error(String(g)))},x=()=>{d!=="capturing"||m||(d="encoding",p(),u.complete().then(g=>{(k=>{m||(m=!0,a?.({state:"completed",frameIndex:Math.min(n,y),totalFrames:n}),h(k))})(g)}).catch(E))};s=r(()=>{(()=>{if(d==="capturing")if(y>=n)x();else try{const g=l(t);u.addFrame(g),y+=1,b(),y>=n&&x()}catch(g){E(g)}})()}),b()})}_createSnapshotSurface(){let t=null,e=null;return r=>{const a=Math.max(1,r.width),i=Math.max(1,r.height),n=((u,l)=>(t||(t=document.createElement("canvas")),t.width!==u||t.height!==l?(t.width=u,t.height=l,e=t.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)):e||(e=t.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)),e?t:null))(a,i);return n&&e?(e.clearRect(0,0,a,i),e.drawImage(r,0,0,a,i),n):r}}}class $e{_recorder;_textmodifier;_registerPostDrawHook;constructor(t,e){this._recorder=new Me,this._textmodifier=t,this._registerPostDrawHook=e}async $saveWEBM(t={}){const e=this._textmodifier.canvas,r=this._applyDefaultOptions(t);try{const a=await this._recorder.$record(e,r,this._registerPostDrawHook,t.onProgress);new X().$downloadFile(a,r.filename)}catch(a){throw t.onProgress?.({state:"error",message:a instanceof Error?a.message:"WEBM export failed"}),a}}_applyDefaultOptions(t){return{filename:t.filename,frameRate:Math.abs(Math.round(t.frameRate??60)),frameCount:Math.abs(Math.round(t.frameCount??300)),quality:Math.abs(Math.min(Math.max(t.quality??1,0),1)),transparent:!!t.transparent,debugLogging:!!t.debugLogging}}}const Se="textmode-export-overlay",z="textmode-export-overlay__stack",dt="textmode-export-overlay__stack--dense",Tt="textmode-export-overlay__stack--compact",Rt="textmode-export-overlay__section",Le="textmode-export-overlay__header",Pe="textmode-export-overlay__header-title-row",Ae="textmode-export-overlay__header-links",Ve="textmode-export-overlay__row",Nt="textmode-export-overlay__label",zt="textmode-export-overlay__field",Gt="textmode-export-overlay__field--compact",Wt="textmode-export-overlay__field--dense",qt="textmode-export-overlay__field--full",Ht="textmode-export-overlay__field--channel",jt="textmode-export-overlay__input",De="textmode-export-overlay__checkbox",Qt="textmode-export-overlay__muted",Oe="textmode-export-overlay__status",Ue="textmode-export-overlay__status--gif",Te="textmode-export-overlay__status--video",Re="textmode-export-overlay__status-title",Ne="textmode-export-overlay__status-value",ze="textmode-export-overlay__divider",Ge="textmode-export-overlay__title",We="textmode-export-overlay__button",ct="textmode-export-overlay__button--primary",ut="textmode-export-overlay__button--secondary",Xt="textmode-export-overlay__button--full",qe="textmode-export-overlay__support-link",He="textmode-export-overlay__support-icon",je="textmode-export-overlay__link-icon";class N{element;mounted=!1;destroyed=!1;mount(t){if(this.destroyed)throw new Error("Cannot mount a destroyed component");if(this.mounted)return;const e=this.render();t.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(t){this.mounted&&this.onUpdate(t)}onMount(){}_onUnmount(){}_onDestroy(){}onUpdate(t){}get root(){if(!this.element)throw new Error("Component is not mounted yet");return this.element}isMounted(){return this.mounted}}class Y extends N{static _iconNamespace="http://www.w3.org/2000/svg";render(){const t=document.createElement("div");t.classList.add(z,dt,Le);const e=document.createElement("div");e.classList.add(Pe);const r=document.createElement("strong");r.textContent="textmode.export.js",r.classList.add(Ge);const a=document.createElement("div");a.classList.add(Ae);const i=this._createLink("https://github.com/humanbydefinition/textmode.export.js","View repository on GitHub",je,[{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/support.html","Support textmode.export.js",He,[{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(r),e.appendChild(a);const u=document.createElement("div");return u.classList.add(ze),t.appendChild(e),t.appendChild(u),t}_createLink(t,e,r,a){const i=document.createElement("a");return i.href=t,i.target="_blank",i.rel="noopener noreferrer",i.classList.add(qe),i.setAttribute("aria-label",e),i.appendChild(this._createIcon(r,a)),i}_createIcon(t,e){const r=document.createElementNS(Y._iconNamespace,"svg");r.setAttribute("xmlns",Y._iconNamespace),r.setAttribute("width","18"),r.setAttribute("height","18"),r.setAttribute("viewBox","0 0 24 24"),r.setAttribute("fill","none"),r.setAttribute("stroke","currentColor"),r.setAttribute("stroke-width","2"),r.setAttribute("stroke-linecap","round"),r.setAttribute("stroke-linejoin","round"),r.classList.add(t);for(const a of e){const i=document.createElementNS(Y._iconNamespace,"path");for(const[n,u]of Object.entries(a))i.setAttribute(n,u);r.appendChild(i)}return r}}class R extends N{props;constructor(t){super(),this.props=t}render(){const t=document.createElement("div");t.classList.add(zt),this.applyVariant(t,this.props.variant);const e=document.createElement("label");if(e.classList.add(Nt),e.textContent=this.props.label,this.props.labelFor&&(e.htmlFor=this.props.labelFor),t.appendChild(e),this.props.description){const r=document.createElement("span");r.classList.add(Qt),r.textContent=this.props.description,t.appendChild(r)}return t}attachControl(t){this.root.appendChild(t)}update(t){this.props=t,super.update(t)}onUpdate(t){const e=this.root;for(;e.firstChild;)e.removeChild(e.firstChild);this.props=t,e.classList.add(zt),this.applyVariant(e,t.variant);const r=document.createElement("label");if(r.classList.add(Nt),r.textContent=t.label,t.labelFor&&(r.htmlFor=t.labelFor),e.appendChild(r),t.description){const a=document.createElement("span");a.classList.add(Qt),a.textContent=t.description,e.appendChild(a)}}applyVariant(t,e){switch(t.classList.remove(Gt,Wt,qt,Ht),e){case"compact":t.classList.add(Gt);break;case"dense":t.classList.add(Wt);break;case"full":t.classList.add(qt);break;case"channel":t.classList.add(Ht)}}}class pt extends N{props;select;handleChange=()=>{this.props.defaultValue=this.select.value};constructor(t){super(),this.props=t}render(){return this.select=document.createElement("select"),this.select.classList.add(jt),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(t){this.select&&(this.select.value=t),this.props.defaultValue=t}_onUnmount(){this.select.removeEventListener("change",this.handleChange)}onUpdate(t){this.props=t,this.populateOptions(),t.defaultValue&&(this.select.value=t.defaultValue)}update(t){this.props={...this.props,...t},this.select&&(t.id&&(this.select.id=t.id),t.options&&this.populateOptions(),t.defaultValue!==void 0&&(this.select.value=t.defaultValue))}populateOptions(){if(this.select){this.select.innerHTML="";for(const t of this.props.options){const e=document.createElement("option");e.value=t.value,e.textContent=t.label,this.select.appendChild(e)}this.props.defaultValue&&(this.select.value=this.props.defaultValue)}}}class Yt extends N{props;button;constructor(t){super(),this.props=t}render(){return this.button=document.createElement("button"),this.button.type="button",this.button.textContent=this.props.label,this.button.classList.add(We),this.props.variant==="secondary"?this.button.classList.add(ut):this.button.classList.add(ct),this.props.fullWidth&&this.button.classList.add(Xt),this.button.disabled=!!this.props.disabled,this.button}get buttonElement(){return this.button}setLabel(t){this.props.label=t,this.button.textContent=t}setDisabled(t){this.props.disabled=t,this.button.disabled=t}onUpdate(t){this.props=t,this.button.textContent=t.label,this.button.disabled=!!t.disabled,t.variant==="secondary"?(this.button.classList.add(ut),this.button.classList.remove(ct)):(this.button.classList.add(ct),this.button.classList.remove(ut)),this.button.classList.toggle(Xt,!!t.fullWidth)}}class Qe{api;constructor(t){this.api=t}async $copy(t,e){switch(t){case"txt":{const r=this.api.toString(e);await navigator.clipboard.writeText(r);break}case"svg":{const r=this.api.toSVG(e);await navigator.clipboard.writeText(r);break}case"image":await this.api.copyCanvas(e);break;default:throw new Error(`Clipboard not supported for ${t}`)}}}class Xe{api;events;constructor(t,e){this.api=t,this.events=e}async $requestExport(t,e,r={}){this.events.$emit("export:request",{format:t});try{const a={onGIFProgress:r.onGIFProgress?i=>{r.onGIFProgress?.(i),this.events.$emit("export:progress",{format:t,progress:i})}:t==="gif"?i=>this.events.$emit("export:progress",{format:t,progress:i}):void 0,onVideoProgress:r.onVideoProgress?i=>{r.onVideoProgress?.(i),this.events.$emit("export:progress",{format:t,progress:i})}:t==="video"?i=>this.events.$emit("export:progress",{format:t,progress:i}):void 0};await this._execute(t,e,a),this.events.$emit("export:success",{format:t})}catch(a){throw this.events.$emit("export:error",{format:t,error:a}),a}}_execute(t,e,r){switch(t){case"txt":return Promise.resolve(this.api.saveStrings(e));case"image":return this.api.saveCanvas(e);case"svg":return Promise.resolve(this.api.saveSVG(e));case"gif":{const a={...e,onProgress:r.onGIFProgress};return this.api.saveGIF(a)}case"video":{const a={...e,onProgress:r.onVideoProgress};return this.api.saveWEBM(a)}}}}class Ye{modifier;overlay;animationFrameId=null;handleUpdate;bound=!1;constructor(t,e){this.modifier=t,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 t=this.modifier.canvas.getBoundingClientRect();this.overlay.style.top=`${t.top+window.scrollY+8}px`,this.overlay.style.left=`${t.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 J="textmode-export-number-input",Je=`${J}__field`,Ze=`${J}__controls`,Ke=`${J}__control`,Jt=`${J}__display`,at=`${Jt}--visible`,Zt=c=>{const t=document.createElement("button");return t.type="button",t.className=Ke,t.textContent=c>0?"▲":"▼",t};class q extends N{props;input;display;incrementButton;decrementButton;suppressClickAfterPointer=new WeakMap;holdTimeoutId;holdIntervalId;activePointerId;disabledObserver;constructor(t){super(),this.props=t}render(){const t=document.createElement("div");t.className=J,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=Je,this.display=document.createElement("div"),this.display.className=Jt;const e=document.createElement("div");return e.className=Ze,this.incrementButton=Zt(1),this.decrementButton=Zt(-1),e.appendChild(this.incrementButton),e.appendChild(this.decrementButton),t.appendChild(this.input),t.appendChild(this.display),t.appendChild(e),this.bindStepControls(),this.bindHoldBehavior(),this.bindInputListeners(),this.observeDisabledState(t),this.updateDisplay(),t}get inputElement(){return this.input}get value(){return this.input.value}set value(t){this.input.value=t,this.updateDisplay()}refresh(){this.updateDisplay()}_onDestroy(){this.clearHoldTimers(),this.disabledObserver?.disconnect()}bindStepControls(){const t=i=>()=>{if(this.input.disabled)return;const n=this.input.value,u=this.input.getAttribute("step");if(u&&u!=="any")i>0?this.input.stepUp():this.input.stepDown();else{const h=i>0?1:-1,o=Number.parseFloat(this.input.value||"0"),s=Number.isFinite(o)?o+h:h;this.input.value=String(s)}var l;this.input.value!==n&&((l=this.input).dispatchEvent(new Event("input",{bubbles:!0})),l.dispatchEvent(new Event("change",{bubbles:!0}))),this.updateDisplay(),this.input.focus({preventScroll:!0})},e=t(1),r=t(-1),a=(i,n)=>u=>{if(this.suppressClickAfterPointer.get(i))return this.suppressClickAfterPointer.set(i,!1),void u.preventDefault();n()};this.incrementButton.addEventListener("click",a(this.incrementButton,e)),this.decrementButton.addEventListener("click",a(this.decrementButton,r))}bindHoldBehavior(){const t=(e,r)=>{const a=r>0?()=>this.incrementButton.click():()=>this.decrementButton.click();e.addEventListener("pointerdown",u=>{if(u.button===0){u.preventDefault(),this.suppressClickAfterPointer.set(e,!0),this.activePointerId=u.pointerId;try{e.setPointerCapture(u.pointerId)}catch{}a(),this.holdTimeoutId=window.setTimeout(()=>{this.holdIntervalId=window.setInterval(a,80)},380)}});const i=()=>{if(this.activePointerId!==void 0){try{e.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}},n=()=>{this.clearHoldTimers(),i()};e.addEventListener("pointerup",n),e.addEventListener("pointerleave",n),e.addEventListener("pointercancel",n)};t(this.incrementButton,1),t(this.decrementButton,-1)}bindInputListeners(){const t=()=>{this.props.defaultValue=this.input.value,this.updateDisplay()};this.input.addEventListener("input",t),this.input.addEventListener("change",t)}observeDisabledState(t){const e=()=>{const r=this.input.disabled;this.incrementButton.disabled=r,this.decrementButton.disabled=r,t.classList.toggle("is-disabled",r),r?(this.display.classList.remove(at),this.input.style.removeProperty("color"),this.input.style.removeProperty("caretColor")):this.updateDisplay()};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(e),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),e()}updateDisplay(){const t=this.props.formatDisplay;if(!t)return this.display.textContent="",this.display.classList.remove(at),this.input.style.removeProperty("color"),void this.input.style.removeProperty("caretColor");const e=this.input.value,r=Number.parseFloat(e),a=t(Number.isFinite(r)?r:Number.NaN,e,this.input);a?(this.display.textContent=a,this.display.classList.add(at),this.input.style.color="transparent",this.input.style.caretColor="#f8fafc"):(this.display.textContent="",this.display.classList.remove(at),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 Z extends N{variant;additionalClasses;constructor(t="stack",e=[]){super(),this.variant=t,this.additionalClasses=e}render(){const t=document.createElement("div"),e=[this.variant==="stack"?z:void 0,this.variant==="stackDense"?dt:void 0,this.variant==="stackCompact"?Tt:void 0,this.variant==="row"?Ve:void 0,this.variant==="section"?Rt:void 0,...this.additionalClasses].filter(Boolean);return t.classList.add(...e),t}}const Kt={neutral:"textmode-export-overlay__status-value--neutral",active:"textmode-export-overlay__status-value--active",alert:"textmode-export-overlay__status-value--alert"};class te extends N{props;container;messageElement;constructor(t){super(),this.props=t}render(){this.container=document.createElement("div"),this.container.classList.add(Oe),this.props.context==="gif"?this.container.classList.add(Ue):this.props.context==="video"&&this.container.classList.add(Te);const t=document.createElement("span");return t.classList.add(Re),t.textContent=this.props.title,this.messageElement=document.createElement("span"),this.messageElement.classList.add(Ne),this.messageElement.textContent=this.props.message,this.applyVariant(this.props.variant??"neutral"),this.container.appendChild(t),this.container.appendChild(this.messageElement),this.container}setMessage(t,e="neutral"){this.messageElement.textContent=t,this.applyVariant(e)}onUpdate(t){this.props=t,this.setMessage(t.message,t.variant??"neutral")}applyVariant(t){this.messageElement.classList.remove(...Object.values(Kt)),this.messageElement.classList.add(Kt[t])}}class K extends N{_config;_managedComponents=new Set;constructor(t){super(),this._config=t}_manageComponent(t){return this._managedComponents.add(t),t}_onUnmount(){for(const t of this._managedComponents)t.unmount()}_onDestroy(){for(const t of this._managedComponents)t.destroy();this._managedComponents.clear()}}const ee=300,re=60,ae=1,tr=0;class ht extends K{frameCountInput=this._manageComponent(new q({defaultValue:String(ee),attributes:{min:"1",max:"600",step:"1"}}));frameRateInput=this._manageComponent(new q({defaultValue:String(re),attributes:{min:"1",max:"60",step:"1"}}));scaleInput=this._manageComponent(new q({defaultValue:String(ae),attributes:{min:"0.1",max:"8",step:"0.1"}}));repeatInput=this._manageComponent(new q({defaultValue:"0",attributes:{min:"0",max:"50",step:"1"},formatDisplay:(t,e)=>Number.isFinite(t)?t===0?"∞":null:e.trim()===""?null:e}));status=this._manageComponent(new te({title:"status",message:"ready to record",variant:"neutral",context:"gif"}));recordingState="idle";constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z);const e=new Z("row");e.mount(t);const r=new R({label:"number of frames",labelFor:"textmode-export-gif-frame-count",variant:"dense"});r.mount(e.root),this.frameCountInput.mount(r.root),this.frameCountInput.inputElement.id="textmode-export-gif-frame-count";const a=new R({label:"frame rate (fps)",labelFor:"textmode-export-gif-frame-rate",variant:"dense"});a.mount(e.root),this.frameRateInput.mount(a.root),this.frameRateInput.inputElement.id="textmode-export-gif-frame-rate";const i=new Z("row");i.mount(t);const n=new R({label:"scale",labelFor:"textmode-export-gif-scale",variant:"dense"});n.mount(i.root),this.scaleInput.mount(n.root),this.scaleInput.inputElement.id="textmode-export-gif-scale";const u=new R({label:"loop count",labelFor:"textmode-export-gif-repeat",variant:"dense"});return u.mount(i.root),this.repeatInput.mount(u.root),this.repeatInput.inputElement.id="textmode-export-gif-repeat",this.status.mount(t),t}getOptions(){const t=this._config.defaultOptions??{};return{frameCount:this.safeParseInt(this.frameCountInput.value,t.frameCount??300),frameRate:this.safeParseInt(this.frameRateInput.value,t.frameRate??60),scale:this.safeParseFloat(this.scaleInput.value,t.scale??1),repeat:this.safeParseInt(this.repeatInput.value,t.repeat??0)}}reset(){this.recordingState="idle",this.applyDefaults(),this.setRecordingState("idle")}validate(){const t=Number.parseInt(this.frameCountInput.value,10),e=Number.parseInt(this.frameRateInput.value,10),r=Number.parseFloat(this.scaleInput.value);return Number.isFinite(t)&&t>0&&Number.isFinite(e)&&e>0&&Number.isFinite(r)&&r>0}isRecording(){return this.recordingState==="recording"}setRecordingState(t,e){this.recordingState=t;const r=t==="recording";switch(this.frameCountInput.inputElement.disabled=r,this.frameRateInput.inputElement.disabled=r,this.scaleInput.inputElement.disabled=r,this.repeatInput.inputElement.disabled=r,t){case"recording":if(e?.totalFrames){const a=e.frameIndex??0;this.status.setMessage(`recording ${a}/${e.totalFrames}`,"active")}else this.status.setMessage("recording…","active");break;case"completed":this.status.setMessage("GIF saved successfully","active");break;case"error":this.status.setMessage(e?.message??"failed to export GIF","alert");break;default:this.status.setMessage("ready to record","neutral")}}handleProgress(t){t.state==="recording"&&t.totalFrames?this.status.setMessage(`recording ${t.frameIndex??0}/${t.totalFrames}`,"active"):t.state==="completed"?this.status.setMessage("GIF saved successfully","active"):t.state==="error"&&this.status.setMessage(t.message??"failed to export GIF","alert")}applyDefaults(){const t=this._config.defaultOptions??{},e=t.frameCount??ee,r=t.frameRate??re,a=t.scale??ae,i=t.repeat??tr;this.frameCountInput.value=String(e),this.frameRateInput.value=String(r),this.scaleInput.value=String(a),this.repeatInput.value=String(i),this.frameCountInput.refresh(),this.frameRateInput.refresh(),this.scaleInput.refresh(),this.repeatInput.refresh()}safeParseInt(t,e){const r=Number.parseInt(t,10);return Number.isFinite(r)?r:e}safeParseFloat(t,e){const r=Number.parseFloat(t);return Number.isFinite(r)?r:e}}const it="textmode-export-range-input",er=`${it}__field`,rr=`${it}__tooltip`,mt=`${it}__tooltip--visible`,ot=(c,t)=>{if(typeof c!="string"||c.length===0)return t;const e=Number.parseFloat(c);return Number.isFinite(e)?e:t};class ar extends N{props;input;tooltip;hoverActive=!1;focusActive=!1;pointerActive=!1;suppressFocusFromPointer=!1;activePointerId;disabledObserver;resizeObserver;constructor(t){super(),this.props=t}render(){const t=document.createElement("div");return t.className=it,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=er,this.tooltip=document.createElement("div"),this.tooltip.className=rr,t.appendChild(this.input),t.appendChild(this.tooltip),this.bindEvents(t),this.updateTooltip(),this.syncDisabledState(t),t}get inputElement(){return this.input}get value(){return this.input.value}set value(t){this.input.value=t,this.updateTooltip()}_onDestroy(){this.disabledObserver?.disconnect(),this.resizeObserver?.disconnect()}bindEvents(t){this.input.addEventListener("pointerenter",()=>{this.hoverActive=!0,this.refreshTooltipVisibility()}),this.input.addEventListener("pointerleave",()=>{this.hoverActive=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("focus",()=>{let r=!1;try{r=this.input.matches(":focus-visible")}catch{r=!this.suppressFocusFromPointer}this.suppressFocusFromPointer||!r||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",r=>{this.pointerActive=!0,this.suppressFocusFromPointer=!0,this.hoverActive=!0,this.refreshTooltipVisibility();try{this.input.setPointerCapture(r.pointerId),this.activePointerId=r.pointerId}catch{this.activePointerId=void 0}});const e=()=>{this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.hoverActive=this.input.matches(":hover"),this.releasePointerCapture(),this.refreshTooltipVisibility()};this.input.addEventListener("pointerup",e),this.input.addEventListener("pointercancel",e),this.input.addEventListener("lostpointercapture",e),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(mt)&&this.updateTooltipPosition()}),this.resizeObserver.observe(t))}refreshTooltipVisibility(){const t=(this.hoverActive||this.focusActive||this.pointerActive)&&!this.input.disabled;t&&this.updateTooltip(),this.tooltip.classList.toggle(mt,t)}syncDisabledState(t){const e=()=>{const r=this.input.disabled;t.classList.toggle("is-disabled",r),r&&(this.hoverActive=!1,this.focusActive=!1,this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.releasePointerCapture(),this.tooltip.classList.remove(mt))};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(e),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),e()}releasePointerCapture(){if(this.activePointerId!==void 0){try{this.input.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}}updateTooltip(){this.updateTooltipContent(),this.updateTooltipPosition()}updateTooltipContent(){const t=this.props.formatValue??(r=>`${r}`),e=this.getCurrentValue();this.tooltip.textContent=t(e,this.input)}updateTooltipPosition(){const t=this.getMin(),e=this.getMax(),r=((n,u,l)=>Math.min(l,Math.max(u,n)))(this.getCurrentValue(),t,e),a=e-t,i=a===0?0:(r-t)/a;this.tooltip.style.left=100*i+"%"}getMin(){return ot(this.input.min,0)}getMax(){return ot(this.input.max,100)}getCurrentValue(){return ot(this.input.value,ot(this.props.defaultValue,0))}}function ir(c){return`${(function(e){if(!Number.isFinite(e))return"default quality";const r=Math.max(0,Math.min(1,e));return r>=.995?"near-lossless":r>=.98?"maximum detail":r>=.88?"ultra quality":r>=.7?"high quality":r>=.5?"balanced":r>=.25?"compact":r>=.1?"lightweight":"draft"})(c)} (quality ≈ ${c.toFixed(3)})`}class ft extends K{frameRateInput=this._manageComponent(new q({defaultValue:String(60),attributes:{min:String(1),max:String(60),step:"1"},formatDisplay:t=>Number.isFinite(t)?`${t} fps`:null}));frameCountInput=this._manageComponent(new q({defaultValue:String(480),attributes:{min:String(1),max:String(3600),step:"1"}}));qualityInput=this._manageComponent(new ar({defaultValue:String(.7),attributes:{min:String(0),max:String(1),step:"0.001"},formatValue:t=>ir(t)}));status=this._manageComponent(new te({title:"status",message:"ready to record",variant:"neutral",context:"video"}));recordingState="idle";constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z);const e=new Z("row");e.mount(t);const r=new R({label:"number of frames",labelFor:"textmode-export-video-frame-count",variant:"compact"});r.mount(e.root),this.frameCountInput.mount(r.root),this.frameCountInput.inputElement.id="textmode-export-video-frame-count";const a=new R({label:"frame rate (fps)",labelFor:"textmode-export-video-frame-rate",variant:"compact"});a.mount(e.root),this.frameRateInput.mount(a.root),this.frameRateInput.inputElement.id="textmode-export-video-frame-rate";const i=new R({label:"quality",labelFor:"textmode-export-video-quality",variant:"full"});return i.mount(t),this.qualityInput.mount(i.root),this.qualityInput.inputElement.id="textmode-export-video-quality",this.status.mount(t),t}getOptions(){const t=this._config.defaultOptions??{},e=Number.parseInt(this.frameCountInput.value,10),r=Number.parseFloat(this.frameRateInput.value),a=Number.parseFloat(this.qualityInput.value);return{frameCount:Number.isFinite(e)?e:t.frameCount??480,frameRate:Number.isFinite(r)?r:t.frameRate??60,quality:Number.isFinite(a)?a:t.quality??.7}}reset(){this.recordingState="idle",this.applyDefaults(),this.status.setMessage("ready to record","neutral")}validate(){const t=Number.parseInt(this.frameCountInput.value,10),e=Number.parseFloat(this.frameRateInput.value);return Number.isFinite(t)&&t>=1&&Number.isFinite(e)&&e>=1}isRecording(){return this.recordingState==="recording"}setRecordingState(t,e){this.recordingState=t;const r=t==="recording";this.frameCountInput.inputElement.disabled=r,this.frameRateInput.inputElement.disabled=r,this.qualityInput.inputElement.disabled=r,this.syncStatus(t,e)}handleProgress(t){this.syncStatus(t.state,t)}syncStatus(t,e){switch(t){case"recording":{const r=e?.frameIndex??0,a=e?.totalFrames??this.resolvePlannedFrameCount();if(a){const i=Math.min(Math.max(0,Math.round(r)),a);this.status.setMessage(`recording ${i}/${a} frames`,"active")}else this.status.setMessage(`recording ${Math.max(0,Math.round(r))} frames`,"active");break}case"completed":this.status.setMessage("saved to disk","active");break;case"error":this.status.setMessage(e?.message?`error: ${e.message}`:"recording failed","alert");break;default:this.status.setMessage("ready to record","neutral")}}resolvePlannedFrameCount(){const t=Number.parseInt(this.frameCountInput.value,10);return Number.isFinite(t)&&t>0?Math.round(t):void 0}applyDefaults(){const t=this._config.defaultOptions??{},e=t.frameCount??480,r=t.frameRate??60,a=t.quality??.7;this.frameCountInput.value=String(e),this.frameRateInput.value=String(r),this.qualityInput.value=String(a),this.frameCountInput.refresh(),this.frameRateInput.refresh()}}class or{_textmodifier;_state;_events;_exportService;_clipboardService;_definitions;_formats=new Map;_eventUnsubscribers=[];_shadowHost;_shadowRoot;_overlayElement;_optionsContainer;_copyButtonContainer;_positionService;_header=new Y;_formatField=new R({label:"export format",labelFor:"textmode-export-format",variant:"full"});_formatSelect=new pt({id:"textmode-export-format",options:[]});_exportButton=new Yt({label:"download file",fullWidth:!0,variant:"primary"});_copyButton=new Yt({label:"copy to clipboard",fullWidth:!0,variant:"primary"});_currentFormat;_currentBlade;_handleFormatSelectChange=()=>{this._handleFormatChange(this._formatSelect.value)};_handleExportClickSafe=()=>{this._handleExportClick().catch(t=>{console.error("[textmode-export] Export failed",t)})};_handleCopyClickSafe=()=>{this._handleCopyClick().catch(t=>{console.error("[textmode-export] Copy failed",t)})};constructor(t,e,r,a,i){this._textmodifier=t,this._state=r,this._events=a,this._exportService=new Xe(e,a),this._clipboardService=new Qe(e),this._definitions=i,this._currentFormat=r.snapshot.format,this._initializeFormatMap(),this._registerEventHandlers()}$mount(){this._createOverlay(),this._renderStaticContent(),this._positionService=new Ye(this._textmodifier,this._shadowHost),this._positionService.bind(),this._switchFormat(this._currentFormat)}$dispose(){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,this._shadowHost?.isConnected&&this._shadowHost.remove(),this._positionService?.dispose()}_initializeFormatMap(){for(const t of this._definitions){const e=t.createBlade();this._formats.set(t.format,{definition:t,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 t=document.createElement("style");t.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;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;inset: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;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(t),this._overlayElement=document.createElement("div"),this._overlayElement.dataset.plugin="textmode-export-overlay",this._overlayElement.classList.add(Se,z),this._shadowRoot.appendChild(this._overlayElement),document.body.appendChild(this._shadowHost)}_renderStaticContent(){this._header.mount(this._overlayElement);const t=document.createElement("div");t.classList.add(Rt),this._overlayElement.appendChild(t),this._formatField.mount(t),this._prepareFormatOptions(),this._formatSelect.mount(this._formatField.root),this._formatSelect.selectElement.addEventListener("change",this._handleFormatSelectChange),this._optionsContainer=document.createElement("div"),this._optionsContainer.classList.add(z,Tt),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(z,dt),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 t=this._definitions.map(e=>({value:e.format,label:e.label}));this._formatSelect.update({options:t,defaultValue:this._currentFormat})}_registerEventHandlers(){this._eventUnsubscribers.push(this._events.$on("export:request",({format:t})=>{t===this._currentFormat&&(this._state.$set({isBusy:!0,error:void 0}),this._updateExportButton())}),this._events.$on("export:success",({format:t})=>{if(t===this._currentFormat){const e={isBusy:!1};t==="gif"&&(e.gifProgress=void 0),t==="video"&&(e.videoProgress=void 0),this._state.$set(e),this._updateExportButton()}}),this._events.$on("export:error",({format:t,error:e})=>{t===this._currentFormat&&(this._state.$set({isBusy:!1,error:e}),this._updateExportButton())}),this._events.$on("export:progress",({format:t,progress:e})=>{if(e){if(t==="gif"&&this._currentBlade?.blade instanceof ht){const r=e;this._state.$set({gifProgress:r}),this._currentBlade.blade.handleProgress(r)}else if(t==="video"&&this._currentBlade?.blade instanceof ft){const r=e;this._state.$set({videoProgress:r}),this._currentBlade.blade.handleProgress(r)}this._updateExportButton()}}))}_handleFormatChange(t){this._currentFormat=t,this._state.$set({format:t}),this._switchFormat(t),this._events.$emit("format:change",{format:t})}_switchFormat(t){const e=this._formats.get(t);if(!e)throw new Error(`Unknown export format: ${t}`);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=t,this._updateCopyButtonState(),this._updateExportButton(),this._positionService?.scheduleUpdate()}_updateCopyButtonState(){const t=this._currentBlade?.definition.supportsClipboard??!1;this._copyButtonContainer.style.display=t?"flex":"none",this._copyButton.setDisabled(!t)}async _handleExportClick(){if(!this._currentBlade)return;const t=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions();if(this._currentBlade.blade.validate()){if(t==="gif"){const r=this._currentBlade.blade;if(r.isRecording())return;r.setRecordingState("recording");try{await this._exportService.$requestExport("gif",e,{onGIFProgress:a=>{r.setRecordingState(a.state,a)}})}catch(a){throw r.setRecordingState("error"),a}return void window.setTimeout(()=>{r.setRecordingState("idle"),this._updateExportButton()},1600)}if(t==="video"){const r=this._currentBlade.blade;if(r.isRecording())return;r.setRecordingState("recording");try{await this._exportService.$requestExport("video",e,{onVideoProgress:a=>{r.setRecordingState(a.state,a)}})}catch(a){throw r.setRecordingState("error"),a}return void window.setTimeout(()=>{r.setRecordingState("idle"),this._updateExportButton()},1600)}this._exportButton.setDisabled(!0),this._exportButton.setLabel("exporting…");try{await this._exportService.$requestExport(t,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 t=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions(),r=this._copyButton.buttonElement.dataset.defaultLabel??"copy to clipboard";this._copyButton.setDisabled(!0),this._copyButton.setLabel("copying…");try{await this._clipboardService.$copy(t,e),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(r),this._copyButton.setDisabled(!1)},1200)}}_updateExportButton(){if(!this._currentBlade)return;const t=this._currentBlade.definition.format;if(t==="gif"&&this._currentBlade.blade instanceof ht){const r=this._currentBlade.blade,a=this._state.snapshot.gifProgress;if(r.isRecording())if(this._exportButton.setDisabled(!0),a?.totalFrames){const i=a.frameIndex??0;this._exportButton.setLabel(`recording ${i}/${a.totalFrames}`)}else this._exportButton.setLabel("recording…");else this._exportButton.setDisabled(!1),this._exportButton.setLabel("start recording");return}if(t==="video"&&this._currentBlade.blade instanceof ft){const r=this._currentBlade.blade,a=this._state.snapshot.videoProgress;if(r.isRecording())if(this._exportButton.setDisabled(!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 nr{_listeners=new Map;$on(t,e){this._listeners.has(t)||this._listeners.set(t,new Set);const r=this._listeners.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&this._listeners.delete(t)}}$emit(t,e){const r=this._listeners.get(t);if(r)for(const a of[...r])try{a(e)}catch(i){console.error("[textmode-export] Event handler failed",i)}}$clear(){this._listeners.clear()}}class sr{_state;_listeners=new Set;constructor(t){this._state=t}get snapshot(){return Object.freeze({...this._state})}$set(t){this._state=Object.assign({},this._state,t);const e=this.snapshot;for(const r of[...this._listeners])try{r(e)}catch(a){console.error("[textmode-export] State listener failed",a)}}$subscribe(t){return this._listeners.add(t),t(this.snapshot),()=>{this._listeners.delete(t)}}$reset(t){this._state=t;const e=this.snapshot;for(const r of[...this._listeners])r(e)}}class ie extends N{props;checkbox;labelElement;handleChange=()=>{this.props.defaultChecked=this.checkbox.checked};constructor(t){super(),this.props=t}render(){this.labelElement=document.createElement("label"),this.labelElement.classList.add(De),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 t=document.createElement("span");return t.textContent=this.props.label,this.labelElement.htmlFor=this.props.id??"",this.labelElement.appendChild(this.checkbox),this.labelElement.appendChild(t),this.labelElement}get inputElement(){return this.checkbox}get checked(){return this.checkbox.checked}set checked(t){this.checkbox.checked=t}_onUnmount(){this.checkbox.removeEventListener("change",this.handleChange)}onUpdate(t){this.props=t,t.id&&(this.checkbox.id=t.id,this.labelElement.htmlFor=t.id),this.checkbox.checked=!!t.defaultChecked,this.labelElement.lastElementChild&&(this.labelElement.lastElementChild.textContent=t.label)}}class lr extends N{props;input;handleInput=()=>{this.props.defaultValue=this.input.value};constructor(t){super(),this.props=t}render(){return this.input=document.createElement("input"),this.input.type="text",this.input.classList.add(jt),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(t){this.input.value=t}_onUnmount(){this.input.removeEventListener("input",this.handleInput)}onUpdate(t){this.props=t,t.id&&(this.input.id=t.id),t.maxLength!==void 0&&(this.input.maxLength=t.maxLength),t.defaultValue!==void 0&&(this.input.value=t.defaultValue)}}class dr extends K{trailingSpaces=this._manageComponent(new ie({label:"preserve trailing spaces",defaultChecked:!1}));emptyCharacter=this._manageComponent(new lr({id:"textmode-export-empty-character",defaultValue:" ",maxLength:1}));constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z),this.trailingSpaces.mount(t);const e=new R({label:"empty character",labelFor:"textmode-export-empty-character",variant:"full"});return e.mount(t),this.emptyCharacter.mount(e.root),t}getOptions(){const t=this._config.defaultOptions??{},e=this.emptyCharacter.value||t.emptyCharacter||" ";return{preserveTrailingSpaces:this.trailingSpaces.checked,emptyCharacter:e}}reset(){this.applyDefaults()}validate(){return this.emptyCharacter.value.length<=1}applyDefaults(){const t=this._config.defaultOptions??{};this.trailingSpaces.checked=t.preserveTrailingSpaces??!1,this.emptyCharacter.value=t.emptyCharacter??" "}}class cr extends K{formatSelect=this._manageComponent(new pt({id:"textmode-export-image-format",options:[{value:"png",label:`PNG (${de})`},{value:"jpg",label:`JPG (${ce})`},{value:"webp",label:`WEBP (${ue})`}],defaultValue:"png"}));scaleInput=this._manageComponent(new q({defaultValue:"1",attributes:{min:"0.1",step:"0.1"}}));constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z);const e=new Z("row");e.mount(t);const r=new R({label:"image format",labelFor:"textmode-export-image-format",variant:"compact"});r.mount(e.root),this.formatSelect.mount(r.root);const a=new R({label:"scale",labelFor:"textmode-export-image-scale",variant:"dense"});return a.mount(e.root),this.scaleInput.mount(a.root),this.scaleInput.inputElement.id="textmode-export-image-scale",t}getOptions(){const t=Number.parseFloat(this.scaleInput.value);return{format:this.formatSelect.value,scale:Number.isFinite(t)?t:this._config.defaultOptions?.scale??1}}reset(){this.applyDefaults(),this.scaleInput.refresh()}validate(){const t=Number.parseFloat(this.scaleInput.value);return Number.isFinite(t)&&t>0}applyDefaults(){const t=this._config.defaultOptions??{};this.formatSelect.value=t.format??"png";const e=t.scale??1;this.scaleInput.value=String(e)}}class ur extends K{includeBackground=this._manageComponent(new ie({id:"textmode-export-svg-include-backgrounds",label:"include cell backgrounds",defaultChecked:!0}));drawMode=this._manageComponent(new pt({id:"textmode-export-svg-draw-mode",options:[{value:"fill",label:"fill"},{value:"stroke",label:"stroke"}],defaultValue:"fill"}));strokeWidth=this._manageComponent(new q({defaultValue:"1",attributes:{min:"0",step:"0.1"}}));constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z),this.includeBackground.mount(t);const e=new Z("row");e.mount(t);const r=new R({label:"draw mode",labelFor:"textmode-export-svg-draw-mode",variant:"compact"});r.mount(e.root),this.drawMode.mount(r.root);const a=new R({label:"stroke width",labelFor:"textmode-export-svg-stroke-width",variant:"compact"});return a.mount(e.root),this.strokeWidth.mount(a.root),this.strokeWidth.inputElement.id="textmode-export-svg-stroke-width",this.drawMode.selectElement.addEventListener("change",()=>this.updateStrokeControls()),this.updateStrokeControls(),t}getOptions(){return{includeBackgroundRectangles:this.includeBackground.checked,drawMode:this.drawMode.value,strokeWidth:Number.parseFloat(this.strokeWidth.value)}}reset(){this.applyDefaults(),this.updateStrokeControls()}validate(){const t=Number.parseFloat(this.strokeWidth.value);return this.drawMode.value!=="stroke"||Number.isFinite(t)&&t>=0}updateStrokeControls(){const t=this.drawMode.value==="stroke";this.strokeWidth.inputElement.disabled=!t,this.strokeWidth.refresh()}applyDefaults(){const t=this._config.defaultOptions??{};this.includeBackground.checked=t.includeBackgroundRectangles??!0,this.drawMode.value=t.drawMode??"fill";const e=t.strokeWidth??1;this.strokeWidth.value=String(e),this.strokeWidth.refresh()}}const pr=[{format:"txt",label:"plain text (.txt)",supportsClipboard:!0,createBlade:()=>new dr({format:"txt",label:"plain text (.txt)",supportsClipboard:!0,defaultOptions:{preserveTrailingSpaces:!1,emptyCharacter:" "}})},{format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,createBlade:()=>new cr({format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,defaultOptions:{format:"png",scale:1}})},{format:"svg",label:"vector (.svg)",supportsClipboard:!0,createBlade:()=>new ur({format:"svg",label:"vector (.svg)",supportsClipboard:!0,defaultOptions:{includeBackgroundRectangles:!0,drawMode:"fill",strokeWidth:1}})},{format:"gif",label:"animated GIF (.gif)",supportsClipboard:!1,createBlade:()=>new ht({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 ft({format:"video",label:"video (.webm)",supportsClipboard:!1,defaultOptions:{frameCount:480,frameRate:60,quality:.7}})}];function hr(c,t){const e=pr,r=e[0]?.format,a=new sr((u=>({format:u,isBusy:!1}))(r)),i=new nr,n=new or(c,t,a,i,e);return n.$mount(),n}const oe=(c={})=>{const t=c.overlay??!0;let e;return{name:"textmode-export",version:"1.0.0",async install(r,a){const i={saveCanvas:async(n={})=>new yt().$saveImage(r.canvas,n),copyCanvas:async(n={})=>new yt().$copyImageToClipboard(r.canvas,n),saveSVG:(n={})=>{new xt().$saveSVG(r,n)},saveStrings:(n={})=>{new _t().$saveTXT(r,n)},toSVG:(n={})=>new xt().$generateSVG(r,n),toString:(n={})=>new _t().$generateTXT(r,n),saveGIF:async(n={})=>new we(r,a.registerPostDrawHook).$saveGIF(n),saveWEBM:async(n={})=>new $e(r,a.registerPostDrawHook).$saveWEBM(n)};Object.assign(r,i),t&&(e=hr(r,i))},async uninstall(r){e?.$dispose(),e=void 0;const a=["saveCanvas","copyCanvas","saveSVG","saveStrings","toSVG","toString","saveGIF","saveWEBM"];for(const i of a)delete r[i]}}};typeof window<"u"&&(window.createTextmodeExportPlugin=oe),Q.createTextmodeExportPlugin=oe,Object.defineProperty(Q,Symbol.toStringTag,{value:"Module"})});
1
+ (function(j,Q){typeof exports=="object"&&typeof module<"u"?Q(exports):typeof define=="function"&&define.amd?define(["exports"],Q):Q((j=typeof globalThis<"u"?globalThis:j||self).TextmodeExport={})})(this,function(j){"use strict";class Q{$extractFramebufferData(t){return{characterPixels:t.readPixels(0),primaryColorPixels:t.readPixels(1),secondaryColorPixels:t.readPixels(2)}}$getCharacterIndex(t,e){return t[e]+(t[e+1]<<8)}}class X{$downloadFile(t,e){try{const r=this._sanitizeFilename(e),a=URL.createObjectURL(t),i=document.createElement("a");i.href=a,i.download=r,i.style.display="none",i.rel="noopener",document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(a)}catch(r){console.error("[textmode-export] Failed to download file:",r)}}_sanitizeFilename(t){if(!t)return this._generateDefaultFilename();const e=t.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,"-")}`}}function xt(c,t){return{r:c[t],g:c[t+1],b:c[t+2],a:c[t+3]}}class se extends Q{_extractTransformData(t,e){const r=t[e+2],a=!!(1&r),i=!!(2&r),n=!!(4&r),l=t[e+3]/255;return{isInverted:a,flipHorizontal:i,flipVertical:n,rotation:Math.round(360*l*100)/100}}_calculateCellPosition(t,e,r){return{x:t,y:e,cellX:t*r.cellWidth,cellY:e*r.cellHeight}}$extractSVGCellData(t,e){const r=[];let a=0;for(let i=0;i<e.rows;i++)for(let n=0;n<e.cols;n++){const l=4*a,d=this.$getCharacterIndex(t.characterPixels,l);let p=xt(t.primaryColorPixels,l),o=xt(t.secondaryColorPixels,l);const s=this._extractTransformData(t.characterPixels,l);if(s.isInverted){const m=p;p=o,o=m}const u=this._calculateCellPosition(n,i,e);r.push({charIndex:d,primaryColor:p,secondaryColor:o,transform:s,position:u}),a++}return r}}class le{_createGlyphPath(t,e,r,a,i){const n=i/t.head.unitsPerEm;return{getBoundingBox:()=>({x1:r+e.xMin*n,y1:a+-e.yMax*n,x2:r+e.xMax*n,y2:a+-e.yMin*n}),toSVG:()=>this._glyphToSVGPath(e,r,a,n)}}_glyphToSVGPath(t,e,r,a){if(!t||!t.xs)return"";const{xs:i,ys:n,endPts:l,flags:d}=t;if(!(i&&n&&l&&d))return"";let p="",o=0;for(let s=0;s<l.length;s++){const u=l[s];if(!(u<o)){if(u>=o){const m=e+i[o]*a,x=r-n[o]*a;p+=`M${m.toFixed(2)},${x.toFixed(2)}`;let h=o+1;for(;h<=u;)if(1&d[h]){const b=e+i[h]*a,w=r-n[h]*a;p+=`L${b.toFixed(2)},${w.toFixed(2)}`,h++}else{const b=e+i[h]*a,w=r-n[h]*a,v=h+1>u?o:h+1;if(1&d[v]){const g=e+i[v]*a,k=r-n[v]*a;p+=`Q${b.toFixed(2)},${w.toFixed(2)} ${g.toFixed(2)},${k.toFixed(2)}`,h=v+1}else{const g=(b+(e+i[v]*a))/2,k=(w+(r-n[v]*a))/2;p+=`Q${b.toFixed(2)},${w.toFixed(2)} ${g.toFixed(2)},${k.toFixed(2)}`,h=v}}p+="Z"}o=u+1}}return p}_generateCharacterPath(t,e,r,a,i){const n=e.characterMap.get(t)?.glyphData;return n?this._createGlyphPath(e.font,n,r,a,i):null}$generatePositionedCharacterPath(t,e,r,a,i,n,l,d){if(!d)return null;const p=l/e.font.head.unitsPerEm,o=r+(i-d.advanceWidth*p)/2,s=a+(n+.7*l)/2,u=this._generateCharacterPath(t,e,o,s,l);return u&&u.toSVG()||null}}class de{_pathGenerator;constructor(){this._pathGenerator=new le}$generateSVGHeader(t){const{width:e,height:r}=t;return`<?xml version="1.0" encoding="UTF-8"?><svg width="${e}" height="${r}" viewBox="0 0 ${e} ${r}" xmlns="http://www.w3.org/2000/svg"><title>textmode.js sketch</title>`}$generateSVGFooter(){return"</g></svg>"}_generateTransformAttribute(t,e){const{transform:r,position:a}=t;if(!r.flipHorizontal&&!r.flipVertical&&!r.rotation)return"";const i=a.cellX+e.cellWidth/2,n=a.cellY+e.cellHeight/2,l=[];if(r.flipHorizontal||r.flipVertical){const d=r.flipHorizontal?-1:1,p=r.flipVertical?-1:1;l.push(`translate(${i} ${n})scale(${d} ${p})translate(${-i} ${-n})`)}return r.rotation&&l.push(`rotate(${r.rotation} ${i} ${n})`),` transform="${l.join(" ")}"`}_generateCellBackground(t,e,r){if(!r.includeBackgroundRectangles||t.secondaryColor.a===0)return"";const{position:a}=t,{r:i,g:n,b:l,a:d}=t.secondaryColor,p=`rgba(${i},${n},${l},${d/255})`;return r.drawMode==="stroke"?`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" stroke="${p}" fill="none" stroke-width="${r.strokeWidth}"/>`:`<rect x="${a.cellX}" y="${a.cellY}" width="${e.cellWidth}" height="${e.cellHeight}" fill="${p}"/>`}_generateCharacterPath(t,e,r,a){const i=r.characters[t.charIndex];if(!i)return"";const n=this._pathGenerator.$generatePositionedCharacterPath(i.character,r,t.position.cellX,t.position.cellY,e.cellWidth,e.cellHeight,r.fontSize,i.glyphData);if(!n)return"";const{r:l,g:d,b:p,a:o}=t.primaryColor,s=`rgba(${l},${d},${p},${o/255})`;return a.drawMode==="stroke"?`<path d="${n}" stroke="${s}" stroke-width="${a.strokeWidth}" fill="none"/>`:`<path d="${n}" fill="${s}"/>`}$generateCellContent(t,e,r,a){const i=[],n=this._generateCellBackground(t,e,a);n&&i.push(n);const l=this._generateCharacterPath(t,e,r,a);if(l){const d=this._generateTransformAttribute(t,e);i.push(d?`<g${d}>${l}</g>`:l)}return i.join("")}$generateSVGContent(t,e,r,a){const i=[this.$generateSVGHeader(e),'<g id="ascii-cells">'];for(const n of t)i.push(this.$generateCellContent(n,e,r,a));return i.push(this.$generateSVGFooter()),i.join("")}$optimizeSVGContent(t){return t.replace(/\s+/g," ").replace(/> </g,"><")}}class yt{_applyDefaultOptions(t){return{includeBackgroundRectangles:t.includeBackgroundRectangles??!0,drawMode:t.drawMode??"fill",strokeWidth:t.strokeWidth??1,filename:t.filename}}$generateSVG(t,e={}){const r=new se,a=new de,i=r.$extractSVGCellData(r.$extractFramebufferData(t.layers.base.drawFramebuffer),t.grid),n=a.$generateSVGContent(i,t.grid,t.font,this._applyDefaultOptions(e));return a.$optimizeSVGContent(n)}$saveSVG(t,e={}){new X().$downloadFile(new Blob([this.$generateSVG(t,e)],{type:"image/svg+xml;charset=utf-8"}),e.filename)}}const nt={png:"image/png",jpg:"image/jpeg",webp:"image/webp"},ce=".png",ue=".jpg",pe=".webp";class _t{_applyDefaultOptions(t){return{format:t.format??"png",scale:Math.abs(t.scale??1),filename:t.filename}}_validateOptions(t){if(!(t.format in nt))throw new Error(`Saving '${t.format}' files is not supported`)}async $generateImageBlob(t,e){const r=t,a=document.createElement("canvas"),i=a.getContext("2d"),n=Math.round(r.width*e.scale),l=Math.round(r.height*e.scale);return a.width=n,a.height=l,i.imageSmoothingEnabled=!1,i.clearRect(0,0,n,l),i.drawImage(r,0,0,r.width,r.height,0,0,n,l),await new Promise((d,p)=>{a.toBlob(o=>{o?d(o):p(new Error(`Failed to generate ${e.format.toUpperCase()} blob`))},nt[e.format])})}async $saveImage(t,e={}){const r=this._applyDefaultOptions(e);this._validateOptions(r);const a=await this.$generateImageBlob(t,r);new X().$downloadFile(a,r.filename)}async $copyImageToClipboard(t,e={}){if(typeof navigator>"u"||!navigator.clipboard||typeof navigator.clipboard.write!="function")throw new Error("Clipboard API is not available in this environment");const r=this._applyDefaultOptions(e);this._validateOptions(r);const a=await this.$generateImageBlob(t,r),i=new ClipboardItem({[nt[r.format]]:a});await navigator.clipboard.write([i])}}class wt{_applyDefaultOptions(t){return{preserveTrailingSpaces:t.preserveTrailingSpaces??!1,emptyCharacter:t.emptyCharacter??" ",filename:t.filename}}_createTXTContent(t,e){const r=new Q,a=t.layers.base.drawFramebuffer,i=r.$extractFramebufferData(a),n=[];let l=0;for(let d=0;d<t.grid.rows;d++){let p="";for(let o=0;o<t.grid.cols;o++){const s=4*l,u=r.$getCharacterIndex(i.characterPixels,s);p+=t.font.characters[u]?.character||e.emptyCharacter,l++}e.preserveTrailingSpaces||(p=p.trimEnd()),n.push(p)}return n.join(`
2
+ `)}$generateTXT(t,e={}){return this._createTXTContent(t,this._applyDefaultOptions(e))}$saveTXT(t,e={}){const r=this._applyDefaultOptions(e),a=this._createTXTContent(t,r),i=new Blob([a],{type:"text/plain;charset=utf-8"});new X().$downloadFile(i,r.filename)}}class he{_canvas;_ctx;async $record(t,e,r,a){const i=Math.max(1,Math.round(e.frameRate)),n=Math.round(1e3/i),l=Math.max(1,Math.round(e.frameCount));return await new Promise((d,p)=>{const o=[];let s,u=0,m=!1;const x=()=>{s&&(s(),s=void 0)},h=w=>{m||(m=!0,x(),d(w))},b=()=>{if(u>=l)h(o);else try{const w=e.scale,v=Math.max(1,Math.round(t.width*w)),g=Math.max(1,Math.round(t.height*w));this._canvas||(this._canvas=document.createElement("canvas")),this._canvas.width===v&&this._canvas.height===g||(this._canvas.width=v,this._canvas.height=g),this._ctx||(this._ctx=this._canvas.getContext("2d"));const k=this._ctx;k.imageSmoothingEnabled=!1,k.clearRect(0,0,v,g),k.drawImage(t,0,0,t.width,t.height,0,0,v,g);const L={imageData:k.getImageData(0,0,v,g),width:v,height:g,delayMs:n};o.push(L),u+=1,a?.({state:"recording",frameIndex:u,totalFrames:l}),u>=l&&h(o)}catch(w){(v=>{if(m)return;m=!0,x();const g=v instanceof Error?v.message:"GIF recording failed";a?.({state:"error",message:g}),p(v instanceof Error?v:new Error(String(v)))})(w)}};s=r(()=>{b()}),a?.({state:"recording",frameIndex:0,totalFrames:l})})}}var Ct,tt,Et=Object.defineProperty,me=(Ct=c=>{function t(s,u,m){return .29889531*s+.58662247*u+.11448223*m}function e(s,u,m){return .59597799*s-.2741761*u-.32180189*m}function r(s,u,m){return .21147017*s-.52261711*u+.31114694*m}function a(s,u){let m=s[0]-u[0],x=s[1]-u[1],h=s[2]-u[2],b=i(s)-i(u);return m*m*.5053+x*x*.299+h*h*.1957+b*b}function i(s){return s[3]!=null?s[3]:255}function n(s,u){return Math.sqrt(a(s,u))}function l(s,u){let[m,x,h]=s,[b,w,v]=u,g=t(m,x,h)-t(b,w,v),k=e(m,x,h)-e(b,w,v),L=r(m,x,h)-r(b,w,v),I=i(s)-i(u);return g*g*.5053+k*k*.299+L*L*.1957+I*I}function d(s,u){return Math.sqrt(l(s,u))}function p(s,u){var m,x=0;for(m=0;m<s.length;m++){let h=s[m]-u[m];x+=h*h}return x}function o(s,u){return Math.sqrt(p(s,u))}Et(c,"__esModule",{value:!0}),((s,u)=>{for(var m in u)Et(s,m,{get:u[m],enumerable:!0})})(c,{colorDifferenceRGBToYIQ:()=>d,colorDifferenceRGBToYIQSquared:()=>l,colorDifferenceYIQ:()=>n,colorDifferenceYIQSquared:()=>a,euclideanDistance:()=>o,euclideanDistanceSquared:()=>p})},()=>(tt||Ct((tt={exports:{}}).exports,tt),tt.exports)),fe=59;function kt(c=256){let t=0,e=new Uint8Array(c);return{get buffer(){return e.buffer},reset(){t=0},bytesView:()=>e.subarray(0,t),bytes:()=>e.slice(0,t),writeByte(a){r(t+1),e[t]=a,t++},writeBytes(a,i=0,n=a.length){r(t+n);for(let l=0;l<n;l++)e[t++]=a[l+i]},writeBytesView(a,i=0,n=a.byteLength){r(t+n),e.set(a.subarray(i,i+n),t),t+=n}};function r(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),t>0&&e.set(n.subarray(0,t),0)}}var ge=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],be=function(c,t,e,r,a,i,n,l){a=a||kt(512),i=i||new Uint8Array(256),n=n||new Int32Array(5003),l=l||new Int32Array(5003);let d=n.length,p=Math.max(2,r);i.fill(0),l.fill(0),M();let o=0,s=0,u=p+1,m=u,x=!1,h=m,b=P(h),w=1<<u-1,v=w+1,g=w+2,k=0,L=e[0],I=0;for(let y=d;y<65536;y*=2)++I;I=8-I,a.writeByte(p),V(w);for(let y=1;y<e.length;y++)A(e[y]);return V(L),V(v),a.writeByte(0),a.bytesView();function C(y){i[k++]=y,k>=254&&E()}function M(){n.fill(-1)}function A(y){let D=(y<<12)+L,f=y<<I^L;if(n[f]===D)L=l[f];else{if(n[f]>=0){let _=f===0?1:d-f;do if(f-=_,f<0&&(f+=d),n[f]===D)return void(L=l[f]);while(n[f]>=0)}V(L),L=y,g<4096?(l[f]=g++,n[f]=D):(M(),g=w+2,x=!0,V(w))}}function E(){k>0&&(a.writeByte(k),a.writeBytesView(i,0,k),k=0)}function P(y){return(1<<y)-1}function V(y){for(o&=ge[s],s>0?o|=y<<s:o=y,s+=h;s>=8;)C(255&o),o>>=8,s-=8;if((g>b||x)&&(x?(h=m,b=P(h),x=!1):(++h,b=h==12?4096:P(h))),y==v){for(;s>0;)C(255&o),o>>=8,s-=8;E()}}};function Bt(c,t,e){return c<<8&63488|t<<2&992|e>>3&31}function It(c,t,e,r){return c>>4|240&t|(240&e)<<4|(240&r)<<8}function Ft(c,t,e){return c>>4<<8|t>>4<<4|e>>4}function et(c,t,e){return c<t?t:c>e?e:c}function rt(c){return c*c}function Mt(c,t,e){for(var r=0,a=1e100,i=c[t],n=i.cnt,l=(i.ac,i.rc),d=i.gc,p=i.bc,o=i.fw;o!=0;o=c[o].fw){var s=c[o].cnt,u=n*s/(n+s);if(!(u>=a)){var m=0;!((m+=u*rt(c[o].rc-l))>=a)&&!((m+=u*rt(c[o].gc-d))>=a)&&!((m+=u*rt(c[o].bc-p))>=a)&&(a=m,r=o)}}i.err=a,i.nn=r}function st(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function ve(c,t,e){let{format:r="rgb565",clearAlpha:a=!0,clearAlphaColor:i=0,clearAlphaThreshold:n=0,oneBitAlpha:l=!1}=e||{},d=e.useSqrt!==!1,p=r==="rgba4444",o=(function(y,D){let f=new Array(D==="rgb444"?4096:65536),_=y.length;if(D==="rgba4444")for(let F=0;F<_;++F){let S=y[F],$=S>>24&255,O=S>>16&255,B=S>>8&255,T=255&S,U=It(T,B,O,$),G=U in f?f[U]:f[U]=st();G.rc+=T,G.gc+=B,G.bc+=O,G.ac+=$,G.cnt++}else if(D==="rgb444")for(let F=0;F<_;++F){let S=y[F],$=S>>16&255,O=S>>8&255,B=255&S,T=Ft(B,O,$),U=T in f?f[T]:f[T]=st();U.rc+=B,U.gc+=O,U.bc+=$,U.cnt++}else for(let F=0;F<_;++F){let S=y[F],$=S>>16&255,O=S>>8&255,B=255&S,T=Bt(B,O,$),U=T in f?f[T]:f[T]=st();U.rc+=B,U.gc+=O,U.bc+=$,U.cnt++}return f})(c,r),s=o.length,u=s-1,m=new Uint32Array(s+1);for(var x=0,h=0;h<o.length;++h){let y=o[h];if(y!=null){var b=1/y.cnt;p&&(y.ac*=b),y.rc*=b,y.gc*=b,y.bc*=b,o[x++]=y}}for(rt(t)/x<.022&&(d=!1),h=0;h<x-1;++h)o[h].fw=h+1,o[h+1].bk=h,d&&(o[h].cnt=Math.sqrt(o[h].cnt));var w,v,g;for(d&&(o[h].cnt=Math.sqrt(o[h].cnt)),h=0;h<x;++h){Mt(o,h);var k=o[h].err;for(v=++m[0];v>1&&!(o[w=m[g=v>>1]].err<=k);v=g)m[v]=w;m[v]=h}var L=x-t;for(h=0;h<L;){for(var I;;){var C=m[1];if((I=o[C]).tm>=I.mtm&&o[I.nn].mtm<=I.tm)break;for(I.mtm==u?C=m[1]=m[m[0]--]:(Mt(o,C),I.tm=h),k=o[C].err,v=1;(g=v+v)<=m[0]&&(g<m[0]&&o[m[g]].err>o[m[g+1]].err&&g++,!(k<=o[w=m[g]].err));v=g)m[v]=w;m[v]=C}var M=o[I.nn],A=I.cnt,E=M.cnt;b=1/(A+E),p&&(I.ac=b*(A*I.ac+E*M.ac)),I.rc=b*(A*I.rc+E*M.rc),I.gc=b*(A*I.gc+E*M.gc),I.bc=b*(A*I.bc+E*M.bc),I.cnt+=M.cnt,I.mtm=++h,o[M.bk].fw=M.fw,o[M.fw].bk=M.bk,M.mtm=u}let P=[];var V=0;for(h=0;;++V){let y=et(Math.round(o[h].rc),0,255),D=et(Math.round(o[h].gc),0,255),f=et(Math.round(o[h].bc),0,255),_=255;p&&(_=et(Math.round(o[h].ac),0,255),l&&(_=_<=(typeof l=="number"?l:127)?0:255),a&&_<=n&&(y=D=f=i,_=0));let F=p?[y,D,f,_]:[y,D,f];if(xe(P,F)||P.push(F),(h=o[h].fw)==0)break}return P}function xe(c,t){for(let e=0;e<c.length;e++){let r=c[e],a=r[0]===t[0]&&r[1]===t[1]&&r[2]===t[2],i=!(r.length>=4&&t.length>=4)||r[3]===t[3];if(a&&i)return!0}return!1}function ye(c,t,e){let r=(e=e||"rgb565")==="rgb444"?4096:65536,a=new Uint8Array(c.length),i=new Array(r);if(e==="rgba4444")for(let n=0;n<c.length;n++){let l,d=c[n],p=d>>24&255,o=d>>16&255,s=d>>8&255,u=255&d,m=It(u,s,o,p);i[m]!=null?l=i[m]:(l=_e(u,s,o,p,t),i[m]=l),a[n]=l}else for(let n=0;n<c.length;n++){let l,d=c[n],p=d>>16&255,o=d>>8&255,s=255&d,u=e==="rgb444"?Ft(s,o,p):Bt(s,o,p);i[u]!=null?l=i[u]:(l=we(s,o,p,t),i[u]=l),a[n]=l}return a}function _e(c,t,e,r,a){let i=0,n=1e100;for(let l=0;l<a.length;l++){let d=a[l],p=d[0],o=d[1],s=d[2],u=q(d[3]-r);u>n||(u+=q(p-c),!(u>n)&&(u+=q(o-t),!(u>n)&&(u+=q(s-e),!(u>n)&&(n=u,i=l))))}return i}function we(c,t,e,r){let a=0,i=1e100;for(let n=0;n<r.length;n++){let l=r[n],d=l[0],p=l[1],o=l[2],s=q(d-c);s>i||(s+=q(p-t),!(s>i)&&(s+=q(o-e),!(s>i)&&(i=s,a=n)))}return a}function q(c){return c*c}function Ce(c={}){let{initialCapacity:t=4096,auto:e=!0}=c,r=kt(t),a=new Uint8Array(256),i=new Int32Array(5003),n=new Int32Array(5003),l=!1;return{reset(){r.reset(),l=!1},finish(){r.writeByte(fe)},bytes:()=>r.bytes(),bytesView:()=>r.bytesView(),get buffer(){return r.buffer},get stream(){return r},writeHeader:d,writeFrame(p,o,s,u={}){let{transparent:m=!1,transparentIndex:x=0,delay:h=0,palette:b=null,repeat:w=0,colorDepth:v=8,dispose:g=-1}=u,k=!1;if(e?l||(k=!0,d(),l=!0):k=!!u.first,o=Math.max(0,Math.floor(o)),s=Math.max(0,Math.floor(s)),k){if(!b)throw new Error("First frame must include a { palette } option");(function(C,M,A,E,P=8){let V=1,y=0,D=lt(E.length)-1,f=V<<7|P-1<<4|y<<3|D;H(C,M),H(C,A),C.writeBytes([f,0,0])})(r,o,s,b,v),St(r,b),w>=0&&(function(C,M){C.writeByte(33),C.writeByte(255),C.writeByte(11),$t(C,"NETSCAPE2.0"),C.writeByte(3),C.writeByte(1),H(C,M),C.writeByte(0)})(r,w)}let L=Math.round(h/10);(function(C,M,A,E,P){var V,y;C.writeByte(33),C.writeByte(249),C.writeByte(4),P<0&&(P=0,E=!1),E?(V=1,y=2):(V=0,y=0),M>=0&&(y=7&M),y<<=2,C.writeByte(0|y|0|V),H(C,A),C.writeByte(P||0),C.writeByte(0)})(r,g,L,m,x);let I=!!b&&!k;(function(C,M,A,E){if(C.writeByte(44),H(C,0),H(C,0),H(C,M),H(C,A),E){let P=0,V=0,y=lt(E.length)-1;C.writeByte(128|P|V|y)}else C.writeByte(0)})(r,o,s,I?b:null),I&&St(r,b),(function(C,M,A,E,P=8,V,y,D){be(A,E,M,P,C,V,y,D)})(r,p,o,s,v,a,i,n)}};function d(){$t(r,"GIF89a")}}function St(c,t){let e=1<<lt(t.length);for(let r=0;r<e;r++){let a=[0,0,0];r<t.length&&(a=t[r]),c.writeByte(a[0]),c.writeByte(a[1]),c.writeByte(a[2])}}function H(c,t){c.writeByte(255&t),c.writeByte(t>>8&255)}function $t(c,t){for(var e=0;e<t.length;e++)c.writeByte(t.charCodeAt(e))}function lt(c){return Math.max(Math.ceil(Math.log2(c)),1)}me();class Ee{_recorder;_textmodifier;_registerPostDrawHook;constructor(t,e){this._recorder=new he,this._textmodifier=t,this._registerPostDrawHook=e}async $saveGIF(t={}){const e=this._textmodifier.canvas,r=this._applyDefaultOptions(t),a=t.onProgress;try{const i=await this._recorder.$record(e,r,this._registerPostDrawHook,a),n=Ce(),{repeat:l}=t;for(let o=0;o<i.length;o++){const s=i[o],{width:u,height:m,imageData:x,delayMs:h}=s,b=new Uint32Array(x.data.buffer),w=ve(b,256,{}),v=ye(b,w);n.writeFrame(v,u,m,{palette:w,delay:h,repeat:o===0?l:-1}),o%2!=0&&o!==i.length-1||(a?.({state:"encoding",frameIndex:o+1,totalFrames:i.length}),await new Promise(g=>setTimeout(g,0)))}n.finish();const d=n.bytes(),p=d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength);new X().$downloadFile(new Blob([p],{type:"image/gif"}),r.filename),a?.({state:"completed",totalFrames:r.frameCount})}catch(i){throw a?.({state:"error",message:i instanceof Error?i.message:"GIF export failed"}),i}}_applyDefaultOptions(t){const e=Math.abs(Math.round(t.frameCount??300)),r=Math.abs(t.frameRate??60),a=Math.abs(t.scale??1),i=Math.max(-1,Math.round(t.repeat??0));return{filename:t.filename,frameCount:e,frameRate:r,scale:a,repeat:i}}}function ke(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var Lt,Pt={exports:{}};function Be(){return Lt||(Lt=1,(function(c){(function(){function t(d,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 d=="string"&&/^data:image\/webp/.test(d)?d:d.toDataURL("image/webp",p))}function e(d){return(d.charCodeAt(0)|d.charCodeAt(1)<<8|d.charCodeAt(2)<<16|d.charCodeAt(3)<<24)>>>0}function r(d){let p=d.indexOf("VP8",12);if(p===-1)throw new Error("Bad image format, does this browser support WebP?");let o=!1;for(;p<d.length-8;){let s,u;switch(u=d.substring(p,p+4),p+=4,s=e(d.substring(p,p+4)),p+=4,u){case"VP8 ":return{frame:d.substring(p,p+s),hasAlpha:o};case"ALPH":o=!0}p+=s,1&s&&p++}throw new Error("Failed to find VP8 keyframe in WebP image, is this image mistakenly encoded in the Lossless WebP format?")}function a(d){this.value=d}function i(d){this.value=d}function n(d,p,o){if(Array.isArray(o))for(let s=0;s<o.length;s++)n(d,p,o[s]);else if(typeof o=="string")d.writeString(o);else if(o instanceof Uint8Array)d.writeBytes(o);else{if(!o.id)throw new Error("Bad EBML datatype "+typeof o.data);if(o.offset=d.pos+p,d.writeUnsignedIntBE(o.id),Array.isArray(o.data)){let s,u,m;o.size===-1?d.writeByte(255):o.size===-2?(s=d.pos,d.writeBytes([15,255,255,255,255])):(s=d.pos,d.writeBytes([0,0,0,0])),u=d.pos,o.dataOffset=u+p,n(d,p,o.data),o.size!==-1&&o.size!==-2&&(m=d.pos,o.size=m-u,d.seek(s),d.writeEBMLVarIntWidth(o.size,4),d.seek(m))}else if(typeof o.data=="string")d.writeEBMLVarInt(o.data.length),o.dataOffset=d.pos+p,d.writeString(o.data);else if(typeof o.data=="number")o.size||(o.size=d.measureUnsignedInt(o.data)),d.writeEBMLVarInt(o.size),o.dataOffset=d.pos+p,d.writeUnsignedIntBE(o.data,o.size);else if(o.data instanceof i)d.writeEBMLVarInt(8),o.dataOffset=d.pos+p,d.writeDoubleBE(o.data.value);else if(o.data instanceof a)d.writeEBMLVarInt(4),o.dataOffset=d.pos+p,d.writeFloatBE(o.data.value);else{if(!(o.data instanceof Uint8Array))throw new Error("Bad EBML datatype "+typeof o.data);d.writeEBMLVarInt(o.data.byteLength),o.dataOffset=d.pos+p,d.writeBytes(o.data)}}}let l=function(d,p){return function(o){let s,u,m=!1,x=0,h=0,b=null,w=null,v=null,g=[],k=0,L=0,I={quality:.95,transparent:!1,alphaQuality:void 0,fileWriter:null,fd:null,frameDuration:null,frameRate:null},C={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}},M={id:17545,data:new i(0)},A=[],E=new p(o.fileWriter||o.fd);function P(f){return f-s.dataOffset}function V(){u=(function(){let $={id:21420,size:5,data:0},O={id:290298740,data:[]};for(let B in C){let T=C[B];T.positionEBML=Object.create($),O.data.push({id:19899,data:[{id:21419,data:T.id},T.positionEBML]})}return O})();let f={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:"webm-writer-js"},{id:22337,data:"webm-writer-js"},M]},_=[{id:176,data:x},{id:186,data:h}];o.transparent&&_.push({id:21440,data:1});let F={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:_}]}]};s={id:408125543,size:-2,data:[u,f,F]};let S=new d(256);n(S,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}]},s]),E.write(S.getAsDataArray()),C.SegmentInfo.positionEBML.data=P(f.offset),C.Tracks.positionEBML.data=P(F.offset),m=!0}function y(f){return f.alpha?(function(_){let F,S,$=new d(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return $.writeEBMLVarInt(_.trackNumber),$.writeU16BE(_.timecode),$.writeByte(0),F={id:161,data:[$.getAsDataArray(),_.frame]},S={id:30113,data:[{id:166,data:[{id:238,data:1},{id:165,data:_.alpha}]}]},{id:160,data:[F,S]}})(f):(function(_){let F=new d(4);if(!(_.trackNumber>0&&_.trackNumber<127))throw new Error("TrackNumber must be > 0 and < 127");return F.writeEBMLVarInt(_.trackNumber),F.writeU16BE(_.timecode),F.writeByte(128),{id:163,data:[F.getAsDataArray(),_.frame]}})(f)}function D(){if(g.length===0)return;let f=0;for(let B=0;B<g.length;B++)f+=g[B].frame.length+(g[B].alpha?g[B].alpha.length:0);let _=new d(f+64*g.length),F=(function(B){return{id:524531317,data:[{id:231,data:Math.round(B.timecode)}]}})({timecode:Math.round(k)});for(let B=0;B<g.length;B++)F.data.push(y(g[B]));var S,$,O;n(_,E.pos,F),E.write(_.getAsDataArray()),S=1,$=Math.round(k),O=F.offset,A.push({id:187,data:[{id:179,data:$},{id:183,data:[{id:247,data:S},{id:241,data:P(O)}]}]}),g=[],k+=L,L=0}this.addFrame=function(f,_,F){m||(x=f.width||0,h=f.height||0,V());let S,$=r(t(f,o.quality)),O=null;S=F||(typeof _=="number"?_:o.frameDuration),o.transparent&&(_ instanceof HTMLCanvasElement||typeof _=="string"?O=_:$.hasAlpha&&(O=(function(B){b!==null&&b.width===B.width&&b.height===B.height||(b=document.createElement("canvas"),b.width=B.width,b.height=B.height,w=b.getContext("2d"),v=w.createImageData(b.width,b.height));let T=B.getContext("2d").getImageData(0,0,B.width,B.height).data,U=v.data,G=0,gr=B.width*B.height*4;for(let bt=3;bt<gr;bt+=4){let vt=T[bt];U[G++]=vt,U[G++]=vt,U[G++]=vt,U[G++]=255}return w.putImageData(v,0,0),b})(f))),(function(B){B.trackNumber=1,B.timecode=Math.round(L),g.push(B),L+=B.duration,L>=5e3&&D()})({frame:$.frame,duration:S,alpha:O?r(t(O,o.alphaQuality)).frame:null})},this.complete=function(){return m||V(),D(),(function(){let f={id:475249515,data:A},_=new d(16+32*A.length);n(_,E.pos,f),E.write(_.getAsDataArray()),C.Cues.positionEBML.data=P(f.offset)})(),(function(){let f=new d(u.size),_=E.pos;n(f,u.dataOffset,u.data),E.seek(u.dataOffset),E.write(f.getAsDataArray()),E.seek(_)})(),(function(){let f=new d(8),_=E.pos;f.writeDoubleBE(k),E.seek(M.dataOffset),E.write(f.getAsDataArray()),E.seek(_)})(),(function(){let f=new d(10),_=E.pos;f.writeUnsignedIntBE(s.id),f.writeEBMLVarIntWidth(E.pos-s.dataOffset,5),E.seek(s.offset),E.write(f.getAsDataArray()),E.seek(_)})(),E.complete("video/webm")},this.getWrittenSize=function(){return E.length},o=(function(f,_){let F={};return[f,_].forEach(function(S){for(let $ in S)Object.prototype.hasOwnProperty.call(S,$)&&(F[$]=S[$])}),F})(I,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)})()}};c.exports=l})()})(Pt)),Pt.exports}var Vt,At={exports:{}};function Ie(){return Vt||(Vt=1,(function(c){(function(){let t=function(e){this.data=new Uint8Array(e),this.pos=0};t.prototype.seek=function(e){this.pos=e},t.prototype.writeBytes=function(e){for(let r=0;r<e.length;r++)this.data[this.pos++]=e[r]},t.prototype.writeByte=function(e){this.data[this.pos++]=e},t.prototype.writeU8=t.prototype.writeByte,t.prototype.writeU16BE=function(e){this.data[this.pos++]=e>>8,this.data[this.pos++]=e},t.prototype.writeDoubleBE=function(e){let r=new Uint8Array(new Float64Array([e]).buffer);for(let a=r.length-1;a>=0;a--)this.writeByte(r[a])},t.prototype.writeFloatBE=function(e){let r=new Uint8Array(new Float32Array([e]).buffer);for(let a=r.length-1;a>=0;a--)this.writeByte(r[a])},t.prototype.writeString=function(e){for(let r=0;r<e.length;r++)this.data[this.pos++]=e.charCodeAt(r)},t.prototype.writeEBMLVarIntWidth=function(e,r){switch(r){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 "+r)}},t.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)},t.prototype.writeEBMLVarInt=function(e){this.writeEBMLVarIntWidth(e,this.measureEBMLVarInt(e))},t.prototype.writeUnsignedIntBE=function(e,r){switch(r===void 0&&(r=this.measureUnsignedInt(e)),r){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 "+r)}},t.prototype.measureUnsignedInt=function(e){return e<256?1:e<65536?2:e<1<<24?3:e<4294967296?4:5},t.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")},c.exports=t})()})(At)),At.exports}var Dt,Ot,Ut,Tt={exports:{}};function Fe(){return Dt||(Dt=1,(function(c){(function(){let t=function(e){return function(r){let a=[],i=Promise.resolve(),n=null,l=null;function d(s){return new Promise(function(u,m){let x=new FileReader;x.addEventListener("loadend",function(){u(x.result)}),x.readAsArrayBuffer(s)})}function p(s){return new Promise(function(u,m){s instanceof Uint8Array?u(s):s instanceof ArrayBuffer||ArrayBuffer.isView(s)?u(new Uint8Array(s)):s instanceof Blob?u(d(s).then(function(x){return new Uint8Array(x)})):u(d(new Blob([s])).then(function(x){return new Uint8Array(x)}))})}function o(s){let u=s.byteLength||s.length||s.size;if(!Number.isInteger(u))throw new Error("Failed to determine size of element");return u}r&&r.constructor.name==="FileWriter"?n=r:e&&r&&(l=r),this.pos=0,this.length=0,this.seek=function(s){if(s<0)throw new Error("Offset may not be negative");if(isNaN(s))throw new Error("Offset may not be NaN");if(s>this.length)throw new Error("Seeking beyond the end of file is not allowed");this.pos=s},this.write=function(s){let u={offset:this.pos,data:s,length:o(s)},m=u.offset>=this.length;this.pos+=u.length,this.length=Math.max(this.length,this.pos),i=i.then(function(){if(l)return new Promise(function(x,h){p(u.data).then(function(b){let w=0,v=Buffer.from(b.buffer),g=function(k,L,I){w+=L,w>=I.length?x():e.write(l,I,w,I.length-w,u.offset+w,g)};e.write(l,v,0,v.length,u.offset,g)})});if(n)return new Promise(function(x,h){n.onwriteend=x,n.seek(u.offset),n.write(new Blob([u.data]))});if(!m)for(let x=0;x<a.length;x++){let h=a[x];if(!(u.offset+u.length<=h.offset||u.offset>=h.offset+h.length)){if(u.offset<h.offset||u.offset+u.length>h.offset+h.length)throw new Error("Overwrite crosses blob boundaries");return u.offset==h.offset&&u.length==h.length?void(h.data=u.data):p(h.data).then(function(b){return h.data=b,p(u.data)}).then(function(b){u.data=b,h.data.set(u.data,u.offset-h.offset)})}}a.push(u)})},this.complete=function(s){return i=l||n?i.then(function(){return null}):i.then(function(){let u=[];for(let m=0;m<a.length;m++)u.push(a[m].data);return new Blob(u,{type:s})}),i}}};c.exports=t})()})(Tt)),Tt.exports}function Me(){return Ut?Ot:(Ut=1,Ot=Be()(Ie(),Fe()(null)))}const Se=ke(Me());class $e{async $record(t,e,r,a){const i=Math.max(1,Math.round(e.frameRate)),n=Math.max(1,Math.round(e.frameCount)),l=new Se({quality:e.quality,alphaQuality:e.transparent?e.quality:void 0,transparent:e.transparent,frameRate:i}),d=this._createSnapshotSurface();return await new Promise((p,o)=>{let s,u="capturing",m=!1,x=0;const h=()=>{s&&(s(),s=void 0)},b=()=>{a?.({state:"recording",frameIndex:x,totalFrames:n})},w=g=>{if(m)return;m=!0,h();const k=g instanceof Error?g.message:"WEBM export failed";a?.({state:"error",message:k}),o(g instanceof Error?g:new Error(String(g)))},v=()=>{u!=="capturing"||m||(u="encoding",h(),l.complete().then(g=>{(k=>{m||(m=!0,a?.({state:"completed",frameIndex:Math.min(n,x),totalFrames:n}),p(k))})(g)}).catch(w))};s=r(()=>{(()=>{if(u==="capturing")if(x>=n)v();else try{const g=d(t);l.addFrame(g),x+=1,b(),x>=n&&v()}catch(g){w(g)}})()}),b()})}_createSnapshotSurface(){let t=null,e=null;return r=>{const a=Math.max(1,r.width),i=Math.max(1,r.height),n=((l,d)=>(t||(t=document.createElement("canvas")),t.width!==l||t.height!==d?(t.width=l,t.height=d,e=t.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)):e||(e=t.getContext("2d"),e&&(e.imageSmoothingEnabled=!1)),e?t:null))(a,i);return n&&e?(e.clearRect(0,0,a,i),e.drawImage(r,0,0,a,i),n):r}}}class Le{_recorder;_textmodifier;_registerPostDrawHook;constructor(t,e){this._recorder=new $e,this._textmodifier=t,this._registerPostDrawHook=e}async $saveWEBM(t={}){const e=this._textmodifier.canvas,r=this._applyDefaultOptions(t);try{const a=await this._recorder.$record(e,r,this._registerPostDrawHook,t.onProgress);new X().$downloadFile(a,r.filename)}catch(a){throw t.onProgress?.({state:"error",message:a instanceof Error?a.message:"WEBM export failed"}),a}}_applyDefaultOptions(t){return{filename:t.filename,frameRate:Math.abs(Math.round(t.frameRate??60)),frameCount:Math.abs(Math.round(t.frameCount??300)),quality:Math.abs(Math.min(Math.max(t.quality??1,0),1)),transparent:!!t.transparent,debugLogging:!!t.debugLogging}}}const Pe="textmode-export-overlay",z="textmode-export-overlay__stack",dt="textmode-export-overlay__stack--dense",Rt="textmode-export-overlay__stack--compact",Nt="textmode-export-overlay__section",Ve="textmode-export-overlay__header",Ae="textmode-export-overlay__header-title-row",De="textmode-export-overlay__header-links",Oe="textmode-export-overlay__row",zt="textmode-export-overlay__label",Gt="textmode-export-overlay__field",Ht="textmode-export-overlay__field--compact",Wt="textmode-export-overlay__field--dense",qt="textmode-export-overlay__field--full",jt="textmode-export-overlay__field--channel",Qt="textmode-export-overlay__input",Ue="textmode-export-overlay__checkbox",Xt="textmode-export-overlay__muted",Te="textmode-export-overlay__status",Re="textmode-export-overlay__status--gif",Ne="textmode-export-overlay__status--video",ze="textmode-export-overlay__status-title",Ge="textmode-export-overlay__status-value",He="textmode-export-overlay__divider",We="textmode-export-overlay__title",qe="textmode-export-overlay__button",ct="textmode-export-overlay__button--primary",ut="textmode-export-overlay__button--secondary",Yt="textmode-export-overlay__button--full",je="textmode-export-overlay__support-link",Qe="textmode-export-overlay__support-icon",Xe="textmode-export-overlay__link-icon";class N{element;mounted=!1;destroyed=!1;mount(t){if(this.destroyed)throw new Error("Cannot mount a destroyed component");if(this.mounted)return;const e=this.render();t.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(t){this.mounted&&this.onUpdate(t)}onMount(){}_onUnmount(){}_onDestroy(){}onUpdate(t){}get root(){if(!this.element)throw new Error("Component is not mounted yet");return this.element}isMounted(){return this.mounted}}class Y extends N{static _iconNamespace="http://www.w3.org/2000/svg";render(){const t=document.createElement("div");t.classList.add(z,dt,Ve);const e=document.createElement("div");e.classList.add(Ae);const r=document.createElement("strong");r.textContent="textmode.export.js",r.classList.add(We);const a=document.createElement("div");a.classList.add(De);const i=this._createLink("https://github.com/humanbydefinition/textmode.export.js","View repository on GitHub",Xe,[{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",Qe,[{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(r),e.appendChild(a);const l=document.createElement("div");return l.classList.add(He),t.appendChild(e),t.appendChild(l),t}_createLink(t,e,r,a){const i=document.createElement("a");return i.href=t,i.target="_blank",i.rel="noopener noreferrer",i.classList.add(je),i.setAttribute("aria-label",e),i.appendChild(this._createIcon(r,a)),i}_createIcon(t,e){const r=document.createElementNS(Y._iconNamespace,"svg");r.setAttribute("xmlns",Y._iconNamespace),r.setAttribute("width","18"),r.setAttribute("height","18"),r.setAttribute("viewBox","0 0 24 24"),r.setAttribute("fill","none"),r.setAttribute("stroke","currentColor"),r.setAttribute("stroke-width","2"),r.setAttribute("stroke-linecap","round"),r.setAttribute("stroke-linejoin","round"),r.classList.add(t);for(const a of e){const i=document.createElementNS(Y._iconNamespace,"path");for(const[n,l]of Object.entries(a))i.setAttribute(n,l);r.appendChild(i)}return r}}class R extends N{props;constructor(t){super(),this.props=t}render(){const t=document.createElement("div");t.classList.add(Gt),this.applyVariant(t,this.props.variant);const e=document.createElement("label");if(e.classList.add(zt),e.textContent=this.props.label,this.props.labelFor&&(e.htmlFor=this.props.labelFor),t.appendChild(e),this.props.description){const r=document.createElement("span");r.classList.add(Xt),r.textContent=this.props.description,t.appendChild(r)}return t}attachControl(t){this.root.appendChild(t)}update(t){this.props=t,super.update(t)}onUpdate(t){const e=this.root;for(;e.firstChild;)e.removeChild(e.firstChild);this.props=t,e.classList.add(Gt),this.applyVariant(e,t.variant);const r=document.createElement("label");if(r.classList.add(zt),r.textContent=t.label,t.labelFor&&(r.htmlFor=t.labelFor),e.appendChild(r),t.description){const a=document.createElement("span");a.classList.add(Xt),a.textContent=t.description,e.appendChild(a)}}applyVariant(t,e){switch(t.classList.remove(Ht,Wt,qt,jt),e){case"compact":t.classList.add(Ht);break;case"dense":t.classList.add(Wt);break;case"full":t.classList.add(qt);break;case"channel":t.classList.add(jt)}}}class pt extends N{props;select;handleChange=()=>{this.props.defaultValue=this.select.value};constructor(t){super(),this.props=t}render(){return this.select=document.createElement("select"),this.select.classList.add(Qt),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(t){this.select&&(this.select.value=t),this.props.defaultValue=t}_onUnmount(){this.select.removeEventListener("change",this.handleChange)}onUpdate(t){this.props=t,this.populateOptions(),t.defaultValue&&(this.select.value=t.defaultValue)}update(t){this.props={...this.props,...t},this.select&&(t.id&&(this.select.id=t.id),t.options&&this.populateOptions(),t.defaultValue!==void 0&&(this.select.value=t.defaultValue))}populateOptions(){if(this.select){this.select.innerHTML="";for(const t of this.props.options){const e=document.createElement("option");e.value=t.value,e.textContent=t.label,this.select.appendChild(e)}this.props.defaultValue&&(this.select.value=this.props.defaultValue)}}}class Jt extends N{props;button;constructor(t){super(),this.props=t}render(){return this.button=document.createElement("button"),this.button.type="button",this.button.textContent=this.props.label,this.button.classList.add(qe),this.props.variant==="secondary"?this.button.classList.add(ut):this.button.classList.add(ct),this.props.fullWidth&&this.button.classList.add(Yt),this.button.disabled=!!this.props.disabled,this.button}get buttonElement(){return this.button}setLabel(t){this.props.label=t,this.button.textContent=t}setDisabled(t){this.props.disabled=t,this.button.disabled=t}onUpdate(t){this.props=t,this.button.textContent=t.label,this.button.disabled=!!t.disabled,t.variant==="secondary"?(this.button.classList.add(ut),this.button.classList.remove(ct)):(this.button.classList.add(ct),this.button.classList.remove(ut)),this.button.classList.toggle(Yt,!!t.fullWidth)}}class Ye{api;constructor(t){this.api=t}async $copy(t,e){switch(t){case"txt":{const r=this.api.toString(e);await navigator.clipboard.writeText(r);break}case"svg":{const r=this.api.toSVG(e);await navigator.clipboard.writeText(r);break}case"image":await this.api.copyCanvas(e);break;default:throw new Error(`Clipboard not supported for ${t}`)}}}class Je{api;events;constructor(t,e){this.api=t,this.events=e}async $requestExport(t,e,r={}){this.events.$emit("export:request",{format:t});try{const a={onGIFProgress:r.onGIFProgress?i=>{r.onGIFProgress?.(i),this.events.$emit("export:progress",{format:t,progress:i})}:t==="gif"?i=>this.events.$emit("export:progress",{format:t,progress:i}):void 0,onVideoProgress:r.onVideoProgress?i=>{r.onVideoProgress?.(i),this.events.$emit("export:progress",{format:t,progress:i})}:t==="video"?i=>this.events.$emit("export:progress",{format:t,progress:i}):void 0};await this._execute(t,e,a),this.events.$emit("export:success",{format:t})}catch(a){throw this.events.$emit("export:error",{format:t,error:a}),a}}_execute(t,e,r){switch(t){case"txt":return Promise.resolve(this.api.saveStrings(e));case"image":return this.api.saveCanvas(e);case"svg":return Promise.resolve(this.api.saveSVG(e));case"gif":{const a={...e,onProgress:r.onGIFProgress};return this.api.saveGIF(a)}case"video":{const a={...e,onProgress:r.onVideoProgress};return this.api.saveWEBM(a)}}}}class Ze{modifier;overlay;animationFrameId=null;handleUpdate;bound=!1;constructor(t,e){this.modifier=t,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 t=this.modifier.canvas.getBoundingClientRect();this.overlay.style.top=`${t.top+window.scrollY+8}px`,this.overlay.style.left=`${t.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 J="textmode-export-number-input",Ke=`${J}__field`,tr=`${J}__controls`,er=`${J}__control`,Zt=`${J}__display`,at=`${Zt}--visible`,Kt=c=>{const t=document.createElement("button");return t.type="button",t.className=er,t.textContent=c>0?"▲":"▼",t};class W extends N{props;input;display;incrementButton;decrementButton;suppressClickAfterPointer=new WeakMap;holdTimeoutId;holdIntervalId;activePointerId;disabledObserver;constructor(t){super(),this.props=t}render(){const t=document.createElement("div");t.className=J,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=Ke,this.display=document.createElement("div"),this.display.className=Zt;const e=document.createElement("div");return e.className=tr,this.incrementButton=Kt(1),this.decrementButton=Kt(-1),e.appendChild(this.incrementButton),e.appendChild(this.decrementButton),t.appendChild(this.input),t.appendChild(this.display),t.appendChild(e),this.bindStepControls(),this.bindHoldBehavior(),this.bindInputListeners(),this.observeDisabledState(t),this.updateDisplay(),t}get inputElement(){return this.input}get value(){return this.input.value}set value(t){this.input.value=t,this.updateDisplay()}refresh(){this.updateDisplay()}_onDestroy(){this.clearHoldTimers(),this.disabledObserver?.disconnect()}bindStepControls(){const t=i=>()=>{if(this.input.disabled)return;const n=this.input.value,l=this.input.getAttribute("step");if(l&&l!=="any")i>0?this.input.stepUp():this.input.stepDown();else{const p=i>0?1:-1,o=Number.parseFloat(this.input.value||"0"),s=Number.isFinite(o)?o+p:p;this.input.value=String(s)}var d;this.input.value!==n&&((d=this.input).dispatchEvent(new Event("input",{bubbles:!0})),d.dispatchEvent(new Event("change",{bubbles:!0}))),this.updateDisplay(),this.input.focus({preventScroll:!0})},e=t(1),r=t(-1),a=(i,n)=>l=>{if(this.suppressClickAfterPointer.get(i))return this.suppressClickAfterPointer.set(i,!1),void l.preventDefault();n()};this.incrementButton.addEventListener("click",a(this.incrementButton,e)),this.decrementButton.addEventListener("click",a(this.decrementButton,r))}bindHoldBehavior(){const t=(e,r)=>{const a=r>0?()=>this.incrementButton.click():()=>this.decrementButton.click();e.addEventListener("pointerdown",l=>{if(l.button===0){l.preventDefault(),this.suppressClickAfterPointer.set(e,!0),this.activePointerId=l.pointerId;try{e.setPointerCapture(l.pointerId)}catch{}a(),this.holdTimeoutId=window.setTimeout(()=>{this.holdIntervalId=window.setInterval(a,80)},380)}});const i=()=>{if(this.activePointerId!==void 0){try{e.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}},n=()=>{this.clearHoldTimers(),i()};e.addEventListener("pointerup",n),e.addEventListener("pointerleave",n),e.addEventListener("pointercancel",n)};t(this.incrementButton,1),t(this.decrementButton,-1)}bindInputListeners(){const t=()=>{this.props.defaultValue=this.input.value,this.updateDisplay()};this.input.addEventListener("input",t),this.input.addEventListener("change",t)}observeDisabledState(t){const e=()=>{const r=this.input.disabled;this.incrementButton.disabled=r,this.decrementButton.disabled=r,t.classList.toggle("is-disabled",r),r?(this.display.classList.remove(at),this.input.style.removeProperty("color"),this.input.style.removeProperty("caretColor")):this.updateDisplay()};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(e),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),e()}updateDisplay(){const t=this.props.formatDisplay;if(!t)return this.display.textContent="",this.display.classList.remove(at),this.input.style.removeProperty("color"),void this.input.style.removeProperty("caretColor");const e=this.input.value,r=Number.parseFloat(e),a=t(Number.isFinite(r)?r:Number.NaN,e,this.input);a?(this.display.textContent=a,this.display.classList.add(at),this.input.style.color="transparent",this.input.style.caretColor="#f8fafc"):(this.display.textContent="",this.display.classList.remove(at),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 Z extends N{variant;additionalClasses;constructor(t="stack",e=[]){super(),this.variant=t,this.additionalClasses=e}render(){const t=document.createElement("div"),e=[this.variant==="stack"?z:void 0,this.variant==="stackDense"?dt:void 0,this.variant==="stackCompact"?Rt:void 0,this.variant==="row"?Oe:void 0,this.variant==="section"?Nt:void 0,...this.additionalClasses].filter(Boolean);return t.classList.add(...e),t}}const te={neutral:"textmode-export-overlay__status-value--neutral",active:"textmode-export-overlay__status-value--active",alert:"textmode-export-overlay__status-value--alert"};class ee extends N{props;container;messageElement;constructor(t){super(),this.props=t}render(){this.container=document.createElement("div"),this.container.classList.add(Te),this.props.context==="gif"?this.container.classList.add(Re):this.props.context==="video"&&this.container.classList.add(Ne);const t=document.createElement("span");return t.classList.add(ze),t.textContent=this.props.title,this.messageElement=document.createElement("span"),this.messageElement.classList.add(Ge),this.messageElement.textContent=this.props.message,this.applyVariant(this.props.variant??"neutral"),this.container.appendChild(t),this.container.appendChild(this.messageElement),this.container}setMessage(t,e="neutral"){this.messageElement.textContent=t,this.applyVariant(e)}onUpdate(t){this.props=t,this.setMessage(t.message,t.variant??"neutral")}applyVariant(t){this.messageElement.classList.remove(...Object.values(te)),this.messageElement.classList.add(te[t])}}class K extends N{_config;_managedComponents=new Set;constructor(t){super(),this._config=t}_manageComponent(t){return this._managedComponents.add(t),t}_onUnmount(){for(const t of this._managedComponents)t.unmount()}_onDestroy(){for(const t of this._managedComponents)t.destroy();this._managedComponents.clear()}}const re=300,ae=60,ie=1,rr=0;class ht extends K{frameCountInput=this._manageComponent(new W({defaultValue:String(re),attributes:{min:"1",max:"600",step:"1"}}));frameRateInput=this._manageComponent(new W({defaultValue:String(ae),attributes:{min:"1",max:"60",step:"1"}}));scaleInput=this._manageComponent(new W({defaultValue:String(ie),attributes:{min:"0.1",max:"8",step:"0.1"}}));repeatInput=this._manageComponent(new W({defaultValue:"0",attributes:{min:"0",max:"50",step:"1"},formatDisplay:(t,e)=>Number.isFinite(t)?t===0?"∞":null:e.trim()===""?null:e}));status=this._manageComponent(new ee({title:"status",message:"ready to record",variant:"neutral",context:"gif"}));recordingState="idle";constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z);const e=new Z("row");e.mount(t);const r=new R({label:"number of frames",labelFor:"textmode-export-gif-frame-count",variant:"dense"});r.mount(e.root),this.frameCountInput.mount(r.root),this.frameCountInput.inputElement.id="textmode-export-gif-frame-count";const a=new R({label:"frame rate (fps)",labelFor:"textmode-export-gif-frame-rate",variant:"dense"});a.mount(e.root),this.frameRateInput.mount(a.root),this.frameRateInput.inputElement.id="textmode-export-gif-frame-rate";const i=new Z("row");i.mount(t);const n=new R({label:"scale",labelFor:"textmode-export-gif-scale",variant:"dense"});n.mount(i.root),this.scaleInput.mount(n.root),this.scaleInput.inputElement.id="textmode-export-gif-scale";const l=new R({label:"loop count",labelFor:"textmode-export-gif-repeat",variant:"dense"});return l.mount(i.root),this.repeatInput.mount(l.root),this.repeatInput.inputElement.id="textmode-export-gif-repeat",this.status.mount(t),t}getOptions(){const t=this._config.defaultOptions??{};return{frameCount:this.safeParseInt(this.frameCountInput.value,t.frameCount??300),frameRate:this.safeParseInt(this.frameRateInput.value,t.frameRate??60),scale:this.safeParseFloat(this.scaleInput.value,t.scale??1),repeat:this.safeParseInt(this.repeatInput.value,t.repeat??0)}}reset(){this.recordingState="idle",this.applyDefaults(),this.setRecordingState("idle")}validate(){const t=Number.parseInt(this.frameCountInput.value,10),e=Number.parseInt(this.frameRateInput.value,10),r=Number.parseFloat(this.scaleInput.value);return Number.isFinite(t)&&t>0&&Number.isFinite(e)&&e>0&&Number.isFinite(r)&&r>0}isRecording(){return this.recordingState==="recording"||this.recordingState==="encoding"}setRecordingState(t,e){this.recordingState=t;const r=t==="recording"||t==="encoding";switch(this.frameCountInput.inputElement.disabled=r,this.frameRateInput.inputElement.disabled=r,this.scaleInput.inputElement.disabled=r,this.repeatInput.inputElement.disabled=r,t){case"recording":if(e?.totalFrames){const a=e.frameIndex??0;this.status.setMessage(`recording ${a}/${e.totalFrames}`,"active")}else this.status.setMessage("recording…","active");break;case"encoding":if(e?.totalFrames){const a=e.frameIndex??0;this.status.setMessage(`encoding ${a}/${e.totalFrames}`,"active")}else this.status.setMessage("encoding…","active");break;case"completed":this.status.setMessage("GIF saved successfully","active");break;case"error":this.status.setMessage(e?.message??"failed to export GIF","alert");break;default:this.status.setMessage("ready to record","neutral")}}handleProgress(t){if(t.state!=="recording"&&t.state!=="encoding"||!t.totalFrames)t.state==="completed"?this.status.setMessage("GIF saved successfully","active"):t.state==="error"&&this.status.setMessage(t.message??"failed to export GIF","alert");else{const e=t.state==="recording"?"recording":"encoding";this.status.setMessage(`${e} ${t.frameIndex??0}/${t.totalFrames}`,"active")}}applyDefaults(){const t=this._config.defaultOptions??{},e=t.frameCount??re,r=t.frameRate??ae,a=t.scale??ie,i=t.repeat??rr;this.frameCountInput.value=String(e),this.frameRateInput.value=String(r),this.scaleInput.value=String(a),this.repeatInput.value=String(i),this.frameCountInput.refresh(),this.frameRateInput.refresh(),this.scaleInput.refresh(),this.repeatInput.refresh()}safeParseInt(t,e){const r=Number.parseInt(t,10);return Number.isFinite(r)?r:e}safeParseFloat(t,e){const r=Number.parseFloat(t);return Number.isFinite(r)?r:e}}const it="textmode-export-range-input",ar=`${it}__field`,ir=`${it}__tooltip`,mt=`${it}__tooltip--visible`,ot=(c,t)=>{if(typeof c!="string"||c.length===0)return t;const e=Number.parseFloat(c);return Number.isFinite(e)?e:t};class or extends N{props;input;tooltip;hoverActive=!1;focusActive=!1;pointerActive=!1;suppressFocusFromPointer=!1;activePointerId;disabledObserver;resizeObserver;constructor(t){super(),this.props=t}render(){const t=document.createElement("div");return t.className=it,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=ar,this.tooltip=document.createElement("div"),this.tooltip.className=ir,t.appendChild(this.input),t.appendChild(this.tooltip),this.bindEvents(t),this.updateTooltip(),this.syncDisabledState(t),t}get inputElement(){return this.input}get value(){return this.input.value}set value(t){this.input.value=t,this.updateTooltip()}_onDestroy(){this.disabledObserver?.disconnect(),this.resizeObserver?.disconnect()}bindEvents(t){this.input.addEventListener("pointerenter",()=>{this.hoverActive=!0,this.refreshTooltipVisibility()}),this.input.addEventListener("pointerleave",()=>{this.hoverActive=!1,this.refreshTooltipVisibility()}),this.input.addEventListener("focus",()=>{let r=!1;try{r=this.input.matches(":focus-visible")}catch{r=!this.suppressFocusFromPointer}this.suppressFocusFromPointer||!r||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",r=>{this.pointerActive=!0,this.suppressFocusFromPointer=!0,this.hoverActive=!0,this.refreshTooltipVisibility();try{this.input.setPointerCapture(r.pointerId),this.activePointerId=r.pointerId}catch{this.activePointerId=void 0}});const e=()=>{this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.hoverActive=this.input.matches(":hover"),this.releasePointerCapture(),this.refreshTooltipVisibility()};this.input.addEventListener("pointerup",e),this.input.addEventListener("pointercancel",e),this.input.addEventListener("lostpointercapture",e),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(mt)&&this.updateTooltipPosition()}),this.resizeObserver.observe(t))}refreshTooltipVisibility(){const t=(this.hoverActive||this.focusActive||this.pointerActive)&&!this.input.disabled;t&&this.updateTooltip(),this.tooltip.classList.toggle(mt,t)}syncDisabledState(t){const e=()=>{const r=this.input.disabled;t.classList.toggle("is-disabled",r),r&&(this.hoverActive=!1,this.focusActive=!1,this.pointerActive=!1,this.suppressFocusFromPointer=!1,this.releasePointerCapture(),this.tooltip.classList.remove(mt))};typeof MutationObserver<"u"&&(this.disabledObserver=new MutationObserver(e),this.disabledObserver.observe(this.input,{attributes:!0,attributeFilter:["disabled"]})),e()}releasePointerCapture(){if(this.activePointerId!==void 0){try{this.input.releasePointerCapture(this.activePointerId)}catch{}this.activePointerId=void 0}}updateTooltip(){this.updateTooltipContent(),this.updateTooltipPosition()}updateTooltipContent(){const t=this.props.formatValue??(r=>`${r}`),e=this.getCurrentValue();this.tooltip.textContent=t(e,this.input)}updateTooltipPosition(){const t=this.getMin(),e=this.getMax(),r=((n,l,d)=>Math.min(d,Math.max(l,n)))(this.getCurrentValue(),t,e),a=e-t,i=a===0?0:(r-t)/a;this.tooltip.style.left=100*i+"%"}getMin(){return ot(this.input.min,0)}getMax(){return ot(this.input.max,100)}getCurrentValue(){return ot(this.input.value,ot(this.props.defaultValue,0))}}function nr(c){return`${(function(e){if(!Number.isFinite(e))return"default quality";const r=Math.max(0,Math.min(1,e));return r>=.995?"near-lossless":r>=.98?"maximum detail":r>=.88?"ultra quality":r>=.7?"high quality":r>=.5?"balanced":r>=.25?"compact":r>=.1?"lightweight":"draft"})(c)} (quality ≈ ${c.toFixed(3)})`}class ft extends K{frameRateInput=this._manageComponent(new W({defaultValue:String(60),attributes:{min:String(1),max:String(60),step:"1"},formatDisplay:t=>Number.isFinite(t)?`${t} fps`:null}));frameCountInput=this._manageComponent(new W({defaultValue:String(480),attributes:{min:String(1),max:String(3600),step:"1"}}));qualityInput=this._manageComponent(new or({defaultValue:String(.7),attributes:{min:String(0),max:String(1),step:"0.001"},formatValue:t=>nr(t)}));status=this._manageComponent(new ee({title:"status",message:"ready to record",variant:"neutral",context:"video"}));recordingState="idle";constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z);const e=new Z("row");e.mount(t);const r=new R({label:"number of frames",labelFor:"textmode-export-video-frame-count",variant:"compact"});r.mount(e.root),this.frameCountInput.mount(r.root),this.frameCountInput.inputElement.id="textmode-export-video-frame-count";const a=new R({label:"frame rate (fps)",labelFor:"textmode-export-video-frame-rate",variant:"compact"});a.mount(e.root),this.frameRateInput.mount(a.root),this.frameRateInput.inputElement.id="textmode-export-video-frame-rate";const i=new R({label:"quality",labelFor:"textmode-export-video-quality",variant:"full"});return i.mount(t),this.qualityInput.mount(i.root),this.qualityInput.inputElement.id="textmode-export-video-quality",this.status.mount(t),t}getOptions(){const t=this._config.defaultOptions??{},e=Number.parseInt(this.frameCountInput.value,10),r=Number.parseFloat(this.frameRateInput.value),a=Number.parseFloat(this.qualityInput.value);return{frameCount:Number.isFinite(e)?e:t.frameCount??480,frameRate:Number.isFinite(r)?r:t.frameRate??60,quality:Number.isFinite(a)?a:t.quality??.7}}reset(){this.recordingState="idle",this.applyDefaults(),this.status.setMessage("ready to record","neutral")}validate(){const t=Number.parseInt(this.frameCountInput.value,10),e=Number.parseFloat(this.frameRateInput.value);return Number.isFinite(t)&&t>=1&&Number.isFinite(e)&&e>=1}isRecording(){return this.recordingState==="recording"}setRecordingState(t,e){this.recordingState=t;const r=t==="recording";this.frameCountInput.inputElement.disabled=r,this.frameRateInput.inputElement.disabled=r,this.qualityInput.inputElement.disabled=r,this.syncStatus(t,e)}handleProgress(t){this.syncStatus(t.state,t)}syncStatus(t,e){switch(t){case"recording":{const r=e?.frameIndex??0,a=e?.totalFrames??this.resolvePlannedFrameCount();if(a){const i=Math.min(Math.max(0,Math.round(r)),a);this.status.setMessage(`recording ${i}/${a} frames`,"active")}else this.status.setMessage(`recording ${Math.max(0,Math.round(r))} frames`,"active");break}case"completed":this.status.setMessage("saved to disk","active");break;case"error":this.status.setMessage(e?.message?`error: ${e.message}`:"recording failed","alert");break;default:this.status.setMessage("ready to record","neutral")}}resolvePlannedFrameCount(){const t=Number.parseInt(this.frameCountInput.value,10);return Number.isFinite(t)&&t>0?Math.round(t):void 0}applyDefaults(){const t=this._config.defaultOptions??{},e=t.frameCount??480,r=t.frameRate??60,a=t.quality??.7;this.frameCountInput.value=String(e),this.frameRateInput.value=String(r),this.qualityInput.value=String(a),this.frameCountInput.refresh(),this.frameRateInput.refresh()}}class sr{_textmodifier;_state;_events;_exportService;_clipboardService;_definitions;_formats=new Map;_eventUnsubscribers=[];_shadowHost;_shadowRoot;_overlayElement;_optionsContainer;_copyButtonContainer;_positionService;_header=new Y;_formatField=new R({label:"export format",labelFor:"textmode-export-format",variant:"full"});_formatSelect=new pt({id:"textmode-export-format",options:[]});_exportButton=new Jt({label:"download file",fullWidth:!0,variant:"primary"});_copyButton=new Jt({label:"copy to clipboard",fullWidth:!0,variant:"primary"});_currentFormat;_currentBlade;_handleFormatSelectChange=()=>{this._handleFormatChange(this._formatSelect.value)};_handleExportClickSafe=()=>{this._handleExportClick().catch(t=>{console.error("[textmode-export] Export failed",t)})};_handleCopyClickSafe=()=>{this._handleCopyClick().catch(t=>{console.error("[textmode-export] Copy failed",t)})};constructor(t,e,r,a,i){this._textmodifier=t,this._state=r,this._events=a,this._exportService=new Je(e,a),this._clipboardService=new Ye(e),this._definitions=i,this._currentFormat=r.snapshot.format,this._initializeFormatMap(),this._registerEventHandlers()}$mount(){this._createOverlay(),this._renderStaticContent(),this._positionService=new Ze(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(){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,this._shadowHost?.isConnected&&this._shadowHost.remove(),this._positionService?.dispose()}_initializeFormatMap(){for(const t of this._definitions){const e=t.createBlade();this._formats.set(t.format,{definition:t,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 t=document.createElement("style");t.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;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;inset: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;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(t),this._overlayElement=document.createElement("div"),this._overlayElement.dataset.plugin="textmode-export-overlay",this._overlayElement.classList.add(Pe,z),this._shadowRoot.appendChild(this._overlayElement),document.body.appendChild(this._shadowHost)}_renderStaticContent(){this._header.mount(this._overlayElement);const t=document.createElement("div");t.classList.add(Nt),this._overlayElement.appendChild(t),this._formatField.mount(t),this._prepareFormatOptions(),this._formatSelect.mount(this._formatField.root),this._formatSelect.selectElement.addEventListener("change",this._handleFormatSelectChange),this._optionsContainer=document.createElement("div"),this._optionsContainer.classList.add(z,Rt),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(z,dt),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 t=this._definitions.map(e=>({value:e.format,label:e.label}));this._formatSelect.update({options:t,defaultValue:this._currentFormat})}_registerEventHandlers(){this._eventUnsubscribers.push(this._events.$on("export:request",({format:t})=>{t===this._currentFormat&&(this._state.$set({isBusy:!0,error:void 0}),this._updateExportButton())}),this._events.$on("export:success",({format:t})=>{if(t===this._currentFormat){const e={isBusy:!1};t==="gif"&&(e.gifProgress=void 0),t==="video"&&(e.videoProgress=void 0),this._state.$set(e),this._updateExportButton()}}),this._events.$on("export:error",({format:t,error:e})=>{t===this._currentFormat&&(this._state.$set({isBusy:!1,error:e}),this._updateExportButton())}),this._events.$on("export:progress",({format:t,progress:e})=>{if(e){if(t==="gif"&&this._currentBlade?.blade instanceof ht){const r=e;this._state.$set({gifProgress:r}),this._currentBlade.blade.handleProgress(r)}else if(t==="video"&&this._currentBlade?.blade instanceof ft){const r=e;this._state.$set({videoProgress:r}),this._currentBlade.blade.handleProgress(r)}this._updateExportButton()}}))}_handleFormatChange(t){this._currentFormat=t,this._state.$set({format:t}),this._switchFormat(t),this._events.$emit("format:change",{format:t})}_switchFormat(t){const e=this._formats.get(t);if(!e)throw new Error(`Unknown export format: ${t}`);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=t,this._updateCopyButtonState(),this._updateExportButton(),this._positionService?.scheduleUpdate()}_updateCopyButtonState(){const t=this._currentBlade?.definition.supportsClipboard??!1;this._copyButtonContainer.style.display=t?"flex":"none",this._copyButton.setDisabled(!t)}async _handleExportClick(){if(!this._currentBlade)return;const t=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions();if(this._currentBlade.blade.validate()){if(t==="gif"){const r=this._currentBlade.blade;if(r.isRecording())return;r.setRecordingState("recording");try{await this._exportService.$requestExport("gif",e,{onGIFProgress:a=>{r.setRecordingState(a.state,a)}})}catch(a){throw r.setRecordingState("error"),a}return void window.setTimeout(()=>{r.setRecordingState("idle"),this._updateExportButton()},1600)}if(t==="video"){const r=this._currentBlade.blade;if(r.isRecording())return;r.setRecordingState("recording");try{await this._exportService.$requestExport("video",e,{onVideoProgress:a=>{r.setRecordingState(a.state,a)}})}catch(a){throw r.setRecordingState("error"),a}return void window.setTimeout(()=>{r.setRecordingState("idle"),this._updateExportButton()},1600)}this._exportButton.setDisabled(!0),this._exportButton.setLabel("exporting…");try{await this._exportService.$requestExport(t,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 t=this._currentBlade.definition.format,e=this._currentBlade.blade.getOptions(),r=this._copyButton.buttonElement.dataset.defaultLabel??"copy to clipboard";this._copyButton.setDisabled(!0),this._copyButton.setLabel("copying…");try{switch(t){case"txt":await this._clipboardService.$copy("txt",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(r),this._copyButton.setDisabled(!1)},1200)}}_updateExportButton(){if(!this._currentBlade)return;const t=this._currentBlade.definition.format;if(t==="gif"&&this._currentBlade.blade instanceof ht){const r=this._currentBlade.blade,a=this._state.snapshot.gifProgress;if(r.isRecording())if(this._exportButton.setDisabled(!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?.state==="encoding"?"encoding":"recording";this._exportButton.setLabel(`${i}…`)}else this._exportButton.setDisabled(!1),this._exportButton.setLabel("start recording");return}if(t==="video"&&this._currentBlade.blade instanceof ft){const r=this._currentBlade.blade,a=this._state.snapshot.videoProgress;if(r.isRecording())if(this._exportButton.setDisabled(!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 lr{_listeners={};_getPool(t){const e=this._listeners[t];if(e)return e;const r=new Set;return this._listeners[t]=r,r}$on(t,e){const r=this._getPool(t);return r.add(e),()=>{r.delete(e),r.size===0&&delete this._listeners[t]}}$emit(t,e){const r=this._listeners[t];if(r)for(const a of[...r])try{a(e)}catch(i){console.error("[textmode-export] Event handler failed",i)}}$clear(){for(const t of Object.keys(this._listeners))delete this._listeners[t]}}class dr{_state;_listeners=new Set;constructor(t){this._state=t}get snapshot(){return Object.freeze({...this._state})}$set(t){this._state=Object.assign({},this._state,t);const e=this.snapshot;for(const r of[...this._listeners])try{r(e)}catch(a){console.error("[textmode-export] State listener failed",a)}}$subscribe(t){return this._listeners.add(t),t(this.snapshot),()=>{this._listeners.delete(t)}}$reset(t){this._state=t;const e=this.snapshot;for(const r of[...this._listeners])r(e)}}class oe extends N{props;checkbox;labelElement;handleChange=()=>{this.props.defaultChecked=this.checkbox.checked};constructor(t){super(),this.props=t}render(){this.labelElement=document.createElement("label"),this.labelElement.classList.add(Ue),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 t=document.createElement("span");return t.textContent=this.props.label,this.labelElement.htmlFor=this.props.id??"",this.labelElement.appendChild(this.checkbox),this.labelElement.appendChild(t),this.labelElement}get inputElement(){return this.checkbox}get checked(){return this.checkbox.checked}set checked(t){this.checkbox.checked=t}_onUnmount(){this.checkbox.removeEventListener("change",this.handleChange)}onUpdate(t){this.props=t,t.id&&(this.checkbox.id=t.id,this.labelElement.htmlFor=t.id),this.checkbox.checked=!!t.defaultChecked,this.labelElement.lastElementChild&&(this.labelElement.lastElementChild.textContent=t.label)}}class cr extends N{props;input;handleInput=()=>{this.props.defaultValue=this.input.value};constructor(t){super(),this.props=t}render(){return this.input=document.createElement("input"),this.input.type="text",this.input.classList.add(Qt),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(t){this.input.value=t}_onUnmount(){this.input.removeEventListener("input",this.handleInput)}onUpdate(t){this.props=t,t.id&&(this.input.id=t.id),t.maxLength!==void 0&&(this.input.maxLength=t.maxLength),t.defaultValue!==void 0&&(this.input.value=t.defaultValue)}}class ur extends K{trailingSpaces=this._manageComponent(new oe({label:"preserve trailing spaces",defaultChecked:!1}));emptyCharacter=this._manageComponent(new cr({id:"textmode-export-empty-character",defaultValue:" ",maxLength:1}));constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z),this.trailingSpaces.mount(t);const e=new R({label:"empty character",labelFor:"textmode-export-empty-character",variant:"full"});return e.mount(t),this.emptyCharacter.mount(e.root),t}getOptions(){const t=this._config.defaultOptions??{},e=this.emptyCharacter.value||t.emptyCharacter||" ";return{preserveTrailingSpaces:this.trailingSpaces.checked,emptyCharacter:e}}reset(){this.applyDefaults()}validate(){return this.emptyCharacter.value.length<=1}applyDefaults(){const t=this._config.defaultOptions??{};this.trailingSpaces.checked=t.preserveTrailingSpaces??!1,this.emptyCharacter.value=t.emptyCharacter??" "}}class pr extends K{formatSelect=this._manageComponent(new pt({id:"textmode-export-image-format",options:[{value:"png",label:`PNG (${ce})`},{value:"jpg",label:`JPG (${ue})`},{value:"webp",label:`WEBP (${pe})`}],defaultValue:"png"}));scaleInput=this._manageComponent(new W({defaultValue:"1",attributes:{min:"0.1",step:"0.1"}}));constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z);const e=new Z("row");e.mount(t);const r=new R({label:"image format",labelFor:"textmode-export-image-format",variant:"compact"});r.mount(e.root),this.formatSelect.mount(r.root);const a=new R({label:"scale",labelFor:"textmode-export-image-scale",variant:"dense"});return a.mount(e.root),this.scaleInput.mount(a.root),this.scaleInput.inputElement.id="textmode-export-image-scale",t}getOptions(){const t=Number.parseFloat(this.scaleInput.value);return{format:this.formatSelect.value,scale:Number.isFinite(t)?t:this._config.defaultOptions?.scale??1}}reset(){this.applyDefaults(),this.scaleInput.refresh()}validate(){const t=Number.parseFloat(this.scaleInput.value);return Number.isFinite(t)&&t>0}applyDefaults(){const t=this._config.defaultOptions??{};this.formatSelect.value=t.format??"png";const e=t.scale??1;this.scaleInput.value=String(e)}}class hr extends K{includeBackground=this._manageComponent(new oe({id:"textmode-export-svg-include-backgrounds",label:"include cell backgrounds",defaultChecked:!0}));drawMode=this._manageComponent(new pt({id:"textmode-export-svg-draw-mode",options:[{value:"fill",label:"fill"},{value:"stroke",label:"stroke"}],defaultValue:"fill"}));strokeWidth=this._manageComponent(new W({defaultValue:"1",attributes:{min:"0",step:"0.1"}}));constructor(t){super(t)}render(){const t=document.createElement("div");t.classList.add(z),this.includeBackground.mount(t);const e=new Z("row");e.mount(t);const r=new R({label:"draw mode",labelFor:"textmode-export-svg-draw-mode",variant:"compact"});r.mount(e.root),this.drawMode.mount(r.root);const a=new R({label:"stroke width",labelFor:"textmode-export-svg-stroke-width",variant:"compact"});return a.mount(e.root),this.strokeWidth.mount(a.root),this.strokeWidth.inputElement.id="textmode-export-svg-stroke-width",this.drawMode.selectElement.addEventListener("change",()=>this.updateStrokeControls()),this.updateStrokeControls(),t}getOptions(){return{includeBackgroundRectangles:this.includeBackground.checked,drawMode:this.drawMode.value,strokeWidth:Number.parseFloat(this.strokeWidth.value)}}reset(){this.applyDefaults(),this.updateStrokeControls()}validate(){const t=Number.parseFloat(this.strokeWidth.value);return this.drawMode.value!=="stroke"||Number.isFinite(t)&&t>=0}updateStrokeControls(){const t=this.drawMode.value==="stroke";this.strokeWidth.inputElement.disabled=!t,this.strokeWidth.refresh()}applyDefaults(){const t=this._config.defaultOptions??{};this.includeBackground.checked=t.includeBackgroundRectangles??!0,this.drawMode.value=t.drawMode??"fill";const e=t.strokeWidth??1;this.strokeWidth.value=String(e),this.strokeWidth.refresh()}}const mr=[{format:"txt",label:"plain text (.txt)",supportsClipboard:!0,createBlade:()=>new ur({format:"txt",label:"plain text (.txt)",supportsClipboard:!0,defaultOptions:{preserveTrailingSpaces:!1,emptyCharacter:" "}})},{format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,createBlade:()=>new pr({format:"image",label:"image (.png / .jpg / .webp)",supportsClipboard:!0,defaultOptions:{format:"png",scale:1}})},{format:"svg",label:"vector (.svg)",supportsClipboard:!0,createBlade:()=>new hr({format:"svg",label:"vector (.svg)",supportsClipboard:!0,defaultOptions:{includeBackgroundRectangles:!0,drawMode:"fill",strokeWidth:1}})},{format:"gif",label:"animated GIF (.gif)",supportsClipboard:!1,createBlade:()=>new ht({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 ft({format:"video",label:"video (.webm)",supportsClipboard:!1,defaultOptions:{frameCount:480,frameRate:60,quality:.7}})}];function fr(c,t){const e=mr,r=e[0]?.format,a=new dr((l=>({format:l,isBusy:!1}))(r)),i=new lr,n=new sr(c,t,a,i,e);return n.$mount(),n}const gt={name:"textmode.export",version:"1.2.1",async install(c,t){const e={saveCanvas:async(l={})=>new _t().$saveImage(c.canvas,l),copyCanvas:async(l={})=>new _t().$copyImageToClipboard(c.canvas,l),saveSVG:(l={})=>{new yt().$saveSVG(c,l)},saveStrings:(l={})=>{new wt().$saveTXT(c,l)},toSVG:(l={})=>new yt().$generateSVG(c,l),toString:(l={})=>new wt().$generateTXT(c,l),saveGIF:async(l={})=>new Ee(c,t.registerPostDrawHook).$saveGIF(l),saveWEBM:async(l={})=>new Le(c,t.registerPostDrawHook).$saveWEBM(l)},r=fr(c,e),a={show:()=>r.show(),hide:()=>r.hide(),toggle:()=>r.toggle(),isVisible:()=>r.isVisible()},i={...e,exportOverlay:a},n=c;Object.assign(n,i),n._exportOverlayController=r},async uninstall(c){const t=c;t._exportOverlayController?.$dispose(),delete t._exportOverlayController;const r=["exportOverlay","saveCanvas","copyCanvas","saveSVG","saveStrings","toSVG","toString","saveGIF","saveWEBM"];for(const a of r)delete t[a]}},ne=(c={})=>{const t=c.overlay??!0,e={...gt},r=e.install;return e.install=async(a,i)=>{const n=a;await r.call(e,n,i),t||n.exportOverlay?.hide()},e};typeof window<"u"&&(window.ExportPlugin=gt,window.createTextmodeExportPlugin=ne),j.ExportPlugin=gt,j.createTextmodeExportPlugin=ne,Object.defineProperty(j,Symbol.toStringTag,{value:"Module"})});
@@ -7,15 +7,16 @@ import type { FramebufferData } from '../svg/types';
7
7
  export declare class DataExtractor {
8
8
  /**
9
9
  * Extracts pixel data from all framebuffers needed for export
10
+ *
10
11
  * @param framebuffer The conversion pipeline containing framebuffers
11
12
  * @returns Object containing all pixel data arrays
12
13
  */
13
14
  $extractFramebufferData(framebuffer: TextmodeFramebuffer): FramebufferData;
14
15
  /**
15
16
  * Gets character index from character framebuffer pixels
17
+ *
16
18
  * @param characterPixels Character framebuffer pixel data
17
19
  * @param pixelIndex Index in the pixel array (already multiplied by 4 for RGBA)
18
- * @param charactersLength Total number of available characters
19
20
  * @returns Character index
20
21
  */
21
22
  $getCharacterIndex(characterPixels: Uint8Array, pixelIndex: number): number;
@@ -1 +1 @@
1
- {"version":3,"file":"DataExtractor.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/DataExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;GAGG;AACH,qBAAa,aAAa;IACtB;;;;OAIG;IACI,uBAAuB,CAAC,WAAW,EAAE,mBAAmB,GAAG,eAAe;IAQjF;;;;;;OAMG;IACI,kBAAkB,CAAC,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAMrF"}
1
+ {"version":3,"file":"DataExtractor.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/DataExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;GAGG;AACH,qBAAa,aAAa;IACzB;;;;;OAKG;IACI,uBAAuB,CAAC,WAAW,EAAE,mBAAmB,GAAG,eAAe;IAQjF;;;;;;OAMG;IACI,kBAAkB,CAAC,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAMlF"}
@@ -5,18 +5,21 @@
5
5
  export declare class FileHandler {
6
6
  /**
7
7
  * Downloads content as a file
8
+ *
8
9
  * @param blob The content to download
9
10
  * @param filename The filename to use for the downloaded file
10
11
  */
11
12
  $downloadFile(blob: Blob, filename: string | undefined): void;
12
13
  /**
13
14
  * Validates and sanitizes filename for safety and compatibility
15
+ *
14
16
  * @param filename The filename to validate
15
17
  * @returns Sanitized filename
16
18
  */
17
19
  private _sanitizeFilename;
18
20
  /**
19
21
  * Generates a default filename with timestamp
22
+ *
20
23
  * @returns Generated filename
21
24
  */
22
25
  private _generateDefaultFilename;
@@ -1 +1 @@
1
- {"version":3,"file":"FileHandler.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/FileHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,WAAW;IAEpB;;;;OAIG;IACI,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAyBpE;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;CAGnC"}
1
+ {"version":3,"file":"FileHandler.d.ts","sourceRoot":"","sources":["../../../../src/exporters/base/FileHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,WAAW;IACvB;;;;;OAKG;IACI,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAyBpE;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;CAGhC"}
@@ -1,4 +1,5 @@
1
- import type { TextmodePluginAPI, Textmodifier } from 'textmode.js';
1
+ import type { Textmodifier } from 'textmode.js';
2
+ import type { TextmodePluginContext } from 'textmode.js/plugins';
2
3
  import type { GIFExportOptions } from './types';
3
4
  /**
4
5
  * Main GIF exporter for the textmode.js library.
@@ -11,17 +12,20 @@ export declare class GIFExporter {
11
12
  private readonly _registerPostDrawHook;
12
13
  /**
13
14
  * Creates an instance of GIFExporter.
15
+ *
14
16
  * @param textmodifier The Textmodifier instance to capture frames from
15
17
  * @param registerPostDrawHook Function to register post-draw hooks
16
18
  */
17
- constructor(textmodifier: Textmodifier, registerPostDrawHook: TextmodePluginAPI['registerPostDrawHook']);
19
+ constructor(textmodifier: Textmodifier, registerPostDrawHook: TextmodePluginContext['registerPostDrawHook']);
18
20
  /**
19
21
  * Captures frames and saves them as a GIF file
22
+ *
20
23
  * @param options Export options
21
24
  */
22
25
  $saveGIF(options?: GIFExportOptions): Promise<void>;
23
26
  /**
24
27
  * Applies default values to the provided export options
28
+ *
25
29
  * @param options User-provided options
26
30
  * @returns Complete options with defaults applied
27
31
  */
@@ -1 +1 @@
1
- {"version":3,"file":"GIFExporter.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/GIFExporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAwB,MAAM,SAAS,CAAC;AAItE;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4C;IAElF;;;;OAIG;gBACS,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC;IAMvG;;;OAGG;IACU,QAAQ,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDpE;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;CAc7B"}
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,4 +1,4 @@
1
- import type { TextmodePluginAPI } from 'textmode.js';
1
+ import type { TextmodePluginContext } from 'textmode.js/plugins';
2
2
  import type { GIFExportProgress, GIFFrame, GIFGenerationOptions } from './types';
3
3
  /**
4
4
  * Records frames from a canvas for GIF generation.
@@ -17,8 +17,8 @@ export declare class GIFRecorder {
17
17
  * @param registerPostDrawHook - Hook registration function from textmode.js API
18
18
  * @param onProgress - Optional callback for recording progress updates
19
19
  * @returns Promise resolving to array of captured frames
20
- * @throws Error if frame capture fails
20
+ * @throws {Error} If frame capture fails
21
21
  */
22
- $record(canvas: HTMLCanvasElement, options: GIFGenerationOptions, registerPostDrawHook: TextmodePluginAPI['registerPostDrawHook'], onProgress?: (progress: GIFExportProgress) => void): Promise<GIFFrame[]>;
22
+ $record(canvas: HTMLCanvasElement, options: GIFGenerationOptions, registerPostDrawHook: TextmodePluginContext['registerPostDrawHook'], onProgress?: (progress: GIFExportProgress) => void): Promise<GIFFrame[]>;
23
23
  }
24
24
  //# sourceMappingURL=GIFRecorder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GIFRecorder.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/GIFRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEjF;;;GAGG;AACH,qBAAa,WAAW;IACtB,wCAAwC;IACxC,OAAO,CAAC,OAAO,CAAC,CAAoB;IAEpC,4CAA4C;IAC5C,OAAO,CAAC,IAAI,CAAC,CAA2B;IAExC;;;;;;;;;OASG;IACU,OAAO,CAClB,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,oBAAoB,EAC7B,oBAAoB,EAAE,iBAAiB,CAAC,sBAAsB,CAAC,EAC/D,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,GACjD,OAAO,CAAC,QAAQ,EAAE,CAAC;CAoIvB"}
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,4 +1,4 @@
1
- export type GIFRecordingState = 'idle' | 'recording' | 'completed' | 'error';
1
+ export type GIFRecordingState = 'idle' | 'recording' | 'encoding' | 'completed' | 'error';
2
2
  /**
3
3
  * Progress information emitted during the GIF export process.
4
4
  */
@@ -6,7 +6,7 @@ export type GIFExportProgress = {
6
6
  /**
7
7
  * Current state of the recording process.
8
8
  */
9
- state: 'idle' | 'recording' | 'completed' | 'error';
9
+ state: 'idle' | 'recording' | 'encoding' | 'completed' | 'error';
10
10
  /**
11
11
  * Number of frames that have been recorded so far.
12
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,WAAW,GACX,WAAW,GACX,OAAO,CAAC;AAEZ;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;IACpD;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACpD,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/exporters/gif/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;AAE1F;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IACjE;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACnD,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB"}