/** * Resizer Component * * 可拖拽的分割线,用于调整面板宽度 */ import { useState, useCallback, useEffect, useRef } from 'react'; import { cn } from '../utils/cn.js'; interface ResizerProps { /** 拖拽时的回调,返回拖拽的像素偏移量 */ onResize: (delta: number) => void; /** 拖拽结束的回调 */ onResizeEnd?: () => void; /** 方向:vertical(左右拖拽)或 horizontal(上下拖拽) */ direction?: 'vertical' | 'horizontal'; className?: string; } export function Resizer({ onResize, onResizeEnd, direction = 'vertical', className, }: ResizerProps) { const [isDragging, setIsDragging] = useState(false); const startPosRef = useRef(0); const handleMouseDown = useCallback((e: React.MouseEvent) => { e.preventDefault(); setIsDragging(true); startPosRef.current = direction === 'vertical' ? e.clientX : e.clientY; }, [direction]); const handleMouseMove = useCallback((e: MouseEvent) => { if (!isDragging) return; const currentPos = direction === 'vertical' ? e.clientX : e.clientY; const delta = currentPos - startPosRef.current; startPosRef.current = currentPos; onResize(delta); }, [isDragging, direction, onResize]); const handleMouseUp = useCallback(() => { if (isDragging) { setIsDragging(false); onResizeEnd?.(); } }, [isDragging, onResizeEnd]); useEffect(() => { if (isDragging) { document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); // 拖拽时禁止选中文本 document.body.style.userSelect = 'none'; document.body.style.cursor = direction === 'vertical' ? 'col-resize' : 'row-resize'; } return () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); document.body.style.userSelect = ''; document.body.style.cursor = ''; }; }, [isDragging, handleMouseMove, handleMouseUp, direction]); return (
); }