@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.
Files changed (77) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +162 -0
  4. package/dist/chunk-27XCNVPR.js +5969 -0
  5. package/dist/chunk-6PDBJDHM.js +2263 -0
  6. package/dist/chunk-BWPS6NQT.js +7465 -0
  7. package/dist/chunk-FBOYSUYV.js +1280 -0
  8. package/dist/chunk-FR632TZX.js +1870 -0
  9. package/dist/chunk-HW4Z7YLJ.js +1242 -0
  10. package/dist/chunk-HWW62IFH.js +5424 -0
  11. package/dist/chunk-I2GZXRH4.js +4790 -0
  12. package/dist/chunk-JQZE3OK4.js +1255 -0
  13. package/dist/chunk-KF7JNK2F.js +1864 -0
  14. package/dist/chunk-KR3P2DYK.js +5655 -0
  15. package/dist/chunk-MO5DSFSW.js +2214 -0
  16. package/dist/chunk-MQAW33RJ.js +5530 -0
  17. package/dist/chunk-N4WUWZZX.js +2833 -0
  18. package/dist/chunk-NRJV7I4C.js +1331 -0
  19. package/dist/chunk-NXG52532.js +2230 -0
  20. package/dist/chunk-PVXF67CN.js +1278 -0
  21. package/dist/chunk-QSB6DHIF.js +5429 -0
  22. package/dist/chunk-QYWJT7HR.js +5837 -0
  23. package/dist/chunk-SWBRCMW7.js +7466 -0
  24. package/dist/chunk-TAT3ULSV.js +2214 -0
  25. package/dist/chunk-TTDP5JUM.js +2228 -0
  26. package/dist/chunk-UAGP4VPG.js +1739 -0
  27. package/dist/chunk-WIG6SY7A.js +1183 -0
  28. package/dist/chunk-YJ2K5N2R.js +6187 -0
  29. package/dist/index-3Lr_vKBd.d.cts +2810 -0
  30. package/dist/index-3Lr_vKBd.d.ts +2810 -0
  31. package/dist/index-7IPJn1yM.d.cts +1146 -0
  32. package/dist/index-7IPJn1yM.d.ts +1146 -0
  33. package/dist/index-B0xOv0V0.d.cts +3259 -0
  34. package/dist/index-B0xOv0V0.d.ts +3259 -0
  35. package/dist/index-B2m3zwg7.d.cts +1381 -0
  36. package/dist/index-B2m3zwg7.d.ts +1381 -0
  37. package/dist/index-B3sUrU_X.d.cts +1249 -0
  38. package/dist/index-B3sUrU_X.d.ts +1249 -0
  39. package/dist/index-B6wla7ZJ.d.cts +2751 -0
  40. package/dist/index-B6wla7ZJ.d.ts +2751 -0
  41. package/dist/index-BIv8RWWT.d.cts +1574 -0
  42. package/dist/index-BIv8RWWT.d.ts +1574 -0
  43. package/dist/index-BJv6hDHL.d.cts +3255 -0
  44. package/dist/index-BJv6hDHL.d.ts +3255 -0
  45. package/dist/index-BUCimS2e.d.cts +1393 -0
  46. package/dist/index-BUCimS2e.d.ts +1393 -0
  47. package/dist/index-Bw_nvNcG.d.cts +1275 -0
  48. package/dist/index-Bw_nvNcG.d.ts +1275 -0
  49. package/dist/index-ByG0gOtd.d.cts +1167 -0
  50. package/dist/index-ByG0gOtd.d.ts +1167 -0
  51. package/dist/index-CDGd2XXv.d.cts +2492 -0
  52. package/dist/index-CDGd2XXv.d.ts +2492 -0
  53. package/dist/index-CznAVeJ6.d.cts +1145 -0
  54. package/dist/index-CznAVeJ6.d.ts +1145 -0
  55. package/dist/index-DQD9IMh7.d.cts +2534 -0
  56. package/dist/index-DQD9IMh7.d.ts +2534 -0
  57. package/dist/index-Dl3qtJEI.d.cts +2178 -0
  58. package/dist/index-Dl3qtJEI.d.ts +2178 -0
  59. package/dist/index-DnE2A-Nz.d.cts +2603 -0
  60. package/dist/index-DnE2A-Nz.d.ts +2603 -0
  61. package/dist/index-DrOA6QmW.d.cts +2492 -0
  62. package/dist/index-DrOA6QmW.d.ts +2492 -0
  63. package/dist/index-Vpa3rPEM.d.cts +1402 -0
  64. package/dist/index-Vpa3rPEM.d.ts +1402 -0
  65. package/dist/index-jP6BomSd.d.cts +2640 -0
  66. package/dist/index-jP6BomSd.d.ts +2640 -0
  67. package/dist/index-wiGRwVyY.d.cts +3259 -0
  68. package/dist/index-wiGRwVyY.d.ts +3259 -0
  69. package/dist/index.cjs +7386 -0
  70. package/dist/index.d.cts +1 -0
  71. package/dist/index.d.ts +1 -0
  72. package/dist/index.js +263 -0
  73. package/dist/internal.cjs +7721 -0
  74. package/dist/internal.d.cts +704 -0
  75. package/dist/internal.d.ts +704 -0
  76. package/dist/internal.js +405 -0
  77. 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 };