UNPKG

@helpwave/hightide

Version:

helpwave's component and theming library

299 lines (296 loc) 8.23 kB
// src/components/icons-and-geometry/Ring.tsx import { useCallback, useEffect, useState } from "react"; // src/util/noop.ts var noop = () => void 0; // src/components/icons-and-geometry/Circle.tsx import clsx from "clsx"; import { jsx } from "react/jsx-runtime"; var Circle = ({ radius = 20, className = "bg-primary", style, ...restProps }) => { const size = radius * 2; return /* @__PURE__ */ jsx( "div", { className: clsx(`rounded-full`, className), style: { width: `${size}px`, height: `${size}px`, ...style }, ...restProps } ); }; // src/components/icons-and-geometry/Ring.tsx import clsx2 from "clsx"; import { jsx as jsx2, jsxs } from "react/jsx-runtime"; var Ring = ({ innerSize = 20, width = 7, className = "outline-primary" }) => { return /* @__PURE__ */ jsx2( "div", { className: clsx2(`bg-transparent rounded-full outline`, className), style: { width: `${innerSize}px`, height: `${innerSize}px`, outlineWidth: `${width}px` } } ); }; var AnimatedRing = ({ innerSize, width, className, fillAnimationDuration = 3, repeating = false, onAnimationFinished = noop, style }) => { const [currentWidth, setCurrentWidth] = useState(0); const milliseconds = 1e3 * fillAnimationDuration; const animate = useCallback((timestamp, startTime) => { const progress = Math.min((timestamp - startTime) / milliseconds, 1); const newWidth = Math.min(width * progress, width); setCurrentWidth(newWidth); if (progress < 1) { requestAnimationFrame((newTimestamp) => animate(newTimestamp, startTime)); } else { onAnimationFinished(); if (repeating) { setCurrentWidth(0); requestAnimationFrame((newTimestamp) => animate(newTimestamp, newTimestamp)); } } }, [milliseconds, onAnimationFinished, repeating, width]); useEffect(() => { if (currentWidth < width) { requestAnimationFrame((timestamp) => animate(timestamp, timestamp)); } }, []); return /* @__PURE__ */ jsx2( "div", { className: "flex-row-2 items-center justify-center", style: { width: `${innerSize + 2 * width}px`, height: `${innerSize + 2 * width}px`, ...style }, children: /* @__PURE__ */ jsx2( Ring, { innerSize, width: currentWidth, className } ) } ); }; var RingWave = ({ startInnerSize = 20, endInnerSize = 30, width, className, fillAnimationDuration = 3, repeating = false, onAnimationFinished = noop, style }) => { const [currentInnerSize, setCurrentInnerSize] = useState(startInnerSize); const distance = endInnerSize - startInnerSize; const milliseconds = 1e3 * fillAnimationDuration; const animate = useCallback((timestamp, startTime) => { const progress = Math.min((timestamp - startTime) / milliseconds, 1); const newInnerSize = Math.min( startInnerSize + distance * progress, endInnerSize ); setCurrentInnerSize(newInnerSize); if (progress < 1) { requestAnimationFrame((newTimestamp) => animate(newTimestamp, startTime)); } else { onAnimationFinished(); if (repeating) { setCurrentInnerSize(startInnerSize); requestAnimationFrame((newTimestamp) => animate(newTimestamp, newTimestamp)); } } }, [distance, endInnerSize, milliseconds, onAnimationFinished, repeating, startInnerSize]); useEffect(() => { if (currentInnerSize < endInnerSize) { requestAnimationFrame((timestamp) => animate(timestamp, timestamp)); } }, []); return /* @__PURE__ */ jsx2( "div", { className: "flex-row-2 items-center justify-center", style: { width: `${endInnerSize + 2 * width}px`, height: `${endInnerSize + 2 * width}px`, ...style }, children: /* @__PURE__ */ jsx2( Ring, { innerSize: currentInnerSize, width, className } ) } ); }; var RadialRings = ({ circle1ClassName = "bg-primary/90 outline-primary/90", circle2ClassName = "bg-primary/60 outline-primary/60", circle3ClassName = "bg-primary/40 outline-primary/40", waveWidth = 10, waveBaseColor = "outline-white/20", sizeCircle1 = 100, sizeCircle2 = 200, sizeCircle3 = 300 }) => { const [currentRing, setCurrentRing] = useState(0); const size = sizeCircle3; return /* @__PURE__ */ jsxs( "div", { className: "relative", style: { width: `${sizeCircle3}px`, height: `${sizeCircle3}px` }, children: [ /* @__PURE__ */ jsx2( Circle, { radius: sizeCircle1 / 2, className: clsx2(circle1ClassName, `absolute z-[10] -translate-y-1/2 -translate-x-1/2`), style: { left: `${size / 2}px`, top: `${size / 2}px` } } ), currentRing === 0 ? /* @__PURE__ */ jsx2( AnimatedRing, { innerSize: sizeCircle1, width: (sizeCircle2 - sizeCircle1) / 2, onAnimationFinished: () => currentRing === 0 ? setCurrentRing(1) : null, repeating: true, className: clsx2( circle2ClassName, { "opacity-5": currentRing !== 0 } ), style: { left: `${size / 2}px`, top: `${size / 2}px`, position: "absolute", translate: `-50% -50%`, zIndex: 9 } } ) : null, currentRing === 2 ? /* @__PURE__ */ jsx2( RingWave, { startInnerSize: sizeCircle1 - waveWidth, endInnerSize: sizeCircle2, width: waveWidth, repeating: true, className: clsx2(waveBaseColor, `opacity-5`), style: { left: `${size / 2}px`, top: `${size / 2}px`, position: "absolute", translate: `-50% -50%`, zIndex: 9 } } ) : null, /* @__PURE__ */ jsx2( Circle, { radius: sizeCircle2 / 2, className: clsx2( circle2ClassName, { "opacity-20": currentRing < 1 }, `absolute z-[8] -translate-y-1/2 -translate-x-1/2` ), style: { left: `${size / 2}px`, top: `${size / 2}px` } } ), currentRing === 1 ? /* @__PURE__ */ jsx2( AnimatedRing, { innerSize: sizeCircle2 - 1, width: (sizeCircle3 - sizeCircle2) / 2, onAnimationFinished: () => currentRing === 1 ? setCurrentRing(2) : null, repeating: true, className: clsx2(circle3ClassName), style: { left: `${size / 2}px`, top: `${size / 2}px`, position: "absolute", translate: `-50% -50%`, zIndex: 7 } } ) : null, currentRing === 2 ? /* @__PURE__ */ jsx2( RingWave, { startInnerSize: sizeCircle2, endInnerSize: sizeCircle3 - waveWidth, width: waveWidth, repeating: true, className: clsx2(waveBaseColor, `opacity-5`), style: { left: `${size / 2}px`, top: `${size / 2}px`, position: "absolute", translate: `-50% -50%`, zIndex: 7 } } ) : null, /* @__PURE__ */ jsx2( Circle, { radius: sizeCircle3 / 2, className: clsx2( circle3ClassName, { "opacity-20": currentRing < 2 }, `absolute z-[6] -translate-y-1/2 -translate-x-1/2` ), style: { left: `${size / 2}px`, top: `${size / 2}px` } } ) ] } ); }; export { AnimatedRing, RadialRings, Ring, RingWave }; //# sourceMappingURL=Ring.mjs.map