@webpacked-timeline/core 1.0.0-beta.1
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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/dist/chunk-27XCNVPR.js +5969 -0
- package/dist/chunk-6PDBJDHM.js +2263 -0
- package/dist/chunk-BWPS6NQT.js +7465 -0
- package/dist/chunk-FBOYSUYV.js +1280 -0
- package/dist/chunk-FR632TZX.js +1870 -0
- package/dist/chunk-HW4Z7YLJ.js +1242 -0
- package/dist/chunk-HWW62IFH.js +5424 -0
- package/dist/chunk-I2GZXRH4.js +4790 -0
- package/dist/chunk-JQZE3OK4.js +1255 -0
- package/dist/chunk-KF7JNK2F.js +1864 -0
- package/dist/chunk-KR3P2DYK.js +5655 -0
- package/dist/chunk-MO5DSFSW.js +2214 -0
- package/dist/chunk-MQAW33RJ.js +5530 -0
- package/dist/chunk-N4WUWZZX.js +2833 -0
- package/dist/chunk-NRJV7I4C.js +1331 -0
- package/dist/chunk-NXG52532.js +2230 -0
- package/dist/chunk-PVXF67CN.js +1278 -0
- package/dist/chunk-QSB6DHIF.js +5429 -0
- package/dist/chunk-QYWJT7HR.js +5837 -0
- package/dist/chunk-SWBRCMW7.js +7466 -0
- package/dist/chunk-TAT3ULSV.js +2214 -0
- package/dist/chunk-TTDP5JUM.js +2228 -0
- package/dist/chunk-UAGP4VPG.js +1739 -0
- package/dist/chunk-WIG6SY7A.js +1183 -0
- package/dist/chunk-YJ2K5N2R.js +6187 -0
- package/dist/index-3Lr_vKBd.d.cts +2810 -0
- package/dist/index-3Lr_vKBd.d.ts +2810 -0
- package/dist/index-7IPJn1yM.d.cts +1146 -0
- package/dist/index-7IPJn1yM.d.ts +1146 -0
- package/dist/index-B0xOv0V0.d.cts +3259 -0
- package/dist/index-B0xOv0V0.d.ts +3259 -0
- package/dist/index-B2m3zwg7.d.cts +1381 -0
- package/dist/index-B2m3zwg7.d.ts +1381 -0
- package/dist/index-B3sUrU_X.d.cts +1249 -0
- package/dist/index-B3sUrU_X.d.ts +1249 -0
- package/dist/index-B6wla7ZJ.d.cts +2751 -0
- package/dist/index-B6wla7ZJ.d.ts +2751 -0
- package/dist/index-BIv8RWWT.d.cts +1574 -0
- package/dist/index-BIv8RWWT.d.ts +1574 -0
- package/dist/index-BJv6hDHL.d.cts +3255 -0
- package/dist/index-BJv6hDHL.d.ts +3255 -0
- package/dist/index-BUCimS2e.d.cts +1393 -0
- package/dist/index-BUCimS2e.d.ts +1393 -0
- package/dist/index-Bw_nvNcG.d.cts +1275 -0
- package/dist/index-Bw_nvNcG.d.ts +1275 -0
- package/dist/index-ByG0gOtd.d.cts +1167 -0
- package/dist/index-ByG0gOtd.d.ts +1167 -0
- package/dist/index-CDGd2XXv.d.cts +2492 -0
- package/dist/index-CDGd2XXv.d.ts +2492 -0
- package/dist/index-CznAVeJ6.d.cts +1145 -0
- package/dist/index-CznAVeJ6.d.ts +1145 -0
- package/dist/index-DQD9IMh7.d.cts +2534 -0
- package/dist/index-DQD9IMh7.d.ts +2534 -0
- package/dist/index-Dl3qtJEI.d.cts +2178 -0
- package/dist/index-Dl3qtJEI.d.ts +2178 -0
- package/dist/index-DnE2A-Nz.d.cts +2603 -0
- package/dist/index-DnE2A-Nz.d.ts +2603 -0
- package/dist/index-DrOA6QmW.d.cts +2492 -0
- package/dist/index-DrOA6QmW.d.ts +2492 -0
- package/dist/index-Vpa3rPEM.d.cts +1402 -0
- package/dist/index-Vpa3rPEM.d.ts +1402 -0
- package/dist/index-jP6BomSd.d.cts +2640 -0
- package/dist/index-jP6BomSd.d.ts +2640 -0
- package/dist/index-wiGRwVyY.d.cts +3259 -0
- package/dist/index-wiGRwVyY.d.ts +3259 -0
- package/dist/index.cjs +7386 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +263 -0
- package/dist/internal.cjs +7721 -0
- package/dist/internal.d.cts +704 -0
- package/dist/internal.d.ts +704 -0
- package/dist/internal.js +405 -0
- package/package.json +58 -0
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import { T as TimelineState, C as Clip, a as Track, b as TimelineFrame, A as Asset } from './index-wiGRwVyY.cjs';
|
|
2
|
+
export { c as AAFExportOptions, d as AnimatableProperty, e as AssetId, f as AssetRegistry, g as AssetRemapCallback, h as AssetStatus, i as AudioChunkRequest, j as AudioChunkResult, k as AudioDecoder, l as AudioProperties, B as Bin, m as BinId, n as BinItem, o as CURRENT_SCHEMA_VERSION, p as ChannelRouting, q as ClipEntry, r as ClipId, s as ClipTransform, t as Clock, u as CompositeLayer, v as CompositeRequest, w as CompositeResult, x as Compositor, y as CompressibleOpType, z as CompressionPolicy, D as DEFAULT_AUDIO_PROPERTIES, E as DEFAULT_CLIP_TRANSFORM, F as DEFAULT_COMPRESSION_POLICY, G as DEFAULT_KEY_BINDINGS, H as DispatchResult, I as EDLExportOptions, J as EMPTY_STATE_CHANGE, K as EasingCurve, L as Effect, M as EffectId, N as EffectParam, O as EffectType, P as FCPXMLExportOptions, Q as FrameRate, R as FrameRates, S as HOLD_EASING, U as HandTool, V as HistoryEntry, W as HistoryStack, X as HistoryState, Y as ITool, Z as Interval, _ as IntervalTree, $ as InvariantViolation, a0 as KeyBinding, a1 as KeyboardHandler, a2 as KeyboardHandlerOptions, a3 as Keyframe, a4 as KeyframeId, a5 as KeyframeTool, a6 as LINEAR_EASING, a7 as LinkGroup, a8 as LinkGroupId, a9 as LoopRegion, aa as MarkerId, ab as Modifiers, ac as NO_COMPRESSION, ad as NoOpTool, ae as OTIODocument, af as OTIOImportOptions, ag as OfflineAsset, ah as OperationPrimitive, ai as PipelineConfig, aj as PlaybackEngine, ak as PlaybackQuality, al as PlaybackRate, am as PlayheadController, an as PlayheadEvent, ao as PlayheadEventType, ap as PlayheadListener, aq as PlayheadState, ar as PlayheadUnsubscribe, as as Project, at as ProjectId, au as ProvisionalManager, av as ProvisionalState, aw as RationalTime, ax as RazorTool, ay as RejectionReason, az as RenderStage, aA as RippleDeleteTool, aB as RippleInsertTool, aC as RippleTrimTool, aD as RollTrimTool, aE as RubberBandRegion, aF as SRTParseOptions, aG as SelectionTool, aH as SequenceSettings, aI as SerializationError, aJ as SlideTool, aK as SlipTool, aL as SnapIndex, aM as SnapIndexManager, aN as SnapPoint, aO as SnapPointType, aP as StateChange, aQ as ThumbnailCache, aR as ThumbnailPriority, aS as ThumbnailProvider, aT as ThumbnailQueue, aU as ThumbnailQueueEntry, aV as ThumbnailRequest, aW as ThumbnailResult, aX as ThumbnailWorkerMessage, aY as ThumbnailWorkerResponse, aZ as TimeRange, a_ as Timecode, a$ as Timeline, b0 as TimelineEngine, b1 as TimelineKeyAction, b2 as TimelineKeyEvent, b3 as TimelinePointerEvent, b4 as ToolContext, b5 as ToolId, b6 as ToolRegistry, b7 as TrackGroup, b8 as TrackGroupId, b9 as TrackId, ba as TrackIndex, bb as TrackType, bc as Transaction, bd as TransactionCompressor, be as Transition, bf as TransitionAlignment, bg as TransitionId, bh as TransitionParam, bi as TransitionTool, bj as TransitionType, bk as VTTParseOptions, bl as VideoDecoder, bm as VideoFrameRequest, bn as VideoFrameResult, bo as ViolationType, bp as VirtualClipEntry, bq as VirtualWindow, br as WaveformPeak, bs as WaveformRequest, bt as WaveformResult, bu as WaveformWorkerMessage, bv as WaveformWorkerResponse, bw as ZoomTool, bx as ZoomToolOptions, by as activateTool, by as activateToolInRegistry, bz as addBin, bA as addFrames, bB as addItemToBin, bC as addTimeline, bD as browserClock, bE as buildSnapIndex, bF as canRedo, bG as canUndo, bH as checkInvariants, bI as clampFrame, bJ as clearProvisional, bK as clipContainsFrame, bL as clipsOverlap, bM as createAnimatableProperty, bN as createAsset, bO as createBin, bP as createClip, bQ as createEffect, bR as createHistory, bS as createLinkGroup, bT as createProject, bU as createProvisionalManager, bV as createRegistry, bW as createTestClock, bX as createTimeline, bY as createTimelineState, bZ as createTrack, b_ as createTrackGroup, b$ as createTransition, c0 as createZoomTool, c1 as defaultCaptionStyle, c2 as deserializeProject, c3 as deserializeTimeline, c4 as diffStates, c5 as dispatch, c6 as exportToAAF, c7 as exportToEDL, c8 as exportToFCPXML, c9 as exportToOTIO, ca as findMarkersByColor, cb as findMarkersByLabel, cc as findNextClipBoundary, cd as findNextMarker, ce as findOfflineAssets, cf as findPrevClipBoundary, cg as findPrevMarker, ch as frame, ci as frameDuration, cj as frameRate, ck as frameToTimecode, cl as framesToMinutesSeconds, cm as framesToSeconds, cn as framesToTimecode, co as getActiveTool, cp as getClipDuration, cq as getClipMediaDuration, cr as getCurrentState, cs as getVisibleClips, ct as getVisibleFrameRange, cu as importFromOTIO, cv as isDropFrame, cw as isValidFrame, cx as mediaFrameForClip, cy as moveItemBetweenBins, cz as nearest, cA as nodeClock, cB as parseSRT, cC as parseVTT, cD as pushHistory, cE as redo, cF as reelName, cG as registerTool, cH as remapAssetPaths, cI as removeBin, cJ as removeItemFromBin, cK as removeTimeline, cL as resolveClip, cM as resolveFrame, cN as secondsToFrames, cO as serializeProject, cP as serializeTimeline, cQ as setProvisional, cR as sortTrackClips, cS as subtitleImportToOps, cT as subtractFrames, cU as toAssetId, cV as toBinId, cW as toClipId, cX as toEffectId, cY as toFCPTime, cZ as toFrame, c_ as toKeyframeId, c$ as toLinkGroupId, d0 as toMarkerId, d1 as toProjectId, d2 as toTimecode, d3 as toToolId, d4 as toTrackGroupId, d5 as toTrackId, d6 as toTransitionId, d7 as toggleSnap, d8 as undo } from './index-wiGRwVyY.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* VALIDATION SYSTEM TYPES
|
|
6
|
+
*
|
|
7
|
+
* This file defines the structure for validation results throughout the engine.
|
|
8
|
+
*
|
|
9
|
+
* WHY STRUCTURED VALIDATION?
|
|
10
|
+
* - Operations can fail gracefully (no exceptions thrown)
|
|
11
|
+
* - Errors are descriptive and actionable
|
|
12
|
+
* - Multiple errors can be collected and reported together
|
|
13
|
+
* - Validation logic is separated from business logic
|
|
14
|
+
*
|
|
15
|
+
* USAGE:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const result = validateClip(state, clip);
|
|
18
|
+
* if (!result.valid) {
|
|
19
|
+
* console.error('Validation failed:', result.errors);
|
|
20
|
+
* return;
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* ValidationError - A single validation error
|
|
26
|
+
*
|
|
27
|
+
* Contains:
|
|
28
|
+
* - code: Machine-readable error code (e.g., "CLIP_OVERLAP")
|
|
29
|
+
* - message: Human-readable error message
|
|
30
|
+
* - context: Optional additional data about the error
|
|
31
|
+
*/
|
|
32
|
+
interface ValidationError {
|
|
33
|
+
/** Machine-readable error code */
|
|
34
|
+
code: string;
|
|
35
|
+
/** Human-readable error message */
|
|
36
|
+
message: string;
|
|
37
|
+
/** Optional context data for debugging */
|
|
38
|
+
context?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* ValidationResult - The result of a validation operation
|
|
42
|
+
*
|
|
43
|
+
* Contains:
|
|
44
|
+
* - valid: Whether the validation passed
|
|
45
|
+
* - errors: Array of validation errors (empty if valid)
|
|
46
|
+
*/
|
|
47
|
+
interface ValidationResult {
|
|
48
|
+
/** Whether the validation passed */
|
|
49
|
+
valid: boolean;
|
|
50
|
+
/** Array of validation errors (empty if valid) */
|
|
51
|
+
errors: ValidationError[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create a successful validation result
|
|
55
|
+
*
|
|
56
|
+
* @returns A ValidationResult indicating success
|
|
57
|
+
*/
|
|
58
|
+
declare function validResult(): ValidationResult;
|
|
59
|
+
/**
|
|
60
|
+
* Create a failed validation result with a single error
|
|
61
|
+
*
|
|
62
|
+
* @param code - Error code
|
|
63
|
+
* @param message - Error message
|
|
64
|
+
* @param context - Optional context data
|
|
65
|
+
* @returns A ValidationResult indicating failure
|
|
66
|
+
*/
|
|
67
|
+
declare function invalidResult(code: string, message: string, context?: Record<string, unknown>): ValidationResult;
|
|
68
|
+
/**
|
|
69
|
+
* Create a failed validation result with multiple errors
|
|
70
|
+
*
|
|
71
|
+
* @param errors - Array of validation errors
|
|
72
|
+
* @returns A ValidationResult indicating failure
|
|
73
|
+
*/
|
|
74
|
+
declare function invalidResults(errors: ValidationError[]): ValidationResult;
|
|
75
|
+
/**
|
|
76
|
+
* Combine multiple validation results
|
|
77
|
+
*
|
|
78
|
+
* If any result is invalid, the combined result is invalid.
|
|
79
|
+
* All errors are collected together.
|
|
80
|
+
*
|
|
81
|
+
* @param results - Array of validation results to combine
|
|
82
|
+
* @returns A combined ValidationResult
|
|
83
|
+
*/
|
|
84
|
+
declare function combineResults(...results: ValidationResult[]): ValidationResult;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* VALIDATION SYSTEM
|
|
88
|
+
*
|
|
89
|
+
* Pure functions for validating timeline state integrity.
|
|
90
|
+
*
|
|
91
|
+
* WHAT IS VALIDATION?
|
|
92
|
+
* - Checks that state meets all invariants and rules
|
|
93
|
+
* - Returns structured errors (doesn't throw exceptions)
|
|
94
|
+
* - Prevents invalid states from entering history
|
|
95
|
+
*
|
|
96
|
+
* WHY VALIDATE?
|
|
97
|
+
* - Catch errors early before they corrupt state
|
|
98
|
+
* - Provide clear error messages for debugging
|
|
99
|
+
* - Ensure timeline integrity at all times
|
|
100
|
+
*
|
|
101
|
+
* VALIDATION RULES:
|
|
102
|
+
*
|
|
103
|
+
* CLIP VALIDATION:
|
|
104
|
+
* - Asset must exist in registry
|
|
105
|
+
* - timelineEnd > timelineStart
|
|
106
|
+
* - mediaOut > mediaIn
|
|
107
|
+
* - mediaOut <= asset.intrinsicDuration
|
|
108
|
+
* - Timeline duration === media duration (Phase 1, no speed)
|
|
109
|
+
*
|
|
110
|
+
* TRACK VALIDATION:
|
|
111
|
+
* - No overlapping clips
|
|
112
|
+
* - All clips valid
|
|
113
|
+
*
|
|
114
|
+
* TIMELINE VALIDATION:
|
|
115
|
+
* - FPS > 0
|
|
116
|
+
* - Duration > 0
|
|
117
|
+
* - All tracks valid
|
|
118
|
+
*
|
|
119
|
+
* USAGE:
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const result = validateClip(state, clip);
|
|
122
|
+
* if (!result.valid) {
|
|
123
|
+
* console.error('Invalid clip:', result.errors);
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Validate a clip
|
|
130
|
+
*
|
|
131
|
+
* Checks:
|
|
132
|
+
* - Asset exists
|
|
133
|
+
* - Timeline bounds are valid
|
|
134
|
+
* - Media bounds are valid
|
|
135
|
+
* - Media bounds don't exceed asset duration
|
|
136
|
+
* - Timeline duration matches media duration (Phase 1)
|
|
137
|
+
*
|
|
138
|
+
* @param state - Current timeline state
|
|
139
|
+
* @param clip - Clip to validate
|
|
140
|
+
* @returns Validation result
|
|
141
|
+
*/
|
|
142
|
+
declare function validateClip(state: TimelineState, clip: Clip): ValidationResult;
|
|
143
|
+
/**
|
|
144
|
+
* Validate a track
|
|
145
|
+
*
|
|
146
|
+
* Checks:
|
|
147
|
+
* - No overlapping clips
|
|
148
|
+
* - All clips are valid
|
|
149
|
+
*
|
|
150
|
+
* @param state - Current timeline state
|
|
151
|
+
* @param track - Track to validate
|
|
152
|
+
* @returns Validation result
|
|
153
|
+
*/
|
|
154
|
+
declare function validateTrack(state: TimelineState, track: Track): ValidationResult;
|
|
155
|
+
/**
|
|
156
|
+
* Validate the entire timeline
|
|
157
|
+
*
|
|
158
|
+
* Checks:
|
|
159
|
+
* - FPS is positive
|
|
160
|
+
* - Duration is positive
|
|
161
|
+
* - All tracks are valid
|
|
162
|
+
*
|
|
163
|
+
* @param state - Current timeline state
|
|
164
|
+
* @returns Validation result
|
|
165
|
+
*/
|
|
166
|
+
declare function validateTimeline(state: TimelineState): ValidationResult;
|
|
167
|
+
/**
|
|
168
|
+
* Check if adding a clip to a track would cause overlap
|
|
169
|
+
*
|
|
170
|
+
* This is a helper for operations to check before adding a clip.
|
|
171
|
+
*
|
|
172
|
+
* @param track - Track to check
|
|
173
|
+
* @param clip - Clip to add
|
|
174
|
+
* @returns Validation result
|
|
175
|
+
*/
|
|
176
|
+
declare function validateNoOverlap(track: Track, clip: Clip): ValidationResult;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* QUERY SYSTEM
|
|
180
|
+
*
|
|
181
|
+
* Read-only query functions for the timeline state.
|
|
182
|
+
*
|
|
183
|
+
* WHAT ARE QUERIES?
|
|
184
|
+
* - Pure functions that read data from state
|
|
185
|
+
* - Never mutate state
|
|
186
|
+
* - Provide convenient access to timeline data
|
|
187
|
+
*
|
|
188
|
+
* WHY QUERIES?
|
|
189
|
+
* - Separate read operations from write operations
|
|
190
|
+
* - Reusable logic for finding clips, tracks, etc.
|
|
191
|
+
* - Makes the codebase easier to understand and test
|
|
192
|
+
*
|
|
193
|
+
* USAGE:
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const clip = findClipById(state, 'clip_1');
|
|
196
|
+
* const track = findTrackById(state, 'track_1');
|
|
197
|
+
* const clips = getClipsAtFrame(state, frame(150));
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* ALL FUNCTIONS ARE PURE AND READ-ONLY:
|
|
201
|
+
* - Take state as input
|
|
202
|
+
* - Return data (never mutate state)
|
|
203
|
+
* - No side effects
|
|
204
|
+
*/
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Find a clip by ID
|
|
208
|
+
*
|
|
209
|
+
* Searches all tracks for a clip with the given ID.
|
|
210
|
+
*
|
|
211
|
+
* @param state - Current timeline state
|
|
212
|
+
* @param clipId - ID of the clip to find
|
|
213
|
+
* @returns The clip, or undefined if not found
|
|
214
|
+
*/
|
|
215
|
+
declare function findClipById(state: TimelineState, clipId: string): Clip | undefined;
|
|
216
|
+
/**
|
|
217
|
+
* Find a track by ID
|
|
218
|
+
*
|
|
219
|
+
* @param state - Current timeline state
|
|
220
|
+
* @param trackId - ID of the track to find
|
|
221
|
+
* @returns The track, or undefined if not found
|
|
222
|
+
*/
|
|
223
|
+
declare function findTrackById(state: TimelineState, trackId: string): Track | undefined;
|
|
224
|
+
/**
|
|
225
|
+
* Get all clips on a specific track
|
|
226
|
+
*
|
|
227
|
+
* @param state - Current timeline state
|
|
228
|
+
* @param trackId - ID of the track
|
|
229
|
+
* @returns Array of clips on the track (empty if track not found)
|
|
230
|
+
*/
|
|
231
|
+
declare function getClipsOnTrack(state: TimelineState, trackId: string): Clip[];
|
|
232
|
+
/**
|
|
233
|
+
* Get all clips at a specific frame
|
|
234
|
+
*
|
|
235
|
+
* Returns all clips that contain the given frame.
|
|
236
|
+
*
|
|
237
|
+
* @param state - Current timeline state
|
|
238
|
+
* @param frame - The frame to check
|
|
239
|
+
* @returns Array of clips at that frame
|
|
240
|
+
*/
|
|
241
|
+
declare function getClipsAtFrame(state: TimelineState, frame: TimelineFrame): Clip[];
|
|
242
|
+
/**
|
|
243
|
+
* Get all clips in a frame range
|
|
244
|
+
*
|
|
245
|
+
* Returns all clips that overlap with the given range.
|
|
246
|
+
*
|
|
247
|
+
* @param state - Current timeline state
|
|
248
|
+
* @param start - Start frame (inclusive)
|
|
249
|
+
* @param end - End frame (exclusive)
|
|
250
|
+
* @returns Array of clips in the range
|
|
251
|
+
*/
|
|
252
|
+
declare function getClipsInRange(state: TimelineState, start: TimelineFrame, end: TimelineFrame): Clip[];
|
|
253
|
+
/**
|
|
254
|
+
* Get all clips in the timeline
|
|
255
|
+
*
|
|
256
|
+
* @param state - Current timeline state
|
|
257
|
+
* @returns Array of all clips across all tracks
|
|
258
|
+
*/
|
|
259
|
+
declare function getAllClips(state: TimelineState): Clip[];
|
|
260
|
+
/**
|
|
261
|
+
* Get all tracks in the timeline
|
|
262
|
+
*
|
|
263
|
+
* @param state - Current timeline state
|
|
264
|
+
* @returns Array of all tracks
|
|
265
|
+
*/
|
|
266
|
+
declare function getAllTracks(state: TimelineState): readonly Track[];
|
|
267
|
+
/**
|
|
268
|
+
* Find the index of a track by ID
|
|
269
|
+
*
|
|
270
|
+
* @param state - Current timeline state
|
|
271
|
+
* @param trackId - ID of the track
|
|
272
|
+
* @returns The index of the track, or -1 if not found
|
|
273
|
+
*/
|
|
274
|
+
declare function findTrackIndex(state: TimelineState, trackId: string): number;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* ASSET REGISTRY SYSTEM — Phase 0 compliant
|
|
278
|
+
*
|
|
279
|
+
* Pure functions for managing assets in the timeline state.
|
|
280
|
+
* Uses state.assetRegistry (ReadonlyMap<AssetId, Asset>).
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
declare function registerAsset(state: TimelineState, asset: Asset): TimelineState;
|
|
284
|
+
declare function getAsset(state: TimelineState, assetId: string): Asset | undefined;
|
|
285
|
+
declare function hasAsset(state: TimelineState, assetId: string): boolean;
|
|
286
|
+
declare function getAllAssets(state: TimelineState): Asset[];
|
|
287
|
+
declare function unregisterAsset(state: TimelineState, assetId: string): TimelineState;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* CLIP OPERATIONS
|
|
291
|
+
*
|
|
292
|
+
* Pure functions for manipulating clips in the timeline state.
|
|
293
|
+
*
|
|
294
|
+
* WHAT ARE OPERATIONS?
|
|
295
|
+
* - Pure functions that transform state
|
|
296
|
+
* - Take current state, return new state
|
|
297
|
+
* - Never mutate input state
|
|
298
|
+
* - No side effects
|
|
299
|
+
*
|
|
300
|
+
* WHY PURE OPERATIONS?
|
|
301
|
+
* - Predictable and testable
|
|
302
|
+
* - Can be composed together
|
|
303
|
+
* - Easy to undo/redo (just store snapshots)
|
|
304
|
+
* - No hidden state changes
|
|
305
|
+
*
|
|
306
|
+
* IMPORTANT:
|
|
307
|
+
* These operations do NOT validate. Validation happens at the
|
|
308
|
+
* dispatch layer. Operations assume inputs are valid.
|
|
309
|
+
*
|
|
310
|
+
* USAGE:
|
|
311
|
+
* ```typescript
|
|
312
|
+
* let state = addClip(state, 'track_1', clip);
|
|
313
|
+
* state = moveClip(state, 'clip_1', frame(200));
|
|
314
|
+
* state = removeClip(state, 'clip_1');
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
|
|
318
|
+
type Frame$2 = TimelineFrame;
|
|
319
|
+
/**
|
|
320
|
+
* Add a clip to a track
|
|
321
|
+
*
|
|
322
|
+
* Creates a new state with the clip added to the specified track.
|
|
323
|
+
* The track's clips are sorted by timeline start after adding.
|
|
324
|
+
*
|
|
325
|
+
* @param state - Current timeline state
|
|
326
|
+
* @param trackId - ID of the track to add to
|
|
327
|
+
* @param clip - Clip to add
|
|
328
|
+
* @returns New timeline state with clip added
|
|
329
|
+
*/
|
|
330
|
+
declare function addClip(state: TimelineState, trackId: string, clip: Clip): TimelineState;
|
|
331
|
+
/**
|
|
332
|
+
* Remove a clip from the timeline
|
|
333
|
+
*
|
|
334
|
+
* Searches all tracks and removes the clip with the given ID.
|
|
335
|
+
*
|
|
336
|
+
* @param state - Current timeline state
|
|
337
|
+
* @param clipId - ID of the clip to remove
|
|
338
|
+
* @returns New timeline state with clip removed
|
|
339
|
+
*/
|
|
340
|
+
declare function removeClip(state: TimelineState, clipId: string): TimelineState;
|
|
341
|
+
/**
|
|
342
|
+
* Move a clip to a new timeline position
|
|
343
|
+
*
|
|
344
|
+
* Moves the clip by updating its timelineStart and timelineEnd.
|
|
345
|
+
* The media bounds (mediaIn/mediaOut) remain unchanged.
|
|
346
|
+
*
|
|
347
|
+
* @param state - Current timeline state
|
|
348
|
+
* @param clipId - ID of the clip to move
|
|
349
|
+
* @param newStart - New timeline start frame
|
|
350
|
+
* @returns New timeline state with clip moved
|
|
351
|
+
*/
|
|
352
|
+
declare function moveClip(state: TimelineState, clipId: string, newStart: Frame$2): TimelineState;
|
|
353
|
+
/**
|
|
354
|
+
* Resize a clip by changing its timeline bounds
|
|
355
|
+
*
|
|
356
|
+
* This adjusts the timeline bounds AND the corresponding media bounds
|
|
357
|
+
* to maintain the Phase 1 invariant: timeline duration === media duration.
|
|
358
|
+
*
|
|
359
|
+
* Left resize: Updates timelineStart and mediaIn
|
|
360
|
+
* Right resize: Updates timelineEnd and mediaOut
|
|
361
|
+
*
|
|
362
|
+
* @param state - Current timeline state
|
|
363
|
+
* @param clipId - ID of the clip to resize
|
|
364
|
+
* @param newStart - New timeline start frame
|
|
365
|
+
* @param newEnd - New timeline end frame
|
|
366
|
+
* @returns New timeline state with clip resized
|
|
367
|
+
*/
|
|
368
|
+
declare function resizeClip(state: TimelineState, clipId: string, newStart: Frame$2, newEnd: Frame$2): TimelineState;
|
|
369
|
+
/**
|
|
370
|
+
* Trim a clip by changing its media bounds
|
|
371
|
+
*
|
|
372
|
+
* This adjusts which portion of the source asset is played.
|
|
373
|
+
* The timeline bounds remain unchanged.
|
|
374
|
+
*
|
|
375
|
+
* @param state - Current timeline state
|
|
376
|
+
* @param clipId - ID of the clip to trim
|
|
377
|
+
* @param newMediaIn - New media in frame
|
|
378
|
+
* @param newMediaOut - New media out frame
|
|
379
|
+
* @returns New timeline state with clip trimmed
|
|
380
|
+
*/
|
|
381
|
+
declare function trimClip(state: TimelineState, clipId: string, newMediaIn: Frame$2, newMediaOut: Frame$2): TimelineState;
|
|
382
|
+
/**
|
|
383
|
+
* Update clip properties
|
|
384
|
+
*
|
|
385
|
+
* Generic function to update any clip properties.
|
|
386
|
+
*
|
|
387
|
+
* @param state - Current timeline state
|
|
388
|
+
* @param clipId - ID of the clip to update
|
|
389
|
+
* @param updates - Partial clip properties to update
|
|
390
|
+
* @returns New timeline state with clip updated
|
|
391
|
+
*/
|
|
392
|
+
declare function updateClip(state: TimelineState, clipId: string, updates: Partial<Clip>): TimelineState;
|
|
393
|
+
/**
|
|
394
|
+
* Move a clip to a different track
|
|
395
|
+
*
|
|
396
|
+
* Removes the clip from its current track and adds it to the target track.
|
|
397
|
+
*
|
|
398
|
+
* If validation fails (e.g., track type mismatch), returns state unchanged.
|
|
399
|
+
* The dispatcher will catch validation errors after the operation completes.
|
|
400
|
+
*
|
|
401
|
+
* @param state - Current timeline state
|
|
402
|
+
* @param clipId - ID of the clip to move
|
|
403
|
+
* @param targetTrackId - ID of the target track
|
|
404
|
+
* @returns New timeline state with clip moved to new track, or unchanged state if validation fails
|
|
405
|
+
*/
|
|
406
|
+
declare function moveClipToTrack(state: TimelineState, clipId: string, targetTrackId: string): TimelineState;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* TRACK OPERATIONS
|
|
410
|
+
*
|
|
411
|
+
* Pure functions for manipulating tracks in the timeline state.
|
|
412
|
+
*
|
|
413
|
+
* WHAT ARE TRACK OPERATIONS?
|
|
414
|
+
* - Add/remove tracks
|
|
415
|
+
* - Reorder tracks
|
|
416
|
+
* - Update track properties (name, mute, lock)
|
|
417
|
+
*
|
|
418
|
+
* ALL OPERATIONS ARE PURE:
|
|
419
|
+
* - Take state as input
|
|
420
|
+
* - Return new state as output
|
|
421
|
+
* - Never mutate input state
|
|
422
|
+
*
|
|
423
|
+
* USAGE:
|
|
424
|
+
* ```typescript
|
|
425
|
+
* let state = addTrack(state, track);
|
|
426
|
+
* state = moveTrack(state, 'track_1', 2);
|
|
427
|
+
* state = updateTrack(state, 'track_1', { muted: true });
|
|
428
|
+
* state = removeTrack(state, 'track_1');
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Add a track to the timeline
|
|
434
|
+
*
|
|
435
|
+
* Adds the track to the end of the tracks array (top layer).
|
|
436
|
+
*
|
|
437
|
+
* @param state - Current timeline state
|
|
438
|
+
* @param track - Track to add
|
|
439
|
+
* @returns New timeline state with track added
|
|
440
|
+
*/
|
|
441
|
+
declare function addTrack(state: TimelineState, track: Track): TimelineState;
|
|
442
|
+
/**
|
|
443
|
+
* Remove a track from the timeline
|
|
444
|
+
*
|
|
445
|
+
* WARNING: This also removes all clips on the track.
|
|
446
|
+
*
|
|
447
|
+
* @param state - Current timeline state
|
|
448
|
+
* @param trackId - ID of the track to remove
|
|
449
|
+
* @returns New timeline state with track removed
|
|
450
|
+
*/
|
|
451
|
+
declare function removeTrack(state: TimelineState, trackId: string): TimelineState;
|
|
452
|
+
/**
|
|
453
|
+
* Move a track to a new position
|
|
454
|
+
*
|
|
455
|
+
* Changes the track order (bottom-to-top rendering).
|
|
456
|
+
*
|
|
457
|
+
* @param state - Current timeline state
|
|
458
|
+
* @param trackId - ID of the track to move
|
|
459
|
+
* @param newIndex - New index position (0 = bottom)
|
|
460
|
+
* @returns New timeline state with track moved
|
|
461
|
+
*/
|
|
462
|
+
declare function moveTrack(state: TimelineState, trackId: string, newIndex: number): TimelineState;
|
|
463
|
+
/**
|
|
464
|
+
* Update track properties
|
|
465
|
+
*
|
|
466
|
+
* Generic function to update any track properties.
|
|
467
|
+
*
|
|
468
|
+
* @param state - Current timeline state
|
|
469
|
+
* @param trackId - ID of the track to update
|
|
470
|
+
* @param updates - Partial track properties to update
|
|
471
|
+
* @returns New timeline state with track updated
|
|
472
|
+
*/
|
|
473
|
+
declare function updateTrack(state: TimelineState, trackId: string, updates: Partial<Track>): TimelineState;
|
|
474
|
+
/**
|
|
475
|
+
* Toggle track mute
|
|
476
|
+
*
|
|
477
|
+
* @param state - Current timeline state
|
|
478
|
+
* @param trackId - ID of the track
|
|
479
|
+
* @returns New timeline state with track mute toggled
|
|
480
|
+
*/
|
|
481
|
+
declare function toggleTrackMute(state: TimelineState, trackId: string): TimelineState;
|
|
482
|
+
/**
|
|
483
|
+
* Toggle track lock
|
|
484
|
+
*
|
|
485
|
+
* @param state - Current timeline state
|
|
486
|
+
* @param trackId - ID of the track
|
|
487
|
+
* @returns New timeline state with track lock toggled
|
|
488
|
+
*/
|
|
489
|
+
declare function toggleTrackLock(state: TimelineState, trackId: string): TimelineState;
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* TIMELINE OPERATIONS
|
|
493
|
+
*
|
|
494
|
+
* Pure functions for manipulating timeline-level properties.
|
|
495
|
+
*
|
|
496
|
+
* WHAT ARE TIMELINE OPERATIONS?
|
|
497
|
+
* - Update timeline duration
|
|
498
|
+
* - Update timeline name
|
|
499
|
+
* - Update timeline metadata
|
|
500
|
+
*
|
|
501
|
+
* ALL OPERATIONS ARE PURE:
|
|
502
|
+
* - Take state as input
|
|
503
|
+
* - Return new state as output
|
|
504
|
+
* - Never mutate input state
|
|
505
|
+
*
|
|
506
|
+
* USAGE:
|
|
507
|
+
* ```typescript
|
|
508
|
+
* let state = setTimelineDuration(state, frame(9000));
|
|
509
|
+
* state = setTimelineName(state, 'My Project');
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
|
|
513
|
+
type Frame$1 = TimelineFrame;
|
|
514
|
+
/**
|
|
515
|
+
* Set the timeline duration
|
|
516
|
+
*
|
|
517
|
+
* @param state - Current timeline state
|
|
518
|
+
* @param duration - New duration in frames
|
|
519
|
+
* @returns New timeline state with updated duration
|
|
520
|
+
*/
|
|
521
|
+
declare function setTimelineDuration(state: TimelineState, duration: Frame$1): TimelineState;
|
|
522
|
+
/**
|
|
523
|
+
* Set the timeline name
|
|
524
|
+
*
|
|
525
|
+
* @param state - Current timeline state
|
|
526
|
+
* @param name - New timeline name
|
|
527
|
+
* @returns New timeline state with updated name
|
|
528
|
+
*/
|
|
529
|
+
declare function setTimelineName(state: TimelineState, name: string): TimelineState;
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* RIPPLE OPERATIONS
|
|
533
|
+
*
|
|
534
|
+
* Ripple edits shift subsequent clips on the same track.
|
|
535
|
+
* These compose basic operations using transactions.
|
|
536
|
+
*
|
|
537
|
+
* DESIGN:
|
|
538
|
+
* - Use transactions to batch multiple moves
|
|
539
|
+
* - Only affect clips on the same track
|
|
540
|
+
* - Preserve Phase 1 collision rules
|
|
541
|
+
* - Pure functions - no mutations
|
|
542
|
+
*/
|
|
543
|
+
|
|
544
|
+
type Frame = TimelineFrame;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Ripple delete - delete clip and shift all subsequent clips left
|
|
548
|
+
*
|
|
549
|
+
* @param state - Timeline state
|
|
550
|
+
* @param clipId - Clip ID to delete
|
|
551
|
+
* @returns New state with clip deleted and subsequent clips shifted
|
|
552
|
+
*/
|
|
553
|
+
declare function rippleDelete(state: TimelineState, clipId: string): TimelineState;
|
|
554
|
+
/**
|
|
555
|
+
* Ripple trim - trim clip end and shift all subsequent clips
|
|
556
|
+
*
|
|
557
|
+
* @param state - Timeline state
|
|
558
|
+
* @param clipId - Clip ID to trim
|
|
559
|
+
* @param newEnd - New end frame for the clip
|
|
560
|
+
* @returns New state with clip trimmed and subsequent clips shifted
|
|
561
|
+
*/
|
|
562
|
+
declare function rippleTrim(state: TimelineState, clipId: string, newEnd: Frame): TimelineState;
|
|
563
|
+
/**
|
|
564
|
+
* Insert edit - insert clip and shift all subsequent clips right
|
|
565
|
+
*
|
|
566
|
+
* @param state - Timeline state
|
|
567
|
+
* @param trackId - Track ID to insert into
|
|
568
|
+
* @param clip - Clip to insert
|
|
569
|
+
* @param atFrame - Frame to insert at
|
|
570
|
+
* @returns New state with clip inserted and subsequent clips shifted
|
|
571
|
+
*/
|
|
572
|
+
declare function insertEdit(state: TimelineState, trackId: string, clip: Clip, atFrame: Frame): TimelineState;
|
|
573
|
+
/**
|
|
574
|
+
* Ripple move - move clip to new position with automatic gap/shift handling
|
|
575
|
+
*
|
|
576
|
+
* SEMANTICS (based on test contract):
|
|
577
|
+
*
|
|
578
|
+
* Moving RIGHT (newStart > originalStart):
|
|
579
|
+
* - Leaves gap at source
|
|
580
|
+
* - All clips at/after originalEnd shift RIGHT by clipDuration
|
|
581
|
+
* - Target clip moves to newStart
|
|
582
|
+
*
|
|
583
|
+
* Moving LEFT (newStart < originalStart):
|
|
584
|
+
* - Closes gap at source
|
|
585
|
+
* - All clips at/after originalEnd shift LEFT by clipDuration
|
|
586
|
+
* - Target clip moves to newStart
|
|
587
|
+
*
|
|
588
|
+
* @param state - Timeline state
|
|
589
|
+
* @param clipId - Clip ID to move
|
|
590
|
+
* @param newStart - New start frame for the clip
|
|
591
|
+
* @returns New state with clip moved and surrounding clips adjusted
|
|
592
|
+
*/
|
|
593
|
+
declare function rippleMove(state: TimelineState, clipId: string, newStart: Frame): TimelineState;
|
|
594
|
+
/**
|
|
595
|
+
* Insert move - move clip to new position and shift destination clips right
|
|
596
|
+
*
|
|
597
|
+
* This differs from ripple move:
|
|
598
|
+
* - Ripple move: closes gap at source, swaps with intermediate clips
|
|
599
|
+
* - Insert move: leaves gap at source, pushes all destination clips right
|
|
600
|
+
*
|
|
601
|
+
* This is useful for "inserting" a clip into a specific position without
|
|
602
|
+
* affecting the source timeline structure.
|
|
603
|
+
*
|
|
604
|
+
* All operations are atomic via transaction.
|
|
605
|
+
*
|
|
606
|
+
* @param state - Timeline state
|
|
607
|
+
* @param clipId - Clip ID to move
|
|
608
|
+
* @param newStart - New start frame for the clip
|
|
609
|
+
* @returns New state with clip moved and destination clips shifted
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* // Timeline before: [A][B*][C]__[D]
|
|
613
|
+
* // Insert move B to position after D
|
|
614
|
+
* // Timeline after: [A]__[C][D][B*] (gap remains at A)
|
|
615
|
+
*/
|
|
616
|
+
declare function insertMove(state: TimelineState, clipId: string, newStart: Frame): TimelineState;
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* ID GENERATION UTILITIES
|
|
620
|
+
*
|
|
621
|
+
* Simple, deterministic ID generation for timeline entities.
|
|
622
|
+
*
|
|
623
|
+
* WHY SIMPLE IDS?
|
|
624
|
+
* - Easy to debug (readable IDs like "clip_1", "track_2")
|
|
625
|
+
* - Deterministic for testing (can reset counter)
|
|
626
|
+
* - No external dependencies (no UUID library needed)
|
|
627
|
+
*
|
|
628
|
+
* USAGE:
|
|
629
|
+
* ```typescript
|
|
630
|
+
* const clipId = generateClipId(); // "clip_1"
|
|
631
|
+
* const trackId = generateTrackId(); // "track_1"
|
|
632
|
+
*
|
|
633
|
+
* // For testing, you can reset the counter
|
|
634
|
+
* resetIdCounter();
|
|
635
|
+
* ```
|
|
636
|
+
*
|
|
637
|
+
* NOTE: In production, you might want to use UUIDs or other
|
|
638
|
+
* globally unique identifiers. This simple system is sufficient
|
|
639
|
+
* for Phase 1 and makes debugging easier.
|
|
640
|
+
*/
|
|
641
|
+
/**
|
|
642
|
+
* Generate a unique ID with a given prefix
|
|
643
|
+
*
|
|
644
|
+
* @param prefix - Prefix for the ID (e.g., "clip", "track")
|
|
645
|
+
* @returns A unique ID string
|
|
646
|
+
*/
|
|
647
|
+
declare function generateId(prefix: string): string;
|
|
648
|
+
/**
|
|
649
|
+
* Generate a unique clip ID
|
|
650
|
+
*
|
|
651
|
+
* @returns A unique clip ID (e.g., "clip_1")
|
|
652
|
+
*/
|
|
653
|
+
declare function generateClipId(): string;
|
|
654
|
+
/**
|
|
655
|
+
* Generate a unique track ID
|
|
656
|
+
*
|
|
657
|
+
* @returns A unique track ID (e.g., "track_1")
|
|
658
|
+
*/
|
|
659
|
+
declare function generateTrackId(): string;
|
|
660
|
+
/**
|
|
661
|
+
* Generate a unique timeline ID
|
|
662
|
+
*
|
|
663
|
+
* @returns A unique timeline ID (e.g., "timeline_1")
|
|
664
|
+
*/
|
|
665
|
+
declare function generateTimelineId(): string;
|
|
666
|
+
/**
|
|
667
|
+
* Generate a unique asset ID
|
|
668
|
+
*
|
|
669
|
+
* @returns A unique asset ID (e.g., "asset_1")
|
|
670
|
+
*/
|
|
671
|
+
declare function generateAssetId(): string;
|
|
672
|
+
/**
|
|
673
|
+
* Reset the ID counter
|
|
674
|
+
*
|
|
675
|
+
* This is useful for testing to ensure deterministic IDs.
|
|
676
|
+
* DO NOT use this in production code.
|
|
677
|
+
*/
|
|
678
|
+
declare function resetIdCounter(): void;
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* ID GENERATION UTILITIES - PHASE 2
|
|
682
|
+
*
|
|
683
|
+
* Additional ID generators for Phase 2 features.
|
|
684
|
+
*/
|
|
685
|
+
/**
|
|
686
|
+
* Generate a unique link group ID
|
|
687
|
+
*
|
|
688
|
+
* @returns A unique link group ID
|
|
689
|
+
*/
|
|
690
|
+
declare function generateLinkGroupId(): string;
|
|
691
|
+
/**
|
|
692
|
+
* Generate a unique group ID
|
|
693
|
+
*
|
|
694
|
+
* @returns A unique group ID
|
|
695
|
+
*/
|
|
696
|
+
declare function generateGroupId(): string;
|
|
697
|
+
/**
|
|
698
|
+
* Generate a unique marker ID
|
|
699
|
+
*
|
|
700
|
+
* @returns A unique marker ID
|
|
701
|
+
*/
|
|
702
|
+
declare function generateMarkerId(): string;
|
|
703
|
+
|
|
704
|
+
export { Asset, Clip, TimelineFrame as Frame, TimelineFrame, TimelineState, Track, addClip, addTrack, combineResults, findClipById, findTrackById, findTrackIndex, generateAssetId, generateClipId, generateGroupId, generateId, generateLinkGroupId, generateMarkerId, generateTimelineId, generateTrackId, getAllAssets, getAllClips, getAllTracks, getAsset, getClipsAtFrame, getClipsInRange, getClipsOnTrack, hasAsset, insertEdit, insertMove, invalidResult, invalidResults, moveClip, moveClipToTrack, moveTrack, registerAsset, removeClip, removeTrack, resetIdCounter, resizeClip, rippleDelete, rippleMove, rippleTrim, setTimelineDuration, setTimelineName, toggleTrackLock, toggleTrackMute, trimClip, unregisterAsset, updateClip, updateTrack, validResult, validateClip, validateNoOverlap, validateTimeline, validateTrack };
|