{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shopping-cart-add-01",
  "title": "shopping-cart-add-01",
  "description": "Animated shopping cart add icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/shopping-cart-add-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 ShoppingCartAdd01IconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface ShoppingCartAdd01IconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// the plus lands in place while the cart absorbs the weight without crossing it\nconst wheelVariants: Variants = {\n  normal: { transform: 'translateY(0px) scale(1)' },\n  animate: {\n    transform: ['translateY(0px) scale(1)', 'translateY(-1px) scale(1.14)', 'translateY(0.45px) scale(0.96)', 'translateY(0px) scale(1)'],\n    transition: { duration: 0.54, ease: [0.23, 1, 0.32, 1] },\n  },\n};\n\nconst cartVariants: Variants = {\n  normal: { transform: 'scaleY(1)' },\n  animate: {\n    transform: ['scaleY(1)', 'scaleY(0.96)', 'scaleY(1.025)', 'scaleY(1)'],\n    transition: { duration: 0.52, ease: [0.23, 1, 0.32, 1] },\n  },\n};\n\nconst plusVariants: Variants = {\n  normal: { transform: 'scale(1)' },\n  animate: {\n    transform: ['scale(0.5)', 'scale(1.22)', 'scale(0.96)', 'scale(1)'],\n    transition: { duration: 0.5, delay: 0.06, ease: [0.23, 1, 0.32, 1] },\n  },\n};\n\nconst ShoppingCartAdd01Icon = forwardRef<ShoppingCartAdd01IconHandle, ShoppingCartAdd01IconProps>(\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=\"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            variants={wheelVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '9.75px 20.25px' }}\n          />\n          <motion.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            variants={wheelVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '18.25px 20.25px' }}\n          />\n          <motion.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.7417C21.9426 12.0793 21.9872 11.299 21.9972 10M12.5 6H5.5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={cartVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '12px 13px' }}\n          />\n          <motion.path\n            d=\"M16 6H22M19 9V3\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={plusVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '19px 6px' }}\n          />\n        </svg>\n      </div>\n    );\n  }\n);\n\nShoppingCartAdd01Icon.displayName = 'ShoppingCartAdd01Icon';\n\nexport { ShoppingCartAdd01Icon };\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"
}