@video-editor/editor-core 1.0.0-beta.1 → 1.0.0-beta.2
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/dist/index.d.ts +421 -1
- package/dist/index.js +642 -69
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,144 @@
|
|
|
1
|
+
import { AssetReference } from '@video-editor/protocol';
|
|
2
|
+
import { AssetReferenceTarget } from '@video-editor/protocol';
|
|
1
3
|
import { ComputedRef } from '@vue/reactivity';
|
|
2
4
|
import { createVideoProtocolManager } from '@video-editor/protocol';
|
|
3
5
|
import { DeepReadonly } from '@vue/reactivity';
|
|
6
|
+
import { IKeyframeEasing } from '@video-editor/shared';
|
|
7
|
+
import { IKeyframeProperty } from '@video-editor/shared';
|
|
4
8
|
import { ITrackType } from '@video-editor/shared';
|
|
5
9
|
import { IVideoProtocol } from '@video-editor/shared';
|
|
10
|
+
import { OperationLogMeta } from '@video-editor/protocol';
|
|
6
11
|
import { SegmentUnion } from '@video-editor/shared';
|
|
7
12
|
import { TrackUnion } from '@video-editor/shared';
|
|
8
13
|
|
|
9
14
|
/** Result payload returned by addSegment. */
|
|
10
15
|
export declare type AddSegmentResult = ReturnType<ProtocolManager['addSegment']>;
|
|
11
16
|
|
|
17
|
+
/** Input and result types for track structure commands. */
|
|
18
|
+
export declare type AddTrackOptions = Parameters<ProtocolManager['addTrack']>[0];
|
|
19
|
+
|
|
20
|
+
export declare type AddTrackResult = ReturnType<ProtocolManager['addTrack']>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The single commands a batch is built from. Taken as a parameter rather than
|
|
24
|
+
* read off the finished command object so this module cannot accidentally reach
|
|
25
|
+
* for anything else.
|
|
26
|
+
*/
|
|
27
|
+
declare interface BatchDeps {
|
|
28
|
+
transaction: EditorCoreCommands['transaction'];
|
|
29
|
+
moveSegment: EditorCoreCommands['moveSegment'];
|
|
30
|
+
removeSegment: EditorCoreCommands['removeSegment'];
|
|
31
|
+
duplicateSegment: EditorCoreCommands['duplicateSegment'];
|
|
32
|
+
updateSegment: EditorCoreCommands['updateSegment'];
|
|
33
|
+
getSegment: EditorCoreSelectors['getSegment'];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Outcome of a batch command.
|
|
38
|
+
*
|
|
39
|
+
* A batch is atomic: either every step landed and `success` is true, or nothing
|
|
40
|
+
* did and `error` says which step refused. The resulting protocol is read from
|
|
41
|
+
* `editor.state`, which is reactive — the batch reports what it operated on, not
|
|
42
|
+
* a snapshot that later steps in the same transaction may already have moved.
|
|
43
|
+
*/
|
|
44
|
+
export declare interface BatchResult {
|
|
45
|
+
success: boolean;
|
|
46
|
+
/** Why the batch was rejected. Absent on success. */
|
|
47
|
+
error?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The segments the batch operated on, in call order. For
|
|
50
|
+
* `duplicateSegments` these are the new copies, not the sources.
|
|
51
|
+
*/
|
|
52
|
+
segmentIds: string[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export declare function checkKeyframeCommand(check: KeyframeCommandCheck, getSegment: GetKeyframeSegment): CommandCheckResult;
|
|
56
|
+
|
|
57
|
+
/** The commands `canRun` can answer for, with the arguments each needs. */
|
|
58
|
+
export declare type CommandCheck = {
|
|
59
|
+
command: 'undo';
|
|
60
|
+
} | {
|
|
61
|
+
command: 'redo';
|
|
62
|
+
} | {
|
|
63
|
+
command: 'removeSegment';
|
|
64
|
+
segmentId: string;
|
|
65
|
+
} | {
|
|
66
|
+
command: 'duplicateSegment';
|
|
67
|
+
segmentId: string;
|
|
68
|
+
} | {
|
|
69
|
+
command: 'splitSegment';
|
|
70
|
+
segmentId: string;
|
|
71
|
+
timelineMs: number;
|
|
72
|
+
} | {
|
|
73
|
+
command: 'addTransition';
|
|
74
|
+
} | {
|
|
75
|
+
command: 'setCanvasSize';
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
} | {
|
|
79
|
+
command: 'setFps';
|
|
80
|
+
fps: number;
|
|
81
|
+
} | {
|
|
82
|
+
command: 'addTrack';
|
|
83
|
+
input: AddTrackOptions;
|
|
84
|
+
} | {
|
|
85
|
+
command: 'removeTrack';
|
|
86
|
+
trackId: string;
|
|
87
|
+
} | {
|
|
88
|
+
command: 'moveTrack';
|
|
89
|
+
trackId: string;
|
|
90
|
+
toIndex: number;
|
|
91
|
+
} | {
|
|
92
|
+
command: 'replaceSegmentAsset';
|
|
93
|
+
input: ReplaceSegmentAssetOptions;
|
|
94
|
+
} | KeyframeCommandCheck;
|
|
95
|
+
|
|
96
|
+
export declare interface CommandCheckResult {
|
|
97
|
+
ok: boolean;
|
|
98
|
+
/** Why the command would refuse. Absent when `ok`. */
|
|
99
|
+
reason?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export declare function createBatchCommands(deps: BatchDeps): {
|
|
103
|
+
moveSegments(moves: readonly MoveSegmentOptions[]): BatchResult;
|
|
104
|
+
removeSegments(ids: readonly string[], options?: RemoveSegmentOptions): BatchResult;
|
|
105
|
+
updateSegments(ids: readonly string[], updater: (segment: SegmentUnion) => void): BatchResult;
|
|
106
|
+
duplicateSegments(ids: readonly string[]): BatchResult;
|
|
107
|
+
};
|
|
108
|
+
|
|
12
109
|
export declare function createEditorCore(options: EditorCoreOptions): EditorCore;
|
|
13
110
|
|
|
111
|
+
export declare function createKeyframeCommands(deps: KeyframeCommandDeps): {
|
|
112
|
+
upsertKeyframe(input: UpsertKeyframeOptions): KeyframeCommandResult;
|
|
113
|
+
moveKeyframe(input: MoveKeyframeOptions): KeyframeCommandResult;
|
|
114
|
+
removeKeyframe(input: RemoveKeyframeOptions): KeyframeCommandResult;
|
|
115
|
+
setKeyframeEasing(input: SetKeyframeEasingOptions): KeyframeCommandResult;
|
|
116
|
+
};
|
|
117
|
+
|
|
14
118
|
export declare function createPluginManager(ctx: EditorCoreContext): EditorCorePluginManager;
|
|
15
119
|
|
|
120
|
+
export declare function createProposalManager(deps: ProposalManagerDependencies): EditorProposalManager;
|
|
121
|
+
|
|
16
122
|
export declare function createSegmentRegistry(): SegmentRegistry;
|
|
17
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Read-only queries over the protocol.
|
|
126
|
+
*
|
|
127
|
+
* An agent has to understand the timeline before it can edit it. Without these
|
|
128
|
+
* it would have to parse the whole protocol itself, which means implementing
|
|
129
|
+
* the timeline rules a second time — and the two copies would drift.
|
|
130
|
+
*/
|
|
131
|
+
export declare function createStructuralSelectors(deps: StructuralSelectorDeps): {
|
|
132
|
+
getSegmentsAt: (timeMs: number, options?: SegmentsAtOptions) => SegmentPlacement[];
|
|
133
|
+
getSegmentAt: (trackId: string, timeMs: number) => SegmentUnion | undefined;
|
|
134
|
+
getTrackGaps: (trackId: string) => TrackGap[];
|
|
135
|
+
getAdjacentSegments: (segmentId: string) => SegmentNeighbours;
|
|
136
|
+
getOverlaps: (trackId?: string) => SegmentOverlap[];
|
|
137
|
+
sampleProperty: (segmentId: string, property: IKeyframeProperty, timeMs: number) => SampledProperty | undefined;
|
|
138
|
+
getSelection: () => EditorSelection;
|
|
139
|
+
canRun: (check: CommandCheck) => CommandCheckResult;
|
|
140
|
+
};
|
|
141
|
+
|
|
18
142
|
/** Result payload returned by duplicateSegment. */
|
|
19
143
|
export declare type DuplicateSegmentResult = ReturnType<ProtocolManager['duplicateSegment']>;
|
|
20
144
|
|
|
@@ -28,6 +152,8 @@ export declare interface EditorCore {
|
|
|
28
152
|
commands: EditorCoreCommands;
|
|
29
153
|
/** Read-only selectors. */
|
|
30
154
|
selectors: EditorCoreSelectors;
|
|
155
|
+
/** Isolated agent proposals waiting for review. */
|
|
156
|
+
proposals: EditorProposalManager;
|
|
31
157
|
/** Plugin manager instance. */
|
|
32
158
|
plugins: EditorCorePluginManager;
|
|
33
159
|
/** Segment plugin registry. */
|
|
@@ -60,6 +186,8 @@ export declare interface EditorCoreCommands {
|
|
|
60
186
|
moveSegment: ProtocolManager['moveSegment'];
|
|
61
187
|
/** Resize a segment's time range. */
|
|
62
188
|
resizeSegment: ProtocolManager['resizeSegment'];
|
|
189
|
+
/** Replace a media source with an explicit duration adaptation strategy. */
|
|
190
|
+
replaceSegmentAsset: ProtocolManager['replaceSegmentAsset'];
|
|
63
191
|
/** Split a segment into two at a timeline position (single undo step). */
|
|
64
192
|
splitSegment: ProtocolManager['splitSegment'];
|
|
65
193
|
/** Add a transition at the current time or a specified time. */
|
|
@@ -70,12 +198,61 @@ export declare interface EditorCoreCommands {
|
|
|
70
198
|
updateTransition: ProtocolManager['updateTransition'];
|
|
71
199
|
/** Update a track's mutable presentation fields (hidden / muted / extra). */
|
|
72
200
|
updateTrack: ProtocolManager['updateTrack'];
|
|
201
|
+
/** Add an empty track. */
|
|
202
|
+
addTrack: ProtocolManager['addTrack'];
|
|
203
|
+
/** Remove a track and all of its segments as one undo step. */
|
|
204
|
+
removeTrack: ProtocolManager['removeTrack'];
|
|
205
|
+
/** Move a track to its final zero-based position. */
|
|
206
|
+
moveTrack: ProtocolManager['moveTrack'];
|
|
73
207
|
/** Resize the project canvas as a single undoable step. */
|
|
74
208
|
setCanvasSize: ProtocolManager['setCanvasSize'];
|
|
209
|
+
/** Set the project frame rate as a single undoable step. */
|
|
210
|
+
setFps: ProtocolManager['setFps'];
|
|
211
|
+
/** Insert a keyframe, or update the value at the same property and time. */
|
|
212
|
+
upsertKeyframe: (input: UpsertKeyframeOptions) => KeyframeCommandResult;
|
|
213
|
+
/** Move one keyframe without replacing a frame already at the target time. */
|
|
214
|
+
moveKeyframe: (input: MoveKeyframeOptions) => KeyframeCommandResult;
|
|
215
|
+
/** Remove one keyframe and clean up its empty property track. */
|
|
216
|
+
removeKeyframe: (input: RemoveKeyframeOptions) => KeyframeCommandResult;
|
|
217
|
+
/** Change one keyframe's outgoing easing; omit easing to restore linear. */
|
|
218
|
+
setKeyframeEasing: (input: SetKeyframeEasingOptions) => KeyframeCommandResult;
|
|
75
219
|
/** Replace a track id (useful for migrations). */
|
|
76
220
|
replaceTrackId: ProtocolManager['replaceTrackId'];
|
|
77
221
|
/** Replace a segment id (useful for migrations). */
|
|
78
222
|
replaceSegmentId: ProtocolManager['replaceSegmentId'];
|
|
223
|
+
/**
|
|
224
|
+
* Move several segments as one undo step. Moves are applied in the order
|
|
225
|
+
* given; if any is refused the whole batch is rolled back.
|
|
226
|
+
*/
|
|
227
|
+
moveSegments: (moves: readonly MoveSegmentOptions[]) => BatchResult;
|
|
228
|
+
/**
|
|
229
|
+
* Remove several segments as one undo step. Later segments are removed first,
|
|
230
|
+
* since a ripple delete shifts the ones after it left.
|
|
231
|
+
*/
|
|
232
|
+
removeSegments: (ids: readonly string[], options?: RemoveSegmentOptions) => BatchResult;
|
|
233
|
+
/**
|
|
234
|
+
* Apply the same edit to several segments as one undo step — the entry point
|
|
235
|
+
* for adjusting a property across a multi-selection. An edit the protocol
|
|
236
|
+
* rejects fails the whole batch rather than being silently skipped.
|
|
237
|
+
*/
|
|
238
|
+
updateSegments: (ids: readonly string[], updater: (segment: SegmentUnion) => void) => BatchResult;
|
|
239
|
+
/** Duplicate several segments as one undo step; reports the new ids. */
|
|
240
|
+
duplicateSegments: (ids: readonly string[]) => BatchResult;
|
|
241
|
+
/**
|
|
242
|
+
* Run a batch of commands as one atomic undo step.
|
|
243
|
+
*
|
|
244
|
+
* Every command inside still updates state immediately, so previews stay
|
|
245
|
+
* live, but only one history item is pushed when the batch commits. If the
|
|
246
|
+
* body throws, the protocol is restored and the error is rethrown; calling
|
|
247
|
+
* `tx.cancel()` discards the batch without touching the undo/redo stacks.
|
|
248
|
+
*/
|
|
249
|
+
transaction: ProtocolManager['transaction'];
|
|
250
|
+
/**
|
|
251
|
+
* Open a transaction that spans multiple events, for continuous interactions
|
|
252
|
+
* such as a canvas or timeline drag. Commit on pointer up, cancel to restore
|
|
253
|
+
* the state captured at pointer down.
|
|
254
|
+
*/
|
|
255
|
+
beginTransaction: ProtocolManager['beginTransaction'];
|
|
79
256
|
/** Undo the last mutation. */
|
|
80
257
|
undo: ProtocolManager['undo'];
|
|
81
258
|
/** Redo the last undone mutation. */
|
|
@@ -103,10 +280,11 @@ export declare interface EditorCoreContext {
|
|
|
103
280
|
export declare interface EditorCoreOptions {
|
|
104
281
|
/** Initial protocol snapshot. */
|
|
105
282
|
protocol: IVideoProtocol;
|
|
106
|
-
/** Optional id generators for segments
|
|
283
|
+
/** Optional id generators for segments, tracks and proposals. */
|
|
107
284
|
idFactory?: {
|
|
108
285
|
segment?: () => string;
|
|
109
286
|
track?: () => string;
|
|
287
|
+
proposal?: () => string;
|
|
110
288
|
};
|
|
111
289
|
/** Optional shared services (resource manager, renderer, etc). */
|
|
112
290
|
services?: EditorCoreServices;
|
|
@@ -164,6 +342,37 @@ export declare interface EditorCoreSelectors {
|
|
|
164
342
|
getTrackBySegmentId: (segmentId: string) => DeepReadonly<TrackUnion> | undefined;
|
|
165
343
|
/** List tracks, optionally filtered by type. */
|
|
166
344
|
getTracks: (trackType?: ITrackType) => DeepReadonly<TrackUnion>[];
|
|
345
|
+
/**
|
|
346
|
+
* Every segment playing at `timeMs`, in track order — the answer to "what is
|
|
347
|
+
* on screen right now". Segment ranges are half-open, so a segment ending at
|
|
348
|
+
* `timeMs` and the one starting there are never both returned.
|
|
349
|
+
*/
|
|
350
|
+
getSegmentsAt: (timeMs: number, options?: SegmentsAtOptions) => SegmentPlacement[];
|
|
351
|
+
/** The segment playing on one track at `timeMs`. */
|
|
352
|
+
getSegmentAt: (trackId: string, timeMs: number) => SegmentUnion | undefined;
|
|
353
|
+
/**
|
|
354
|
+
* Bounded empty stretches on a track, in order. The open range after the last
|
|
355
|
+
* segment is not a gap — nothing bounds it.
|
|
356
|
+
*/
|
|
357
|
+
getTrackGaps: (trackId: string) => TrackGap[];
|
|
358
|
+
/** The segments either side of one, on its own track. */
|
|
359
|
+
getAdjacentSegments: (segmentId: string) => SegmentNeighbours;
|
|
360
|
+
/** Segments of one track (or every track) that share time, which is invalid. */
|
|
361
|
+
getOverlaps: (trackId?: string) => SegmentOverlap[];
|
|
362
|
+
/**
|
|
363
|
+
* A property's effective value at a moment, and whether it came from a
|
|
364
|
+
* keyframe, an interpolation between two, the segment's static field, or the
|
|
365
|
+
* documented default. Uses the same pure sampler as the renderer and export.
|
|
366
|
+
*/
|
|
367
|
+
sampleProperty: (segmentId: string, property: IKeyframeProperty, timeMs: number) => SampledProperty | undefined;
|
|
368
|
+
/** The current selection, resolved against the protocol. */
|
|
369
|
+
getSelection: () => EditorSelection;
|
|
370
|
+
/** Find every segment in this protocol that uses a library asset. */
|
|
371
|
+
getAssetReferences: (asset: AssetReferenceTarget) => AssetReference[];
|
|
372
|
+
/** Semantic history entries without internal Immer patches. */
|
|
373
|
+
getOperationLog: () => ProtocolManager['operationLog']['value'];
|
|
374
|
+
/** Whether a command would do anything right now, and why not when it would not. */
|
|
375
|
+
canRun: (check: CommandCheck) => CommandCheckResult;
|
|
167
376
|
}
|
|
168
377
|
|
|
169
378
|
/**
|
|
@@ -198,26 +407,195 @@ export declare interface EditorCoreState {
|
|
|
198
407
|
undoCount: ProtocolManager['undoCount'];
|
|
199
408
|
/** Redo stack size. */
|
|
200
409
|
redoCount: ProtocolManager['redoCount'];
|
|
410
|
+
/** Semantic descriptions of the currently reachable history branch. */
|
|
411
|
+
operationLog: ProtocolManager['operationLog'];
|
|
412
|
+
/** Monotonic committed-state version used for proposal conflict checks. */
|
|
413
|
+
revision: ProtocolManager['revision'];
|
|
414
|
+
/** Whether a history transaction is currently open. */
|
|
415
|
+
isTransactionActive: ProtocolManager['isTransactionActive'];
|
|
416
|
+
/** Nesting depth of the open transaction; 0 when none is open. */
|
|
417
|
+
transactionDepth: ProtocolManager['transactionDepth'];
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/** A valid protocol preview produced without changing the main editor. */
|
|
421
|
+
export declare interface EditorProposal {
|
|
422
|
+
id: string;
|
|
423
|
+
baseRevision: number;
|
|
424
|
+
previewProtocol: IVideoProtocol;
|
|
425
|
+
validation: {
|
|
426
|
+
valid: true;
|
|
427
|
+
};
|
|
428
|
+
operations: readonly OperationLogMeta[];
|
|
429
|
+
summary: ProposalChangeSummary;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export declare interface EditorProposalManager {
|
|
433
|
+
/** Run commands against an isolated copy and keep the resulting preview for review. */
|
|
434
|
+
create: (build: (editor: EditorCore) => void, options?: {
|
|
435
|
+
id?: string;
|
|
436
|
+
}) => ProposalActionResult;
|
|
437
|
+
/** Apply the whole proposal as one history item if its base revision is current. */
|
|
438
|
+
accept: (id: string) => ProposalActionResult;
|
|
439
|
+
/** Discard a proposal without touching protocol history. */
|
|
440
|
+
reject: (id: string) => ProposalActionResult;
|
|
441
|
+
get: (id: string) => EditorProposal | undefined;
|
|
442
|
+
list: () => EditorProposal[];
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export declare interface EditorSelection {
|
|
446
|
+
segmentId?: string;
|
|
447
|
+
segment?: SegmentUnion;
|
|
448
|
+
trackId?: string;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
declare type GetKeyframeSegment = (segmentId: string) => ReadableKeyframeSegment | undefined;
|
|
452
|
+
|
|
453
|
+
export declare type KeyframeCommandCheck = {
|
|
454
|
+
command: 'upsertKeyframe';
|
|
455
|
+
input: UpsertKeyframeOptions;
|
|
456
|
+
} | {
|
|
457
|
+
command: 'moveKeyframe';
|
|
458
|
+
input: MoveKeyframeOptions;
|
|
459
|
+
} | {
|
|
460
|
+
command: 'removeKeyframe';
|
|
461
|
+
input: RemoveKeyframeOptions;
|
|
462
|
+
} | {
|
|
463
|
+
command: 'setKeyframeEasing';
|
|
464
|
+
input: SetKeyframeEasingOptions;
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
declare interface KeyframeCommandDeps {
|
|
468
|
+
getSegment: GetKeyframeSegment;
|
|
469
|
+
updateSegment: EditorCoreCommands['updateSegment'];
|
|
470
|
+
transaction: EditorCoreCommands['transaction'];
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export declare interface KeyframeCommandResult {
|
|
474
|
+
success: boolean;
|
|
475
|
+
error?: string;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export declare interface MoveKeyframeOptions {
|
|
479
|
+
segmentId: string;
|
|
480
|
+
property: IKeyframeProperty;
|
|
481
|
+
/** Current segment-relative timeline time in ms. */
|
|
482
|
+
timeMs: number;
|
|
483
|
+
/** New segment-relative timeline time in ms. */
|
|
484
|
+
toTimeMs: number;
|
|
201
485
|
}
|
|
202
486
|
|
|
203
487
|
/** Options for moving a segment between tracks or within a track. */
|
|
204
488
|
export declare type MoveSegmentOptions = Parameters<ProtocolManager['moveSegment']>[0];
|
|
205
489
|
|
|
490
|
+
export declare interface ProposalActionResult {
|
|
491
|
+
success: boolean;
|
|
492
|
+
error?: string;
|
|
493
|
+
proposal?: EditorProposal;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export declare interface ProposalChangeSummary {
|
|
497
|
+
addedTrackIds: string[];
|
|
498
|
+
removedTrackIds: string[];
|
|
499
|
+
changedTrackIds: string[];
|
|
500
|
+
addedSegmentIds: string[];
|
|
501
|
+
removedSegmentIds: string[];
|
|
502
|
+
changedSegmentIds: string[];
|
|
503
|
+
projectFields: Array<'width' | 'height' | 'fps'>;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
declare interface ProposalManagerDependencies {
|
|
507
|
+
getProtocol: () => IVideoProtocol;
|
|
508
|
+
getRevision: () => number;
|
|
509
|
+
isTransactionActive: () => boolean;
|
|
510
|
+
createSandbox: (protocol: IVideoProtocol) => EditorCore;
|
|
511
|
+
applySnapshot: (protocol: IVideoProtocol, proposal: EditorProposal) => 'committed' | 'empty' | 'cancelled' | 'invalid' | 'nested';
|
|
512
|
+
createId: () => string;
|
|
513
|
+
}
|
|
514
|
+
|
|
206
515
|
/** Internal protocol manager type used to align editor-core signatures with protocol behavior. */
|
|
207
516
|
declare type ProtocolManager = ReturnType<typeof createVideoProtocolManager>;
|
|
208
517
|
|
|
518
|
+
declare type ReadableEasing = Exclude<IKeyframeEasing, [number, number, number, number]> | readonly [number, number, number, number];
|
|
519
|
+
|
|
520
|
+
declare interface ReadableKeyframe {
|
|
521
|
+
readonly timeMs: number;
|
|
522
|
+
readonly value: number;
|
|
523
|
+
readonly easing?: ReadableEasing;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
declare interface ReadableKeyframeSegment {
|
|
527
|
+
readonly segmentType: SegmentUnion['segmentType'];
|
|
528
|
+
readonly type?: string;
|
|
529
|
+
readonly startTime: number;
|
|
530
|
+
readonly endTime: number;
|
|
531
|
+
readonly keyframes?: readonly {
|
|
532
|
+
readonly property: IKeyframeProperty;
|
|
533
|
+
readonly frames: readonly ReadableKeyframe[];
|
|
534
|
+
}[];
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export declare interface RemoveKeyframeOptions {
|
|
538
|
+
segmentId: string;
|
|
539
|
+
property: IKeyframeProperty;
|
|
540
|
+
/** Segment-relative timeline time in ms. */
|
|
541
|
+
timeMs: number;
|
|
542
|
+
}
|
|
543
|
+
|
|
209
544
|
/** Optional flags accepted by removeSegment (e.g. ripple delete). */
|
|
210
545
|
export declare type RemoveSegmentOptions = Parameters<ProtocolManager['removeSegment']>[1];
|
|
211
546
|
|
|
547
|
+
/** Input and result types for replacing a segment's media source. */
|
|
548
|
+
export declare type ReplaceSegmentAssetOptions = Parameters<ProtocolManager['replaceSegmentAsset']>[0];
|
|
549
|
+
|
|
550
|
+
export declare type ReplaceSegmentAssetResult = ReturnType<ProtocolManager['replaceSegmentAsset']>;
|
|
551
|
+
|
|
212
552
|
/** Options for resizing a segment on a track. */
|
|
213
553
|
export declare type ResizeSegmentOptions = Parameters<ProtocolManager['resizeSegment']>[0];
|
|
214
554
|
|
|
555
|
+
/**
|
|
556
|
+
* A property's effective value at a moment, and where it came from — a curve,
|
|
557
|
+
* the segment's own field, or the documented fallback. An agent reviewing a
|
|
558
|
+
* value needs to know which, since only an interpolated one is changing here.
|
|
559
|
+
*
|
|
560
|
+
* `keyframe` covers a value read straight off a frame, including one held at
|
|
561
|
+
* either end of the curve; `interpolated` means strictly between two frames.
|
|
562
|
+
*/
|
|
563
|
+
export declare interface SampledProperty {
|
|
564
|
+
value: number;
|
|
565
|
+
source: 'keyframe' | 'interpolated' | 'static' | 'default';
|
|
566
|
+
/** False when the queried time lies outside the segment's own range. */
|
|
567
|
+
withinSegment: boolean;
|
|
568
|
+
}
|
|
569
|
+
|
|
215
570
|
/** Input payload for adding a segment (id is optional). */
|
|
216
571
|
export declare type SegmentInput = Parameters<ProtocolManager['addSegment']>[0];
|
|
217
572
|
|
|
218
573
|
/** Result payload returned by segment mutation commands. */
|
|
219
574
|
export declare type SegmentMutationResult = ReturnType<ProtocolManager['removeSegment']>;
|
|
220
575
|
|
|
576
|
+
export declare interface SegmentNeighbours {
|
|
577
|
+
trackId?: string;
|
|
578
|
+
previous?: SegmentUnion;
|
|
579
|
+
next?: SegmentUnion;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/** Two segments of one track sharing time, which the timeline rules forbid. */
|
|
583
|
+
export declare interface SegmentOverlap {
|
|
584
|
+
trackId: string;
|
|
585
|
+
a: SegmentUnion;
|
|
586
|
+
b: SegmentUnion;
|
|
587
|
+
/** The overlapping stretch itself. */
|
|
588
|
+
startTime: number;
|
|
589
|
+
endTime: number;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/** Where a segment sits: the segment itself plus the track carrying it. */
|
|
593
|
+
export declare interface SegmentPlacement {
|
|
594
|
+
segment: SegmentUnion;
|
|
595
|
+
trackId: string;
|
|
596
|
+
trackType: ITrackType;
|
|
597
|
+
}
|
|
598
|
+
|
|
221
599
|
/**
|
|
222
600
|
* Segment plugin bundle: ops + renderer adapter + optional UI bindings.
|
|
223
601
|
*/
|
|
@@ -264,10 +642,52 @@ export declare interface SegmentRegistry {
|
|
|
264
642
|
list: () => SegmentPlugin[];
|
|
265
643
|
}
|
|
266
644
|
|
|
645
|
+
export declare interface SegmentsAtOptions {
|
|
646
|
+
/** Only look at tracks of this type. */
|
|
647
|
+
trackType?: ITrackType;
|
|
648
|
+
/** Pass `false` to skip hidden tracks — what is actually on screen. */
|
|
649
|
+
includeHidden?: boolean;
|
|
650
|
+
}
|
|
651
|
+
|
|
267
652
|
/** Result payload returned by setCanvasSize. */
|
|
268
653
|
export declare type SetCanvasSizeResult = ReturnType<ProtocolManager['setCanvasSize']>;
|
|
269
654
|
|
|
655
|
+
/** Result payload returned by setFps. */
|
|
656
|
+
export declare type SetFpsResult = ReturnType<ProtocolManager['setFps']>;
|
|
657
|
+
|
|
658
|
+
export declare interface SetKeyframeEasingOptions extends RemoveKeyframeOptions {
|
|
659
|
+
/** Omit to restore linear easing. */
|
|
660
|
+
easing?: IKeyframeEasing;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
declare interface StructuralSelectorDeps {
|
|
664
|
+
protocol: () => IVideoProtocol;
|
|
665
|
+
selectedSegmentId: () => string | undefined;
|
|
666
|
+
undoCount: () => number;
|
|
667
|
+
redoCount: () => number;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export declare function summarizeProposal(before: IVideoProtocol, after: IVideoProtocol): ProposalChangeSummary;
|
|
671
|
+
|
|
672
|
+
/** A bounded stretch of empty time on a track. */
|
|
673
|
+
export declare interface TrackGap {
|
|
674
|
+
startTime: number;
|
|
675
|
+
endTime: number;
|
|
676
|
+
}
|
|
677
|
+
|
|
270
678
|
/** The mutable track fields exposed to an updateTrack updater. */
|
|
271
679
|
export declare type TrackMutableFields = Parameters<Parameters<ProtocolManager['updateTrack']>[1]>[0];
|
|
272
680
|
|
|
681
|
+
export declare type TrackStructureResult = ReturnType<ProtocolManager['removeTrack']>;
|
|
682
|
+
|
|
683
|
+
export declare interface UpsertKeyframeOptions {
|
|
684
|
+
segmentId: string;
|
|
685
|
+
property: IKeyframeProperty;
|
|
686
|
+
/** Segment-relative timeline time in ms. */
|
|
687
|
+
timeMs: number;
|
|
688
|
+
value: number;
|
|
689
|
+
/** When omitted, an existing frame keeps its easing. */
|
|
690
|
+
easing?: IKeyframeEasing;
|
|
691
|
+
}
|
|
692
|
+
|
|
273
693
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,74 +1,603 @@
|
|
|
1
|
-
import { createVideoProtocolManager as
|
|
2
|
-
import { computed as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { MIN_FPS as R, MIN_CANVAS_SIZE as L, MAX_CANVAS_SIZE as j, createVideoProtocolManager as Q, findAssetReferences as W } from "@video-editor/protocol";
|
|
2
|
+
import { computed as O } from "@vue/reactivity";
|
|
3
|
+
import { isVideoFramesSegment as ee, isAudioSegment as te, sampleKeyframes as re } from "@video-editor/shared";
|
|
4
|
+
function K(t) {
|
|
5
|
+
return { success: !0, segmentIds: t };
|
|
6
|
+
}
|
|
7
|
+
function _(t) {
|
|
8
|
+
return { success: !1, error: t, segmentIds: [] };
|
|
9
|
+
}
|
|
10
|
+
function P(t) {
|
|
11
|
+
return [...new Set(t)];
|
|
12
|
+
}
|
|
13
|
+
function ne(t) {
|
|
14
|
+
const { transaction: e, getSegment: n } = t;
|
|
15
|
+
function i(r, s, c) {
|
|
16
|
+
let p = _(`${r}: nothing ran`);
|
|
17
|
+
return e((v) => {
|
|
18
|
+
const f = c();
|
|
19
|
+
if (typeof f == "string") {
|
|
20
|
+
p = _(f), v.cancel();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
p = K(f);
|
|
24
|
+
}, { label: r, data: s }), p;
|
|
25
|
+
}
|
|
26
|
+
function a(r, s) {
|
|
27
|
+
const c = [];
|
|
28
|
+
for (const p of r) {
|
|
29
|
+
const v = n(p);
|
|
30
|
+
if (!v)
|
|
31
|
+
return `${s}: no segment with id ${p}`;
|
|
32
|
+
c.push({ id: v.id, startTime: v.startTime });
|
|
33
|
+
}
|
|
34
|
+
return c;
|
|
35
|
+
}
|
|
6
36
|
return {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
37
|
+
moveSegments(r) {
|
|
38
|
+
return r.length ? i("move-segments", { moves: r.map((s) => ({ ...s })) }, () => {
|
|
39
|
+
const s = [];
|
|
40
|
+
for (const c of r) {
|
|
41
|
+
if (!t.moveSegment(c).success)
|
|
42
|
+
return `move-segments: could not move ${c.segmentId}`;
|
|
43
|
+
s.push(c.segmentId);
|
|
44
|
+
}
|
|
45
|
+
return s;
|
|
46
|
+
}) : K([]);
|
|
47
|
+
},
|
|
48
|
+
removeSegments(r, s) {
|
|
49
|
+
const c = P(r);
|
|
50
|
+
return c.length ? i("remove-segments", { segmentIds: c, ripple: s?.ripple === !0 }, () => {
|
|
51
|
+
const p = a(c, "remove-segments");
|
|
52
|
+
if (typeof p == "string")
|
|
53
|
+
return p;
|
|
54
|
+
const v = p.map((f, k) => ({ segment: f, index: k })).sort((f, k) => k.segment.startTime - f.segment.startTime || k.index - f.index);
|
|
55
|
+
for (const { segment: f } of v)
|
|
56
|
+
if (!t.removeSegment(f.id, s).success)
|
|
57
|
+
return `remove-segments: could not remove ${f.id}`;
|
|
58
|
+
return c;
|
|
59
|
+
}) : K([]);
|
|
60
|
+
},
|
|
61
|
+
updateSegments(r, s) {
|
|
62
|
+
const c = P(r);
|
|
63
|
+
return c.length ? i("update-segments", { segmentIds: c }, () => {
|
|
64
|
+
const p = a(c, "update-segments");
|
|
65
|
+
if (typeof p == "string")
|
|
66
|
+
return p;
|
|
67
|
+
for (const v of c)
|
|
68
|
+
if (!t.updateSegment(s, v))
|
|
69
|
+
return `update-segments: rejected the edit to ${v}`;
|
|
70
|
+
return c;
|
|
71
|
+
}) : K([]);
|
|
72
|
+
},
|
|
73
|
+
duplicateSegments(r) {
|
|
74
|
+
const s = P(r);
|
|
75
|
+
return s.length ? i("duplicate-segments", { segmentIds: s }, () => {
|
|
76
|
+
const c = a(s, "duplicate-segments");
|
|
77
|
+
if (typeof c == "string")
|
|
78
|
+
return c;
|
|
79
|
+
const p = [];
|
|
80
|
+
for (const v of s) {
|
|
81
|
+
const f = t.duplicateSegment(v);
|
|
82
|
+
if (!f.success)
|
|
83
|
+
return `duplicate-segments: could not duplicate ${v}`;
|
|
84
|
+
p.push(f.id);
|
|
85
|
+
}
|
|
86
|
+
return p;
|
|
87
|
+
}) : K([]);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const se = /* @__PURE__ */ new Set(["linear", "easeIn", "easeOut", "easeInOut"]), oe = {
|
|
92
|
+
moveKeyframe: "move-keyframe",
|
|
93
|
+
removeKeyframe: "remove-keyframe",
|
|
94
|
+
setKeyframeEasing: "set-keyframe-easing",
|
|
95
|
+
upsertKeyframe: "upsert-keyframe"
|
|
96
|
+
};
|
|
97
|
+
function T(t) {
|
|
98
|
+
return { ok: !1, reason: t };
|
|
99
|
+
}
|
|
100
|
+
function q(t) {
|
|
101
|
+
return t === void 0 ? !0 : typeof t == "string" ? se.has(t) : t.length === 4 && t.every(Number.isFinite);
|
|
102
|
+
}
|
|
103
|
+
function z(t, e) {
|
|
104
|
+
return t === e ? !0 : !Array.isArray(t) || !Array.isArray(e) ? !1 : t.every((n, i) => n === e[i]);
|
|
105
|
+
}
|
|
106
|
+
function E(t) {
|
|
107
|
+
return Array.isArray(t) ? [...t] : t;
|
|
108
|
+
}
|
|
109
|
+
function ae(t, e) {
|
|
110
|
+
return e === "opacity" ? t.segmentType === "frames" || t.segmentType === "text" : e === "volume" ? t.segmentType === "audio" || t.segmentType === "frames" && t.type === "video" : e === "intensity" ? t.segmentType === "filter" : t.segmentType === "frames" || t.segmentType === "text" || t.segmentType === "sticker";
|
|
111
|
+
}
|
|
112
|
+
function D(t, e, n) {
|
|
113
|
+
return t.keyframes?.find((a) => a.property === e)?.frames.find((a) => a.timeMs === n);
|
|
114
|
+
}
|
|
115
|
+
function V(t, e) {
|
|
116
|
+
const n = t(e.segmentId);
|
|
117
|
+
if (!n)
|
|
118
|
+
return T(`no segment with id ${e.segmentId}`);
|
|
119
|
+
if (!ae(n, e.property))
|
|
120
|
+
return T(`${e.property} keyframes are not supported by this segment`);
|
|
121
|
+
if (!Number.isFinite(e.timeMs))
|
|
122
|
+
return T("keyframe time must be a finite number");
|
|
123
|
+
const i = n.endTime - n.startTime;
|
|
124
|
+
return e.timeMs < 0 || e.timeMs > i ? T(`keyframe time must be between 0 and ${i}`) : { ok: !0 };
|
|
125
|
+
}
|
|
126
|
+
function Y(t, e) {
|
|
127
|
+
const n = V(e, t.input);
|
|
128
|
+
if (!n.ok)
|
|
129
|
+
return n;
|
|
130
|
+
const i = e(t.input.segmentId), a = D(i, t.input.property, t.input.timeMs);
|
|
131
|
+
switch (t.command) {
|
|
132
|
+
case "upsertKeyframe": {
|
|
133
|
+
const { input: r } = t;
|
|
134
|
+
return Number.isFinite(r.value) ? q(r.easing) ? a && a.value === r.value && (r.easing === void 0 || z(a.easing, r.easing)) ? T("keyframe already has the requested value") : { ok: !0 } : T("keyframe easing is invalid") : T("keyframe value must be a finite number");
|
|
135
|
+
}
|
|
136
|
+
case "moveKeyframe": {
|
|
137
|
+
const { input: r } = t;
|
|
138
|
+
if (!a)
|
|
139
|
+
return T(`no ${r.property} keyframe at ${r.timeMs}`);
|
|
140
|
+
const s = V(e, { ...r, timeMs: r.toTimeMs });
|
|
141
|
+
return s.ok ? r.toTimeMs === r.timeMs ? T("keyframe is already at the requested time") : D(i, r.property, r.toTimeMs) ? T(`a ${r.property} keyframe already exists at ${r.toTimeMs}`) : { ok: !0 } : s;
|
|
142
|
+
}
|
|
143
|
+
case "removeKeyframe": {
|
|
144
|
+
const { input: r } = t;
|
|
145
|
+
return a ? { ok: !0 } : T(`no ${r.property} keyframe at ${r.timeMs}`);
|
|
146
|
+
}
|
|
147
|
+
case "setKeyframeEasing": {
|
|
148
|
+
const { input: r } = t;
|
|
149
|
+
return a ? q(r.easing) ? z(a.easing, r.easing) ? T("keyframe already has the requested easing") : { ok: !0 } : T("keyframe easing is invalid") : T(`no ${r.property} keyframe at ${r.timeMs}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function ie(t) {
|
|
154
|
+
function e(n, i) {
|
|
155
|
+
const a = Y(n, t.getSegment);
|
|
156
|
+
return a.ok ? t.transaction(() => t.updateSegment(i, n.input.segmentId) ? { success: !0 } : { success: !1, error: "the protocol rejected the keyframe edit" }, {
|
|
157
|
+
label: oe[n.command],
|
|
158
|
+
data: { ...n.input }
|
|
159
|
+
}).value : { success: !1, error: a.reason };
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
upsertKeyframe(n) {
|
|
163
|
+
return e({ command: "upsertKeyframe", input: n }, (i) => {
|
|
164
|
+
const a = i.keyframes ?? (i.keyframes = []);
|
|
165
|
+
let r = a.find((c) => c.property === n.property);
|
|
166
|
+
r || (r = { property: n.property, frames: [] }, a.push(r));
|
|
167
|
+
const s = r.frames.find((c) => c.timeMs === n.timeMs);
|
|
168
|
+
s ? (s.value = n.value, n.easing !== void 0 && (s.easing = E(n.easing))) : (r.frames.push({
|
|
169
|
+
timeMs: n.timeMs,
|
|
170
|
+
value: n.value,
|
|
171
|
+
...n.easing === void 0 ? {} : { easing: E(n.easing) }
|
|
172
|
+
}), r.frames.sort((c, p) => c.timeMs - p.timeMs));
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
moveKeyframe(n) {
|
|
176
|
+
return e({ command: "moveKeyframe", input: n }, (i) => {
|
|
177
|
+
const a = i.keyframes.find((s) => s.property === n.property), r = a.frames.find((s) => s.timeMs === n.timeMs);
|
|
178
|
+
r.timeMs = n.toTimeMs, a.frames.sort((s, c) => s.timeMs - c.timeMs);
|
|
179
|
+
});
|
|
180
|
+
},
|
|
181
|
+
removeKeyframe(n) {
|
|
182
|
+
return e({ command: "removeKeyframe", input: n }, (i) => {
|
|
183
|
+
const a = i.keyframes, r = a.findIndex((p) => p.property === n.property), s = a[r], c = s.frames.findIndex((p) => p.timeMs === n.timeMs);
|
|
184
|
+
s.frames.splice(c, 1), s.frames.length || a.splice(r, 1), a.length || delete i.keyframes;
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
setKeyframeEasing(n) {
|
|
188
|
+
return e({ command: "setKeyframeEasing", input: n }, (i) => {
|
|
189
|
+
const r = i.keyframes.find((s) => s.property === n.property).frames.find((s) => s.timeMs === n.timeMs);
|
|
190
|
+
n.easing === void 0 ? delete r.easing : r.easing = E(n.easing);
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function ce(t) {
|
|
196
|
+
const e = [], n = /* @__PURE__ */ new Map();
|
|
197
|
+
let i = !1;
|
|
198
|
+
return {
|
|
199
|
+
register: async (f, k) => {
|
|
200
|
+
const w = f(t), { name: S } = w;
|
|
201
|
+
if (n.has(S)) {
|
|
202
|
+
if (!k?.override)
|
|
203
|
+
throw new Error(`Plugin ${S} has been registered`);
|
|
204
|
+
await n.get(S)?.destroy?.();
|
|
205
|
+
const g = e.findIndex((u) => u.name === S);
|
|
206
|
+
g >= 0 && e.splice(g, 1), n.delete(S);
|
|
15
207
|
}
|
|
16
|
-
e.push(
|
|
208
|
+
e.push(w), n.set(S, w), (k?.autoInit || i) && await w.init?.();
|
|
17
209
|
},
|
|
18
210
|
init: async () => {
|
|
19
|
-
for (const
|
|
20
|
-
await
|
|
21
|
-
|
|
211
|
+
for (const f of e)
|
|
212
|
+
await f.init?.();
|
|
213
|
+
i = !0;
|
|
22
214
|
},
|
|
23
|
-
get: (
|
|
24
|
-
has: (
|
|
25
|
-
remove: async (
|
|
26
|
-
const
|
|
27
|
-
return
|
|
215
|
+
get: (f) => n.get(f),
|
|
216
|
+
has: (f) => n.has(f),
|
|
217
|
+
remove: async (f) => {
|
|
218
|
+
const k = e.findIndex((S) => S.name === f);
|
|
219
|
+
return k === -1 ? !1 : (await e[k].destroy?.(), e.splice(k, 1), n.delete(f));
|
|
28
220
|
},
|
|
29
221
|
destroy: async () => {
|
|
30
|
-
for (const
|
|
31
|
-
await
|
|
32
|
-
e.length = 0,
|
|
222
|
+
for (const f of e)
|
|
223
|
+
await f.destroy?.();
|
|
224
|
+
e.length = 0, n.clear(), i = !1;
|
|
33
225
|
}
|
|
34
226
|
};
|
|
35
227
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
228
|
+
function Z(t, e) {
|
|
229
|
+
return JSON.stringify(t) === JSON.stringify(e);
|
|
230
|
+
}
|
|
231
|
+
function B(t) {
|
|
232
|
+
const e = /* @__PURE__ */ new Map();
|
|
233
|
+
for (const n of t.tracks)
|
|
234
|
+
for (const i of n.children)
|
|
235
|
+
e.set(i.id, i);
|
|
236
|
+
return e;
|
|
237
|
+
}
|
|
238
|
+
function U(t) {
|
|
239
|
+
return new Map(t.tracks.map((e) => [e.trackId, e]));
|
|
240
|
+
}
|
|
241
|
+
function G(t, e) {
|
|
242
|
+
const n = [], i = [], a = [];
|
|
243
|
+
for (const [r, s] of e) {
|
|
244
|
+
const c = t.get(r);
|
|
245
|
+
c === void 0 ? n.push(r) : Z(c, s) || a.push(r);
|
|
246
|
+
}
|
|
247
|
+
for (const r of t.keys())
|
|
248
|
+
e.has(r) || i.push(r);
|
|
249
|
+
return { added: n, removed: i, changed: a };
|
|
250
|
+
}
|
|
251
|
+
function me(t, e) {
|
|
252
|
+
const n = G(U(t), U(e)), i = G(B(t), B(e)), a = [];
|
|
253
|
+
for (const r of ["width", "height", "fps"])
|
|
254
|
+
t[r] !== e[r] && a.push(r);
|
|
255
|
+
return {
|
|
256
|
+
addedTrackIds: n.added,
|
|
257
|
+
removedTrackIds: n.removed,
|
|
258
|
+
changedTrackIds: n.changed,
|
|
259
|
+
addedSegmentIds: i.added,
|
|
260
|
+
removedSegmentIds: i.removed,
|
|
261
|
+
changedSegmentIds: i.changed,
|
|
262
|
+
projectFields: a
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function A(t) {
|
|
266
|
+
return structuredClone(t);
|
|
267
|
+
}
|
|
268
|
+
function J(t) {
|
|
269
|
+
return {
|
|
270
|
+
success: !1,
|
|
271
|
+
error: t instanceof Error ? t.message : String(t)
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
function ue(t) {
|
|
275
|
+
const e = /* @__PURE__ */ new Map();
|
|
276
|
+
return {
|
|
277
|
+
create: (r, s) => {
|
|
278
|
+
const c = s?.id ?? t.createId();
|
|
279
|
+
if (!c)
|
|
280
|
+
return { success: !1, error: "proposal id must not be empty" };
|
|
281
|
+
if (e.has(c))
|
|
282
|
+
return { success: !1, error: `proposal id ${c} already exists` };
|
|
283
|
+
const p = t.getRevision(), v = structuredClone(t.getProtocol()), f = t.createSandbox(v);
|
|
284
|
+
try {
|
|
285
|
+
r(f);
|
|
286
|
+
const k = structuredClone(f.commands.exportProtocol());
|
|
287
|
+
if (Z(v, k))
|
|
288
|
+
return { success: !1, error: "proposal must change the protocol" };
|
|
289
|
+
const w = f.selectors.getOperationLog().filter((M) => M.status === "applied").flatMap((M) => M.operations.length ? M.operations : M.meta === void 0 ? [] : [M.meta]), S = {
|
|
290
|
+
id: c,
|
|
291
|
+
baseRevision: p,
|
|
292
|
+
previewProtocol: k,
|
|
293
|
+
validation: { valid: !0 },
|
|
294
|
+
operations: structuredClone(w),
|
|
295
|
+
summary: me(v, k)
|
|
296
|
+
};
|
|
297
|
+
return e.set(c, S), { success: !0, proposal: A(S) };
|
|
298
|
+
} catch (k) {
|
|
299
|
+
return J(k);
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
accept: (r) => {
|
|
303
|
+
const s = e.get(r);
|
|
304
|
+
if (!s)
|
|
305
|
+
return { success: !1, error: `no proposal with id ${r}` };
|
|
306
|
+
if (t.isTransactionActive())
|
|
307
|
+
return { success: !1, error: "cannot accept a proposal while a transaction is active" };
|
|
308
|
+
if (t.getRevision() !== s.baseRevision)
|
|
309
|
+
return {
|
|
310
|
+
success: !1,
|
|
311
|
+
error: `proposal ${r} conflicts with the current protocol revision`
|
|
312
|
+
};
|
|
313
|
+
try {
|
|
314
|
+
const c = t.applySnapshot(s.previewProtocol, s);
|
|
315
|
+
return c !== "committed" ? { success: !1, error: `proposal ${r} could not be committed: ${c}` } : (e.delete(r), { success: !0, proposal: A(s) });
|
|
316
|
+
} catch (c) {
|
|
317
|
+
return J(c);
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
reject: (r) => {
|
|
321
|
+
const s = e.get(r);
|
|
322
|
+
return s ? (e.delete(r), { success: !0, proposal: A(s) }) : { success: !1, error: `no proposal with id ${r}` };
|
|
323
|
+
},
|
|
324
|
+
get: (r) => {
|
|
325
|
+
const s = e.get(r);
|
|
326
|
+
return s === void 0 ? void 0 : A(s);
|
|
327
|
+
},
|
|
328
|
+
list: () => [...e.values()].map(A)
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function de() {
|
|
332
|
+
const t = /* @__PURE__ */ new Map();
|
|
38
333
|
return {
|
|
39
|
-
register: (
|
|
40
|
-
if (
|
|
41
|
-
throw new Error(`Segment plugin ${
|
|
42
|
-
|
|
334
|
+
register: (a, r) => {
|
|
335
|
+
if (t.has(a.type) && !r?.override)
|
|
336
|
+
throw new Error(`Segment plugin ${a.type} has been registered`);
|
|
337
|
+
t.set(a.type, a);
|
|
43
338
|
},
|
|
44
|
-
get: (
|
|
45
|
-
list: () => [...
|
|
339
|
+
get: (a) => t.get(a),
|
|
340
|
+
list: () => [...t.values()]
|
|
46
341
|
};
|
|
47
342
|
}
|
|
48
|
-
|
|
343
|
+
const fe = {
|
|
344
|
+
opacity: 1,
|
|
345
|
+
"position.x": 0,
|
|
346
|
+
"position.y": 0,
|
|
347
|
+
scale: 1,
|
|
348
|
+
rotation: 0,
|
|
349
|
+
volume: 1,
|
|
350
|
+
intensity: 1
|
|
351
|
+
}, le = /* @__PURE__ */ new Set(["frames", "text", "sticker", "audio", "effect", "filter"]);
|
|
352
|
+
function ge(t, e) {
|
|
353
|
+
const n = t, i = n.transform;
|
|
354
|
+
switch (e) {
|
|
355
|
+
case "opacity":
|
|
356
|
+
return n.opacity;
|
|
357
|
+
case "volume":
|
|
358
|
+
return n.volume;
|
|
359
|
+
case "intensity":
|
|
360
|
+
return n.intensity;
|
|
361
|
+
case "position.x":
|
|
362
|
+
return i?.position?.[0];
|
|
363
|
+
case "position.y":
|
|
364
|
+
return i?.position?.[1];
|
|
365
|
+
case "scale":
|
|
366
|
+
return i?.scale?.[0];
|
|
367
|
+
case "rotation":
|
|
368
|
+
return i?.rotation?.[2];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function pe(t, e) {
|
|
372
|
+
return t.keyframes?.find((n) => n.property === e && n.frames.length > 0);
|
|
373
|
+
}
|
|
374
|
+
function F(t, e) {
|
|
375
|
+
return e >= t.startTime && e < t.endTime;
|
|
376
|
+
}
|
|
377
|
+
function N(t) {
|
|
378
|
+
return [...t.children].sort((e, n) => e.startTime - n.startTime);
|
|
379
|
+
}
|
|
380
|
+
function ye(t) {
|
|
381
|
+
const { protocol: e, selectedSegmentId: n, undoCount: i, redoCount: a } = t, r = (m) => e().tracks.find((o) => o.children.some((l) => l.id === m)), s = (m) => {
|
|
382
|
+
for (const o of e().tracks) {
|
|
383
|
+
const l = o.children.find((d) => d.id === m);
|
|
384
|
+
if (l)
|
|
385
|
+
return l;
|
|
386
|
+
}
|
|
387
|
+
}, c = () => e().tracks.find((m) => m.trackType === "frames" && m.isMain);
|
|
388
|
+
function p(m, o) {
|
|
389
|
+
const l = [];
|
|
390
|
+
for (const d of e().tracks)
|
|
391
|
+
if (!(o?.trackType && d.trackType !== o.trackType) && !(o?.includeHidden === !1 && d.hidden))
|
|
392
|
+
for (const y of d.children)
|
|
393
|
+
F(y, m) && l.push({ segment: y, trackId: d.trackId, trackType: d.trackType });
|
|
394
|
+
return l;
|
|
395
|
+
}
|
|
396
|
+
function v(m, o) {
|
|
397
|
+
return e().tracks.find((d) => d.trackId === m)?.children.find((d) => F(d, o));
|
|
398
|
+
}
|
|
399
|
+
function f(m) {
|
|
400
|
+
const o = e().tracks.find((y) => y.trackId === m);
|
|
401
|
+
if (!o)
|
|
402
|
+
return [];
|
|
403
|
+
const l = [];
|
|
404
|
+
let d = 0;
|
|
405
|
+
for (const y of N(o))
|
|
406
|
+
y.startTime > d && l.push({ startTime: d, endTime: y.startTime }), d = Math.max(d, y.endTime);
|
|
407
|
+
return l;
|
|
408
|
+
}
|
|
409
|
+
function k(m) {
|
|
410
|
+
const o = r(m);
|
|
411
|
+
if (!o)
|
|
412
|
+
return {};
|
|
413
|
+
const l = N(o), d = l.findIndex((y) => y.id === m);
|
|
414
|
+
return d < 0 ? {} : {
|
|
415
|
+
trackId: o.trackId,
|
|
416
|
+
previous: l[d - 1],
|
|
417
|
+
next: l[d + 1]
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function w(m) {
|
|
421
|
+
const o = m ? e().tracks.filter((d) => d.trackId === m) : e().tracks, l = [];
|
|
422
|
+
for (const d of o) {
|
|
423
|
+
const y = N(d);
|
|
424
|
+
for (let h = 0; h < y.length - 1; h++) {
|
|
425
|
+
const I = y[h];
|
|
426
|
+
for (let b = h + 1; b < y.length; b++) {
|
|
427
|
+
const x = y[b];
|
|
428
|
+
if (x.startTime >= I.endTime)
|
|
429
|
+
break;
|
|
430
|
+
l.push({
|
|
431
|
+
trackId: d.trackId,
|
|
432
|
+
a: I,
|
|
433
|
+
b: x,
|
|
434
|
+
startTime: x.startTime,
|
|
435
|
+
endTime: Math.min(I.endTime, x.endTime)
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return l;
|
|
441
|
+
}
|
|
442
|
+
function S(m, o, l) {
|
|
443
|
+
const d = s(m);
|
|
444
|
+
if (!d)
|
|
445
|
+
return;
|
|
446
|
+
const y = F(d, l), h = pe(d, o);
|
|
447
|
+
if (h) {
|
|
448
|
+
const b = Math.max(0, l - d.startTime), x = re(h, b);
|
|
449
|
+
if (Number.isFinite(x)) {
|
|
450
|
+
const $ = h.frames, H = $.length === 1 || b <= $[0].timeMs || b >= $[$.length - 1].timeMs || $.some((X) => X.timeMs === b);
|
|
451
|
+
return {
|
|
452
|
+
value: x,
|
|
453
|
+
source: H ? "keyframe" : "interpolated",
|
|
454
|
+
withinSegment: y
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const I = ge(d, o);
|
|
459
|
+
return I !== void 0 && Number.isFinite(I) ? { value: I, source: "static", withinSegment: y } : { value: fe[o], source: "default", withinSegment: y };
|
|
460
|
+
}
|
|
461
|
+
function M() {
|
|
462
|
+
const m = n();
|
|
463
|
+
if (!m)
|
|
464
|
+
return {};
|
|
465
|
+
const o = s(m);
|
|
466
|
+
return o ? { segmentId: m, segment: o, trackId: r(m)?.trackId } : {};
|
|
467
|
+
}
|
|
468
|
+
const g = { ok: !0 }, u = (m) => ({ ok: !1, reason: m });
|
|
469
|
+
function C(m) {
|
|
470
|
+
switch (m.command) {
|
|
471
|
+
case "undo":
|
|
472
|
+
return i() > 0 ? g : u("nothing to undo");
|
|
473
|
+
case "redo":
|
|
474
|
+
return a() > 0 ? g : u("nothing to redo");
|
|
475
|
+
case "removeSegment":
|
|
476
|
+
case "duplicateSegment":
|
|
477
|
+
return s(m.segmentId) ? g : u(`no segment with id ${m.segmentId}`);
|
|
478
|
+
case "splitSegment": {
|
|
479
|
+
const o = s(m.segmentId);
|
|
480
|
+
return o ? Number.isFinite(m.timelineMs) ? m.timelineMs <= o.startTime || m.timelineMs >= o.endTime ? u("split time must fall strictly inside the segment") : g : u("split time must be a finite number") : u(`no segment with id ${m.segmentId}`);
|
|
481
|
+
}
|
|
482
|
+
case "addTransition": {
|
|
483
|
+
const o = c();
|
|
484
|
+
return o ? o.children.length < 2 ? u("a transition needs two adjacent segments") : g : u("the project has no main frames track");
|
|
485
|
+
}
|
|
486
|
+
case "setCanvasSize": {
|
|
487
|
+
for (const [o, l] of [["width", m.width], ["height", m.height]]) {
|
|
488
|
+
if (!Number.isInteger(l))
|
|
489
|
+
return u(`${o} must be a whole number of pixels`);
|
|
490
|
+
if (l < L || l > j)
|
|
491
|
+
return u(`${o} must be between ${L} and ${j}`);
|
|
492
|
+
}
|
|
493
|
+
return g;
|
|
494
|
+
}
|
|
495
|
+
case "setFps":
|
|
496
|
+
return Number.isFinite(m.fps) ? m.fps < R ? u(`fps must be at least ${R}`) : g : u("fps must be a finite number");
|
|
497
|
+
case "addTrack": {
|
|
498
|
+
const { input: o } = m;
|
|
499
|
+
if (!le.has(o.trackType))
|
|
500
|
+
return u(`unsupported track type ${String(o.trackType)}`);
|
|
501
|
+
if (o.trackId !== void 0 && (typeof o.trackId != "string" || o.trackId.length === 0))
|
|
502
|
+
return u("track id must not be empty");
|
|
503
|
+
if (o.trackId && e().tracks.some((d) => d.trackId === o.trackId))
|
|
504
|
+
return u(`track id ${o.trackId} already exists`);
|
|
505
|
+
const l = o.index ?? 0;
|
|
506
|
+
return !Number.isInteger(l) || l < 0 || l > e().tracks.length ? u(`track index must be between 0 and ${e().tracks.length}`) : g;
|
|
507
|
+
}
|
|
508
|
+
case "removeTrack":
|
|
509
|
+
return e().tracks.some((o) => o.trackId === m.trackId) ? g : u(`no track with id ${m.trackId}`);
|
|
510
|
+
case "moveTrack": {
|
|
511
|
+
const o = e().tracks;
|
|
512
|
+
return o.some((l) => l.trackId === m.trackId) ? !Number.isInteger(m.toIndex) || m.toIndex < 0 || m.toIndex >= o.length ? u(`track index must be between 0 and ${Math.max(0, o.length - 1)}`) : g : u(`no track with id ${m.trackId}`);
|
|
513
|
+
}
|
|
514
|
+
case "replaceSegmentAsset": {
|
|
515
|
+
const { asset: o, segmentId: l, strategy: d } = m.input, y = s(l);
|
|
516
|
+
if (!y)
|
|
517
|
+
return u(`no segment with id ${l}`);
|
|
518
|
+
const h = ee(y) ? "video" : te(y) ? "audio" : y.segmentType === "sticker" || y.segmentType === "frames" && y.type === "image" ? "image" : void 0;
|
|
519
|
+
if (!h)
|
|
520
|
+
return u("segment does not use a replaceable asset");
|
|
521
|
+
if (h !== o.kind)
|
|
522
|
+
return u(`cannot replace ${h} with ${o.kind}`);
|
|
523
|
+
if (o.id !== void 0 && !o.id)
|
|
524
|
+
return u("asset id must not be empty");
|
|
525
|
+
try {
|
|
526
|
+
if (!new URL(o.url).protocol)
|
|
527
|
+
return u("asset url must be an absolute URL");
|
|
528
|
+
} catch {
|
|
529
|
+
return u("asset url must be an absolute URL");
|
|
530
|
+
}
|
|
531
|
+
if (d !== "preserve" && d !== "fit")
|
|
532
|
+
return u(`unsupported replacement strategy ${String(d)}`);
|
|
533
|
+
if (h === "image")
|
|
534
|
+
return d === "fit" ? u("fit strategy requires a video or audio asset with a duration") : g;
|
|
535
|
+
if (typeof o.durationMs != "number" || !Number.isFinite(o.durationMs) || o.durationMs <= 0)
|
|
536
|
+
return u("asset durationMs must be a positive number for video and audio");
|
|
537
|
+
if (d === "preserve") {
|
|
538
|
+
const I = y, b = (I.fromTime ?? 0) + (I.endTime - I.startTime) * (I.playRate ?? 1);
|
|
539
|
+
if (b > o.durationMs)
|
|
540
|
+
return u(`current source window ends at ${b}ms, beyond the ${o.durationMs}ms asset`);
|
|
541
|
+
}
|
|
542
|
+
return g;
|
|
543
|
+
}
|
|
544
|
+
case "upsertKeyframe":
|
|
545
|
+
case "moveKeyframe":
|
|
546
|
+
case "removeKeyframe":
|
|
547
|
+
case "setKeyframeEasing":
|
|
548
|
+
return Y(m, s);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
getSegmentsAt: p,
|
|
553
|
+
getSegmentAt: v,
|
|
554
|
+
getTrackGaps: f,
|
|
555
|
+
getAdjacentSegments: k,
|
|
556
|
+
getOverlaps: w,
|
|
557
|
+
sampleProperty: S,
|
|
558
|
+
getSelection: M,
|
|
559
|
+
canRun: C
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
function ve(t) {
|
|
49
563
|
let e = 0;
|
|
50
|
-
for (const
|
|
51
|
-
for (const
|
|
52
|
-
|
|
564
|
+
for (const n of t)
|
|
565
|
+
for (const i of n.children)
|
|
566
|
+
i.endTime > e && (e = i.endTime);
|
|
53
567
|
return e;
|
|
54
568
|
}
|
|
55
|
-
function
|
|
56
|
-
const e =
|
|
57
|
-
idFactory:
|
|
58
|
-
}),
|
|
569
|
+
function ke(t) {
|
|
570
|
+
const e = Q(t.protocol, {
|
|
571
|
+
idFactory: t.idFactory
|
|
572
|
+
}), n = O(() => e.selectedSegment.value?.id), i = O(() => ve(e.protocol.value.tracks)), a = {
|
|
59
573
|
protocol: e.protocol,
|
|
60
574
|
videoBasicInfo: e.videoBasicInfo,
|
|
61
575
|
currentTime: e.curTime,
|
|
62
576
|
selectedSegment: e.selectedSegment,
|
|
63
|
-
selectedSegmentId:
|
|
577
|
+
selectedSegmentId: n,
|
|
64
578
|
trackMap: e.trackMap,
|
|
65
579
|
segmentMap: e.segmentMap,
|
|
66
|
-
duration:
|
|
580
|
+
duration: i,
|
|
67
581
|
undoCount: e.undoCount,
|
|
68
|
-
redoCount: e.redoCount
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
582
|
+
redoCount: e.redoCount,
|
|
583
|
+
operationLog: e.operationLog,
|
|
584
|
+
revision: e.revision,
|
|
585
|
+
isTransactionActive: e.isTransactionActive,
|
|
586
|
+
transactionDepth: e.transactionDepth
|
|
587
|
+
}, r = ne({
|
|
588
|
+
transaction: e.transaction,
|
|
589
|
+
moveSegment: e.moveSegment,
|
|
590
|
+
removeSegment: e.removeSegment,
|
|
591
|
+
duplicateSegment: e.duplicateSegment,
|
|
592
|
+
updateSegment: e.updateSegment,
|
|
593
|
+
getSegment: e.getSegment
|
|
594
|
+
}), s = ie({
|
|
595
|
+
getSegment: e.getSegment,
|
|
596
|
+
updateSegment: e.updateSegment,
|
|
597
|
+
transaction: e.transaction
|
|
598
|
+
}), c = {
|
|
599
|
+
setCurrentTime: (g) => {
|
|
600
|
+
e.curTime.value = g;
|
|
72
601
|
},
|
|
73
602
|
setSelectedSegment: e.setSelectedSegment,
|
|
74
603
|
addSegment: e.addSegment,
|
|
@@ -77,45 +606,89 @@ function x(s) {
|
|
|
77
606
|
updateSegment: e.updateSegment,
|
|
78
607
|
moveSegment: e.moveSegment,
|
|
79
608
|
resizeSegment: e.resizeSegment,
|
|
609
|
+
replaceSegmentAsset: e.replaceSegmentAsset,
|
|
80
610
|
splitSegment: e.splitSegment,
|
|
81
611
|
addTransition: e.addTransition,
|
|
82
612
|
removeTransition: e.removeTransition,
|
|
83
613
|
updateTransition: e.updateTransition,
|
|
614
|
+
addTrack: e.addTrack,
|
|
615
|
+
removeTrack: e.removeTrack,
|
|
616
|
+
moveTrack: e.moveTrack,
|
|
84
617
|
updateTrack: e.updateTrack,
|
|
85
618
|
setCanvasSize: e.setCanvasSize,
|
|
619
|
+
setFps: e.setFps,
|
|
620
|
+
upsertKeyframe: s.upsertKeyframe,
|
|
621
|
+
moveKeyframe: s.moveKeyframe,
|
|
622
|
+
removeKeyframe: s.removeKeyframe,
|
|
623
|
+
setKeyframeEasing: s.setKeyframeEasing,
|
|
86
624
|
replaceTrackId: e.replaceTrackId,
|
|
87
625
|
replaceSegmentId: e.replaceSegmentId,
|
|
626
|
+
moveSegments: r.moveSegments,
|
|
627
|
+
removeSegments: r.removeSegments,
|
|
628
|
+
updateSegments: r.updateSegments,
|
|
629
|
+
duplicateSegments: r.duplicateSegments,
|
|
630
|
+
transaction: e.transaction,
|
|
631
|
+
beginTransaction: e.beginTransaction,
|
|
88
632
|
undo: e.undo,
|
|
89
633
|
redo: e.redo,
|
|
90
634
|
exportProtocol: e.exportProtocol
|
|
91
|
-
},
|
|
635
|
+
}, v = {
|
|
636
|
+
...ye({
|
|
637
|
+
protocol: () => e.exportProtocol(),
|
|
638
|
+
selectedSegmentId: () => n.value,
|
|
639
|
+
undoCount: () => e.undoCount.value,
|
|
640
|
+
redoCount: () => e.redoCount.value
|
|
641
|
+
}),
|
|
92
642
|
getSegment: e.getSegment,
|
|
93
|
-
getTrackById: (
|
|
94
|
-
getTrackBySegmentId: (
|
|
95
|
-
getTracks: (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
643
|
+
getTrackById: (g) => a.protocol.value.tracks.find((u) => u.trackId === g),
|
|
644
|
+
getTrackBySegmentId: (g) => a.protocol.value.tracks.find((u) => u.children.some((C) => C.id === g)),
|
|
645
|
+
getTracks: (g) => g ? a.protocol.value.tracks.filter((u) => u.trackType === g) : a.protocol.value.tracks,
|
|
646
|
+
getOperationLog: () => structuredClone(a.operationLog.value),
|
|
647
|
+
getAssetReferences: (g) => W(e.exportProtocol(), g)
|
|
648
|
+
}, f = {
|
|
649
|
+
segments: de()
|
|
650
|
+
}, k = t.services ?? {}, S = ce({
|
|
651
|
+
state: a,
|
|
652
|
+
commands: c,
|
|
653
|
+
selectors: v,
|
|
654
|
+
registry: f,
|
|
655
|
+
services: k
|
|
656
|
+
}), M = ue({
|
|
657
|
+
getProtocol: () => e.exportProtocol(),
|
|
658
|
+
getRevision: () => e.revision.value,
|
|
659
|
+
isTransactionActive: () => e.isTransactionActive.value,
|
|
660
|
+
createSandbox: (g) => ke({
|
|
661
|
+
protocol: g,
|
|
662
|
+
idFactory: t.idFactory
|
|
663
|
+
}),
|
|
664
|
+
applySnapshot: (g, u) => e.applyProtocolSnapshot(g, {
|
|
665
|
+
label: "accept-proposal",
|
|
666
|
+
data: { proposalId: u.id, baseRevision: u.baseRevision },
|
|
667
|
+
operations: u.operations
|
|
668
|
+
}).status,
|
|
669
|
+
createId: t.idFactory?.proposal ?? (() => globalThis.crypto.randomUUID())
|
|
104
670
|
});
|
|
105
671
|
return {
|
|
106
|
-
state:
|
|
107
|
-
commands:
|
|
108
|
-
selectors:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
672
|
+
state: a,
|
|
673
|
+
commands: c,
|
|
674
|
+
selectors: v,
|
|
675
|
+
proposals: M,
|
|
676
|
+
plugins: S,
|
|
677
|
+
registry: f,
|
|
678
|
+
services: k,
|
|
112
679
|
destroy: async () => {
|
|
113
|
-
await
|
|
680
|
+
await S.destroy();
|
|
114
681
|
}
|
|
115
682
|
};
|
|
116
683
|
}
|
|
117
684
|
export {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
685
|
+
Y as checkKeyframeCommand,
|
|
686
|
+
ne as createBatchCommands,
|
|
687
|
+
ke as createEditorCore,
|
|
688
|
+
ie as createKeyframeCommands,
|
|
689
|
+
ce as createPluginManager,
|
|
690
|
+
ue as createProposalManager,
|
|
691
|
+
de as createSegmentRegistry,
|
|
692
|
+
ye as createStructuralSelectors,
|
|
693
|
+
me as summarizeProposal
|
|
121
694
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@video-editor/editor-core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.2",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -19,14 +19,15 @@
|
|
|
19
19
|
"@vue/reactivity": "^3.5.26"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@video-editor/protocol": "1.0.0-beta.
|
|
23
|
-
"@video-editor/shared": "1.0.0-beta.
|
|
22
|
+
"@video-editor/protocol": "1.0.0-beta.2",
|
|
23
|
+
"@video-editor/shared": "1.0.0-beta.2"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@vue/reactivity": "^3.5.26"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"build": "vite build",
|
|
30
|
-
"preview": "vite preview"
|
|
30
|
+
"preview": "vite preview",
|
|
31
|
+
"test": "vitest run --config ./vitest.config.ts"
|
|
31
32
|
}
|
|
32
33
|
}
|