{"version":3,"file":"components\\ui\\fireworks-background.cjs","sources":["webpack://@arolariu/components/./src/components/ui/fireworks-background.tsx"],"sourcesContent":["\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst rand = (min: number, max: number): number =>\n  Math.random() * (max - min) + min;\nconst randInt = (min: number, max: number): number =>\n  Math.floor(Math.random() * (max - min) + min);\nconst randColor = (): string => `hsl(${randInt(0, 360)}, 100%, 50%)`;\n\ninterface ParticleType {\n  x: number;\n  y: number;\n  color: string;\n  speed: number;\n  direction: number;\n  vx: number;\n  vy: number;\n  gravity: number;\n  friction: number;\n  alpha: number;\n  decay: number;\n  size: number;\n  update: () => void;\n  draw: (ctx: CanvasRenderingContext2D) => void;\n  isAlive: () => boolean;\n}\n\nconst createParticle = (\n  x: number,\n  y: number,\n  color: string,\n  speed: number,\n  direction: number,\n  gravity: number,\n  friction: number,\n  size: number\n): ParticleType => {\n  const vx = Math.cos(direction) * speed;\n  const vy = Math.sin(direction) * speed;\n  const alpha = 1;\n  const decay = rand(0.005, 0.02);\n\n  return {\n    x,\n    y,\n    color,\n    speed,\n    direction,\n    vx,\n    vy,\n    gravity,\n    friction,\n    alpha,\n    decay,\n    size,\n    update() {\n      this.vx *= this.friction;\n      this.vy *= this.friction;\n      this.vy += this.gravity;\n      this.x += this.vx;\n      this.y += this.vy;\n      this.alpha -= this.decay;\n    },\n    draw(ctx: CanvasRenderingContext2D) {\n      ctx.save();\n      ctx.globalAlpha = this.alpha;\n      ctx.beginPath();\n      ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);\n      ctx.fillStyle = this.color;\n      ctx.fill();\n      ctx.restore();\n    },\n    isAlive() {\n      return this.alpha > 0;\n    },\n  };\n};\n\ninterface FireworkType {\n  x: number;\n  y: number;\n  targetY: number;\n  color: string;\n  speed: number;\n  size: number;\n  angle: number;\n  vx: number;\n  vy: number;\n  trail: { x: number; y: number }[];\n  trailLength: number;\n  exploded: boolean;\n  update: () => boolean;\n  explode: () => void;\n  draw: (ctx: CanvasRenderingContext2D) => void;\n}\n\nconst createFirework = (\n  x: number,\n  y: number,\n  targetY: number,\n  color: string,\n  speed: number,\n  size: number,\n  particleSpeed: { min: number; max: number } | number,\n  particleSize: { min: number; max: number } | number,\n  onExplode: (particles: ParticleType[]) => void\n): FireworkType => {\n  const angle = -Math.PI / 2 + rand(-0.3, 0.3);\n  const vx = Math.cos(angle) * speed;\n  const vy = Math.sin(angle) * speed;\n  const trail: { x: number; y: number }[] = [];\n  const trailLength = randInt(10, 25);\n\n  return {\n    x,\n    y,\n    targetY,\n    color,\n    speed,\n    size,\n    angle,\n    vx,\n    vy,\n    trail,\n    trailLength,\n    exploded: false,\n    update() {\n      this.trail.push({ x: this.x, y: this.y });\n      if (this.trail.length > this.trailLength) {\n        this.trail.shift();\n      }\n      this.x += this.vx;\n      this.y += this.vy;\n      this.vy += 0.02;\n      if (this.vy >= 0 || this.y <= this.targetY) {\n        this.explode();\n        return false;\n      }\n      return true;\n    },\n    explode() {\n      const numParticles = randInt(50, 150);\n      const particles: ParticleType[] = [];\n      for (let i = 0; i < numParticles; i++) {\n        const particleAngle = rand(0, Math.PI * 2);\n        const localParticleSpeed = getValueByRange(particleSpeed);\n        const localParticleSize = getValueByRange(particleSize);\n        particles.push(\n          createParticle(\n            this.x,\n            this.y,\n            this.color,\n            localParticleSpeed,\n            particleAngle,\n            0.05,\n            0.98,\n            localParticleSize\n          )\n        );\n      }\n      onExplode(particles);\n    },\n    draw(ctx: CanvasRenderingContext2D) {\n      ctx.save();\n      ctx.beginPath();\n      if (this.trail.length > 1) {\n        ctx.moveTo(this.trail[0].x, this.trail[0].y);\n        for (const point of this.trail) {\n          ctx.lineTo(point.x, point.y);\n        }\n      } else {\n        ctx.moveTo(this.x, this.y);\n        ctx.lineTo(this.x, this.y);\n      }\n      ctx.strokeStyle = this.color;\n      ctx.lineWidth = this.size;\n      ctx.lineCap = \"round\";\n      ctx.stroke();\n      ctx.restore();\n    },\n  };\n};\n\nconst getValueByRange = (\n  range: { min: number; max: number } | number\n): number => {\n  if (typeof range === \"number\") {\n    return range;\n  }\n  return rand(range.min, range.max);\n};\n\nconst getColor = (color: string | string[] | undefined): string => {\n  if (Array.isArray(color)) {\n    return color[randInt(0, color.length)];\n  }\n  return color ?? randColor();\n};\n\ninterface FireworksBackgroundProps\n  extends Omit<React.HTMLAttributes<HTMLDivElement>, \"color\"> {\n  canvasProps?: React.HTMLAttributes<HTMLCanvasElement>;\n  population?: number;\n  color?: string | string[];\n  fireworkSpeed?: { min: number; max: number } | number;\n  fireworkSize?: { min: number; max: number } | number;\n  particleSpeed?: { min: number; max: number } | number;\n  particleSize?: { min: number; max: number } | number;\n}\n\nconst FireworksBackground = React.forwardRef<\n  HTMLDivElement,\n  FireworksBackgroundProps\n>(\n  (\n    {\n      className,\n      canvasProps,\n      population = 1,\n      color,\n      fireworkSpeed = { min: 4, max: 8 },\n      fireworkSize = { min: 2, max: 5 },\n      particleSpeed = { min: 2, max: 7 },\n      particleSize = { min: 1, max: 5 },\n      ...props\n    },\n    ref\n  ) => {\n    const canvasRef = React.useRef<HTMLCanvasElement>(null);\n    const containerRef = React.useRef<HTMLDivElement>(null);\n    React.useImperativeHandle(\n      ref,\n      () => containerRef.current as HTMLDivElement\n    );\n\n    React.useEffect(() => {\n      const canvas = canvasRef.current;\n      const container = containerRef.current;\n      if (!canvas || !container) return;\n      const ctx = canvas.getContext(\"2d\");\n      if (!ctx) return;\n\n      let maxX = window.innerWidth;\n      let ratio = container.offsetHeight / container.offsetWidth;\n      let maxY = maxX * ratio;\n      canvas.width = maxX;\n      canvas.height = maxY;\n\n      const setCanvasSize = () => {\n        maxX = window.innerWidth;\n        ratio = container.offsetHeight / container.offsetWidth;\n        maxY = maxX * ratio;\n        canvas.width = maxX;\n        canvas.height = maxY;\n      };\n      window.addEventListener(\"resize\", setCanvasSize);\n\n      const explosions: ParticleType[] = [];\n      const fireworks: FireworkType[] = [];\n\n      const handleExplosion = (particles: ParticleType[]) => {\n        explosions.push(...particles);\n      };\n\n      const launchFirework = () => {\n        const x = rand(maxX * 0.1, maxX * 0.9);\n        const y = maxY;\n        const targetY = rand(maxY * 0.1, maxY * 0.4);\n        const fireworkColor = getColor(color);\n        const speed = getValueByRange(fireworkSpeed);\n        const size = getValueByRange(fireworkSize);\n        fireworks.push(\n          createFirework(\n            x,\n            y,\n            targetY,\n            fireworkColor,\n            speed,\n            size,\n            particleSpeed,\n            particleSize,\n            handleExplosion\n          )\n        );\n        const timeout = rand(300, 800) / population;\n        setTimeout(launchFirework, timeout);\n      };\n\n      launchFirework();\n\n      let animationFrameId: number;\n      const animate = () => {\n        ctx.clearRect(0, 0, maxX, maxY);\n\n        for (let i = fireworks.length - 1; i >= 0; i--) {\n          const firework = fireworks[i];\n          if (!firework.update()) {\n            fireworks.splice(i, 1);\n          } else {\n            firework.draw(ctx);\n          }\n        }\n\n        for (let i = explosions.length - 1; i >= 0; i--) {\n          const particle = explosions[i];\n          particle.update();\n          if (particle.isAlive()) {\n            particle.draw(ctx);\n          } else {\n            explosions.splice(i, 1);\n          }\n        }\n\n        animationFrameId = requestAnimationFrame(animate);\n      };\n\n      animate();\n\n      const handleClick = (event: MouseEvent) => {\n        const x = event.clientX;\n        const y = maxY;\n        const targetY = event.clientY;\n        const fireworkColor = getColor(color);\n        const speed = getValueByRange(fireworkSpeed);\n        const size = getValueByRange(fireworkSize);\n        fireworks.push(\n          createFirework(\n            x,\n            y,\n            targetY,\n            fireworkColor,\n            speed,\n            size,\n            particleSpeed,\n            particleSize,\n            handleExplosion\n          )\n        );\n      };\n\n      container.addEventListener(\"click\", handleClick);\n\n      return () => {\n        window.removeEventListener(\"resize\", setCanvasSize);\n        container.removeEventListener(\"click\", handleClick);\n        cancelAnimationFrame(animationFrameId);\n      };\n    }, [\n      population,\n      color,\n      fireworkSpeed,\n      fireworkSize,\n      particleSpeed,\n      particleSize,\n    ]);\n\n    return (\n      <div\n        ref={containerRef}\n        className={cn(\"relative size-full overflow-hidden\", className)}\n        {...props}\n      >\n        <canvas\n          {...canvasProps}\n          ref={canvasRef}\n          className={cn(\"absolute inset-0 size-full\", canvasProps?.className)}\n        />\n      </div>\n    );\n  }\n);\n\nFireworksBackground.displayName = \"FireworksBackground\";\n\nexport { FireworksBackground, type FireworksBackgroundProps };\n"],"names":["rand","min","max","Math","randInt","randColor","createParticle","x","y","color","speed","direction","gravity","friction","size","vx","vy","alpha","decay","ctx","createFirework","targetY","particleSpeed","particleSize","onExplode","angle","trail","trailLength","numParticles","particles","i","particleAngle","localParticleSpeed","getValueByRange","localParticleSize","point","range","getColor","Array","FireworksBackground","React","className","canvasProps","population","fireworkSpeed","fireworkSize","props","ref","canvasRef","containerRef","canvas","container","maxX","window","ratio","maxY","setCanvasSize","explosions","fireworks","handleExplosion","launchFirework","fireworkColor","timeout","setTimeout","animationFrameId","animate","firework","particle","requestAnimationFrame","handleClick","event","cancelAnimationFrame","cn"],"mappings":"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"}