@liiift-studio/threadtext 0.1.0 → 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.
- package/README.md +18 -12
- package/dist/index.cjs +1 -1
- package/dist/index.js +383 -350
- package/dist/threadtext.webflow.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
**Render any text as photorealistic, procedural satin-stitch embroidery — in real time, in the browser, from the font's actual glyph geometry.**
|
|
4
4
|
|
|
5
|
-
> Status: **
|
|
6
|
-
> hook
|
|
7
|
-
>
|
|
8
|
-
> The original reference renderer lives in
|
|
9
|
-
>
|
|
10
|
-
>
|
|
5
|
+
> Status: **shipped.** Published to npm (`@liiift-studio/threadtext`) with a framework-agnostic
|
|
6
|
+
> core (`createThreadText`), a React hook + component, Framer and Webflow ports, tests, and a
|
|
7
|
+
> live landing site at [threadtext.com](https://threadtext.com) (demo font: the OFL Fraunces
|
|
8
|
+
> variable). The original single-file reference renderer lives in
|
|
9
|
+
> [`demo/index.html`](./demo/index.html) as the visual oracle; tool-build conventions are in the
|
|
10
|
+
> monorepo [`../GUIDE.md`](../GUIDE.md).
|
|
11
11
|
|
|
12
12
|
Homepage: [threadtext.com](https://threadtext.com) · npm: `@liiift-studio/threadtext`
|
|
13
13
|
|
|
@@ -58,10 +58,12 @@ const thread = createThreadText(document.getElementById('host'), {
|
|
|
58
58
|
weight: 680,
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
thread.setText('Threads')
|
|
62
|
-
thread.
|
|
63
|
-
thread.
|
|
64
|
-
thread.
|
|
61
|
+
thread.setText('Threads') // re-fit to width and redraw instantly (no sew-in)
|
|
62
|
+
thread.update({ threadColor: '#e6c200', fill: 0.8 }) // live changes — instant, no re-sew
|
|
63
|
+
thread.replay() // re-run the sew-in animation
|
|
64
|
+
thread.resize() // re-fit to the container
|
|
65
|
+
thread.focus() // focus the surface for typing (editable mode)
|
|
66
|
+
thread.destroy() // cancel rAF, remove listeners, free canvases
|
|
65
67
|
```
|
|
66
68
|
|
|
67
69
|
React:
|
|
@@ -74,13 +76,17 @@ import { ThreadText } from '@liiift-studio/threadtext'
|
|
|
74
76
|
|
|
75
77
|
Thread colour, `fill` (size — the word re-fits to the container width on load/resize),
|
|
76
78
|
`weight`, `font`, `sewRate`, `sheen`, `animate`, and `editable` (type straight on the
|
|
77
|
-
artwork
|
|
79
|
+
artwork — backed by a real input, so touch keyboards and IME work) with an `onTextChange`
|
|
80
|
+
callback are all options — see `ThreadTextOptions`. Change any of them live with
|
|
78
81
|
`instance.update(...)` — it redraws instantly, never re-running the sew-in. `react`/`react-dom`
|
|
79
82
|
are optional peers; the core is framework-free.
|
|
80
83
|
|
|
81
84
|
## What's next
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
Now shipped. Remaining ideas (see `HANDOFF.md`): region-limit or move the per-keystroke geometry
|
|
87
|
+
rebuild to a Web Worker/WASM (it currently re-runs the full distance-transform pipeline on every
|
|
88
|
+
edit); real variable-font axis control (`opsz`/`wght`) via path-based glyph rendering, since canvas
|
|
89
|
+
`fillText` can't set `font-variation-settings`; and additional stitch modes (chain, cross, running).
|
|
84
90
|
|
|
85
91
|
---
|
|
86
92
|
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const X=require("react"),xe=require("react/jsx-runtime"),pt={bg:"tt-bg",fx:"tt-fx",caret:"tt-caret"};function Q(m,e){let o=Math.imul(m|0,374761393)+Math.imul(e|0,668265263)|0;return o=Math.imul(o^o>>>13,1274126177),((o^o>>>16)>>>0)/4294967295}function Qt(m,e){const o=Math.floor(m),r=Math.floor(e),i=m-o,a=e-r,f=i*i*(3-2*i),A=a*a*(3-2*a),E=Q(o,r),C=Q(o+1,r),c=Q(o,r+1),d=Q(o+1,r+1);return E+(C-E)*f+(c-E)*A+(E-C-c+d)*f*A}const Mt=1e20;function Zt(m,e,o,r,i){let a=0;r[0]=0,i[0]=-Mt,i[1]=Mt;for(let f=1;f<e;f++){let A=(m[f]+f*f-(m[r[a]]+r[a]*r[a]))/(2*f-2*r[a]);for(;A<=i[a];)a--,A=(m[f]+f*f-(m[r[a]]+r[a]*r[a]))/(2*f-2*r[a]);a++,r[a]=f,i[a]=A,i[a+1]=Mt}a=0;for(let f=0;f<e;f++){for(;i[a+1]<f;)a++;o[f]=(f-r[a])*(f-r[a])+m[r[a]]}}function ge(m,e,o){const r=new Float64Array(e*o);for(let c=0;c<e*o;c++)r[c]=m[c]?Mt:0;const i=Math.max(e,o),a=new Float64Array(i),f=new Float64Array(i),A=new Int32Array(i),E=new Float64Array(i+1);for(let c=0;c<e;c++){for(let d=0;d<o;d++)a[d]=r[d*e+c];Zt(a,o,f,A,E);for(let d=0;d<o;d++)r[d*e+c]=f[d]}for(let c=0;c<o;c++){for(let d=0;d<e;d++)a[d]=r[c*e+d];Zt(a,e,f,A,E);for(let d=0;d<e;d++)r[c*e+d]=f[d]}const C=new Float32Array(e*o);for(let c=0;c<e*o;c++)C[c]=Math.sqrt(r[c]);return C}function Ht(m,e,o,r,i){let a=Float32Array.from(m);const f=new Float32Array(e*o),A=1/(2*r+1),E=(C,c)=>C<0?0:C>c?c:C;for(let C=0;C<i;C++){for(let c=0;c<o;c++){const d=c*e;let $=0;for(let B=-r;B<=r;B++)$+=a[d+E(B,e-1)];for(let B=0;B<e;B++)f[d+B]=$*A,$+=a[d+E(B+r+1,e-1)]-a[d+E(B-r,e-1)]}for(let c=0;c<e;c++){let d=0;for(let $=-r;$<=r;$++)d+=f[E($,o-1)*e+c];for(let $=0;$<o;$++)a[$*e+c]=d*A,d+=f[E($+r+1,o-1)*e+c]-f[E($-r,o-1)*e+c]}}return a}function Wt(m,e){if(!m)return e;const o=m.trim();if(o[0]==="#"){let i=o.slice(1);if(i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),i.length>=6){const a=parseInt(i.slice(0,2),16),f=parseInt(i.slice(2,4),16),A=parseInt(i.slice(4,6),16);if(!Number.isNaN(a)&&!Number.isNaN(f)&&!Number.isNaN(A))return[a,f,A]}return e}const r=o.match(/rgba?\(([^)]+)\)/i);if(r){const i=r[1].split(",").map(a=>parseFloat(a));if(i.length>=3&&i.slice(0,3).every(a=>!Number.isNaN(a)))return[Math.round(i[0]),Math.round(i[1]),Math.round(i[2])]}return e}function K(m){return m<0?0:m>255?255:Math.round(m)}function te(m){return(m.split(",")[0]||"serif").trim().replace(/^["']|["']$/g,"")}function ee(m,e){if(typeof window>"u"||typeof document>"u"||!m)return{setText(){},replay(){},resize(){},update(){},focus(){},destroy(){},get text(){return e.text??""}};let o=e.text??"",r=e.font??"Georgia, serif",i=e.weight??680,a=e.fill??.9,f=e.sewRate??110,A=e.sheen??!0,E=e.animate??!0,C=e.editable??!1,c=e.pitch,d=e.onTextChange,$=te(r);const B=e.reducedMotion??!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches);let D=Wt(e.threadColor??"#fffbf3",[255,251,243]),tt=[0,0,0],N=[0,0,0];function et(t){D=Wt(t,[255,251,243]),tt=[D[0]*.585,D[1]*.585,D[2]*.585],N=[D[0]*.47,D[1]*.47,D[2]*.47]}et(e.threadColor??"#fffbf3");const G=[];let P,g;m instanceof HTMLCanvasElement?(P=m,g=m.parentElement??m):(g=m,P=document.createElement("canvas"),G.push(P),g.appendChild(P)),P.classList.add(pt.bg);const O=document.createElement("canvas");G.push(O),O.classList.add(pt.fx),g.appendChild(O),getComputedStyle(g).position==="static"&&(g.style.position="relative"),P.style.display="block",P.style.width="100%",Object.assign(O.style,{position:"absolute",inset:"0",width:"100%",pointerEvents:"none",mixBlendMode:"screen"});let S=null,Z=!1,s=0,h=0,H=0,bt=0,ft=4,nt=[],ot=0,rt=0,Ct=new Uint8Array(0),Tt=new Float32Array(0),ut=new Float32Array(0),dt=new Float32Array(0),U=null,it=null,ht=null,mt=[],yt=3;const L={rows:[],idx:0,acc:0,rate:0,on:!1},Y={x:0,y:0,set:!1};let W=!0,vt=0,Bt=!1,xt=0,q=!1,J=!1;function re(){const t=g.getBoundingClientRect(),n=Math.max(1,Math.round(t.width||Math.min(window.innerWidth*.95,1240))),l=o||"Ag",y=P.getContext("2d");let T=100;y&&(y.font=`${i} 100px ${r}`,T=y.measureText(l).width||100);let b=Math.max(8,100*(n*a)/T),v=b*.7,R=b*.3,I=n*a;if(y){y.font=`${i} ${b}px ${r}`;const p=y.measureText(l);I=p.width||I,p.actualBoundingBoxAscent>0&&(v=p.actualBoundingBoxAscent),p.actualBoundingBoxDescent>0&&(R=p.actualBoundingBoxDescent)}const w=Math.max(1,Math.round(2*Math.max(v,R)*1.12));let u=Math.min(window.devicePixelRatio||1,1.7);for(;n*u*w*u>9e5&&u>.4;)u-=.1;s=Math.max(1,Math.round(n*u)),h=Math.max(1,Math.round(w*u)),H=Math.max(4,Math.round(b*u)),bt=Math.round(s/2-I*u/2);for(const p of[P,O])p.width=s,p.height=h,p.style.height=w+"px";g.style.height=w+"px",ft=c??Math.max(3,h*.0095)}function ie(){it=document.createElement("canvas"),it.width=s,it.height=h,ht=it.getContext("2d",{willReadFrequently:!0})}function Nt(){const t=Math.max(7,ft*2.5),n=Math.max(3.2,ft*1.3);ot=Math.ceil(t)+2,rt=Math.ceil(n)+2,nt=[];for(let l=0;l<20;l++){const y=.34+l/19*.82,T=document.createElement("canvas");T.width=ot,T.height=rt;const b=T.getContext("2d");if(!b){nt.push(T);continue}const v=ot/2,R=rt/2,I=b.createLinearGradient(0,R-n/2,0,R+n/2),w=(k,j)=>`rgba(${K(k[0]*y)},${K(k[1]*y)},${K(k[2]*y)},${j})`;I.addColorStop(0,w(N,0)),I.addColorStop(.16,w(tt,1)),I.addColorStop(.5,w(D,1)),I.addColorStop(.84,w(tt,1)),I.addColorStop(1,w(N,0)),b.fillStyle=I,b.beginPath();const u=n/2;b.moveTo(v-t/2+u,R-u),b.lineTo(v+t/2-u,R-u),b.arc(v+t/2-u,R,u,-Math.PI/2,Math.PI/2),b.lineTo(v-t/2+u,R+u),b.arc(v-t/2+u,R,u,Math.PI/2,-Math.PI/2),b.closePath(),b.fill(),b.globalCompositeOperation="destination-in";const p=b.createLinearGradient(v-t/2,0,v+t/2,0);p.addColorStop(0,"rgba(0,0,0,0)"),p.addColorStop(.22,"rgba(0,0,0,1)"),p.addColorStop(.78,"rgba(0,0,0,1)"),p.addColorStop(1,"rgba(0,0,0,0)"),b.fillStyle=p,b.fillRect(0,0,ot,rt),nt.push(T)}}function ae(){if(!ht)return;const t=ht;t.clearRect(0,0,s,h),t.fillStyle="#fff",t.textAlign="left",t.textBaseline="middle",t.font=`${i} ${H}px ${r}`,t.fillText(o,bt,h*.5);const n=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 F=x*s+M,_=n[F*4+3]/255,z=Qt(M*.5,x*.5)*.22+Qt(M*1.8,x*1.8)*.1;l[F]=_>.5+(z-.16)?1:0}Ct=l;const y=ge(l,s,h),T=new Float32Array(s*h);for(let x=1;x<h-1;x++)for(let M=1;M<s-1;M++){const F=x*s+M;T[F]=(y[F]*4+y[F-1]+y[F+1]+y[F-s]+y[F+s])/8}const b=new Float32Array(s*h),v=new Float32Array(s*h),R=new Float32Array(s*h),I=new Float32Array(s*h);for(let x=1;x<h-1;x++)for(let M=1;M<s-1;M++){const F=x*s+M;if(!l[F])continue;const _=(T[F+1]-T[F-1])*.5,z=(T[F+s]-T[F-s])*.5;R[F]=_,I[F]=z,b[F]=_*_-z*z,v[F]=2*_*z}const w=Math.max(7,Math.round(h*.05)),u=Ht(b,s,h,w,2),p=Ht(v,s,h,w,2);ut=new Float32Array(s*h),dt=new Float32Array(s*h);for(let x=0;x<s*h;x++){if(!l[x])continue;const M=.5*Math.atan2(p[x],u[x]);ut[x]=Math.cos(M),dt[x]=Math.sin(M)}const k=Math.max(9,h*.04),j=new Float32Array(s*h),ct=-.45,st=-.62,wt=.64;for(let x=1;x<h-1;x++)for(let M=1;M<s-1;M++){const F=x*s+M;if(!l[F])continue;let _=R[F],z=I[F];const Ut=Math.hypot(_,z)||1;_/=Ut,z/=Ut;const Vt=T[F],Yt=(1-Math.min(Vt/k,1))*1.25;let It=-_*Yt,Pt=-z*Yt;const Jt=1.5,Dt=Math.hypot(It,Pt,Jt);It/=Dt,Pt/=Dt;let kt=It*ct+Pt*st+Jt/Dt*wt;kt<0&&(kt=0);const ye=Math.min(1,.45+.55*Math.min(Vt/(k*.7),1));j[F]=Math.min(1.12,(.5+.75*kt)*ye)}Tt=j,U=document.createElement("canvas"),U.width=s,U.height=h;const V=U.getContext("2d");if(V){const x=V.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);V.putImageData(x,0,0)}}function le(){const t=Math.max(1.6,ft*.6);yt=t;const n=[];for(let l=0;l<h;l+=t)for(let y=0;y<s;y+=t){const T=(Q(Math.floor(y),Math.floor(l))-.5)*t*.9,b=(Q(Math.floor(l),Math.floor(y))-.5)*t*.9,v=Math.round(y+T),R=Math.round(l+b);if(v<1||R<1||v>=s-1||R>=h-1)continue;const I=R*s+v;if(!Ct[I])continue;const w=Math.atan2(dt[I],ut[I]),u=.86+Q(v*7,R*13)*.18;let p=Tt[I]*u;p=p<0?0:p>1.12?1.12:p,n.push({x:v,y:R,ang:w,idx:Math.min(19,Math.max(0,Math.round(p/1.12*19)))})}n.sort((l,y)=>l.x-y.x),mt=n}function Ot(t,n){t.save(),t.translate(n.x,n.y),t.rotate(n.ang),t.drawImage(nt[n.idx],-ot/2,-rt/2),t.restore()}function At(){const t=P.getContext("2d");if(t)for(const n of mt)Ot(t,n)}function Et(){const t=P.getContext("2d");t&&t.clearRect(0,0,s,h)}function ce(t){if(!t.length)return[];const n=Math.max(4,yt*1.5),l=new Map,y=(w,u)=>w+","+u;t.forEach((w,u)=>{const p=y(Math.floor(w.x/n),Math.floor(w.y/n));let k=l.get(p);k||l.set(p,k=[]),k.push(u)});const T=yt*1.8*(yt*1.8);function b(w){const u=t[w],p=Math.floor(u.x/n),k=Math.floor(u.y/n),j=[];for(let ct=-1;ct<=1;ct++)for(let st=-1;st<=1;st++){const wt=l.get(y(p+ct,k+st));if(wt)for(const V of wt){if(V===w)continue;const x=t[V].x-u.x,M=t[V].y-u.y;x*x+M*M<=T&&j.push(V)}}return j}const v=new Uint8Array(t.length),R=[],I=t.map((w,u)=>u).sort((w,u)=>t[w].x+t[w].y-(t[u].x+t[u].y));for(const w of I){if(v[w])continue;let u=[w];for(v[w]=1;u.length;){R.push(u.map(k=>t[k]));const p=[];for(const k of u)for(const j of b(k))v[j]||(v[j]=1,p.push(j));u=p}}return R}function se(){if(Et(),B||!E){At(),L.on=!1;return}L.rows=ce(mt),L.idx=0,L.acc=0,L.rate=f,L.on=L.rows.length>0}function fe(t){const n=P.getContext("2d");if(n)for(t>L.rows.length&&(t=L.rows.length);L.idx<t;){const l=L.rows[L.idx++];for(const y of l)Ot(n,y)}}function ue(t,n){const l=O.getContext("2d");if(!l||(l.clearRect(0,0,s,h),!A||!U))return;const y=s*.32,T=l.createRadialGradient(t,n,0,t,n,y);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)"),l.fillStyle=T,l.fillRect(0,0,s,h),l.globalCompositeOperation="destination-in",l.drawImage(U,0,0),l.globalCompositeOperation="source-over"}function de(){S||!C||(S=document.createElement("span"),S.className=pt.caret,S.setAttribute("aria-hidden","true"),Object.assign(S.style,{position:"absolute",pointerEvents:"none",borderRadius:"1px",opacity:"0",background:`rgb(${K(D[0])},${K(D[1])},${K(D[2])})`}),g.appendChild(S),G.push(S))}function St(){if(!C||!S)return;const t=P.getContext("2d");if(!t)return;t.font=`${i} ${H}px ${r}`;const n=t.measureText(o).width,l=(P.clientWidth||s)/s,y=H*.7;S.style.left=(bt+n+H*.05)*l+"px",S.style.top=.5*(P.clientHeight||h)-y*l/2+"px",S.style.height=y*l+"px",S.style.width=Math.max(2,Math.round(H*.02*l))+"px",S.style.background=`rgb(${K(D[0])},${K(D[1])},${K(D[2])})`}function jt(t){if(q)return;xt||(xt=t);const n=Math.min(.25,(t-xt)/1e3);xt=t,L.on&&(L.acc+=L.rate*n,fe(L.acc),L.idx>=L.rows.length&&(L.on=!1)),W&&U&&(ue(Y.set?Y.x:s*.5,Y.set?Y.y:h*.34),W=!1),S&&(S.style.opacity=C&&Z&&Math.floor(t/530)%2===0?"1":"0"),vt=requestAnimationFrame(jt)}function gt(t){const n=O.getBoundingClientRect();Y.x=(t.clientX-n.left)/(n.width||1)*s,Y.y=(t.clientY-n.top)/(n.height||1)*h,Y.set=!0,W=!0}function qt(t){if(!(!C||t.metaKey||t.ctrlKey||t.altKey)){if(t.key==="Backspace"){t.preventDefault(),Rt(o.slice(0,-1),!0);return}if(t.key==="Enter"){t.preventDefault(),$t.replay();return}[...t.key].length===1&&(t.preventDefault(),Rt(o+t.key,!0))}}function _t(){Z=!0}function zt(){Z=!1,S&&(S.style.opacity="0")}function Kt(){C&&g.focus()}function Ft(t){C=t,t?(g.tabIndex=0,g.setAttribute("role","textbox"),g.getAttribute("aria-label")||g.setAttribute("aria-label","Editable embroidered text — type to change it"),de(),g.addEventListener("keydown",qt),g.addEventListener("focus",_t),g.addEventListener("blur",zt),g.addEventListener("pointerdown",Kt),St()):(g.removeAttribute("tabindex"),g.removeAttribute("role"),g.removeEventListener("keydown",qt),g.removeEventListener("focus",_t),g.removeEventListener("blur",zt),g.removeEventListener("pointerdown",Kt),S&&(S.style.opacity="0"))}function he(t){if(t!==A)if(A=t,t)window.addEventListener("pointermove",gt,{passive:!0}),W=!0;else{window.removeEventListener("pointermove",gt);const n=O.getContext("2d");n&&n.clearRect(0,0,s,h)}}function at(t){re(),ie(),Nt(),ae(),le(),t?se():(Et(),At(),L.on=!1),St(),W=!0}function Rt(t,n){t=t??"",!(t===o&&J)&&(o=t,J&&(at(!1),n&&d&&d(o)))}let lt;function Xt(t,n,l){const y=`${n} 200px ${t}`;let T=!1;try{T=!!document.fonts&&document.fonts.check(y)}catch{T=!0}if(!document.fonts||T){l();return}let b=!1;const v=()=>{b||(b=!0,lt&&clearTimeout(lt),l())};document.fonts.load(y,o).then(()=>document.fonts.ready).then(v,v),lt=setTimeout(v,1500)}function me(){q||(at(!0),J=!0,Bt||(Bt=!0,vt=requestAnimationFrame(jt)))}C&&Ft(!0),A&&window.addEventListener("pointermove",gt,{passive:!0}),Xt($,i,me);let Lt;function Gt(){clearTimeout(Lt),Lt=setTimeout(()=>$t.resize(),200)}window.addEventListener("resize",Gt);const $t={get text(){return o},setText(t){if(!q){if(!J){o=t??"";return}Rt(t,!1)}},replay(){q||!J||at(!0)},resize(){q||!J||at(!1)},update(t){if(q)return;let n=!1,l=!1;t.font!==void 0&&t.font!==r&&(r=t.font,$=te(r),n=!0),t.weight!==void 0&&t.weight!==i&&(i=t.weight,n=!0),t.fill!==void 0&&t.fill!==a&&(a=t.fill,n=!0),t.pitch!==void 0&&t.pitch!==c&&(c=t.pitch,n=!0),t.threadColor!==void 0&&(et(t.threadColor),l=!0),t.sewRate!==void 0&&(f=t.sewRate),t.animate!==void 0&&(E=t.animate),t.onTextChange!==void 0&&(d=t.onTextChange),t.sheen!==void 0&&he(t.sheen),t.editable!==void 0&&t.editable!==C&&Ft(t.editable),J&&(n?Xt($,i,()=>{q||at(!1)}):l&&(Nt(),Et(),At(),St()),W=!0)},focus(){!q&&C&&g.focus()},destroy(){if(!q){q=!0,cancelAnimationFrame(vt),clearTimeout(Lt),lt&&clearTimeout(lt),window.removeEventListener("resize",Gt),window.removeEventListener("pointermove",gt),C&&Ft(!1);for(const t of G)t.remove();nt=[],mt=[],L.rows=[],Ct=new Uint8Array(0),Tt=new Float32Array(0),ut=new Float32Array(0),dt=new Float32Array(0),U=it=null,ht=null,S=null}}};return $t}function ne(m){const e=X.useRef(null),o=X.useRef(null),r=X.useRef(m);r.current=m;const i=X.useRef(m.onTextChange);i.current=m.onTextChange;const{text:a,font:f,weight:A,threadColor:E,pitch:C,fill:c,animate:d,sewRate:$,sheen:B,editable:D,reducedMotion:tt}=m;return X.useLayoutEffect(()=>{const N=e.current;if(!N)return;const et=ee(N,{...r.current,onTextChange:O=>{var S;return(S=i.current)==null?void 0:S.call(i,O)}});o.current=et;let G=0,P=0,g;return typeof ResizeObserver<"u"&&(g=new ResizeObserver(O=>{const S=Math.round(O[0].contentRect.width);S!==P&&(P=S,cancelAnimationFrame(G),G=requestAnimationFrame(()=>{var Z;return(Z=o.current)==null?void 0:Z.resize()}))}),g.observe(N)),()=>{g==null||g.disconnect(),cancelAnimationFrame(G),et.destroy(),o.current=null}},[tt]),X.useEffect(()=>{var N;(N=o.current)==null||N.update({font:f,weight:A,threadColor:E,pitch:C,fill:c,animate:d,sewRate:$,sheen:B,editable:D})},[f,A,E,C,c,d,$,B,D]),X.useEffect(()=>{var N;(N=o.current)==null||N.setText(a)},[a]),e}const oe=X.forwardRef(function({className:e,style:o,as:r="div","aria-label":i,role:a,"aria-describedby":f,...A},E){const C=ne(A),c=X.useCallback(d=>{C.current=d,typeof E=="function"?E(d):E&&(E.current=d)},[C,E]);return xe.jsx(r,{ref:c,className:e,style:o,role:a??"img","aria-label":i??A.text,"aria-describedby":f})});oe.displayName="ThreadText";exports.THREAD_TEXT_CLASSES=pt;exports.ThreadText=oe;exports.createThreadText=ee;exports.useThreadText=ne;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const V=require("react"),At=require("react/jsx-runtime"),Te={bg:"tt-bg",fx:"tt-fx",caret:"tt-caret"};function W(h,t){let n=Math.imul(h|0,374761393)+Math.imul(t|0,668265263)|0;return n=Math.imul(n^n>>>13,1274126177),((n^n>>>16)>>>0)/4294967295}function tt(h,t){const n=Math.floor(h),r=Math.floor(t),i=h-n,a=t-r,u=i*i*(3-2*i),b=a*a*(3-2*a),S=W(n,r),E=W(n+1,r),c=W(n,r+1),m=W(n+1,r+1);return S+(E-S)*u+(c-S)*b+(S-E-c+m)*u*b}const Ee=1e20;function nt(h,t,n,r,i){let a=0;r[0]=0,i[0]=-Ee,i[1]=Ee;for(let u=1;u<t;u++){let b=(h[u]+u*u-(h[r[a]]+r[a]*r[a]))/(2*u-2*r[a]);for(;b<=i[a];)a--,b=(h[u]+u*u-(h[r[a]]+r[a]*r[a]))/(2*u-2*r[a]);a++,r[a]=u,i[a]=b,i[a+1]=Ee}a=0;for(let u=0;u<t;u++){for(;i[a+1]<u;)a++;n[u]=(u-r[a])*(u-r[a])+h[r[a]]}}function St(h,t,n){const r=new Float64Array(t*n);for(let c=0;c<t*n;c++)r[c]=h[c]?Ee:0;const i=Math.max(t,n),a=new Float64Array(i),u=new Float64Array(i),b=new Int32Array(i),S=new Float64Array(i+1);for(let c=0;c<t;c++){for(let m=0;m<n;m++)a[m]=r[m*t+c];nt(a,n,u,b,S);for(let m=0;m<n;m++)r[m*t+c]=u[m]}for(let c=0;c<n;c++){for(let m=0;m<t;m++)a[m]=r[c*t+m];nt(a,t,u,b,S);for(let m=0;m<t;m++)r[c*t+m]=u[m]}const E=new Float32Array(t*n);for(let c=0;c<t*n;c++)E[c]=Math.sqrt(r[c]);return E}function ot(h,t,n,r,i){let a=Float32Array.from(h);const u=new Float32Array(t*n),b=1/(2*r+1),S=(E,c)=>E<0?0:E>c?c:E;for(let E=0;E<i;E++){for(let c=0;c<n;c++){const m=c*t;let I=0;for(let N=-r;N<=r;N++)I+=a[m+S(N,t-1)];for(let N=0;N<t;N++)u[m+N]=I*b,I+=a[m+S(N+r+1,t-1)]-a[m+S(N-r,t-1)]}for(let c=0;c<t;c++){let m=0;for(let I=-r;I<=r;I++)m+=u[S(I,n-1)*t+c];for(let I=0;I<n;I++)a[I*t+c]=m*b,m+=u[S(I+r+1,n-1)*t+c]-u[S(I-r,n-1)*t+c]}}return a}function rt(h,t){if(!h)return t;const n=h.trim();if(n[0]==="#"){let i=n.slice(1);if(i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),i.length>=6){const a=parseInt(i.slice(0,2),16),u=parseInt(i.slice(2,4),16),b=parseInt(i.slice(4,6),16);if(!Number.isNaN(a)&&!Number.isNaN(u)&&!Number.isNaN(b))return[a,u,b]}return t}const r=n.match(/rgba?\(([^)]+)\)/i);if(r){const i=r[1].split(",").map(a=>parseFloat(a));if(i.length>=3&&i.slice(0,3).every(a=>!Number.isNaN(a)))return[Math.round(i[0]),Math.round(i[1]),Math.round(i[2])]}return t}function K(h){return h<0?0:h>255?255:Math.round(h)}function be(h,t,n){return h<t?t:h>n?n:h}function it(h){return(h.split(",")[0]||"serif").trim().replace(/^["']|["']$/g,"")}function at(h,t){if(typeof window>"u"||typeof document>"u"||!h)return{setText(){},replay(){},resize(){},update(){},focus(){},destroy(){},get text(){return t.text??""}};let n=t.text??"",r=t.font??"Georgia, serif",i=be(t.weight??680,1,1e3),a=be(t.fill??.9,.05,1),u=Math.max(1,t.sewRate??110),b=t.sheen??!0,S=t.animate??!0,E=t.editable??!1,c=t.pitch,m=t.onTextChange,I=it(r);const N=t.reducedMotion??!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches);let B=rt(t.threadColor??"#fffbf3",[255,251,243]),ae=[0,0,0],D=[0,0,0];function le(e){B=rt(e,[255,251,243]),ae=[B[0]*.585,B[1]*.585,B[2]*.585],D=[B[0]*.47,B[1]*.47,B[2]*.47]}le(t.threadColor??"#fffbf3");const G=[];let O,L;h instanceof HTMLCanvasElement?(O=h,L=h.parentElement??h):(L=h,O=document.createElement("canvas"),G.push(O),L.appendChild(O)),O.classList.add(Te.bg);const j=document.createElement("canvas");G.push(j),j.classList.add(Te.fx),L.appendChild(j),getComputedStyle(L).position==="static"&&(L.style.position="relative"),O.style.display="block",O.style.width="100%",Object.assign(j.style,{position:"absolute",inset:"0",width:"100%",pointerEvents:"none",mixBlendMode:"screen"});let y=null,A=null,Q=!1,s=0,x=0,ee=0,Ae=0,te=4,ne=[],se=0,ce=0,je=-1,qe="",ze=-1,_e=-1,Se=new Uint8Array(0),Fe=new Float32Array(0),me=new Float32Array(0),xe=new Float32Array(0),Y=null,oe=null,ye=null,ge=[],pe=3;const $={rows:[],idx:0,acc:0,rate:0,on:!1},U={x:0,y:0,set:!1};let Z=!0,Re=0,fe=!1,ue=0,q=!1,H=!1;function ct(){const e=L.getBoundingClientRect(),o=Math.max(1,Math.round(e.width||Math.min(window.innerWidth*.95,1240))),l=n||"Ag",f=O.getContext("2d");f&&(f.textBaseline="middle");let T=100;f&&(f.font=`${i} 100px ${r}`,T=f.measureText(l).width||100);const C=Math.max(8,100*(o*a)/T);let v=C*.62,F=C*.62,P=o*a;if(f){f.font=`${i} ${C}px ${r}`;const w=f.measureText(l);P=w.width||P,w.actualBoundingBoxAscent>0&&(v=w.actualBoundingBoxAscent),w.actualBoundingBoxDescent>0&&(F=w.actualBoundingBoxDescent)}const p=Math.max(1,Math.round(2*Math.max(v,F)*1.1));let d=Math.min(window.devicePixelRatio||1,1.7);for(;o*d*p*d>9e5&&d>.4;)d-=.1;s=Math.max(1,Math.round(o*d)),x=Math.max(1,Math.round(p*d)),ee=Math.max(4,Math.round(C*d)),Ae=Math.round(s/2-P*d/2);for(const w of[O,j])w.width=s,w.height=x,w.style.height=p+"px";L.style.height=p+"px",te=c??Math.max(3,x*.0095)}function ft(){oe&&ze===s&&_e===x||(oe=document.createElement("canvas"),oe.width=s,oe.height=x,ye=oe.getContext("2d",{willReadFrequently:!0}),ze=s,_e=x)}function Xe(){const e=Math.max(7,te*2.5),o=Math.max(3.2,te*1.3);se=Math.ceil(e)+2,ce=Math.ceil(o)+2,ne=[];for(let l=0;l<20;l++){const f=.34+l/19*.82,T=document.createElement("canvas");T.width=se,T.height=ce;const C=T.getContext("2d");if(!C){ne.push(T);continue}const v=se/2,F=ce/2,P=C.createLinearGradient(0,F-o/2,0,F+o/2),p=(k,z)=>`rgba(${K(k[0]*f)},${K(k[1]*f)},${K(k[2]*f)},${z})`;P.addColorStop(0,p(D,0)),P.addColorStop(.16,p(ae,1)),P.addColorStop(.5,p(B,1)),P.addColorStop(.84,p(ae,1)),P.addColorStop(1,p(D,0)),C.fillStyle=P,C.beginPath();const d=o/2;C.moveTo(v-e/2+d,F-d),C.lineTo(v+e/2-d,F-d),C.arc(v+e/2-d,F,d,-Math.PI/2,Math.PI/2),C.lineTo(v-e/2+d,F+d),C.arc(v-e/2+d,F,d,Math.PI/2,-Math.PI/2),C.closePath(),C.fill(),C.globalCompositeOperation="destination-in";const w=C.createLinearGradient(v-e/2,0,v+e/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)"),C.fillStyle=w,C.fillRect(0,0,se,ce),ne.push(T)}je=te,qe=B.join(",")}function ut(){ne.length&&je===te&&qe===B.join(",")||Xe()}function dt(){if(!ye)return;const e=ye;e.clearRect(0,0,s,x),e.fillStyle="#fff",e.textAlign="left",e.textBaseline="middle",e.font=`${i} ${ee}px ${r}`,e.fillText(n,Ae,x*.5);const o=e.getImageData(0,0,s,x).data,l=new Uint8Array(s*x);for(let g=0;g<x;g++)for(let M=0;M<s;M++){const R=g*s+M,_=o[R*4+3]/255,X=tt(M*.5,g*.5)*.22+tt(M*1.8,g*1.8)*.1;l[R]=_>.5+(X-.16)?1:0}Se=l;const f=St(l,s,x),T=new Float32Array(s*x);for(let g=1;g<x-1;g++)for(let M=1;M<s-1;M++){const R=g*s+M;T[R]=(f[R]*4+f[R-1]+f[R+1]+f[R-s]+f[R+s])/8}const C=new Float32Array(s*x),v=new Float32Array(s*x),F=new Float32Array(s*x),P=new Float32Array(s*x);for(let g=1;g<x-1;g++)for(let M=1;M<s-1;M++){const R=g*s+M;if(!l[R])continue;const _=(T[R+1]-T[R-1])*.5,X=(T[R+s]-T[R-s])*.5;F[R]=_,P[R]=X,C[R]=_*_-X*X,v[R]=2*_*X}const p=Math.max(7,Math.round(x*.05)),d=ot(C,s,x,p,2),w=ot(v,s,x,p,2);me=new Float32Array(s*x),xe=new Float32Array(s*x);for(let g=0;g<s*x;g++){if(!l[g])continue;const M=.5*Math.atan2(w[g],d[g]);me[g]=Math.cos(M),xe[g]=Math.sin(M)}const k=Math.max(9,x*.04),z=new Float32Array(s*x),de=-.45,he=-.62,ve=.64;for(let g=1;g<x-1;g++)for(let M=1;M<s-1;M++){const R=g*s+M;if(!l[R])continue;let _=F[R],X=P[R];const Qe=Math.hypot(_,X)||1;_/=Qe,X/=Qe;const Ze=T[R],We=(1-Math.min(Ze/k,1))*1.25;let Oe=-_*We,ke=-X*We;const et=1.5,Ne=Math.hypot(Oe,ke,et);Oe/=Ne,ke/=Ne;let De=Oe*de+ke*he+et/Ne*ve;De<0&&(De=0);const Et=Math.min(1,.45+.55*Math.min(Ze/(k*.7),1));z[R]=Math.min(1.12,(.5+.75*De)*Et)}Fe=z,Y=document.createElement("canvas"),Y.width=s,Y.height=x;const J=Y.getContext("2d");if(J){const g=J.createImageData(s,x);for(let M=0;M<s*x;M++)l[M]&&(g.data[M*4]=255,g.data[M*4+1]=255,g.data[M*4+2]=255,g.data[M*4+3]=255);J.putImageData(g,0,0)}}function ht(){const e=Math.max(1.6,te*.6);pe=e;const o=[];for(let l=0;l<x;l+=e)for(let f=0;f<s;f+=e){const T=(W(Math.floor(f),Math.floor(l))-.5)*e*.9,C=(W(Math.floor(l),Math.floor(f))-.5)*e*.9,v=Math.round(f+T),F=Math.round(l+C);if(v<1||F<1||v>=s-1||F>=x-1)continue;const P=F*s+v;if(!Se[P])continue;const p=Math.atan2(xe[P],me[P]),d=.86+W(v*7,F*13)*.18;let w=Fe[P]*d;w=w<0?0:w>1.12?1.12:w,o.push({x:v,y:F,ang:p,idx:Math.min(19,Math.max(0,Math.round(w/1.12*19)))})}ge=o}function Ge(e,o){e.save(),e.translate(o.x,o.y),e.rotate(o.ang),e.drawImage(ne[o.idx],-se/2,-ce/2),e.restore()}function Le(){const e=O.getContext("2d");if(e)for(const o of ge)Ge(e,o)}function $e(){const e=O.getContext("2d");e&&e.clearRect(0,0,s,x)}function mt(e){if(!e.length)return[];const o=Math.max(4,pe*1.5),l=new Map,f=(p,d)=>p+","+d;e.forEach((p,d)=>{const w=f(Math.floor(p.x/o),Math.floor(p.y/o));let k=l.get(w);k||l.set(w,k=[]),k.push(d)});const T=pe*1.8*(pe*1.8);function C(p){const d=e[p],w=Math.floor(d.x/o),k=Math.floor(d.y/o),z=[];for(let de=-1;de<=1;de++)for(let he=-1;he<=1;he++){const ve=l.get(f(w+de,k+he));if(ve)for(const J of ve){if(J===p)continue;const g=e[J].x-d.x,M=e[J].y-d.y;g*g+M*M<=T&&z.push(J)}}return z}const v=new Uint8Array(e.length),F=[],P=e.map((p,d)=>d).sort((p,d)=>e[p].x+e[p].y-(e[d].x+e[d].y));for(const p of P){if(v[p])continue;let d=[p];for(v[p]=1;d.length;){F.push(d.map(k=>e[k]));const w=[];for(const k of d)for(const z of C(k))v[z]||(v[z]=1,w.push(z));d=w}}return F}function xt(){if($e(),N||!S){Le(),$.on=!1;return}$.rows=mt(ge),$.idx=0,$.acc=0,$.rate=u,$.on=$.rows.length>0}function yt(e){const o=O.getContext("2d");if(o)for(e>$.rows.length&&(e=$.rows.length);$.idx<e;){const l=$.rows[$.idx++];for(const f of l)Ge(o,f)}}function gt(e,o){const l=j.getContext("2d");if(!l||(l.clearRect(0,0,s,x),!b||!Y))return;const f=s*.32,T=l.createRadialGradient(e,o,0,e,o,f);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)"),l.fillStyle=T,l.fillRect(0,0,s,x),l.globalCompositeOperation="destination-in",l.drawImage(Y,0,0),l.globalCompositeOperation="source-over"}function pt(){A||!E||(A=document.createElement("span"),A.className=Te.caret,A.setAttribute("aria-hidden","true"),Object.assign(A.style,{position:"absolute",pointerEvents:"none",borderRadius:"1px",opacity:"0",background:`rgb(${K(B[0])},${K(B[1])},${K(B[2])})`}),L.appendChild(A),G.push(A))}function Ie(){if(!E||!A)return;const e=O.getContext("2d");if(!e)return;e.font=`${i} ${ee}px ${r}`;const o=e.measureText(n).width,l=(O.clientWidth||s)/s,f=ee*.7;A.style.left=(Ae+o+ee*.05)*l+"px",A.style.top=.5*(O.clientHeight||x)-f*l/2+"px",A.style.height=f*l+"px",A.style.width=Math.max(2,Math.round(ee*.02*l))+"px",A.style.background=`rgb(${K(B[0])},${K(B[1])},${K(B[2])})`}function re(){q||fe||(fe=!0,ue=0,Re=requestAnimationFrame(Ue))}function Ue(e){if(q){fe=!1;return}ue||(ue=e);const o=Math.min(.25,(e-ue)/1e3);ue=e,$.on&&($.acc+=$.rate*o,yt($.acc),$.idx>=$.rows.length&&($.on=!1)),Z&&Y&&(gt(U.set?U.x:s*.5,U.set?U.y:x*.45),Z=!1);const l=E&&Q;if(A&&(A.style.opacity=l&&Math.floor(e/530)%2===0?"1":"0"),!$.on&&!Z&&!l){fe=!1;return}Re=requestAnimationFrame(Ue)}function we(e){const o=L.getBoundingClientRect();U.x=(e.clientX-o.left)/(o.width||1)*s,U.y=(e.clientY-o.top)/(o.height||1)*x,U.set=!0,Z=!0,re()}function Me(){U.set=!1,Z=!0,re()}function wt(){y&&Ve(y.value,!0)}function Mt(e){e.key==="Enter"&&(e.preventDefault(),Be.replay())}function Ct(){Q=!0,re()}function vt(){Q=!1,A&&(A.style.opacity="0")}function Ke(e){e===E&&y||(E=e,e?(y||(y=document.createElement("input"),y.type="text",y.value=n,y.maxLength=64,y.setAttribute("aria-label","Embroidered text — type to change it"),y.setAttribute("autocomplete","off"),y.setAttribute("autocapitalize","off"),y.spellcheck=!1,Object.assign(y.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"}),y.addEventListener("input",wt),y.addEventListener("keydown",Mt),y.addEventListener("focus",Ct),y.addEventListener("blur",vt),L.appendChild(y),G.push(y)),pt(),Ie()):(y&&(y.remove(),y=null),Q=!1,A&&(A.style.opacity="0")))}function bt(e){if(e!==b)if(b=e,e)L.addEventListener("pointermove",we,{passive:!0}),L.addEventListener("pointerleave",Me,{passive:!0}),U.set=!1,Z=!0,re();else{L.removeEventListener("pointermove",we),L.removeEventListener("pointerleave",Me);const o=j.getContext("2d");o&&o.clearRect(0,0,s,x)}}function ie(e){ct(),ft(),ut(),dt(),ht(),e?xt():($e(),Le(),$.on=!1),y&&y.value!==n&&(y.value=n),Ie(),Z=!0,re()}function Ve(e,o){e=e??"",!(e===n&&H)&&(n=e,H&&(ie(!1),o&&m&&m(n)))}const Ce=new Set;function Ye(e,o,l){const f=`${o} 200px ${e}`;let T=!1;try{T=!!document.fonts&&document.fonts.check(f)}catch{T=!0}if(!document.fonts||T){l();return}let C=!1,v;const F=()=>{C||(C=!0,clearTimeout(v),Ce.delete(v),q||l())};document.fonts.load(f,n).then(()=>document.fonts.ready).then(F,F),v=setTimeout(F,1500),Ce.add(v)}function Tt(){q||(ie(!0),H=!0)}E&&(E=!1,Ke(!0)),b&&(L.addEventListener("pointermove",we,{passive:!0}),L.addEventListener("pointerleave",Me,{passive:!0})),Ye(I,i,Tt);let Pe,He=-1;function Je(){clearTimeout(Pe),Pe=setTimeout(()=>{if(q||!H)return;const e=Math.round(L.getBoundingClientRect().width);e!==He&&(He=e,ie(!1))},200)}window.addEventListener("resize",Je);const Be={get text(){return n},setText(e){if(!q){if(!H){n=e??"",y&&(y.value=n);return}Ve(e,!1)}},replay(){q||!H||ie(!0)},resize(){q||!H||ie(!1)},update(e){if(q)return;e.text!==void 0&&Be.setText(e.text);let o=!1,l=!1;if(e.font!==void 0&&e.font!==r&&(r=e.font,I=it(r),o=!0),e.weight!==void 0){const f=be(e.weight,1,1e3);f!==i&&(i=f,o=!0)}if(e.fill!==void 0){const f=be(e.fill,.05,1);f!==a&&(a=f,o=!0)}e.pitch!==void 0&&e.pitch!==c&&(c=e.pitch,o=!0),e.threadColor!==void 0&&(le(e.threadColor),l=!0),e.sewRate!==void 0&&(u=Math.max(1,e.sewRate)),e.animate!==void 0&&(S=e.animate),e.onTextChange!==void 0&&(m=e.onTextChange),e.sheen!==void 0&&bt(e.sheen),e.editable!==void 0&&Ke(e.editable),H&&(o?Ye(I,i,()=>{q||ie(!1)}):l&&(Xe(),$e(),Le(),Ie(),re()))},focus(){!q&&E&&(y==null||y.focus())},destroy(){if(!q){q=!0,fe=!1,cancelAnimationFrame(Re),clearTimeout(Pe);for(const e of Ce)clearTimeout(e);Ce.clear(),window.removeEventListener("resize",Je),L.removeEventListener("pointermove",we),L.removeEventListener("pointerleave",Me);for(const e of G)e.remove();ne=[],ge=[],$.rows=[],Se=new Uint8Array(0),Fe=new Float32Array(0),me=new Float32Array(0),xe=new Float32Array(0),Y=oe=null,ye=null,A=null,y=null}}};return Be}function lt(h){const t=V.useRef(null),n=V.useRef(null),r=V.useRef(h);r.current=h;const i=V.useRef(h.onTextChange);i.current=h.onTextChange;const{text:a,font:u,weight:b,threadColor:S,pitch:E,fill:c,animate:m,sewRate:I,sheen:N,editable:B,reducedMotion:ae}=h;return V.useLayoutEffect(()=>{const D=t.current;if(!D)return;const le=at(D,{...r.current,onTextChange:y=>{var A;return(A=i.current)==null?void 0:A.call(i,y)}});n.current=le;let G=0,O=0,L=!0,j;return typeof ResizeObserver<"u"&&(j=new ResizeObserver(y=>{const A=Math.round(y[0].contentRect.width);if(L){L=!1,O=A;return}A!==O&&(O=A,cancelAnimationFrame(G),G=requestAnimationFrame(()=>{var Q;return(Q=n.current)==null?void 0:Q.resize()}))}),j.observe(D)),()=>{j==null||j.disconnect(),cancelAnimationFrame(G),le.destroy(),n.current=null}},[ae]),V.useEffect(()=>{var D;(D=n.current)==null||D.update({font:u,weight:b,threadColor:S,pitch:E,fill:c,animate:m,sewRate:I,sheen:N,editable:B})},[u,b,S,E,c,m,I,N,B]),V.useEffect(()=>{var D;(D=n.current)==null||D.setText(a)},[a]),t}const st=V.forwardRef(function({className:t,style:n,as:r="div","aria-label":i,role:a,"aria-describedby":u,...b},S){const E=lt(b),c=V.useCallback(m=>{E.current=m,typeof S=="function"?S(m):S&&(S.current=m)},[E,S]);return At.jsx(r,{ref:c,className:t,style:n,role:b.editable?a:a??"img","aria-label":b.editable?i:i??b.text,"aria-describedby":u})});st.displayName="ThreadText";exports.THREAD_TEXT_CLASSES=Te;exports.ThreadText=st;exports.createThreadText=at;exports.useThreadText=lt;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useRef as
|
|
2
|
-
import { jsx as
|
|
3
|
-
const
|
|
1
|
+
import { useRef as vt, useLayoutEffect as Te, useEffect as ee, forwardRef as Ae, useCallback as Ee } from "react";
|
|
2
|
+
import { jsx as Se } from "react/jsx-runtime";
|
|
3
|
+
const Dt = {
|
|
4
4
|
/** Base canvas: the baked satin stitches (transparent ground). */
|
|
5
5
|
bg: "tt-bg",
|
|
6
6
|
/** Overlay canvas: cursor sheen (`mix-blend-mode: screen`). */
|
|
@@ -8,80 +8,80 @@ const Bt = {
|
|
|
8
8
|
/** Blinking text caret shown in editable mode. */
|
|
9
9
|
caret: "tt-caret"
|
|
10
10
|
};
|
|
11
|
-
function
|
|
12
|
-
let
|
|
13
|
-
return
|
|
11
|
+
function H(h, e) {
|
|
12
|
+
let n = Math.imul(h | 0, 374761393) + Math.imul(e | 0, 668265263) | 0;
|
|
13
|
+
return n = Math.imul(n ^ n >>> 13, 1274126177), ((n ^ n >>> 16) >>> 0) / 4294967295;
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
const
|
|
17
|
-
return
|
|
15
|
+
function ne(h, e) {
|
|
16
|
+
const n = Math.floor(h), r = Math.floor(e), i = h - n, a = e - r, u = i * i * (3 - 2 * i), b = a * a * (3 - 2 * a), S = H(n, r), A = H(n + 1, r), c = H(n, r + 1), m = H(n + 1, r + 1);
|
|
17
|
+
return S + (A - S) * u + (c - S) * b + (S - A - c + m) * u * b;
|
|
18
18
|
}
|
|
19
|
-
const
|
|
20
|
-
function
|
|
19
|
+
const Tt = 1e20;
|
|
20
|
+
function oe(h, e, n, r, i) {
|
|
21
21
|
let a = 0;
|
|
22
|
-
r[0] = 0, i[0] = -
|
|
23
|
-
for (let
|
|
24
|
-
let
|
|
25
|
-
for (;
|
|
26
|
-
a--,
|
|
27
|
-
a++, r[a] =
|
|
22
|
+
r[0] = 0, i[0] = -Tt, i[1] = Tt;
|
|
23
|
+
for (let u = 1; u < e; u++) {
|
|
24
|
+
let b = (h[u] + u * u - (h[r[a]] + r[a] * r[a])) / (2 * u - 2 * r[a]);
|
|
25
|
+
for (; b <= i[a]; )
|
|
26
|
+
a--, b = (h[u] + u * u - (h[r[a]] + r[a] * r[a])) / (2 * u - 2 * r[a]);
|
|
27
|
+
a++, r[a] = u, i[a] = b, i[a + 1] = Tt;
|
|
28
28
|
}
|
|
29
29
|
a = 0;
|
|
30
|
-
for (let
|
|
31
|
-
for (; i[a + 1] <
|
|
32
|
-
|
|
30
|
+
for (let u = 0; u < e; u++) {
|
|
31
|
+
for (; i[a + 1] < u; ) a++;
|
|
32
|
+
n[u] = (u - r[a]) * (u - r[a]) + h[r[a]];
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
function
|
|
36
|
-
const r = new Float64Array(e *
|
|
37
|
-
for (let c = 0; c < e *
|
|
38
|
-
const i = Math.max(e,
|
|
35
|
+
function Fe(h, e, n) {
|
|
36
|
+
const r = new Float64Array(e * n);
|
|
37
|
+
for (let c = 0; c < e * n; c++) r[c] = h[c] ? Tt : 0;
|
|
38
|
+
const i = Math.max(e, n), a = new Float64Array(i), u = new Float64Array(i), b = new Int32Array(i), S = new Float64Array(i + 1);
|
|
39
39
|
for (let c = 0; c < e; c++) {
|
|
40
|
-
for (let
|
|
41
|
-
|
|
42
|
-
for (let
|
|
43
|
-
}
|
|
44
|
-
for (let c = 0; c <
|
|
45
|
-
for (let
|
|
46
|
-
|
|
47
|
-
for (let
|
|
48
|
-
}
|
|
49
|
-
const
|
|
50
|
-
for (let c = 0; c < e *
|
|
51
|
-
return
|
|
40
|
+
for (let m = 0; m < n; m++) a[m] = r[m * e + c];
|
|
41
|
+
oe(a, n, u, b, S);
|
|
42
|
+
for (let m = 0; m < n; m++) r[m * e + c] = u[m];
|
|
43
|
+
}
|
|
44
|
+
for (let c = 0; c < n; c++) {
|
|
45
|
+
for (let m = 0; m < e; m++) a[m] = r[c * e + m];
|
|
46
|
+
oe(a, e, u, b, S);
|
|
47
|
+
for (let m = 0; m < e; m++) r[c * e + m] = u[m];
|
|
48
|
+
}
|
|
49
|
+
const A = new Float32Array(e * n);
|
|
50
|
+
for (let c = 0; c < e * n; c++) A[c] = Math.sqrt(r[c]);
|
|
51
|
+
return A;
|
|
52
52
|
}
|
|
53
|
-
function
|
|
54
|
-
let a = Float32Array.from(
|
|
55
|
-
const
|
|
56
|
-
for (let
|
|
57
|
-
for (let c = 0; c <
|
|
58
|
-
const
|
|
59
|
-
let
|
|
60
|
-
for (let
|
|
61
|
-
for (let
|
|
62
|
-
|
|
53
|
+
function re(h, e, n, r, i) {
|
|
54
|
+
let a = Float32Array.from(h);
|
|
55
|
+
const u = new Float32Array(e * n), b = 1 / (2 * r + 1), S = (A, c) => A < 0 ? 0 : A > c ? c : A;
|
|
56
|
+
for (let A = 0; A < i; A++) {
|
|
57
|
+
for (let c = 0; c < n; c++) {
|
|
58
|
+
const m = c * e;
|
|
59
|
+
let I = 0;
|
|
60
|
+
for (let O = -r; O <= r; O++) I += a[m + S(O, e - 1)];
|
|
61
|
+
for (let O = 0; O < e; O++)
|
|
62
|
+
u[m + O] = I * b, I += a[m + S(O + r + 1, e - 1)] - a[m + S(O - r, e - 1)];
|
|
63
63
|
}
|
|
64
64
|
for (let c = 0; c < e; c++) {
|
|
65
|
-
let
|
|
66
|
-
for (let
|
|
67
|
-
for (let
|
|
68
|
-
a[
|
|
65
|
+
let m = 0;
|
|
66
|
+
for (let I = -r; I <= r; I++) m += u[S(I, n - 1) * e + c];
|
|
67
|
+
for (let I = 0; I < n; I++)
|
|
68
|
+
a[I * e + c] = m * b, m += u[S(I + r + 1, n - 1) * e + c] - u[S(I - r, n - 1) * e + c];
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
return a;
|
|
72
72
|
}
|
|
73
|
-
function
|
|
74
|
-
if (!
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
let i =
|
|
73
|
+
function ie(h, e) {
|
|
74
|
+
if (!h) return e;
|
|
75
|
+
const n = h.trim();
|
|
76
|
+
if (n[0] === "#") {
|
|
77
|
+
let i = n.slice(1);
|
|
78
78
|
if (i.length === 3 && (i = i[0] + i[0] + i[1] + i[1] + i[2] + i[2]), i.length >= 6) {
|
|
79
|
-
const a = parseInt(i.slice(0, 2), 16),
|
|
80
|
-
if (!Number.isNaN(a) && !Number.isNaN(
|
|
79
|
+
const a = parseInt(i.slice(0, 2), 16), u = parseInt(i.slice(2, 4), 16), b = parseInt(i.slice(4, 6), 16);
|
|
80
|
+
if (!Number.isNaN(a) && !Number.isNaN(u) && !Number.isNaN(b)) return [a, u, b];
|
|
81
81
|
}
|
|
82
82
|
return e;
|
|
83
83
|
}
|
|
84
|
-
const r =
|
|
84
|
+
const r = n.match(/rgba?\(([^)]+)\)/i);
|
|
85
85
|
if (r) {
|
|
86
86
|
const i = r[1].split(",").map((a) => parseFloat(a));
|
|
87
87
|
if (i.length >= 3 && i.slice(0, 3).every((a) => !Number.isNaN(a)))
|
|
@@ -89,14 +89,17 @@ function te(m, e) {
|
|
|
89
89
|
}
|
|
90
90
|
return e;
|
|
91
91
|
}
|
|
92
|
-
function K(
|
|
93
|
-
return
|
|
92
|
+
function K(h) {
|
|
93
|
+
return h < 0 ? 0 : h > 255 ? 255 : Math.round(h);
|
|
94
94
|
}
|
|
95
|
-
function
|
|
96
|
-
return
|
|
95
|
+
function bt(h, e, n) {
|
|
96
|
+
return h < e ? e : h > n ? n : h;
|
|
97
97
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
98
|
+
function ae(h) {
|
|
99
|
+
return (h.split(",")[0] || "serif").trim().replace(/^["']|["']$/g, "");
|
|
100
|
+
}
|
|
101
|
+
function Le(h, e) {
|
|
102
|
+
if (typeof window > "u" || typeof document > "u" || !h)
|
|
100
103
|
return { setText() {
|
|
101
104
|
}, replay() {
|
|
102
105
|
}, resize() {
|
|
@@ -106,388 +109,418 @@ function pe(m, e) {
|
|
|
106
109
|
}, get text() {
|
|
107
110
|
return e.text ?? "";
|
|
108
111
|
} };
|
|
109
|
-
let
|
|
110
|
-
const
|
|
111
|
-
let
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
let
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
let
|
|
122
|
-
const
|
|
123
|
-
let
|
|
124
|
-
function
|
|
125
|
-
const t =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
112
|
+
let n = e.text ?? "", r = e.font ?? "Georgia, serif", i = bt(e.weight ?? 680, 1, 1e3), a = bt(e.fill ?? 0.9, 0.05, 1), u = Math.max(1, e.sewRate ?? 110), b = e.sheen ?? !0, S = e.animate ?? !0, A = e.editable ?? !1, c = e.pitch, m = e.onTextChange, I = ae(r);
|
|
113
|
+
const O = e.reducedMotion ?? !!(window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches);
|
|
114
|
+
let B = ie(e.threadColor ?? "#fffbf3", [255, 251, 243]), it = [0, 0, 0], D = [0, 0, 0];
|
|
115
|
+
function at(t) {
|
|
116
|
+
B = ie(t, [255, 251, 243]), it = [B[0] * 0.585, B[1] * 0.585, B[2] * 0.585], D = [B[0] * 0.47, B[1] * 0.47, B[2] * 0.47];
|
|
117
|
+
}
|
|
118
|
+
at(e.threadColor ?? "#fffbf3");
|
|
119
|
+
const U = [];
|
|
120
|
+
let k, R;
|
|
121
|
+
h instanceof HTMLCanvasElement ? (k = h, R = h.parentElement ?? h) : (R = h, k = document.createElement("canvas"), U.push(k), R.appendChild(k)), k.classList.add(Dt.bg);
|
|
122
|
+
const j = document.createElement("canvas");
|
|
123
|
+
U.push(j), j.classList.add(Dt.fx), R.appendChild(j), getComputedStyle(R).position === "static" && (R.style.position = "relative"), k.style.display = "block", k.style.width = "100%", Object.assign(j.style, { position: "absolute", inset: "0", width: "100%", pointerEvents: "none", mixBlendMode: "screen" });
|
|
124
|
+
let y = null, E = null, Q = !1, s = 0, x = 0, W = 0, At = 0, tt = 4, et = [], lt = 0, st = 0, jt = -1, zt = "", qt = -1, _t = -1, Et = new Uint8Array(0), St = new Float32Array(0), ht = new Float32Array(0), mt = new Float32Array(0), V = null, nt = null, xt = null, yt = [], gt = 3;
|
|
125
|
+
const $ = { rows: [], idx: 0, acc: 0, rate: 0, on: !1 }, X = { x: 0, y: 0, set: !1 };
|
|
126
|
+
let Z = !0, Ft = 0, ct = !1, ft = 0, z = !1, Y = !1;
|
|
127
|
+
function le() {
|
|
128
|
+
const t = R.getBoundingClientRect(), o = Math.max(1, Math.round(t.width || Math.min(window.innerWidth * 0.95, 1240))), l = n || "Ag", f = k.getContext("2d");
|
|
129
|
+
f && (f.textBaseline = "middle");
|
|
130
|
+
let T = 100;
|
|
131
|
+
f && (f.font = `${i} 100px ${r}`, T = f.measureText(l).width || 100);
|
|
132
|
+
const C = Math.max(8, 100 * (o * a) / T);
|
|
133
|
+
let v = C * 0.62, F = C * 0.62, P = o * a;
|
|
134
|
+
if (f) {
|
|
135
|
+
f.font = `${i} ${C}px ${r}`;
|
|
136
|
+
const w = f.measureText(l);
|
|
137
|
+
P = w.width || P, w.actualBoundingBoxAscent > 0 && (v = w.actualBoundingBoxAscent), w.actualBoundingBoxDescent > 0 && (F = w.actualBoundingBoxDescent);
|
|
133
138
|
}
|
|
134
|
-
const
|
|
139
|
+
const p = Math.max(1, Math.round(2 * Math.max(v, F) * 1.1));
|
|
135
140
|
let d = Math.min(window.devicePixelRatio || 1, 1.7);
|
|
136
|
-
for (;
|
|
137
|
-
s = Math.max(1, Math.round(
|
|
138
|
-
for (const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
function
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
function
|
|
146
|
-
const t = Math.max(7,
|
|
147
|
-
|
|
141
|
+
for (; o * d * p * d > 9e5 && d > 0.4; ) d -= 0.1;
|
|
142
|
+
s = Math.max(1, Math.round(o * d)), x = Math.max(1, Math.round(p * d)), W = Math.max(4, Math.round(C * d)), At = Math.round(s / 2 - P * d / 2);
|
|
143
|
+
for (const w of [k, j])
|
|
144
|
+
w.width = s, w.height = x, w.style.height = p + "px";
|
|
145
|
+
R.style.height = p + "px", tt = c ?? Math.max(3, x * 95e-4);
|
|
146
|
+
}
|
|
147
|
+
function se() {
|
|
148
|
+
nt && qt === s && _t === x || (nt = document.createElement("canvas"), nt.width = s, nt.height = x, xt = nt.getContext("2d", { willReadFrequently: !0 }), qt = s, _t = x);
|
|
149
|
+
}
|
|
150
|
+
function Gt() {
|
|
151
|
+
const t = Math.max(7, tt * 2.5), o = Math.max(3.2, tt * 1.3);
|
|
152
|
+
lt = Math.ceil(t) + 2, st = Math.ceil(o) + 2, et = [];
|
|
148
153
|
for (let l = 0; l < 20; l++) {
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
if (!
|
|
153
|
-
et.push(
|
|
154
|
+
const f = 0.34 + l / 19 * 0.82, T = document.createElement("canvas");
|
|
155
|
+
T.width = lt, T.height = st;
|
|
156
|
+
const C = T.getContext("2d");
|
|
157
|
+
if (!C) {
|
|
158
|
+
et.push(T);
|
|
154
159
|
continue;
|
|
155
160
|
}
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
const d =
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
161
|
+
const v = lt / 2, F = st / 2, P = C.createLinearGradient(0, F - o / 2, 0, F + o / 2), p = (N, q) => `rgba(${K(N[0] * f)},${K(N[1] * f)},${K(N[2] * f)},${q})`;
|
|
162
|
+
P.addColorStop(0, p(D, 0)), P.addColorStop(0.16, p(it, 1)), P.addColorStop(0.5, p(B, 1)), P.addColorStop(0.84, p(it, 1)), P.addColorStop(1, p(D, 0)), C.fillStyle = P, C.beginPath();
|
|
163
|
+
const d = o / 2;
|
|
164
|
+
C.moveTo(v - t / 2 + d, F - d), C.lineTo(v + t / 2 - d, F - d), C.arc(v + t / 2 - d, F, d, -Math.PI / 2, Math.PI / 2), C.lineTo(v - t / 2 + d, F + d), C.arc(v - t / 2 + d, F, d, Math.PI / 2, -Math.PI / 2), C.closePath(), C.fill(), C.globalCompositeOperation = "destination-in";
|
|
165
|
+
const w = C.createLinearGradient(v - t / 2, 0, v + t / 2, 0);
|
|
166
|
+
w.addColorStop(0, "rgba(0,0,0,0)"), w.addColorStop(0.22, "rgba(0,0,0,1)"), w.addColorStop(0.78, "rgba(0,0,0,1)"), w.addColorStop(1, "rgba(0,0,0,0)"), C.fillStyle = w, C.fillRect(0, 0, lt, st), et.push(T);
|
|
162
167
|
}
|
|
168
|
+
jt = tt, zt = B.join(",");
|
|
163
169
|
}
|
|
164
|
-
function
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
function ce() {
|
|
171
|
+
et.length && jt === tt && zt === B.join(",") || Gt();
|
|
172
|
+
}
|
|
173
|
+
function fe() {
|
|
174
|
+
if (!xt) return;
|
|
175
|
+
const t = xt;
|
|
176
|
+
t.clearRect(0, 0, s, x), t.fillStyle = "#fff", t.textAlign = "left", t.textBaseline = "middle", t.font = `${i} ${W}px ${r}`, t.fillText(n, At, x * 0.5);
|
|
177
|
+
const o = t.getImageData(0, 0, s, x).data, l = new Uint8Array(s * x);
|
|
178
|
+
for (let g = 0; g < x; g++) for (let M = 0; M < s; M++) {
|
|
179
|
+
const L = g * s + M, _ = o[L * 4 + 3] / 255, G = ne(M * 0.5, g * 0.5) * 0.22 + ne(M * 1.8, g * 1.8) * 0.1;
|
|
180
|
+
l[L] = _ > 0.5 + (G - 0.16) ? 1 : 0;
|
|
172
181
|
}
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
for (let
|
|
176
|
-
const
|
|
177
|
-
|
|
182
|
+
Et = l;
|
|
183
|
+
const f = Fe(l, s, x), T = new Float32Array(s * x);
|
|
184
|
+
for (let g = 1; g < x - 1; g++) for (let M = 1; M < s - 1; M++) {
|
|
185
|
+
const L = g * s + M;
|
|
186
|
+
T[L] = (f[L] * 4 + f[L - 1] + f[L + 1] + f[L - s] + f[L + s]) / 8;
|
|
178
187
|
}
|
|
179
|
-
const
|
|
180
|
-
for (let
|
|
181
|
-
const
|
|
182
|
-
if (!l[
|
|
183
|
-
const
|
|
184
|
-
L
|
|
188
|
+
const C = new Float32Array(s * x), v = new Float32Array(s * x), F = new Float32Array(s * x), P = new Float32Array(s * x);
|
|
189
|
+
for (let g = 1; g < x - 1; g++) for (let M = 1; M < s - 1; M++) {
|
|
190
|
+
const L = g * s + M;
|
|
191
|
+
if (!l[L]) continue;
|
|
192
|
+
const _ = (T[L + 1] - T[L - 1]) * 0.5, G = (T[L + s] - T[L - s]) * 0.5;
|
|
193
|
+
F[L] = _, P[L] = G, C[L] = _ * _ - G * G, v[L] = 2 * _ * G;
|
|
185
194
|
}
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
for (let
|
|
189
|
-
if (!l[
|
|
190
|
-
const M = 0.5 * Math.atan2(
|
|
191
|
-
|
|
195
|
+
const p = Math.max(7, Math.round(x * 0.05)), d = re(C, s, x, p, 2), w = re(v, s, x, p, 2);
|
|
196
|
+
ht = new Float32Array(s * x), mt = new Float32Array(s * x);
|
|
197
|
+
for (let g = 0; g < s * x; g++) {
|
|
198
|
+
if (!l[g]) continue;
|
|
199
|
+
const M = 0.5 * Math.atan2(w[g], d[g]);
|
|
200
|
+
ht[g] = Math.cos(M), mt[g] = Math.sin(M);
|
|
192
201
|
}
|
|
193
|
-
const
|
|
194
|
-
for (let
|
|
195
|
-
const
|
|
196
|
-
if (!l[
|
|
197
|
-
let
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
let
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
let
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
|
|
202
|
+
const N = Math.max(9, x * 0.04), q = new Float32Array(s * x), ut = -0.45, dt = -0.62, Ct = 0.64;
|
|
203
|
+
for (let g = 1; g < x - 1; g++) for (let M = 1; M < s - 1; M++) {
|
|
204
|
+
const L = g * s + M;
|
|
205
|
+
if (!l[L]) continue;
|
|
206
|
+
let _ = F[L], G = P[L];
|
|
207
|
+
const Zt = Math.hypot(_, G) || 1;
|
|
208
|
+
_ /= Zt, G /= Zt;
|
|
209
|
+
const Ht = T[L], Wt = (1 - Math.min(Ht / N, 1)) * 1.25;
|
|
210
|
+
let Bt = -_ * Wt, kt = -G * Wt;
|
|
211
|
+
const te = 1.5, Nt = Math.hypot(Bt, kt, te);
|
|
212
|
+
Bt /= Nt, kt /= Nt;
|
|
213
|
+
let Ot = Bt * ut + kt * dt + te / Nt * Ct;
|
|
214
|
+
Ot < 0 && (Ot = 0);
|
|
215
|
+
const be = Math.min(1, 0.45 + 0.55 * Math.min(Ht / (N * 0.7), 1));
|
|
216
|
+
q[L] = Math.min(1.12, (0.5 + 0.75 * Ot) * be);
|
|
208
217
|
}
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
212
|
-
const
|
|
213
|
-
for (let M = 0; M < s *
|
|
214
|
-
|
|
218
|
+
St = q, V = document.createElement("canvas"), V.width = s, V.height = x;
|
|
219
|
+
const J = V.getContext("2d");
|
|
220
|
+
if (J) {
|
|
221
|
+
const g = J.createImageData(s, x);
|
|
222
|
+
for (let M = 0; M < s * x; M++) l[M] && (g.data[M * 4] = 255, g.data[M * 4 + 1] = 255, g.data[M * 4 + 2] = 255, g.data[M * 4 + 3] = 255);
|
|
223
|
+
J.putImageData(g, 0, 0);
|
|
215
224
|
}
|
|
216
225
|
}
|
|
217
|
-
function
|
|
218
|
-
const t = Math.max(1.6,
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
for (let l = 0; l <
|
|
222
|
-
const
|
|
223
|
-
if (
|
|
224
|
-
const
|
|
225
|
-
if (!
|
|
226
|
-
const
|
|
227
|
-
let
|
|
228
|
-
|
|
226
|
+
function ue() {
|
|
227
|
+
const t = Math.max(1.6, tt * 0.6);
|
|
228
|
+
gt = t;
|
|
229
|
+
const o = [];
|
|
230
|
+
for (let l = 0; l < x; l += t) for (let f = 0; f < s; f += t) {
|
|
231
|
+
const T = (H(Math.floor(f), Math.floor(l)) - 0.5) * t * 0.9, C = (H(Math.floor(l), Math.floor(f)) - 0.5) * t * 0.9, v = Math.round(f + T), F = Math.round(l + C);
|
|
232
|
+
if (v < 1 || F < 1 || v >= s - 1 || F >= x - 1) continue;
|
|
233
|
+
const P = F * s + v;
|
|
234
|
+
if (!Et[P]) continue;
|
|
235
|
+
const p = Math.atan2(mt[P], ht[P]), d = 0.86 + H(v * 7, F * 13) * 0.18;
|
|
236
|
+
let w = St[P] * d;
|
|
237
|
+
w = w < 0 ? 0 : w > 1.12 ? 1.12 : w, o.push({ x: v, y: F, ang: p, idx: Math.min(19, Math.max(0, Math.round(w / 1.12 * 19))) });
|
|
229
238
|
}
|
|
230
|
-
|
|
239
|
+
yt = o;
|
|
231
240
|
}
|
|
232
|
-
function
|
|
233
|
-
t.save(), t.translate(
|
|
241
|
+
function Ut(t, o) {
|
|
242
|
+
t.save(), t.translate(o.x, o.y), t.rotate(o.ang), t.drawImage(et[o.idx], -lt / 2, -st / 2), t.restore();
|
|
234
243
|
}
|
|
235
|
-
function
|
|
236
|
-
const t =
|
|
244
|
+
function Lt() {
|
|
245
|
+
const t = k.getContext("2d");
|
|
237
246
|
if (t)
|
|
238
|
-
for (const
|
|
247
|
+
for (const o of yt) Ut(t, o);
|
|
239
248
|
}
|
|
240
|
-
function
|
|
241
|
-
const t =
|
|
242
|
-
t && t.clearRect(0, 0, s,
|
|
249
|
+
function Rt() {
|
|
250
|
+
const t = k.getContext("2d");
|
|
251
|
+
t && t.clearRect(0, 0, s, x);
|
|
243
252
|
}
|
|
244
|
-
function
|
|
253
|
+
function de(t) {
|
|
245
254
|
if (!t.length) return [];
|
|
246
|
-
const
|
|
247
|
-
t.forEach((
|
|
248
|
-
const
|
|
249
|
-
let
|
|
250
|
-
|
|
255
|
+
const o = Math.max(4, gt * 1.5), l = /* @__PURE__ */ new Map(), f = (p, d) => p + "," + d;
|
|
256
|
+
t.forEach((p, d) => {
|
|
257
|
+
const w = f(Math.floor(p.x / o), Math.floor(p.y / o));
|
|
258
|
+
let N = l.get(w);
|
|
259
|
+
N || l.set(w, N = []), N.push(d);
|
|
251
260
|
});
|
|
252
|
-
const
|
|
253
|
-
function
|
|
254
|
-
const d = t[
|
|
255
|
-
for (let
|
|
256
|
-
const
|
|
257
|
-
if (
|
|
258
|
-
for (const
|
|
259
|
-
if (
|
|
260
|
-
const
|
|
261
|
-
|
|
261
|
+
const T = gt * 1.8 * (gt * 1.8);
|
|
262
|
+
function C(p) {
|
|
263
|
+
const d = t[p], w = Math.floor(d.x / o), N = Math.floor(d.y / o), q = [];
|
|
264
|
+
for (let ut = -1; ut <= 1; ut++) for (let dt = -1; dt <= 1; dt++) {
|
|
265
|
+
const Ct = l.get(f(w + ut, N + dt));
|
|
266
|
+
if (Ct)
|
|
267
|
+
for (const J of Ct) {
|
|
268
|
+
if (J === p) continue;
|
|
269
|
+
const g = t[J].x - d.x, M = t[J].y - d.y;
|
|
270
|
+
g * g + M * M <= T && q.push(J);
|
|
262
271
|
}
|
|
263
272
|
}
|
|
264
|
-
return
|
|
273
|
+
return q;
|
|
265
274
|
}
|
|
266
|
-
const
|
|
267
|
-
for (const
|
|
268
|
-
if (
|
|
269
|
-
let d = [
|
|
270
|
-
for (
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
for (const
|
|
274
|
-
d =
|
|
275
|
+
const v = new Uint8Array(t.length), F = [], P = t.map((p, d) => d).sort((p, d) => t[p].x + t[p].y - (t[d].x + t[d].y));
|
|
276
|
+
for (const p of P) {
|
|
277
|
+
if (v[p]) continue;
|
|
278
|
+
let d = [p];
|
|
279
|
+
for (v[p] = 1; d.length; ) {
|
|
280
|
+
F.push(d.map((N) => t[N]));
|
|
281
|
+
const w = [];
|
|
282
|
+
for (const N of d) for (const q of C(N)) v[q] || (v[q] = 1, w.push(q));
|
|
283
|
+
d = w;
|
|
275
284
|
}
|
|
276
285
|
}
|
|
277
|
-
return
|
|
286
|
+
return F;
|
|
278
287
|
}
|
|
279
|
-
function
|
|
280
|
-
if (
|
|
281
|
-
|
|
288
|
+
function he() {
|
|
289
|
+
if (Rt(), O || !S) {
|
|
290
|
+
Lt(), $.on = !1;
|
|
282
291
|
return;
|
|
283
292
|
}
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
function
|
|
287
|
-
const
|
|
288
|
-
if (
|
|
289
|
-
for (t >
|
|
290
|
-
const l =
|
|
291
|
-
for (const
|
|
293
|
+
$.rows = de(yt), $.idx = 0, $.acc = 0, $.rate = u, $.on = $.rows.length > 0;
|
|
294
|
+
}
|
|
295
|
+
function me(t) {
|
|
296
|
+
const o = k.getContext("2d");
|
|
297
|
+
if (o)
|
|
298
|
+
for (t > $.rows.length && (t = $.rows.length); $.idx < t; ) {
|
|
299
|
+
const l = $.rows[$.idx++];
|
|
300
|
+
for (const f of l) Ut(o, f);
|
|
292
301
|
}
|
|
293
302
|
}
|
|
294
|
-
function
|
|
295
|
-
const l =
|
|
296
|
-
if (!l || (l.clearRect(0, 0, s,
|
|
297
|
-
const
|
|
298
|
-
|
|
303
|
+
function xe(t, o) {
|
|
304
|
+
const l = j.getContext("2d");
|
|
305
|
+
if (!l || (l.clearRect(0, 0, s, x), !b || !V)) return;
|
|
306
|
+
const f = s * 0.32, T = l.createRadialGradient(t, o, 0, t, o, f);
|
|
307
|
+
T.addColorStop(0, "rgba(255,250,238,0.18)"), T.addColorStop(0.5, "rgba(255,250,238,0.055)"), T.addColorStop(1, "rgba(255,250,238,0)"), l.fillStyle = T, l.fillRect(0, 0, s, x), l.globalCompositeOperation = "destination-in", l.drawImage(V, 0, 0), l.globalCompositeOperation = "source-over";
|
|
299
308
|
}
|
|
300
|
-
function
|
|
301
|
-
|
|
309
|
+
function ye() {
|
|
310
|
+
E || !A || (E = document.createElement("span"), E.className = Dt.caret, E.setAttribute("aria-hidden", "true"), Object.assign(E.style, { position: "absolute", pointerEvents: "none", borderRadius: "1px", opacity: "0", background: `rgb(${K(B[0])},${K(B[1])},${K(B[2])})` }), R.appendChild(E), U.push(E));
|
|
302
311
|
}
|
|
303
|
-
function
|
|
304
|
-
if (!
|
|
305
|
-
const t =
|
|
312
|
+
function $t() {
|
|
313
|
+
if (!A || !E) return;
|
|
314
|
+
const t = k.getContext("2d");
|
|
306
315
|
if (!t) return;
|
|
307
|
-
t.font = `${i} ${
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
function
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const n = O.getBoundingClientRect();
|
|
319
|
-
V.x = (t.clientX - n.left) / (n.width || 1) * s, V.y = (t.clientY - n.top) / (n.height || 1) * h, V.set = !0, H = !0;
|
|
320
|
-
}
|
|
321
|
-
function zt(t) {
|
|
322
|
-
if (!(!C || t.metaKey || t.ctrlKey || t.altKey)) {
|
|
323
|
-
if (t.key === "Backspace") {
|
|
324
|
-
t.preventDefault(), Ft(o.slice(0, -1), !0);
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
if (t.key === "Enter") {
|
|
328
|
-
t.preventDefault(), Rt.replay();
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
[...t.key].length === 1 && (t.preventDefault(), Ft(o + t.key, !0));
|
|
316
|
+
t.font = `${i} ${W}px ${r}`;
|
|
317
|
+
const o = t.measureText(n).width, l = (k.clientWidth || s) / s, f = W * 0.7;
|
|
318
|
+
E.style.left = (At + o + W * 0.05) * l + "px", E.style.top = 0.5 * (k.clientHeight || x) - f * l / 2 + "px", E.style.height = f * l + "px", E.style.width = Math.max(2, Math.round(W * 0.02 * l)) + "px", E.style.background = `rgb(${K(B[0])},${K(B[1])},${K(B[2])})`;
|
|
319
|
+
}
|
|
320
|
+
function ot() {
|
|
321
|
+
z || ct || (ct = !0, ft = 0, Ft = requestAnimationFrame(Xt));
|
|
322
|
+
}
|
|
323
|
+
function Xt(t) {
|
|
324
|
+
if (z) {
|
|
325
|
+
ct = !1;
|
|
326
|
+
return;
|
|
332
327
|
}
|
|
328
|
+
ft || (ft = t);
|
|
329
|
+
const o = Math.min(0.25, (t - ft) / 1e3);
|
|
330
|
+
ft = t, $.on && ($.acc += $.rate * o, me($.acc), $.idx >= $.rows.length && ($.on = !1)), Z && V && (xe(X.set ? X.x : s * 0.5, X.set ? X.y : x * 0.45), Z = !1);
|
|
331
|
+
const l = A && Q;
|
|
332
|
+
if (E && (E.style.opacity = l && Math.floor(t / 530) % 2 === 0 ? "1" : "0"), !$.on && !Z && !l) {
|
|
333
|
+
ct = !1;
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
Ft = requestAnimationFrame(Xt);
|
|
333
337
|
}
|
|
334
|
-
function
|
|
335
|
-
|
|
338
|
+
function pt(t) {
|
|
339
|
+
const o = R.getBoundingClientRect();
|
|
340
|
+
X.x = (t.clientX - o.left) / (o.width || 1) * s, X.y = (t.clientY - o.top) / (o.height || 1) * x, X.set = !0, Z = !0, ot();
|
|
336
341
|
}
|
|
337
|
-
function
|
|
338
|
-
|
|
342
|
+
function wt() {
|
|
343
|
+
X.set = !1, Z = !0, ot();
|
|
339
344
|
}
|
|
340
|
-
function
|
|
341
|
-
|
|
345
|
+
function ge() {
|
|
346
|
+
y && Vt(y.value, !0);
|
|
342
347
|
}
|
|
343
|
-
function
|
|
344
|
-
|
|
348
|
+
function pe(t) {
|
|
349
|
+
t.key === "Enter" && (t.preventDefault(), Pt.replay());
|
|
345
350
|
}
|
|
346
|
-
function
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
351
|
+
function we() {
|
|
352
|
+
Q = !0, ot();
|
|
353
|
+
}
|
|
354
|
+
function Me() {
|
|
355
|
+
Q = !1, E && (E.style.opacity = "0");
|
|
356
|
+
}
|
|
357
|
+
function Kt(t) {
|
|
358
|
+
t === A && y || (A = t, t ? (y || (y = document.createElement("input"), y.type = "text", y.value = n, y.maxLength = 64, y.setAttribute("aria-label", "Embroidered text — type to change it"), y.setAttribute("autocomplete", "off"), y.setAttribute("autocapitalize", "off"), y.spellcheck = !1, Object.assign(y.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" }), y.addEventListener("input", ge), y.addEventListener("keydown", pe), y.addEventListener("focus", we), y.addEventListener("blur", Me), R.appendChild(y), U.push(y)), ye(), $t()) : (y && (y.remove(), y = null), Q = !1, E && (E.style.opacity = "0")));
|
|
359
|
+
}
|
|
360
|
+
function Ce(t) {
|
|
361
|
+
if (t !== b)
|
|
362
|
+
if (b = t, t)
|
|
363
|
+
R.addEventListener("pointermove", pt, { passive: !0 }), R.addEventListener("pointerleave", wt, { passive: !0 }), X.set = !1, Z = !0, ot();
|
|
350
364
|
else {
|
|
351
|
-
|
|
352
|
-
const
|
|
353
|
-
|
|
365
|
+
R.removeEventListener("pointermove", pt), R.removeEventListener("pointerleave", wt);
|
|
366
|
+
const o = j.getContext("2d");
|
|
367
|
+
o && o.clearRect(0, 0, s, x);
|
|
354
368
|
}
|
|
355
369
|
}
|
|
356
|
-
function
|
|
357
|
-
|
|
370
|
+
function rt(t) {
|
|
371
|
+
le(), se(), ce(), fe(), ue(), t ? he() : (Rt(), Lt(), $.on = !1), y && y.value !== n && (y.value = n), $t(), Z = !0, ot();
|
|
358
372
|
}
|
|
359
|
-
function
|
|
360
|
-
t = t ?? "", !(t ===
|
|
373
|
+
function Vt(t, o) {
|
|
374
|
+
t = t ?? "", !(t === n && Y) && (n = t, Y && (rt(!1), o && m && m(n)));
|
|
361
375
|
}
|
|
362
|
-
|
|
363
|
-
function
|
|
364
|
-
const
|
|
365
|
-
let
|
|
376
|
+
const Mt = /* @__PURE__ */ new Set();
|
|
377
|
+
function Yt(t, o, l) {
|
|
378
|
+
const f = `${o} 200px ${t}`;
|
|
379
|
+
let T = !1;
|
|
366
380
|
try {
|
|
367
|
-
|
|
381
|
+
T = !!document.fonts && document.fonts.check(f);
|
|
368
382
|
} catch {
|
|
369
|
-
|
|
383
|
+
T = !0;
|
|
370
384
|
}
|
|
371
|
-
if (!document.fonts ||
|
|
385
|
+
if (!document.fonts || T) {
|
|
372
386
|
l();
|
|
373
387
|
return;
|
|
374
388
|
}
|
|
375
|
-
let
|
|
376
|
-
const
|
|
377
|
-
|
|
389
|
+
let C = !1, v;
|
|
390
|
+
const F = () => {
|
|
391
|
+
C || (C = !0, clearTimeout(v), Mt.delete(v), z || l());
|
|
378
392
|
};
|
|
379
|
-
document.fonts.load(
|
|
380
|
-
}
|
|
381
|
-
function
|
|
382
|
-
z || (
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
let
|
|
386
|
-
function
|
|
387
|
-
clearTimeout(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
393
|
+
document.fonts.load(f, n).then(() => document.fonts.ready).then(F, F), v = setTimeout(F, 1500), Mt.add(v);
|
|
394
|
+
}
|
|
395
|
+
function ve() {
|
|
396
|
+
z || (rt(!0), Y = !0);
|
|
397
|
+
}
|
|
398
|
+
A && (A = !1, Kt(!0)), b && (R.addEventListener("pointermove", pt, { passive: !0 }), R.addEventListener("pointerleave", wt, { passive: !0 })), Yt(I, i, ve);
|
|
399
|
+
let It, Jt = -1;
|
|
400
|
+
function Qt() {
|
|
401
|
+
clearTimeout(It), It = setTimeout(() => {
|
|
402
|
+
if (z || !Y) return;
|
|
403
|
+
const t = Math.round(R.getBoundingClientRect().width);
|
|
404
|
+
t !== Jt && (Jt = t, rt(!1));
|
|
405
|
+
}, 200);
|
|
406
|
+
}
|
|
407
|
+
window.addEventListener("resize", Qt);
|
|
408
|
+
const Pt = {
|
|
391
409
|
get text() {
|
|
392
|
-
return
|
|
410
|
+
return n;
|
|
393
411
|
},
|
|
394
412
|
setText(t) {
|
|
395
413
|
if (!z) {
|
|
396
414
|
if (!Y) {
|
|
397
|
-
|
|
415
|
+
n = t ?? "", y && (y.value = n);
|
|
398
416
|
return;
|
|
399
417
|
}
|
|
400
|
-
|
|
418
|
+
Vt(t, !1);
|
|
401
419
|
}
|
|
402
420
|
},
|
|
403
421
|
replay() {
|
|
404
|
-
z || !Y ||
|
|
422
|
+
z || !Y || rt(!0);
|
|
405
423
|
},
|
|
406
424
|
resize() {
|
|
407
|
-
z || !Y ||
|
|
425
|
+
z || !Y || rt(!1);
|
|
408
426
|
},
|
|
409
427
|
update(t) {
|
|
410
428
|
if (z) return;
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
429
|
+
t.text !== void 0 && Pt.setText(t.text);
|
|
430
|
+
let o = !1, l = !1;
|
|
431
|
+
if (t.font !== void 0 && t.font !== r && (r = t.font, I = ae(r), o = !0), t.weight !== void 0) {
|
|
432
|
+
const f = bt(t.weight, 1, 1e3);
|
|
433
|
+
f !== i && (i = f, o = !0);
|
|
434
|
+
}
|
|
435
|
+
if (t.fill !== void 0) {
|
|
436
|
+
const f = bt(t.fill, 0.05, 1);
|
|
437
|
+
f !== a && (a = f, o = !0);
|
|
438
|
+
}
|
|
439
|
+
t.pitch !== void 0 && t.pitch !== c && (c = t.pitch, o = !0), t.threadColor !== void 0 && (at(t.threadColor), l = !0), t.sewRate !== void 0 && (u = Math.max(1, t.sewRate)), t.animate !== void 0 && (S = t.animate), t.onTextChange !== void 0 && (m = t.onTextChange), t.sheen !== void 0 && Ce(t.sheen), t.editable !== void 0 && Kt(t.editable), Y && (o ? Yt(I, i, () => {
|
|
440
|
+
z || rt(!1);
|
|
441
|
+
}) : l && (Gt(), Rt(), Lt(), $t(), ot()));
|
|
415
442
|
},
|
|
416
443
|
focus() {
|
|
417
|
-
!z &&
|
|
444
|
+
!z && A && (y == null || y.focus());
|
|
418
445
|
},
|
|
419
446
|
destroy() {
|
|
420
447
|
if (!z) {
|
|
421
|
-
z = !0,
|
|
422
|
-
for (const t of
|
|
423
|
-
|
|
448
|
+
z = !0, ct = !1, cancelAnimationFrame(Ft), clearTimeout(It);
|
|
449
|
+
for (const t of Mt) clearTimeout(t);
|
|
450
|
+
Mt.clear(), window.removeEventListener("resize", Qt), R.removeEventListener("pointermove", pt), R.removeEventListener("pointerleave", wt);
|
|
451
|
+
for (const t of U) t.remove();
|
|
452
|
+
et = [], yt = [], $.rows = [], Et = new Uint8Array(0), St = new Float32Array(0), ht = new Float32Array(0), mt = new Float32Array(0), V = nt = null, xt = null, E = null, y = null;
|
|
424
453
|
}
|
|
425
454
|
}
|
|
426
455
|
};
|
|
427
|
-
return
|
|
456
|
+
return Pt;
|
|
428
457
|
}
|
|
429
|
-
function
|
|
430
|
-
const e =
|
|
431
|
-
r.current =
|
|
432
|
-
const i =
|
|
433
|
-
i.current =
|
|
434
|
-
const { text: a, font:
|
|
435
|
-
return
|
|
436
|
-
const
|
|
437
|
-
if (!
|
|
438
|
-
const
|
|
458
|
+
function Re(h) {
|
|
459
|
+
const e = vt(null), n = vt(null), r = vt(h);
|
|
460
|
+
r.current = h;
|
|
461
|
+
const i = vt(h.onTextChange);
|
|
462
|
+
i.current = h.onTextChange;
|
|
463
|
+
const { text: a, font: u, weight: b, threadColor: S, pitch: A, fill: c, animate: m, sewRate: I, sheen: O, editable: B, reducedMotion: it } = h;
|
|
464
|
+
return Te(() => {
|
|
465
|
+
const D = e.current;
|
|
466
|
+
if (!D) return;
|
|
467
|
+
const at = Le(D, {
|
|
439
468
|
...r.current,
|
|
440
469
|
// Stable callback wrapper so typing edits always reach the latest handler.
|
|
441
|
-
onTextChange: (
|
|
442
|
-
var
|
|
443
|
-
return (
|
|
470
|
+
onTextChange: (y) => {
|
|
471
|
+
var E;
|
|
472
|
+
return (E = i.current) == null ? void 0 : E.call(i, y);
|
|
444
473
|
}
|
|
445
474
|
});
|
|
446
|
-
|
|
447
|
-
let
|
|
448
|
-
return typeof ResizeObserver < "u" && (
|
|
449
|
-
const
|
|
450
|
-
|
|
475
|
+
n.current = at;
|
|
476
|
+
let U = 0, k = 0, R = !0, j;
|
|
477
|
+
return typeof ResizeObserver < "u" && (j = new ResizeObserver((y) => {
|
|
478
|
+
const E = Math.round(y[0].contentRect.width);
|
|
479
|
+
if (R) {
|
|
480
|
+
R = !1, k = E;
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
E !== k && (k = E, cancelAnimationFrame(U), U = requestAnimationFrame(() => {
|
|
451
484
|
var Q;
|
|
452
|
-
return (Q =
|
|
485
|
+
return (Q = n.current) == null ? void 0 : Q.resize();
|
|
453
486
|
}));
|
|
454
|
-
}),
|
|
455
|
-
|
|
487
|
+
}), j.observe(D)), () => {
|
|
488
|
+
j == null || j.disconnect(), cancelAnimationFrame(U), at.destroy(), n.current = null;
|
|
456
489
|
};
|
|
457
|
-
}, [
|
|
458
|
-
var
|
|
459
|
-
(
|
|
460
|
-
}, [
|
|
461
|
-
var
|
|
462
|
-
(
|
|
490
|
+
}, [it]), ee(() => {
|
|
491
|
+
var D;
|
|
492
|
+
(D = n.current) == null || D.update({ font: u, weight: b, threadColor: S, pitch: A, fill: c, animate: m, sewRate: I, sheen: O, editable: B });
|
|
493
|
+
}, [u, b, S, A, c, m, I, O, B]), ee(() => {
|
|
494
|
+
var D;
|
|
495
|
+
(D = n.current) == null || D.setText(a);
|
|
463
496
|
}, [a]), e;
|
|
464
497
|
}
|
|
465
|
-
const
|
|
466
|
-
function({ className: e, style:
|
|
467
|
-
const
|
|
468
|
-
(
|
|
469
|
-
|
|
498
|
+
const $e = Ae(
|
|
499
|
+
function({ className: e, style: n, as: r = "div", "aria-label": i, role: a, "aria-describedby": u, ...b }, S) {
|
|
500
|
+
const A = Re(b), c = Ee(
|
|
501
|
+
(m) => {
|
|
502
|
+
A.current = m, typeof S == "function" ? S(m) : S && (S.current = m);
|
|
470
503
|
},
|
|
471
504
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
472
|
-
[
|
|
505
|
+
[A, S]
|
|
473
506
|
);
|
|
474
|
-
return /* @__PURE__ */
|
|
507
|
+
return /* @__PURE__ */ Se(
|
|
475
508
|
r,
|
|
476
509
|
{
|
|
477
510
|
ref: c,
|
|
478
511
|
className: e,
|
|
479
|
-
style:
|
|
480
|
-
role: a ?? "img",
|
|
481
|
-
"aria-label": i ??
|
|
482
|
-
"aria-describedby":
|
|
512
|
+
style: n,
|
|
513
|
+
role: b.editable ? a : a ?? "img",
|
|
514
|
+
"aria-label": b.editable ? i : i ?? b.text,
|
|
515
|
+
"aria-describedby": u
|
|
483
516
|
}
|
|
484
517
|
);
|
|
485
518
|
}
|
|
486
519
|
);
|
|
487
|
-
|
|
520
|
+
$e.displayName = "ThreadText";
|
|
488
521
|
export {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
522
|
+
Dt as THREAD_TEXT_CLASSES,
|
|
523
|
+
$e as ThreadText,
|
|
524
|
+
Le as createThreadText,
|
|
525
|
+
Re as useThreadText
|
|
493
526
|
};
|
|
@@ -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(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.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",
|