UNPKG

@arolariu/components

Version:

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

259 lines (258 loc) • 9.25 kB
"use client"; "use strict"; var __webpack_require__ = {}; (()=>{ __webpack_require__.d = (exports1, definition)=>{ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, { enumerable: true, get: definition[key] }); }; })(); (()=>{ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop); })(); (()=>{ __webpack_require__.r = (exports1)=>{ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, { value: 'Module' }); Object.defineProperty(exports1, '__esModule', { value: true }); }; })(); var __webpack_exports__ = {}; __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { FireworksBackground: ()=>FireworksBackground }); const jsx_runtime_namespaceObject = require("react/jsx-runtime"); const external_react_namespaceObject = require("react"); const utils_cjs_namespaceObject = require("../../lib/utils.cjs"); 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 numParticles = randInt(50, 150); const particles = []; for(let i = 0; i < numParticles; i++){ 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)]; return color ?? randColor(); }; const FireworksBackground = /*#__PURE__*/ external_react_namespaceObject.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 = external_react_namespaceObject.useRef(null); const containerRef = external_react_namespaceObject.useRef(null); external_react_namespaceObject.useImperativeHandle(ref, ()=>containerRef.current); external_react_namespaceObject.useEffect(()=>{ const canvas = canvasRef.current; const container = containerRef.current; if (!canvas || !container) return; const ctx = canvas.getContext("2d"); if (!ctx) return; let maxX = window.innerWidth; let ratio = container.offsetHeight / container.offsetWidth; let maxY = maxX * ratio; canvas.width = maxX; canvas.height = maxY; const setCanvasSize = ()=>{ maxX = window.innerWidth; ratio = container.offsetHeight / container.offsetWidth; maxY = maxX * ratio; canvas.width = maxX; canvas.height = maxY; }; 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; setTimeout(launchFirework, timeout); }; launchFirework(); let animationFrameId; const animate = ()=>{ ctx.clearRect(0, 0, maxX, maxY); for(let i = fireworks.length - 1; i >= 0; i--){ const firework = fireworks[i]; if (firework.update()) firework.draw(ctx); else fireworks.splice(i, 1); } for(let i = explosions.length - 1; i >= 0; i--){ const particle = explosions[i]; particle.update(); if (particle.isAlive()) particle.draw(ctx); else explosions.splice(i, 1); } animationFrameId = requestAnimationFrame(animate); }; animate(); const handleClick = (event)=>{ const x = event.clientX; const y = maxY; const targetY = event.clientY; const fireworkColor = getColor(color); const speed = getValueByRange(fireworkSpeed); const size = getValueByRange(fireworkSize); fireworks.push(createFirework(x, y, targetY, fireworkColor, speed, size, particleSpeed, particleSize, handleExplosion)); }; container.addEventListener("click", handleClick); return ()=>{ window.removeEventListener("resize", setCanvasSize); container.removeEventListener("click", handleClick); cancelAnimationFrame(animationFrameId); }; }, [ population, color, fireworkSpeed, fireworkSize, particleSpeed, particleSize ]); return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", { ref: containerRef, className: (0, utils_cjs_namespaceObject.cn)("relative size-full overflow-hidden", className), ...props, children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("canvas", { ...canvasProps, ref: canvasRef, className: (0, utils_cjs_namespaceObject.cn)("absolute inset-0 size-full", canvasProps?.className) }) }); }); FireworksBackground.displayName = "FireworksBackground"; exports.FireworksBackground = __webpack_exports__.FireworksBackground; for(var __webpack_i__ in __webpack_exports__)if (-1 === [ "FireworksBackground" ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__]; Object.defineProperty(exports, '__esModule', { value: true }); //# sourceMappingURL=fireworks-background.cjs.map