{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "party",
  "title": "party",
  "description": "Animated party icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/party.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 PartyIconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface PartyIconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// the popper recoils and the existing confetti emerges from inside its cone\nconst popperVariants: Variants = {\n  normal: { translateX: 0, translateY: 0, rotate: 0, transition: { type: 'spring', duration: 0.5, bounce: 0 } },\n  animate: {\n    translateX: [0, -1, 0.5, 0],\n    translateY: [0, 1, -0.5, 0],\n    rotate: [0, -6, 2, 0],\n    transition: { duration: 0.75, times: [0, 0.25, 0.62, 1], ease: 'easeOut' },\n  },\n};\n\nconst confettiVariants: Variants = {\n  normal: { visibility: 'visible', transform: 'translate(0px, 0px) rotate(0deg) scale(1)' },\n  animate: (i: number) => ({\n    visibility: ['hidden', 'visible', 'visible'],\n    transform: [\n      'translate(-7px, 7px) rotate(0deg) scale(0.2)',\n      'translate(' + (0.7 + (i % 2) * 0.7) + 'px, ' + (-1.2 - (i % 3) * 0.45) + 'px) rotate(' + ((i % 2 === 0 ? 1 : -1) * (14 + i * 2)) + 'deg) scale(1.05)',\n      'translate(0px, 0px) rotate(0deg) scale(1)',\n    ],\n    transition: { duration: 0.62, delay: i * 0.025, ease: [0.23, 1, 0.32, 1] },\n  }),\n};\n\nconst PartyIcon = forwardRef<PartyIconHandle, PartyIconProps>(\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.65784 11.0022L4.18747 14.3105C2.3324 18.4844 1.40486 20.5713 2.41719 21.5837C3.42951 22.596 5.51646 21.6685 9.69037 19.8134L12.9987 18.343C15.5161 17.2242 16.7748 16.6647 16.9751 15.586C17.1754 14.5073 16.2014 13.5333 14.2535 11.5854L12.4155 9.7474C10.4675 7.79944 9.49353 6.82546 8.41482 7.02575C7.33611 7.22604 6.77669 8.48475 5.65784 11.0022Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={popperVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '5px 19px' }}\n          />\n          <motion.path\n            d=\"M6.50085 10.5L13.5009 17.5M4.50085 15.5L8.50085 19.5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={popperVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '5px 19px' }}\n          />\n          <motion.path\n            d=\"M16.0009 8L19.0009 5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={0}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M21.8759 6H21.7509M22.0009 6C22.0009 6.13807 21.8889 6.25 21.7509 6.25C21.6128 6.25 21.5009 6.13807 21.5009 6C21.5009 5.86193 21.6128 5.75 21.7509 5.75C21.8889 5.75 22.0009 5.86193 22.0009 6Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={1}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M20.8759 13.25H20.7509M21.0009 13.25C21.0009 13.3881 20.8889 13.5 20.7509 13.5C20.6128 13.5 20.5009 13.3881 20.5009 13.25C20.5009 13.1119 20.6128 13 20.7509 13C20.8889 13 21.0009 13.1119 21.0009 13.25Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={2}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M18.1259 2.25H18.0009M18.2509 2.25C18.2509 2.38807 18.1389 2.5 18.0009 2.5C17.8628 2.5 17.7509 2.38807 17.7509 2.25C17.7509 2.11193 17.8628 2 18.0009 2C18.1389 2 18.2509 2.11193 18.2509 2.25Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={3}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M11.1259 3.25H11.0009M11.2509 3.25C11.2509 3.38807 11.1389 3.5 11.0009 3.5C10.8628 3.5 10.7509 3.38807 10.7509 3.25C10.7509 3.11193 10.8628 3 11.0009 3C11.1389 3 11.2509 3.11193 11.2509 3.25Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={4}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M14.1981 2C14.5972 2.66667 14.9165 4.4 13.0009 6\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={5}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M22.0009 9.80274C21.3342 9.40365 19.6009 9.08438 18.0009 11\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={confettiVariants}\n            custom={6}\n            animate={controls}\n            initial=\"normal\"\n          />\n        </svg>\n      </div>\n    );\n  }\n);\n\nPartyIcon.displayName = 'PartyIcon';\n\nexport { PartyIcon };\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"
}