{"version":3,"file":"Confetti.rdPy939g.mjs","names":["useRef","useState","useCallback"],"sources":["https:/framerusercontent.com/modules/hq4jwvbtjJ8P19NlmL3V/r6KpTwHlujrm8L2NXWlU/Confetti.js"],"sourcesContent":["// SectionConfetti.tsx — Framer Component\n// Drop this into your Framer project as a Code Component.\n// Set the `sectionId` prop to match the HTML id of your target section.\nimport{jsx as _jsx}from\"react/jsx-runtime\";import{addPropertyControls,ControlType}from\"framer\";import{startTransition,useCallback,useEffect,useRef,useState}from\"react\";import{createPortal}from\"react-dom\";// ─── Helpers ──────────────────────────────────────────────────────────────────\nconst randomBetween=(a,b)=>a+Math.random()*(b-a);const createParticle=(id,canvasW,spread,colors)=>{const shape=[\"rect\",\"circle\",\"ribbon\"][Math.floor(Math.random()*3)];return{id,x:randomBetween(canvasW*.2,canvasW*.8),y:randomBetween(-80,-10),vx:randomBetween(-spread,spread),vy:randomBetween(2,6),rotation:randomBetween(0,360),rotationSpeed:randomBetween(-6,6),color:colors[Math.floor(Math.random()*colors.length)],shape,width:shape===\"circle\"?randomBetween(6,14):randomBetween(8,18),height:shape===\"ribbon\"?randomBetween(14,28):shape===\"circle\"?randomBetween(6,14):randomBetween(8,14),opacity:1,gravity:randomBetween(.08,.18)};};// ─── Canvas Renderer ──────────────────────────────────────────────────────────\nfunction drawParticle(ctx,p){ctx.save();ctx.globalAlpha=p.opacity;ctx.fillStyle=p.color;ctx.translate(p.x,p.y);ctx.rotate(p.rotation*Math.PI/180);if(p.shape===\"circle\"){ctx.beginPath();ctx.arc(0,0,p.width/2,0,Math.PI*2);ctx.fill();}else if(p.shape===\"ribbon\"){ctx.beginPath();ctx.moveTo(-p.width/2,-p.height/2);ctx.quadraticCurveTo(p.width/2,0,-p.width/2,p.height/2);ctx.quadraticCurveTo(p.width/2,0,-p.width/2,-p.height/2);ctx.fill();}else{ctx.fillRect(-p.width/2,-p.height/2,p.width,p.height);}ctx.restore();}// ─── Component ────────────────────────────────────────────────────────────────\nexport default function SectionConfetti({sectionId,particleCount,colors,spread,duration,once,offsetY,confineToSection}){const canvasRef=useRef(null);const particlesRef=useRef([]);const rafRef=useRef(0);const firedRef=useRef(false);const targetRef=useRef(null);const targetStyleRestoreRef=useRef(null);const[active,setActive]=useState(false);const[portalTarget,setPortalTarget]=useState(null);const shouldConfine=confineToSection||sectionId===\"certificate-mobile\"||sectionId.toLowerCase().includes(\"mobile\");const resizeCanvas=useCallback(()=>{const canvas=canvasRef.current;if(!canvas)return;if(shouldConfine&&targetRef.current){canvas.width=Math.max(1,Math.floor(targetRef.current.clientWidth));canvas.height=Math.max(1,Math.floor(targetRef.current.clientHeight));return;}if(typeof window!==\"undefined\"){canvas.width=window.innerWidth;canvas.height=window.innerHeight;}},[shouldConfine]);// ── Launch burst ──────────────────────────────────────────────────────────\nconst launch=useCallback(()=>{const canvas=canvasRef.current;if(!canvas)return;// Spawn particles\nparticlesRef.current=Array.from({length:particleCount},(_,i)=>createParticle(i,canvas.width,spread,colors));startTransition(()=>setActive(true));const endTime=Date.now()+duration*1e3;const tick=()=>{const ctx=canvas.getContext(\"2d\");if(!ctx)return;ctx.clearRect(0,0,canvas.width,canvas.height);particlesRef.current=particlesRef.current.map(p=>({...p,x:p.x+p.vx,y:p.y+p.vy,vy:p.vy+p.gravity,vx:p.vx*.99,rotation:p.rotation+p.rotationSpeed,opacity:Date.now()>endTime-800?Math.max(0,p.opacity-.015):p.opacity})).filter(p=>p.y<canvas.height+50&&p.opacity>0);particlesRef.current.forEach(p=>drawParticle(ctx,p));if(Date.now()<endTime&&particlesRef.current.length>0){rafRef.current=requestAnimationFrame(tick);}else{startTransition(()=>setActive(false));ctx.clearRect(0,0,canvas.width,canvas.height);}};rafRef.current=requestAnimationFrame(tick);},[colors,duration,particleCount,spread]);// ── Observe section ───────────────────────────────────────────────────────\nuseEffect(()=>{if(!sectionId||typeof document===\"undefined\")return;const target=document.getElementById(sectionId);if(!target){console.warn(`[SectionConfetti] No element found with id=\"${sectionId}\"`);targetRef.current=null;startTransition(()=>setPortalTarget(null));return;}targetRef.current=target;startTransition(()=>setPortalTarget(target));resizeCanvas();if(shouldConfine){targetStyleRestoreRef.current={position:target.style.position,overflow:target.style.overflow};if(!target.style.position)target.style.position=\"relative\";if(!target.style.overflow)target.style.overflow=\"hidden\";}else if(targetStyleRestoreRef.current){target.style.position=targetStyleRestoreRef.current.position;target.style.overflow=targetStyleRestoreRef.current.overflow;targetStyleRestoreRef.current=null;}const observer=new IntersectionObserver(([entry])=>{if(entry.isIntersecting){if(once&&firedRef.current)return;firedRef.current=true;cancelAnimationFrame(rafRef.current);launch();}},{threshold:.3,rootMargin:`${offsetY}px 0px 0px 0px`});observer.observe(target);return()=>{observer.disconnect();if(targetStyleRestoreRef.current&&targetRef.current){targetRef.current.style.position=targetStyleRestoreRef.current.position;targetRef.current.style.overflow=targetStyleRestoreRef.current.overflow;targetStyleRestoreRef.current=null;}};},[sectionId,particleCount,spread,duration,once,offsetY,launch,shouldConfine,resizeCanvas]);// ── Resize canvas ─────────────────────────────────────────────────────────\nuseEffect(()=>{if(typeof window===\"undefined\")return;resizeCanvas();window.addEventListener(\"resize\",resizeCanvas);let sectionResizeObserver=null;if(shouldConfine&&typeof ResizeObserver!==\"undefined\"&&targetRef.current){sectionResizeObserver=new ResizeObserver(()=>resizeCanvas());sectionResizeObserver.observe(targetRef.current);}return()=>{window.removeEventListener(\"resize\",resizeCanvas);sectionResizeObserver?.disconnect();};},[shouldConfine,resizeCanvas,sectionId]);useEffect(()=>{return()=>cancelAnimationFrame(rafRef.current);},[]);const canvasElement=/*#__PURE__*/_jsx(\"canvas\",{ref:canvasRef,style:shouldConfine?{position:\"absolute\",inset:0,width:\"100%\",height:\"100%\",pointerEvents:\"none\",zIndex:9999,opacity:active?1:0}:{position:\"fixed\",inset:0,width:\"100vw\",height:\"100vh\",pointerEvents:\"none\",zIndex:9999,opacity:active?1:0}});if(shouldConfine&&portalTarget){return /*#__PURE__*/createPortal(canvasElement,portalTarget);}return canvasElement;}// ─── Default Props ────────────────────────────────────────────────────────────\nSectionConfetti.defaultProps={sectionId:\"hero\",particleCount:160,colors:[\"#FF6B6B\",\"#FFD93D\",\"#6BCB77\",\"#4D96FF\",\"#C77DFF\",\"#FF9F1C\",\"#ffffff\"],spread:5,duration:4,once:true,offsetY:0,confineToSection:false};// ─── Property Controls (Framer UI) ────────────────────────────────────────────\naddPropertyControls(SectionConfetti,{sectionId:{type:ControlType.String,title:\"Section ID\",placeholder:\"e.g. hero, features, pricing\",description:'The HTML id of the section that triggers confetti (e.g. id=\"hero\")'},particleCount:{type:ControlType.Number,title:\"Particle Count\",min:20,max:500,step:10,defaultValue:160},spread:{type:ControlType.Number,title:\"Spread\",min:1,max:20,step:.5,defaultValue:5,description:\"Horizontal spread of particles\"},duration:{type:ControlType.Number,title:\"Duration (s)\",min:1,max:10,step:.5,defaultValue:4},once:{type:ControlType.Boolean,title:\"Fire Once\",defaultValue:true,description:\"Only trigger confetti the first time the section appears\"},offsetY:{type:ControlType.Number,title:\"Trigger Offset Y\",min:-300,max:300,step:10,defaultValue:0,description:\"Adjust when the trigger fires (negative = earlier)\"},confineToSection:{type:ControlType.Boolean,title:\"Confine to Section\",defaultValue:false,description:\"When enabled, confetti renders inside the target section bounds instead of fullscreen.\"},colors:{type:ControlType.Array,title:\"Colors\",control:{type:ControlType.Color},defaultValue:[\"#FF6B6B\",\"#FFD93D\",\"#6BCB77\",\"#4D96FF\",\"#C77DFF\",\"#FF9F1C\"]}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"SectionConfetti\",\"slots\":[],\"annotations\":{\"framerContractVersion\":\"1\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./Confetti.map"],"mappings":"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"}