{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "Dock-TS-CSS",
	"title": "Dock",
	"description": "macOS style magnifying dock with proximity scaling of icons.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:file",
			"path": "Dock.css",
			"target": "@components/Dock.css",
			"content": ".dock-outer {\n  margin: 0 0.5rem;\n  display: flex;\n  max-width: 100%;\n  align-items: center;\n}\n\n.dock-panel {\n  position: absolute;\n  bottom: 0.5rem;\n  left: 50%;\n  transform: translateX(-50%);\n  display: flex;\n  align-items: flex-end;\n  width: fit-content;\n  gap: 1rem;\n  border-radius: 1rem;\n  background-color: #120F17;\n  border: 1px solid #222;\n  padding: 0 0.5rem 0.5rem;\n}\n\n.dock-item {\n  position: relative;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  border-radius: 10px;\n  background-color: #120F17;\n  border: 1px solid #222;\n  box-shadow:\n    0 4px 6px -1px rgba(0, 0, 0, 0.1),\n    0 2px 4px -1px rgba(0, 0, 0, 0.06);\n  cursor: pointer;\n  outline: none;\n}\n\n.dock-icon {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.dock-label {\n  position: absolute;\n  top: -1.5rem;\n  left: 50%;\n  width: fit-content;\n  white-space: pre;\n  border-radius: 0.375rem;\n  border: 1px solid #222;\n  background-color: #120F17;\n  padding: 0.125rem 0.5rem;\n  font-size: 0.75rem;\n  color: #fff;\n  transform: translateX(-50%);\n}\n"
		},
		{
			"type": "registry:component",
			"path": "Dock.tsx",
			"content": "'use client';\n\nimport {\n  motion,\n  MotionValue,\n  useMotionValue,\n  useSpring,\n  useTransform,\n  type SpringOptions,\n  AnimatePresence\n} from 'motion/react';\nimport React, { Children, cloneElement, useEffect, useMemo, useRef, useState } from 'react';\n\nimport './Dock.css';\n\nexport type DockItemData = {\n  icon: React.ReactNode;\n  label: React.ReactNode;\n  onClick: () => void;\n  className?: string;\n};\n\nexport type DockProps = {\n  items: DockItemData[];\n  className?: string;\n  distance?: number;\n  panelHeight?: number;\n  baseItemSize?: number;\n  dockHeight?: number;\n  magnification?: number;\n  spring?: SpringOptions;\n};\n\ntype DockItemProps = {\n  className?: string;\n  children: React.ReactNode;\n  onClick?: () => void;\n  mouseX: MotionValue<number>;\n  spring: SpringOptions;\n  distance: number;\n  baseItemSize: number;\n  magnification: number;\n  label?: React.ReactNode;\n};\n\nfunction DockItem({\n  children,\n  className = '',\n  onClick,\n  mouseX,\n  spring,\n  distance,\n  magnification,\n  baseItemSize,\n  label\n}: DockItemProps) {\n  const ref = useRef<HTMLDivElement>(null);\n  const isHovered = useMotionValue(0);\n\n  const mouseDistance = useTransform(mouseX, val => {\n    const rect = ref.current?.getBoundingClientRect() ?? {\n      x: 0,\n      width: baseItemSize\n    };\n    return val - rect.x - baseItemSize / 2;\n  });\n\n  const targetSize = useTransform(mouseDistance, [-distance, 0, distance], [baseItemSize, magnification, baseItemSize]);\n  const size = useSpring(targetSize, spring);\n\n  const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n    if (e.key === 'Enter' || e.key === ' ') {\n      e.preventDefault();\n      onClick?.();\n    }\n  };\n\n  return (\n    <motion.div\n      ref={ref}\n      style={{\n        width: size,\n        height: size\n      }}\n      onHoverStart={() => isHovered.set(1)}\n      onHoverEnd={() => isHovered.set(0)}\n      onFocus={() => isHovered.set(1)}\n      onBlur={() => isHovered.set(0)}\n      onClick={onClick}\n      onKeyDown={handleKeyDown}\n      className={`dock-item ${className}`}\n      tabIndex={0}\n      role=\"button\"\n      aria-haspopup=\"true\"\n      aria-label={typeof label === 'string' ? label : undefined}\n    >\n      {Children.map(children, child =>\n        React.isValidElement(child)\n          ? cloneElement(child as React.ReactElement<{ isHovered?: MotionValue<number> }>, { isHovered })\n          : child\n      )}\n    </motion.div>\n  );\n}\n\ntype DockLabelProps = {\n  className?: string;\n  children: React.ReactNode;\n  isHovered?: MotionValue<number>;\n};\n\nfunction DockLabel({ children, className = '', isHovered }: DockLabelProps) {\n  const [isVisible, setIsVisible] = useState(false);\n\n  useEffect(() => {\n    if (!isHovered) return;\n    const unsubscribe = isHovered.on('change', latest => {\n      setIsVisible(latest === 1);\n    });\n    return () => unsubscribe();\n  }, [isHovered]);\n\n  return (\n    <AnimatePresence>\n      {isVisible && (\n        <motion.div\n          initial={{ opacity: 0, y: 0 }}\n          animate={{ opacity: 1, y: -10 }}\n          exit={{ opacity: 0, y: 0 }}\n          transition={{ duration: 0.2 }}\n          className={`dock-label ${className}`}\n          role=\"tooltip\"\n          style={{ x: '-50%' }}\n        >\n          {children}\n        </motion.div>\n      )}\n    </AnimatePresence>\n  );\n}\n\ntype DockIconProps = {\n  className?: string;\n  children: React.ReactNode;\n  isHovered?: MotionValue<number>;\n};\n\nfunction DockIcon({ children, className = '' }: DockIconProps) {\n  return <div className={`dock-icon ${className}`}>{children}</div>;\n}\n\nexport default function Dock({\n  items,\n  className = '',\n  spring = { mass: 0.1, stiffness: 150, damping: 12 },\n  magnification = 70,\n  distance = 200,\n  panelHeight = 68,\n  dockHeight = 256,\n  baseItemSize = 50\n}: DockProps) {\n  const mouseX = useMotionValue(Infinity);\n  const isHovered = useMotionValue(0);\n\n  const maxHeight = useMemo(\n    () => Math.max(dockHeight, magnification + magnification / 2 + 4),\n    [magnification, dockHeight]\n  );\n  const heightRow = useTransform(isHovered, [0, 1], [panelHeight, maxHeight]);\n  const height = useSpring(heightRow, spring);\n\n  return (\n    <motion.div style={{ height, scrollbarWidth: 'none' }} className=\"dock-outer\">\n      <motion.div\n        onMouseMove={({ pageX }) => {\n          isHovered.set(1);\n          mouseX.set(pageX);\n        }}\n        onMouseLeave={() => {\n          isHovered.set(0);\n          mouseX.set(Infinity);\n        }}\n        className={`dock-panel ${className}`}\n        style={{ height: panelHeight }}\n        role=\"toolbar\"\n        aria-label=\"Application dock\"\n      >\n        {items.map((item, index) => (\n          <DockItem\n            key={index}\n            onClick={item.onClick}\n            className={item.className}\n            mouseX={mouseX}\n            spring={spring}\n            distance={distance}\n            magnification={magnification}\n            baseItemSize={baseItemSize}\n            label={item.label}\n          >\n            <DockIcon>{item.icon}</DockIcon>\n            <DockLabel>{item.label}</DockLabel>\n          </DockItem>\n        ))}\n      </motion.div>\n    </motion.div>\n  );\n}\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}