@linker-design-plus/timeline-track 2.0.10 → 2.0.12

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.
Files changed (34) hide show
  1. package/README.md +22 -1
  2. package/dist/assets/AlibabaPuHuiTi-3-55-Regular.woff2 +0 -0
  3. package/dist/components/panel/ClipConfigPanel.d.ts +76 -38
  4. package/dist/components/panel/ClipConfigPanelRenderer.d.ts +104 -0
  5. package/dist/components/panel/TrackInfoPanel.d.ts +3 -3
  6. package/dist/components/panel/TrackInfoPanelRenderer.d.ts +33 -0
  7. package/dist/components/track/Track.d.ts +4 -0
  8. package/dist/core/commands/timelineCommands.d.ts +1 -0
  9. package/dist/core/controllers/index.d.ts +1 -0
  10. package/dist/core/controllers/previewBackend.d.ts +4 -1
  11. package/dist/core/controllers/previewPendingOverlayRenderer.d.ts +17 -0
  12. package/dist/core/controllers/timelineClipConfigController.d.ts +5 -1
  13. package/dist/core/controllers/timelineClipEventController.d.ts +1 -0
  14. package/dist/core/controllers/timelineKeyboardShortcutsController.d.ts +29 -0
  15. package/dist/core/controllers/timelinePreviewSession.d.ts +36 -4
  16. package/dist/core/controllers/timelineSelectionController.d.ts +7 -1
  17. package/dist/core/controllers/timelineTrackMutationController.d.ts +2 -2
  18. package/dist/core/facade/timelineManager.d.ts +38 -6
  19. package/dist/core/layout/TimelineManagerLayoutRenderer.d.ts +25 -0
  20. package/dist/core/layout/timelineManagerDom.d.ts +2 -11
  21. package/dist/core/models/constants.d.ts +1 -0
  22. package/dist/core/models/types.d.ts +90 -10
  23. package/dist/core/renderers/domRenderer.d.ts +17 -0
  24. package/dist/core/resources/sourceMediaRegistry.d.ts +24 -0
  25. package/dist/core/testing/konva-test-stub.d.ts +2 -0
  26. package/dist/core/theme/colorTokens.d.ts +147 -0
  27. package/dist/index.cjs.js +521 -74
  28. package/dist/index.es.js +7543 -4865
  29. package/dist/utils/rendering/KonvaUtils.d.ts +2 -2
  30. package/dist/utils/rendering/clipCoverRenderer.d.ts +1 -0
  31. package/dist/utils/rendering/clipVisualRenderer.d.ts +2 -2
  32. package/dist/utils/svgIcon.d.ts +1 -0
  33. package/dist/utils/time/timeUtils.d.ts +8 -1
  34. package/package.json +3 -2
package/README.md CHANGED
@@ -39,7 +39,12 @@ const timeline = new TimelineManager({
39
39
  container,
40
40
  zoom: 100,
41
41
  currentTime: 0,
42
- previewBackend: 'dom'
42
+ previewBackend: 'dom',
43
+ keyboardShortcuts: {
44
+ bindings: {
45
+ togglePlay: 'Mod+Alt+P'
46
+ }
47
+ }
43
48
  });
44
49
 
45
50
  timeline.attachPreview(preview);
