@liiift-studio/threadtext 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- var ThreadText=(function(at){"use strict";const Dt={bg:"tt-bg",fx:"tt-fx"};function B(s,n){let e=Math.imul(s|0,374761393)+Math.imul(n|0,668265263)|0;return e=Math.imul(e^e>>>13,1274126177),((e^e>>>16)>>>0)/4294967295}function xt(s,n){const e=Math.floor(s),o=Math.floor(n),r=s-e,d=n-o,m=r*r*(3-2*r),b=d*d*(3-2*d),E=B(e,o),L=B(e+1,o),u=B(e,o+1),g=B(e+1,o+1);return E+(L-E)*m+(u-E)*b+(E-L-u+g)*m*b}const it=1e20;function Ot(s,n,e,o,r){let d=0;o[0]=0,r[0]=-it,r[1]=it;for(let m=1;m<n;m++){let b=(s[m]+m*m-(s[o[d]]+o[d]*o[d]))/(2*m-2*o[d]);for(;b<=r[d];)d--,b=(s[m]+m*m-(s[o[d]]+o[d]*o[d]))/(2*m-2*o[d]);d++,o[d]=m,r[d]=b,r[d+1]=it}d=0;for(let m=0;m<n;m++){for(;r[d+1]<m;)d++;e[m]=(m-o[d])*(m-o[d])+s[o[d]]}}function ee(s,n,e){const o=new Float64Array(n*e);for(let u=0;u<n*e;u++)o[u]=s[u]?it:0;const r=Math.max(n,e),d=new Float64Array(r),m=new Float64Array(r),b=new Int32Array(r),E=new Float64Array(r+1);for(let u=0;u<n;u++){for(let g=0;g<e;g++)d[g]=o[g*n+u];Ot(d,e,m,b,E);for(let g=0;g<e;g++)o[g*n+u]=m[g]}for(let u=0;u<e;u++){for(let g=0;g<n;g++)d[g]=o[u*n+g];Ot(d,n,m,b,E);for(let g=0;g<n;g++)o[u*n+g]=m[g]}const L=new Float32Array(n*e);for(let u=0;u<n*e;u++)L[u]=Math.sqrt(o[u]);return L}function _t(s,n,e,o,r){let d=Float32Array.from(s);const m=new Float32Array(n*e),b=1/(2*o+1),E=(L,u)=>L<0?0:L>u?u:L;for(let L=0;L<r;L++){for(let u=0;u<e;u++){const g=u*n;let v=0;for(let $=-o;$<=o;$++)v+=d[g+E($,n-1)];for(let $=0;$<n;$++)m[g+$]=v*b,v+=d[g+E($+o+1,n-1)]-d[g+E($-o,n-1)]}for(let u=0;u<n;u++){let g=0;for(let v=-o;v<=o;v++)g+=m[E(v,e-1)*n+u];for(let v=0;v<e;v++)d[v*n+u]=g*b,g+=m[E(v+o+1,e-1)*n+u]-m[E(v-o,e-1)*n+u]}}return d}function qt(s,n){if(!s)return n;const e=s.trim();if(e[0]==="#"){let r=e.slice(1);if(r.length===3&&(r=r[0]+r[0]+r[1]+r[1]+r[2]+r[2]),r.length>=6){const d=parseInt(r.slice(0,2),16),m=parseInt(r.slice(2,4),16),b=parseInt(r.slice(4,6),16);if(!Number.isNaN(d)&&!Number.isNaN(m)&&!Number.isNaN(b))return[d,m,b]}return n}const o=e.match(/rgba?\(([^)]+)\)/i);if(o){const r=o[1].split(",").map(d=>parseFloat(d));if(r.length>=3&&r.slice(0,3).every(d=>!Number.isNaN(d)))return[Math.round(r[0]),Math.round(r[1]),Math.round(r[2])]}return n}function P(s){return s<0?0:s>255?255:Math.round(s)}function ne(s,n){if(typeof window>"u"||typeof document>"u"||!s)return{setText(){},replay(){},resize(){},destroy(){},get text(){return n.text??""}};let e=n.text??"";const o=n.font??"Georgia, serif",r=n.weight??680,d=n.aspect??.46,m=n.sewRate??110,b=n.sheen??!0,E=n.animate??!0,L=(o.split(",")[0]||"serif").trim().replace(/^["']|["']$/g,""),u=n.reducedMotion??!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),g=qt(n.threadColor??"#fffbf3",[255,251,243]),v=[g[0]*.585,g[1]*.585,g[2]*.585],$=[g[0]*.47,g[1]*.47,g[2]*.47],st=qt(n.fabricColor??"#08080a",[8,8,10]),ce=[P(st[0]+14),P(st[1]+13),P(st[2]+15)],kt=t=>`rgb(${P(t[0])},${P(t[1])},${P(t[2])})`,Mt=[];let R,j;s instanceof HTMLCanvasElement?(R=s,j=s.parentElement??s):(j=s,R=document.createElement("canvas"),Mt.push(R),j.appendChild(R)),R.classList.add(Dt.bg);const X=document.createElement("canvas");Mt.push(X),X.classList.add(Dt.fx),j.appendChild(X),getComputedStyle(j).position==="static"&&(j.style.position="relative"),R.style.display="block",R.style.width="100%",Object.assign(X.style,{position:"absolute",inset:"0",width:"100%",pointerEvents:"none",mixBlendMode:"screen"});let c=0,l=0,lt=0,Ct=0,J=4,Q=[],Z=0,W=0,St=new Uint8Array(0),At=new Float32Array(0),ft=new Float32Array(0),dt=new Float32Array(0),k=null,G=null,U=null,tt=null,ut=null,q=[],ht=3;const S={rows:[],idx:0,acc:0,rate:0,on:!1},V={x:0,y:0,set:!1};let H=!0,Tt=0,zt=!1,mt=0,K=!1,Ft=!1;function Bt(){const t=j.getBoundingClientRect(),a=Math.round(t.width||Math.min(window.innerWidth*.95,1240)),i=Math.round(a*d);let f=Math.min(window.devicePixelRatio||1,1.7);for(;a*f*i*f>9e5&&f>.55;)f-=.1;c=Math.max(1,Math.round(a*f)),l=Math.max(1,Math.round(i*f));for(const h of[R,X])h.width=c,h.height=l,h.style.height=i+"px";j.style.height=i+"px"}function Xt(){const t=Math.max(7,J*2.5),a=Math.max(3.2,J*1.3);Z=Math.ceil(t)+2,W=Math.ceil(a)+2,Q=[];for(let i=0;i<20;i++){const f=.34+i/19*.82,h=document.createElement("canvas");h.width=Z,h.height=W;const M=h.getContext("2d");if(!M){Q.push(h);continue}const C=Z/2,T=W/2,I=M.createLinearGradient(0,T-a/2,0,T+a/2),p=(N,D)=>`rgba(${P(N[0]*f)},${P(N[1]*f)},${P(N[2]*f)},${D})`;I.addColorStop(0,p($,0)),I.addColorStop(.16,p(v,1)),I.addColorStop(.5,p(g,1)),I.addColorStop(.84,p(v,1)),I.addColorStop(1,p($,0)),M.fillStyle=I,M.beginPath();const x=a/2;M.moveTo(C-t/2+x,T-x),M.lineTo(C+t/2-x,T-x),M.arc(C+t/2-x,T,x,-Math.PI/2,Math.PI/2),M.lineTo(C-t/2+x,T+x),M.arc(C-t/2+x,T,x,Math.PI/2,-Math.PI/2),M.closePath(),M.fill(),M.globalCompositeOperation="destination-in";const F=M.createLinearGradient(C-t/2,0,C+t/2,0);F.addColorStop(0,"rgba(0,0,0,0)"),F.addColorStop(.22,"rgba(0,0,0,1)"),F.addColorStop(.78,"rgba(0,0,0,1)"),F.addColorStop(1,"rgba(0,0,0,0)"),M.fillStyle=F,M.fillRect(0,0,Z,W),Q.push(h)}}function bt(){if(!ut)return;const t=ut;t.clearRect(0,0,c,l),t.fillStyle="#fff",t.textAlign="left",t.textBaseline="middle",t.font=`${r} ${lt}px ${o}`,t.fillText(e,Ct,l*.5);const a=t.getImageData(0,0,c,l).data,i=new Uint8Array(c*l);for(let y=0;y<l;y++)for(let A=0;A<c;A++){const w=y*c+A,O=a[w*4+3]/255,_=xt(A*.5,y*.5)*.22+xt(A*1.8,y*1.8)*.1;i[w]=O>.5+(_-.16)?1:0}St=i;const f=ee(i,c,l),h=new Float32Array(c*l);for(let y=1;y<l-1;y++)for(let A=1;A<c-1;A++){const w=y*c+A;h[w]=(f[w]*4+f[w-1]+f[w+1]+f[w-c]+f[w+c])/8}const M=new Float32Array(c*l),C=new Float32Array(c*l),T=new Float32Array(c*l),I=new Float32Array(c*l);for(let y=1;y<l-1;y++)for(let A=1;A<c-1;A++){const w=y*c+A;if(!i[w])continue;const O=(h[w+1]-h[w-1])*.5,_=(h[w+c]-h[w-c])*.5;T[w]=O,I[w]=_,M[w]=O*O-_*_,C[w]=2*O*_}const p=Math.max(7,Math.round(l*.05)),x=_t(M,c,l,p,2),F=_t(C,c,l,p,2);ft=new Float32Array(c*l),dt=new Float32Array(c*l);for(let y=0;y<c*l;y++){if(!i[y])continue;const A=.5*Math.atan2(F[y],x[y]);ft[y]=Math.cos(A),dt[y]=Math.sin(A)}const N=Math.max(9,l*.04),D=new Float32Array(c*l),ot=-.45,rt=-.62,wt=.64;for(let y=1;y<l-1;y++)for(let A=1;A<c-1;A++){const w=y*c+A;if(!i[w])continue;let O=T[w],_=I[w];const Qt=Math.hypot(O,_)||1;O/=Qt,_/=Qt;const Zt=h[w],Wt=(1-Math.min(Zt/N,1))*1.25;let Lt=-O*Wt,Rt=-_*Wt;const te=1.5,Pt=Math.hypot(Lt,Rt,te);Lt/=Pt,Rt/=Pt;let $t=Lt*ot+Rt*rt+te/Pt*wt;$t<0&&($t=0);const me=Math.min(1,.45+.55*Math.min(Zt/(N*.7),1));D[w]=Math.min(1.12,(.5+.75*$t)*me)}At=D,k=document.createElement("canvas"),k.width=c,k.height=l;const z=k.getContext("2d");G=document.createElement("canvas"),G.width=c,G.height=l;const Y=G.getContext("2d");if(z&&Y){const y=z.createImageData(c,l),A=Y.createImageData(c,l);for(let w=0;w<c*l;w++)i[w]&&(y.data[w*4]=255,y.data[w*4+1]=255,y.data[w*4+2]=255,y.data[w*4+3]=255,A.data[w*4+3]=255);z.putImageData(y,0,0),Y.putImageData(A,0,0)}}function Gt(){U=document.createElement("canvas"),U.width=c,U.height=l;const t=U.getContext("2d",{willReadFrequently:!0});if(t){const a=t.createRadialGradient(c*.5,l*.4,0,c*.5,l*.5,c*.72);a.addColorStop(0,kt(ce)),a.addColorStop(1,kt(st)),t.fillStyle=a,t.fillRect(0,0,c,l);const i=t.getImageData(0,0,c,l),f=i.data;for(let h=0;h<l;h++)for(let M=0;M<c;M++){const C=(h*c+M)*4,T=Math.sin(M*1.9)*.5+.5,I=Math.sin(h*1.9)*.5+.5,p=T*I*9-4.5+(xt(M*.18,h*.18)-.5)*15;f[C]=P(f[C]+p),f[C+1]=P(f[C+1]+p),f[C+2]=P(f[C+2]+p*1.1)}t.putImageData(i,0,0)}tt=document.createElement("canvas"),tt.width=c,tt.height=l,ut=tt.getContext("2d",{willReadFrequently:!0})}function Et(){const t=Math.max(1.6,J*.6);ht=t;const a=[];for(let i=0;i<l;i+=t)for(let f=0;f<c;f+=t){const h=(B(Math.floor(f),Math.floor(i))-.5)*t*.9,M=(B(Math.floor(i),Math.floor(f))-.5)*t*.9,C=Math.round(f+h),T=Math.round(i+M);if(C<1||T<1||C>=c-1||T>=l-1)continue;const I=T*c+C;if(!St[I])continue;const p=Math.atan2(dt[I],ft[I]),x=.86+B(C*7,T*13)*.18;let F=At[I]*x;F=F<0?0:F>1.12?1.12:F,a.push({x:C,y:T,ang:p,idx:Math.min(19,Math.max(0,Math.round(F/1.12*19)))})}a.sort((i,f)=>i.x-f.x),q=a}function gt(t,a){t.save(),t.translate(a.x,a.y),t.rotate(a.ang),t.drawImage(Q[a.idx],-Z/2,-W/2),t.restore()}function yt(){const t=R.getContext("2d");if(t)for(const a of q)gt(t,a)}function Ut(){return q.length?q[q.length-1].x:0}function It(){return q.length?q[0].x:0}function et(){const t=R.getContext("2d");!t||!U||(t.drawImage(U,0,0),G&&(t.save(),t.globalAlpha=.85,t.filter=`blur(${Math.round(l*.018)}px)`,t.drawImage(G,0,Math.round(l*.02)),t.restore()))}function se(t){if(!t.length)return[];const a=Math.max(4,ht*1.5),i=new Map,f=(p,x)=>p+","+x;t.forEach((p,x)=>{const F=f(Math.floor(p.x/a),Math.floor(p.y/a));let N=i.get(F);N||i.set(F,N=[]),N.push(x)});const h=ht*1.8*(ht*1.8);function M(p){const x=t[p],F=Math.floor(x.x/a),N=Math.floor(x.y/a),D=[];for(let ot=-1;ot<=1;ot++)for(let rt=-1;rt<=1;rt++){const wt=i.get(f(F+ot,N+rt));if(wt)for(const z of wt){if(z===p)continue;const Y=t[z].x-x.x,y=t[z].y-x.y;Y*Y+y*y<=h&&D.push(z)}}return D}const C=new Uint8Array(t.length),T=[],I=t.map((p,x)=>x).sort((p,x)=>t[p].x+t[p].y-(t[x].x+t[x].y));for(const p of I){if(C[p])continue;let x=[p];for(C[p]=1;x.length;){T.push(x.map(N=>t[N]));const F=[];for(const N of x)for(const D of M(N))C[D]||(C[D]=1,F.push(D));x=F}}return T}function vt(t,a){et();const i=R.getContext("2d");if(!i)return;const f=[];for(const h of q)h.x<=t?gt(i,h):f.push(h);if(u){for(const h of f)gt(i,h);S.on=!1;return}S.rows=se(f),S.idx=0,S.acc=0,S.rate=a||m,S.on=S.rows.length>0}function le(t){const a=R.getContext("2d");if(a)for(t>S.rows.length&&(t=S.rows.length);S.idx<t;){const i=S.rows[S.idx++];for(const f of i)gt(a,f)}}function fe(t,a){const i=X.getContext("2d");if(!i||(i.clearRect(0,0,c,l),!b||!k))return;const f=c*.32,h=i.createRadialGradient(t,a,0,t,a,f);h.addColorStop(0,"rgba(255,250,238,0.18)"),h.addColorStop(.5,"rgba(255,250,238,0.055)"),h.addColorStop(1,"rgba(255,250,238,0)"),i.fillStyle=h,i.fillRect(0,0,c,l),i.globalCompositeOperation="destination-in",i.drawImage(k,0,0),i.globalCompositeOperation="source-over"}function Vt(){const t=R.getContext("2d");if(!t){lt=Math.round(l*.6),Ct=Math.round(c*.14);return}const a=e||"Ag";t.font=`${r} 100px ${o}`;const i=t.measureText(a).width||100;lt=Math.round(100*(c*.72)/i),t.font=`${r} ${lt}px ${o}`,Ct=Math.round(c/2-t.measureText(a).width/2)}function Ht(t){if(K)return;mt||(mt=t);const a=Math.min(.25,(t-mt)/1e3);mt=t,S.on&&(S.acc+=S.rate*a,le(S.acc),S.idx>=S.rows.length&&(S.on=!1)),H&&k&&(fe(V.set?V.x:c*.5,V.set?V.y:l*.34),H=!1),Tt=requestAnimationFrame(Ht)}function Kt(t){const a=X.getBoundingClientRect();V.x=(t.clientX-a.left)/(a.width||1)*c,V.y=(t.clientY-a.top)/(a.height||1)*l,V.set=!0,H=!0}b&&window.addEventListener("pointermove",Kt,{passive:!0});function de(t){bt(),Et(),E&&!u?vt(It()-1,m):(et(),yt(),S.on=!1),H=!0}function ue(){K||(Bt(),Gt(),J=Math.max(3.4,l*.0095),Xt(),Vt(),de(),Ft=!0,zt||(zt=!0,Tt=requestAnimationFrame(Ht)))}let nt;function he(t){const a=`${r} 200px ${L}`;let i=!1;try{i=!!document.fonts&&document.fonts.check(a)}catch{i=!0}if(!document.fonts||i){t();return}let f=!1;const h=()=>{f||(f=!0,nt&&clearTimeout(nt),t())};document.fonts.load(a,e).then(()=>document.fonts.ready).then(h,h),nt=setTimeout(h,1500)}he(ue);let Nt;function Yt(){clearTimeout(Nt),Nt=setTimeout(()=>Jt.resize(),200)}window.addEventListener("resize",Yt);const Jt={get text(){return e},setText(t){if(K||!Ft){e=t??"";return}t=t??"";const a=t.length>e.length&&e.length>0&&t.startsWith(e),i=a?Ut():-1;e=t,bt(),Et(),u||!E?(et(),yt(),S.on=!1):vt(a&&i>0?Math.min(i,Ut()):It()-1,a?320:m),H=!0},replay(){K||!Ft||(u||!E?(et(),yt(),S.on=!1):vt(It()-1,m),H=!0)},resize(){K||(Bt(),Gt(),J=Math.max(3.4,l*.0095),Xt(),Vt(),bt(),Et(),et(),yt(),S.on=!1,H=!0)},destroy(){if(!K){K=!0,cancelAnimationFrame(Tt),clearTimeout(Nt),nt&&clearTimeout(nt),window.removeEventListener("resize",Yt),b&&window.removeEventListener("pointermove",Kt);for(const t of Mt)t.remove();Q=[],q=[],S.rows=[],St=new Uint8Array(0),At=new Float32Array(0),ft=new Float32Array(0),dt=new Float32Array(0),k=G=U=tt=null,ut=null}}};return Jt}const oe="data-threadtext",pt=new WeakMap;function re(s,n){const e=s.dataset,o={text:e.ttText??n};if(e.ttFont&&(o.font=e.ttFont),e.ttWeight!==void 0){const r=parseFloat(e.ttWeight);isNaN(r)||(o.weight=r)}if(e.ttThreadColor&&(o.threadColor=e.ttThreadColor),e.ttFabricColor&&(o.fabricColor=e.ttFabricColor),e.ttPitch!==void 0){const r=parseFloat(e.ttPitch);isNaN(r)||(o.pitch=r)}if(e.ttSewRate!==void 0){const r=parseFloat(e.ttSewRate);isNaN(r)||(o.sewRate=r)}if(e.ttAspect!==void 0){const r=parseFloat(e.ttAspect);isNaN(r)||(o.aspect=r)}return e.ttSheen==="false"&&(o.sheen=!1),e.ttAnimate==="false"&&(o.animate=!1),o}function ae(s){jt(s);const n=s.innerHTML,e=(s.dataset.ttText??s.textContent??"").trim();if(!e)return;const o=re(s,e);s.setAttribute("role","img"),s.setAttribute("aria-label",e),s.innerHTML="";const r=ne(s,o);pt.set(s,{instance:r,originalHTML:n})}function jt(s){const n=pt.get(s);n&&(n.instance.destroy(),s.removeAttribute("role"),s.removeAttribute("aria-label"),s.innerHTML=n.originalHTML,pt.delete(s))}function ct(s=document){s.querySelectorAll(`[${oe}]`).forEach(ae)}function ie(){const s=()=>{var n;typeof document<"u"&&((n=document.fonts)!=null&&n.ready)?document.fonts.ready.then(()=>ct()).catch(()=>ct()):ct()};typeof document<"u"&&document.readyState==="loading"?document.addEventListener("DOMContentLoaded",s,{once:!0}):s()}return ie(),at.destroy=jt,at.init=ct,Object.defineProperty(at,Symbol.toStringTag,{value:"Module"}),at})({});
1
+ var ThreadText=(function(ct){"use strict";const bt={bg:"tt-bg",fx:"tt-fx",caret:"tt-caret"};function K(r,n){let e=Math.imul(r|0,374761393)+Math.imul(n|0,668265263)|0;return e=Math.imul(e^e>>>13,1274126177),((e^e>>>16)>>>0)/4294967295}function _t(r,n){const e=Math.floor(r),o=Math.floor(n),i=r-e,c=n-o,m=i*i*(3-2*i),F=c*c*(3-2*c),$=K(e,o),E=K(e+1,o),u=K(e,o+1),y=K(e+1,o+1);return $+(E-$)*m+(u-$)*F+($-E-u+y)*m*F}const ft=1e20;function qt(r,n,e,o,i){let c=0;o[0]=0,i[0]=-ft,i[1]=ft;for(let m=1;m<n;m++){let F=(r[m]+m*m-(r[o[c]]+o[c]*o[c]))/(2*m-2*o[c]);for(;F<=i[c];)c--,F=(r[m]+m*m-(r[o[c]]+o[c]*o[c]))/(2*m-2*o[c]);c++,o[c]=m,i[c]=F,i[c+1]=ft}c=0;for(let m=0;m<n;m++){for(;i[c+1]<m;)c++;e[m]=(m-o[c])*(m-o[c])+r[o[c]]}}function ce(r,n,e){const o=new Float64Array(n*e);for(let u=0;u<n*e;u++)o[u]=r[u]?ft:0;const i=Math.max(n,e),c=new Float64Array(i),m=new Float64Array(i),F=new Int32Array(i),$=new Float64Array(i+1);for(let u=0;u<n;u++){for(let y=0;y<e;y++)c[y]=o[y*n+u];qt(c,e,m,F,$);for(let y=0;y<e;y++)o[y*n+u]=m[y]}for(let u=0;u<e;u++){for(let y=0;y<n;y++)c[y]=o[u*n+y];qt(c,n,m,F,$);for(let y=0;y<n;y++)o[u*n+y]=m[y]}const E=new Float32Array(n*e);for(let u=0;u<n*e;u++)E[u]=Math.sqrt(o[u]);return E}function zt(r,n,e,o,i){let c=Float32Array.from(r);const m=new Float32Array(n*e),F=1/(2*o+1),$=(E,u)=>E<0?0:E>u?u:E;for(let E=0;E<i;E++){for(let u=0;u<e;u++){const y=u*n;let I=0;for(let D=-o;D<=o;D++)I+=c[y+$(D,n-1)];for(let D=0;D<n;D++)m[y+D]=I*F,I+=c[y+$(D+o+1,n-1)]-c[y+$(D-o,n-1)]}for(let u=0;u<n;u++){let y=0;for(let I=-o;I<=o;I++)y+=m[$(I,e-1)*n+u];for(let I=0;I<e;I++)c[I*n+u]=y*F,y+=m[$(I+o+1,e-1)*n+u]-m[$(I-o,e-1)*n+u]}}return c}function Gt(r,n){if(!r)return n;const e=r.trim();if(e[0]==="#"){let i=e.slice(1);if(i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),i.length>=6){const c=parseInt(i.slice(0,2),16),m=parseInt(i.slice(2,4),16),F=parseInt(i.slice(4,6),16);if(!Number.isNaN(c)&&!Number.isNaN(m)&&!Number.isNaN(F))return[c,m,F]}return n}const o=e.match(/rgba?\(([^)]+)\)/i);if(o){const i=o[1].split(",").map(c=>parseFloat(c));if(i.length>=3&&i.slice(0,3).every(c=>!Number.isNaN(c)))return[Math.round(i[0]),Math.round(i[1]),Math.round(i[2])]}return n}function z(r){return r<0?0:r>255?255:Math.round(r)}function dt(r,n,e){return r<n?n:r>e?e:r}function Ut(r){return(r.split(",")[0]||"serif").trim().replace(/^["']|["']$/g,"")}function fe(r,n){if(typeof window>"u"||typeof document>"u"||!r)return{setText(){},replay(){},resize(){},update(){},focus(){},destroy(){},get text(){return n.text??""}};let e=n.text??"",o=n.font??"Georgia, serif",i=dt(n.weight??680,1,1e3),c=dt(n.fill??.9,.05,1),m=Math.max(1,n.sewRate??110),F=n.sheen??!0,$=n.animate??!0,E=n.editable??!1,u=n.pitch,y=n.onTextChange,I=Ut(o);const D=n.reducedMotion??!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches);let P=Gt(n.threadColor??"#fffbf3",[255,251,243]),St=[0,0,0],At=[0,0,0];function Ht(t){P=Gt(t,[255,251,243]),St=[P[0]*.585,P[1]*.585,P[2]*.585],At=[P[0]*.47,P[1]*.47,P[2]*.47]}Ht(n.threadColor??"#fffbf3");const nt=[];let O,L;r instanceof HTMLCanvasElement?(O=r,L=r.parentElement??r):(L=r,O=document.createElement("canvas"),nt.push(O),L.appendChild(O)),O.classList.add(bt.bg);const V=document.createElement("canvas");nt.push(V),V.classList.add(bt.fx),L.appendChild(V),getComputedStyle(L).position==="static"&&(L.style.position="relative"),O.style.display="block",O.style.width="100%",Object.assign(V.style,{position:"absolute",inset:"0",width:"100%",pointerEvents:"none",mixBlendMode:"screen"});let g=null,R=null,ht=!1,s=0,h=0,J=0,Et=0,Q=4,Z=[],ot=0,it=0,Kt=-1,Vt="",Yt=-1,Jt=-1,Ft=new Uint8Array(0),Lt=new Float32Array(0),mt=new Float32Array(0),yt=new Float32Array(0),U=null,W=null,xt=null,gt=[],pt=3;const A={rows:[],idx:0,acc:0,rate:0,on:!1},G={x:0,y:0,set:!1};let Y=!0,Rt=0,rt=!1,at=0,k=!1,X=!1;function ye(){const t=L.getBoundingClientRect(),a=Math.max(1,Math.round(t.width||Math.min(window.innerWidth*.95,1240))),l=e||"Ag",f=O.getContext("2d");f&&(f.textBaseline="middle");let b=100;f&&(f.font=`${i} 100px ${o}`,b=f.measureText(l).width||100);const v=Math.max(8,100*(a*c)/b);let C=v*.62,T=v*.62,N=a*c;if(f){f.font=`${i} ${v}px ${o}`;const w=f.measureText(l);N=w.width||N,w.actualBoundingBoxAscent>0&&(C=w.actualBoundingBoxAscent),w.actualBoundingBoxDescent>0&&(T=w.actualBoundingBoxDescent)}const p=Math.max(1,Math.round(2*Math.max(C,T)*1.1));let d=Math.min(window.devicePixelRatio||1,1.7);for(;a*d*p*d>9e5&&d>.4;)d-=.1;s=Math.max(1,Math.round(a*d)),h=Math.max(1,Math.round(p*d)),J=Math.max(4,Math.round(v*d)),Et=Math.round(s/2-N*d/2);for(const w of[O,V])w.width=s,w.height=h,w.style.height=p+"px";L.style.height=p+"px",Q=u??Math.max(3,h*.0095)}function xe(){W&&Yt===s&&Jt===h||(W=document.createElement("canvas"),W.width=s,W.height=h,xt=W.getContext("2d",{willReadFrequently:!0}),Yt=s,Jt=h)}function Qt(){const t=Math.max(7,Q*2.5),a=Math.max(3.2,Q*1.3);ot=Math.ceil(t)+2,it=Math.ceil(a)+2,Z=[];for(let l=0;l<20;l++){const f=.34+l/19*.82,b=document.createElement("canvas");b.width=ot,b.height=it;const v=b.getContext("2d");if(!v){Z.push(b);continue}const C=ot/2,T=it/2,N=v.createLinearGradient(0,T-a/2,0,T+a/2),p=(B,j)=>`rgba(${z(B[0]*f)},${z(B[1]*f)},${z(B[2]*f)},${j})`;N.addColorStop(0,p(At,0)),N.addColorStop(.16,p(St,1)),N.addColorStop(.5,p(P,1)),N.addColorStop(.84,p(St,1)),N.addColorStop(1,p(At,0)),v.fillStyle=N,v.beginPath();const d=a/2;v.moveTo(C-t/2+d,T-d),v.lineTo(C+t/2-d,T-d),v.arc(C+t/2-d,T,d,-Math.PI/2,Math.PI/2),v.lineTo(C-t/2+d,T+d),v.arc(C-t/2+d,T,d,Math.PI/2,-Math.PI/2),v.closePath(),v.fill(),v.globalCompositeOperation="destination-in";const w=v.createLinearGradient(C-t/2,0,C+t/2,0);w.addColorStop(0,"rgba(0,0,0,0)"),w.addColorStop(.22,"rgba(0,0,0,1)"),w.addColorStop(.78,"rgba(0,0,0,1)"),w.addColorStop(1,"rgba(0,0,0,0)"),v.fillStyle=w,v.fillRect(0,0,ot,it),Z.push(b)}Kt=Q,Vt=P.join(",")}function ge(){Z.length&&Kt===Q&&Vt===P.join(",")||Qt()}function pe(){if(!xt)return;const t=xt;t.clearRect(0,0,s,h),t.fillStyle="#fff",t.textAlign="left",t.textBaseline="middle",t.font=`${i} ${J}px ${o}`,t.fillText(e,Et,h*.5);const a=t.getImageData(0,0,s,h).data,l=new Uint8Array(s*h);for(let x=0;x<h;x++)for(let M=0;M<s;M++){const S=x*s+M,_=a[S*4+3]/255,q=_t(M*.5,x*.5)*.22+_t(M*1.8,x*1.8)*.1;l[S]=_>.5+(q-.16)?1:0}Ft=l;const f=ce(l,s,h),b=new Float32Array(s*h);for(let x=1;x<h-1;x++)for(let M=1;M<s-1;M++){const S=x*s+M;b[S]=(f[S]*4+f[S-1]+f[S+1]+f[S-s]+f[S+s])/8}const v=new Float32Array(s*h),C=new Float32Array(s*h),T=new Float32Array(s*h),N=new Float32Array(s*h);for(let x=1;x<h-1;x++)for(let M=1;M<s-1;M++){const S=x*s+M;if(!l[S])continue;const _=(b[S+1]-b[S-1])*.5,q=(b[S+s]-b[S-s])*.5;T[S]=_,N[S]=q,v[S]=_*_-q*q,C[S]=2*_*q}const p=Math.max(7,Math.round(h*.05)),d=zt(v,s,h,p,2),w=zt(C,s,h,p,2);mt=new Float32Array(s*h),yt=new Float32Array(s*h);for(let x=0;x<s*h;x++){if(!l[x])continue;const M=.5*Math.atan2(w[x],d[x]);mt[x]=Math.cos(M),yt[x]=Math.sin(M)}const B=Math.max(9,h*.04),j=new Float32Array(s*h),lt=-.45,st=-.62,Ct=.64;for(let x=1;x<h-1;x++)for(let M=1;M<s-1;M++){const S=x*s+M;if(!l[S])continue;let _=T[S],q=N[S];const re=Math.hypot(_,q)||1;_/=re,q/=re;const ae=b[S],le=(1-Math.min(ae/B,1))*1.25;let Ot=-_*le,kt=-q*le;const se=1.5,Dt=Math.hypot(Ot,kt,se);Ot/=Dt,kt/=Dt;let jt=Ot*lt+kt*st+se/Dt*Ct;jt<0&&(jt=0);const Ne=Math.min(1,.45+.55*Math.min(ae/(B*.7),1));j[S]=Math.min(1.12,(.5+.75*jt)*Ne)}Lt=j,U=document.createElement("canvas"),U.width=s,U.height=h;const H=U.getContext("2d");if(H){const x=H.createImageData(s,h);for(let M=0;M<s*h;M++)l[M]&&(x.data[M*4]=255,x.data[M*4+1]=255,x.data[M*4+2]=255,x.data[M*4+3]=255);H.putImageData(x,0,0)}}function we(){const t=Math.max(1.6,Q*.6);pt=t;const a=[];for(let l=0;l<h;l+=t)for(let f=0;f<s;f+=t){const b=(K(Math.floor(f),Math.floor(l))-.5)*t*.9,v=(K(Math.floor(l),Math.floor(f))-.5)*t*.9,C=Math.round(f+b),T=Math.round(l+v);if(C<1||T<1||C>=s-1||T>=h-1)continue;const N=T*s+C;if(!Ft[N])continue;const p=Math.atan2(yt[N],mt[N]),d=.86+K(C*7,T*13)*.18;let w=Lt[N]*d;w=w<0?0:w>1.12?1.12:w,a.push({x:C,y:T,ang:p,idx:Math.min(19,Math.max(0,Math.round(w/1.12*19)))})}gt=a}function Zt(t,a){t.save(),t.translate(a.x,a.y),t.rotate(a.ang),t.drawImage(Z[a.idx],-ot/2,-it/2),t.restore()}function Nt(){const t=O.getContext("2d");if(t)for(const a of gt)Zt(t,a)}function $t(){const t=O.getContext("2d");t&&t.clearRect(0,0,s,h)}function Me(t){if(!t.length)return[];const a=Math.max(4,pt*1.5),l=new Map,f=(p,d)=>p+","+d;t.forEach((p,d)=>{const w=f(Math.floor(p.x/a),Math.floor(p.y/a));let B=l.get(w);B||l.set(w,B=[]),B.push(d)});const b=pt*1.8*(pt*1.8);function v(p){const d=t[p],w=Math.floor(d.x/a),B=Math.floor(d.y/a),j=[];for(let lt=-1;lt<=1;lt++)for(let st=-1;st<=1;st++){const Ct=l.get(f(w+lt,B+st));if(Ct)for(const H of Ct){if(H===p)continue;const x=t[H].x-d.x,M=t[H].y-d.y;x*x+M*M<=b&&j.push(H)}}return j}const C=new Uint8Array(t.length),T=[],N=t.map((p,d)=>d).sort((p,d)=>t[p].x+t[p].y-(t[d].x+t[d].y));for(const p of N){if(C[p])continue;let d=[p];for(C[p]=1;d.length;){T.push(d.map(B=>t[B]));const w=[];for(const B of d)for(const j of v(B))C[j]||(C[j]=1,w.push(j));d=w}}return T}function ve(){if($t(),D||!$){Nt(),A.on=!1;return}A.rows=Me(gt),A.idx=0,A.acc=0,A.rate=m,A.on=A.rows.length>0}function Ce(t){const a=O.getContext("2d");if(a)for(t>A.rows.length&&(t=A.rows.length);A.idx<t;){const l=A.rows[A.idx++];for(const f of l)Zt(a,f)}}function be(t,a){const l=V.getContext("2d");if(!l||(l.clearRect(0,0,s,h),!F||!U))return;const f=s*.32,b=l.createRadialGradient(t,a,0,t,a,f);b.addColorStop(0,"rgba(255,250,238,0.18)"),b.addColorStop(.5,"rgba(255,250,238,0.055)"),b.addColorStop(1,"rgba(255,250,238,0)"),l.fillStyle=b,l.fillRect(0,0,s,h),l.globalCompositeOperation="destination-in",l.drawImage(U,0,0),l.globalCompositeOperation="source-over"}function Te(){R||!E||(R=document.createElement("span"),R.className=bt.caret,R.setAttribute("aria-hidden","true"),Object.assign(R.style,{position:"absolute",pointerEvents:"none",borderRadius:"1px",opacity:"0",background:`rgb(${z(P[0])},${z(P[1])},${z(P[2])})`}),L.appendChild(R),nt.push(R))}function It(){if(!E||!R)return;const t=O.getContext("2d");if(!t)return;t.font=`${i} ${J}px ${o}`;const a=t.measureText(e).width,l=(O.clientWidth||s)/s,f=J*.7;R.style.left=(Et+a+J*.05)*l+"px",R.style.top=.5*(O.clientHeight||h)-f*l/2+"px",R.style.height=f*l+"px",R.style.width=Math.max(2,Math.round(J*.02*l))+"px",R.style.background=`rgb(${z(P[0])},${z(P[1])},${z(P[2])})`}function tt(){k||rt||(rt=!0,at=0,Rt=requestAnimationFrame(Wt))}function Wt(t){if(k){rt=!1;return}at||(at=t);const a=Math.min(.25,(t-at)/1e3);at=t,A.on&&(A.acc+=A.rate*a,Ce(A.acc),A.idx>=A.rows.length&&(A.on=!1)),Y&&U&&(be(G.set?G.x:s*.5,G.set?G.y:h*.45),Y=!1);const l=E&&ht;if(R&&(R.style.opacity=l&&Math.floor(t/530)%2===0?"1":"0"),!A.on&&!Y&&!l){rt=!1;return}Rt=requestAnimationFrame(Wt)}function wt(t){const a=L.getBoundingClientRect();G.x=(t.clientX-a.left)/(a.width||1)*s,G.y=(t.clientY-a.top)/(a.height||1)*h,G.set=!0,Y=!0,tt()}function Mt(){G.set=!1,Y=!0,tt()}function Se(){g&&ee(g.value,!0)}function Ae(t){t.key==="Enter"&&(t.preventDefault(),Bt.replay())}function Ee(){ht=!0,tt()}function Fe(){ht=!1,R&&(R.style.opacity="0")}function te(t){t===E&&g||(E=t,t?(g||(g=document.createElement("input"),g.type="text",g.value=e,g.maxLength=64,g.setAttribute("aria-label","Embroidered text — type to change it"),g.setAttribute("autocomplete","off"),g.setAttribute("autocapitalize","off"),g.spellcheck=!1,Object.assign(g.style,{position:"absolute",inset:"0",width:"100%",height:"100%",margin:"0",padding:"0",border:"0",outline:"none",background:"transparent",color:"transparent",caretColor:"transparent",font:"inherit",textAlign:"center",cursor:"text"}),g.addEventListener("input",Se),g.addEventListener("keydown",Ae),g.addEventListener("focus",Ee),g.addEventListener("blur",Fe),L.appendChild(g),nt.push(g)),Te(),It()):(g&&(g.remove(),g=null),ht=!1,R&&(R.style.opacity="0")))}function Le(t){if(t!==F)if(F=t,t)L.addEventListener("pointermove",wt,{passive:!0}),L.addEventListener("pointerleave",Mt,{passive:!0}),G.set=!1,Y=!0,tt();else{L.removeEventListener("pointermove",wt),L.removeEventListener("pointerleave",Mt);const a=V.getContext("2d");a&&a.clearRect(0,0,s,h)}}function et(t){ye(),xe(),ge(),pe(),we(),t?ve():($t(),Nt(),A.on=!1),g&&g.value!==e&&(g.value=e),It(),Y=!0,tt()}function ee(t,a){t=t??"",!(t===e&&X)&&(e=t,X&&(et(!1),a&&y&&y(e)))}const vt=new Set;function ne(t,a,l){const f=`${a} 200px ${t}`;let b=!1;try{b=!!document.fonts&&document.fonts.check(f)}catch{b=!0}if(!document.fonts||b){l();return}let v=!1,C;const T=()=>{v||(v=!0,clearTimeout(C),vt.delete(C),k||l())};document.fonts.load(f,e).then(()=>document.fonts.ready).then(T,T),C=setTimeout(T,1500),vt.add(C)}function Re(){k||(et(!0),X=!0)}E&&(E=!1,te(!0)),F&&(L.addEventListener("pointermove",wt,{passive:!0}),L.addEventListener("pointerleave",Mt,{passive:!0})),ne(I,i,Re);let Pt,oe=-1;function ie(){clearTimeout(Pt),Pt=setTimeout(()=>{if(k||!X)return;const t=Math.round(L.getBoundingClientRect().width);t!==oe&&(oe=t,et(!1))},200)}window.addEventListener("resize",ie);const Bt={get text(){return e},setText(t){if(!k){if(!X){e=t??"",g&&(g.value=e);return}ee(t,!1)}},replay(){k||!X||et(!0)},resize(){k||!X||et(!1)},update(t){if(k)return;t.text!==void 0&&Bt.setText(t.text);let a=!1,l=!1;if(t.font!==void 0&&t.font!==o&&(o=t.font,I=Ut(o),a=!0),t.weight!==void 0){const f=dt(t.weight,1,1e3);f!==i&&(i=f,a=!0)}if(t.fill!==void 0){const f=dt(t.fill,.05,1);f!==c&&(c=f,a=!0)}t.pitch!==void 0&&t.pitch!==u&&(u=t.pitch,a=!0),t.threadColor!==void 0&&(Ht(t.threadColor),l=!0),t.sewRate!==void 0&&(m=Math.max(1,t.sewRate)),t.animate!==void 0&&($=t.animate),t.onTextChange!==void 0&&(y=t.onTextChange),t.sheen!==void 0&&Le(t.sheen),t.editable!==void 0&&te(t.editable),X&&(a?ne(I,i,()=>{k||et(!1)}):l&&(Qt(),$t(),Nt(),It(),tt()))},focus(){!k&&E&&(g==null||g.focus())},destroy(){if(!k){k=!0,rt=!1,cancelAnimationFrame(Rt),clearTimeout(Pt);for(const t of vt)clearTimeout(t);vt.clear(),window.removeEventListener("resize",ie),L.removeEventListener("pointermove",wt),L.removeEventListener("pointerleave",Mt);for(const t of nt)t.remove();Z=[],gt=[],A.rows=[],Ft=new Uint8Array(0),Lt=new Float32Array(0),mt=new Float32Array(0),yt=new Float32Array(0),U=W=null,xt=null,R=null,g=null}}};return Bt}const de="data-threadtext",Tt=new WeakMap;function ue(r,n){const e=r.dataset,o={text:e.ttText??n};if(e.ttFont&&(o.font=e.ttFont),e.ttWeight!==void 0){const i=parseFloat(e.ttWeight);isNaN(i)||(o.weight=i)}if(e.ttThreadColor&&(o.threadColor=e.ttThreadColor),e.ttPitch!==void 0){const i=parseFloat(e.ttPitch);isNaN(i)||(o.pitch=i)}if(e.ttFill!==void 0){const i=parseFloat(e.ttFill);isNaN(i)||(o.fill=i)}if(e.ttSewRate!==void 0){const i=parseFloat(e.ttSewRate);isNaN(i)||(o.sewRate=i)}return e.ttSheen==="false"&&(o.sheen=!1),e.ttAnimate==="false"&&(o.animate=!1),e.ttEditable==="true"&&(o.editable=!0),o}function he(r){Xt(r);const n=r.innerHTML,e=(r.dataset.ttText??r.textContent??"").trim();if(!e)return;const o=ue(r,e);r.innerHTML="",o.editable||(r.setAttribute("role","img"),r.setAttribute("aria-label",e));const i=fe(r,o);Tt.set(r,{instance:i,originalHTML:n})}function Xt(r){const n=Tt.get(r);n&&(n.instance.destroy(),r.removeAttribute("role"),r.removeAttribute("aria-label"),r.innerHTML=n.originalHTML,Tt.delete(r))}function ut(r=document){r.querySelectorAll(`[${de}]`).forEach(he)}function me(){const r=()=>{var n;typeof document<"u"&&((n=document.fonts)!=null&&n.ready)?document.fonts.ready.then(()=>ut()).catch(()=>ut()):ut()};typeof document<"u"&&document.readyState==="loading"?document.addEventListener("DOMContentLoaded",r,{once:!0}):r()}return me(),ct.destroy=Xt,ct.init=ut,Object.defineProperty(ct,Symbol.toStringTag,{value:"Module"}),ct})({});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liiift-studio/threadtext",
3
- "version": "0.0.1",
3
+ "version": "0.1.1",
4
4
  "description": "Render any text as photorealistic procedural satin-stitch embroidery, in real time in the browser, from the font's glyph geometry",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -42,6 +42,7 @@
42
42
  "@types/react": "^19.0.0",
43
43
  "@vitejs/plugin-react": "^4.0.0",
44
44
  "happy-dom": "^20.10.6",
45
+ "next": "16.2.2",
45
46
  "react": "^19.0.0",
46
47
  "react-dom": "^19.0.0",
47
48
  "typescript": "^5.0.0",
@@ -73,7 +74,7 @@
73
74
  "homepage": "https://threadtext.com",
74
75
  "repository": {
75
76
  "type": "git",
76
- "url": "https://github.com/Liiift-Studio/ThreadText.git"
77
+ "url": "git+https://github.com/Liiift-Studio/ThreadText.git"
77
78
  },
78
79
  "bugs": {
79
80
  "url": "https://github.com/Liiift-Studio/ThreadText/issues"