Minor UI, fix dragging to select

This commit is contained in:
Zimeng Xiong
2025-11-21 22:52:32 -08:00
parent 6a57e668dd
commit aae0059a6f
3 changed files with 48 additions and 22 deletions
+40 -14
View File
@@ -11,6 +11,32 @@ import clsx from 'clsx';
import { ConfirmModal } from '../components/ConfirmModal';
import { importDrawings, importLibrary } from '../utils/importUtils';
type Point = { x: number; y: number };
type SelectionBounds = {
left: number;
top: number;
right: number;
bottom: number;
width: number;
height: number;
};
const getSelectionBounds = (start: Point, current: Point): SelectionBounds => {
const left = Math.min(start.x, current.x);
const right = Math.max(start.x, current.x);
const top = Math.min(start.y, current.y);
const bottom = Math.max(start.y, current.y);
return {
left,
top,
right,
bottom,
width: right - left,
height: bottom - top,
};
};
const DragOverlayPortal: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return createPortal(children, document.body);
};
@@ -55,8 +81,8 @@ export const Dashboard: React.FC = () => {
// Drag Selection State
const [isDragSelecting, setIsDragSelecting] = useState(false);
const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null);
const [dragCurrent, setDragCurrent] = useState<{ x: number; y: number } | null>(null);
const [dragStart, setDragStart] = useState<Point | null>(null);
const [dragCurrent, setDragCurrent] = useState<Point | null>(null);
const [potentialDragId, setPotentialDragId] = useState<string | null>(null);
const containerRef = useRef<HTMLDivElement>(null);
@@ -123,6 +149,11 @@ export const Dashboard: React.FC = () => {
}
}, []);
const selectionBounds = React.useMemo<SelectionBounds | null>(() => {
if (!dragStart || !dragCurrent) return null;
return getSelectionBounds(dragStart, dragCurrent);
}, [dragStart, dragCurrent]);
useEffect(() => {
if (!isDragSelecting) return;
@@ -138,14 +169,9 @@ export const Dashboard: React.FC = () => {
return;
}
// Calculate selection rect
const left = Math.min(dragStart.x, dragCurrent.x);
const top = Math.min(dragStart.y, dragCurrent.y);
const width = Math.abs(dragCurrent.x - dragStart.x);
const height = Math.abs(dragCurrent.y - dragStart.y);
const selectionRect = { left, top, right: left + width, bottom: top + height };
const selectionRect = getSelectionBounds(dragStart, dragCurrent);
if (width > 5 || height > 5) {
if (selectionRect.width > 5 || selectionRect.height > 5) {
const newSelectedIds = new Set(selectedIds);
drawings.forEach(drawing => {
const card = document.getElementById(`drawing-card-${drawing.id}`);
@@ -636,15 +662,15 @@ export const Dashboard: React.FC = () => {
</div>
{/* Drag Selection Overlay */}
{isDragSelecting && dragStart && dragCurrent && (
{isDragSelecting && selectionBounds && (
<DragOverlayPortal>
<div
className="fixed z-50 pointer-events-none border-2 border-black dark:border-neutral-500 bg-neutral-500/20 shadow-[2px_2px_0px_0px_rgba(0,0,0,1)] dark:shadow-[2px_2px_0px_0px_rgba(255,255,255,0.2)]"
style={{
left: Math.min(dragStart.x, dragCurrent.x),
top: Math.min(dragStart.y, dragCurrent.y),
width: Math.abs(dragCurrent.x - dragStart.x),
height: Math.abs(dragCurrent.y - dragStart.y),
left: selectionBounds.left,
top: selectionBounds.top,
width: selectionBounds.width,
height: selectionBounds.height,
}}
/>
</DragOverlayPortal>