Fix fit-to-screen drag types to match EventCallback signature

All LayoutItem args are nullable (LayoutItem | null) and event is Event
not MouseEvent — matching the actual react-grid-layout EventCallback type.
fitDragRef simplified to string | null. Cast event to MouseEvent inside
the handler to access clientX/Y for pixel-accurate slot detection.

https://claude.ai/code/session_01Cu7YDRKZrYX3sBs6g9w2dy
This commit is contained in:
Claude 2026-03-21 23:56:49 +00:00
parent b393f20857
commit 29e2003a84
No known key found for this signature in database

View File

@ -467,27 +467,41 @@ export default function DraggableGridLayout({
}, [fitToScreen, fitGridParams, cameras, includeBirdseye, birdseyeConfig]);
const [fitLayoutOverride, setFitLayoutOverride] = useState<Layout | undefined>();
const draggedItemRef = useRef<string | null>(null);
const fitDragRef = useRef<string | null>(null);
useEffect(() => {
setFitLayoutOverride(undefined);
}, [fitGridParams, cameras, includeBirdseye]);
const handleFitDrag = useCallback(
(_layout: Layout, _oldItem: LayoutItem, layoutItem: LayoutItem) => {
draggedItemRef.current = layoutItem.i;
(
_layout: Layout,
_oldItem: LayoutItem | null,
newItem: LayoutItem | null,
) => {
if (newItem) {
fitDragRef.current = newItem.i;
}
},
[],
);
const handleFitDragStop = useCallback(
(newLayout: Layout, _oldItem: LayoutItem, layoutItem: LayoutItem) => {
(
_layout: Layout,
_oldItem: LayoutItem | null,
newItem: LayoutItem | null,
_placeholder: LayoutItem | null,
event: Event,
) => {
if (!fitToScreen || !fitGridParams) return;
const w = fitGridParams.gridUnitsPerCam;
const colsPerRow = fitGridParams.colsPerRow;
const draggedId = draggedItemRef.current ?? layoutItem.i;
draggedItemRef.current = null;
const draggedId = fitDragRef.current ?? newItem?.i;
fitDragRef.current = null;
if (!draggedId) return;
const currentOrder = fitLayoutOverride ?? fitLayout ?? [];
const orderedNames = [...currentOrder]
@ -497,10 +511,24 @@ export default function DraggableGridLayout({
})
.map((item) => item.i);
const dropCenterX = layoutItem.x + w / 2;
const dropCenterY = layoutItem.y + w / 2;
const targetCol = Math.min(Math.floor(dropCenterX / w), colsPerRow - 1);
const targetRow = Math.floor(dropCenterY / w);
const gridEl = containerRef.current?.querySelector(
".grid-layout",
) as HTMLElement | null;
if (!gridEl) return;
const mouseEvent = event as MouseEvent;
const rect = gridEl.getBoundingClientRect();
const mouseRelX = mouseEvent.clientX - rect.left;
const mouseRelY = mouseEvent.clientY - rect.top;
const cellWidthPx = rect.width / colsPerRow;
const cellHeightPx = cellHeight * w;
const targetCol = Math.max(
0,
Math.min(Math.floor(mouseRelX / cellWidthPx), colsPerRow - 1),
);
const targetRow = Math.max(0, Math.floor(mouseRelY / cellHeightPx));
const totalRows = Math.ceil(orderedNames.length / colsPerRow);
const clampedRow = Math.min(targetRow, totalRows - 1);
const targetIndex = Math.min(
@ -510,7 +538,7 @@ export default function DraggableGridLayout({
const sourceIndex = orderedNames.indexOf(draggedId);
if (sourceIndex === -1 || sourceIndex === targetIndex) {
setFitLayoutOverride((prev) => prev);
setFitLayoutOverride((prev) => (prev ? [...prev] : prev));
return;
}
@ -530,7 +558,7 @@ export default function DraggableGridLayout({
setFitLayoutOverride(normalized);
},
[fitToScreen, fitGridParams, fitLayoutOverride, fitLayout],
[fitToScreen, fitGridParams, fitLayoutOverride, fitLayout, cellHeight, containerRef],
);
const activeGridLayout = useMemo(() => {