{"version":3,"file":"ParticleText.CUVEBeHI.mjs","names":["useRef","useState"],"sources":["https:/framerusercontent.com/modules/U5YgcgkBjbdV21j0ZwuS/otOSwmqP2acS2BjTve4l/ParticleText.js"],"sourcesContent":["// Animated particles text component where particles are pushed around by the mouse pointer\nimport{jsx as _jsx}from\"react/jsx-runtime\";import{useEffect,useRef,useState,startTransition}from\"react\";import{addPropertyControls,ControlType,useIsStaticRenderer}from\"framer\";/**\n * @framerIntrinsicWidth 500\n * @framerIntrinsicHeight 500\n * @framerSupportedLayoutWidth fixed\n * @framerSupportedLayoutHeight fixed\n */export default function TextFlow(props){const{text=\"Pola\",particleColor=\"#FFFFFF\",backgroundColor=\"#000000\",particleSize=2,particleDensity=3,mouseRadius=100,returnSpeed=.05,font,verticalAlign=\"center\",horizontalAlign=\"center\",style}=props;const canvasRef=useRef(null);const particlesRef=useRef([]);const mouseRef=useRef({x:-1e3,y:-1e3});const animationFrameRef=useRef();const isStatic=useIsStaticRenderer();const[isInitialized,setIsInitialized]=useState(false);// Initialize particles\nuseEffect(()=>{if(isStatic)return;const canvas=canvasRef.current;if(!canvas)return;const ctx=canvas.getContext(\"2d\",{willReadFrequently:true});if(!ctx)return;// Use a timeout to prevent blocking\nconst timeoutId=setTimeout(()=>{const dpr=typeof window!==\"undefined\"?window.devicePixelRatio||1:1;const rect=canvas.getBoundingClientRect();canvas.width=rect.width*dpr;canvas.height=rect.height*dpr;ctx.scale(dpr,dpr);const width=rect.width;const height=rect.height;// Draw text to get particle positions\nctx.fillStyle=particleColor;// Set horizontal alignment\nif(horizontalAlign===\"left\"){ctx.textAlign=\"left\";}else if(horizontalAlign===\"right\"){ctx.textAlign=\"right\";}else{ctx.textAlign=\"center\";}// Set vertical baseline\nctx.textBaseline=\"middle\";const fontSize=parseInt(font.fontSize)||80;const fontWeight=font.fontWeight||\"400\";const fontStyle=font.fontStyle||\"normal\";const fontFamily=font.fontFamily||\"Inter, sans-serif\";ctx.font=`${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;// Add padding to prevent text cutoff\nconst padding=fontSize*.3;// Calculate maximum text width based on container size\nconst maxTextWidth=width-padding*2;// Function to wrap text to fit within container width\nconst wrapText=inputText=>{const inputLines=inputText.split(\"\\n\");const wrappedLines=[];for(const line of inputLines){// If line is empty or fits, keep it as is\nif(!line.trim()){wrappedLines.push(\"\");continue;}// Check if line fits in container\nconst metrics=ctx.measureText(line);if(metrics.width<=maxTextWidth){wrappedLines.push(line);continue;}// Split line into words\nconst words=line.split(\" \");let currentLine=\"\";for(const word of words){const testLine=currentLine?`${currentLine} ${word}`:word;const testMetrics=ctx.measureText(testLine);if(testMetrics.width<=maxTextWidth){currentLine=testLine;}else{if(currentLine){wrappedLines.push(currentLine);currentLine=word;}else{// Single word too long, add it anyway\nwrappedLines.push(word);}}}if(currentLine){wrappedLines.push(currentLine);}}return wrappedLines;};const lines=wrapText(text);const lineHeight=fontSize*1.2;const totalHeight=lines.length*lineHeight;// Calculate vertical position\nlet startY;if(verticalAlign===\"top\"){startY=lineHeight/2+padding;}else if(verticalAlign===\"bottom\"){startY=height-totalHeight+lineHeight/2-padding;}else{startY=(height-totalHeight)/2+lineHeight/2;}// Calculate horizontal position\nlet textX;if(horizontalAlign===\"left\"){textX=padding;}else if(horizontalAlign===\"right\"){textX=width-padding;}else{textX=width/2;}lines.forEach((line,index)=>{ctx.fillText(line,textX,startY+index*lineHeight);});// Get pixel data\nconst imageData=ctx.getImageData(0,0,canvas.width,canvas.height);const pixels=imageData.data;// Create particles from text pixels\nconst particles=[];const gap=Math.max(2,particleDensity);for(let y=0;y<canvas.height;y+=gap){for(let x=0;x<canvas.width;x+=gap){const index=(y*canvas.width+x)*4;const alpha=pixels[index+3];if(alpha>128){const px=x/dpr;const py=y/dpr;particles.push({x:px,y:py,baseX:px,baseY:py,vx:0,vy:0});}}}particlesRef.current=particles;startTransition(()=>setIsInitialized(true));},0);return()=>{clearTimeout(timeoutId);};},[text,particleColor,particleDensity,font,isStatic,horizontalAlign,verticalAlign]);// Animation loop\nuseEffect(()=>{if(isStatic||!isInitialized)return;const canvas=canvasRef.current;if(!canvas)return;const ctx=canvas.getContext(\"2d\");if(!ctx)return;const rect=canvas.getBoundingClientRect();const width=rect.width;const height=rect.height;const animate=()=>{ctx.clearRect(0,0,width,height);const mouse=mouseRef.current;const particles=particlesRef.current;for(let i=0;i<particles.length;i++){const particle=particles[i];const dx=mouse.x-particle.x;const dy=mouse.y-particle.y;const distance=Math.sqrt(dx*dx+dy*dy);// Push particles away from mouse\nif(distance<mouseRadius){const force=(mouseRadius-distance)/mouseRadius;const angle=Math.atan2(dy,dx);particle.vx-=Math.cos(angle)*force*2;particle.vy-=Math.sin(angle)*force*2;}// Return to base position\nparticle.vx+=(particle.baseX-particle.x)*returnSpeed;particle.vy+=(particle.baseY-particle.y)*returnSpeed;// Apply velocity with damping\nparticle.vx*=.95;particle.vy*=.95;particle.x+=particle.vx;particle.y+=particle.vy;// Draw particle\nctx.fillStyle=particleColor;ctx.beginPath();ctx.arc(particle.x,particle.y,particleSize,0,Math.PI*2);ctx.fill();}animationFrameRef.current=requestAnimationFrame(animate);};animate();return()=>{if(animationFrameRef.current){cancelAnimationFrame(animationFrameRef.current);}};},[isInitialized,particleColor,particleSize,mouseRadius,returnSpeed,isStatic]);const handleMouseMove=e=>{if(isStatic)return;const canvas=canvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();mouseRef.current={x:e.clientX-rect.left,y:e.clientY-rect.top};};const handleMouseLeave=()=>{mouseRef.current={x:-1e3,y:-1e3};};// Static preview\nif(isStatic){// Map alignment values to CSS\nconst alignItems=verticalAlign===\"top\"?\"flex-start\":verticalAlign===\"bottom\"?\"flex-end\":\"center\";const justifyContent=horizontalAlign===\"left\"?\"flex-start\":horizontalAlign===\"right\"?\"flex-end\":\"center\";const textAlign=horizontalAlign;return /*#__PURE__*/_jsx(\"div\",{style:{...style,width:\"100%\",height:\"100%\",backgroundColor,display:\"flex\",alignItems,justifyContent,color:particleColor,textAlign,whiteSpace:\"pre-wrap\",wordBreak:\"break-word\",overflowWrap:\"break-word\",hyphens:\"auto\",padding:\"16px\",boxSizing:\"border-box\",...font},children:text});}return /*#__PURE__*/_jsx(\"canvas\",{ref:canvasRef,onMouseMove:handleMouseMove,onMouseLeave:handleMouseLeave,style:{...style,width:\"100%\",height:\"100%\",backgroundColor,cursor:\"default\"}});}addPropertyControls(TextFlow,{text:{type:ControlType.String,title:\"Text\",defaultValue:\"Pola\",displayTextArea:true},font:{type:ControlType.Font,title:\"Font\",controls:\"extended\",defaultFontType:\"sans-serif\",defaultValue:{fontSize:\"80px\",variant:\"Regular\",letterSpacing:\"-0.02em\",lineHeight:\"1.2em\"}},horizontalAlign:{type:ControlType.Enum,title:\"Horizontal\",options:[\"left\",\"center\",\"right\"],optionTitles:[\"Left\",\"Center\",\"Right\"],defaultValue:\"center\",displaySegmentedControl:true},verticalAlign:{type:ControlType.Enum,title:\"Vertical\",options:[\"top\",\"center\",\"bottom\"],optionTitles:[\"Top\",\"Center\",\"Bottom\"],defaultValue:\"center\",displaySegmentedControl:true},particleColor:{type:ControlType.Color,title:\"Particle Color\",defaultValue:\"#FFFFFF\"},backgroundColor:{type:ControlType.Color,title:\"Background\",defaultValue:\"#000000\"},particleSize:{type:ControlType.Number,title:\"Particle Size\",defaultValue:2,min:1,max:10,step:.5,unit:\"px\"},particleDensity:{type:ControlType.Number,title:\"Density\",description:\"Lower values create more particles (denser text)\",defaultValue:3,min:1,max:10,step:1,unit:\"px\"},mouseRadius:{type:ControlType.Number,title:\"Mouse Radius\",defaultValue:100,min:50,max:300,step:10,unit:\"px\"},returnSpeed:{type:ControlType.Number,title:\"Return Speed\",defaultValue:.05,min:.01,max:.2,step:.01}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"TextFlow\",\"slots\":[],\"annotations\":{\"framerContractVersion\":\"1\",\"framerIntrinsicHeight\":\"500\",\"framerIntrinsicWidth\":\"500\",\"framerSupportedLayoutHeight\":\"fixed\",\"framerSupportedLayoutWidth\":\"fixed\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./ParticleText.map"],"mappings":"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"}