summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/drag-source.ts
diff options
context:
space:
mode:
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;
+ }
+}