summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/drag-source.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-25 03:56:22 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-25 03:56:22 +0200
commit6a22a3ecbdff2d0e6a4c24c8db40bb86bc01b692 (patch)
tree976d60dbe1ac8e44d6a9259f9d6e20fe6530c698 /apps/web/src/timeline/drag-source.ts
parent0dffefdd59d8c70fece63436e8556f8ec1e43a49 (diff)
downloadopencut-6a22a3ecbdff2d0e6a4c24c8db40bb86bc01b692.tar.gz
refactor: centralize editor interaction state
Move timeline and preview gestures into dedicated controllers so hooks stay thin around editor state and DOM events. This also routes drag and playback synchronization through manager APIs and reuses persistent wasm surfaces so scrubbing, seeking, and preview rendering stay in sync. Made-with: Cursor
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;
+ }
+}