mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-06 14:37:38 +00:00
115 lines
3.1 KiB
TypeScript
115 lines
3.1 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
import type { MouseEvent as ReactMouseEvent } from 'react';
|
|
import type { Project } from '../../../types/app';
|
|
import type { CodeEditorDiffInfo, CodeEditorFile } from '../types/types';
|
|
|
|
type UseEditorSidebarOptions = {
|
|
selectedProject: Project | null;
|
|
isMobile: boolean;
|
|
initialWidth?: number;
|
|
};
|
|
|
|
export const useEditorSidebar = ({
|
|
selectedProject,
|
|
isMobile,
|
|
initialWidth = 600,
|
|
}: UseEditorSidebarOptions) => {
|
|
const [editingFile, setEditingFile] = useState<CodeEditorFile | null>(null);
|
|
const [editorWidth, setEditorWidth] = useState(initialWidth);
|
|
const [editorExpanded, setEditorExpanded] = useState(false);
|
|
const [isResizing, setIsResizing] = useState(false);
|
|
const [hasManualWidth, setHasManualWidth] = useState(false);
|
|
const resizeHandleRef = useRef<HTMLDivElement | null>(null);
|
|
|
|
const handleFileOpen = useCallback(
|
|
(filePath: string, diffInfo: CodeEditorDiffInfo | null = null) => {
|
|
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
const fileName = normalizedPath.split('/').pop() || filePath;
|
|
|
|
setEditingFile({
|
|
name: fileName,
|
|
path: filePath,
|
|
projectName: selectedProject?.name,
|
|
diffInfo,
|
|
});
|
|
},
|
|
[selectedProject?.name],
|
|
);
|
|
|
|
const handleCloseEditor = useCallback(() => {
|
|
setEditingFile(null);
|
|
setEditorExpanded(false);
|
|
}, []);
|
|
|
|
const handleToggleEditorExpand = useCallback(() => {
|
|
setEditorExpanded((previous) => !previous);
|
|
}, []);
|
|
|
|
const handleResizeStart = useCallback(
|
|
(event: ReactMouseEvent<HTMLDivElement>) => {
|
|
if (isMobile) {
|
|
return;
|
|
}
|
|
|
|
// After first drag interaction, the editor width is user-controlled.
|
|
setHasManualWidth(true);
|
|
setIsResizing(true);
|
|
event.preventDefault();
|
|
},
|
|
[isMobile],
|
|
);
|
|
|
|
useEffect(() => {
|
|
const handleMouseMove = (event: globalThis.MouseEvent) => {
|
|
if (!isResizing) {
|
|
return;
|
|
}
|
|
|
|
const container = resizeHandleRef.current?.parentElement;
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
const containerRect = container.getBoundingClientRect();
|
|
const newWidth = containerRect.right - event.clientX;
|
|
|
|
const minWidth = 300;
|
|
const maxWidth = containerRect.width * 0.8;
|
|
|
|
if (newWidth >= minWidth && newWidth <= maxWidth) {
|
|
setEditorWidth(newWidth);
|
|
}
|
|
};
|
|
|
|
const handleMouseUp = () => {
|
|
setIsResizing(false);
|
|
};
|
|
|
|
if (isResizing) {
|
|
document.addEventListener('mousemove', handleMouseMove);
|
|
document.addEventListener('mouseup', handleMouseUp);
|
|
document.body.style.cursor = 'col-resize';
|
|
document.body.style.userSelect = 'none';
|
|
}
|
|
|
|
return () => {
|
|
document.removeEventListener('mousemove', handleMouseMove);
|
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
document.body.style.cursor = '';
|
|
document.body.style.userSelect = '';
|
|
};
|
|
}, [isResizing]);
|
|
|
|
return {
|
|
editingFile,
|
|
editorWidth,
|
|
editorExpanded,
|
|
hasManualWidth,
|
|
resizeHandleRef,
|
|
handleFileOpen,
|
|
handleCloseEditor,
|
|
handleToggleEditorExpand,
|
|
handleResizeStart,
|
|
};
|
|
};
|