"use client"; import React, { useState, useRef, useEffect } from "react"; import { motion, useMotionValue, useTransform, PanInfo } from "motion/react"; interface HandlebarsProps { children: React.ReactNode; minWidth?: number; maxWidth?: number; onRangeChange?: (left: number, right: number) => void; } export function Handlebars({ children, minWidth = 50, maxWidth = 400, onRangeChange, }: HandlebarsProps) { const [leftHandle, setLeftHandle] = useState(0); const [rightHandle, setRightHandle] = useState(maxWidth); const [contentWidth, setContentWidth] = useState(maxWidth); const leftHandleX = useMotionValue(0); const rightHandleX = useMotionValue(maxWidth); const visibleWidth = useTransform( [leftHandleX, rightHandleX], (values: number[]) => values[1] - values[0] ); const contentLeft = useTransform(leftHandleX, (left: number) => -left); const containerRef = useRef(null); const measureRef = useRef(null); useEffect(() => { if (!measureRef.current) return; const measureContent = () => { if (measureRef.current) { const width = measureRef.current.scrollWidth; const paddedWidth = width + 32; setContentWidth(paddedWidth); setRightHandle(paddedWidth); rightHandleX.set(paddedWidth); } }; measureContent(); const timer = setTimeout(measureContent, 50); return () => clearTimeout(timer); }, [children, rightHandleX]); useEffect(() => { leftHandleX.set(leftHandle); }, [leftHandle, leftHandleX]); useEffect(() => { rightHandleX.set(rightHandle); }, [rightHandle, rightHandleX]); useEffect(() => { onRangeChange?.(leftHandle, rightHandle); }, [leftHandle, rightHandle, onRangeChange]); const handleLeftDrag = (event: any, info: PanInfo) => { const newLeft = Math.max( 0, Math.min(leftHandle + info.offset.x, rightHandle - minWidth) ); setLeftHandle(newLeft); }; const handleRightDrag = (event: any, info: PanInfo) => { const newRight = Math.max( leftHandle + minWidth, Math.min(contentWidth, rightHandle + info.offset.x) ); setRightHandle(newRight); }; return (
{children}
{children}
); }