summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/drag-source.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-26 17:31:28 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-26 17:31:28 +0200
commit56ca09692a308b22455420d11376ff8d41244c47 (patch)
tree4eca5ae032451c5db954801008aa9f164b2e2b1d /apps/web/src/timeline/drag-source.ts
parente6c6193638e4247ff1e6f2df40de2a057112c773 (diff)
downloadopencut-56ca09692a308b22455420d11376ff8d41244c47.tar.gz
refactor: thinner hooks
Diffstat (limited to 'apps/web/src/timeline/drag-source.ts')
-rw-r--r--apps/web/src/timeline/drag-source.ts40
1 files changed, 40 insertions, 0 deletions
diff --git a/apps/web/src/timeline/drag-source.ts b/apps/web/src/timeline/drag-source.ts
new file mode 100644
index 00000000..503c547b
--- /dev/null
+++ b/apps/web/src/timeline/drag-source.ts
@@ -0,0 +1,40 @@
+import type { TimelineDragData } from "@/timeline/drag";
+
+const TIMELINE_DRAG_MIME = "application/x-timeline-drag";
+
+/**
+ * Owns the state of an in-progress timeline drag session.
+ *
+ * Exists because browsers restrict `DataTransfer.getData()` to the `drop`
+ * event for security — during `dragover`/`dragenter` only `types` is
+ * readable. The drop target needs the payload (element type, target
+ * element types, source duration) while the pointer is hovering, so we
+ * keep a live copy here and hand it out via {@link getActive}.
+ */
+export class TimelineDragSource {
+ private active: TimelineDragData | null = null;
+
+ begin({
+ dataTransfer,
+ dragData,
+ }: {
+ dataTransfer: DataTransfer;
+ dragData: TimelineDragData;
+ }): void {
+ dataTransfer.setData(TIMELINE_DRAG_MIME, JSON.stringify(dragData));
+ dataTransfer.effectAllowed = "copy";
+ this.active = dragData;
+ }
+
+ end(): void {
+ this.active = null;
+ }
+
+ getActive(): TimelineDragData | null {
+ return this.active;
+ }
+
+ isActive(): boolean {
+ return this.active !== null;
+ }
+}