diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-04-20 11:31:17 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-04-20 11:31:17 +0200 |
| commit | 3e89d2998588f8e35c524e523ba2ee853f0f6475 (patch) | |
| tree | 57221f96c1259b3b07e3ddf8c1adefc502b9d8eb /apps/web/src/preview/components/preview-interaction-overlay.tsx | |
| parent | 729d10592f4e802f91c555c309ff3ba4b119f843 (diff) | |
| download | opencut-3e89d2998588f8e35c524e523ba2ee853f0f6475.tar.gz | |
refactor: restructure files to their domains, new preview overlay system, and dep graph
Diffstat (limited to 'apps/web/src/preview/components/preview-interaction-overlay.tsx')
| -rw-r--r-- | apps/web/src/preview/components/preview-interaction-overlay.tsx | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/apps/web/src/preview/components/preview-interaction-overlay.tsx b/apps/web/src/preview/components/preview-interaction-overlay.tsx new file mode 100644 index 00000000..e16a31d2 --- /dev/null +++ b/apps/web/src/preview/components/preview-interaction-overlay.tsx @@ -0,0 +1,103 @@ +import { useState } from "react"; +import { usePreviewViewport } from "@/preview/components/preview-viewport"; +import { usePreviewInteraction } from "@/preview/hooks/use-preview-interaction"; +import type { SnapLine } from "@/preview/preview-snap"; +import { TransformHandles } from "./transform-handles"; +import { MaskHandles } from "./mask-handles"; +import { SnapGuides } from "./snap-guides"; +import { TextEditOverlay } from "./text-edit-overlay"; +import { usePropertiesStore } from "@/components/editor/panels/properties/stores/properties-store"; +import { useEditor } from "@/editor/use-editor"; + +export function PreviewInteractionOverlay() { + const [snapLines, setSnapLines] = useState<SnapLine[]>([]); + const editor = useEditor(); + const viewport = usePreviewViewport(); + const selectedElements = useEditor((e) => e.selection.getSelectedElements()); + const activeTabPerType = usePropertiesStore((s) => s.activeTabPerType); + + const selectedRef = + selectedElements.length === 1 ? selectedElements[0] : null; + const activeTrack = selectedRef + ? editor.timeline.getTrackById({ trackId: selectedRef.trackId }) + : null; + const activeElement = + activeTrack?.elements.find( + (element) => element.id === selectedRef?.elementId, + ) ?? null; + const isMaskMode = activeElement + ? activeTabPerType[activeElement.type] === "masks" + : false; + + const { + onPointerDown, + onPointerMove, + onPointerUp, + onDoubleClick, + editingText, + commitTextEdit, + } = usePreviewInteraction({ + onSnapLinesChange: setSnapLines, + isMaskMode, + }); + + const handlePointerDown = (event: React.PointerEvent) => { + if (viewport.handlePanPointerDown({ event })) { + return; + } + + onPointerDown(event); + }; + + const handlePointerMove = (event: React.PointerEvent) => { + if (viewport.handlePanPointerMove({ event })) { + return; + } + + onPointerMove(event); + }; + + const handlePointerUp = (event: React.PointerEvent) => { + if (viewport.handlePanPointerUp({ event })) { + return; + } + + onPointerUp(event); + }; + + return ( + <div className="absolute inset-0"> + <div + className="absolute inset-0 pointer-events-auto" + role="application" + aria-label="Preview canvas" + style={{ + cursor: viewport.isPanning + ? "grabbing" + : viewport.canPan + ? "default" + : undefined, + }} + onPointerDown={handlePointerDown} + onPointerMove={handlePointerMove} + onPointerUp={handlePointerUp} + onPointerCancel={handlePointerUp} + onDoubleClick={onDoubleClick} + onDragStart={(e) => e.preventDefault()} + /> + {editingText ? ( + <TextEditOverlay + trackId={editingText.trackId} + elementId={editingText.elementId} + element={editingText.element} + onCommit={commitTextEdit} + /> + ) : isMaskMode ? ( + <MaskHandles onSnapLinesChange={setSnapLines} /> + ) : ( + <TransformHandles onSnapLinesChange={setSnapLines} /> + )} + <SnapGuides lines={snapLines} /> + </div> + ); +} |
