{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "qr-code-01",
  "title": "qr-code-01",
  "description": "Animated qr code icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/qr-code-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 QrCode01IconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface QrCode01IconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// a scanner line travels down while the code cells answer in sequence\nconst qrCellVariants: Variants = {\n  normal: { visibility: 'visible', scale: 1 },\n  animate: (i: number) => ({\n    visibility: ['visible', 'visible', 'visible'],\n    scale: [1, 0.82, 1],\n    transition: { duration: 0.42, delay: 0.12 + i * 0.07, ease: 'easeOut' },\n  }),\n};\n\nconst qrFrameVariants: Variants = {\n  normal: { scale: 1, transition: { type: 'spring', duration: 0.4, bounce: 0 } },\n  animate: {\n    scale: [1, 1.03, 1],\n    transition: { duration: 0.75, ease: 'easeOut' },\n  },\n};\n\nconst scannerVariants: Variants = {\n  normal: { visibility: 'hidden', translateY: -7 },\n  animate: {\n    visibility: ['hidden', 'visible', 'visible', 'hidden'],\n    translateY: [-7, 7],\n    transition: { duration: 1, times: [0, 0.12, 0.88, 1], ease: 'easeInOut' },\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 QrCode01Icon = forwardRef<QrCode01IconHandle, QrCode01IconProps>(\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=\"M6.79289 6.79289C6.5 7.08579 6.5 7.55719 6.5 8.5C6.5 9.44281 6.5 9.91421 6.79289 10.2071C7.08579 10.5 7.55719 10.5 8.5 10.5C9.44281 10.5 9.91421 10.5 10.2071 10.2071C10.5 9.91421 10.5 9.44281 10.5 8.5C10.5 7.55719 10.5 7.08579 10.2071 6.79289C9.91421 6.5 9.44281 6.5 8.5 6.5C7.55719 6.5 7.08579 6.5 6.79289 6.79289Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={qrCellVariants}\n            custom={0}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '8.5px 8.5px' }}\n          />\n          <motion.path\n            d=\"M13.5 10.5C14.4428 10.5 14.9142 10.5 15.2071 10.2071C15.5 9.91421 15.5 9.44281 15.5 8.5C15.5 7.55719 15.5 7.08579 15.7929 6.79289C16.0858 6.5 16.5572 6.5 17.5 6.5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={qrCellVariants}\n            custom={1}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M6.5 13.5H8.5C9.44281 13.5 9.91421 13.5 10.2071 13.7929C10.5 14.0858 10.5 14.5572 10.5 15.5V17.5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={qrCellVariants}\n            custom={2}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M6.875 17.25H6.75M7 17.25C7 17.3881 6.88807 17.5 6.75 17.5C6.61193 17.5 6.5 17.3881 6.5 17.25C6.5 17.1119 6.61193 17 6.75 17C6.88807 17 7 17.1119 7 17.25Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={qrCellVariants}\n            custom={3}\n            animate={controls}\n            initial=\"normal\"\n          />\n          <motion.path\n            d=\"M13.7929 13.7929C13.5 14.0858 13.5 14.5572 13.5 15.5C13.5 16.4428 13.5 16.9142 13.7929 17.2071C14.0858 17.5 14.5572 17.5 15.5 17.5C16.4428 17.5 16.9142 17.5 17.2071 17.2071C17.5 16.9142 17.5 16.4428 17.5 15.5C17.5 14.5572 17.5 14.0858 17.2071 13.7929C16.9142 13.5 16.4428 13.5 15.5 13.5C14.5572 13.5 14.0858 13.5 13.7929 13.7929Z\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={qrCellVariants}\n            custom={4}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '15.5px 15.5px' }}\n          />\n          <motion.path\n            d=\"M6.5 21.5C6.03563 21.5 5.80344 21.5 5.60812 21.478C3.98545 21.2952 2.70484 20.0145 2.52201 18.3919C2.5 18.1966 2.5 17.9644 2.5 17.5M17.5 21.5C17.9644 21.5 18.1966 21.5 18.3919 21.478C20.0145 21.2952 21.2952 20.0145 21.478 18.3919C21.5 18.1966 21.5 17.9644 21.5 17.5M6.5 2.5C6.03563 2.5 5.80344 2.5 5.60812 2.52201C3.98545 2.70484 2.70484 3.98545 2.52201 5.60812C2.5 5.80344 2.5 6.03563 2.5 6.5M17.5 2.5C17.9644 2.5 18.1966 2.5 18.3919 2.52201C20.0145 2.70484 21.2952 3.98545 21.478 5.60812C21.5 5.80344 21.5 6.03563 21.5 6.5\"\n            stroke=\"currentColor\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"1.5\"\n            variants={qrFrameVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '12px 12px' }}\n          />\n          <motion.g\n            variants={generatedGeometryVariants}\n            animate={controls}\n            initial=\"normal\"\n          >\n          <motion.path d=\"M4 12H20\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"1\" variants={scannerVariants} animate={controls} initial=\"normal\" />\n          </motion.g>\n        </svg>\n      </div>\n    );\n  }\n);\n\nQrCode01Icon.displayName = 'QrCode01Icon';\n\nexport { QrCode01Icon };\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"
}