aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/lib/drag-and-drop.ts
diff options
context:
space:
mode:
authorkamtschatka <sschatka@gmail.com>2024-05-18 12:22:50 +0200
committerGitHub <noreply@github.com>2024-05-18 11:22:50 +0100
commit1fee129c337069fc41d1c46141beaaec94033af8 (patch)
tree1eec8b4f971731b6c24fafd93f7fc6adf881f32c /apps/web/lib/drag-and-drop.ts
parent6eea67186c2fa5f5c5e155c7fe17f63a0114157f (diff)
downloadkarakeep-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/drag-and-drop.ts')
-rw-r--r--apps/web/lib/drag-and-drop.ts89
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,
+ };
+}