'use client'; import { ReactNode, useCallback, useRef, useState } from 'react'; import { cn } from '@/lib/utils'; type Direction = 'horizontal' | 'vertical'; interface ResizableSplitProps { direction: Direction; initialSizes?: [number, number]; minSizes?: [number, number]; className?: string; handleClassName?: string; children: [ReactNode, ReactNode]; } export function ResizableSplit({ direction, initialSizes = [50, 50], minSizes = [20, 20], className, handleClassName, children, }: ResizableSplitProps) { const containerRef = useRef(null); const [sizes, setSizes] = useState<[number, number]>(initialSizes); const [isDragging, setIsDragging] = useState(false); const clampSizes = useCallback( (nextFirst: number) => { const minFirst = minSizes[0]; const minSecond = minSizes[1]; const clampedFirst = Math.min(100 - minSecond, Math.max(minFirst, nextFirst)); return [clampedFirst, 100 - clampedFirst] as [number, number]; }, [minSizes] ); const updateSizes = useCallback( (event: PointerEvent | React.PointerEvent) => { const rect = containerRef.current?.getBoundingClientRect(); if (!rect) return; const total = direction === 'horizontal' ? rect.width : rect.height; if (!total) return; const offset = direction === 'horizontal' ? event.clientX - rect.left : event.clientY - rect.top; const nextFirst = (offset / total) * 100; setSizes(clampSizes(nextFirst)); }, [clampSizes, direction] ); const handlePointerDown = useCallback( (event: React.PointerEvent) => { event.preventDefault(); setIsDragging(true); updateSizes(event); const handleMove = (moveEvent: PointerEvent) => { updateSizes(moveEvent); }; const handleUp = (upEvent: PointerEvent) => { updateSizes(upEvent); setIsDragging(false); window.removeEventListener('pointermove', handleMove); window.removeEventListener('pointerup', handleUp); }; window.addEventListener('pointermove', handleMove); window.addEventListener('pointerup', handleUp); }, [updateSizes] ); const isHorizontal = direction === 'horizontal'; return (
{children[0]}
{children[1]}
); }