{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "bug-01",
  "title": "bug-01",
  "description": "Animated bug icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/bug-01.tsx",
      "content": "'use client';\n\nimport type { Variants } from 'motion/react';\nimport { motion, useAnimation } from 'motion/react';\nimport type { HTMLAttributes } from 'react';\nimport { forwardRef } from 'react';\nimport { useIconAnimation } from '@/lib/use-icon-animation';\nimport { cn } from '@/lib/utils';\n\nexport interface Bug01IconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface Bug01IconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// six deliberately mismatched leg cycles drift in and out of phase while the\n// shell makes a small irregular weight shift\nconst bugVariants: Variants = {\n  normal: {\n    transform: 'translate(0px, 0px) rotate(0deg)',\n    transition: { type: 'spring', duration: 0.32, bounce: 0 },\n  },\n  animate: {\n    transform: [\n      'translate(0px, 0px) rotate(0deg)',\n      'translate(0.42px, -0.45px) rotate(-0.9deg)',\n      'translate(-0.28px, -0.12px) rotate(0.65deg)',\n      'translate(0.55px, 0.08px) rotate(-1.15deg)',\n      'translate(-0.4px, -0.36px) rotate(1deg)',\n      'translate(0.18px, -0.52px) rotate(-0.4deg)',\n      'translate(0px, 0px) rotate(0deg)',\n    ],\n    transition: {\n      duration: 1.12,\n      ease: [0.77, 0, 0.175, 1],\n      times: [0, 0.13, 0.31, 0.46, 0.68, 0.82, 1],\n      repeat: Infinity,\n    },\n  },\n};\n\ninterface LegMotion {\n  angles: number[];\n  delay: number;\n  duration: number;\n  times: number[];\n}\n\nconst DEFAULT_LEG_MOTION: LegMotion = {\n  angles: [0, 18, -7, 25, -15, 9, -22, 0],\n  delay: 0,\n  duration: 0.83,\n  times: [0, 0.11, 0.24, 0.39, 0.55, 0.7, 0.86, 1],\n};\n\nconst LEG_MOTIONS: readonly LegMotion[] = [\n  DEFAULT_LEG_MOTION,\n  {\n    angles: [0, -12, 23, -19, 8, -25, 14, 0],\n    delay: 0.05,\n    duration: 0.91,\n    times: [0, 0.16, 0.29, 0.43, 0.6, 0.76, 0.9, 1],\n  },\n  {\n    angles: [0, 21, -16, 7, -24, 18, -9, 0],\n    delay: 0.11,\n    duration: 0.84,\n    times: [0, 0.09, 0.22, 0.38, 0.57, 0.71, 0.89, 1],\n  },\n  {\n    angles: [0, -22, 11, -17, 24, -6, 15, 0],\n    delay: 0.02,\n    duration: 1.03,\n    times: [0, 0.14, 0.31, 0.45, 0.62, 0.78, 0.91, 1],\n  },\n  {\n    angles: [0, 14, -20, 9, -16, 22, -7, 0],\n    delay: 0.14,\n    duration: 0.88,\n    times: [0, 0.12, 0.26, 0.47, 0.59, 0.74, 0.87, 1],\n  },\n  {\n    angles: [0, -18, 8, -22, 16, -10, 20, 0],\n    delay: 0.08,\n    duration: 0.96,\n    times: [0, 0.18, 0.33, 0.48, 0.64, 0.79, 0.92, 1],\n  },\n];\n\nconst randomLegVariants: Variants = {\n  normal: { transform: 'rotate(0deg)' },\n  animate: (legIndex: number) => {\n    const legMotion = LEG_MOTIONS[legIndex] ?? DEFAULT_LEG_MOTION;\n\n    return {\n      transform: legMotion.angles.map((angle) => `rotate(${angle}deg)`),\n      transition: {\n        delay: legMotion.delay,\n        duration: legMotion.duration,\n        ease: 'linear',\n        times: legMotion.times,\n        repeat: Infinity,\n      },\n    };\n  },\n};\n\nconst Bug01Icon = forwardRef<Bug01IconHandle, Bug01IconProps>(\n  ({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => {\n    const controls = useAnimation();\n    const { handleMouseEnter, handleMouseLeave } = useIconAnimation({\n      controls,\n      loops: true,\n      onMouseEnter,\n      onMouseLeave,\n      ref,\n    });\n\n    return (\n      <div\n        className={cn(className)}\n        onMouseEnter={handleMouseEnter}\n        onMouseLeave={handleMouseLeave}\n        {...props}\n      >\n        <motion.svg\n          xmlns=\"http://www.w3.org/2000/svg\"\n          width={size}\n          height={size}\n          viewBox=\"0 0 24 24\"\n          fill=\"none\"\n          overflow=\"visible\"\n          variants={bugVariants}\n          animate={controls}\n          initial=\"normal\"\n          style={{ transformBox: 'view-box', originX: 0.5, originY: 12.5 / 24 }}\n        >\n          <motion.path\n            d=\"M3.01309 4.99084C2.89323 6.05084 3.55249 8.42285 6.48923 8.42285\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={randomLegVariants}\n            custom={0}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformBox: 'view-box', originX: 6.5 / 24, originY: 8.4 / 24 }}\n          />\n          <motion.path\n            d=\"M17.5951 8.38081C18.8357 8.57881 21.1132 7.49881 20.9957 5.00281\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={randomLegVariants}\n            custom={1}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformBox: 'view-box', originX: 17.6 / 24, originY: 8.4 / 24 }}\n          />\n          <motion.path\n            d=\"M20.9928 20.9989C21.0528 19.9429 20.1777 17.5549 17.599 17.4229\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={randomLegVariants}\n            custom={2}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformBox: 'view-box', originX: 17.6 / 24, originY: 17.4 / 24 }}\n          />\n          <motion.path\n            d=\"M6.45163 17.4708C5.65013 17.2308 3.01306 18.3348 3.01306 20.9988\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={randomLegVariants}\n            custom={3}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformBox: 'view-box', originX: 6.45 / 24, originY: 17.47 / 24 }}\n          />\n          <path\n            d=\"M9.3299 6.11884C9.35388 5.09884 9.84533 2.99884 12.0029 2.99884C13.9208 2.99884 14.5861 4.61884 14.676 6.11884M6.26131 9.41884C6.38118 8.63884 7.29216 6.81484 9.36586 6.63484C11.4635 6.55564 14.3403 6.58684 14.8797 6.67084C15.5869 6.73377 17.2951 7.43884 17.7506 9.41884C17.9124 10.4388 17.8285 11.8788 17.8524 12.7188C17.8165 13.5588 17.9207 15.2623 17.7565 16.1388C17.6367 17.0988 16.9894 18.4668 16.1024 19.3068C14.7838 20.7228 11.1639 22.2108 8.03534 19.4508C6.41713 17.8908 6.30925 16.3788 6.18939 15.7788C6.15725 15.4571 6.15875 13.8763 6.16541 12.3588C6.14144 11.046 6.17235 9.78063 6.26131 9.41884Z\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1.5\"\n          />\n          <motion.path\n            d=\"M3.01306 12.8988H5.9498\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={randomLegVariants}\n            custom={4}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformBox: 'view-box', originX: 5.95 / 24, originY: 12.9 / 24 }}\n          />\n          <motion.path\n            d=\"M20.9929 12.8988L18.1161 12.8988\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={randomLegVariants}\n            custom={5}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformBox: 'view-box', originX: 18.12 / 24, originY: 12.9 / 24 }}\n          />\n          <path\n            d=\"M12.0033 16.4988L12.0033 20.2788\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n          />\n        </motion.svg>\n      </div>\n    );\n  }\n);\n\nBug01Icon.displayName = 'Bug01Icon';\n\nexport { Bug01Icon };\n",
      "type": "registry:ui"
    },
    {
      "path": "lib/use-icon-animation.ts",
      "content": "'use client';\n\nimport type { LegacyAnimationControls } from 'motion/react';\nimport { useReducedMotion } from 'motion/react';\nimport type {\n  ForwardedRef,\n  MouseEventHandler,\n} from 'react';\nimport { useCallback, useImperativeHandle, useRef } from 'react';\n\nexport interface AnimatedIconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface UseIconAnimationOptions {\n  controls: LegacyAnimationControls;\n  loops?: boolean;\n  onMouseEnter?: MouseEventHandler<HTMLDivElement>;\n  onMouseLeave?: MouseEventHandler<HTMLDivElement>;\n  ref: ForwardedRef<AnimatedIconHandle>;\n}\n\nexport function useIconAnimation({\n  controls,\n  loops = false,\n  onMouseEnter,\n  onMouseLeave,\n  ref,\n}: UseIconAnimationOptions) {\n  const shouldReduceMotion = useReducedMotion();\n  const isControlledRef = useRef(false);\n  const isPlayingRef = useRef(false);\n  const runRef = useRef(0);\n\n  const startAnimation = useCallback(() => {\n    if (shouldReduceMotion || isPlayingRef.current) return;\n\n    isPlayingRef.current = true;\n    const run = ++runRef.current;\n    controls.set('normal');\n    void controls.start('animate').then(() => {\n      if (runRef.current === run) isPlayingRef.current = false;\n    });\n  }, [controls, shouldReduceMotion]);\n\n  const stopAnimation = useCallback(() => {\n    if (!loops) return;\n\n    runRef.current++;\n    isPlayingRef.current = false;\n    void controls.start('normal');\n  }, [controls, loops]);\n\n  useImperativeHandle(\n    ref,\n    () => {\n      isControlledRef.current = true;\n      return { startAnimation, stopAnimation };\n    },\n    [startAnimation, stopAnimation]\n  );\n\n  const handleMouseEnter = useCallback<MouseEventHandler<HTMLDivElement>>(\n    (event) => {\n      onMouseEnter?.(event);\n      if (!isControlledRef.current) startAnimation();\n    },\n    [onMouseEnter, startAnimation]\n  );\n\n  const handleMouseLeave = useCallback<MouseEventHandler<HTMLDivElement>>(\n    (event) => {\n      onMouseLeave?.(event);\n      if (!isControlledRef.current) stopAnimation();\n    },\n    [onMouseLeave, stopAnimation]\n  );\n\n  return { handleMouseEnter, handleMouseLeave };\n}\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:ui"
}