"use client"; import React, { PropsWithChildren, useRef } from "react"; import { cva, type VariantProps } from "class-variance-authority"; import { motion, useMotionValue, useSpring, useTransform } from "framer-motion"; import { cn } from "@/utils/cn"; export interface DockProps extends VariantProps { className?: string; magnification?: number; distance?: number; direction?: "top" | "middle" | "bottom"; children: React.ReactNode; } const DEFAULT_MAGNIFICATION = 60; const DEFAULT_DISTANCE = 125; const dockVariants = cva( "mx-auto w-max mt-8 h-[58px] p-2 flex gap-2 rounded-2xl supports-backdrop-blur:bg-white/10 supports-backdrop-blur:dark:bg-black/10 backdrop-blur-md dark:border-zinc-800", ); const Dock = React.forwardRef( ( { className, children, magnification = DEFAULT_MAGNIFICATION, distance = DEFAULT_DISTANCE, direction = "bottom", ...props }, ref, ) => { const mouseX = useMotionValue(Infinity); const renderChildren = () => { return React.Children.map(children, (child: any) => { return React.cloneElement(child, { mouseX: mouseX, magnification: magnification, distance: distance, }); }); }; return ( mouseX.set(e.pageX)} onMouseLeave={() => mouseX.set(Infinity)} {...props} className={cn(dockVariants({ className }), { "items-start": direction === "top", "items-center": direction === "middle", "items-end": direction === "bottom", })} > {renderChildren()} ); }, ); Dock.displayName = "Dock"; export interface DockIconProps { size?: number; magnification?: number; distance?: number; mouseX?: any; className?: string; children?: React.ReactNode; props?: PropsWithChildren; } const DockIcon = ({ size, magnification = DEFAULT_MAGNIFICATION, distance = DEFAULT_DISTANCE, mouseX, className, children, ...props }: DockIconProps) => { const ref = useRef(null); const distanceCalc = useTransform(mouseX, (val: number) => { const bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 }; return val - bounds.x - bounds.width / 2; }); let widthSync = useTransform( distanceCalc, [-distance, 0, distance], [40, magnification, 40], ); let width = useSpring(widthSync, { mass: 0.1, stiffness: 150, damping: 12, }); return ( {children} ); }; DockIcon.displayName = "DockIcon"; export { Dock, DockIcon, dockVariants };