{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "AnimatedList-JS-TW",
	"title": "AnimatedList",
	"description": "List items enter with staggered motion variants for polished reveals.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "AnimatedList/AnimatedList.jsx",
			"content": "import { useCallback, useEffect, useRef, useState } from 'react';\nimport { motion, useInView } from 'motion/react';\n\nconst AnimatedItem = ({ children, delay = 0, index, onMouseEnter, onClick }) => {\n  const ref = useRef(null);\n  const inView = useInView(ref, { amount: 0.5, triggerOnce: false });\n  return (\n    <motion.div\n      ref={ref}\n      data-index={index}\n      onMouseEnter={onMouseEnter}\n      onClick={onClick}\n      initial={{ scale: 0.7, opacity: 0 }}\n      animate={inView ? { scale: 1, opacity: 1 } : { scale: 0.7, opacity: 0 }}\n      transition={{ duration: 0.2, delay }}\n      className=\"mb-4 cursor-pointer\"\n    >\n      {children}\n    </motion.div>\n  );\n};\n\nconst AnimatedList = ({\n  items = [\n    'Item 1',\n    'Item 2',\n    'Item 3',\n    'Item 4',\n    'Item 5',\n    'Item 6',\n    'Item 7',\n    'Item 8',\n    'Item 9',\n    'Item 10',\n    'Item 11',\n    'Item 12',\n    'Item 13',\n    'Item 14',\n    'Item 15'\n  ],\n  onItemSelect,\n  showGradients = true,\n  enableArrowNavigation = true,\n  className = '',\n  itemClassName = '',\n  displayScrollbar = true,\n  initialSelectedIndex = -1\n}) => {\n  const listRef = useRef(null);\n  const [selectedIndex, setSelectedIndex] = useState(initialSelectedIndex);\n  const [keyboardNav, setKeyboardNav] = useState(false);\n  const [topGradientOpacity, setTopGradientOpacity] = useState(0);\n  const [bottomGradientOpacity, setBottomGradientOpacity] = useState(1);\n\n  const handleItemMouseEnter = useCallback(index => {\n    setSelectedIndex(index);\n  }, []);\n\n  const handleItemClick = useCallback(\n    (item, index) => {\n      setSelectedIndex(index);\n      if (onItemSelect) {\n        onItemSelect(item, index);\n      }\n    },\n    [onItemSelect]\n  );\n\n  const handleScroll = useCallback(e => {\n    const { scrollTop, scrollHeight, clientHeight } = e.target;\n    setTopGradientOpacity(Math.min(scrollTop / 50, 1));\n    const bottomDistance = scrollHeight - (scrollTop + clientHeight);\n    setBottomGradientOpacity(scrollHeight <= clientHeight ? 0 : Math.min(bottomDistance / 50, 1));\n  }, []);\n\n  useEffect(() => {\n    if (!enableArrowNavigation) return;\n    const handleKeyDown = e => {\n      if (e.key === 'ArrowDown' || (e.key === 'Tab' && !e.shiftKey)) {\n        e.preventDefault();\n        setKeyboardNav(true);\n        setSelectedIndex(prev => Math.min(prev + 1, items.length - 1));\n      } else if (e.key === 'ArrowUp' || (e.key === 'Tab' && e.shiftKey)) {\n        e.preventDefault();\n        setKeyboardNav(true);\n        setSelectedIndex(prev => Math.max(prev - 1, 0));\n      } else if (e.key === 'Enter') {\n        if (selectedIndex >= 0 && selectedIndex < items.length) {\n          e.preventDefault();\n          if (onItemSelect) {\n            onItemSelect(items[selectedIndex], selectedIndex);\n          }\n        }\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [items, selectedIndex, onItemSelect, enableArrowNavigation]);\n\n  useEffect(() => {\n    if (!keyboardNav || selectedIndex < 0 || !listRef.current) return;\n    const container = listRef.current;\n    const selectedItem = container.querySelector(`[data-index=\"${selectedIndex}\"]`);\n    if (selectedItem) {\n      const extraMargin = 50;\n      const containerScrollTop = container.scrollTop;\n      const containerHeight = container.clientHeight;\n      const itemTop = selectedItem.offsetTop;\n      const itemBottom = itemTop + selectedItem.offsetHeight;\n      if (itemTop < containerScrollTop + extraMargin) {\n        container.scrollTo({ top: itemTop - extraMargin, behavior: 'smooth' });\n      } else if (itemBottom > containerScrollTop + containerHeight - extraMargin) {\n        container.scrollTo({\n          top: itemBottom - containerHeight + extraMargin,\n          behavior: 'smooth'\n        });\n      }\n    }\n    setKeyboardNav(false);\n  }, [selectedIndex, keyboardNav]);\n\n  return (\n    <div className={`relative w-[500px] ${className}`}>\n      <div\n        ref={listRef}\n        className={`max-h-[400px] overflow-y-auto p-4 ${\n          displayScrollbar\n            ? '[&::-webkit-scrollbar]:w-[8px] [&::-webkit-scrollbar-track]:bg-[#120F17] [&::-webkit-scrollbar-thumb]:bg-[#222] [&::-webkit-scrollbar-thumb]:rounded-[4px]'\n            : 'scrollbar-hide'\n        }`}\n        onScroll={handleScroll}\n        style={{\n          scrollbarWidth: displayScrollbar ? 'thin' : 'none',\n          scrollbarColor: '#222 #120F17'\n        }}\n      >\n        {items.map((item, index) => (\n          <AnimatedItem\n            key={index}\n            delay={0.1}\n            index={index}\n            onMouseEnter={() => handleItemMouseEnter(index)}\n            onClick={() => handleItemClick(item, index)}\n          >\n            <div className={`p-4 bg-[#111] rounded-lg ${selectedIndex === index ? 'bg-[#222]' : ''} ${itemClassName}`}>\n              <p className=\"text-white m-0\">{item}</p>\n            </div>\n          </AnimatedItem>\n        ))}\n      </div>\n      {showGradients && (\n        <>\n          <div\n            className=\"absolute top-0 left-0 right-0 h-[50px] bg-gradient-to-b from-[#120F17] to-transparent pointer-events-none transition-opacity duration-300 ease\"\n            style={{ opacity: topGradientOpacity }}\n          ></div>\n          <div\n            className=\"absolute bottom-0 left-0 right-0 h-[100px] bg-gradient-to-t from-[#120F17] to-transparent pointer-events-none transition-opacity duration-300 ease\"\n            style={{ opacity: bottomGradientOpacity }}\n          ></div>\n        </>\n      )}\n    </div>\n  );\n};\n\nexport default AnimatedList;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}