@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! ⚡
361 lines (360 loc) • 14.5 kB
JavaScript
"use client";
;
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__, {
HoleBackground: ()=>HoleBackground
});
const jsx_runtime_namespaceObject = require("react/jsx-runtime");
const external_react_namespaceObject = require("react");
const react_namespaceObject = require("motion/react");
const utils_cjs_namespaceObject = require("../../lib/utils.cjs");
const HoleBackground = /*#__PURE__*/ external_react_namespaceObject.forwardRef(({ strokeColor = "#737373", numberOfLines = 50, numberOfDiscs = 50, particleRGBColor = [
255,
255,
255
], className, children, ...props }, ref)=>{
const canvasRef = external_react_namespaceObject.useRef(null);
external_react_namespaceObject.useImperativeHandle(ref, ()=>canvasRef.current);
const animationFrameIdRef = external_react_namespaceObject.useRef(0);
const stateRef = external_react_namespaceObject.useRef({
discs: [],
lines: [],
particles: [],
clip: {},
startDisc: {},
endDisc: {},
rect: {
width: 0,
height: 0
},
render: {
width: 0,
height: 0,
dpi: 1
},
particleArea: {},
linesCanvas: null
});
const linear = (p)=>p;
const easeInExpo = (p)=>0 === p ? 0 : Math.pow(2, 10 * (p - 1));
const tweenValue = external_react_namespaceObject.useCallback((start, end, p, ease = null)=>{
const delta = end - start;
const easeFn = "inExpo" === ease ? easeInExpo : linear;
return start + delta * easeFn(p);
}, []);
const tweenDisc = external_react_namespaceObject.useCallback((disc)=>{
const { startDisc, endDisc } = stateRef.current;
disc.x = tweenValue(startDisc.x, endDisc.x, disc.p);
disc.y = tweenValue(startDisc.y, endDisc.y, disc.p, "inExpo");
disc.w = tweenValue(startDisc.w, endDisc.w, disc.p);
disc.h = tweenValue(startDisc.h, endDisc.h, disc.p);
}, [
tweenValue
]);
const setSize = external_react_namespaceObject.useCallback(()=>{
const canvas = canvasRef.current;
if (!canvas) return;
const rect = canvas.getBoundingClientRect();
stateRef.current.rect = {
width: rect.width,
height: rect.height
};
stateRef.current.render = {
width: rect.width,
height: rect.height,
dpi: window.devicePixelRatio || 1
};
canvas.width = stateRef.current.render.width * stateRef.current.render.dpi;
canvas.height = stateRef.current.render.height * stateRef.current.render.dpi;
}, []);
const setDiscs = external_react_namespaceObject.useCallback(()=>{
const { width, height } = stateRef.current.rect;
stateRef.current.discs = [];
stateRef.current.startDisc = {
x: 0.5 * width,
y: 0.45 * height,
w: 0.75 * width,
h: 0.7 * height
};
stateRef.current.endDisc = {
x: 0.5 * width,
y: 0.95 * height,
w: 0,
h: 0
};
let prevBottom = height;
stateRef.current.clip = {};
for(let i = 0; i < numberOfDiscs; i++){
const p = i / numberOfDiscs;
const disc = {
p,
x: 0,
y: 0,
w: 0,
h: 0
};
tweenDisc(disc);
const bottom = disc.y + disc.h;
if (bottom <= prevBottom) stateRef.current.clip = {
disc: {
...disc
},
i
};
prevBottom = bottom;
stateRef.current.discs.push(disc);
}
const clipPath = new Path2D();
const disc = stateRef.current.clip.disc;
clipPath.ellipse(disc.x, disc.y, disc.w, disc.h, 0, 0, 2 * Math.PI);
clipPath.rect(disc.x - disc.w, 0, 2 * disc.w, disc.y);
stateRef.current.clip.path = clipPath;
}, [
tweenDisc
]);
const setLines = external_react_namespaceObject.useCallback(()=>{
const { width, height } = stateRef.current.rect;
stateRef.current.lines = [];
const linesAngle = 2 * Math.PI / numberOfLines;
for(let i = 0; i < numberOfLines; i++)stateRef.current.lines.push([]);
stateRef.current.discs.forEach((disc)=>{
for(let i = 0; i < numberOfLines; i++){
const angle = i * linesAngle;
const p = {
x: disc.x + Math.cos(angle) * disc.w,
y: disc.y + Math.sin(angle) * disc.h
};
stateRef.current.lines[i].push(p);
}
});
const offCanvas = document.createElement("canvas");
offCanvas.width = width;
offCanvas.height = height;
const ctx = offCanvas.getContext("2d");
if (!ctx) return;
stateRef.current.lines.forEach((line)=>{
ctx.save();
let lineIsIn = false;
line.forEach((p1, j)=>{
if (0 === j) return;
const p0 = line[j - 1];
if (!lineIsIn && (ctx.isPointInPath(stateRef.current.clip.path, p1.x, p1.y) || ctx.isPointInStroke(stateRef.current.clip.path, p1.x, p1.y))) lineIsIn = true;
else if (lineIsIn) ctx.clip(stateRef.current.clip.path);
ctx.beginPath();
ctx.moveTo(p0.x, p0.y);
ctx.lineTo(p1.x, p1.y);
ctx.strokeStyle = strokeColor;
ctx.lineWidth = 2;
ctx.stroke();
ctx.closePath();
});
ctx.restore();
});
stateRef.current.linesCanvas = offCanvas;
}, [
strokeColor
]);
const initParticle = external_react_namespaceObject.useCallback((start = false)=>{
const sx = stateRef.current.particleArea.sx + stateRef.current.particleArea.sw * Math.random();
const ex = stateRef.current.particleArea.ex + stateRef.current.particleArea.ew * Math.random();
const dx = ex - sx;
const y = start ? stateRef.current.particleArea.h * Math.random() : stateRef.current.particleArea.h;
const r = 0.5 + 4 * Math.random();
const vy = 0.5 + Math.random();
return {
x: sx,
sx,
dx,
y,
vy,
p: 0,
r,
c: `rgba(${particleRGBColor[0]}, ${particleRGBColor[1]}, ${particleRGBColor[2]}, ${Math.random()})`
};
}, []);
const setParticles = external_react_namespaceObject.useCallback(()=>{
const { width, height } = stateRef.current.rect;
stateRef.current.particles = [];
const disc = stateRef.current.clip.disc;
stateRef.current.particleArea = {
sw: 0.5 * disc.w,
ew: 2 * disc.w,
h: 0.85 * height
};
stateRef.current.particleArea.sx = (width - stateRef.current.particleArea.sw) / 2;
stateRef.current.particleArea.ex = (width - stateRef.current.particleArea.ew) / 2;
const totalParticles = 100;
for(let i = 0; i < totalParticles; i++)stateRef.current.particles.push(initParticle(true));
}, [
initParticle
]);
const drawDiscs = external_react_namespaceObject.useCallback((ctx)=>{
ctx.strokeStyle = strokeColor;
ctx.lineWidth = 2;
const outerDisc = stateRef.current.startDisc;
ctx.beginPath();
ctx.ellipse(outerDisc.x, outerDisc.y, outerDisc.w, outerDisc.h, 0, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
stateRef.current.discs.forEach((disc, i)=>{
if (i % 5 !== 0) return;
if (disc.w < stateRef.current.clip.disc.w - 5) {
ctx.save();
ctx.clip(stateRef.current.clip.path);
}
ctx.beginPath();
ctx.ellipse(disc.x, disc.y, disc.w, disc.h, 0, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
if (disc.w < stateRef.current.clip.disc.w - 5) ctx.restore();
});
}, [
strokeColor
]);
const drawLines = external_react_namespaceObject.useCallback((ctx)=>{
if (stateRef.current.linesCanvas) ctx.drawImage(stateRef.current.linesCanvas, 0, 0);
}, []);
const drawParticles = external_react_namespaceObject.useCallback((ctx)=>{
ctx.save();
ctx.clip(stateRef.current.clip.path);
stateRef.current.particles.forEach((particle)=>{
ctx.fillStyle = particle.c;
ctx.beginPath();
ctx.rect(particle.x, particle.y, particle.r, particle.r);
ctx.closePath();
ctx.fill();
});
ctx.restore();
}, []);
const moveDiscs = external_react_namespaceObject.useCallback(()=>{
stateRef.current.discs.forEach((disc)=>{
disc.p = (disc.p + 0.001) % 1;
tweenDisc(disc);
});
}, [
tweenDisc
]);
const moveParticles = external_react_namespaceObject.useCallback(()=>{
stateRef.current.particles.forEach((particle, idx)=>{
particle.p = 1 - particle.y / stateRef.current.particleArea.h;
particle.x = particle.sx + particle.dx * particle.p;
particle.y -= particle.vy;
if (particle.y < 0) stateRef.current.particles[idx] = initParticle();
});
}, [
initParticle
]);
const tick = external_react_namespaceObject.useCallback(()=>{
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.scale(stateRef.current.render.dpi, stateRef.current.render.dpi);
moveDiscs();
moveParticles();
drawDiscs(ctx);
drawLines(ctx);
drawParticles(ctx);
ctx.restore();
animationFrameIdRef.current = requestAnimationFrame(tick);
}, [
moveDiscs,
moveParticles,
drawDiscs,
drawLines,
drawParticles
]);
const init = external_react_namespaceObject.useCallback(()=>{
setSize();
setDiscs();
setLines();
setParticles();
}, [
setSize,
setDiscs,
setLines,
setParticles
]);
external_react_namespaceObject.useEffect(()=>{
const canvas = canvasRef.current;
if (!canvas) return;
init();
tick();
const handleResize = ()=>{
setSize();
setDiscs();
setLines();
setParticles();
};
window.addEventListener("resize", handleResize);
return ()=>{
window.removeEventListener("resize", handleResize);
cancelAnimationFrame(animationFrameIdRef.current);
};
}, [
init,
tick,
setSize,
setDiscs,
setLines,
setParticles
]);
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)("div", {
className: (0, utils_cjs_namespaceObject.cn)("relative size-full overflow-hidden", 'before:content-[""] before:absolute before:top-1/2 before:left-1/2 before:block before:size-[140%] dark:before:[background:radial-gradient(ellipse_at_50%_55%,transparent_10%,black_50%)] before:[background:radial-gradient(ellipse_at_50%_55%,transparent_10%,white_50%)] before:[transform:translate3d(-50%,-50%,0)]', 'after:content-[""] after:absolute after:z-[5] after:top-1/2 after:left-1/2 after:block after:size-full after:[background:radial-gradient(ellipse_at_50%_75%,#a900ff_20%,transparent_75%)] after:[transform:translate3d(-50%,-50%,0)] after:mix-blend-overlay', className),
children: [
children,
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("canvas", {
ref: canvasRef,
className: "absolute inset-0 block size-full dark:opacity-20 opacity-10",
...props
}),
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(react_namespaceObject.motion.div, {
className: (0, utils_cjs_namespaceObject.cn)("absolute top-[-71.5%] left-1/2 z-[3] w-[30%] h-[140%] rounded-b-full blur-3xl opacity-75 dark:mix-blend-plus-lighter mix-blend-plus-darker [transform:translate3d(-50%,0,0)] [background-position:0%_100%] [background-size:100%_200%]", "dark:[background:linear-gradient(20deg,#00f8f1,#ffbd1e20_16.5%,#fe848f_33%,#fe848f20_49.5%,#00f8f1_66%,#00f8f160_85.5%,#ffbd1e_100%)_0_100%_/_100%_200%] [background:linear-gradient(20deg,#00f8f1,#ffbd1e40_16.5%,#fe848f_33%,#fe848f40_49.5%,#00f8f1_66%,#00f8f180_85.5%,#ffbd1e_100%)_0_100%_/_100%_200%]"),
animate: {
backgroundPosition: "0% 300%"
},
transition: {
duration: 5,
ease: "linear",
repeat: 1 / 0
}
}),
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
className: "absolute top-0 left-0 z-[7] size-full dark:[background:repeating-linear-gradient(transparent,transparent_1px,white_1px,white_2px)] mix-blend-overlay opacity-50"
})
]
});
});
exports.HoleBackground = __webpack_exports__.HoleBackground;
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
"HoleBackground"
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
Object.defineProperty(exports, '__esModule', {
value: true
});
//# sourceMappingURL=hole-background.cjs.map