{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shopping-cart-01",
  "title": "shopping-cart-01",
  "description": "Animated shopping cart icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/shopping-cart-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 ShoppingCart01IconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface ShoppingCart01IconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// while you hover, the cart is mid-dash — rattling over the floor while\n// drawn speed lines whip past behind it\nconst svgVariants: Variants = {\n  normal: { rotate: 0, translateY: 0, transition: { duration: 0.3 } },\n  animate: {\n    rotate: [0, -1.6, 1.2, -0.8, 0],\n    translateY: [0, -0.5, 0, -0.3, 0],\n    transition: {\n      duration: 0.55,\n      ease: 'easeInOut',\n      repeat: Infinity,\n      repeatDelay: 0.35,\n    },\n  },\n};\n\n// the groceries bounce a beat behind the chassis\nconst itemsVariants: Variants = {\n  normal: { translateY: 0, transition: { duration: 0.3 } },\n  animate: {\n    translateY: [0, -0.9, 0],\n    transition: {\n      duration: 0.55,\n      ease: 'easeInOut',\n      repeat: Infinity,\n      repeatDelay: 0.35,\n      delay: 0.08,\n    },\n  },\n};\n\nconst speedVariants: Variants = {\n  normal: { visibility: 'hidden', transition: { duration: 0.15 } },\n  animate: (i: number) => ({\n    visibility: ['hidden', 'visible', 'hidden'],\n    translateX: [2, -2.5],\n    transition: {\n      duration: 0.5,\n      ease: 'easeOut',\n      repeat: Infinity,\n      repeatDelay: 0.35,\n      delay: i * 0.22,\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 ShoppingCart01Icon = forwardRef<ShoppingCart01IconHandle, ShoppingCart01IconProps>(\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={svgVariants}\n          animate={controls}\n          initial=\"normal\"\n          style={{ transformOrigin: '12px 18px' }}\n        >\n          <path\n            d=\"M10.5 20.25C10.5 20.6642 10.1642 21 9.75 21C9.33579 21 9 20.6642 9 20.25C9 19.8358 9.33579 19.5 9.75 19.5C10.1642 19.5 10.5 19.8358 10.5 20.25Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n          />\n          <path\n            d=\"M19 20.25C19 20.6642 18.6642 21 18.25 21C17.8358 21 17.5 20.6642 17.5 20.25C17.5 19.8358 17.8358 19.5 18.25 19.5C18.6642 19.5 19 19.8358 19 20.25Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n          />\n          <path\n            d=\"M2 3H2.20664C3.53124 3 4.19354 3 4.6255 3.40221C5.05746 3.80441 5.10464 4.46503 5.19902 5.78626L5.45035 9.30496C5.5924 11.2936 5.66342 12.2879 5.96476 13.0961C6.62531 14.8677 8.08229 16.2244 9.89648 16.757C10.7241 17 11.7267 17 13.7317 17C15.8373 17 16.89 17 17.7417 16.7416C19.6593 16.1599 21.1599 14.6593 21.7416 12.7417C22 11.89 22 10.8433 22 8.75C22 8.05222 22 7.70333 21.9139 7.41943C21.72 6.78023 21.2198 6.28002 20.5806 6.08612C20.2967 6 19.9478 6 19.25 6H5.5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n          />\n          <motion.path\n            d=\"M16 10V13M11 10V13\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={itemsVariants}\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=\"M-2 9.5H0.8\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={speedVariants}\n            custom={0}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M-2 13.5H-0.2\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeWidth=\"1.5\"\n            variants={speedVariants}\n            custom={1}\n            animate={controls}\n            initial=\"normal\"\n          />\n          </motion.g>\n        </motion.svg>\n      </div>\n    );\n  }\n);\n\nShoppingCart01Icon.displayName = 'ShoppingCart01Icon';\n\nexport { ShoppingCart01Icon };\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"
}