summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-20 11:31:17 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-20 11:31:17 +0200
commit3e89d2998588f8e35c524e523ba2ee853f0f6475 (patch)
tree57221f96c1259b3b07e3ddf8c1adefc502b9d8eb /apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts
parent729d10592f4e802f91c555c309ff3ba4b119f843 (diff)
downloadopencut-3e89d2998588f8e35c524e523ba2ee853f0f6475.tar.gz
refactor: restructure files to their domains, new preview overlay system, and dep graph
Diffstat (limited to 'apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts')
-rw-r--r--apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts222
1 files changed, 0 insertions, 222 deletions
diff --git a/apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts b/apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts
deleted file mode 100644
index 0fc46372..00000000
--- a/apps/web/src/hooks/timeline/element/use-keyframe-box-select.ts
+++ /dev/null
@@ -1,222 +0,0 @@
-import { useCallback, useRef, useMemo } from "react";
-import { useBoxSelect } from "@/lib/selection/hooks/use-box-select";
-import {
- useKeyframeSelection,
- getSelectedKeyframeId,
-} from "./use-keyframe-selection";
-import type {
- SelectedKeyframeRef,
- ElementKeyframe,
-} from "@/lib/animation/types";
-import type { ExpandedRow } from "@/components/editor/panels/timeline/expanded-layout";
-import { timelineTimeToSnappedPixels } from "@/lib/timeline";
-import {
- KEYFRAME_LANE_HEIGHT_PX,
- KEYFRAME_DIAMOND_SIZE_PX,
-} from "@/components/editor/panels/timeline/layout";
-
-export function useKeyframeBoxSelect({
- trackId,
- elementId,
- rows,
- keyframes,
- displayedStartTime,
- zoomLevel,
- elementLeft,
-}: {
- trackId: string;
- elementId: string;
- rows: ExpandedRow[];
- keyframes: ElementKeyframe[];
- displayedStartTime: number;
- zoomLevel: number;
- elementLeft: number;
-}) {
- const {
- selectedKeyframes,
- keyframeSelectionAnchor,
- setKeyframeSelection,
- clearKeyframeSelection,
- } = useKeyframeSelection();
-
- const containerRef = useRef<HTMLDivElement>(null);
- const initialKeyframesRef = useRef<SelectedKeyframeRef[]>([]);
-
- const keyframeEntries = useMemo(() => {
- const entries: Array<{
- id: string;
- ref: SelectedKeyframeRef;
- rowIndex: number;
- offsetPx: number;
- }> = [];
-
- for (const kf of keyframes) {
- const rowIndex = rows.findIndex(
- (r) => r.propertyPath === kf.propertyPath,
- );
- if (rowIndex === -1) continue;
-
- const ref: SelectedKeyframeRef = {
- trackId,
- elementId,
- propertyPath: kf.propertyPath,
- keyframeId: kf.id,
- };
-
- const kfLeft = timelineTimeToSnappedPixels({
- time: displayedStartTime + kf.time,
- zoomLevel,
- });
-
- entries.push({
- id: getSelectedKeyframeId({ keyframe: ref }),
- ref,
- rowIndex,
- offsetPx: kfLeft - elementLeft,
- });
- }
-
- return entries;
- }, [
- keyframes,
- rows,
- trackId,
- elementId,
- displayedStartTime,
- zoomLevel,
- elementLeft,
- ]);
-
- const idToRefMap = useMemo(() => {
- const map = new Map<string, SelectedKeyframeRef>();
- for (const entry of keyframeEntries) {
- map.set(entry.id, entry.ref);
- }
- return map;
- }, [keyframeEntries]);
-
- const selectedIds = useMemo(
- () => selectedKeyframes.map((keyframe) => getSelectedKeyframeId({ keyframe })),
- [selectedKeyframes],
- );
-
- const anchorId = useMemo(
- () =>
- keyframeSelectionAnchor
- ? getSelectedKeyframeId({ keyframe: keyframeSelectionAnchor })
- : null,
- [keyframeSelectionAnchor],
- );
-
- const resolveIntersections = useCallback(
- ({
- startPos,
- currentPos,
- }: {
- startPos: { x: number; y: number };
- currentPos: { x: number; y: number };
- }) => {
- const container = containerRef.current;
- if (!container) return [];
-
- const containerRect = container.getBoundingClientRect();
-
- const sx = startPos.x - containerRect.left;
- const sy = startPos.y - containerRect.top;
- const cx = currentPos.x - containerRect.left;
- const cy = currentPos.y - containerRect.top;
-
- const selLeft = Math.min(sx, cx);
- const selTop = Math.min(sy, cy);
- const selRight = Math.max(sx, cx);
- const selBottom = Math.max(sy, cy);
-
- const halfHit = KEYFRAME_DIAMOND_SIZE_PX / 2;
-
- return keyframeEntries
- .filter((entry) => {
- const kfX = entry.offsetPx;
- const kfY =
- entry.rowIndex * KEYFRAME_LANE_HEIGHT_PX +
- KEYFRAME_LANE_HEIGHT_PX / 2;
-
- return !(
- kfX + halfHit < selLeft ||
- kfX - halfHit > selRight ||
- kfY + halfHit < selTop ||
- kfY - halfHit > selBottom
- );
- })
- .map((entry) => entry.id);
- },
- [keyframeEntries],
- );
-
- const onSelectionChange = useCallback(
- ({
- intersectedIds,
- isAdditive,
- }: {
- intersectedIds: string[];
- initialSelectedIds: string[];
- initialAnchorId: string | null;
- isAdditive: boolean;
- }) => {
- const intersectedRefs = intersectedIds
- .map((id) => idToRefMap.get(id))
- .filter((ref): ref is SelectedKeyframeRef => ref != null);
-
- if (isAdditive) {
- setKeyframeSelection({
- keyframes: [
- ...initialKeyframesRef.current,
- ...intersectedRefs,
- ],
- });
- } else {
- setKeyframeSelection({ keyframes: intersectedRefs });
- }
- },
- [idToRefMap, setKeyframeSelection],
- );
-
- const {
- selectionBox,
- handleMouseDown: boxSelectMouseDown,
- isSelecting,
- shouldIgnoreClick,
- } = useBoxSelect<string>({
- containerRef,
- resolveIntersections,
- selectedIds,
- anchorId,
- onSelectionChange,
- });
-
- const handleExpandedAreaMouseDown = useCallback(
- (event: React.MouseEvent) => {
- event.stopPropagation();
- initialKeyframesRef.current = selectedKeyframes;
- boxSelectMouseDown(event);
- },
- [boxSelectMouseDown, selectedKeyframes],
- );
-
- const handleExpandedAreaClick = useCallback(
- (event: React.MouseEvent) => {
- event.stopPropagation();
- if (shouldIgnoreClick()) return;
- if (event.metaKey || event.ctrlKey || event.shiftKey) return;
- clearKeyframeSelection();
- },
- [shouldIgnoreClick, clearKeyframeSelection],
- );
-
- return {
- containerRef,
- selectionBox,
- isBoxSelecting: isSelecting,
- handleExpandedAreaMouseDown,
- handleExpandedAreaClick,
- };
-}