refactor(TimelinePanel): 抽取 ClipTrack 组件
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import React from "react"
|
||||
import type { ClipData, TrimConfig } from "../../types"
|
||||
import { ClipCard } from "./ClipCard"
|
||||
|
||||
interface ClipTrackProps {
|
||||
/** 片段列表 */
|
||||
clips: ClipData[]
|
||||
/** 选中的片段ID */
|
||||
selectedClipId: string | null
|
||||
/** 缩放:每秒像素数 */
|
||||
pps: number
|
||||
/** 当前播放时间(秒) */
|
||||
currentTime: number
|
||||
/** 总时长(秒) */
|
||||
totalDuration: number
|
||||
/** 正在拖拽的片段索引 */
|
||||
dragIdx: number | null
|
||||
/** 拖拽悬停的片段索引 */
|
||||
dragOverIdx: number | null
|
||||
/** 悬停的片段ID */
|
||||
hoveredClipId: string | null
|
||||
/** 是否正在裁剪拖拽 */
|
||||
trimDragActive: boolean
|
||||
/** 是否显示裁剪手柄 */
|
||||
showTrimHandles: boolean
|
||||
/** 轨道ref */
|
||||
trackRef: React.RefObject<HTMLDivElement>
|
||||
/** 添加卡片ref */
|
||||
addCardRef: React.RefObject<HTMLDivElement>
|
||||
/** 播放头拖拽开始 */
|
||||
onPlayheadMouseDown: (e: React.MouseEvent) => void
|
||||
/** 片段选中 */
|
||||
onClipSelect: (clipId: string) => void
|
||||
/** 拖拽开始 */
|
||||
onDragStart: (idx: number, e: React.DragEvent) => void
|
||||
/** 拖拽悬停 */
|
||||
onDragOver: (idx: number, e: React.DragEvent) => void
|
||||
/** 拖拽结束 */
|
||||
onDragEnd: () => void
|
||||
/** 放置 */
|
||||
onDrop: (idx: number, e: React.DragEvent) => void
|
||||
/** 空区域拖拽悬停 */
|
||||
onEmptyDragOver: (e: React.DragEvent) => void
|
||||
/** 右键菜单 */
|
||||
onContextMenu: (clipId: string, e: React.MouseEvent) => void
|
||||
/** 片段悬停进入 */
|
||||
onClipMouseEnter: (clipId: string) => void
|
||||
/** 片段悬停离开 */
|
||||
onClipMouseLeave: () => void
|
||||
/** 裁剪手柄按下 */
|
||||
onTrimHandleMouseDown: (clipId: string, side: "start" | "end", e: React.MouseEvent) => void
|
||||
/** 删除片段 */
|
||||
onClipRemove: (clipId: string) => void
|
||||
/** 点击添加卡片 */
|
||||
onTogglePicker: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* 片段轨道组件
|
||||
* 包含播放头、片段列表、空状态和添加卡片
|
||||
*/
|
||||
export const ClipTrack: React.FC<ClipTrackProps> = ({
|
||||
clips,
|
||||
selectedClipId,
|
||||
pps,
|
||||
currentTime,
|
||||
totalDuration,
|
||||
dragIdx,
|
||||
dragOverIdx,
|
||||
hoveredClipId,
|
||||
trimDragActive,
|
||||
showTrimHandles,
|
||||
trackRef,
|
||||
addCardRef,
|
||||
onPlayheadMouseDown,
|
||||
onClipSelect,
|
||||
onDragStart,
|
||||
onDragOver,
|
||||
onDragEnd,
|
||||
onDrop,
|
||||
onEmptyDragOver,
|
||||
onContextMenu,
|
||||
onClipMouseEnter,
|
||||
onClipMouseLeave,
|
||||
onTrimHandleMouseDown,
|
||||
onClipRemove,
|
||||
onTogglePicker,
|
||||
}) => {
|
||||
return (
|
||||
<div className="ep-clip-track" ref={trackRef} onDragOver={onEmptyDragOver}>
|
||||
{/* 播放头 */}
|
||||
{totalDuration > 0 && (
|
||||
<div
|
||||
className="ep-playhead"
|
||||
style={{ left: currentTime * pps }}
|
||||
onMouseDown={onPlayheadMouseDown}
|
||||
>
|
||||
<div className="ep-playhead-handle" />
|
||||
</div>
|
||||
)}
|
||||
{clips.length === 0 ? (
|
||||
<div className="ep-track-empty">
|
||||
<div className="ep-track-empty-icon">🎬</div>
|
||||
<div className="ep-track-empty-text">点击右侧 + 添加片段</div>
|
||||
</div>
|
||||
) : (
|
||||
clips.map((clip, idx) => (
|
||||
<ClipCard
|
||||
key={clip.id}
|
||||
clip={clip}
|
||||
idx={idx}
|
||||
isSelected={selectedClipId === clip.id}
|
||||
isDragging={dragIdx === idx}
|
||||
isDragOver={dragOverIdx === idx}
|
||||
isHovered={hoveredClipId === clip.id}
|
||||
pps={pps}
|
||||
trimDragActive={trimDragActive}
|
||||
showTrimHandles={showTrimHandles}
|
||||
onDragStart={onDragStart}
|
||||
onDragOver={onDragOver}
|
||||
onDragEnd={onDragEnd}
|
||||
onDrop={onDrop}
|
||||
onSelect={onClipSelect}
|
||||
onContextMenu={onContextMenu}
|
||||
onMouseEnter={() => onClipMouseEnter(clip.id)}
|
||||
onMouseLeave={onClipMouseLeave}
|
||||
onTrimHandleMouseDown={onTrimHandleMouseDown}
|
||||
onRemove={onClipRemove}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
|
||||
{/* ── 轨道末尾 "+" 添加卡片 ── */}
|
||||
<div className="ep-track-add-card-wrapper">
|
||||
<div
|
||||
ref={addCardRef}
|
||||
className="ep-track-add-card"
|
||||
onClick={onTogglePicker}
|
||||
title="添加片段"
|
||||
>
|
||||
+
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user