{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "history",
  "title": "history",
  "description": "Animated history icon",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "icons/history.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 HistoryIconHandle {\n  startAnimation: () => void;\n  stopAnimation: () => void;\n}\n\ninterface HistoryIconProps extends HTMLAttributes<HTMLDivElement> {\n  size?: number;\n}\n\n// The rewind ring and both hands share one motion curve. A small forward\n// anticipation leads into the backward sweep, then every part overshoots and\n// settles together. The hour hand turns three times and the minute hand turns\n// six times, preserving Clock's 2:1 pace with much more visible rewinding.\n// rest-parity: split-source-path\nconst HISTORY_DURATION = 0.82;\nconst HISTORY_TIMES = [\n  0, 0.06, 0.1, 0.14, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.51, 0.56, 0.61,\n  0.66, 0.71, 0.77, 0.84, 0.91, 1,\n];\n\nconst frameVariants: Variants = {\n  normal: { transform: 'rotate(0deg)' },\n  animate: {\n    transform: [\n      'rotate(0deg)',\n      'rotate(8deg)',\n      'rotate(12deg)',\n      'rotate(8deg)',\n      'rotate(-30deg)',\n      'rotate(-60deg)',\n      'rotate(-90deg)',\n      'rotate(-120deg)',\n      'rotate(-150deg)',\n      'rotate(-180deg)',\n      'rotate(-210deg)',\n      'rotate(-240deg)',\n      'rotate(-270deg)',\n      'rotate(-300deg)',\n      'rotate(-330deg)',\n      'rotate(-355deg)',\n      'rotate(-369deg)',\n      'rotate(-366deg)',\n      'rotate(-360deg)',\n    ],\n    transition: {\n      duration: HISTORY_DURATION,\n      ease: 'linear',\n      times: HISTORY_TIMES,\n    },\n  },\n};\n\nconst minuteHandVariants: Variants = {\n  normal: { transform: 'rotate(0deg)' },\n  animate: {\n    transform: [\n      'rotate(0deg)',\n      'rotate(48deg)',\n      'rotate(72deg)',\n      'rotate(48deg)',\n      'rotate(-180deg)',\n      'rotate(-360deg)',\n      'rotate(-540deg)',\n      'rotate(-720deg)',\n      'rotate(-900deg)',\n      'rotate(-1080deg)',\n      'rotate(-1260deg)',\n      'rotate(-1440deg)',\n      'rotate(-1620deg)',\n      'rotate(-1800deg)',\n      'rotate(-1980deg)',\n      'rotate(-2130deg)',\n      'rotate(-2214deg)',\n      'rotate(-2196deg)',\n      'rotate(-2160deg)',\n    ],\n    transition: {\n      duration: HISTORY_DURATION,\n      ease: 'linear',\n      times: HISTORY_TIMES,\n    },\n  },\n};\n\nconst hourHandVariants: Variants = {\n  normal: { transform: 'rotate(0deg)' },\n  animate: {\n    transform: [\n      'rotate(0deg)',\n      'rotate(24deg)',\n      'rotate(36deg)',\n      'rotate(24deg)',\n      'rotate(-90deg)',\n      'rotate(-180deg)',\n      'rotate(-270deg)',\n      'rotate(-360deg)',\n      'rotate(-450deg)',\n      'rotate(-540deg)',\n      'rotate(-630deg)',\n      'rotate(-720deg)',\n      'rotate(-810deg)',\n      'rotate(-900deg)',\n      'rotate(-990deg)',\n      'rotate(-1065deg)',\n      'rotate(-1107deg)',\n      'rotate(-1098deg)',\n      'rotate(-1080deg)',\n    ],\n    transition: {\n      duration: HISTORY_DURATION,\n      ease: 'linear',\n      times: HISTORY_TIMES,\n    },\n  },\n};\n\nconst HistoryIcon = forwardRef<HistoryIconHandle, HistoryIconProps>(\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.g\n            variants={frameVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{ transformOrigin: '12.9319px 12px' }}\n          >\n            <path\n              d=\"M4.43186 14.9656C5.65759 18.4791 9.00032 21 12.9318 21C17.9024 21 21.9318 16.9706 21.9318 12C21.9318 7.02944 17.9024 3 12.9318 3C9.23111 3 5.83124 5.6756 4.62227 8.5\"\n              stroke=\"currentColor\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth=\"1.5\"\n            />\n            <path\n              d=\"M8.43054 8.74363C8.43054 8.74363 4.74691 9.3026 4.1879 8.7436C3.62888 8.1846 4.18791 4.50098 4.18791 4.50098\"\n              stroke=\"currentColor\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth=\"1.5\"\n            />\n          </motion.g>\n          <motion.g\n            variants={minuteHandVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{\n              transformBox: 'view-box',\n              originX: 12.9319 / 24,\n              originY: 0.5,\n            }}\n          >\n            <path\n              d=\"M12.9319 7V12\"\n              stroke=\"currentColor\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth=\"1.5\"\n            />\n          </motion.g>\n          <motion.g\n            variants={hourHandVariants}\n            animate={controls}\n            initial=\"normal\"\n            style={{\n              transformBox: 'view-box',\n              originX: 12.9319 / 24,\n              originY: 0.5,\n            }}\n          >\n            <path\n              d=\"M12.9319 12L15.9319 14\"\n              stroke=\"currentColor\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              strokeWidth=\"1.5\"\n            />\n          </motion.g>\n        </svg>\n      </div>\n    );\n  }\n);\n\nHistoryIcon.displayName = 'HistoryIcon';\n\nexport { HistoryIcon };\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"
}