@liiift-studio/threadtext 0.1.0 → 0.2.0

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