@overpunch/threadtext 0.4.6 → 0.5.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.
package/dist/index.cjs CHANGED
@@ -1,7 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ie=require("react"),Zt=require("react/jsx-runtime"),Ye={bg:"tt-bg",fx:"tt-fx",caret:"tt-caret"};function ae(M,n){let r=Math.imul(M|0,374761393)+Math.imul(n|0,668265263)|0;return r=Math.imul(r^r>>>13,1274126177),((r^r>>>16)>>>0)/4294967295}function ct(M,n){const r=Math.floor(M),u=Math.floor(n),f=M-r,C=n-u,h=f*f*(3-2*f),y=C*C*(3-2*C),S=ae(r,u),I=ae(r+1,u),b=ae(r,u+1),p=ae(r+1,u+1);return S+(I-S)*h+(b-S)*y+(S-I-b+p)*h*y}function lt(M,n,r,u,f){let h=0;u[0]=0,f[0]=-1e20,f[1]=1e20;for(let y=1;y<n;y++){let S=(M[y]+y*y-(M[u[h]]+u[h]*u[h]))/(2*y-2*u[h]);for(;S<=f[h];)h--,S=(M[y]+y*y-(M[u[h]]+u[h]*u[h]))/(2*y-2*u[h]);h++,u[h]=y,f[h]=S,f[h+1]=1e20}h=0;for(let y=0;y<n;y++){for(;f[h+1]<y;)h++;r[y]=(y-u[h])*(y-u[h])+M[u[h]]}}function Lt(M,n,r){const f=new Float64Array(n*r);for(let p=0;p<n*r;p++)f[p]=M[p]?1e20:0;const C=Math.max(n,r),h=new Float64Array(C),y=new Float64Array(C),S=new Int32Array(C),I=new Float64Array(C+1);for(let p=0;p<n;p++){for(let w=0;w<r;w++)h[w]=f[w*n+p];lt(h,r,y,S,I);for(let w=0;w<r;w++)f[w*n+p]=y[w]}for(let p=0;p<r;p++){for(let w=0;w<n;w++)h[w]=f[p*n+w];lt(h,n,y,S,I);for(let w=0;w<n;w++)f[p*n+w]=y[w]}const b=new Float32Array(n*r);for(let p=0;p<n*r;p++)b[p]=Math.sqrt(f[p]);return b}function ft(M,n,r,u,f){let C=Float32Array.from(M);const h=new Float32Array(n*r),y=1/(2*u+1),S=(I,b)=>I<0?0:I>b?b:I;for(let I=0;I<f;I++){for(let b=0;b<r;b++){const p=b*n;let w=0;for(let O=-u;O<=u;O++)w+=C[p+S(O,n-1)];for(let O=0;O<n;O++)h[p+O]=w*y,w+=C[p+S(O+u+1,n-1)]-C[p+S(O-u,n-1)]}for(let b=0;b<n;b++){let p=0;for(let w=-u;w<=u;w++)p+=h[S(w,r-1)*n+b];for(let w=0;w<r;w++)C[w*n+b]=p*y,p+=h[S(w+u+1,r-1)*n+b]-h[S(w-u,r-1)*n+b]}}return C}function at(M,n){if(!M)return n;const r=M.trim();if(r[0]==="#"){let f=r.slice(1);if(f.length===3&&(f=f[0]+f[0]+f[1]+f[1]+f[2]+f[2]),f.length>=6){const C=parseInt(f.slice(0,2),16),h=parseInt(f.slice(2,4),16),y=parseInt(f.slice(4,6),16);if(!Number.isNaN(C)&&!Number.isNaN(h)&&!Number.isNaN(y))return[C,h,y]}return n}const u=r.match(/rgba?\(([^)]+)\)/i);if(u){const f=u[1].split(",").map(C=>parseFloat(C));if(f.length>=3&&f.slice(0,3).every(C=>!Number.isNaN(C)))return[Math.round(f[0]),Math.round(f[1]),Math.round(f[2])]}return n}function re(M){return M<0?0:M>255?255:Math.round(M)}function Ve(M,n,r){return M<n?n:M>r?r:M}function kt(M){return(M.split(",")[0]||"serif").trim().replace(/^["']|["']$/g,"")}function st(M,n,r){const u=new Uint8Array(n*r);for(let v=0;v<r;v++)for(let F=0;F<n;F++){const E=v*n+F,B=M[E*4+3]/255,U=ct(F*.5,v*.5)*.22+ct(F*1.8,v*1.8)*.1;u[E]=B>.5+(U-.16)?1:0}const f=Lt(u,n,r),C=new Float32Array(n*r);for(let v=1;v<r-1;v++)for(let F=1;F<n-1;F++){const E=v*n+F;C[E]=(f[E]*4+f[E-1]+f[E+1]+f[E-n]+f[E+n])/8}const h=new Float32Array(n*r),y=new Float32Array(n*r),S=new Float32Array(n*r),I=new Float32Array(n*r);for(let v=1;v<r-1;v++)for(let F=1;F<n-1;F++){const E=v*n+F;if(!u[E])continue;const B=(C[E+1]-C[E-1])*.5,U=(C[E+n]-C[E-n])*.5;S[E]=B,I[E]=U,h[E]=B*B-U*U,y[E]=2*B*U}const b=Math.max(7,Math.round(r*.05)),p=ft(h,n,r,b,2),w=ft(y,n,r,b,2),O=new Float32Array(n*r),Q=new Float32Array(n*r);for(let v=0;v<n*r;v++){if(!u[v])continue;const F=.5*Math.atan2(w[v],p[v]);O[v]=Math.cos(F),Q[v]=Math.sin(F)}const se=Math.max(9,r*.04),G=new Float32Array(n*r),ce=-.45,le=-.62,ee=.64;for(let v=1;v<r-1;v++)for(let F=1;F<n-1;F++){const E=v*n+F;if(!u[E])continue;let B=S[E],U=I[E];const K=Math.hypot(B,U)||1;B/=K,U/=K;const fe=C[E],D=(1-Math.min(fe/se,1))*1.25;let ue=-B*D,te=-U*D;const Z=1.5,V=Math.hypot(ue,te,Z);ue/=V,te/=V;let xe=ue*ce+te*le+Z/V*ee;xe<0&&(xe=0);const $e=Math.min(1,.45+.55*Math.min(fe/(se*.7),1));G[E]=Math.min(1.12,(.5+.75*xe)*$e)}return{mask:u,ex:O,ey:Q,shade:G}}function Ft(M,n){if(typeof window>"u"||typeof document>"u"||!M)return{setText(){},replay(){},resize(){},update(){},focus(){},destroy(){},get text(){return n.text??""}};let r=n.text??"",u=n.font??"Georgia, serif",f=Ve(n.weight??680,1,1e3),C=Ve(n.fill??.9,.05,1),h=n.align==="left"||n.align==="right"?n.align:"center",y=Math.max(1,n.sewRate??110),S=n.sewStyle==="hand"?"hand":"machine";const I=["satin","cross","chain","running"];let b=I.includes(n.stitchMode??"")?n.stitchMode:"satin",p=n.sheen??!0,w=n.animate??!0,O=n.editable??!1,Q=n.pitch;const se=["solid","twotone","gradient"];let G=se.includes(n.colorMode??"")?n.colorMode:"solid",ce=n.threadColor??"#fffbf3",le=n.threadColor2??ce,ee=n.backstitch??!1,v=n.outlineColor,F=n.axes,E=n.onTextChange,B=kt(u);function U(){if(!F)return"";const e=[];for(const t in F){const o=F[t];typeof o=="number"&&isFinite(o)&&e.push(`"${t}" ${o}`)}return e.join(", ")}function K(e){"fontVariationSettings"in e&&(e.fontVariationSettings=U()||"normal")}const fe=n.reducedMotion??!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),D=e=>({peak:e,mid:[e[0]*.585,e[1]*.585,e[2]*.585],end:[e[0]*.47,e[1]*.47,e[2]*.47]}),ue=(e,t,o)=>[e[0]+(t[0]-e[0])*o,e[1]+(t[1]-e[1])*o,e[2]+(t[2]-e[2])*o],te=6;let Z=[255,251,243],V=[],xe=D([0,0,0]);function $e(){const e=at(ce,[255,251,243]),t=at(le,e);if(G==="twotone")V=[D(e),D(t)];else if(G==="gradient"){V=[];for(let o=0;o<te;o++)V.push(D(ue(e,t,o/(te-1))))}else V=[D(e)];Z=V[0].peak,xe=D(v?at(v,[0,0,0]):[e[0]*.32,e[1]*.32,e[2]*.32])}$e();const Ae=[];let q,N;M instanceof HTMLCanvasElement?(q=M,N=M.parentElement??M):(N=M,q=document.createElement("canvas"),Ae.push(q),N.appendChild(q)),q.classList.add(Ye.bg);const pe=document.createElement("canvas");Ae.push(pe),pe.classList.add(Ye.fx),N.appendChild(pe),getComputedStyle(N).position==="static"&&(N.style.position="relative"),q.style.display="block",q.style.width="100%",Object.assign(pe.style,{position:"absolute",inset:"0",width:"100%",pointerEvents:"none",mixBlendMode:"screen"});let k=null,j=null,Pe=!1,A=0,R=0,Me=0,Je=0,H=4,ke=[],be=0,Te=0,Qe=[],ut=0,dt=-1,ht="",mt=-1,gt=-1,Y=new Uint8Array(0),Ne=new Float32Array(0),Ze=new Float32Array(0),He=new Float32Array(0),de=null,Se=null,je=null,Le=[],he=[],Fe=[],we=3;const $={rows:[],idx:0,acc:0,rate:0,on:!1},ne={x:0,y:0,set:!1};let Ce=!0,We=0,Re=!1,Ie=0,z=!1,me=!1,W=null,Oe="",Be=!1,et=0,tt=!1,J;function Ot(){const e=N.getBoundingClientRect(),t=Math.max(1,Math.round(e.width||Math.min(window.innerWidth*.95,1240))),o=r||"Ag",i=q.getContext("2d");i&&(i.textBaseline="middle");let s=100;i&&(i.font=`${f} 100px ${u}`,K(i),s=i.measureText(o).width||100);const a=Math.max(8,100*(t*C)/s);let c=a*.62,T=a*.62,l=t*C;if(i){i.font=`${f} ${a}px ${u}`,K(i);const x=i.measureText(o);l=x.width||l,x.actualBoundingBoxAscent>0&&(c=x.actualBoundingBoxAscent),x.actualBoundingBoxDescent>0&&(T=x.actualBoundingBoxDescent)}const m=Math.max(1,Math.round(2*Math.max(c,T)*1.1));let g=Math.min(window.devicePixelRatio||1,1.7);for(;t*g*m*g>9e5&&g>.4;)g-=.1;A=Math.max(1,Math.round(t*g)),R=Math.max(1,Math.round(m*g)),Me=Math.max(4,Math.round(a*g));const d=l*g,L=Math.max(2,Math.round(Me*.08));Je=Math.round(h==="left"?L:h==="right"?A-d-L:A/2-d/2);for(const x of[q,pe])x.width=A,x.height=R,x.style.height=m+"px";N.style.height=m+"px",H=Q??Math.max(3,R*.0095)}function $t(){Se&&mt===A&&gt===R||(Se=document.createElement("canvas"),Se.width=A,Se.height=R,je=Se.getContext("2d",{willReadFrequently:!0}),mt=A,gt=R)}function yt(){return V.map(e=>e.peak.join(",")).join(";")+"|"+b+"|"+G+(ee?"|bs"+xe.peak.join(","):"")}function xt(e,t){const o=Math.max(7,H*2.5),i=Math.max(3.2,H*1.3),s=[];for(let a=0;a<20;a++){const c=.34+a/19*.82,T=document.createElement("canvas");T.width=be,T.height=Te;const l=T.getContext("2d");if(!l){s.push(T);continue}const m=be/2,g=Te/2,d=(x,P)=>`rgba(${re(x[0]*c)},${re(x[1]*c)},${re(x[2]*c)},${P})`,L=(x,P,ge,oe)=>{l.save(),l.translate(m,g),l.rotate(ge);const X=l.createLinearGradient(0,-P/2,0,P/2);X.addColorStop(0,d(e.end,0)),X.addColorStop(.16,d(e.mid,1)),X.addColorStop(.5,d(e.peak,1)),X.addColorStop(.84,d(e.mid,1)),X.addColorStop(1,d(e.end,0)),l.fillStyle=X;const _=P/2;if(l.beginPath(),l.moveTo(-x/2+_,-_),l.lineTo(x/2-_,-_),l.arc(x/2-_,0,_,-Math.PI/2,Math.PI/2),l.lineTo(-x/2+_,_),l.arc(-x/2+_,0,_,Math.PI/2,-Math.PI/2),l.closePath(),l.fill(),oe){l.globalCompositeOperation="destination-in";const ye=l.createLinearGradient(-x/2,0,x/2,0);ye.addColorStop(0,"rgba(0,0,0,0)"),ye.addColorStop(.22,"rgba(0,0,0,1)"),ye.addColorStop(.78,"rgba(0,0,0,1)"),ye.addColorStop(1,"rgba(0,0,0,0)"),l.fillStyle=ye,l.fillRect(-x/2-1,-P/2-1,x+2,P+2),l.globalCompositeOperation="source-over"}l.restore()};if(t==="cross")L(o*.92,i*.82,Math.PI/4,!1),L(o*.92,i*.82,-Math.PI/4,!1);else if(t==="chain"){l.save(),l.translate(m,g);const x=l.createLinearGradient(0,-i,0,i);x.addColorStop(0,d(e.mid,1)),x.addColorStop(.5,d(e.peak,1)),x.addColorStop(1,d(e.mid,1)),l.strokeStyle=x,l.lineWidth=Math.max(1.6,i*.7),l.lineCap="round",l.beginPath(),l.ellipse(0,0,o*.34,i*1.05,0,0,Math.PI*2),l.stroke(),l.restore()}else t==="running"?L(o*.5,i,0,!1):L(o,i,0,!0);s.push(T)}return s}function nt(){const e=Math.max(7,H*2.5),t=Math.max(3.2,H*1.3);b==="cross"||b==="chain"?be=Te=Math.ceil(e)+2:(be=Math.ceil(e)+2,Te=Math.ceil(t)+2),ut=b==="chain"||b==="running"?Math.PI/2:0,ke=[];for(const o of V)for(const i of xt(o,b))ke.push(i);Qe=ee?xt(xe,"running"):[],dt=H,ht=yt()}function Pt(){ke.length&&dt===H&&ht===yt()||nt()}function pt(){if(!je)return null;const e=je;return e.clearRect(0,0,A,R),e.fillStyle="#fff",e.textAlign="left",e.textBaseline="middle",e.font=`${f} ${Me}px ${u}`,K(e),e.fillText(r,Je,R*.5),e.getImageData(0,0,A,R).data}function ot(e){Y=e.mask,Ze=e.ex,He=e.ey,Ne=e.shade,de=document.createElement("canvas"),de.width=A,de.height=R;const t=de.getContext("2d");if(t){const o=t.createImageData(A,R);for(let i=0;i<A*R;i++)Y[i]&&(o.data[i*4]=255,o.data[i*4+1]=255,o.data[i*4+2]=255,o.data[i*4+3]=255);t.putImageData(o,0,0)}}function Mt(){const e=Math.max(1.6,H*.6);we=e;const t=[],o=[];let i=1/0,s=-1/0;for(let a=0;a<R;a+=e)for(let c=0;c<A;c+=e){const T=(ae(Math.floor(c),Math.floor(a))-.5)*e*.9,l=(ae(Math.floor(a),Math.floor(c))-.5)*e*.9,m=Math.round(c+T),g=Math.round(a+l);if(m<1||g<1||m>=A-1||g>=R-1)continue;const d=g*A+m;if(!Y[d])continue;const L=Math.atan2(He[d],Ze[d]),x=.86+ae(m*7,g*13)*.18;let P=Ne[d]*x;P=P<0?0:P>1.12?1.12:P,t.push({x:m,y:g,ang:L,idx:Math.min(19,Math.max(0,Math.round(P/1.12*19)))}),m<i&&(i=m),m>s&&(s=m)}if(G==="twotone")if(b==="satin"){const a=Math.max(4,H*1.6);for(const c of t){const T=-Math.sin(c.ang)*c.x+Math.cos(c.ang)*c.y;c.pal=Math.floor(T/a)&1}}else for(const a of t)a.pal=Math.round(a.x/e)+Math.round(a.y/e)&1;else if(G==="gradient"){const a=Math.max(1,s-i);for(const c of t){const T=(c.x-i)/a*(te-1),l=Math.min(te-1,Math.max(0,Math.floor(T)));c.pal=l,l<te-1&&ae(c.x*3+1,c.y*5+2)<T-l&&o.push({x:c.x,y:c.y,ang:c.ang,idx:c.idx,pal:l+1})}}Le=t,Fe=o,Nt()}function Nt(){if(he=[],!ee||!Y.length)return;const e=Math.max(3,H*1.5),t=Math.max(1,Math.ceil(A/e)),o=new Set,i=(s,a)=>Y[a*A+s]?1:0;for(let s=1;s<R-1;s++)for(let a=1;a<A-1;a++){const c=s*A+a;if(!Y[c]||Y[c-1]&&Y[c+1]&&Y[c-A]&&Y[c+A])continue;const T=Math.floor(s/e)*t+Math.floor(a/e);if(o.has(T))continue;o.add(T);const l=i(a+1,s-1)+2*i(a+1,s)+i(a+1,s+1)-(i(a-1,s-1)+2*i(a-1,s)+i(a-1,s+1)),m=i(a-1,s+1)+2*i(a,s+1)+i(a+1,s+1)-(i(a-1,s-1)+2*i(a,s-1)+i(a+1,s-1)),g=Math.atan2(l,-m);let d=Ne[c];d=d<0?0:d>1.12?1.12:d,he.push({x:a,y:s,ang:g,idx:Math.min(19,Math.max(8,Math.round(d/1.12*19))),outline:1})}}function De(e,t){e.save(),e.translate(t.x,t.y),t.outline?(e.rotate(t.ang),e.drawImage(Qe[t.idx],-be/2,-Te/2)):(e.rotate(t.ang+ut),e.drawImage(ke[(t.pal||0)*20+t.idx],-be/2,-Te/2)),e.restore()}function _e(){const e=q.getContext("2d");if(e){for(const t of Le)De(e,t);for(const t of Fe)De(e,t);for(const t of he)De(e,t)}}function Ue(){const e=q.getContext("2d");e&&e.clearRect(0,0,A,R)}function wt(e){if(!e.length)return[];const t=Math.max(4,we*1.5),o=new Map,i=(m,g)=>m+","+g;e.forEach((m,g)=>{const d=i(Math.floor(m.x/t),Math.floor(m.y/t));let L=o.get(d);L||o.set(d,L=[]),L.push(g)});const s=we*1.8*(we*1.8);function a(m){const g=e[m],d=Math.floor(g.x/t),L=Math.floor(g.y/t),x=[];for(let P=-1;P<=1;P++)for(let ge=-1;ge<=1;ge++){const oe=o.get(i(d+P,L+ge));if(oe)for(const X of oe){if(X===m)continue;const _=e[X].x-g.x,ye=e[X].y-g.y;_*_+ye*ye<=s&&x.push(X)}}return x}const c=new Uint8Array(e.length),T=[],l=e.map((m,g)=>g).sort((m,g)=>e[m].x+e[m].y-(e[g].x+e[g].y));for(const m of l){if(c[m])continue;let g=[m];for(c[m]=1;g.length;){T.push(g.map(L=>e[L]));const d=[];for(const L of g)for(const x of a(L))c[x]||(c[x]=1,d.push(x));g=d}}return T}function jt(e){const t=Math.max(4,we*1.5),o=new Map,i=(l,m)=>l+","+m;e.forEach((l,m)=>{const g=i(Math.floor(l.x/t),Math.floor(l.y/t));let d=o.get(g);d||o.set(g,d=[]),d.push(m)});const s=we*1.8*(we*1.8),a=l=>{const m=e[l],g=Math.floor(m.x/t),d=Math.floor(m.y/t),L=[];for(let x=-1;x<=1;x++)for(let P=-1;P<=1;P++){const ge=o.get(i(g+x,d+P));if(ge)for(const oe of ge){if(oe===l)continue;const X=e[oe].x-m.x,_=e[oe].y-m.y;X*X+_*_<=s&&L.push(oe)}}return L},c=new Uint8Array(e.length),T=[];for(let l=0;l<e.length;l++){if(c[l])continue;const m=[];let g=[l];for(c[l]=1;g.length;){const d=[];for(const L of g){m.push(e[L]);for(const x of a(L))c[x]||(c[x]=1,d.push(x))}g=d}T.push(m)}return T}function Bt(e){if(!e.length)return[];const t=a=>{let c=1/0;for(const T of a)T.x<c&&(c=T.x);return c},o=a=>{let c=0;for(const T of a)c+=T.y;return c/a.length},i=jt(e).sort((a,c)=>t(a)-t(c)),s=[];for(const a of i){const c=wt(a);let T=1;for(const d of c)d.length>T&&(T=d.length);const l=Math.max(2,T*.45),m=c.filter(d=>d.length>=l).sort((d,L)=>o(d)-o(L)),g=c.filter(d=>d.length<l).sort((d,L)=>o(d)-o(L));for(const d of m)s.push(d);for(const d of g)s.push(d)}return s}function Dt(){if(Ue(),fe||!w){_e(),$.on=!1;return}const e=S==="hand"?Bt:wt;let t;if(G==="gradient"&&V.length>1){t=[];const o=new Map;for(const i of Le){const s=i.pal||0,a=o.get(s);a?a.push(i):o.set(s,[i])}for(const i of[...o.keys()].sort((s,a)=>s-a))for(const s of e(o.get(i)))t.push(s)}else t=e(Le);if(Fe.length)for(const o of e(Fe))t.push(o);if(he.length){const i=Math.ceil(he.length/24);for(let s=0;s<he.length;s+=i)t.push(he.slice(s,s+i))}$.rows=t,$.idx=0,$.acc=0,$.rate=y,$.on=$.rows.length>0}function _t(e){const t=q.getContext("2d");if(t)for(e>$.rows.length&&(e=$.rows.length);$.idx<e;){const o=$.rows[$.idx++];for(const i of o)De(t,i)}}function Ut(e,t){const o=pe.getContext("2d");if(!o||(o.clearRect(0,0,A,R),!p||!de))return;const i=A*.32,s=o.createRadialGradient(e,t,0,e,t,i);s.addColorStop(0,"rgba(255,250,238,0.18)"),s.addColorStop(.5,"rgba(255,250,238,0.055)"),s.addColorStop(1,"rgba(255,250,238,0)"),o.fillStyle=s,o.fillRect(0,0,A,R),o.globalCompositeOperation="destination-in",o.drawImage(de,0,0),o.globalCompositeOperation="source-over"}function qt(){j||!O||(j=document.createElement("span"),j.className=Ye.caret,j.setAttribute("aria-hidden","true"),Object.assign(j.style,{position:"absolute",pointerEvents:"none",borderRadius:"1px",opacity:"0",background:`rgb(${re(Z[0])},${re(Z[1])},${re(Z[2])})`}),N.appendChild(j),Ae.push(j))}function qe(){if(!O||!j)return;const e=q.getContext("2d");if(!e)return;e.font=`${f} ${Me}px ${u}`,K(e);const t=e.measureText(r).width,o=(q.clientWidth||A)/A,i=Me*.7;j.style.left=(Je+t+Me*.05)*o+"px",j.style.top=.5*(q.clientHeight||R)-i*o/2+"px",j.style.height=i*o+"px",j.style.width=Math.max(2,Math.round(Me*.02*o))+"px",j.style.background=`rgb(${re(Z[0])},${re(Z[1])},${re(Z[2])})`}function ve(){z||Re||(Re=!0,Ie=0,We=requestAnimationFrame(Ct))}function Ct(e){if(z){Re=!1;return}Ie||(Ie=e);const t=Math.min(.25,(e-Ie)/1e3);Ie=e,$.on&&($.acc+=$.rate*t,_t($.acc),$.idx>=$.rows.length&&($.on=!1)),Ce&&de&&(Ut(ne.set?ne.x:A*.5,ne.set?ne.y:R*.45),Ce=!1);const o=O&&Pe;if(j&&(j.style.opacity=o&&Math.floor(e/530)%2===0?"1":"0"),!$.on&&!Ce&&!o){Re=!1;return}We=requestAnimationFrame(Ct)}function ze(e){const t=N.getBoundingClientRect();ne.x=(e.clientX-t.left)/(t.width||1)*A,ne.y=(e.clientY-t.top)/(t.height||1)*R,ne.set=!0,Ce=!0,ve()}function Ge(){ne.set=!1,Ce=!0,ve()}function zt(){k&&Tt(k.value,!0)}function Gt(e){e.key==="Enter"&&(e.preventDefault(),it.replay())}function Xt(){Pe=!0,ve()}function Kt(){Pe=!1,j&&(j.style.opacity="0")}function vt(e){e===O&&k||(O=e,e?(k||(k=document.createElement("input"),k.type="text",k.value=r,k.maxLength=64,k.setAttribute("aria-label","Embroidered text — type to change it"),k.setAttribute("autocomplete","off"),k.setAttribute("autocapitalize","off"),k.spellcheck=!1,Object.assign(k.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"}),k.addEventListener("input",zt),k.addEventListener("keydown",Gt),k.addEventListener("focus",Xt),k.addEventListener("blur",Kt),N.appendChild(k),Ae.push(k)),qt(),qe()):(k&&(k.remove(),k=null),Pe=!1,j&&(j.style.opacity="0")))}function Vt(e){if(e!==p)if(p=e,e)N.addEventListener("pointermove",ze,{passive:!0}),N.addEventListener("pointerleave",Ge,{passive:!0}),ne.set=!1,Ce=!0,ve();else{N.removeEventListener("pointermove",ze),N.removeEventListener("pointerleave",Ge);const t=pe.getContext("2d");t&&t.clearRect(0,0,A,R)}}function Xe(e){Mt(),e?Dt():(Ue(),_e(),$.on=!1),k&&k.value!==r&&(k.value=r),qe(),Ce=!0,ve()}function Ee(e){Ot(),$t(),Pt();const t=pt();if(!t){Xe(e);return}if(W&&Be){const o=++et;tt=e,J&&clearTimeout(J),J=setTimeout(()=>bt(o),800);try{W.postMessage({id:o,W:A,H:R,alpha:t},[t.buffer])}catch{bt(o)}return}ot(st(t,A,R)),Xe(e)}function bt(e){if(e!==et||z)return;J&&(clearTimeout(J),J=void 0),Be=!1;const t=pt();t&&(ot(st(t,A,R)),Xe(tt))}function Tt(e,t){e=e??"",!(e===r&&me)&&(r=e,me&&(Ee(!1),t&&E&&E(r)))}const Ke=new Set;function St(e,t,o){const i=`${t} 200px ${e}`;let s=!1;try{s=!!document.fonts&&document.fonts.check(i)}catch{s=!0}if(!document.fonts||s){o();return}let a=!1,c;const T=()=>{a||(a=!0,clearTimeout(c),Ke.delete(c),z||o())};document.fonts.load(i,r).then(()=>document.fonts.ready).then(T,T),c=setTimeout(T,1500),Ke.add(c)}function Yt(e){const t=e.data;if(t&&t.type==="pong"){Be=!0;return}!t||z||t.id!==et||(J&&(clearTimeout(J),J=void 0),ot({mask:t.mask,ex:t.ex,ey:t.ey,shade:t.shade}),Xe(tt))}function Jt(){if(!(typeof Worker>"u"||typeof Blob>"u"||typeof URL>"u"||!URL.createObjectURL))try{const e=`${ae}
2
- ${ct}
3
- ${lt}
4
- ${Lt}
5
- ${ft}
6
- var __cg=${st};
7
- self.onmessage=function(ev){var d=ev.data;if(d&&d.type==='ping'){try{__cg(new Uint8ClampedArray(4),1,1);self.postMessage({type:'pong'})}catch(e){}return}var g=__cg(d.alpha,d.W,d.H);self.postMessage({id:d.id,mask:g.mask,ex:g.ex,ey:g.ey,shade:g.shade},[g.mask.buffer,g.ex.buffer,g.ey.buffer,g.shade.buffer])};`;Oe=URL.createObjectURL(new Blob([e],{type:"application/javascript"})),W=new Worker(Oe),W.onmessage=Yt,W.onerror=()=>{Be=!1},W.postMessage({type:"ping"})}catch{W=null}}function Qt(){z||(Ee(!0),me=!0)}Jt(),O&&(O=!1,vt(!0)),p&&(N.addEventListener("pointermove",ze,{passive:!0}),N.addEventListener("pointerleave",Ge,{passive:!0})),St(B,f,Qt);let rt,Et=-1;function At(){clearTimeout(rt),rt=setTimeout(()=>{if(z||!me)return;const e=Math.round(N.getBoundingClientRect().width);e!==Et&&(Et=e,Ee(!1))},200)}window.addEventListener("resize",At);const it={get text(){return r},setText(e){if(!z){if(!me){r=e??"",k&&(k.value=r);return}Tt(e,!1)}},replay(){z||!me||Ee(!0)},resize(){z||!me||Ee(!1)},update(e){if(z)return;e.text!==void 0&&it.setText(e.text);let t=!1,o=!1,i=!1,s=!1;if(e.font!==void 0&&e.font!==u&&(u=e.font,B=kt(u),t=!0),e.weight!==void 0){const a=Ve(e.weight,1,1e3);a!==f&&(f=a,t=!0)}if(e.fill!==void 0){const a=Ve(e.fill,.05,1);a!==C&&(C=a,t=!0)}if(e.align!==void 0){const a=e.align==="left"||e.align==="right"?e.align:"center";a!==h&&(h=a,t=!0)}e.pitch!==void 0&&e.pitch!==Q&&(Q=e.pitch,t=!0),e.axes!==void 0&&(F=e.axes,t=!0),e.threadColor!==void 0&&e.threadColor!==ce&&(ce=e.threadColor,s=!0),e.threadColor2!==void 0&&e.threadColor2!==le&&(le=e.threadColor2,s=!0),e.outlineColor!==void 0&&e.outlineColor!==v&&(v=e.outlineColor,s=!0),e.colorMode!==void 0&&e.colorMode!==G&&se.includes(e.colorMode)&&(G=e.colorMode,s=!0,i=!0),e.backstitch!==void 0&&e.backstitch!==ee&&(ee=e.backstitch,i=!0),e.stitchMode!==void 0&&e.stitchMode!==b&&I.includes(e.stitchMode)&&(b=e.stitchMode,o=!0),e.sewRate!==void 0&&(y=Math.max(1,e.sewRate)),e.sewStyle!==void 0&&(S=e.sewStyle==="hand"?"hand":"machine"),e.animate!==void 0&&(w=e.animate),e.onTextChange!==void 0&&(E=e.onTextChange),e.sheen!==void 0&&Vt(e.sheen),e.editable!==void 0&&vt(e.editable),s&&$e(),me&&(t?St(B,f,()=>{z||Ee(!1)}):i?(nt(),Mt(),Ue(),_e(),qe(),ve()):(o||s)&&(nt(),Ue(),_e(),qe(),ve()))},focus(){!z&&O&&(k==null||k.focus())},destroy(){if(!z){z=!0,Re=!1,cancelAnimationFrame(We),clearTimeout(rt),J&&clearTimeout(J);for(const e of Ke)clearTimeout(e);if(Ke.clear(),W&&(W.terminate(),W=null),Oe){try{URL.revokeObjectURL(Oe)}catch{}Oe=""}window.removeEventListener("resize",At),N.removeEventListener("pointermove",ze),N.removeEventListener("pointerleave",Ge);for(const e of Ae)e.remove();ke=[],Qe=[],Le=[],he=[],Fe=[],$.rows=[],Y=new Uint8Array(0),Ne=new Float32Array(0),Ze=new Float32Array(0),He=new Float32Array(0),de=Se=null,je=null,j=null,k=null}}};return it}function Rt(M){const n=ie.useRef(null),r=ie.useRef(null),u=ie.useRef(M);u.current=M;const f=ie.useRef(M.onTextChange);f.current=M.onTextChange;const{text:C,font:h,weight:y,threadColor:S,pitch:I,fill:b,animate:p,sewStyle:w,stitchMode:O,sewRate:Q,sheen:se,editable:G,reducedMotion:ce,axes:le}=M,ee=JSON.stringify(le??null);return ie.useLayoutEffect(()=>{const v=n.current;if(!v)return;const F=Ft(v,{...u.current,onTextChange:fe=>{var D;return(D=f.current)==null?void 0:D.call(f,fe)}});r.current=F;let E=0,B=0,U=!0,K;return typeof ResizeObserver<"u"&&(K=new ResizeObserver(fe=>{const D=Math.round(fe[0].contentRect.width);if(U){U=!1,B=D;return}D!==B&&(B=D,cancelAnimationFrame(E),E=requestAnimationFrame(()=>{var ue;return(ue=r.current)==null?void 0:ue.resize()}))}),K.observe(v)),()=>{K==null||K.disconnect(),cancelAnimationFrame(E),F.destroy(),r.current=null}},[ce]),ie.useEffect(()=>{var v;(v=r.current)==null||v.update({font:h,weight:y,threadColor:S,pitch:I,fill:b,animate:p,sewStyle:w,stitchMode:O,sewRate:Q,sheen:se,editable:G,axes:le})},[h,y,S,I,b,p,w,O,Q,se,G,ee]),ie.useEffect(()=>{var v;(v=r.current)==null||v.setText(C)},[C]),n}const It=ie.forwardRef(function({className:n,style:r,as:u="div","aria-label":f,role:C,"aria-describedby":h,...y},S){const I=Rt(y),b=ie.useCallback(p=>{I.current=p,typeof S=="function"?S(p):S&&(S.current=p)},[I,S]);return Zt.jsx(u,{ref:b,className:n,style:r,role:y.editable?C:C??"img","aria-label":y.editable?f:f??y.text,"aria-describedby":h})});It.displayName="ThreadText";exports.THREAD_TEXT_CLASSES=Ye;exports.ThreadText=It;exports.createThreadText=Ft;exports.useThreadText=Rt;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./core.cjs"),r=require("react"),S=require("react/jsx-runtime");function g(o){const a=r.useRef(null),n=r.useRef(null),u=r.useRef(o);u.current=o;const s=r.useRef(o.onTextChange);s.current=o.onTextChange;const{text:c,reducedMotion:l,onTextChange:d,...T}=o,h=JSON.stringify(T),t=r.useRef(null);return r.useLayoutEffect(()=>{var x;const e=a.current,f=t.current;f&&f.el===e&&f.reducedMotion===l||((x=n.current)==null||x.destroy(),n.current=null,t.current=null,e&&(n.current=y.createThreadText(e,{...u.current,onTextChange:C=>{var i;return(i=s.current)==null?void 0:i.call(s,C)}}),t.current={el:e,reducedMotion:l}))}),r.useEffect(()=>()=>{var e;(e=n.current)==null||e.destroy(),n.current=null,t.current=null},[]),r.useEffect(()=>{var i;const{text:e,reducedMotion:f,onTextChange:x,...C}=u.current;(i=n.current)==null||i.update(C)},[h]),r.useEffect(()=>{var e;(e=n.current)==null||e.setText(c)},[c]),a}const R=["text","font","weight","fill","align","pitch","threadColor","threadColor2","colorMode","backstitch","outlineColor","sewRate","sewStyle","stitchMode","sheen","animate","editable","reducedMotion","axes","onTextChange"],E=r.forwardRef(function({className:a,style:n,as:u="div",...s},c){const l={},d={};for(const[t,e]of Object.entries(s))R.includes(t)?l[t]=e:d[t]=e;const T=g(l),h=r.useCallback(t=>{T.current=t,typeof c=="function"?c(t):c&&(c.current=t)},[T,c]);return S.jsx(u,{ref:h,className:a,style:n,...d},typeof u=="string"?u:"C")});E.displayName="ThreadText";exports.THREAD_TEXT_CLASSES=y.THREAD_TEXT_CLASSES;exports.createThreadText=y.createThreadText;exports.ThreadText=E;exports.useThreadText=g;
package/dist/index.d.ts CHANGED
@@ -16,13 +16,17 @@ export declare const THREAD_TEXT_CLASSES: {
16
16
  readonly bg: "tt-bg";
17
17
  /** Overlay canvas: cursor sheen (`mix-blend-mode: screen`). */
18
18
  readonly fx: "tt-fx";
19
+ /** The visually hidden real text (the element's own content, or a copy of `text`) for assistive tech. */
20
+ readonly text: "tt-text";
19
21
  /** Blinking text caret shown in editable mode. */
20
22
  readonly caret: "tt-caret";
21
23
  };
22
24
 
23
25
  /**
24
- * Drop-in component that embroiders `text` inside a self-sizing container. The canvas
25
- * output is decorative; the word is exposed to assistive tech via `aria-label`.
26
+ * Drop-in component that embroiders `text` inside a self-sizing container. The element keeps its own
27
+ * semantics (`as="h1"` stays a heading): the renderer puts the text in the element, visually hidden, for
28
+ * screen readers, find-in-page and translation, and hides the canvases from them. HTML attributes and
29
+ * handlers (id, aria-*, data-*, lang, onClick…) are forwarded to the element.
26
30
  */
27
31
  export declare const ThreadText: default_2.ForwardRefExoticComponent<ThreadTextProps & default_2.RefAttributes<HTMLElement>>;
28
32
 
@@ -146,28 +150,20 @@ export declare interface ThreadTextOptions {
146
150
  reducedMotion?: boolean;
147
151
  }
148
152
 
149
- declare interface ThreadTextProps extends ThreadTextOptions {
153
+ declare interface ThreadTextProps extends ThreadTextOptions, Omit<default_2.HTMLAttributes<HTMLElement>, 'children' | 'className' | 'style'> {
150
154
  className?: string;
151
155
  style?: default_2.CSSProperties;
152
- /** Container element type. (default: 'div') */
156
+ /** Container element type, e.g. 'h1' — it keeps its own semantics. (default: 'div') */
153
157
  as?: default_2.ElementType;
154
- /**
155
- * Accessible label for the embroidery. Defaults to the embroidered `text`, so
156
- * screen readers announce the word even though it is drawn on a canvas.
157
- */
158
- 'aria-label'?: string;
159
- role?: string;
160
- 'aria-describedby'?: string;
161
158
  }
162
159
 
163
160
  /**
164
161
  * React hook that mounts a threadText renderer inside a ref'd container.
165
162
  *
166
- * The instance is created once and kept alive; option changes (font, weight, colour,
167
- * size, sew rate, sheen, editability) are applied live via `instance.update()` — no
168
- * remount, no re-sew. Text changes route through `setText`. The surface re-fits to the
169
- * container width via ResizeObserver, and tears down on unmount. Only `reducedMotion`
170
- * (fixed at creation) forces a fresh instance.
163
+ * The instance is created once and kept alive; every option change is applied live via
164
+ * `instance.update()` (no remount, no re-sew), and text changes route through `setText`. The renderer
165
+ * re-fits to its container's width by itself and tears down on unmount. Only `reducedMotion` (fixed at
166
+ * creation) forces a fresh instance.
171
167
  *
172
168
  * @typeParam T - the container element type (default `HTMLElement`); pass e.g.
173
169
  * `useThreadText<HTMLDivElement>(...)` so the returned ref attaches cleanly to a `<div>`.