diff options
| author | kamtschatka <sschatka@gmail.com> | 2024-05-18 12:22:50 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-18 11:22:50 +0100 |
| commit | 1fee129c337069fc41d1c46141beaaec94033af8 (patch) | |
| tree | 1eec8b4f971731b6c24fafd93f7fc6adf881f32c /apps/web/lib | |
| parent | 6eea67186c2fa5f5c5e155c7fe17f63a0114157f (diff) | |
| download | karakeep-1fee129c337069fc41d1c46141beaaec94033af8.tar.zst | |
feature(web): Improve merging of tags by simple drag and drop #144 (#154)
* Improve merging of tags by simple drag and drop #144
Added drag&drop functionality
Allowing sorting the tags by name, as this is more intuitive
* Improve merging of tags by simple drag and drop #144
minor renamings
removed some unnecessary code
* Improve merging of tags by simple drag and drop #144
extracted out the drag and drop functionality to be more encapsulated and reusable
* Improve merging of tags by simple drag and drop #144
improved the usage sorter to additionally compare by name if the usage is the same
* Improve merging of tags by simple drag and drop #144
replaced checkboxes with toggles floating on the right
---------
Co-authored-by: kamtschatka <simon.schatka@gmx.at>
Diffstat (limited to 'apps/web/lib')
| -rw-r--r-- | apps/web/lib/drag-and-drop.ts | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/apps/web/lib/drag-and-drop.ts b/apps/web/lib/drag-and-drop.ts new file mode 100644 index 00000000..03a9e7c3 --- /dev/null +++ b/apps/web/lib/drag-and-drop.ts @@ -0,0 +1,89 @@ +import { DraggableData, DraggableEvent } from "react-draggable"; + +export interface DragState { + // The id of the element that is being dragged + dragSourceId: string | null; + // The id of the element that is currently being hovered over + dragTargetId: string | null; + // The position of the elements being dragged such that on drag over, we can revert the position. + initialX: number; + initialY: number; +} + +export interface DragAndDropFunctions { + handleDragStart: (e: DraggableEvent, data: DraggableData) => void; + handleDrag: (e: DraggableEvent) => void; + handleDragEnd: () => void; + dragState: DragState; +} + +export function useDragAndDrop( + dragSourceIdAttribute: string, + dragTargetIdAttribute: string, + callback: (dragSourceId: string, dragTargetId: string) => void, +): DragAndDropFunctions { + const initialState: DragState = { + dragSourceId: null, + dragTargetId: null, + initialX: 0, + initialY: 0, + }; + + let currentState: DragState = initialState; + + function handleDragStart(e: DraggableEvent, data: DraggableData): void { + const { node } = data; + const id = node.getAttribute(dragSourceIdAttribute); + + currentState = { + ...initialState, + dragSourceId: id, + initialX: data.x, + initialY: data.y, + }; + } + + function handleDrag(e: DraggableEvent): void { + const { dragTargetId } = currentState; + const { target } = e; + + // Important according to the sample I found + e.preventDefault(); + + if (target) { + const id = (target as HTMLElement).getAttribute(dragTargetIdAttribute); + + if (id !== dragTargetId) { + currentState.dragTargetId = id; + } + } + } + + function handleDragEnd(): void { + const { dragSourceId, dragTargetId } = currentState; + + if (dragSourceId && dragTargetId && dragSourceId !== 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 + Draggable so it would fix the issue until + they fix it on their end. + */ + setTimeout(() => { + console.log(dragSourceId, dragTargetId); + callback(dragSourceId, dragTargetId); + }, 0); + } + + currentState = initialState; + } + + return { + dragState: currentState, + handleDragStart, + handleDrag, + handleDragEnd, + }; +} |
