Files
hyperframes/packages/studio/src/player/components/timelineCallbacks.ts
T
Miguel Angel Simon Sierra e5ed512529 feat(studio): timeline track = stacking layer (NLE-style layering)
Re-architect the timeline row model from data-track-index rows to stacking
layers. Rows represent stacking layers per context: explicit-z clips merge onto
one track when they share a z and don't overlap in time; auto-z clips stay one
row each (DOM order); audio is pulled into its own bottom lanes. Rows keyed by a
stable layer id, not data-track-index.

Vertical drag always writes z-index, never track: drop onto a layer joins it
(same z), between layers interpolates a new z, past the ends creates a new
front/back layer. data-track-index is never rewritten; #958 holds. Adds
hasExplicitZIndex capture (computed z != auto).

L1: hasExplicitZIndex on the element model
L2: buildStackingTimelineLayers (layer-based rows)
L3: layer-aware vertical drag (join / interpolate / new-extreme)
2026-07-08 23:46:25 -04:00

54 lines
2.2 KiB
TypeScript

// fallow-ignore-file code-duplication
// fallow-ignore-file dead-code
import type { TimelineElement } from "../store/playerStore";
import type { BlockedTimelineEditIntent, TimelineStackingReorderIntent } from "./timelineEditing";
/**
* Shared callback signatures for timeline editing operations.
* Used by NLELayout, Timeline, and any component that passes through
* the standard set of timeline mutation handlers.
*/
export interface TimelineDropCallbacks {
onFileDrop?: (
files: File[],
placement?: { start: number; track: number },
) => Promise<void> | void;
onAssetDrop?: (
assetPath: string,
placement: { start: number; track: number },
) => Promise<void> | void;
onBlockDrop?: (
blockName: string,
placement: { start: number; track: number },
) => Promise<void> | void;
}
export interface TimelineEditCallbacks {
onMoveElement?: (
element: TimelineElement,
updates: Pick<TimelineElement, "start" | "track"> & {
stackingReorder?: TimelineStackingReorderIntent | null;
},
) => Promise<void> | void;
onResizeElement?: (
element: TimelineElement,
updates: Pick<TimelineElement, "start" | "duration" | "playbackStart">,
) => Promise<void> | void;
onToggleTrackHidden?: (track: number, hidden: boolean) => Promise<void> | void;
onToggleElementHidden?: (elementKey: string, hidden: boolean) => Promise<void> | void;
onBlockedEditAttempt?: (element: TimelineElement, intent: BlockedTimelineEditIntent) => void;
onSplitElement?: (element: TimelineElement, splitTime: number) => Promise<void> | void;
onRazorSplit?: (element: TimelineElement, splitTime: number) => Promise<void> | void;
onRazorSplitAll?: (splitTime: number) => Promise<void> | void;
onDeleteKeyframe?: (elementId: string, percentage: number) => void;
onDeleteAllKeyframes?: (elementId: string) => void;
onChangeKeyframeEase?: (elementId: string, percentage: number, ease: string) => void;
onMoveKeyframeToPlayhead?: (elementId: string, percentage: number) => void;
onMoveKeyframe?: (
elementId: string,
fromClipPercentage: number,
toClipPercentage: number,
) => void;
onToggleKeyframeAtPlayhead?: (element: TimelineElement) => void;
}