summaryrefslogtreecommitdiff
path: root/legacy/timeline/use-selection-box.ts
diff options
context:
space:
mode:
Diffstat (limited to 'legacy/timeline/use-selection-box.ts')
-rw-r--r--legacy/timeline/use-selection-box.ts265
1 files changed, 0 insertions, 265 deletions
diff --git a/legacy/timeline/use-selection-box.ts b/legacy/timeline/use-selection-box.ts
deleted file mode 100644
index 979bb480..00000000
--- a/legacy/timeline/use-selection-box.ts
+++ /dev/null
@@ -1,265 +0,0 @@
-import { useCallback, useEffect, useRef, useState } from "react";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
-import { getCumulativeHeightBefore, getTrackHeight } from "@/lib/timeline";
-import { useEditor } from "../use-editor";
-
-interface UseSelectionBoxProps {
- containerRef: React.RefObject<HTMLElement | null>;
- headerRef?: React.RefObject<HTMLElement | null>;
- onSelectionComplete: ({
- elements,
- isAdditive,
- }: {
- elements: { trackId: string; elementId: string }[];
- isAdditive: boolean;
- }) => void;
- isEnabled?: boolean;
- tracksScrollRef: React.RefObject<HTMLDivElement | null>;
- zoomLevel: number;
-}
-
-interface SelectionBoxState {
- startPos: { x: number; y: number };
- currentPos: { x: number; y: number };
- isActive: boolean;
- isAdditive: boolean;
-}
-
-interface SelectionRectangle {
- left: number;
- top: number;
- right: number;
- bottom: number;
-}
-
-function getNormalizedRectangle({
- startPos,
- endPos,
-}: {
- startPos: { x: number; y: number };
- endPos: { x: number; y: number };
-}): SelectionRectangle {
- return {
- left: Math.min(startPos.x, endPos.x),
- top: Math.min(startPos.y, endPos.y),
- right: Math.max(startPos.x, endPos.x),
- bottom: Math.max(startPos.y, endPos.y),
- };
-}
-
-function getSelectionRectangleInContent({
- container,
- scrollContainer,
- startPos,
- endPos,
-}: {
- container: HTMLElement;
- scrollContainer: HTMLDivElement | null;
- startPos: { x: number; y: number };
- endPos: { x: number; y: number };
-}): SelectionRectangle {
- const containerRect = container.getBoundingClientRect();
- const scrollRect = scrollContainer?.getBoundingClientRect() ?? containerRect;
- const scrollLeft = scrollContainer?.scrollLeft ?? 0;
- const scrollTop = scrollContainer?.scrollTop ?? 0;
-
- const adjustedStart = {
- x: startPos.x - containerRect.left + scrollLeft,
- y: startPos.y - scrollRect.top + scrollTop,
- };
- const adjustedEnd = {
- x: endPos.x - containerRect.left + scrollLeft,
- y: endPos.y - scrollRect.top + scrollTop,
- };
-
- return getNormalizedRectangle({
- startPos: adjustedStart,
- endPos: adjustedEnd,
- });
-}
-
-function isRectangleIntersecting({
- elementRectangle,
- selectionRectangle,
-}: {
- elementRectangle: SelectionRectangle;
- selectionRectangle: SelectionRectangle;
-}): boolean {
- return !(
- elementRectangle.right < selectionRectangle.left ||
- elementRectangle.left > selectionRectangle.right ||
- elementRectangle.bottom < selectionRectangle.top ||
- elementRectangle.top > selectionRectangle.bottom
- );
-}
-
-export function useSelectionBox({
- containerRef,
- headerRef,
- onSelectionComplete,
- isEnabled = true,
- tracksScrollRef,
- zoomLevel,
-}: UseSelectionBoxProps) {
- const editor = useEditor();
- const [selectionBox, setSelectionBox] = useState<SelectionBoxState | null>(
- null,
- );
- const justFinishedSelectingRef = useRef(false);
-
- const handleMouseDown = useCallback(
- ({ clientX, clientY, shiftKey, ctrlKey, metaKey }: React.MouseEvent) => {
- if (!isEnabled) return;
-
- setSelectionBox({
- startPos: { x: clientX, y: clientY },
- currentPos: { x: clientX, y: clientY },
- isActive: false,
- isAdditive: shiftKey || ctrlKey || metaKey,
- });
- },
- [isEnabled],
- );
-
- const selectElementsInBox = useCallback(
- ({
- startPos,
- endPos,
- isAdditive,
- }: {
- startPos: { x: number; y: number };
- endPos: { x: number; y: number };
- isAdditive: boolean;
- }) => {
- if (!containerRef.current) return;
-
- const tracks = editor.timeline.getTracks();
- const container = containerRef.current;
- const selectionRectangle = getSelectionRectangleInContent({
- container,
- scrollContainer: tracksScrollRef.current,
- startPos,
- endPos,
- });
- const pixelsPerSecond = TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel;
- const timelineHeaderHeight =
- headerRef?.current?.getBoundingClientRect().height ?? 0;
- const selectedElements: { trackId: string; elementId: string }[] = [];
-
- for (const [trackIndex, track] of tracks.entries()) {
- const trackTop = getCumulativeHeightBefore({
- tracks,
- trackIndex,
- });
- const trackHeight = getTrackHeight({ type: track.type });
- const elementTop =
- timelineHeaderHeight + TIMELINE_CONSTANTS.PADDING_TOP_PX + trackTop;
- const elementBottom = elementTop + trackHeight;
-
- for (const element of track.elements) {
- const elementLeft = element.startTime * pixelsPerSecond;
- const elementRight = elementLeft + element.duration * pixelsPerSecond;
-
- const elementRectangle = {
- left: elementLeft,
- top: elementTop,
- right: elementRight,
- bottom: elementBottom,
- };
-
- const intersects = isRectangleIntersecting({
- elementRectangle,
- selectionRectangle,
- });
-
- if (intersects) {
- selectedElements.push({
- trackId: track.id,
- elementId: element.id,
- });
- }
- }
- }
- onSelectionComplete({ elements: selectedElements, isAdditive });
- },
- [
- containerRef,
- headerRef,
- onSelectionComplete,
- editor,
- tracksScrollRef,
- zoomLevel,
- ],
- );
-
- useEffect(() => {
- if (!selectionBox) return;
-
- const handleMouseMove = ({ clientX, clientY }: MouseEvent) => {
- const deltaX = Math.abs(clientX - selectionBox.startPos.x);
- const deltaY = Math.abs(clientY - selectionBox.startPos.y);
- const shouldActivate = deltaX > 5 || deltaY > 5;
-
- const newSelectionBox = {
- ...selectionBox,
- currentPos: { x: clientX, y: clientY },
- isActive: shouldActivate || selectionBox.isActive,
- };
-
- setSelectionBox(newSelectionBox);
-
- if (newSelectionBox.isActive) {
- selectElementsInBox({
- startPos: newSelectionBox.startPos,
- endPos: newSelectionBox.currentPos,
- isAdditive: newSelectionBox.isAdditive,
- });
- }
- };
-
- const handleMouseUp = () => {
- if (selectionBox?.isActive) {
- justFinishedSelectingRef.current = true;
- requestAnimationFrame(() => {
- justFinishedSelectingRef.current = false;
- });
- }
- setSelectionBox(null);
- };
-
- window.addEventListener("mousemove", handleMouseMove);
- window.addEventListener("mouseup", handleMouseUp);
-
- return () => {
- window.removeEventListener("mousemove", handleMouseMove);
- window.removeEventListener("mouseup", handleMouseUp);
- };
- }, [selectionBox, selectElementsInBox]);
-
- useEffect(() => {
- if (!selectionBox) return;
-
- const previousBodyUserSelect = document.body.style.userSelect;
- const container = containerRef.current;
- const previousContainerUserSelect = container?.style.userSelect ?? "";
-
- document.body.style.userSelect = "none";
- if (container) container.style.userSelect = "none";
-
- return () => {
- document.body.style.userSelect = previousBodyUserSelect;
- if (container) container.style.userSelect = previousContainerUserSelect;
- };
- }, [selectionBox, containerRef]);
-
- const shouldIgnoreClick = useCallback(() => {
- return justFinishedSelectingRef.current;
- }, []);
-
- return {
- selectionBox,
- handleMouseDown,
- isSelecting: selectionBox?.isActive || false,
- shouldIgnoreClick,
- };
-}