@@ -88,6 +93,21 @@ timeline.on('history_change', (_event, data) => {
88
93
  - `attachPreview(containerOrConfig)` / `detachPreview()`
89
94
  - `exportTimeline()` / `loadDraft(data)`
90
95
 
96
+ 快捷键配置:
97
+
98
+ - `keyboardShortcuts: false` 可彻底关闭快捷键
99
+ - `keyboardShortcuts.bindings` 可按动作覆盖默认键位
100
+ - 时间轴挂载后默认在当前页面生效
101
+
102
+ 默认快捷键:
103
+
104
+ - 播放 / 暂停:`Space`
105
+ - 删除片段:`Delete` / `Backspace`
106
+ - 分离 / 还原音频:`Mod+Alt+A`
107
+ - 分割片段:`Mod+B`
108
+ - 撤销:`Mod+Z`
109
+ - 还原:`Mod+Shift+Z`,Windows 另支持 `Ctrl+Y`
110
+
91
111
  常用事件:
92
112
 
93
113
  - `time_change`
@@ -190,3 +210,4 @@ pnpm exec tsc -p tsconfig.json --noEmit
190
210
  - [docs/interaction-model.md](./docs/interaction-model.md): 指针交互分层和拖拽约束
191
211
  - [docs/refactor-roadmap.md](./docs/refactor-roadmap.md): 主线重构归档与后续收敛方向
192
212
  - [docs/maintenance-audit.md](./docs/maintenance-audit.md): 本轮仓库审计、验证结果和依赖建议
213
+ - [docs/review-remediation-plan.md](./docs/review-remediation-plan.md): 基于审查结论的修复计划与阶段性落地建议
@@ -1,4 +1,4 @@
1
- import type { Clip } from '../../core/models';
1
+ import { type Clip, type VoiceOption } from '../../core/models';
2
2
  export interface ClipConfigPanelTheme {
3
3
  backgroundColor: string;
4
4
  borderColor: string;
@@ -17,54 +17,92 @@ export declare const defaultDarkTheme: ClipConfigPanelTheme;
17
17
  export interface ClipConfigPanelConfig {
18
18
  container: HTMLElement;
19
19
  theme?: ClipConfigPanelTheme;
20
+ voiceCatalog?: VoiceOption[];
20
21
  onClipUpdate?: (clipId: string, updates: Partial<Clip>) => void;
22
+ onGenerateVoice?: (clip: Clip, voice: VoiceOption, followTextUpdates: boolean) => Promise<void>;
21
23
  }
24
+ export declare const CSS_CLASSES: {
25
+ readonly container: "clip-config-panel";
26
+ readonly tabBar: "clip-config-tab-bar";
27
+ readonly tabButton: "clip-config-tab-button";
28
+ readonly content: "clip-config-content";
29
+ readonly visualPanel: "clip-config-visual-panel";
30
+ readonly audioPanel: "clip-config-audio-panel";
31
+ readonly textPanel: "clip-config-text-panel";
32
+ readonly voicePanel: "clip-config-voice-panel";
33
+ readonly actionBar: "clip-config-action-bar";
34
+ readonly section: "clip-config-section";
35
+ readonly sectionTitle: "clip-config-section-title";
36
+ readonly row: "clip-config-row";
37
+ readonly label: "clip-config-label";
38
+ readonly slider: "clip-config-slider";
39
+ readonly input: "clip-config-input";
40
+ readonly textarea: "clip-config-textarea";
41
+ readonly colorInput: "clip-config-color-input";
42
+ readonly presetGrid: "clip-config-preset-grid";
43
+ readonly presetButton: "clip-config-preset-button";
44
+ readonly resetButton: "clip-config-reset-button";
45
+ readonly emptyState: "clip-config-empty-state";
46
+ readonly filterGroup: "clip-config-filter-group";
47
+ readonly filterButton: "clip-config-filter-button";
48
+ readonly voiceCardGrid: "clip-config-voice-grid";
49
+ readonly voiceCard: "clip-config-voice-card";
50
+ readonly voiceCardAvatar: "clip-config-voice-avatar";
51
+ readonly voiceCardMeta: "clip-config-voice-meta";
52
+ readonly voiceCardTitle: "clip-config-voice-title";
53
+ readonly voiceCardSubtitle: "clip-config-voice-subtitle";
54
+ readonly voiceCardCheck: "clip-config-voice-check";
55
+ readonly voiceCheckbox: "clip-config-voice-checkbox";
56
+ readonly primaryButton: "clip-config-primary-button";
57
+ readonly errorText: "clip-config-error-text";
58
+ readonly voiceLoadingOverlay: "clip-config-voice-loading-overlay";
59
+ readonly voiceLoadingCard: "clip-config-voice-loading-card";
60
+ readonly voiceLoadingIcon: "clip-config-voice-loading-icon";
61
+ readonly voiceLoadingText: "clip-config-voice-loading-text";
62
+ };
22
63
  export declare class ClipConfigPanel {
23
- private container;
24
- private rootElement;
25
- private theme;
26
- private onClipUpdate?;
64
+ private readonly container;
65
+ private readonly theme;
66
+ private readonly renderer;
67
+ private readonly onClipUpdate?;
68
+ private readonly onGenerateVoice?;
69
+ private readonly voiceCatalog;
27
70
  private currentClip;
28
71
  private activeTab;
29
- private iconCache;
30
- private tabBar;
31
- private contentArea;
32
- private visualPanel;
33
- private audioPanel;
34
- private xSlider;
35
- private xInput;
36
- private ySlider;
37
- private yInput;
38
- private scaleSlider;
39
- private scaleInput;
40
- private volumeSlider;
41
- private volumeInput;
72
+ private readonly iconCache;
73
+ private pendingPreferredTab;
74
+ private selectedVoiceId;
75
+ private activeVoiceFilterTag;
76
+ private textDraftContent;
77
+ private followTextUpdates;
78
+ private voiceLoadingBusyCount;
79
+ private isVoiceLoadingOverlayRendered;
80
+ private isVoiceLoadingOverlayExiting;
81
+ private voiceLoadingOverlayHideTimer;
82
+ private voiceErrorMessage;
42
83
  constructor(config: ClipConfigPanelConfig);
43
84
  setClip(clip: Clip | null): void;
85
+ setPreferredTab(tab: 'voice' | null): void;
86
+ setVoiceGenerationBusy(isBusy: boolean): void;
44
87
  destroy(): void;
45
- private getAvailableTabs;
46
88
  private render;
47
- private applyBaseTheme;
48
- private renderEmptyState;
49
- private renderPanel;
50
- private renderTabBar;
51
- private updateTabBarState;
52
- private renderContentArea;
53
- private updateContentVisibility;
54
- private renderVisualPanel;
55
- private renderAudioPanel;
56
- private renderActionBar;
57
- private renderPositionControl;
58
- private renderPresetGrid;
59
- private calculatePresetPosition;
60
- private renderScaleControl;
61
- private renderVolumeControl;
89
+ private getAvailableTabs;
90
+ private resetVoiceState;
91
+ private syncVoiceStateForClip;
92
+ private syncActiveTab;
93
+ private supportsVoicePanel;
94
+ private resolveDefaultVoiceFilterTag;
95
+ private getVisibleVoiceOptions;
96
+ private ensureVoiceFilters;
97
+ private handleVoiceFilterChange;
98
+ private handleVoiceSelect;
99
+ private handleVoiceFollowTextUpdatesChange;
100
+ private handleGenerateVoice;
62
101
  private handleVolumeChange;
63
- private updateVolumeControls;
64
102
  private clampValue;
65
- private updateUIControls;
66
- private updateSliderAndInput;
67
- private updateSliderVisual;
68
103
  private handleTransformChange;
69
104
  private handleTransformChanges;
105
+ private handleTextContentInput;
106
+ private handleTextContentCommit;
107
+ private handleTextStyleChange;
70
108
  }
@@ -0,0 +1,104 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { type Clip, type VoiceOption } from '../../core/models';
3
+ import { LitDomRenderer } from '../../core/renderers/domRenderer';
4
+ import type { ClipConfigPanelTheme } from './ClipConfigPanel';
5
+ export type ClipConfigPanelTabKey = 'visual' | 'audio' | 'text' | 'voice';
6
+ export interface ClipConfigPanelCallbacks {
7
+ onTabChange: (tab: ClipConfigPanelTabKey) => void;
8
+ onTransformChange: (property: 'x' | 'y' | 'scale', value: number) => void;
9
+ onPresetSelect: (x: number, y: number) => void;
10
+ onVolumeChange: (value: number) => void;
11
+ onTextContentInput: (value: string) => void;
12
+ onTextContentCommit: () => void;
13
+ onTextStyleChange: (property: 'fontSize' | 'color' | 'rotation' | 'x' | 'y', value: number | string) => void;
14
+ onVoiceFilterChange: (tag: string) => void;
15
+ onVoiceSelect: (voiceId: string) => void;
16
+ onVoiceFollowTextUpdatesChange: (value: boolean) => void;
17
+ onGenerateVoice: () => Promise<void>;
18
+ }
19
+ export interface ClipConfigPanelViewModel {
20
+ clip: Clip | null;
21
+ activeTab: ClipConfigPanelTabKey;
22
+ theme: ClipConfigPanelTheme;
23
+ emptyStateIconSvg: string;
24
+ loadingIconSvg: string;
25
+ selectedIconSvg: string;
26
+ textDraftContent: string;
27
+ voiceCatalog: VoiceOption[];
28
+ selectedVoiceId: string | null;
29
+ activeVoiceFilterTag: string | null;
30
+ followTextUpdates: boolean;
31
+ isVoiceLoadingOverlayVisible: boolean;
32
+ isVoiceLoadingOverlayExiting: boolean;
33
+ voiceErrorMessage: string | null;
34
+ callbacks: ClipConfigPanelCallbacks;
35
+ }
36
+ export declare const CLIP_CONFIG_CSS_CLASSES: {
37
+ readonly container: "clip-config-panel";
38
+ readonly tabBar: "clip-config-tab-bar";
39
+ readonly tabButton: "clip-config-tab-button";
40
+ readonly content: "clip-config-content";
41
+ readonly visualPanel: "clip-config-visual-panel";
42
+ readonly audioPanel: "clip-config-audio-panel";
43
+ readonly textPanel: "clip-config-text-panel";
44
+ readonly voicePanel: "clip-config-voice-panel";
45
+ readonly actionBar: "clip-config-action-bar";
46
+ readonly section: "clip-config-section";
47
+ readonly sectionTitle: "clip-config-section-title";
48
+ readonly row: "clip-config-row";
49
+ readonly label: "clip-config-label";
50
+ readonly slider: "clip-config-slider";
51
+ readonly input: "clip-config-input";
52
+ readonly textarea: "clip-config-textarea";
53
+ readonly colorInput: "clip-config-color-input";
54
+ readonly presetGrid: "clip-config-preset-grid";
55
+ readonly presetButton: "clip-config-preset-button";
56
+ readonly resetButton: "clip-config-reset-button";
57
+ readonly emptyState: "clip-config-empty-state";
58
+ readonly filterGroup: "clip-config-filter-group";
59
+ readonly filterButton: "clip-config-filter-button";
60
+ readonly voiceCardGrid: "clip-config-voice-grid";
61
+ readonly voiceCard: "clip-config-voice-card";
62
+ readonly voiceCardAvatar: "clip-config-voice-avatar";
63
+ readonly voiceCardMeta: "clip-config-voice-meta";
64
+ readonly voiceCardTitle: "clip-config-voice-title";
65
+ readonly voiceCardSubtitle: "clip-config-voice-subtitle";
66
+ readonly voiceCardCheck: "clip-config-voice-check";
67
+ readonly voiceCheckbox: "clip-config-voice-checkbox";
68
+ readonly primaryButton: "clip-config-primary-button";
69
+ readonly errorText: "clip-config-error-text";
70
+ readonly voiceLoadingOverlay: "clip-config-voice-loading-overlay";
71
+ readonly voiceLoadingCard: "clip-config-voice-loading-card";
72
+ readonly voiceLoadingIcon: "clip-config-voice-loading-icon";
73
+ readonly voiceLoadingText: "clip-config-voice-loading-text";
74
+ };
75
+ export declare class ClipConfigPanelRenderer extends LitDomRenderer<ClipConfigPanelViewModel> {
76
+ protected renderTemplate(viewModel: ClipConfigPanelViewModel): TemplateResult;
77
+ private renderVoiceLoadingOverlay;
78
+ private renderEmptyState;
79
+ private renderPanel;
80
+ private renderTabBar;
81
+ private renderActionBar;
82
+ private renderVoiceActionBar;
83
+ private renderVisualPanel;
84
+ private renderPositionSection;
85
+ private renderScaleSection;
86
+ private renderAudioPanel;
87
+ private renderTextPanel;
88
+ private renderVoicePanel;
89
+ private renderFilterButton;
90
+ private renderVoiceCard;
91
+ private renderPositionControl;
92
+ private renderPresetGrid;
93
+ private renderSectionTitle;
94
+ private renderRangeInput;
95
+ private renderNumberInput;
96
+ private renderLabeledNumberInput;
97
+ private getContainerStyle;
98
+ private getSliderStyle;
99
+ private getAvailableTabs;
100
+ private supportsVoicePanel;
101
+ private getTransform;
102
+ private calculatePresetPosition;
103
+ private resizeSvg;
104
+ }
@@ -20,8 +20,9 @@ export declare class TrackInfoPanel {
20
20
  private width;
21
21
  private timeScaleHeight;
22
22
  private includeTimeScaleSpacer;
23
- private trackList;
24
- private iconCache;
23
+ private scrollTop;
24
+ private readonly renderer;
25
+ private readonly iconCache;
25
26
  private onMuteTrack?;
26
27
  constructor(config: TrackInfoPanelConfig, _onRenameTrack?: (trackId: string, newName: string) => void, _onDeleteTrack?: (trackId: string) => void, onMuteTrack?: (trackId: string, isMuted: boolean) => void);
27
28
  private init;
@@ -29,6 +30,5 @@ export declare class TrackInfoPanel {
29
30
  getTracks(): Track[];
30
31
  render(): void;
31
32
  setScrollTop(scrollTop: number): void;
32
- private createTrackItem;
33
33
  destroy(): void;
34
34
  }
@@ -0,0 +1,33 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { Track } from '../../core/models';
3
+ import { LitDomRenderer } from '../../core/renderers/domRenderer';
4
+ export interface TrackInfoPanelTheme {
5
+ background: string;
6
+ border: string;
7
+ text: string;
8
+ buttonBackground: string;
9
+ buttonHover: string;
10
+ buttonDanger: string;
11
+ }
12
+ export interface TrackInfoPanelViewModel {
13
+ tracks: Track[];
14
+ scrollTop: number;
15
+ theme: TrackInfoPanelTheme;
16
+ timeScaleHeight: number;
17
+ includeTimeScaleSpacer: boolean;
18
+ onMuteTrack?: (trackId: string, isMuted: boolean) => void;
19
+ icons: {
20
+ textTrack: string;
21
+ videoTrack: string;
22
+ audioTrack: string;
23
+ display: string;
24
+ hide: string;
25
+ volume: string;
26
+ volumeMuted: string;
27
+ };
28
+ }
29
+ export declare class TrackInfoPanelRenderer extends LitDomRenderer<TrackInfoPanelViewModel> {
30
+ protected renderTemplate(viewModel: TrackInfoPanelViewModel): TemplateResult;
31
+ private renderTrackItem;
32
+ private resizeSvg;
33
+ }
@@ -99,6 +99,9 @@ export declare class Track {
99
99
  private readonly handleEdgeAutoScrollFrame;
100
100
  private handleTrackBackgroundClick;
101
101
  private handleTrackBackgroundMouseDown;
102
+ private getClipDisplayLabel;
103
+ private getClipAudioBadgeText;
104
+ private isSourceBoundClip;
102
105
  updateClipSelection(clipId: string, isSelected: boolean): void;
103
106
  private createClipGroup;
104
107
  private handleClipClick;
@@ -130,6 +133,7 @@ export declare class Track {
130
133
  setCurrentTime(_time: TimeMs): void;
131
134
  setScrollLeft(scrollLeft: number): void;
132
135
  private updateClipVisibility;
136
+ private updateClipViewportState;
133
137
  setTrackY(trackY: number): void;
134
138
  setTrackStackOrder(order: number): void;
135
139
  setDragOverlayLayer(layer: Konva.Layer | null): void;
@@ -61,6 +61,7 @@ export type TrackPlacementCommandResult = {
61
61
  status: 'create_track';
62
62
  trackType: TrackType;
63
63
  suggestedTrackName: string;
64
+ insertionPlacement: TrackInsertionPlacement;
64
65
  };
65
66
  export type CrossTrackMoveCommandResult = {
66
67
  status: 'missing_target_track_by_position';
@@ -10,6 +10,7 @@ export { TimelinePlaybackResolver } from './timelinePlaybackResolver';
10
10
  export { TimelinePreviewSession } from './timelinePreviewSession';
11
11
  export { TimelinePreviewRuntimeController } from './timelinePreviewRuntimeController';
12
12
  export { TimelinePreviewStateController, type TimelinePendingPreviewState } from './timelinePreviewStateController';
13
+ export { TimelineKeyboardShortcutsController, type TimelineKeyboardShortcutsControllerCallbacks } from './timelineKeyboardShortcutsController';
13
14
  export * from './timelineSelectionController';
14
15
  export * from './timelineTrackMutationController';
15
16
  export { TimelineTrackInfoPanelController } from './timelineTrackInfoPanelController';
@@ -1,4 +1,5 @@
1
- import type { ActiveClipPlaybackInfo, Clip, ClipVisualTransform, PlayState, PreviewAspectRatio, PreviewMediaSource, PreviewSourceResolver, TimeMs } from '../models/types';
1
+ import type { ActiveClipPlaybackInfo, Clip, ClipVisualTransform, PlayState, PreviewAspectRatio, PreviewMediaSource, PreviewSourceResolver, TextPreviewFontConfig, TimeMs } from '../models/types';
2
+ import type { SourceMediaRegistry } from '../resources/sourceMediaRegistry';
2
3
  export interface TimelinePreviewSyncPayload {
3
4
  activeClips: ActiveClipPlaybackInfo[];
4
5
  nextClips: ActiveClipPlaybackInfo[];
@@ -66,6 +67,8 @@ export interface PreviewBackendClockState {
66
67
  export interface TimelinePreviewBackendOptions {
67
68
  callbacks?: TimelinePreviewBackendCallbacks;
68
69
  previewSourceResolver?: PreviewSourceResolver;
70
+ textPreviewFont?: TextPreviewFontConfig | null;
71
+ sourceMediaRegistry?: SourceMediaRegistry;
69
72
  rootClassName?: string;
70
73
  frameClassName?: string;
71
74
  slotClassNamePrefix?: string;
@@ -0,0 +1,17 @@
1
+ import type { PreviewPendingState, PreviewRuntimeState } from './previewBackend';
2
+ import type { DomRenderer } from '../renderers/domRenderer';
3
+ export interface PreviewPendingOverlayViewModel {
4
+ pendingState: PreviewPendingState | null;
5
+ runtimeState: PreviewRuntimeState;
6
+ }
7
+ export declare class PreviewPendingOverlayRenderer implements DomRenderer<PreviewPendingOverlayViewModel> {
8
+ private container;
9
+ private statusElement;
10
+ private detailElement;
11
+ private actionElement;
12
+ private readonly onRetry;
13
+ constructor(onRetry: () => void);
14
+ mount(container: HTMLElement): void;
15
+ update(viewModel: PreviewPendingOverlayViewModel): void;
16
+ destroy(): void;
17
+ }
@@ -1,9 +1,11 @@
1
- import { Theme, Clip } from '../models';
1
+ import { Theme, Clip, type VoiceOption } from '../models';
2
2
  export interface TimelineClipConfigControllerConfig {
3
3
  container: HTMLElement;
4
4
  theme: Theme;
5
5
  getPrimarySelectedClip: () => Clip | null;
6
+ voiceCatalog: VoiceOption[];
6
7
  updateClip: (clipId: string, updates: Partial<Clip>) => void;
8
+ onGenerateVoice?: (clip: Clip, voice: VoiceOption, followTextUpdates: boolean) => Promise<void>;
7
9
  }
8
10
  export declare class TimelineClipConfigController {
9
11
  private panel;
@@ -13,5 +15,7 @@ export declare class TimelineClipConfigController {
13
15
  update(): void;
14
16
  updateFromExternal(): void;
15
17
  destroy(): void;
18
+ setPreferredTab(tab: 'voice' | null): void;
19
+ setVoiceGenerationBusy(isBusy: boolean): void;
16
20
  private convertTheme;
17
21
  }
@@ -1,6 +1,7 @@
1
1
  import type { Clip, PlayState } from '../models/types';
2
2
  export interface ClipMutationEffectHandlers {
3
3
  notifySelectionChange: () => void;
4
+ emitSelectionChangeEvent?: () => void;
4
5
  emitSelectedClipChangeIfNeeded: () => void;
5
6
  handleClipChange: () => void;
6
7
  checkTrackDurationChange?: () => void;
@@ -0,0 +1,29 @@
1
+ import type { TimelineKeyboardShortcutsConfig } from '../models';
2
+ export interface TimelineKeyboardShortcutsControllerCallbacks {
3
+ togglePlay(): void;
4
+ deleteSelectedClips(): void;
5
+ toggleSelectedClipsAudio(): Promise<boolean>;
6
+ splitCurrentClip(): void;
7
+ undo(): boolean;
8
+ redo(): boolean;
9
+ canDeleteSelectedClips(): boolean;
10
+ canSplitSelectedClip(): boolean;
11
+ canToggleSelectedClipsAudio(): boolean;
12
+ }
13
+ export interface TimelineKeyboardShortcutsControllerOptions {
14
+ root: HTMLElement;
15
+ config?: false | TimelineKeyboardShortcutsConfig;
16
+ callbacks: TimelineKeyboardShortcutsControllerCallbacks;
17
+ isMacLike?: boolean;
18
+ }
19
+ export declare class TimelineKeyboardShortcutsController {
20
+ private readonly callbacks;
21
+ private readonly bindings;
22
+ private readonly enabled;
23
+ private readonly keydownListener;
24
+ constructor(options: TimelineKeyboardShortcutsControllerOptions);
25
+ init(): void;
26
+ destroy(): void;
27
+ private handleKeydown;
28
+ private dispatchAction;
29
+ }
@@ -1,4 +1,5 @@
1
- import type { ActiveClipPlaybackInfo, ClipVisualTransform, PlayState, PreviewAspectRatio, PreviewSourceResolver, TimeMs, TrackType } from '../models/types';
1
+ import type { ActiveClipPlaybackInfo, ClipVisualTransform, PlayState, PreviewAspectRatio, PreviewSourceResolver, TextPreviewFontConfig, TimeMs, TrackType } from '../models/types';
2
+ import type { SourceMediaRegistry } from '../resources/sourceMediaRegistry';
2
3
  import type { PreviewPendingState, PreviewRuntimeState } from './previewBackend';
3
4
  interface TimelinePreviewSessionCallbacks {
4
5
  onBufferingStateChange?: (isBuffering: boolean) => void;
@@ -17,6 +18,8 @@ interface TimelinePreviewSessionDependencies {
17
18
  frameClassName?: string;
18
19
  slotClassNamePrefix?: string;
19
20
  previewSourceResolver?: PreviewSourceResolver;
21
+ textPreviewFont?: TextPreviewFontConfig | null;
22
+ sourceMediaRegistry?: SourceMediaRegistry;
20
23
  }
21
24
  export interface TimelinePreviewSyncPayload {
22
25
  activeClips: ActiveClipPlaybackInfo[];
@@ -33,12 +36,12 @@ export declare class TimelinePreviewSession {
33
36
  private container;
34
37
  private rootElement;
35
38
  private frameElement;
39
+ private textOverlayRoot;
36
40
  private pendingOverlayElement;
37
- private pendingOverlayStatusElement;
38
- private pendingOverlayDetailElement;
39
- private pendingOverlayActionElement;
41
+ private readonly pendingOverlayRenderer;
40
42
  private resizeObserver;
41
43
  private readonly trackSlots;
44
+ private readonly textPreviewEntries;
42
45
  private audioContext;
43
46
  private masterGainNode;
44
47
  private loadingCount;
@@ -49,9 +52,18 @@ export declare class TimelinePreviewSession {
49
52
  private lastSettledSyncRequestId;
50
53
  private primarySelectedClipId;
51
54
  private transientVisualTransform;
55
+ private textPreviewDragState;
56
+ private textPreviewFontStyleElement;
57
+ private textPreviewFontSignature;
58
+ private textPreviewFontLoadState;
59
+ private textPreviewFontLoadToken;
52
60
  private readonly callbacks;
53
61
  private readonly dependencies;
54
62
  private readonly transformOverlay;
63
+ private readonly boundTextPreviewPointerMove;
64
+ private readonly boundTextPreviewPointerUp;
65
+ private readonly boundTextPreviewVisibilityChange;
66
+ private readonly boundTextPreviewWindowBlur;
55
67
  private requestedAspectRatio;
56
68
  private resolvedAutoAspectRatio;
57
69
  private aspectRatioProbe;
@@ -96,6 +108,7 @@ export declare class TimelinePreviewSession {
96
108
  private updateFrameLayout;
97
109
  private maybeResolveAutoAspectRatio;
98
110
  private resolveAspectRatioProbeSource;
111
+ private buildPreviewSourceCacheKey;
99
112
  private getAspectRatioProbe;
100
113
  private tryResolveAutoAspectRatioFromSlot;
101
114
  private handleResolvedAutoAspectRatio;
@@ -105,9 +118,28 @@ export declare class TimelinePreviewSession {
105
118
  private refreshPendingOverlay;
106
119
  private handlePreviewTransformChange;
107
120
  private refreshVisualLayout;
121
+ private syncTextPreviewEntries;
122
+ private clearTextPreviewEntries;
123
+ private removeTextPreviewEntry;
124
+ private applyTextPreviewEntry;
125
+ private refreshTextPreviewLayout;
126
+ private refreshTextPreviewEntries;
127
+ private createTextPreviewPointerDownHandler;
128
+ private bindTextPreviewDocumentListeners;
129
+ private unbindTextPreviewDocumentListeners;
130
+ private handleTextPreviewPointerMove;
131
+ private finishTextPreviewDrag;
132
+ private refreshTextPreviewInteractionState;
133
+ private getTextPreviewFontConfig;
134
+ private getTextPreviewFontFamily;
135
+ private ensureTextPreviewFontReady;
136
+ private resetTextPreviewFontState;
108
137
  private refreshSlotVisualLayout;
109
138
  private buildSelectedOverlayState;
110
139
  private getFrameSize;
140
+ private getDocument;
141
+ private toFrameLocalPoint;
142
+ private getTextPreviewBaselineMetrics;
111
143
  private getMediaSize;
112
144
  private getEffectiveVisualTransform;
113
145
  }
@@ -1,4 +1,4 @@
1
- import type { Clip } from '../models/types';
1
+ import type { Clip, SelectedClipAudioAction, SelectionChangeData } from '../models/types';
2
2
  export interface SelectedClipSnapshot {
3
3
  clip: Clip | null;
4
4
  hasSelectedClip: boolean;
@@ -7,11 +7,17 @@ interface ResolveSelectedClipOptions {
7
7
  getPrimarySelectedClip: () => Clip | null;
8
8
  findFallbackSelectedClip?: () => Clip | null;
9
9
  }
10
+ interface ResolveSelectionChangeOptions extends ResolveSelectedClipOptions {
11
+ getSelectedClipIds: () => string[];
12
+ canSplitSelectedClip: () => boolean;
13
+ getSelectedClipAudioAction: () => SelectedClipAudioAction;
14
+ }
10
15
  interface EmitSelectedClipChangeOptions {
11
16
  lastSelectedClipId: string | null;
12
17
  resolveSelectedClip: () => SelectedClipSnapshot;
13
18
  emitSelectedClipChange: (payload: SelectedClipSnapshot) => void;
14
19
  }
15
20
  export declare function resolveSelectedClipSnapshot(options: ResolveSelectedClipOptions): SelectedClipSnapshot;
21
+ export declare function resolveSelectionChangeData(options: ResolveSelectionChangeOptions): SelectionChangeData;
16
22
  export declare function emitSelectedClipChangeIfNeeded(options: EmitSelectedClipChangeOptions): string | null;
17
23
  export {};
@@ -1,8 +1,8 @@
1
1
  import type { MoveClipToTrackCommandResult, RemoveClipCommandResult, TrackPlacementCommandResult } from '../commands/timelineCommands';
2
- import type { Clip, TrackType } from '../models/types';
2
+ import type { Clip, TrackInsertionPlacement, TrackType } from '../models/types';
3
3
  import type { TimelineTrackCollection } from '../tracks/timelineTrackCollection';
4
4
  interface CreateTrackHandler {
5
- (type: TrackType, name?: string): string;
5
+ (type: TrackType, name?: string, insertionPlacement?: TrackInsertionPlacement, referenceTrackId?: string): string;
6
6
  }
7
7
  interface ApplyClipPlacementOptions {
8
8
  clip: Clip;