@aicut/core 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -0
- package/dist/chunk-H6AY6NW4.js +123 -0
- package/dist/chunk-H6AY6NW4.js.map +1 -0
- package/dist/chunk-WTCK3XQ6.js +93 -0
- package/dist/chunk-WTCK3XQ6.js.map +1 -0
- package/dist/{i18n-B-DFWgKe.d.cts → i18n-B24k4XVG.d.cts} +34 -1
- package/dist/{i18n-B-DFWgKe.d.ts → i18n-B24k4XVG.d.ts} +34 -1
- package/dist/index.cjs +1917 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +348 -25
- package/dist/index.d.ts +348 -25
- package/dist/index.js +1779 -86
- package/dist/index.js.map +1 -1
- package/dist/lighting/index.cjs +24 -6
- package/dist/lighting/index.cjs.map +1 -1
- package/dist/lighting/index.d.cts +2 -2
- package/dist/lighting/index.d.ts +2 -2
- package/dist/lighting/index.js +1 -1
- package/dist/playback/webcodecs/index.cjs +113 -6
- package/dist/playback/webcodecs/index.cjs.map +1 -1
- package/dist/playback/webcodecs/index.d.cts +18 -2
- package/dist/playback/webcodecs/index.d.ts +18 -2
- package/dist/playback/webcodecs/index.js +46 -6
- package/dist/playback/webcodecs/index.js.map +1 -1
- package/dist/{types-DvKlxylu.d.cts → types-BbZjOQLz.d.ts} +34 -1
- package/dist/{types-rwZx6FxE.d.ts → types-CjvRUPtZ.d.cts} +34 -1
- package/dist/types-CmS-UIEr.d.cts +137 -0
- package/dist/types-CmS-UIEr.d.ts +137 -0
- package/package.json +1 -1
- package/styles/theme.css +351 -0
- package/dist/chunk-CCDON7CU.js +0 -87
- package/dist/chunk-CCDON7CU.js.map +0 -1
- package/dist/types-CHplD9V5.d.cts +0 -70
- package/dist/types-CHplD9V5.d.ts +0 -70
package/dist/index.d.cts
CHANGED
|
@@ -1,33 +1,22 @@
|
|
|
1
|
-
import { P as PlaybackEngine, a as PlaybackEngineOptions, b as PlaybackEngineFactory } from './types-
|
|
2
|
-
import { M as Ms, P as Project, T as Track, C as Clip, a as MediaSource, b as Theme } from './types-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { P as PlaybackEngine, a as PlaybackEngineOptions, b as PlaybackEngineFactory } from './types-CjvRUPtZ.cjs';
|
|
2
|
+
import { M as Ms, P as Project, T as Track, C as Clip, a as MediaSource, b as Theme, K as KeyframeProp, E as EasingKind } from './types-CmS-UIEr.cjs';
|
|
3
|
+
export { c as Keyframe } from './types-CmS-UIEr.cjs';
|
|
4
|
+
import { L as Locale } from './i18n-B24k4XVG.cjs';
|
|
5
|
+
export { f as formatLabel, l as localeEn, a as localeZh, m as mergeLocale } from './i18n-B24k4XVG.cjs';
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
-
* Default preview engine — one hidden `<video>` per `MediaSource`,
|
|
8
|
-
* "active" video shown for the current playhead. Tick loop drives a
|
|
9
|
-
* single video track's playhead, advancing through clips end-to-end.
|
|
10
|
-
* When the playhead crosses a clip boundary we pause the outgoing
|
|
11
|
-
* video and resume the next at `clip.in`.
|
|
12
|
-
*
|
|
13
|
-
* Strengths: zero deps, browser-native decode (GPU when available),
|
|
14
|
-
* works in every browser today.
|
|
15
|
-
*
|
|
16
|
-
* Limits: no multi-track compositing (one video visible at a time),
|
|
17
|
-
* seek snaps to keyframes (browser controls the decode pipeline), no
|
|
18
|
-
* transitions / shaders / filters. See `WebCodecsEngine` for the
|
|
19
|
-
* frame-accurate path.
|
|
20
|
-
*/
|
|
21
7
|
declare class HtmlVideoEngine implements PlaybackEngine {
|
|
22
8
|
private host;
|
|
23
9
|
private mount;
|
|
24
|
-
private
|
|
10
|
+
private sources;
|
|
25
11
|
private project;
|
|
26
12
|
private currentClipId;
|
|
27
13
|
private playing;
|
|
28
14
|
private timeMs;
|
|
29
15
|
private rafHandle;
|
|
30
16
|
private lastFrameTs;
|
|
17
|
+
/** Permanent rAF that positions the active wrapper at the output
|
|
18
|
+
* rect + pushes keyframe transform onto the inner video via CSS. */
|
|
19
|
+
private transformRaf;
|
|
31
20
|
/** Public event hooks — set by Editor. */
|
|
32
21
|
onTimeUpdate?: (ms: Ms) => void;
|
|
33
22
|
onEnded?: () => void;
|
|
@@ -41,6 +30,37 @@ declare class HtmlVideoEngine implements PlaybackEngine {
|
|
|
41
30
|
isPlaying(): boolean;
|
|
42
31
|
getTime(): Ms;
|
|
43
32
|
seek(timeMs: Ms): void;
|
|
33
|
+
/**
|
|
34
|
+
* The OUTPUT frame — the fixed stage the rendered video is clipped
|
|
35
|
+
* to. Independent of the keyframe transform. Used by the overlay to
|
|
36
|
+
* draw the dashed border at a stable position.
|
|
37
|
+
*/
|
|
38
|
+
getOutputFrameRect(): {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
w: number;
|
|
42
|
+
h: number;
|
|
43
|
+
} | null;
|
|
44
|
+
/**
|
|
45
|
+
* The CONTENT frame — where the transformed video pixels actually
|
|
46
|
+
* land. Equal to the output frame when transform is identity; may
|
|
47
|
+
* extend outside (zoom in) or fit inside (zoom out) when not.
|
|
48
|
+
*/
|
|
49
|
+
getFrameRect(): {
|
|
50
|
+
x: number;
|
|
51
|
+
y: number;
|
|
52
|
+
w: number;
|
|
53
|
+
h: number;
|
|
54
|
+
} | null;
|
|
55
|
+
/** Untransformed contain-letterbox rect — the OUTPUT frame. */
|
|
56
|
+
private baseFrameRect;
|
|
57
|
+
/**
|
|
58
|
+
* Permanent rAF that (a) sizes + positions the active wrapper to
|
|
59
|
+
* the output frame, and (b) writes the keyframe transform onto the
|
|
60
|
+
* inner video. Negligible cost — three style writes per frame max.
|
|
61
|
+
*/
|
|
62
|
+
private startTransformLoop;
|
|
63
|
+
private applyTransforms;
|
|
44
64
|
destroy(): void;
|
|
45
65
|
private syncSources;
|
|
46
66
|
private activate;
|
|
@@ -49,10 +69,7 @@ declare class HtmlVideoEngine implements PlaybackEngine {
|
|
|
49
69
|
/**
|
|
50
70
|
* Find the clip whose timeline range contains `timeMs`, searching
|
|
51
71
|
* across ALL video tracks. If multiple tracks have a clip at this
|
|
52
|
-
* moment, the lowest-index track wins
|
|
53
|
-
* background" convention used in the auto-split UX — overlapping
|
|
54
|
-
* placements would have created a new track on top, but here we
|
|
55
|
-
* fall back to the underlying clip).
|
|
72
|
+
* moment, the lowest-index track wins.
|
|
56
73
|
*/
|
|
57
74
|
private clipAtTime;
|
|
58
75
|
/** Earliest clip starting at-or-after `timeMs` across all video tracks. */
|
|
@@ -107,6 +124,10 @@ declare class CanvasCompositorEngine implements PlaybackEngine {
|
|
|
107
124
|
private rafHandle;
|
|
108
125
|
private lastFrameTs;
|
|
109
126
|
private paintedFrames;
|
|
127
|
+
/** Output frame rect (no transform) — fixed bounds. */
|
|
128
|
+
private lastOutputRect;
|
|
129
|
+
/** Post-transform content rect. */
|
|
130
|
+
private lastFrameRect;
|
|
110
131
|
onTimeUpdate?: (ms: Ms) => void;
|
|
111
132
|
onEnded?: () => void;
|
|
112
133
|
onError?: (err: Error) => void;
|
|
@@ -138,6 +159,18 @@ declare class CanvasCompositorEngine implements PlaybackEngine {
|
|
|
138
159
|
* and the seek preview both update when paused.
|
|
139
160
|
*/
|
|
140
161
|
private paint;
|
|
162
|
+
getOutputFrameRect(): {
|
|
163
|
+
x: number;
|
|
164
|
+
y: number;
|
|
165
|
+
w: number;
|
|
166
|
+
h: number;
|
|
167
|
+
} | null;
|
|
168
|
+
getFrameRect(): {
|
|
169
|
+
x: number;
|
|
170
|
+
y: number;
|
|
171
|
+
w: number;
|
|
172
|
+
h: number;
|
|
173
|
+
} | null;
|
|
141
174
|
private updateBadge;
|
|
142
175
|
}
|
|
143
176
|
/** Factory shorthand for `Editor.create({ playbackEngine })`. */
|
|
@@ -194,6 +227,31 @@ interface EditorOptions {
|
|
|
194
227
|
* Reasonable range: [120, 480].
|
|
195
228
|
*/
|
|
196
229
|
timelineHeight?: number;
|
|
230
|
+
/**
|
|
231
|
+
* Per-clip keyframe animation (X / Y / Scale). Off by default; flip
|
|
232
|
+
* `enabled: true` to surface keyframe markers on the timeline and
|
|
233
|
+
* route the canvas / WebCodecs engines through `getEffectiveTransform`
|
|
234
|
+
* when painting. Data is preserved either way — disabling just hides
|
|
235
|
+
* the editing UI and renders identity transforms.
|
|
236
|
+
*
|
|
237
|
+
* HtmlVideoEngine cannot apply per-frame transforms (it shows a raw
|
|
238
|
+
* `<video>`), so keyframes are silently ignored on that engine
|
|
239
|
+
* regardless of this flag. Swap to `CanvasCompositorEngine` or
|
|
240
|
+
* `WebCodecsEngine` for live preview.
|
|
241
|
+
*/
|
|
242
|
+
keyframes?: {
|
|
243
|
+
enabled?: boolean;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Show the |◀ / ▶| "jump to clip start / end" toolbar buttons and
|
|
247
|
+
* bind the I / O keyboard shortcuts. Off by default — hosts opt in
|
|
248
|
+
* the same way they do for keyframes. When off the buttons are
|
|
249
|
+
* completely hidden (display: none) so they don't take up toolbar
|
|
250
|
+
* space, and the I / O keys fall through to the page.
|
|
251
|
+
*/
|
|
252
|
+
clipEdgeNav?: {
|
|
253
|
+
enabled?: boolean;
|
|
254
|
+
};
|
|
197
255
|
}
|
|
198
256
|
interface EditorEventMap {
|
|
199
257
|
/** Emitted whenever the project mutates. */
|
|
@@ -221,6 +279,23 @@ interface EditorEventMap {
|
|
|
221
279
|
selectionChange: {
|
|
222
280
|
clipId: string | null;
|
|
223
281
|
};
|
|
282
|
+
/** Currently selected keyframe (parent clip + keyframe id), or null.
|
|
283
|
+
* Selecting a keyframe also selects its parent clip — listeners
|
|
284
|
+
* watching `selectionChange` get notified independently. */
|
|
285
|
+
keyframeSelectionChange: {
|
|
286
|
+
target: {
|
|
287
|
+
clipId: string;
|
|
288
|
+
keyframeId: string;
|
|
289
|
+
} | null;
|
|
290
|
+
};
|
|
291
|
+
/** Keyframe-mode toggle changed (Editor.setKeyframesEnabled). */
|
|
292
|
+
keyframesEnabledChange: {
|
|
293
|
+
enabled: boolean;
|
|
294
|
+
};
|
|
295
|
+
/** Jump-to-clip-edge nav toggle changed (Editor.setClipEdgeNavEnabled). */
|
|
296
|
+
clipEdgeNavEnabledChange: {
|
|
297
|
+
enabled: boolean;
|
|
298
|
+
};
|
|
224
299
|
/** Zoom (px/sec) changed. */
|
|
225
300
|
scaleChange: {
|
|
226
301
|
pxPerSec: number;
|
|
@@ -297,10 +372,131 @@ interface EditorApi {
|
|
|
297
372
|
setSnap(snap: boolean): void;
|
|
298
373
|
getSelection(): string | null;
|
|
299
374
|
setSelection(clipId: string | null): void;
|
|
375
|
+
isKeyframesEnabled(): boolean;
|
|
376
|
+
setKeyframesEnabled(enabled: boolean): void;
|
|
377
|
+
isClipEdgeNavEnabled(): boolean;
|
|
378
|
+
setClipEdgeNavEnabled(enabled: boolean): void;
|
|
379
|
+
/** Screen-space CSS-pixel rect of the active rendered frame, post
|
|
380
|
+
* transform, relative to the editor preview. Null when none. */
|
|
381
|
+
getActiveFrameRect(): {
|
|
382
|
+
x: number;
|
|
383
|
+
y: number;
|
|
384
|
+
w: number;
|
|
385
|
+
h: number;
|
|
386
|
+
} | null;
|
|
387
|
+
/** Output frame rect (fixed bounds, no transform). The overlay
|
|
388
|
+
* draws the dashed border here. */
|
|
389
|
+
getActiveOutputFrameRect(): {
|
|
390
|
+
x: number;
|
|
391
|
+
y: number;
|
|
392
|
+
w: number;
|
|
393
|
+
h: number;
|
|
394
|
+
} | null;
|
|
395
|
+
/**
|
|
396
|
+
* Upsert a per-property keyframe at the given clip-local time. If a
|
|
397
|
+
* keyframe for the same `prop` already exists within ~1 frame of
|
|
398
|
+
* `time` it gets its value updated; else a new one is appended.
|
|
399
|
+
* Returns the keyframe's id, or null when the clip can't be found.
|
|
400
|
+
*
|
|
401
|
+
* Defaults: `time` = playhead in clip-local coords; `value` = the
|
|
402
|
+
* currently interpolated value for that prop (so adding doesn't
|
|
403
|
+
* cause a visible jump).
|
|
404
|
+
*/
|
|
405
|
+
addKeyframe(clipId: string, prop: KeyframeProp, opts?: {
|
|
406
|
+
time?: Ms;
|
|
407
|
+
value?: number;
|
|
408
|
+
}): string | null;
|
|
409
|
+
removeKeyframe(clipId: string, keyframeId: string): boolean;
|
|
410
|
+
moveKeyframe(clipId: string, keyframeId: string, timeMs: Ms): boolean;
|
|
411
|
+
/** Change one keyframe's value (single number, since each kf is
|
|
412
|
+
* per-property). */
|
|
413
|
+
setKeyframeValue(clipId: string, keyframeId: string, value: number): boolean;
|
|
414
|
+
/**
|
|
415
|
+
* Change one keyframe's outgoing easing curve. Shapes only the
|
|
416
|
+
* segment from this kf to the NEXT kf in time on the same prop.
|
|
417
|
+
* The kf's value is untouched.
|
|
418
|
+
*/
|
|
419
|
+
setKeyframeEasing(clipId: string, keyframeId: string, easing: EasingKind): boolean;
|
|
420
|
+
/**
|
|
421
|
+
* Batch-set the outgoing easing on every kf at one moment in time
|
|
422
|
+
* (within the 16ms tolerance that the rest of the API uses) on a
|
|
423
|
+
* single clip. Mirrors the panel's "one dropdown for the moment"
|
|
424
|
+
* UX so all three props (panX / panY / scale) at the selected
|
|
425
|
+
* moment animate with the same curve. Single history entry.
|
|
426
|
+
*/
|
|
427
|
+
setKeyframesEasingAtTime(clipId: string, timeMs: Ms, easing: EasingKind): boolean;
|
|
428
|
+
/**
|
|
429
|
+
* CapCut-style auto-record: write `value` for `prop` at the playhead.
|
|
430
|
+
* - If the prop already has keyframes → upsert a keyframe at the
|
|
431
|
+
* playhead with this value.
|
|
432
|
+
* - If the prop has no keyframes → just update the static base
|
|
433
|
+
* (panX / panY / scale on the clip) so the visual changes
|
|
434
|
+
* without committing the user to an animation track yet.
|
|
435
|
+
* Returns true if the project changed.
|
|
436
|
+
*/
|
|
437
|
+
setValueAtPlayhead(clipId: string, prop: KeyframeProp, value: number): boolean;
|
|
438
|
+
getSelectedKeyframe(): {
|
|
439
|
+
clipId: string;
|
|
440
|
+
keyframeId: string;
|
|
441
|
+
} | null;
|
|
442
|
+
setSelectedKeyframe(target: {
|
|
443
|
+
clipId: string;
|
|
444
|
+
keyframeId: string;
|
|
445
|
+
} | null): void;
|
|
446
|
+
/**
|
|
447
|
+
* Toolbar-style toggle. If ANY keyframe exists at the playhead time
|
|
448
|
+
* on the selected clip, remove every keyframe at that time (all
|
|
449
|
+
* props). Otherwise, capture one keyframe per prop (panX, panY,
|
|
450
|
+
* scale) at the playhead with the currently interpolated values.
|
|
451
|
+
* Returns true when the project changed.
|
|
452
|
+
*/
|
|
453
|
+
toggleKeyframeAtPlayhead(): boolean;
|
|
454
|
+
/**
|
|
455
|
+
* Clear every keyframe AND every static transform value on a clip,
|
|
456
|
+
* restoring the identity pose (panX=0, panY=0, scale=1). Single
|
|
457
|
+
* history entry. */
|
|
458
|
+
resetClipTransform(clipId: string): boolean;
|
|
459
|
+
/**
|
|
460
|
+
* Pin all three transform props (panX, panY, scale) to identity
|
|
461
|
+
* (0, 0, 1) at one specific clip-local time. Upserts on each prop —
|
|
462
|
+
* keyframes that already exist at that time get their values
|
|
463
|
+
* overwritten; props with no kf there get one added. Single history
|
|
464
|
+
* entry. Used by the panel's Reset button when a keyframe is selected.
|
|
465
|
+
*/
|
|
466
|
+
resetKeyframesAtTime(clipId: string, timeMs: Ms): boolean;
|
|
467
|
+
/**
|
|
468
|
+
* Move the playhead to a clip edge. "end" intentionally lands 1ms
|
|
469
|
+
* INSIDE the clip (clipEnd - 1) so the playhead remains inside the
|
|
470
|
+
* clip — that lets the user immediately press the keyframe button
|
|
471
|
+
* (or the I/O shortcut) and have it find the right clip + drop a
|
|
472
|
+
* keyframe at clip-local time `duration - 1ms`. Without the -1ms
|
|
473
|
+
* offset the playhead lands on the seam and `toggleKeyframeAtPlayhead`
|
|
474
|
+
* picks the next clip (or none at all).
|
|
475
|
+
* Returns true when the seek actually moved.
|
|
476
|
+
*/
|
|
477
|
+
seekToClipEdge(clipId: string, edge: "start" | "end"): boolean;
|
|
478
|
+
/** Convenience for the toolbar: act on the currently-selected clip. */
|
|
479
|
+
seekToSelectedClipEdge(edge: "start" | "end"): boolean;
|
|
300
480
|
canUndo(): boolean;
|
|
301
481
|
canRedo(): boolean;
|
|
302
482
|
undo(): boolean;
|
|
303
483
|
redo(): boolean;
|
|
484
|
+
/**
|
|
485
|
+
* Open a "drag session". While open, every internal `pushHistory`
|
|
486
|
+
* call captures the pre-session snapshot ONCE — subsequent calls
|
|
487
|
+
* during the same session are no-ops. The session commits a single
|
|
488
|
+
* history entry on `endInteraction()` (or is dropped entirely if
|
|
489
|
+
* the project ended up unchanged). Nestable: nested begin/end pairs
|
|
490
|
+
* count by depth and only the outermost commits.
|
|
491
|
+
*
|
|
492
|
+
* Hosts call this around continuous gestures (drag the preview
|
|
493
|
+
* overlay, scrub a numeric slider, wheel-zoom) so a single user
|
|
494
|
+
* gesture becomes ONE undo entry instead of 30-100. Without this,
|
|
495
|
+
* each pointermove of an overlay drag pushes its own history entry
|
|
496
|
+
* and the user has to mash Cmd+Z that many times to fully undo.
|
|
497
|
+
*/
|
|
498
|
+
beginInteraction(): void;
|
|
499
|
+
endInteraction(): void;
|
|
304
500
|
/**
|
|
305
501
|
* Bookend slot at the very left of the top toolbar — host appends
|
|
306
502
|
* its own controls (e.g. an aspect-ratio dropdown). Empty by default
|
|
@@ -339,6 +535,13 @@ declare class Editor implements EditorApi {
|
|
|
339
535
|
private bus;
|
|
340
536
|
private history;
|
|
341
537
|
private selectedClipId;
|
|
538
|
+
private selectedKeyframe;
|
|
539
|
+
private keyframesEnabled;
|
|
540
|
+
private clipEdgeNavEnabled;
|
|
541
|
+
/** Drag-session bookkeeping for ripple-merge undo. See
|
|
542
|
+
* beginInteraction / endInteraction docs on EditorApi. */
|
|
543
|
+
private interactionDepth;
|
|
544
|
+
private interactionStartSnapshot;
|
|
342
545
|
private pxPerSec;
|
|
343
546
|
private snap;
|
|
344
547
|
private locale;
|
|
@@ -426,10 +629,74 @@ declare class Editor implements EditorApi {
|
|
|
426
629
|
snapMs(timeMs: Ms, ignoreClipId?: string | null): Ms;
|
|
427
630
|
getSelection(): string | null;
|
|
428
631
|
setSelection(clipId: string | null): void;
|
|
632
|
+
isKeyframesEnabled(): boolean;
|
|
633
|
+
/**
|
|
634
|
+
* Screen-space CSS-pixel rect of the actively painted frame
|
|
635
|
+
* (post-transform), relative to the editor's preview element.
|
|
636
|
+
* Null when no clip is active, the engine doesn't expose
|
|
637
|
+
* `getFrameRect`, or the rect isn't computed yet. Used by the
|
|
638
|
+
* library's keyframe-editing overlay.
|
|
639
|
+
*/
|
|
640
|
+
getActiveFrameRect(): {
|
|
641
|
+
x: number;
|
|
642
|
+
y: number;
|
|
643
|
+
w: number;
|
|
644
|
+
h: number;
|
|
645
|
+
} | null;
|
|
646
|
+
/**
|
|
647
|
+
* Screen-space CSS-pixel rect of the OUTPUT FRAME (the fixed
|
|
648
|
+
* stage that clips the rendered video). Different from
|
|
649
|
+
* `getActiveFrameRect` which includes the keyframe transform —
|
|
650
|
+
* this one stays put as the user drags / scales the content.
|
|
651
|
+
* Used by the overlay to anchor the dashed border + drag body.
|
|
652
|
+
*/
|
|
653
|
+
getActiveOutputFrameRect(): {
|
|
654
|
+
x: number;
|
|
655
|
+
y: number;
|
|
656
|
+
w: number;
|
|
657
|
+
h: number;
|
|
658
|
+
} | null;
|
|
659
|
+
setKeyframesEnabled(enabled: boolean): void;
|
|
660
|
+
isClipEdgeNavEnabled(): boolean;
|
|
661
|
+
setClipEdgeNavEnabled(enabled: boolean): void;
|
|
662
|
+
addKeyframe(clipId: string, prop: KeyframeProp, opts?: {
|
|
663
|
+
time?: Ms;
|
|
664
|
+
value?: number;
|
|
665
|
+
}): string | null;
|
|
666
|
+
removeKeyframe(clipId: string, keyframeId: string): boolean;
|
|
667
|
+
moveKeyframe(clipId: string, keyframeId: string, timeMs: Ms): boolean;
|
|
668
|
+
setKeyframeValue(clipId: string, keyframeId: string, value: number): boolean;
|
|
669
|
+
setKeyframeEasing(clipId: string, keyframeId: string, easing: EasingKind): boolean;
|
|
670
|
+
setKeyframesEasingAtTime(clipId: string, timeMs: Ms, easing: EasingKind): boolean;
|
|
671
|
+
setValueAtPlayhead(clipId: string, prop: KeyframeProp, value: number): boolean;
|
|
672
|
+
getSelectedKeyframe(): {
|
|
673
|
+
clipId: string;
|
|
674
|
+
keyframeId: string;
|
|
675
|
+
} | null;
|
|
676
|
+
resetClipTransform(clipId: string): boolean;
|
|
677
|
+
resetKeyframesAtTime(clipId: string, timeMs: Ms): boolean;
|
|
678
|
+
seekToClipEdge(clipId: string, edge: "start" | "end"): boolean;
|
|
679
|
+
seekToSelectedClipEdge(edge: "start" | "end"): boolean;
|
|
680
|
+
toggleKeyframeAtPlayhead(): boolean;
|
|
681
|
+
setSelectedKeyframe(target: {
|
|
682
|
+
clipId: string;
|
|
683
|
+
keyframeId: string;
|
|
684
|
+
} | null): void;
|
|
429
685
|
canUndo(): boolean;
|
|
430
686
|
canRedo(): boolean;
|
|
431
687
|
undo(): boolean;
|
|
432
688
|
redo(): boolean;
|
|
689
|
+
beginInteraction(): void;
|
|
690
|
+
endInteraction(): void;
|
|
691
|
+
/**
|
|
692
|
+
* Selections (clipId + selectedKeyframe) live OUTSIDE the project
|
|
693
|
+
* snapshot, so undo / redo can leave them pointing at ids that no
|
|
694
|
+
* longer exist. Defend against dangling refs by clearing anything
|
|
695
|
+
* the restored project doesn't actually contain — and emit the
|
|
696
|
+
* paired change events so panels / overlays hide cleanly instead
|
|
697
|
+
* of holding zombie references.
|
|
698
|
+
*/
|
|
699
|
+
private reconcileSelectionsWithProject;
|
|
433
700
|
on<K extends EditorEventName>(event: K, handler: (payload: EditorEventMap[K]) => void): () => void;
|
|
434
701
|
off<K extends EditorEventName>(event: K, handler: (payload: EditorEventMap[K]) => void): void;
|
|
435
702
|
destroy(): void;
|
|
@@ -441,6 +708,32 @@ declare class Editor implements EditorApi {
|
|
|
441
708
|
private handleSourceMetadata;
|
|
442
709
|
}
|
|
443
710
|
|
|
711
|
+
/**
|
|
712
|
+
* The transform a clip's content is rendered with at a given moment.
|
|
713
|
+
* Engines apply this INSIDE a fixed output frame: `panX` / `panY`
|
|
714
|
+
* translate the content (in CSS px), `scale` resizes it around the
|
|
715
|
+
* output frame's center. Anything pushed outside the frame is
|
|
716
|
+
* clipped. Identity = `{ panX: 0, panY: 0, scale: 1 }`.
|
|
717
|
+
*/
|
|
718
|
+
interface EffectiveTransform {
|
|
719
|
+
panX: number;
|
|
720
|
+
panY: number;
|
|
721
|
+
scale: number;
|
|
722
|
+
}
|
|
723
|
+
/** Identity transform — no pan, no scaling (content fills the output frame). */
|
|
724
|
+
declare const IDENTITY_TRANSFORM: EffectiveTransform;
|
|
725
|
+
/** True when a transform is effectively identity (within FP slop). */
|
|
726
|
+
declare function isIdentityTransform(t: EffectiveTransform): boolean;
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Effective transform = all three properties evaluated together. The
|
|
730
|
+
* engine applies this to the content inside the fixed output frame:
|
|
731
|
+
* scale around frame center, then translate by (panX, panY).
|
|
732
|
+
*/
|
|
733
|
+
declare function getEffectiveTransform(clip: Clip, localMs: Ms): EffectiveTransform;
|
|
734
|
+
/** Same as `getEffectiveTransform` but takes timeline-absolute time. */
|
|
735
|
+
declare function getTransformAtTimelineTime(clip: Clip, timelineMs: Ms): EffectiveTransform;
|
|
736
|
+
|
|
444
737
|
declare function createEmptyProject(): Project;
|
|
445
738
|
/**
|
|
446
739
|
* Defensive normalization — ensures clips on each track are sorted by
|
|
@@ -528,6 +821,23 @@ interface TimelineOptions {
|
|
|
528
821
|
}) => void;
|
|
529
822
|
onResizeClip?: (clipId: string, edits: Partial<Pick<Clip, "in" | "out" | "start">>) => void;
|
|
530
823
|
onChange?: (project: Project) => void;
|
|
824
|
+
/**
|
|
825
|
+
* Hosts wire these to forward keyframe edits to the Editor. The
|
|
826
|
+
* Timeline only paints + hit-tests; mutation goes through these
|
|
827
|
+
* callbacks so the Editor can push history + emit events.
|
|
828
|
+
*/
|
|
829
|
+
onSelectKeyframe?: (target: {
|
|
830
|
+
clipId: string;
|
|
831
|
+
keyframeId: string;
|
|
832
|
+
} | null) => void;
|
|
833
|
+
onMoveKeyframe?: (clipId: string, keyframeId: string, timeMs: Ms) => void;
|
|
834
|
+
/** Host-driven state mirror — Editor passes these on every render
|
|
835
|
+
* via `Timeline.setKeyframeState`. */
|
|
836
|
+
keyframesEnabled?: boolean;
|
|
837
|
+
selectedKeyframe?: {
|
|
838
|
+
clipId: string;
|
|
839
|
+
keyframeId: string;
|
|
840
|
+
} | null;
|
|
531
841
|
/**
|
|
532
842
|
* Lets the host predict where a drop will actually land — used to
|
|
533
843
|
* keep the drag-ghost visual honest. The Editor wires this to its
|
|
@@ -576,6 +886,8 @@ declare class Timeline {
|
|
|
576
886
|
private readOnly;
|
|
577
887
|
private autoFitEnabled;
|
|
578
888
|
private locale;
|
|
889
|
+
private keyframesEnabled;
|
|
890
|
+
private selectedKeyframe;
|
|
579
891
|
private scrollLeft;
|
|
580
892
|
private scrollTop;
|
|
581
893
|
private viewportWidth;
|
|
@@ -594,6 +906,7 @@ declare class Timeline {
|
|
|
594
906
|
private scrollbarDrag;
|
|
595
907
|
private hoveredClipId;
|
|
596
908
|
private hoveredTrackIndex;
|
|
909
|
+
private hoveredKeyframe;
|
|
597
910
|
private hoverCursor;
|
|
598
911
|
private dropTargetTrackIndex;
|
|
599
912
|
private snapX;
|
|
@@ -690,6 +1003,15 @@ declare class Timeline {
|
|
|
690
1003
|
private maybeContinueFade;
|
|
691
1004
|
private maybeAutoFit;
|
|
692
1005
|
private buildDrawState;
|
|
1006
|
+
/** Host-pushed state — Editor calls this when its keyframe mode
|
|
1007
|
+
* changes or when a keyframe is selected/deselected externally. */
|
|
1008
|
+
setKeyframeState(state: {
|
|
1009
|
+
enabled?: boolean;
|
|
1010
|
+
selected?: {
|
|
1011
|
+
clipId: string;
|
|
1012
|
+
keyframeId: string;
|
|
1013
|
+
} | null;
|
|
1014
|
+
}): void;
|
|
693
1015
|
private readStyle;
|
|
694
1016
|
private attachPointer;
|
|
695
1017
|
private onPointerDown;
|
|
@@ -718,6 +1040,7 @@ declare class Timeline {
|
|
|
718
1040
|
*/
|
|
719
1041
|
private maybeStartDragAutoScroll;
|
|
720
1042
|
private onPointerUp;
|
|
1043
|
+
private attachKeyboard;
|
|
721
1044
|
private attachWheel;
|
|
722
1045
|
private attachResize;
|
|
723
1046
|
private localCoords;
|
|
@@ -726,4 +1049,4 @@ declare class Timeline {
|
|
|
726
1049
|
private applySnap;
|
|
727
1050
|
}
|
|
728
1051
|
|
|
729
|
-
export { CanvasCompositorEngine, type CanvasCompositorEngineOptions, Clip, Editor, type EditorApi, type EditorEventMap, type EditorEventName, type EditorOptions, HEADER_WIDTH, HtmlVideoEngine, Locale, MediaSource, Ms, PlaybackEngine, PlaybackEngineFactory, PlaybackEngineOptions, Project, RULER_HEIGHT, TRACK_HEIGHT, Theme, Timeline, type TimelineOptions, Track, canvasCompositorEngineFactory, createEmptyProject, createId, htmlVideoEngineFactory, normalizeProject, setTimelineMetrics };
|
|
1052
|
+
export { CanvasCompositorEngine, type CanvasCompositorEngineOptions, Clip, EasingKind, Editor, type EditorApi, type EditorEventMap, type EditorEventName, type EditorOptions, type EffectiveTransform, HEADER_WIDTH, HtmlVideoEngine, IDENTITY_TRANSFORM, KeyframeProp, Locale, MediaSource, Ms, PlaybackEngine, PlaybackEngineFactory, PlaybackEngineOptions, Project, RULER_HEIGHT, TRACK_HEIGHT, Theme, Timeline, type TimelineOptions, Track, canvasCompositorEngineFactory, createEmptyProject, createId, getEffectiveTransform, getTransformAtTimelineTime, htmlVideoEngineFactory, isIdentityTransform, normalizeProject, setTimelineMetrics };
|