diff --git a/surfsense_web/components/homepage/github-stars-badge.tsx b/surfsense_web/components/homepage/github-stars-badge.tsx index 8aaeea65b..8f313db58 100644 --- a/surfsense_web/components/homepage/github-stars-badge.tsx +++ b/surfsense_web/components/homepage/github-stars-badge.tsx @@ -1,174 +1,14 @@ "use client"; import { IconBrandGithub } from "@tabler/icons-react"; -import { StarIcon } from "lucide-react"; -import type { HTMLMotionProps, UseInViewOptions } from "motion/react"; import { - AnimatePresence, motion, - useInView, useMotionValue, useSpring, - useTransform, } from "motion/react"; import * as React from "react"; import { cn } from "@/lib/utils"; -// --------------------------------------------------------------------------- -// Utilities -// --------------------------------------------------------------------------- -function getStrictContext(name?: string) { - const Context = React.createContext(undefined); - const Provider = ({ value, children }: { value: T; children?: React.ReactNode }) => ( - {children} - ); - const useSafeContext = () => { - const ctx = React.useContext(Context); - if (ctx === undefined) { - throw new Error(`useContext must be used within ${name ?? "a Provider"}`); - } - return ctx; - }; - return [Provider, useSafeContext] as const; -} - -interface UseIsInViewOptions { - inView?: boolean; - inViewOnce?: boolean; - inViewMargin?: UseInViewOptions["margin"]; -} - -function useIsInView( - ref: React.Ref, - options: UseIsInViewOptions = {} -) { - const { inView, inViewOnce = false, inViewMargin = "0px" } = options; - const localRef = React.useRef(null); - React.useImperativeHandle(ref, () => localRef.current as T); - const inViewResult = useInView(localRef, { - once: inViewOnce, - margin: inViewMargin, - }); - const isInView = !inView || inViewResult; - return { ref: localRef, isInView }; -} - -// --------------------------------------------------------------------------- -// Particles (for star burst effect on completion) -// --------------------------------------------------------------------------- -type ParticlesContextType = { animate: boolean; isInView: boolean }; -const [ParticlesProvider, useParticles] = - getStrictContext("ParticlesContext"); - -function Particles({ - ref, - animate = true, - inView = false, - inViewMargin = "0px", - inViewOnce = true, - children, - style, - ...props -}: Omit, "children"> & { - animate?: boolean; - children: React.ReactNode; -} & UseIsInViewOptions) { - const { ref: localRef, isInView } = useIsInView(ref as React.Ref, { - inView, - inViewOnce, - inViewMargin, - }); - return ( - - - {children} - - - ); -} - -function ParticlesEffect({ - side = "top", - align = "center", - count = 6, - radius = 30, - spread = 360, - duration = 0.8, - holdDelay = 0.05, - sideOffset = 0, - alignOffset = 0, - delay = 0, - transition, - style, - ...props -}: Omit, "children"> & { - side?: "top" | "bottom" | "left" | "right"; - align?: "start" | "center" | "end"; - count?: number; - radius?: number; - spread?: number; - duration?: number; - holdDelay?: number; - sideOffset?: number; - alignOffset?: number; - delay?: number; -}) { - const { animate, isInView } = useParticles(); - const isVertical = side === "top" || side === "bottom"; - const alignPct = align === "start" ? "0%" : align === "end" ? "100%" : "50%"; - - const top = isVertical - ? side === "top" - ? `calc(0% - ${sideOffset}px)` - : `calc(100% + ${sideOffset}px)` - : `calc(${alignPct} + ${alignOffset}px)`; - const left = isVertical - ? `calc(${alignPct} + ${alignOffset}px)` - : side === "left" - ? `calc(0% - ${sideOffset}px)` - : `calc(100% + ${sideOffset}px)`; - - const containerStyle: React.CSSProperties = { - position: "absolute", - top, - left, - transform: "translate(-50%, -50%)", - }; - const angleStep = (spread * (Math.PI / 180)) / Math.max(1, count - 1); - - return ( - - {animate && - isInView && - [...Array(count)].map((_, i) => { - const angle = i * angleStep; - const x = Math.cos(angle) * radius; - const y = Math.sin(angle) * radius; - return ( - - ); - })} - - ); -} - // --------------------------------------------------------------------------- // Per-digit scrolling wheel // --------------------------------------------------------------------------- @@ -409,11 +249,6 @@ function NavbarGitHubStars({ }: NavbarGitHubStarsProps) { const [stars, setStars] = React.useState(0); const [isLoading, setIsLoading] = React.useState(true); - const [isCompleted, setIsCompleted] = React.useState(false); - - const fillRaw = useMotionValue(0); - const fillSpring = useSpring(fillRaw, { stiffness: 12, damping: 14 }); - const clipPath = useTransform(fillSpring, (v) => `inset(${100 - v * 100}% 0 0 0)`); React.useEffect(() => { const abortController = new AbortController(); @@ -424,7 +259,6 @@ function NavbarGitHubStars({ .then((data) => { if (data && typeof data.stargazers_count === "number") { setStars(data.stargazers_count); - fillRaw.set(1); } }) .catch((err) => { @@ -434,7 +268,7 @@ function NavbarGitHubStars({ }) .finally(() => setIsLoading(false)); return () => abortController.abort(); - }, [username, repo, fillRaw]); + }, [username, repo]); return ( -
- setIsCompleted(true)} - /> - -
-
- -
-
+
); }