{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "bulb",
  "title": "bulb",
  "description": "Animated bulb icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/bulb.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 BulbIconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface BulbIconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// a current climbs the stem, energizes the filament, and flexes the glass\n// before five well-spaced rays draw outward\nconst glassVariants: Variants = {\n  normal: { transform: 'translateY(0px) scale(1, 1)' },\n  animate: {\n    transform: [\n      'translateY(0px) scale(1, 1)',\n      'translateY(0.35px) scale(0.97, 0.94)',\n      'translateY(-0.55px) scale(1.045, 1.06)',\n      'translateY(0.1px) scale(0.995, 0.99)',\n      'translateY(0px) scale(1, 1)',\n    ],\n    transition: { duration: 0.58, delay: 0.08, ease: [0.23, 1, 0.32, 1], times: [0, 0.24, 0.52, 0.78, 1] },\n  },\n};\n\nconst filamentVariants: Variants = {\n  normal: { pathLength: 1, visibility: 'visible', transform: 'scaleX(1)' },\n  animate: {\n    pathLength: [1, 0.35, 1, 1],\n    visibility: ['visible', 'visible', 'visible', 'visible'],\n    transform: ['scaleX(1)', 'scaleX(0.78)', 'scaleX(1.14)', 'scaleX(1)'],\n    transition: { duration: 0.5, delay: 0.05, ease: [0.23, 1, 0.32, 1], times: [0, 0.22, 0.62, 1] },\n  },\n};\n\nconst currentVariants: Variants = {\n  normal: { pathLength: 1, visibility: 'visible' },\n  animate: {\n    pathLength: [1, 0.12, 1, 1],\n    visibility: ['visible', 'visible', 'visible', 'visible'],\n    transition: { duration: 0.42, ease: [0.23, 1, 0.32, 1], times: [0, 0.2, 0.7, 1] },\n  },\n};\n\ntype LightRay = { x: number; y: number; delay: number };\n\nconst rayVariants: Variants = {\n  normal: ({ x, y }: LightRay) => ({\n    visibility: 'hidden',\n    pathLength: 0,\n    transform: 'translate(' + -x + 'px, ' + -y + 'px)',\n  }),\n  animate: ({ x, y, delay }: LightRay) => ({\n    visibility: ['hidden', 'visible', 'visible'],\n    pathLength: [0, 1, 1],\n    transform: [\n      'translate(' + -x + 'px, ' + -y + 'px)',\n      'translate(0px, 0px)',\n      'translate(' + x * 0.18 + 'px, ' + y * 0.18 + 'px)',\n    ],\n    transition: {\n      duration: 0.48,\n      ease: [0.23, 1, 0.32, 1],\n      times: [0, 0.68, 1],\n      delay: 0.18 + delay,\n    },\n  }),\n};\nconst generatedGeometryVariants: Variants = {\n  normal: { visibility: 'hidden', transition: { duration: 0.08 } },\n  animate: { visibility: 'visible', transition: { duration: 0.08 } },\n};\n\n\nconst BulbIcon = forwardRef<BulbIconHandle, BulbIconProps>(\n  ({ onMouseEnter, onMouseLeave, className, size = 28, ...props }, ref) => {\n    const controls = useAnimation();\n    const { handleMouseEnter, handleMouseLeave } = useIconAnimation({\n      controls,\n      loops: false,\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        <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        >\n          <motion.path\n            d=\"M5.14286 14C4.41735 12.8082 4 11.4118 4 9.91886C4 5.54539 7.58172 2 12 2C16.4183 2 20 5.54539 20 9.91886C20 11.4118 19.5827 12.8082 18.8571 14\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={glassVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '12px 14px' }}\n          />\n          <motion.path\n            d=\"M14 10C13.3875 10.6432 12.7111 11 12 11C11.2889 11 10.6125 10.6432 10 10\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={filamentVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '12px 10.5px' }}\n          />\n          <path\n            d=\"M7.38287 17.0982C7.291 16.8216 7.24507 16.6833 7.25042 16.5713C7.26174 16.3343 7.41114 16.1262 7.63157 16.0405C7.73579 16 7.88105 16 8.17157 16H15.8284C16.119 16 16.2642 16 16.3684 16.0405C16.5889 16.1262 16.7383 16.3343 16.7496 16.5713C16.7549 16.6833 16.709 16.8216 16.6171 17.0982C16.4473 17.6094 16.3624 17.8651 16.2315 18.072C15.9572 18.5056 15.5272 18.8167 15.0306 18.9408C14.7935 19 14.525 19 13.9881 19H10.0119C9.47495 19 9.2065 19 8.96944 18.9408C8.47283 18.8167 8.04281 18.5056 7.7685 18.072C7.63755 17.8651 7.55266 17.6094 7.38287 17.0982Z\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1.5\"\n          />\n          <path\n            d=\"M15 19L14.8707 19.6466C14.7293 20.3537 14.6586 20.7072 14.5001 20.9866C14.2552 21.4185 13.8582 21.7439 13.3866 21.8994C13.0816 22 12.7211 22 12 22C11.2789 22 10.9184 22 10.6134 21.8994C10.1418 21.7439 9.74484 21.4185 9.49987 20.9866C9.34144 20.7072 9.27073 20.3537 9.12932 19.6466L9 19\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1.5\"\n          />\n          <motion.path\n            d=\"M12 15.5V11\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={currentVariants}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.g\n            variants={generatedGeometryVariants}\n            animate={controls}\n            initial=\"normal\"\n          >\n          <motion.path\n            d=\"M12 0V-1.8\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={rayVariants}\n            custom={{ x: 0, y: -0.8, delay: 0.08 }}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M5 2.2L3.7 0.9\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={rayVariants}\n            custom={{ x: -0.55, y: -0.55, delay: 0 }}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M19 2.2L20.3 0.9\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={rayVariants}\n            custom={{ x: 0.55, y: -0.55, delay: 0.04 }}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M2 9.8H0.2\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={rayVariants}\n            custom={{ x: -0.75, y: 0, delay: 0.12 }}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M22 9.8H23.8\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={rayVariants}\n            custom={{ x: 0.75, y: 0, delay: 0.16 }}\n            animate={controls}\n            initial=\"normal\"\n          />\n          </motion.g>\n        </svg>\n      </div>\n    );\n  }\n);\n\nBulbIcon.displayName = 'BulbIcon';\n\nexport { BulbIcon };\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"
}