v12-ui
Version:
A React component library with a focus on utility-first design and accessibility.
2 lines (1 loc) • 4.6 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("react/jsx-runtime"),M=require("react"),P=require("../Hooks/useDataTheme.cjs"),b=require("../utils/utils.cjs");class T{canvas;ctx;particles=[];mouse=null;animationId=null;dpr;config;constructor(t,i){this.canvas=t;const e=t.getContext("2d");if(!e)throw new Error("No se pudo obtener el contexto 2D del canvas");this.ctx=e,this.dpr=window.devicePixelRatio||1,this.config=i,this.setupCanvas(),this.generateParticles(),this.animate=this.animate.bind(this),this.animate()}setupCanvas(){const t=this.canvas.getBoundingClientRect();this.canvas.width=t.width*this.dpr,this.canvas.height=t.height*this.dpr,this.canvas.style.width=`${t.width}px`,this.canvas.style.height=`${t.height}px`,this.ctx.scale(this.dpr,this.dpr),this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality&&(this.ctx.imageSmoothingQuality="high")}createTextMask(){return this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.font=`bold ${this.config.fontSize||50}px ${this.config.fontFamily||"sans-serif"}`,this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillStyle=`${this.config.color||"#fff"}`,this.ctx.fillText(this.config.text,this.canvas.width/2,this.canvas.height/2),this.ctx.getImageData(0,0,this.canvas.width,this.canvas.height)}extractPositions(t){const i=[],{data:e,width:a,height:x}=t,c=Math.max(1,4);let s=0;for(let n=0;n<e.length;n+=4){const[l]=e.slice(n,n+4);l>50&&s++}const o=Math.max(1,Math.floor(Math.sqrt(s/(this.config.particles||6e3)))),h=Math.min(c,o);for(let n=0;n<x;n+=h)for(let l=0;l<a;l+=h){const g=(n*a+l)*4,[f]=e.slice(g,g+4);f>50&&i.push({x:l/this.dpr,y:n/this.dpr})}return i}generateParticles(){const t=this.createTextMask(),i=this.extractPositions(t);if(i.length===0){console.warn("No se encontraron píxeles visibles en la imagen");return}const e=Math.max(this.canvas.width,this.canvas.height)*2;this.particles=i.map(a=>({tx:a.x,ty:a.y,x:a.x+(Math.random()-.5)*e,y:a.y+(Math.random()-.5)*e,vx:0,vy:0,phase:Math.random()*Math.PI*2,age:0,isImmune:Math.random()<.05}))}updateParticle(t){const i=t.tx-t.x,e=t.ty-t.y;if(this.mouse&&this.config.attractMode){const r=this.mouse.x-t.x,c=this.mouse.y-t.y,s=Math.hypot(r,c);if(s<this.config.repulsion&&s>0){const h=10*Math.max(0,1-s/this.config.repulsion);t.vx+=r/s*h,t.vy+=c/s*h}}else if(this.mouse&&!this.config.attractMode){const r=this.mouse.x-t.x,c=this.mouse.y-t.y,s=Math.hypot(r,c);if(s<this.config.repulsion&&s>0){let o;this.config.trace?t.isImmune?o=(this.config.repulsion-s)/this.config.repulsion*.1:o=Math.max(0,1-s/this.config.repulsion):o=Math.max(0,1-s/this.config.repulsion);const h=20*o;t.vx-=r/s*h,t.vy-=c/s*h}}const a=.04,x=.73;t.vx+=i*a,t.vy+=e*a,t.vx*=x,t.vy*=x,t.x+=t.vx,t.y+=t.vy}drawParticles(){const t=this.canvas.width/this.dpr,i=this.canvas.height/this.dpr;this.ctx.clearRect(0,0,t,i);for(const e of this.particles){this.updateParticle(e),e.age+=1;const a=(Math.sin(e.phase+e.age*.15)+1)/2;this.ctx.fillStyle=this.config.color||"#fff",this.config.glow&&(this.ctx.globalAlpha=a),this.ctx.beginPath(),this.ctx.arc(e.x,e.y,this.config.dotSize,0,Math.PI*2),this.ctx.fill()}this.ctx.globalAlpha=1}handleMouseMove=t=>{const i=this.canvas.getBoundingClientRect();this.mouse={x:(t.clientX-i.left)*(this.canvas.width/i.width),y:(t.clientY-i.top)*(this.canvas.height/i.height)}};handleMouseLeave=()=>{this.mouse=null};animate(){this.drawParticles(),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseleave",this.handleMouseLeave),this.animationId=requestAnimationFrame(this.animate)}destroy(){this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseleave",this.handleMouseLeave),this.animationId&&cancelAnimationFrame(this.animationId)}}function I({text:d="Magic Text",particles:t=500,dotSize:i=.9,repulsion:e=50,friction:a=.82,returnSpeed:x=.01,fontFamily:r="sans-serif",fontSize:c=50,color:s,glow:o=!0,trace:h=!0,attractMode:n=!1,className:l,...g}){const{theme:f}=P.useDataTheme(),m=s||(f==="dark"?"#fff":"#000");console.log("Theme:",f,"Color detected:",m);const u=M.useRef(null);return M.useEffect(()=>{const v=u.current;if(!v)return;if(!d){console.warn("MagicText: text needed");return}const p={text:d,particles:t,dotSize:i,repulsion:e,friction:a,returnSpeed:x,fontFamily:r,fontSize:c,color:m,glow:o,trace:h,attractMode:n},y=new T(v,p);return()=>{y&&y.destroy()}},[d,t,i,e,a,x,r,c,f,s,o,h,n]),w.jsx("canvas",{ref:u,...g,className:b.cn("block mx-auto overflow-visible z-0 w-fit h-fit",l)})}exports.MagicText=I;