{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "primitives-animate-github-stars",
  "title": "Github Stars",
  "description": "A component that animates a number of stars, smoothly animating number transitions using the SlidingNumber component.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "@animate-ui/primitives-animate-slot",
    "@animate-ui/primitives-texts-sliding-number",
    "@animate-ui/primitives-effects-particles",
    "@animate-ui/hooks-use-is-in-view",
    "@animate-ui/lib-get-strict-context"
  ],
  "files": [
    {
      "path": "registry/primitives/animate/github-stars/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { motion, type HTMLMotionProps } from 'motion/react';\n\nimport {\n  useIsInView,\n  type UseIsInViewOptions,\n} from '@/hooks/use-is-in-view';\nimport { getStrictContext } from '@/lib/get-strict-context';\nimport { Slot, type WithAsChild } from '@/components/animate-ui/primitives/animate/slot';\nimport {\n  SlidingNumber,\n  type SlidingNumberProps,\n} from '@/components/animate-ui/primitives/texts/sliding-number';\nimport {\n  Particles,\n  ParticlesEffect,\n  type ParticlesEffectProps,\n} from '@/components/animate-ui/primitives/effects/particles';\nimport { cn } from '@/lib/utils';\n\ntype GithubStarsContextType = {\n  stars: number;\n  setStars: (stars: number) => void;\n  currentStars: number;\n  setCurrentStars: (stars: number) => void;\n  isCompleted: boolean;\n  isLoading: boolean;\n};\n\nconst [GithubStarsProvider, useGithubStars] =\n  getStrictContext<GithubStarsContextType>('GithubStarsContext');\n\ntype GithubStarsProps = WithAsChild<\n  {\n    children: React.ReactNode;\n    username?: string;\n    repo?: string;\n    value?: number;\n    delay?: number;\n  } & UseIsInViewOptions &\n    HTMLMotionProps<'div'>\n>;\n\nfunction GithubStars({\n  ref,\n  children,\n  username,\n  repo,\n  value,\n  delay = 0,\n  inView = false,\n  inViewMargin = '0px',\n  inViewOnce = true,\n  asChild = false,\n  ...props\n}: GithubStarsProps) {\n  const { ref: localRef, isInView } = useIsInView(\n    ref as React.Ref<HTMLDivElement>,\n    { inView, inViewOnce, inViewMargin },\n  );\n\n  const [stars, setStars] = React.useState(value ?? 0);\n  const [currentStars, setCurrentStars] = React.useState(0);\n  const [isLoading, setIsLoading] = React.useState(true);\n  const isCompleted = React.useMemo(\n    () => currentStars === stars,\n    [currentStars, stars],\n  );\n\n  const Component = asChild ? Slot : motion.div;\n\n  React.useEffect(() => {\n    if (value !== undefined && username && repo) return;\n    if (!isInView) {\n      setStars(0);\n      setIsLoading(true);\n      return;\n    }\n\n    const timeout = setTimeout(() => {\n      fetch(`https://api.github.com/repos/${username}/${repo}`)\n        .then((response) => response.json())\n        .then((data) => {\n          if (data && typeof data.stargazers_count === 'number') {\n            setStars(data.stargazers_count);\n          }\n        })\n        .catch(console.error)\n        .finally(() => setIsLoading(false));\n    }, delay);\n\n    return () => clearTimeout(timeout);\n  }, [username, repo, value, isInView, delay]);\n\n  return (\n    <GithubStarsProvider\n      value={{\n        stars,\n        currentStars,\n        isCompleted,\n        isLoading,\n        setStars,\n        setCurrentStars,\n      }}\n    >\n      {!isLoading && (\n        <Component ref={localRef} {...props}>\n          {children}\n        </Component>\n      )}\n    </GithubStarsProvider>\n  );\n}\n\ntype GithubStarsNumberProps = Omit<SlidingNumberProps, 'number' | 'fromNumber'>;\n\nfunction GithubStarsNumber({\n  padStart = true,\n  ...props\n}: GithubStarsNumberProps) {\n  const { stars, setCurrentStars } = useGithubStars();\n\n  return (\n    <SlidingNumber\n      number={stars}\n      fromNumber={0}\n      onNumberChange={setCurrentStars}\n      padStart={padStart}\n      {...props}\n    />\n  );\n}\n\ntype GithubStarsIconProps<T extends React.ElementType> = {\n  icon: React.ReactElement<T>;\n  color?: string;\n  activeClassName?: string;\n} & React.ComponentProps<T>;\n\nfunction GithubStarsIcon<T extends React.ElementType>({\n  icon: Icon,\n  color = 'currentColor',\n  activeClassName,\n  className,\n  ...props\n}: GithubStarsIconProps<T>) {\n  const { stars, currentStars, isCompleted } = useGithubStars();\n  const fillPercentage = (currentStars / stars) * 100;\n\n  return (\n    <div style={{ position: 'relative' }}>\n      <Icon aria-hidden=\"true\" className={cn(className)} {...props} />\n      <Icon\n        aria-hidden=\"true\"\n        style={{\n          position: 'absolute',\n          top: 0,\n          left: 0,\n          fill: color,\n          stroke: color,\n          clipPath: `inset(${100 - (isCompleted ? fillPercentage : fillPercentage - 10)}% 0 0 0)`,\n        }}\n        className={cn(className, activeClassName)}\n        {...props}\n      />\n    </div>\n  );\n}\n\ntype GithubStarsParticlesProps = ParticlesEffectProps & {\n  children: React.ReactElement;\n  size?: number;\n};\n\nfunction GithubStarsParticles({\n  children,\n  size = 4,\n  style,\n  ...props\n}: GithubStarsParticlesProps) {\n  const { isCompleted } = useGithubStars();\n\n  return (\n    <Particles animate={isCompleted}>\n      {children}\n      <ParticlesEffect\n        style={{\n          backgroundColor: 'currentcolor',\n          borderRadius: '50%',\n          width: size,\n          height: size,\n          ...style,\n        }}\n        {...props}\n      />\n    </Particles>\n  );\n}\n\ntype GithubStarsLogoProps = React.SVGProps<SVGSVGElement>;\n\nfunction GithubStarsLogo(props: GithubStarsLogoProps) {\n  return (\n    <svg\n      role=\"img\"\n      viewBox=\"0 0 24 24\"\n      fill=\"currentColor\"\n      aria-label=\"GitHub\"\n      {...props}\n    >\n      <path d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"></path>\n    </svg>\n  );\n}\n\nexport {\n  GithubStars,\n  GithubStarsNumber,\n  GithubStarsIcon,\n  GithubStarsParticles,\n  GithubStarsLogo,\n  useGithubStars,\n  type GithubStarsProps,\n  type GithubStarsNumberProps,\n  type GithubStarsIconProps,\n  type GithubStarsParticlesProps,\n  type GithubStarsLogoProps,\n  type GithubStarsContextType,\n};\n",
      "type": "registry:ui",
      "target": "components/animate-ui/primitives/animate/github-stars.tsx"
    }
  ],
  "type": "registry:ui"
}