From 40c7fbb4f86130c83fbd9029e83c5e7550e3219d Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Sun, 6 Jul 2025 20:45:29 +0200 Subject: refactor: move to a typed-tracks system and add support for text --- apps/web/src/types/timeline.ts | 73 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 7 deletions(-) (limited to 'apps/web/src/types') diff --git a/apps/web/src/types/timeline.ts b/apps/web/src/types/timeline.ts index 54a433a7..daada718 100644 --- a/apps/web/src/types/timeline.ts +++ b/apps/web/src/types/timeline.ts @@ -1,20 +1,79 @@ -import { TimelineTrack, TimelineClip } from "@/stores/timeline-store"; +import { MediaType } from "@/stores/media-store"; +import { TimelineTrack } from "@/stores/timeline-store"; -export type TrackType = "video" | "audio" | "effects"; +export type TrackType = "media" | "text" | "audio"; -export interface TimelineClipProps { - clip: TimelineClip; +// Base element properties +interface BaseTimelineElement { + id: string; + name: string; + duration: number; + startTime: number; + trimStart: number; + trimEnd: number; +} + +// Media element that references MediaStore +export interface MediaElement extends BaseTimelineElement { + type: "media"; + mediaId: string; +} + +// Text element with embedded text data +export interface TextElement extends BaseTimelineElement { + type: "text"; + content: string; + fontSize: number; + fontFamily: string; + color: string; + backgroundColor: string; + textAlign: "left" | "center" | "right"; + fontWeight: "normal" | "bold"; + fontStyle: "normal" | "italic"; + textDecoration: "none" | "underline" | "line-through"; + x: number; // Position relative to canvas center + y: number; // Position relative to canvas center + rotation: number; // in degrees + opacity: number; // 0-1 +} + +// Typed timeline elements +export type TimelineElement = MediaElement | TextElement; + +// Creation types (without id, for addElementToTrack) +export type CreateMediaElement = Omit; +export type CreateTextElement = Omit; +export type CreateTimelineElement = CreateMediaElement | CreateTextElement; + +export interface TimelineElementProps { + element: TimelineElement; track: TimelineTrack; zoomLevel: number; isSelected: boolean; - onClipMouseDown: (e: React.MouseEvent, clip: TimelineClip) => void; - onClipClick: (e: React.MouseEvent, clip: TimelineClip) => void; + onElementMouseDown: (e: React.MouseEvent, element: TimelineElement) => void; + onElementClick: (e: React.MouseEvent, element: TimelineElement) => void; } export interface ResizeState { - clipId: string; + elementId: string; side: "left" | "right"; startX: number; initialTrimStart: number; initialTrimEnd: number; } + +// Drag data types for type-safe drag and drop +export interface MediaItemDragData { + id: string; + type: MediaType; + name: string; +} + +export interface TextItemDragData { + id: string; + type: "text"; + name: string; + content: string; +} + +export type DragData = MediaItemDragData | TextItemDragData; -- cgit v1.3.1