chore(react/collections/board): fix column dragging offset

This commit is contained in:
Elian Doran 2025-09-13 11:01:39 +03:00
parent e77a49ace6
commit 4f469d0d3c
No known key found for this signature in database
3 changed files with 60 additions and 31 deletions

View File

@ -106,7 +106,15 @@ export default class BoardApi {
const newColumns = [...this.columns]; const newColumns = [...this.columns];
const [movedColumn] = newColumns.splice(fromIndex, 1); const [movedColumn] = newColumns.splice(fromIndex, 1);
newColumns.splice(toIndex, 0, movedColumn);
// Adjust toIndex after removing the element
// When moving forward (right), the removal shifts indices left
let adjustedToIndex = toIndex;
if (fromIndex < toIndex) {
adjustedToIndex = toIndex - 1;
}
newColumns.splice(adjustedToIndex, 0, movedColumn);
// Update view config with new column order // Update view config with new column order
const newViewConfig = { const newViewConfig = {

View File

@ -26,10 +26,14 @@ export default function Column({
isDraggingColumn, isDraggingColumn,
columnItems, columnItems,
api, api,
onColumnHover,
isAnyColumnDragging,
}: { }: {
columnItems?: { note: FNote, branch: FBranch }[]; columnItems?: { note: FNote, branch: FBranch }[];
isDraggingColumn: boolean, isDraggingColumn: boolean,
api: BoardApi api: BoardApi,
onColumnHover?: (index: number, mouseX: number, rect: DOMRect) => void,
isAnyColumnDragging?: boolean
} & DragContext) { } & DragContext) {
const [ isVisible, setVisible ] = useState(true); const [ isVisible, setVisible ] = useState(true);
const { columnNameToEdit, setColumnNameToEdit, dropTarget, draggedCard, dropPosition } = useContext(BoardViewContext); const { columnNameToEdit, setColumnNameToEdit, dropTarget, draggedCard, dropPosition } = useContext(BoardViewContext);
@ -66,10 +70,17 @@ export default function Column({
setVisible(!isDraggingColumn); setVisible(!isDraggingColumn);
}, [ isDraggingColumn ]); }, [ isDraggingColumn ]);
const handleColumnDragOver = useCallback((e: DragEvent) => {
if (!isAnyColumnDragging || !onColumnHover) return;
e.preventDefault();
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
onColumnHover(columnIndex, e.clientX, rect);
}, [isAnyColumnDragging, onColumnHover, columnIndex]);
return ( return (
<div <div
className={`board-column ${dropTarget === column && draggedCard?.fromColumn !== column ? 'drag-over' : ''}`} className={`board-column ${dropTarget === column && draggedCard?.fromColumn !== column ? 'drag-over' : ''}`}
onDragOver={handleDragOver} onDragOver={isAnyColumnDragging ? handleColumnDragOver : handleDragOver}
onDragLeave={handleDragLeave} onDragLeave={handleDragLeave}
onDrop={handleDrop} onDrop={handleDrop}
onWheel={handleScroll} onWheel={handleScroll}

View File

@ -51,6 +51,7 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
const [ dropPosition, setDropPosition ] = useState<{ column: string, index: number } | null>(null); const [ dropPosition, setDropPosition ] = useState<{ column: string, index: number } | null>(null);
const [ draggedColumn, setDraggedColumn ] = useState<{ column: string, index: number } | null>(null); const [ draggedColumn, setDraggedColumn ] = useState<{ column: string, index: number } | null>(null);
const [ columnDropPosition, setColumnDropPosition ] = useState<number | null>(null); const [ columnDropPosition, setColumnDropPosition ] = useState<number | null>(null);
const [ columnHoverIndex, setColumnHoverIndex ] = useState<number | null>(null);
const [ branchIdToEdit, setBranchIdToEdit ] = useState<string>(); const [ branchIdToEdit, setBranchIdToEdit ] = useState<string>();
const [ columnNameToEdit, setColumnNameToEdit ] = useState<string>(); const [ columnNameToEdit, setColumnNameToEdit ] = useState<string>();
const api = useMemo(() => { const api = useMemo(() => {
@ -129,32 +130,31 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
const handleColumnDragOver = useCallback((e: DragEvent) => { const handleColumnDragOver = useCallback((e: DragEvent) => {
if (!draggedColumn) return; if (!draggedColumn) return;
e.preventDefault(); e.preventDefault();
}, [draggedColumn]);
const container = e.currentTarget as HTMLElement; const handleColumnHover = useCallback((visualIndex: number, mouseX: number, columnRect: DOMRect) => {
const columns = Array.from(container.querySelectorAll('.board-column')); if (!draggedColumn) return;
const mouseX = e.clientX;
let newIndex = columns.length; const columnMiddle = columnRect.left + columnRect.width / 2;
for (let i = 0; i < columns.length; i++) {
const col = columns[i] as HTMLElement;
const rect = col.getBoundingClientRect();
const colMiddle = rect.left + rect.width / 2;
if (mouseX < colMiddle) { // Determine drop position based on mouse position relative to column center
newIndex = i; let dropIndex = mouseX < columnMiddle ? visualIndex : visualIndex + 1;
break;
} // Convert visual index back to actual array index
if (draggedColumn.index <= visualIndex) {
// Add 1 because the dragged column (which is hidden) comes before this position
dropIndex += 1;
} }
setColumnDropPosition(newIndex); setColumnDropPosition(dropIndex);
}, [draggedColumn]); }, [draggedColumn]);
const handleContainerDrop = useCallback((e: DragEvent) => { const handleContainerDrop = useCallback((e: DragEvent) => {
e.preventDefault(); e.preventDefault();
if (draggedColumn && columnDropPosition !== null) { if (draggedColumn && columnDropPosition !== null) {
console.log("Move ", draggedColumn.index, "at", columnDropPosition);
handleColumnDrop(draggedColumn.index, columnDropPosition); handleColumnDrop(draggedColumn.index, columnDropPosition);
} }
setColumnHoverIndex(null);
}, [draggedColumn, columnDropPosition, handleColumnDrop]); }, [draggedColumn, columnDropPosition, handleColumnDrop]);
return ( return (
@ -168,7 +168,14 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
onDragOver={handleColumnDragOver} onDragOver={handleColumnDragOver}
onDrop={handleContainerDrop} onDrop={handleContainerDrop}
> >
{byColumn && columns?.map((column, index) => ( {byColumn && columns?.map((column, index) => {
// Calculate visual index (skipping hidden dragged column)
let visualIndex = index;
if (draggedColumn && draggedColumn.index < index) {
visualIndex = index - 1;
}
return (
<> <>
{columnDropPosition === index && ( {columnDropPosition === index && (
<div className="column-drop-placeholder show" /> <div className="column-drop-placeholder show" />
@ -179,9 +186,12 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC
columnIndex={index} columnIndex={index}
columnItems={byColumn.get(column)} columnItems={byColumn.get(column)}
isDraggingColumn={draggedColumn?.column === column} isDraggingColumn={draggedColumn?.column === column}
onColumnHover={(_, mouseX, rect) => handleColumnHover(visualIndex, mouseX, rect)}
isAnyColumnDragging={!!draggedColumn}
/> />
</> </>
))} );
})}
{columnDropPosition === columns?.length && draggedColumn && ( {columnDropPosition === columns?.length && draggedColumn && (
<div className="column-drop-placeholder show" /> <div className="column-drop-placeholder show" />
)} )}