@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
JavaScript
"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