@linker-design-plus/timeline-track 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +328 -372
- package/dist/components/interaction/globalPointerDragSession.d.ts +8 -0
- package/dist/components/panel/ClipConfigPanel.d.ts +48 -0
- package/dist/components/panel/TrackInfoPanel.d.ts +33 -0
- package/dist/components/scrollbar/KonvaScrollbarView.d.ts +58 -0
- package/dist/components/timeline/ManagedPlayhead.d.ts +29 -0
- package/dist/components/{Playhead.d.ts → timeline/Playhead.d.ts} +1 -1
- package/dist/components/{Timeline.d.ts → timeline/Timeline.d.ts} +27 -6
- package/dist/components/timeline/TimelineHeaderView.d.ts +45 -0
- package/dist/components/track/Clip.d.ts +16 -0
- package/dist/components/track/Track.d.ts +121 -0
- package/dist/components/track/trackClipLayout.d.ts +23 -0
- package/dist/components/track/trackInteractionState.d.ts +79 -0
- package/dist/core/commands/timelineCommands.d.ts +121 -0
- package/dist/core/controllers/demoPreviewRebuildState.d.ts +54 -0
- package/dist/core/controllers/domPreviewBackend.d.ts +5 -0
- package/dist/core/controllers/index.d.ts +13 -0
- package/dist/core/controllers/previewBackend.d.ts +53 -0
- package/dist/core/controllers/previewBackendSupport.d.ts +2 -0
- package/dist/core/controllers/previewClockController.d.ts +13 -0
- package/dist/core/controllers/previewTransformMath.d.ts +27 -0
- package/dist/core/controllers/previewTransformOverlay.d.ts +45 -0
- package/dist/core/controllers/timelineClipConfigController.d.ts +15 -0
- package/dist/core/controllers/timelineClipEventController.d.ts +32 -0
- package/dist/core/controllers/timelineClipWorkflowController.d.ts +30 -0
- package/dist/core/controllers/timelineDurationController.d.ts +14 -0
- package/dist/core/controllers/timelineEventDispatcher.d.ts +12 -0
- package/dist/core/controllers/timelinePlaybackResolver.d.ts +17 -0
- package/dist/core/controllers/timelinePreviewSession.d.ts +94 -0
- package/dist/core/controllers/timelineSelectionController.d.ts +17 -0
- package/dist/core/controllers/timelineTrackInfoPanelController.d.ts +19 -0
- package/dist/core/controllers/timelineTrackMutationController.d.ts +46 -0
- package/dist/core/facade/timelineManager.d.ts +382 -0
- package/dist/core/{history.d.ts → history/history.d.ts} +16 -14
- package/dist/core/history/index.d.ts +3 -0
- package/dist/core/history/timelineHistoryExecutor.d.ts +23 -0
- package/dist/core/history/timelineHistoryRecorder.d.ts +15 -0
- package/dist/core/layout/index.d.ts +1 -0
- package/dist/core/layout/timelineManagerDom.d.ts +22 -0
- package/dist/core/layout/timelineTrackLayout.d.ts +10 -0
- package/dist/core/models/clipState.d.ts +3 -0
- package/dist/core/{constants.d.ts → models/constants.d.ts} +4 -0
- package/dist/core/models/index.d.ts +3 -0
- package/dist/core/models/types.d.ts +392 -0
- package/dist/core/presentation/index.d.ts +1 -0
- package/dist/core/presentation/timelinePresentationAdapter.d.ts +22 -0
- package/dist/core/stores/index.d.ts +4 -0
- package/dist/core/stores/playbackStore.d.ts +17 -0
- package/dist/core/stores/selectionStore.d.ts +7 -0
- package/dist/core/stores/timelineStore.d.ts +44 -0
- package/dist/core/stores/viewportStore.d.ts +33 -0
- package/dist/core/testing/konva-test-stub.d.ts +81 -0
- package/dist/core/tracks/index.d.ts +3 -0
- package/dist/core/tracks/timelineTrackBridge.d.ts +37 -0
- package/dist/core/tracks/timelineTrackCollection.d.ts +50 -0
- package/dist/core/tracks/trackManager.d.ts +19 -0
- package/dist/core/utils/mountManager.d.ts +10 -0
- package/dist/index.cjs.js +29 -3
- package/dist/index.d.ts +12 -7
- package/dist/index.es.js +8914 -4353
- package/dist/utils/logging/Logger.d.ts +30 -0
- package/dist/utils/logging/index.d.ts +1 -0
- package/dist/utils/{KonvaUtils.d.ts → rendering/KonvaUtils.d.ts} +3 -43
- package/dist/utils/rendering/clipCoverRenderer.d.ts +23 -0
- package/dist/utils/rendering/clipVisualRenderer.d.ts +5 -0
- package/dist/utils/rendering/index.d.ts +4 -0
- package/dist/utils/rendering/timelineGridDrawing.d.ts +8 -0
- package/dist/utils/time/index.d.ts +1 -0
- package/dist/utils/{timeUtils.d.ts → time/timeUtils.d.ts} +4 -0
- package/package.json +5 -3
- package/dist/components/Clip.d.ts +0 -44
- package/dist/components/VideoTrack.d.ts +0 -126
- package/dist/core/timelineManager.d.ts +0 -212
- package/dist/core/types.d.ts +0 -183
- package/dist/utils/Logger.d.ts +0 -49
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface GlobalPointerDragSessionHandlers {
|
|
2
|
+
onPointerMove: (evt: MouseEvent) => void;
|
|
3
|
+
onPointerEnd: () => void;
|
|
4
|
+
onVisibilityChange: () => void;
|
|
5
|
+
onWindowBlur?: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function bindGlobalPointerDragSession(handlers: GlobalPointerDragSessionHandlers): boolean;
|
|
8
|
+
export declare function unbindGlobalPointerDragSession(handlers: GlobalPointerDragSessionHandlers): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Clip } from '../../core/models';
|
|
2
|
+
export interface ClipConfigPanelTheme {
|
|
3
|
+
backgroundColor: string;
|
|
4
|
+
borderColor: string;
|
|
5
|
+
textColor: string;
|
|
6
|
+
labelColor: string;
|
|
7
|
+
inputBackground: string;
|
|
8
|
+
inputBorder: string;
|
|
9
|
+
inputFocusBorder: string;
|
|
10
|
+
buttonBackground: string;
|
|
11
|
+
buttonBorder: string;
|
|
12
|
+
buttonActiveBackground: string;
|
|
13
|
+
buttonActiveBorder: string;
|
|
14
|
+
buttonActiveText: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const defaultDarkTheme: ClipConfigPanelTheme;
|
|
17
|
+
export interface ClipConfigPanelConfig {
|
|
18
|
+
container: HTMLElement;
|
|
19
|
+
theme?: ClipConfigPanelTheme;
|
|
20
|
+
onClipUpdate?: (clipId: string, updates: Partial<Clip>) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare class ClipConfigPanel {
|
|
23
|
+
private container;
|
|
24
|
+
private rootElement;
|
|
25
|
+
private theme;
|
|
26
|
+
private onClipUpdate?;
|
|
27
|
+
private currentClip;
|
|
28
|
+
private xSlider;
|
|
29
|
+
private xInput;
|
|
30
|
+
private ySlider;
|
|
31
|
+
private yInput;
|
|
32
|
+
private scaleSlider;
|
|
33
|
+
private scaleInput;
|
|
34
|
+
constructor(config: ClipConfigPanelConfig);
|
|
35
|
+
setClip(clip: Clip | null): void;
|
|
36
|
+
destroy(): void;
|
|
37
|
+
private render;
|
|
38
|
+
private renderEmptyState;
|
|
39
|
+
private renderConfigPanel;
|
|
40
|
+
private renderPositionControl;
|
|
41
|
+
private renderPresetGrid;
|
|
42
|
+
private renderScaleControl;
|
|
43
|
+
private clampValue;
|
|
44
|
+
private updateUIControls;
|
|
45
|
+
private handleTransformChange;
|
|
46
|
+
private handleTransformChanges;
|
|
47
|
+
private applyTheme;
|
|
48
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Track } from '../../core/models';
|
|
2
|
+
export interface TrackInfoPanelConfig {
|
|
3
|
+
container: HTMLElement;
|
|
4
|
+
theme?: {
|
|
5
|
+
background?: string;
|
|
6
|
+
border?: string;
|
|
7
|
+
text?: string;
|
|
8
|
+
buttonBackground?: string;
|
|
9
|
+
buttonHover?: string;
|
|
10
|
+
buttonDanger?: string;
|
|
11
|
+
};
|
|
12
|
+
width?: number;
|
|
13
|
+
timeScaleHeight?: number;
|
|
14
|
+
includeTimeScaleSpacer?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare class TrackInfoPanel {
|
|
17
|
+
private container;
|
|
18
|
+
private tracks;
|
|
19
|
+
private theme;
|
|
20
|
+
private width;
|
|
21
|
+
private timeScaleHeight;
|
|
22
|
+
private includeTimeScaleSpacer;
|
|
23
|
+
private trackList;
|
|
24
|
+
private onMuteTrack?;
|
|
25
|
+
constructor(config: TrackInfoPanelConfig, _onRenameTrack?: (trackId: string, newName: string) => void, _onDeleteTrack?: (trackId: string) => void, onMuteTrack?: (trackId: string, isMuted: boolean) => void);
|
|
26
|
+
private init;
|
|
27
|
+
setTracks(tracks: Track[]): void;
|
|
28
|
+
getTracks(): Track[];
|
|
29
|
+
render(): void;
|
|
30
|
+
setScrollTop(scrollTop: number): void;
|
|
31
|
+
private createTrackItem;
|
|
32
|
+
destroy(): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Theme } from '../../core/models/types';
|
|
2
|
+
type ScrollbarOrientation = 'horizontal' | 'vertical';
|
|
3
|
+
export interface KonvaScrollbarViewConfig {
|
|
4
|
+
container: HTMLElement;
|
|
5
|
+
orientation: ScrollbarOrientation;
|
|
6
|
+
theme: Theme;
|
|
7
|
+
onScrollChange: (nextOffset: number) => void;
|
|
8
|
+
leadingInset?: number;
|
|
9
|
+
trailingInset?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class KonvaScrollbarView {
|
|
12
|
+
private readonly container;
|
|
13
|
+
private readonly orientation;
|
|
14
|
+
private readonly theme;
|
|
15
|
+
private readonly onScrollChange;
|
|
16
|
+
private readonly leadingInset;
|
|
17
|
+
private readonly trailingInset;
|
|
18
|
+
private readonly stage;
|
|
19
|
+
private readonly layer;
|
|
20
|
+
private readonly hitAreaRect;
|
|
21
|
+
private readonly thumbRect;
|
|
22
|
+
private viewportSize;
|
|
23
|
+
private contentSize;
|
|
24
|
+
private scrollOffset;
|
|
25
|
+
private isDragging;
|
|
26
|
+
private dragStartClient;
|
|
27
|
+
private dragStartOffset;
|
|
28
|
+
private hasBoundGlobalPointerListeners;
|
|
29
|
+
private readonly handleGlobalPointerMove;
|
|
30
|
+
private readonly handleGlobalPointerEnd;
|
|
31
|
+
private readonly handleVisibilityChange;
|
|
32
|
+
constructor(config: KonvaScrollbarViewConfig);
|
|
33
|
+
setViewportMetrics(viewportSize: number, contentSize: number): void;
|
|
34
|
+
setScrollLeft(scrollLeft: number): void;
|
|
35
|
+
setScrollTop(scrollTop: number): void;
|
|
36
|
+
resize(): void;
|
|
37
|
+
destroy(): void;
|
|
38
|
+
private readonly handleStageMouseDown;
|
|
39
|
+
private readonly handleStageMouseUp;
|
|
40
|
+
private readonly handleStageMouseEnter;
|
|
41
|
+
private readonly handleStageMouseMove;
|
|
42
|
+
private readonly handleStageMouseLeave;
|
|
43
|
+
private bindGlobalPointerListeners;
|
|
44
|
+
private unbindGlobalPointerListeners;
|
|
45
|
+
private handleDragMove;
|
|
46
|
+
private jumpToPointer;
|
|
47
|
+
private emitScrollChange;
|
|
48
|
+
private render;
|
|
49
|
+
private getTrackSize;
|
|
50
|
+
private getAvailableTrackSize;
|
|
51
|
+
private getMaxScrollOffset;
|
|
52
|
+
private clampScrollOffset;
|
|
53
|
+
private shouldHideScrollbar;
|
|
54
|
+
private updateCursor;
|
|
55
|
+
private getThumbSize;
|
|
56
|
+
private getThumbPosition;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TimeMs, Theme } from '../../core/models/types';
|
|
2
|
+
export declare class ManagedPlayhead {
|
|
3
|
+
private readonly container;
|
|
4
|
+
private readonly lineElement;
|
|
5
|
+
private readonly handleElement;
|
|
6
|
+
private readonly theme;
|
|
7
|
+
private readonly onTimeChange;
|
|
8
|
+
private currentTime;
|
|
9
|
+
private zoom;
|
|
10
|
+
private scrollLeft;
|
|
11
|
+
private height;
|
|
12
|
+
private isDragging;
|
|
13
|
+
private hasBoundGlobalPointerListeners;
|
|
14
|
+
private handleGlobalPointerMove;
|
|
15
|
+
private handleGlobalPointerEnd;
|
|
16
|
+
private handleVisibilityChange;
|
|
17
|
+
constructor(container: HTMLElement, initialTime: TimeMs, zoom: number, height: number, theme: Theme, onTimeChange: (time: TimeMs) => void);
|
|
18
|
+
setCurrentTime(time: TimeMs): void;
|
|
19
|
+
setTime(time: TimeMs): void;
|
|
20
|
+
setZoom(zoom: number): void;
|
|
21
|
+
setScrollLeft(scrollLeft: number): void;
|
|
22
|
+
setHeight(height: number): void;
|
|
23
|
+
destroy(): void;
|
|
24
|
+
private handleMouseDown;
|
|
25
|
+
private bindGlobalPointerListeners;
|
|
26
|
+
private unbindGlobalPointerListeners;
|
|
27
|
+
private updateTimeFromClientX;
|
|
28
|
+
private render;
|
|
29
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Konva from 'konva';
|
|
2
|
-
import { TimelineConfig, TimeMs } from '
|
|
2
|
+
import { TimelineConfig, TimeMs } from '../../core/models';
|
|
3
3
|
export declare class Timeline {
|
|
4
4
|
private stage;
|
|
5
5
|
private gridLayer;
|
|
@@ -13,14 +13,26 @@ export declare class Timeline {
|
|
|
13
13
|
private onZoomChange;
|
|
14
14
|
private onScrollChange;
|
|
15
15
|
private animationFrameId;
|
|
16
|
-
private
|
|
17
|
-
private scrollbarY;
|
|
16
|
+
private hasBoundGlobalPointerListenersForDrag;
|
|
18
17
|
private isScrollbarDragging;
|
|
19
18
|
private scrollbarDragStartX;
|
|
20
19
|
private scrollbarDragStartScrollLeft;
|
|
20
|
+
private isPointerInsideTimeline;
|
|
21
|
+
private lastPointerXInTimeline;
|
|
22
|
+
private readonly scrollbarHeight;
|
|
23
|
+
private readonly scrollbarMargin;
|
|
24
|
+
private handleGlobalPointerMove;
|
|
25
|
+
private handleGlobalPointerEnd;
|
|
26
|
+
private handleVisibilityChange;
|
|
21
27
|
private leftPadding;
|
|
22
28
|
constructor(stage: Konva.Stage, gridLayer: Konva.Layer, config: Partial<TimelineConfig>, onTimeChange: (time: TimeMs) => void, onZoomChange: (zoom: number) => void, onScrollChange: (scrollLeft: number) => void);
|
|
23
29
|
private initEventListeners;
|
|
30
|
+
private updatePointerPosition;
|
|
31
|
+
private bindGlobalPointerListenersForDrag;
|
|
32
|
+
private unbindGlobalPointerListenersForDrag;
|
|
33
|
+
private isPointerSessionActive;
|
|
34
|
+
private finalizePointerInteraction;
|
|
35
|
+
private handlePointerMove;
|
|
24
36
|
private handleZoom;
|
|
25
37
|
private animateZoom;
|
|
26
38
|
private animateHorizontalScroll;
|
|
@@ -34,14 +46,15 @@ export declare class Timeline {
|
|
|
34
46
|
setPlayState(playState: 'playing' | 'paused'): void;
|
|
35
47
|
update(): void;
|
|
36
48
|
private render;
|
|
37
|
-
/**
|
|
38
|
-
* 绘制滚动条
|
|
39
|
-
*/
|
|
40
49
|
private renderScrollbar;
|
|
41
50
|
private renderTimeTicks;
|
|
42
51
|
getConfig(): TimelineConfig;
|
|
43
52
|
getScrollLeft(): number;
|
|
44
53
|
setScrollLeft(scrollLeft: number): void;
|
|
54
|
+
private getTotalDurationPixels;
|
|
55
|
+
private getScrollbarThumbWidth;
|
|
56
|
+
private getScrollbarThumbX;
|
|
57
|
+
private jumpScrollbarToPointer;
|
|
45
58
|
/**
|
|
46
59
|
* 滚动到指定时间
|
|
47
60
|
* @param time 目标时间(毫秒)
|
|
@@ -63,6 +76,14 @@ export declare class Timeline {
|
|
|
63
76
|
* 获取网格图层
|
|
64
77
|
*/
|
|
65
78
|
getGridLayer(): Konva.Layer;
|
|
79
|
+
/**
|
|
80
|
+
* 鼠标当前是否位于时间轴区域内
|
|
81
|
+
*/
|
|
82
|
+
hasPointerInTimeline(): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 获取时间轴内最近一次鼠标 X 坐标(相对 stage)
|
|
85
|
+
*/
|
|
86
|
+
getPointerXInTimeline(): number | null;
|
|
66
87
|
/**
|
|
67
88
|
* 调整大小
|
|
68
89
|
*/
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import Konva from 'konva';
|
|
2
|
+
import type { TimeMs, TimelineConfig } from '../../core/models/types';
|
|
3
|
+
export declare class TimelineHeaderView {
|
|
4
|
+
private readonly stage;
|
|
5
|
+
private readonly layer;
|
|
6
|
+
private readonly onTimeChange;
|
|
7
|
+
private readonly onScrollChange;
|
|
8
|
+
private config;
|
|
9
|
+
private theme;
|
|
10
|
+
private scrollLeft;
|
|
11
|
+
private timeScaleHeight;
|
|
12
|
+
private isDragging;
|
|
13
|
+
private dragStartX;
|
|
14
|
+
private isPointerInsideTimeline;
|
|
15
|
+
private lastPointerXInTimeline;
|
|
16
|
+
private hasBoundGlobalPointerListenersForDrag;
|
|
17
|
+
private handleGlobalPointerMove;
|
|
18
|
+
private handleGlobalPointerEnd;
|
|
19
|
+
private handleVisibilityChange;
|
|
20
|
+
constructor(stage: Konva.Stage, layer: Konva.Layer, config: Partial<TimelineConfig>, onTimeChange: (time: TimeMs) => void, onScrollChange: (scrollLeft: number) => void);
|
|
21
|
+
setCurrentTime(_time: TimeMs): void;
|
|
22
|
+
setZoom(zoom: number): void;
|
|
23
|
+
setDuration(duration: TimeMs): void;
|
|
24
|
+
setScrollLeft(scrollLeft: number): void;
|
|
25
|
+
getScrollLeft(): number;
|
|
26
|
+
scrollToTime(time: TimeMs): void;
|
|
27
|
+
scrollToClip(clip: {
|
|
28
|
+
startTime: TimeMs;
|
|
29
|
+
duration: TimeMs;
|
|
30
|
+
}): void;
|
|
31
|
+
resize(width: number): void;
|
|
32
|
+
hasPointerInTimeline(): boolean;
|
|
33
|
+
getPointerXInTimeline(): number | null;
|
|
34
|
+
destroy(): void;
|
|
35
|
+
private initEventListeners;
|
|
36
|
+
private updatePointerPosition;
|
|
37
|
+
private bindGlobalPointerListenersForDrag;
|
|
38
|
+
private unbindGlobalPointerListenersForDrag;
|
|
39
|
+
private handlePointerMove;
|
|
40
|
+
private pixelToTime;
|
|
41
|
+
private timeToPixel;
|
|
42
|
+
private render;
|
|
43
|
+
private renderTimeTicks;
|
|
44
|
+
private clampScrollLeft;
|
|
45
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Clip as ClipType, Position } from '../../core/models';
|
|
2
|
+
export declare class Clip {
|
|
3
|
+
private clip;
|
|
4
|
+
private onUpdate;
|
|
5
|
+
private onSplit;
|
|
6
|
+
constructor(clip: ClipType, onUpdate: (clip: ClipType) => void, onSplit: (clip: ClipType, time: number) => void);
|
|
7
|
+
getClip(): ClipType;
|
|
8
|
+
applyPreviewState(clip: ClipType): void;
|
|
9
|
+
setSelected(selected: boolean): void;
|
|
10
|
+
isPointInResizeHandle(x: number, y: number, zoom: number, trackY: number, trackHeight: number, scrollLeft: number): boolean;
|
|
11
|
+
startDrag(_pos: Position): void;
|
|
12
|
+
startResize(_pos: Position): void;
|
|
13
|
+
endDrag(): void;
|
|
14
|
+
split(time: number): void;
|
|
15
|
+
private setResizeHandleState;
|
|
16
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import Konva from 'konva';
|
|
2
|
+
import { Clip as ClipType, ClipStateUpdate, TrackConfig, TimeMs, Theme, TrackType } from '../../core/models';
|
|
3
|
+
export declare class Track {
|
|
4
|
+
private static readonly DEFAULT_DRAG_ACTIVATION_THRESHOLD;
|
|
5
|
+
private static readonly DEFAULT_CLIP_SNAP_THRESHOLD;
|
|
6
|
+
private static readonly AUTO_SCROLL_EDGE_THRESHOLD;
|
|
7
|
+
private static readonly AUTO_SCROLL_MAX_SPEED;
|
|
8
|
+
private layer;
|
|
9
|
+
private trackGroup;
|
|
10
|
+
private dropPreviewGroup;
|
|
11
|
+
private config;
|
|
12
|
+
private theme;
|
|
13
|
+
private trackType;
|
|
14
|
+
private clips;
|
|
15
|
+
private clipGroups;
|
|
16
|
+
private zoom;
|
|
17
|
+
private scrollLeft;
|
|
18
|
+
private trackY;
|
|
19
|
+
private trackHeight;
|
|
20
|
+
private selectedClip;
|
|
21
|
+
private hasSelectedClip;
|
|
22
|
+
private interactionState;
|
|
23
|
+
private isVisualUpdate;
|
|
24
|
+
private onClipUpdate;
|
|
25
|
+
private onClipAdd;
|
|
26
|
+
private onClipRemove;
|
|
27
|
+
private onClipSplit;
|
|
28
|
+
private onClipSelect;
|
|
29
|
+
private onTimeJump;
|
|
30
|
+
private onClipOverlap?;
|
|
31
|
+
private hasBoundGlobalPointerListenersForDrag;
|
|
32
|
+
private hasLockedGlobalCursor;
|
|
33
|
+
private edgeAutoScrollAnimationFrameId;
|
|
34
|
+
private onHorizontalDragAutoScroll?;
|
|
35
|
+
private onClipCrossTrackPreview?;
|
|
36
|
+
private onClipCrossTrack?;
|
|
37
|
+
private onClearDropPreview?;
|
|
38
|
+
private onClearSelection?;
|
|
39
|
+
private onSnapGuideChange?;
|
|
40
|
+
private resolveSnapTargetClips?;
|
|
41
|
+
private readonly dragActivationThreshold;
|
|
42
|
+
private enableClipSnap;
|
|
43
|
+
private readonly clipSnapThreshold;
|
|
44
|
+
private handleGlobalPointerMove;
|
|
45
|
+
private handleGlobalPointerEnd;
|
|
46
|
+
private handleWindowBlur;
|
|
47
|
+
constructor(layer: Konva.Layer, config: TrackConfig, trackType: TrackType, zoom: number, trackY: number, trackHeight: number, theme: Theme, onClipUpdate: (clip: ClipType, originalClip?: ClipType, clipUpdates?: ClipStateUpdate[]) => void, onClipAdd: (clip: ClipType) => void, onClipRemove: (clipId: string) => void, onClipSplit: (clip1: ClipType, clip2: ClipType) => void, onClipSelect: (clip: ClipType) => void, onTimeJump: (time: TimeMs) => void, onHorizontalDragAutoScroll?: (nextScrollLeft: number) => number, onClipOverlap?: (clip: ClipType, currentTrackId: string) => void, onClipCrossTrackPreview?: (clip: ClipType, targetTrackY: number, currentTrackId: string) => 'self' | 'external' | 'clear', onClipCrossTrack?: (clip: ClipType, originalClip: ClipType | null, targetTrackY: number, currentTrackId: string) => boolean | void, onClearDropPreview?: () => void, onClearSelection?: () => void, onSnapGuideChange?: (guideTime: TimeMs | null) => void, dragActivationThreshold?: number, enableClipSnap?: boolean, clipSnapThreshold?: number);
|
|
48
|
+
private initClips;
|
|
49
|
+
private ensureDropPreviewGroup;
|
|
50
|
+
private showDropPreview;
|
|
51
|
+
private hideDropPreview;
|
|
52
|
+
private initEventListeners;
|
|
53
|
+
private bindGlobalPointerListenersForDrag;
|
|
54
|
+
private unbindGlobalPointerListenersForDrag;
|
|
55
|
+
private handleVisibilityChange;
|
|
56
|
+
private readonly handleEdgeAutoScrollFrame;
|
|
57
|
+
private handleTrackBackgroundClick;
|
|
58
|
+
private createClipGroup;
|
|
59
|
+
private handleClipClick;
|
|
60
|
+
private handleClipMouseDown;
|
|
61
|
+
private handleClipMouseMove;
|
|
62
|
+
private handleTrackBackgroundMouseMove;
|
|
63
|
+
private handleClipMouseUp;
|
|
64
|
+
private finishPointerInteraction;
|
|
65
|
+
private applyInteractionTransition;
|
|
66
|
+
private resolveInteractionState;
|
|
67
|
+
private syncLegacyInteractionMirror;
|
|
68
|
+
private handleClipMoveEnd;
|
|
69
|
+
private updateAllClips;
|
|
70
|
+
private buildAndSendUpdates;
|
|
71
|
+
private updateHoverCursor;
|
|
72
|
+
private isDragSessionActive;
|
|
73
|
+
private handleDragMove;
|
|
74
|
+
private handleClipMouseLeave;
|
|
75
|
+
private lockPointerCursor;
|
|
76
|
+
private releasePointerCursor;
|
|
77
|
+
private updateClipGroup;
|
|
78
|
+
private handleClipUpdate;
|
|
79
|
+
private handleClipSplit;
|
|
80
|
+
addClip(clip: ClipType): void;
|
|
81
|
+
removeClip(clipId: string): void;
|
|
82
|
+
updateClip(clipId: string, updates: Partial<ClipType>): void;
|
|
83
|
+
setZoom(zoom: number): void;
|
|
84
|
+
setCurrentTime(_time: TimeMs): void;
|
|
85
|
+
setScrollLeft(scrollLeft: number): void;
|
|
86
|
+
private updateClipVisibility;
|
|
87
|
+
setTrackY(trackY: number): void;
|
|
88
|
+
getTrackType(): TrackType;
|
|
89
|
+
render(shouldBatchDraw?: boolean): void;
|
|
90
|
+
private getTrackBackgroundFill;
|
|
91
|
+
getClips(): ClipType[];
|
|
92
|
+
getSelectedClip(): ClipType | null;
|
|
93
|
+
clearSelection(): void;
|
|
94
|
+
updateSelectionVisual(selectedClipId: string | null): void;
|
|
95
|
+
selectClip(clipId: string): void;
|
|
96
|
+
private applySelectionVisual;
|
|
97
|
+
splitSelectedClip(time: TimeMs): void;
|
|
98
|
+
removeClipGaps(): void;
|
|
99
|
+
getTrackGroup(): Konva.Group;
|
|
100
|
+
getId(): string;
|
|
101
|
+
setTrackHeight(height: number): void;
|
|
102
|
+
showClipDropPreview(clip: ClipType): void;
|
|
103
|
+
clearClipDropPreview(): void;
|
|
104
|
+
getRole(): 'primary' | 'normal';
|
|
105
|
+
setClipSnapEnabled(enabled: boolean): void;
|
|
106
|
+
setSnapTargetResolver(resolver: (() => ClipType[]) | undefined): void;
|
|
107
|
+
private updateDraggedClipFromPointer;
|
|
108
|
+
private buildPreviewClip;
|
|
109
|
+
private constrainResizePreviewToTrackBounds;
|
|
110
|
+
private getResizeLeftBoundaryStart;
|
|
111
|
+
private getResizeRightBoundaryEnd;
|
|
112
|
+
private buildResizeLeftPreviewClip;
|
|
113
|
+
private buildResizeRightPreviewClip;
|
|
114
|
+
private applyClipSnap;
|
|
115
|
+
private applyPreviewClipState;
|
|
116
|
+
private updateSnapGuideLine;
|
|
117
|
+
private updateEdgeAutoScrollState;
|
|
118
|
+
private calculateHorizontalAutoScrollVelocity;
|
|
119
|
+
private startEdgeAutoScroll;
|
|
120
|
+
private stopEdgeAutoScroll;
|
|
121
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Clip, TimeMs } from '../../core/models';
|
|
2
|
+
export type TrackPointerCursor = 'default' | 'pointer' | 'ew-resize';
|
|
3
|
+
export declare const CLIP_RESIZE_HANDLE_SIZE = 8;
|
|
4
|
+
interface TrackClipMetricsInput {
|
|
5
|
+
duration: TimeMs;
|
|
6
|
+
startTime: TimeMs;
|
|
7
|
+
zoom: number;
|
|
8
|
+
scrollLeft: number;
|
|
9
|
+
}
|
|
10
|
+
interface ResolveTrackPointerCursorInput {
|
|
11
|
+
clips: Clip[];
|
|
12
|
+
zoom: number;
|
|
13
|
+
scrollLeft: number;
|
|
14
|
+
trackY: number;
|
|
15
|
+
trackHeight: number;
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function getTrackClipX(startTime: TimeMs, zoom: number, scrollLeft: number): number;
|
|
20
|
+
export declare function getTrackClipRenderWidth(duration: TimeMs, zoom: number): number;
|
|
21
|
+
export declare function isTrackClipVisible(input: TrackClipMetricsInput, viewportWidth: number): boolean;
|
|
22
|
+
export declare function resolveTrackPointerCursor(input: ResolveTrackPointerCursorInput): TrackPointerCursor;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Clip as ClipType } from '../../core/models';
|
|
2
|
+
export type TrackPointerOperation = 'move' | 'resize-left' | 'resize-right';
|
|
3
|
+
export interface TrackInteractionContext {
|
|
4
|
+
clipId: string;
|
|
5
|
+
originalClipsState: ClipType[];
|
|
6
|
+
nonDraggedClips: ClipType[];
|
|
7
|
+
snapCandidateClips: ClipType[];
|
|
8
|
+
pointerStartClientX: number;
|
|
9
|
+
pointerStartClientY: number;
|
|
10
|
+
pointerStartX: number;
|
|
11
|
+
pointerStartY: number;
|
|
12
|
+
dragStartScrollLeft: number;
|
|
13
|
+
lastPointerClientX: number;
|
|
14
|
+
lastPointerClientY: number;
|
|
15
|
+
dragTargetTrackY: number;
|
|
16
|
+
crossTrackDragOffsetY: number;
|
|
17
|
+
}
|
|
18
|
+
export interface IdleTrackInteractionState {
|
|
19
|
+
kind: 'idle';
|
|
20
|
+
}
|
|
21
|
+
export interface PressedTrackInteractionState {
|
|
22
|
+
kind: 'pressed';
|
|
23
|
+
operation: TrackPointerOperation;
|
|
24
|
+
context: TrackInteractionContext;
|
|
25
|
+
}
|
|
26
|
+
export interface DraggingMoveTrackInteractionState {
|
|
27
|
+
kind: 'draggingMove';
|
|
28
|
+
context: TrackInteractionContext;
|
|
29
|
+
}
|
|
30
|
+
export interface DraggingResizeLeftTrackInteractionState {
|
|
31
|
+
kind: 'draggingResizeLeft';
|
|
32
|
+
context: TrackInteractionContext;
|
|
33
|
+
}
|
|
34
|
+
export interface DraggingResizeRightTrackInteractionState {
|
|
35
|
+
kind: 'draggingResizeRight';
|
|
36
|
+
context: TrackInteractionContext;
|
|
37
|
+
}
|
|
38
|
+
export type TrackInteractionState = IdleTrackInteractionState | PressedTrackInteractionState | DraggingMoveTrackInteractionState | DraggingResizeLeftTrackInteractionState | DraggingResizeRightTrackInteractionState;
|
|
39
|
+
export type TrackInteractionEvent = {
|
|
40
|
+
type: 'POINTER_DOWN';
|
|
41
|
+
operation: TrackPointerOperation;
|
|
42
|
+
clipId: string;
|
|
43
|
+
originalClipsState: ClipType[];
|
|
44
|
+
nonDraggedClips: ClipType[];
|
|
45
|
+
snapCandidateClips: ClipType[];
|
|
46
|
+
clientX: number;
|
|
47
|
+
clientY: number;
|
|
48
|
+
localX: number;
|
|
49
|
+
localY: number;
|
|
50
|
+
scrollLeft: number;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'POINTER_MOVE';
|
|
53
|
+
clientX: number;
|
|
54
|
+
clientY: number;
|
|
55
|
+
localY: number;
|
|
56
|
+
activationThreshold: number;
|
|
57
|
+
} | {
|
|
58
|
+
type: 'SCROLL_LEFT_CHANGED';
|
|
59
|
+
} | {
|
|
60
|
+
type: 'POINTER_UP' | 'VISIBILITY_HIDDEN' | 'WINDOW_BLUR' | 'CANCEL';
|
|
61
|
+
};
|
|
62
|
+
export interface TrackInteractionTransitionEffects {
|
|
63
|
+
bindGlobalListeners?: boolean;
|
|
64
|
+
unbindGlobalListeners?: boolean;
|
|
65
|
+
updatePreview?: boolean;
|
|
66
|
+
commit?: boolean;
|
|
67
|
+
cleanup?: boolean;
|
|
68
|
+
}
|
|
69
|
+
export interface TrackInteractionTransitionResult {
|
|
70
|
+
state: TrackInteractionState;
|
|
71
|
+
effects: TrackInteractionTransitionEffects;
|
|
72
|
+
}
|
|
73
|
+
export declare function createIdleTrackInteractionState(): TrackInteractionState;
|
|
74
|
+
export declare function isTrackInteractionActive(state: TrackInteractionState | null | undefined): boolean;
|
|
75
|
+
export declare function isTrackInteractionDragging(state: TrackInteractionState | null | undefined): boolean;
|
|
76
|
+
export declare function getTrackInteractionContext(state: TrackInteractionState | null | undefined): TrackInteractionContext | null;
|
|
77
|
+
export declare function getTrackInteractionOperation(state: TrackInteractionState | null | undefined): TrackPointerOperation | null;
|
|
78
|
+
export declare function getTrackInteractionCursor(state: TrackInteractionState | null | undefined): 'ew-resize' | 'grabbing' | null;
|
|
79
|
+
export declare function transitionTrackInteraction(state: TrackInteractionState, event: TrackInteractionEvent): TrackInteractionTransitionResult;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { TimelineStore } from '../stores/timelineStore';
|
|
2
|
+
import type { Clip, TimeMs, TrackInsertionPlacement, TrackType } from '../models/types';
|
|
3
|
+
export interface ValueChangeCommandResult<T> {
|
|
4
|
+
previousValue: T;
|
|
5
|
+
nextValue: T;
|
|
6
|
+
changed: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface SelectionCommandResult {
|
|
9
|
+
previousClipId: string | null;
|
|
10
|
+
nextClipId: string | null;
|
|
11
|
+
changed: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface TimelineTrackView {
|
|
14
|
+
getId?(): string;
|
|
15
|
+
id?: string;
|
|
16
|
+
type?: TrackType;
|
|
17
|
+
getClips(): Clip[];
|
|
18
|
+
getTrackType?(): TrackType;
|
|
19
|
+
addClip?(clip: Clip): void;
|
|
20
|
+
removeClip?(clipId: string): void;
|
|
21
|
+
splitSelectedClip?(time: TimeMs): void;
|
|
22
|
+
}
|
|
23
|
+
export interface TimelineTrackLayout {
|
|
24
|
+
id: string;
|
|
25
|
+
type: TrackType;
|
|
26
|
+
role?: 'primary' | 'normal';
|
|
27
|
+
}
|
|
28
|
+
export interface ClipLookupResult {
|
|
29
|
+
clip: Clip;
|
|
30
|
+
track: TimelineTrackView;
|
|
31
|
+
trackId: string | null;
|
|
32
|
+
}
|
|
33
|
+
export interface RemoveClipCommandResult {
|
|
34
|
+
exists: boolean;
|
|
35
|
+
clip: Clip | null;
|
|
36
|
+
trackId: string | null;
|
|
37
|
+
shouldClearSelection: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type MoveClipToTrackCommandResult = {
|
|
40
|
+
status: 'ready';
|
|
41
|
+
clip: Clip;
|
|
42
|
+
sourceTrack: TimelineTrackView;
|
|
43
|
+
sourceTrackId: string;
|
|
44
|
+
targetTrack: TimelineTrackView;
|
|
45
|
+
targetTrackId: string;
|
|
46
|
+
} | {
|
|
47
|
+
status: 'noop';
|
|
48
|
+
clipId: string;
|
|
49
|
+
sourceTrackId: string;
|
|
50
|
+
targetTrackId: string;
|
|
51
|
+
} | {
|
|
52
|
+
status: 'missing_source_track' | 'missing_target_track' | 'track_type_mismatch';
|
|
53
|
+
clipId: string;
|
|
54
|
+
targetTrackId: string;
|
|
55
|
+
sourceTrackId?: string;
|
|
56
|
+
};
|
|
57
|
+
export type TrackPlacementCommandResult = {
|
|
58
|
+
status: 'use_existing_track';
|
|
59
|
+
trackId: string;
|
|
60
|
+
} | {
|
|
61
|
+
status: 'create_track';
|
|
62
|
+
trackType: TrackType;
|
|
63
|
+
suggestedTrackName: string;
|
|
64
|
+
};
|
|
65
|
+
export type CrossTrackMoveCommandResult = {
|
|
66
|
+
status: 'missing_target_track_by_position';
|
|
67
|
+
} | {
|
|
68
|
+
status: 'same_track';
|
|
69
|
+
targetTrackId: string;
|
|
70
|
+
} | {
|
|
71
|
+
status: 'missing_target_track_view';
|
|
72
|
+
targetTrackId: string;
|
|
73
|
+
} | {
|
|
74
|
+
status: 'track_type_mismatch';
|
|
75
|
+
targetTrackId: string;
|
|
76
|
+
targetTrackType: TrackType | null;
|
|
77
|
+
} | {
|
|
78
|
+
status: 'move_to_track';
|
|
79
|
+
targetTrackId: string;
|
|
80
|
+
} | {
|
|
81
|
+
status: 'create_track';
|
|
82
|
+
trackType: TrackType;
|
|
83
|
+
insertionPlacement: TrackInsertionPlacement;
|
|
84
|
+
referenceTrackId?: string;
|
|
85
|
+
};
|
|
86
|
+
export type CrossTrackPreviewCommandResult = {
|
|
87
|
+
status: 'existing_track_placeholder';
|
|
88
|
+
targetTrackId: string;
|
|
89
|
+
} | {
|
|
90
|
+
status: 'new_track_insertion';
|
|
91
|
+
trackType: TrackType;
|
|
92
|
+
insertionPlacement: TrackInsertionPlacement;
|
|
93
|
+
referenceTrackId?: string;
|
|
94
|
+
} | {
|
|
95
|
+
status: 'clear';
|
|
96
|
+
};
|
|
97
|
+
export declare class TimelineCommands {
|
|
98
|
+
private readonly timelineStore;
|
|
99
|
+
constructor(timelineStore: TimelineStore);
|
|
100
|
+
selectClip(clipId: string): SelectionCommandResult;
|
|
101
|
+
clearSelection(): SelectionCommandResult;
|
|
102
|
+
findClipById(tracks: TimelineTrackView[], clipId: string): ClipLookupResult | null;
|
|
103
|
+
findClipAtTime(tracks: TimelineTrackView[], time: TimeMs): ClipLookupResult | null;
|
|
104
|
+
prepareRemoveClip(clipId: string, tracks: TimelineTrackView[]): RemoveClipCommandResult;
|
|
105
|
+
prepareMoveClipToTrack(clipId: string, targetTrackId: string, tracks: TimelineTrackView[]): MoveClipToTrackCommandResult;
|
|
106
|
+
planTrackPlacement(clip: Pick<Clip, 'type' | 'startTime' | 'duration'>, tracks: TimelineTrackView[]): TrackPlacementCommandResult;
|
|
107
|
+
planCrossTrackMove(clip: Pick<Clip, 'id' | 'type' | 'startTime' | 'duration'>, targetTrackY: number, currentTrackId: string, timeScaleHeight: number, layoutTracks: TimelineTrackLayout[], tracks: TimelineTrackView[]): CrossTrackMoveCommandResult;
|
|
108
|
+
planCrossTrackPreview(clip: Pick<Clip, 'id' | 'type' | 'startTime' | 'duration'>, targetTrackY: number, currentTrackId: string, timeScaleHeight: number, layoutTracks: TimelineTrackLayout[], tracks: TimelineTrackView[]): CrossTrackPreviewCommandResult;
|
|
109
|
+
setCurrentTime(time: TimeMs): ValueChangeCommandResult<TimeMs>;
|
|
110
|
+
setZoom(zoom: number): ValueChangeCommandResult<number>;
|
|
111
|
+
setSpeed(speed: number): ValueChangeCommandResult<number>;
|
|
112
|
+
private updateSelection;
|
|
113
|
+
private updateCurrentTime;
|
|
114
|
+
private updateZoom;
|
|
115
|
+
private updateSpeed;
|
|
116
|
+
private resolveTrackId;
|
|
117
|
+
private resolveTrackType;
|
|
118
|
+
private resolveTrackTargetByY;
|
|
119
|
+
private resolvePreferredInsertionPlacement;
|
|
120
|
+
private hasOverlapOnTrack;
|
|
121
|
+
}
|