mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
L4 polish for the stacking-layer timeline: - Sub-composition layers group under a slim "Inside: <comp>" header with a green accent, so it reads that restacking there is scoped to that context. - Audio clips render in a distinct bottom lane: separator border, muted row bg, music glyph in the gutter, beat strip — clearly not part of the z-order stack. - During a vertical drag, a drop affordance shows join-vs-insert: an "onto" target highlights the row (join that layer / same z); "between"/"above"/ "below" shows an insertion line (new layer here). New pure helper timelineDropIndicator.ts (+ test) maps placement -> indicator; row-group rendering extracted into TimelineLayerGroupHeader / TimelineLayerGutter / TimelineDropInsertionLine / TimelineDragGhost to keep files under the 600 cap.
60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { TimelineClip } from "./TimelineClip";
|
|
import { getTimelineEditCapabilities } from "./timelineEditing";
|
|
import { CLIP_Y, TRACK_H } from "./timelineLayout";
|
|
import type { TimelineTheme } from "./timelineTheme";
|
|
import type { TimelineElement } from "../store/playerStore";
|
|
|
|
interface TimelineDragGhostProps {
|
|
element: TimelineElement;
|
|
position: { left: number; top: number };
|
|
pps: number;
|
|
selectedElementId: string | null;
|
|
hasCustomContent: boolean;
|
|
theme: TimelineTheme;
|
|
children: ReactNode;
|
|
}
|
|
|
|
export function TimelineDragGhost({
|
|
element,
|
|
position,
|
|
pps,
|
|
selectedElementId,
|
|
hasCustomContent,
|
|
theme,
|
|
children,
|
|
}: TimelineDragGhostProps) {
|
|
return (
|
|
<div
|
|
className="absolute pointer-events-none"
|
|
style={{
|
|
top: position.top,
|
|
left: position.left,
|
|
width: Math.max(element.duration * pps, 4),
|
|
height: TRACK_H - CLIP_Y * 2,
|
|
zIndex: 40,
|
|
}}
|
|
>
|
|
<TimelineClip
|
|
el={{ ...element, start: 0 }}
|
|
pps={pps}
|
|
clipY={0}
|
|
isSelected={selectedElementId === (element.key ?? element.id)}
|
|
isHovered={false}
|
|
isDragging={true}
|
|
hasCustomContent={hasCustomContent}
|
|
capabilities={getTimelineEditCapabilities(element)}
|
|
theme={theme}
|
|
isComposition={!!element.compositionSrc}
|
|
onHoverStart={() => {}}
|
|
onHoverEnd={() => {}}
|
|
onResizeStart={() => {}}
|
|
onClick={() => {}}
|
|
onDoubleClick={() => {}}
|
|
>
|
|
{children}
|
|
</TimelineClip>
|
|
</div>
|
|
);
|
|
}
|