Files
hyperframes/packages/studio/src/player/components/timelineAuthoredTrack.ts
T
Miguel Ángel 2b65b4efce fix(studio): harden composition timeline reliability (#2615)
* fix(studio): preserve composition playback continuity

* feat(studio): drag compositions into the timeline

* fix(studio): collapse expanded composition move aliases

* fix(studio): make timeline cuts atomic

* fix(studio): group inspector gesture history

* test(studio): cover masked text selection

* fix(studio): harden composition timeline reliability

* fix(studio): satisfy CI source gates

* fix(studio): harden composition mutation requests
2026-07-17 14:15:30 -04:00

30 lines
1.2 KiB
TypeScript

import type { TimelineElement } from "../store/playerStore";
const keyOf = (element: TimelineElement) => element.key ?? element.id;
/** Authored track numbers only compare within one source file. */
export const sameSourceFile = (a: TimelineElement, b: TimelineElement): boolean =>
(a.sourceFile ?? null) === (b.sourceFile ?? null);
/** Translate a display lane into the source-file track to persist. */
export function authoredTrackForLane(
lane: number,
elements: TimelineElement[],
dragged: TimelineElement,
): number {
const dragKey = keyOf(dragged);
const peers = elements.filter((element) => {
return keyOf(element) !== dragKey && sameSourceFile(element, dragged);
});
const occupant = peers.find((element) => element.track === lane);
if (occupant) return occupant.authoredTrack ?? occupant.track;
let nearest: TimelineElement | null = null;
for (const peer of peers) {
if (!nearest || Math.abs(peer.track - lane) < Math.abs(nearest.track - lane)) nearest = peer;
}
if (!nearest) return lane;
// Synthetic expanded-child display rows can be fractional; authored tracks cannot.
return Math.round((nearest.authoredTrack ?? nearest.track) + (lane - nearest.track));
}