diff options
| author | kamtschatka <simon.schatka@gmx.at> | 2024-07-01 13:59:10 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-01 12:59:10 +0100 |
| commit | 9cd617055b7878048120eebd58dc2e05a9cbdfca (patch) | |
| tree | 4c80908640bb6b92e355d027ed64fce26fac2454 /apps/web/lib/drag-and-drop.ts | |
| parent | 9883c6bcd18c2ca1fda7d83e465a0bf9cf45510d (diff) | |
| download | karakeep-9cd617055b7878048120eebd58dc2e05a9cbdfca.tar.zst | |
refactor: drag and drop improvements (#264)
* [Feature request] Drag and Drop Items to Lists #123
reworked the drag and drop mechanism to still have change detection, but not so much that it has a huge overhead
Changed the layout a bit to allow proper drag/drop of elements from the main section to the sidebar
Added the possibility to drag/drop bookmarks onto lists
* [Feature request] Drag and Drop Items to Lists #123
Removed the changes to allow dragging&dropping bookmarks
Diffstat (limited to 'apps/web/lib/drag-and-drop.ts')
| -rw-r--r-- | apps/web/lib/drag-and-drop.ts | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/apps/web/lib/drag-and-drop.ts b/apps/web/lib/drag-and-drop.ts index e005a6d0..ec37e810 100644 --- a/apps/web/lib/drag-and-drop.ts +++ b/apps/web/lib/drag-and-drop.ts @@ -1,31 +1,48 @@ import React from "react"; -import { DraggableData, DraggableEvent } from "react-draggable"; +import { DraggableEvent } from "react-draggable"; + +export interface DraggingState { + isDragging: boolean; + initialX: number; + initialY: number; +} export function useDragAndDrop( - dragSourceIdAttribute: string, dragTargetIdAttribute: string, - onDragOver: (dragSourceId: string, dragTargetId: string) => void, + onDragOver: (dragTargetId: string) => void, + setDraggingState?: React.Dispatch<React.SetStateAction<DraggingState>>, ) { - const [dragSourceId, setDragSourceId] = React.useState<string | null>(null); + function findTargetId(element: HTMLElement): string | null { + let currentElement: HTMLElement | null = element; + while (currentElement) { + const listId = currentElement.getAttribute(dragTargetIdAttribute); + if (listId) { + return listId; + } + currentElement = currentElement.parentElement; + } + return null; + } const handleDragStart = React.useCallback( - (_e: DraggableEvent, { node }: DraggableData) => { - const id = node.getAttribute(dragSourceIdAttribute); - setDragSourceId(id); + (e: DraggableEvent) => { + const rect = (e.target as HTMLElement).getBoundingClientRect(); + setDraggingState?.({ + isDragging: true, + initialX: rect.x, + initialY: rect.y, + }); }, - [], + [setDraggingState], ); const handleDragEnd = React.useCallback( (e: DraggableEvent) => { const { target } = e; - const dragTargetId = (target as HTMLElement).getAttribute( - dragTargetIdAttribute, - ); + const dragTargetId = findTargetId(target as HTMLElement); - if (dragSourceId && dragTargetId && dragSourceId !== dragTargetId) { - /* - As Draggable tries to setState when the + if (dragTargetId) { + /* As Draggable tries to setState when the component is unmounted, it is needed to push onCombine to the event loop queue. onCombine would be run after setState on @@ -33,12 +50,16 @@ export function useDragAndDrop( they fix it on their end. */ setTimeout(() => { - onDragOver(dragSourceId, dragTargetId); + onDragOver(dragTargetId); }, 0); } - setDragSourceId(null); + setDraggingState?.({ + isDragging: false, + initialX: 0, + initialY: 0, + }); }, - [dragSourceId, onDragOver], + [onDragOver], ); return { |
