UNPKG

@arolariu/components

Version:

🎨 70+ beautiful, accessible React components built on Base UI. TypeScript-first, CSS Modules styling, tree-shakeable, SSR-ready. Perfect for modern web apps, design systems & rapid prototyping. Zero config, maximum flexibility! ⚡

226 lines (225 loc) • 8.18 kB
"use client"; import { jsx } from "react/jsx-runtime"; import { cn } from "../../lib/utilities.js"; import fireworks_background_module from "./fireworks-background.module.js"; import * as __rspack_external_react from "react"; const rand = (min, max)=>Math.random() * (max - min) + min; const randInt = (min, max)=>Math.floor(Math.random() * (max - min) + min); const randColor = ()=>`hsl(${randInt(0, 360)}, 100%, 50%)`; const createParticle = (x, y, color, speed, direction, gravity, friction, size)=>{ const vx = Math.cos(direction) * speed; const vy = Math.sin(direction) * speed; const alpha = 1; const decay = rand(0.005, 0.02); return { x, y, color, speed, direction, vx, vy, gravity, friction, alpha, decay, size, update () { this.vx *= this.friction; this.vy *= this.friction; this.vy += this.gravity; this.x += this.vx; this.y += this.vy; this.alpha -= this.decay; }, draw (ctx) { ctx.save(); ctx.globalAlpha = this.alpha; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); ctx.fillStyle = this.color; ctx.fill(); ctx.restore(); }, isAlive () { return this.alpha > 0; } }; }; const createFirework = (x, y, targetY, color, speed, size, particleSpeed, particleSize, onExplode)=>{ const angle = -Math.PI / 2 + rand(-0.3, 0.3); const vx = Math.cos(angle) * speed; const vy = Math.sin(angle) * speed; const trail = []; const trailLength = randInt(10, 25); return { x, y, targetY, color, speed, size, angle, vx, vy, trail, trailLength, exploded: false, update () { this.trail.push({ x: this.x, y: this.y }); if (this.trail.length > this.trailLength) this.trail.shift(); this.x += this.vx; this.y += this.vy; this.vy += 0.02; if (this.vy >= 0 || this.y <= this.targetY) { this.explode(); return false; } return true; }, explode () { const numberOfParticles = randInt(50, 150); const particles = []; for(let index = 0; index < numberOfParticles; index += 1){ const particleAngle = rand(0, 2 * Math.PI); const localParticleSpeed = getValueByRange(particleSpeed); const localParticleSize = getValueByRange(particleSize); particles.push(createParticle(this.x, this.y, this.color, localParticleSpeed, particleAngle, 0.05, 0.98, localParticleSize)); } onExplode(particles); }, draw (ctx) { ctx.save(); ctx.beginPath(); if (this.trail.length > 1) { ctx.moveTo(this.trail[0].x, this.trail[0].y); for (const point of this.trail)ctx.lineTo(point.x, point.y); } else { ctx.moveTo(this.x, this.y); ctx.lineTo(this.x, this.y); } ctx.strokeStyle = this.color; ctx.lineWidth = this.size; ctx.lineCap = "round"; ctx.stroke(); ctx.restore(); } }; }; const getValueByRange = (range)=>{ if ("number" == typeof range) return range; return rand(range.min, range.max); }; const getColor = (color)=>{ if (Array.isArray(color)) return color[randInt(0, color.length)] ?? randColor(); if ("string" == typeof color) return color; return randColor(); }; const FireworksBackground = /*#__PURE__*/ __rspack_external_react.forwardRef(({ className, canvasProps, population = 1, color, fireworkSpeed = { min: 4, max: 8 }, fireworkSize = { min: 2, max: 5 }, particleSpeed = { min: 2, max: 7 }, particleSize = { min: 1, max: 5 }, ...props }, ref)=>{ const canvasRef = __rspack_external_react.useRef(null); const containerRef = __rspack_external_react.useRef(null); __rspack_external_react.useImperativeHandle(ref, ()=>containerRef.current, []); __rspack_external_react.useEffect(()=>{ const canvas = canvasRef.current; const container = containerRef.current; if (!canvas || !container) return; const context = canvas.getContext("2d"); if (!context) return; let maxX = globalThis.window.innerWidth; let ratio = container.offsetHeight / Math.max(container.offsetWidth, 1); let maxY = maxX * ratio; let launchTimeoutId = 0; canvas.width = maxX; canvas.height = maxY; const setCanvasSize = ()=>{ maxX = globalThis.window.innerWidth; ratio = container.offsetHeight / Math.max(container.offsetWidth, 1); maxY = maxX * ratio; canvas.width = maxX; canvas.height = maxY; }; globalThis.window.addEventListener("resize", setCanvasSize); const explosions = []; const fireworks = []; const handleExplosion = (particles)=>{ explosions.push(...particles); }; const launchFirework = ()=>{ const x = rand(0.1 * maxX, 0.9 * maxX); const y = maxY; const targetY = rand(0.1 * maxY, 0.4 * maxY); const fireworkColor = getColor(color); const speed = getValueByRange(fireworkSpeed); const size = getValueByRange(fireworkSize); fireworks.push(createFirework(x, y, targetY, fireworkColor, speed, size, particleSpeed, particleSize, handleExplosion)); const timeout = rand(300, 800) / population; launchTimeoutId = globalThis.window.setTimeout(launchFirework, timeout); }; launchFirework(); let animationFrameId = 0; const animate = ()=>{ context.clearRect(0, 0, maxX, maxY); for(let index = fireworks.length - 1; index >= 0; index -= 1){ const firework = fireworks[index]; if (firework.update()) firework.draw(context); else fireworks.splice(index, 1); } for(let index = explosions.length - 1; index >= 0; index -= 1){ const particle = explosions[index]; particle.update(); if (particle.isAlive()) particle.draw(context); else explosions.splice(index, 1); } animationFrameId = globalThis.requestAnimationFrame(animate); }; animate(); const handleClick = (event)=>{ const fireworkColor = getColor(color); const speed = getValueByRange(fireworkSpeed); const size = getValueByRange(fireworkSize); fireworks.push(createFirework(event.clientX, maxY, event.clientY, fireworkColor, speed, size, particleSpeed, particleSize, handleExplosion)); }; container.addEventListener("click", handleClick); return ()=>{ globalThis.window.removeEventListener("resize", setCanvasSize); container.removeEventListener("click", handleClick); globalThis.window.clearTimeout(launchTimeoutId); globalThis.cancelAnimationFrame(animationFrameId); }; }, [ color, fireworkSize, fireworkSpeed, particleSize, particleSpeed, population ]); return /*#__PURE__*/ jsx("div", { ref: containerRef, className: cn(fireworks_background_module.root, className), ...props, children: /*#__PURE__*/ jsx("canvas", { ...canvasProps, ref: canvasRef, className: cn(fireworks_background_module.canvas, canvasProps?.className) }) }); }); FireworksBackground.displayName = "FireworksBackground"; export { FireworksBackground }; //# sourceMappingURL=fireworks-background.js.map