@aicut/vue 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 CHANGED
@@ -233,6 +233,49 @@ const factory = computed(() =>
233
233
 
234
234
  `WebCodecsEngine` v1 covers single-track MP4/MOV playback (H.264 / HEVC / VP9 / AV1 — whatever the browser's `VideoDecoder` supports). Multi-track compositing, audio, transitions land in follow-up releases.
235
235
 
236
+ ## Keyframes (panX / panY / scale animation)
237
+
238
+ Off by default. Flip the `keyframes` prop and **all three** playback engines (HTML5, Canvas, WebCodecs) start interpolating per-clip transforms between adjacent keyframes. Diamond markers appear on the timeline; drag them, edit values via the floating panel, snap them to each other.
239
+
240
+ ```vue
241
+ <script setup lang="ts">
242
+ import { ref } from "vue";
243
+ const kfEnabled = ref(true);
244
+ const edgeNav = ref(true);
245
+ function onKfSelection(t: { clipId: string; keyframeId: string } | null) {
246
+ console.log(t);
247
+ }
248
+ </script>
249
+
250
+ <template>
251
+ <VideoEditor
252
+ ref="editor"
253
+ :default-project="project"
254
+ :keyframes="{ enabled: kfEnabled }"
255
+ :clip-edge-nav="{ enabled: edgeNav }"
256
+ @keyframe-selection-change="onKfSelection"
257
+ />
258
+ </template>
259
+ ```
260
+
261
+ ```ts
262
+ // Per-property mutators on the editor API.
263
+ api.addKeyframe("clip-1", "scale", { time: 0, value: 1 });
264
+ api.addKeyframe("clip-1", "scale", { time: 2000, value: 2.5, easing: "easeInOut" });
265
+ api.setKeyframeValue("clip-1", kfId, 1.8);
266
+ api.setKeyframeEasing("clip-1", kfId, "easeOut");
267
+
268
+ // Toolbar-style "K at playhead" drops all 3 props at once.
269
+ api.setSelection("clip-1");
270
+ api.toggleKeyframeAtPlayhead();
271
+ ```
272
+
273
+ `Keyframe`, `KeyframeProp`, `EasingKind`, `EffectiveTransform`, `getEffectiveTransform`, `getTransformAtTimelineTime`, `IDENTITY_TRANSFORM`, `isIdentityTransform` are all re-exported from `@aicut/vue` for thumbnail / preview rendering outside the editor.
274
+
275
+ **Backend export:** both `@aicut/backend-ts` and `@aicut/backend-go` compile keyframes to ffmpeg `t`-expressions (`scale=…:eval=frame` + `overlay=…:eval=frame`). Pass `output: { width, height, fps }` in the export request — required for the keyframe filter graph to apply.
276
+
277
+ See [@aicut/core's keyframes section](https://www.npmjs.com/package/@aicut/core#keyframes-per-clip-panx--pany--scale-animation) for the full API.
278
+
236
279
  ## `<LightingEditor>` (opt-in sub-entry)
237
280
 
238
281
  A 3D lighting director for AI relighting flows — separate sub-entry; three.js bundles only here.
@@ -30,6 +30,24 @@ type __VLS_Props = {
30
30
  * 100% and shows an internal scrollbar when track count overflows.
31
31
  */
32
32
  timelineHeight?: number;
33
+ /**
34
+ * Per-clip keyframe animation (X / Y / Scale). Reactive — set
35
+ * `{ enabled: true }` to surface keyframe diamonds on the timeline
36
+ * and route the canvas-based engines through the transform pipeline.
37
+ * Data is preserved when disabled.
38
+ */
39
+ keyframes?: {
40
+ enabled?: boolean;
41
+ };
42
+ /**
43
+ * Jump-to-clip-edge toolbar cluster (|◀ ▶|) + I/O keyboard shortcuts.
44
+ * Reactive — set `{ enabled: true }` to surface the buttons next to
45
+ * the keyframe diamond and bind the shortcuts. Off hides the buttons
46
+ * entirely (no toolbar space cost).
47
+ */
48
+ clipEdgeNav?: {
49
+ enabled?: boolean;
50
+ };
33
51
  };
34
52
  declare var __VLS_5: {}, __VLS_11: {};
35
53
  type __VLS_Slots = {} & {
@@ -48,6 +66,10 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
48
66
  play: () => any;
49
67
  pause: () => any;
50
68
  selectionChange: (clipId: string | null) => any;
69
+ keyframeSelectionChange: (target: {
70
+ clipId: string;
71
+ keyframeId: string;
72
+ } | null) => any;
51
73
  error: (error: Error) => any;
52
74
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
53
75
  onReady?: ((api: EditorApi) => any) | undefined;
@@ -57,6 +79,10 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
57
79
  onPlay?: (() => any) | undefined;
58
80
  onPause?: (() => any) | undefined;
59
81
  onSelectionChange?: ((clipId: string | null) => any) | undefined;
82
+ onKeyframeSelectionChange?: ((target: {
83
+ clipId: string;
84
+ keyframeId: string;
85
+ } | null) => any) | undefined;
60
86
  onError?: ((error: Error) => any) | undefined;
61
87
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
62
88
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
@@ -1 +1 @@
1
- {"version":3,"file":"VideoEditor.vue.d.ts","sourceRoot":"","sources":["../src/VideoEditor.vue"],"names":[],"mappings":"AA6JA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wFAAwF;IACxF,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAmJF,QAAA,IAAI,OAAO,IAAU,EAAE,QAAQ,IAAY,CAAE;AAC7C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAC/C;IAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAwBpD,QAAA,MAAM,eAAe;IA5EnB,kEAAkE;eACzD,SAAS,GAAG,IAAI;;;;;;;;;;;;;;;;;;;kFAmFzB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"VideoEditor.vue.d.ts","sourceRoot":"","sources":["../src/VideoEditor.vue"],"names":[],"mappings":"AA4MA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wFAAwF;IACxF,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACrC,CAAC;AAoLF,QAAA,IAAI,OAAO,IAAU,EAAE,QAAQ,IAAY,CAAE;AAC7C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAC/C;IAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAwBpD,QAAA,MAAM,eAAe;IA5EnB,kEAAkE;eACzD,SAAS,GAAG,IAAI;;;;;;;;;;gBAvHL,MAAM;oBAAc,MAAM;;;;;;;;;;;;gBAA1B,MAAM;oBAAc,MAAM;;;kFA0M9C,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue"),a=require("@aicut/core"),h=t.defineComponent({__name:"VideoEditor",props:{defaultProject:{},theme:{},locale:{},playbackEngine:{type:Function},trackHeight:{},rulerHeight:{},timelineHeight:{}},emits:["ready","change","export","timeUpdate","play","pause","selectionChange","error"],setup(p,{expose:d,emit:m}){const o=p,l=m,c=t.ref(null);let e=null;const r=[],i=t.ref(null),u=t.ref(null);return t.onMounted(()=>{c.value&&(e=a.Editor.create({container:c.value,project:o.defaultProject,theme:o.theme,locale:o.locale,playbackEngine:o.playbackEngine,...o.trackHeight!=null?{trackHeight:o.trackHeight}:{},...o.rulerHeight!=null?{rulerHeight:o.rulerHeight}:{},...o.timelineHeight!=null?{timelineHeight:o.timelineHeight}:{}}),r.push(e.on("change",({project:n})=>l("change",n)),e.on("export",({project:n})=>l("export",n)),e.on("time",({timeMs:n})=>l("timeUpdate",n)),e.on("play",()=>l("play")),e.on("pause",()=>l("pause")),e.on("selectionChange",({clipId:n})=>l("selectionChange",n)),e.on("error",({error:n})=>l("error",n))),i.value=e.headerLeft,u.value=e.headerRight,l("ready",e))}),t.watch(()=>o.theme,n=>{n&&e&&e.setTheme(n)}),t.watch(()=>o.locale,n=>{n&&e&&e.setLocale(n)}),t.watch(()=>o.timelineHeight,n=>{const s=c.value;s&&(n!=null&&n>0?s.style.setProperty("--aicut-timeline-height",`${Math.round(n)}px`):s.style.removeProperty("--aicut-timeline-height"))}),t.onBeforeUnmount(()=>{for(const n of r)n();r.length=0,e==null||e.destroy(),e=null,i.value=null,u.value=null}),d({api:()=>e}),(n,s)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"host",ref:c,"data-aicut-host":""},[i.value?(t.openBlock(),t.createBlock(t.Teleport,{key:0,to:i.value},[t.renderSlot(n.$slots,"headerLeft")],8,["to"])):t.createCommentVNode("",!0),u.value?(t.openBlock(),t.createBlock(t.Teleport,{key:1,to:u.value},[t.renderSlot(n.$slots,"headerRight")],8,["to"])):t.createCommentVNode("",!0)],512))}}),g=t.defineComponent({__name:"Timeline",props:{defaultProject:{},defaultScale:{},defaultTime:{},defaultSelectedClipId:{},showHeader:{type:Boolean},readOnly:{type:Boolean},snap:{type:Boolean},autoFit:{type:Boolean},locale:{}},emits:["seek","selectClip","scaleChange","moveClip","resizeClip","change"],setup(p,{expose:d,emit:m}){const o=p,l=m,c=t.ref(null);let e=null;return t.onMounted(()=>{c.value&&(e=a.Timeline.create({container:c.value,project:o.defaultProject,pxPerSec:o.defaultScale,time:o.defaultTime,selectedClipId:o.defaultSelectedClipId??null,showHeader:o.showHeader,readOnly:o.readOnly,snap:o.snap,autoFit:o.autoFit,locale:o.locale,onSeek:r=>l("seek",r),onSelectClip:r=>l("selectClip",r),onScaleChange:r=>l("scaleChange",r),onMoveClip:(r,i)=>l("moveClip",r,i),onResizeClip:(r,i)=>l("resizeClip",r,i),onChange:r=>l("change",r)}))}),t.watch(()=>o.locale,r=>{r&&e&&e.setLocale(r)}),t.onBeforeUnmount(()=>{e==null||e.destroy(),e=null}),d({api:()=>e}),(r,i)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"host",ref:c,"data-aicut-timeline-host":"",style:{width:"100%",height:"240px"}},null,512))}});Object.defineProperty(exports,"CanvasCompositorEngine",{enumerable:!0,get:()=>a.CanvasCompositorEngine});Object.defineProperty(exports,"HEADER_WIDTH",{enumerable:!0,get:()=>a.HEADER_WIDTH});Object.defineProperty(exports,"HtmlVideoEngine",{enumerable:!0,get:()=>a.HtmlVideoEngine});Object.defineProperty(exports,"RULER_HEIGHT",{enumerable:!0,get:()=>a.RULER_HEIGHT});Object.defineProperty(exports,"TRACK_HEIGHT",{enumerable:!0,get:()=>a.TRACK_HEIGHT});Object.defineProperty(exports,"canvasCompositorEngineFactory",{enumerable:!0,get:()=>a.canvasCompositorEngineFactory});Object.defineProperty(exports,"createEmptyProject",{enumerable:!0,get:()=>a.createEmptyProject});Object.defineProperty(exports,"createId",{enumerable:!0,get:()=>a.createId});Object.defineProperty(exports,"htmlVideoEngineFactory",{enumerable:!0,get:()=>a.htmlVideoEngineFactory});Object.defineProperty(exports,"localeEn",{enumerable:!0,get:()=>a.localeEn});Object.defineProperty(exports,"localeZh",{enumerable:!0,get:()=>a.localeZh});Object.defineProperty(exports,"setTimelineMetrics",{enumerable:!0,get:()=>a.setTimelineMetrics});exports.Timeline=g;exports.VideoEditor=h;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("vue"),o=require("@aicut/core"),f=n.defineComponent({__name:"VideoEditor",props:{defaultProject:{},theme:{},locale:{},playbackEngine:{type:Function},trackHeight:{},rulerHeight:{},timelineHeight:{},keyframes:{},clipEdgeNav:{}},emits:["ready","change","export","timeUpdate","play","pause","selectionChange","keyframeSelectionChange","error"],setup(d,{expose:p,emit:m}){const r=d,a=m,u=n.ref(null);let e=null;const l=[],c=n.ref(null),s=n.ref(null);return n.onMounted(()=>{u.value&&(e=o.Editor.create({container:u.value,project:r.defaultProject,theme:r.theme,locale:r.locale,playbackEngine:r.playbackEngine,...r.trackHeight!=null?{trackHeight:r.trackHeight}:{},...r.rulerHeight!=null?{rulerHeight:r.rulerHeight}:{},...r.timelineHeight!=null?{timelineHeight:r.timelineHeight}:{},...r.keyframes!=null?{keyframes:r.keyframes}:{},...r.clipEdgeNav!=null?{clipEdgeNav:r.clipEdgeNav}:{}}),l.push(e.on("change",({project:t})=>a("change",t)),e.on("export",({project:t})=>a("export",t)),e.on("time",({timeMs:t})=>a("timeUpdate",t)),e.on("play",()=>a("play")),e.on("pause",()=>a("pause")),e.on("selectionChange",({clipId:t})=>a("selectionChange",t)),e.on("keyframeSelectionChange",({target:t})=>a("keyframeSelectionChange",t)),e.on("error",({error:t})=>a("error",t))),c.value=e.headerLeft,s.value=e.headerRight,a("ready",e))}),n.watch(()=>r.theme,t=>{t&&e&&e.setTheme(t)}),n.watch(()=>r.locale,t=>{t&&e&&e.setLocale(t)}),n.watch(()=>{var t;return(t=r.keyframes)==null?void 0:t.enabled},t=>{if(!e)return;const i=t===!0;e.isKeyframesEnabled()!==i&&e.setKeyframesEnabled(i)}),n.watch(()=>{var t;return(t=r.clipEdgeNav)==null?void 0:t.enabled},t=>{if(!e)return;const i=t===!0;e.isClipEdgeNavEnabled()!==i&&e.setClipEdgeNavEnabled(i)}),n.watch(()=>r.timelineHeight,t=>{const i=u.value;i&&(t!=null&&t>0?i.style.setProperty("--aicut-timeline-height",`${Math.round(t)}px`):i.style.removeProperty("--aicut-timeline-height"))}),n.onBeforeUnmount(()=>{for(const t of l)t();l.length=0,e==null||e.destroy(),e=null,c.value=null,s.value=null}),p({api:()=>e}),(t,i)=>(n.openBlock(),n.createElementBlock("div",{ref_key:"host",ref:u,"data-aicut-host":""},[c.value?(n.openBlock(),n.createBlock(n.Teleport,{key:0,to:c.value},[n.renderSlot(t.$slots,"headerLeft")],8,["to"])):n.createCommentVNode("",!0),s.value?(n.openBlock(),n.createBlock(n.Teleport,{key:1,to:s.value},[n.renderSlot(t.$slots,"headerRight")],8,["to"])):n.createCommentVNode("",!0)],512))}}),g=n.defineComponent({__name:"Timeline",props:{defaultProject:{},defaultScale:{},defaultTime:{},defaultSelectedClipId:{},showHeader:{type:Boolean},readOnly:{type:Boolean},snap:{type:Boolean},autoFit:{type:Boolean},locale:{}},emits:["seek","selectClip","scaleChange","moveClip","resizeClip","change"],setup(d,{expose:p,emit:m}){const r=d,a=m,u=n.ref(null);let e=null;return n.onMounted(()=>{u.value&&(e=o.Timeline.create({container:u.value,project:r.defaultProject,pxPerSec:r.defaultScale,time:r.defaultTime,selectedClipId:r.defaultSelectedClipId??null,showHeader:r.showHeader,readOnly:r.readOnly,snap:r.snap,autoFit:r.autoFit,locale:r.locale,onSeek:l=>a("seek",l),onSelectClip:l=>a("selectClip",l),onScaleChange:l=>a("scaleChange",l),onMoveClip:(l,c)=>a("moveClip",l,c),onResizeClip:(l,c)=>a("resizeClip",l,c),onChange:l=>a("change",l)}))}),n.watch(()=>r.locale,l=>{l&&e&&e.setLocale(l)}),n.onBeforeUnmount(()=>{e==null||e.destroy(),e=null}),p({api:()=>e}),(l,c)=>(n.openBlock(),n.createElementBlock("div",{ref_key:"host",ref:u,"data-aicut-timeline-host":"",style:{width:"100%",height:"240px"}},null,512))}});Object.defineProperty(exports,"CanvasCompositorEngine",{enumerable:!0,get:()=>o.CanvasCompositorEngine});Object.defineProperty(exports,"HEADER_WIDTH",{enumerable:!0,get:()=>o.HEADER_WIDTH});Object.defineProperty(exports,"HtmlVideoEngine",{enumerable:!0,get:()=>o.HtmlVideoEngine});Object.defineProperty(exports,"IDENTITY_TRANSFORM",{enumerable:!0,get:()=>o.IDENTITY_TRANSFORM});Object.defineProperty(exports,"RULER_HEIGHT",{enumerable:!0,get:()=>o.RULER_HEIGHT});Object.defineProperty(exports,"TRACK_HEIGHT",{enumerable:!0,get:()=>o.TRACK_HEIGHT});Object.defineProperty(exports,"canvasCompositorEngineFactory",{enumerable:!0,get:()=>o.canvasCompositorEngineFactory});Object.defineProperty(exports,"createEmptyProject",{enumerable:!0,get:()=>o.createEmptyProject});Object.defineProperty(exports,"createId",{enumerable:!0,get:()=>o.createId});Object.defineProperty(exports,"getEffectiveTransform",{enumerable:!0,get:()=>o.getEffectiveTransform});Object.defineProperty(exports,"getTransformAtTimelineTime",{enumerable:!0,get:()=>o.getTransformAtTimelineTime});Object.defineProperty(exports,"htmlVideoEngineFactory",{enumerable:!0,get:()=>o.htmlVideoEngineFactory});Object.defineProperty(exports,"isIdentityTransform",{enumerable:!0,get:()=>o.isIdentityTransform});Object.defineProperty(exports,"localeEn",{enumerable:!0,get:()=>o.localeEn});Object.defineProperty(exports,"localeZh",{enumerable:!0,get:()=>o.localeZh});Object.defineProperty(exports,"setTimelineMetrics",{enumerable:!0,get:()=>o.setTimelineMetrics});exports.Timeline=g;exports.VideoEditor=f;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/VideoEditor.vue","../src/Timeline.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Editor,\n type EditorApi,\n type Locale,\n type Ms,\n type PlaybackEngineFactory,\n type Project,\n type Theme,\n} from \"@aicut/core\";\n\n/**\n * Vue 3 wrapper around `@aicut/core`. Same shape as `@aicut/react`:\n * uncontrolled for project state, theme is reactive, API exposed via\n * `defineExpose` so a parent `ref` can call cut/seek/setProject/etc.\n */\nconst props = defineProps<{\n defaultProject?: Project;\n theme?: Theme;\n /** UI string overrides (English default). Reactive — swap to `localeZh` for Chinese. */\n locale?: Partial<Locale>;\n /**\n * Initial-only factory for a custom playback engine. Defaults to the\n * built-in `HtmlVideoEngine`. Pass `WebCodecsEngine` (v0.6+) or your\n * own engine to override. Bound at mount; later prop changes are\n * ignored.\n */\n playbackEngine?: PlaybackEngineFactory;\n /**\n * Initial-only — pixel height of each track row (default 56). Lower\n * values (~32–40) shrink the timeline for small viewports. Applied\n * process-wide at construction time.\n */\n trackHeight?: number;\n /** Initial-only — pixel height of the timeline ruler (default 24). */\n rulerHeight?: number;\n /**\n * Pixel height of the whole bottom timeline area (default 240).\n * Reactive — swap any time to recompact. The canvas inside fills\n * 100% and shows an internal scrollbar when track count overflows.\n */\n timelineHeight?: number;\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\", api: EditorApi): void;\n (e: \"change\", project: Project): void;\n (e: \"export\", project: Project): void;\n (e: \"timeUpdate\", timeMs: Ms): void;\n (e: \"play\"): void;\n (e: \"pause\"): void;\n (e: \"selectionChange\", clipId: string | null): void;\n (e: \"error\", error: Error): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet editor: Editor | null = null;\nconst offs: Array<() => void> = [];\n/** Header slot DOM nodes — set after editor mount so Vue Teleports\n * have a valid target. Library renders nothing here; named slots\n * `#headerLeft` / `#headerRight` portal whatever the host provides. */\nconst headerLeftSlot = ref<HTMLElement | null>(null);\nconst headerRightSlot = ref<HTMLElement | null>(null);\n\nonMounted(() => {\n if (!host.value) return;\n editor = Editor.create({\n container: host.value,\n project: props.defaultProject,\n theme: props.theme,\n locale: props.locale,\n playbackEngine: props.playbackEngine,\n ...(props.trackHeight != null ? { trackHeight: props.trackHeight } : {}),\n ...(props.rulerHeight != null ? { rulerHeight: props.rulerHeight } : {}),\n ...(props.timelineHeight != null\n ? { timelineHeight: props.timelineHeight }\n : {}),\n });\n\n offs.push(\n editor.on(\"change\", ({ project }) => emit(\"change\", project)),\n editor.on(\"export\", ({ project }) => emit(\"export\", project)),\n editor.on(\"time\", ({ timeMs }) => emit(\"timeUpdate\", timeMs)),\n editor.on(\"play\", () => emit(\"play\")),\n editor.on(\"pause\", () => emit(\"pause\")),\n editor.on(\"selectionChange\", ({ clipId }) =>\n emit(\"selectionChange\", clipId),\n ),\n editor.on(\"error\", ({ error }) => emit(\"error\", error)),\n );\n\n headerLeftSlot.value = editor.headerLeft;\n headerRightSlot.value = editor.headerRight;\n emit(\"ready\", editor);\n});\n\nwatch(\n () => props.theme,\n (theme) => {\n if (theme && editor) editor.setTheme(theme);\n },\n);\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && editor) editor.setLocale(locale);\n },\n);\n\n// Reactive — sets the CSS custom property directly so the timeline\n// height can be tweaked without remounting.\nwatch(\n () => props.timelineHeight,\n (timelineHeight) => {\n const root = host.value;\n if (!root) return;\n if (timelineHeight != null && timelineHeight > 0) {\n root.style.setProperty(\n \"--aicut-timeline-height\",\n `${Math.round(timelineHeight)}px`,\n );\n } else {\n root.style.removeProperty(\"--aicut-timeline-height\");\n }\n },\n);\n\nonBeforeUnmount(() => {\n for (const off of offs) off();\n offs.length = 0;\n editor?.destroy();\n editor = null;\n headerLeftSlot.value = null;\n headerRightSlot.value = null;\n});\n\ndefineExpose({\n /** Returns the underlying core API or null if not yet mounted. */\n api: (): EditorApi | null => editor,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-host=\"\">\n <Teleport v-if=\"headerLeftSlot\" :to=\"headerLeftSlot\">\n <slot name=\"headerLeft\" />\n </Teleport>\n <Teleport v-if=\"headerRightSlot\" :to=\"headerRightSlot\">\n <slot name=\"headerRight\" />\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Timeline as CoreTimeline,\n type Clip,\n type Locale,\n type Ms,\n type Project,\n} from \"@aicut/core\";\n\n/**\n * Standalone canvas Timeline wrapped for Vue 3. Same surface as the\n * React `<Timeline>`: pass `defaultProject`, drive imperatively via\n * the exposed `api()` ref.\n */\nconst props = defineProps<{\n defaultProject: Project;\n defaultScale?: number;\n defaultTime?: Ms;\n defaultSelectedClipId?: string | null;\n showHeader?: boolean;\n readOnly?: boolean;\n snap?: boolean;\n autoFit?: boolean;\n locale?: Partial<Locale>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"seek\", timeMs: Ms): void;\n (e: \"selectClip\", clipId: string | null): void;\n (e: \"scaleChange\", pxPerSec: number): void;\n (e: \"moveClip\", clipId: string, opts: { start?: Ms; trackId?: string }): void;\n (\n e: \"resizeClip\",\n clipId: string,\n edits: Partial<Pick<Clip, \"in\" | \"out\" | \"start\">>,\n ): void;\n (e: \"change\", project: Project): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet timeline: CoreTimeline | null = null;\n\nonMounted(() => {\n if (!host.value) return;\n timeline = CoreTimeline.create({\n container: host.value,\n project: props.defaultProject,\n pxPerSec: props.defaultScale,\n time: props.defaultTime,\n selectedClipId: props.defaultSelectedClipId ?? null,\n showHeader: props.showHeader,\n readOnly: props.readOnly,\n snap: props.snap,\n autoFit: props.autoFit,\n locale: props.locale,\n onSeek: (t) => emit(\"seek\", t),\n onSelectClip: (id) => emit(\"selectClip\", id),\n onScaleChange: (s) => emit(\"scaleChange\", s),\n onMoveClip: (id, opts) => emit(\"moveClip\", id, opts),\n onResizeClip: (id, edits) => emit(\"resizeClip\", id, edits),\n onChange: (p) => emit(\"change\", p),\n });\n});\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && timeline) timeline.setLocale(locale);\n },\n);\n\nonBeforeUnmount(() => {\n timeline?.destroy();\n timeline = null;\n});\n\ndefineExpose({\n api: (): CoreTimeline | null => timeline,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-timeline-host=\"\" :style=\"{ width: '100%', height: '240px' }\" />\n</template>\n"],"names":["props","__props","emit","__emit","host","ref","editor","offs","headerLeftSlot","headerRightSlot","onMounted","Editor","project","timeMs","clipId","error","watch","theme","locale","timelineHeight","root","onBeforeUnmount","off","__expose","_createElementBlock","_createBlock","_Teleport","_renderSlot","_ctx","timeline","CoreTimeline","t","id","s","opts","edits","p"],"mappings":"yZAiBA,MAAMA,EAAQC,EA4BRC,EAAOC,EAWPC,EAAOC,EAAAA,IAA2B,IAAI,EAC5C,IAAIC,EAAwB,KAC5B,MAAMC,EAA0B,CAAA,EAI1BC,EAAiBH,EAAAA,IAAwB,IAAI,EAC7CI,EAAkBJ,EAAAA,IAAwB,IAAI,EAEpDK,OAAAA,EAAAA,UAAU,IAAM,CACTN,EAAK,QACVE,EAASK,EAAAA,OAAO,OAAO,CACrB,UAAWP,EAAK,MAChB,QAASJ,EAAM,eACf,MAAOA,EAAM,MACb,OAAQA,EAAM,OACd,eAAgBA,EAAM,eACtB,GAAIA,EAAM,aAAe,KAAO,CAAE,YAAaA,EAAM,WAAA,EAAgB,CAAA,EACrE,GAAIA,EAAM,aAAe,KAAO,CAAE,YAAaA,EAAM,WAAA,EAAgB,CAAA,EACrE,GAAIA,EAAM,gBAAkB,KACxB,CAAE,eAAgBA,EAAM,gBACxB,CAAA,CAAC,CACN,EAEDO,EAAK,KACHD,EAAO,GAAG,SAAU,CAAC,CAAE,QAAAM,KAAcV,EAAK,SAAUU,CAAO,CAAC,EAC5DN,EAAO,GAAG,SAAU,CAAC,CAAE,QAAAM,KAAcV,EAAK,SAAUU,CAAO,CAAC,EAC5DN,EAAO,GAAG,OAAQ,CAAC,CAAE,OAAAO,KAAaX,EAAK,aAAcW,CAAM,CAAC,EAC5DP,EAAO,GAAG,OAAQ,IAAMJ,EAAK,MAAM,CAAC,EACpCI,EAAO,GAAG,QAAS,IAAMJ,EAAK,OAAO,CAAC,EACtCI,EAAO,GAAG,kBAAmB,CAAC,CAAE,OAAAQ,CAAA,IAC9BZ,EAAK,kBAAmBY,CAAM,CAAA,EAEhCR,EAAO,GAAG,QAAS,CAAC,CAAE,MAAAS,KAAYb,EAAK,QAASa,CAAK,CAAC,CAAA,EAGxDP,EAAe,MAAQF,EAAO,WAC9BG,EAAgB,MAAQH,EAAO,YAC/BJ,EAAK,QAASI,CAAM,EACtB,CAAC,EAEDU,EAAAA,MACE,IAAMhB,EAAM,MACXiB,GAAU,CACLA,GAASX,GAAQA,EAAO,SAASW,CAAK,CAC5C,CAAA,EAGFD,EAAAA,MACE,IAAMhB,EAAM,OACXkB,GAAW,CACNA,GAAUZ,GAAQA,EAAO,UAAUY,CAAM,CAC/C,CAAA,EAKFF,EAAAA,MACE,IAAMhB,EAAM,eACXmB,GAAmB,CAClB,MAAMC,EAAOhB,EAAK,MACbgB,IACDD,GAAkB,MAAQA,EAAiB,EAC7CC,EAAK,MAAM,YACT,0BACA,GAAG,KAAK,MAAMD,CAAc,CAAC,IAAA,EAG/BC,EAAK,MAAM,eAAe,yBAAyB,EAEvD,CAAA,EAGFC,EAAAA,gBAAgB,IAAM,CACpB,UAAWC,KAAOf,EAAMe,EAAA,EACxBf,EAAK,OAAS,EACdD,GAAA,MAAAA,EAAQ,UACRA,EAAS,KACTE,EAAe,MAAQ,KACvBC,EAAgB,MAAQ,IAC1B,CAAC,EAEDc,EAAa,CAEX,IAAK,IAAwBjB,CAAA,CAC9B,wBAICkB,EAAAA,mBAOM,MAAA,SAPG,OAAJ,IAAIpB,EAAO,kBAAgB,EAAA,GACdI,EAAA,qBAAhBiB,EAAAA,YAEWC,EAAAA,SAAA,OAFsB,GAAIlB,EAAA,KAAA,GACnCmB,aAA0BC,EAAA,OAAA,YAAA,CAAA,yCAEZnB,EAAA,qBAAhBgB,EAAAA,YAEWC,EAAAA,SAAA,OAFuB,GAAIjB,EAAA,KAAA,GACpCkB,aAA2BC,EAAA,OAAA,aAAA,CAAA,yXCvIjC,MAAM5B,EAAQC,EAYRC,EAAOC,EAaPC,EAAOC,EAAAA,IAA2B,IAAI,EAC5C,IAAIwB,EAAgC,KAEpCnB,OAAAA,EAAAA,UAAU,IAAM,CACTN,EAAK,QACVyB,EAAWC,EAAAA,SAAa,OAAO,CAC7B,UAAW1B,EAAK,MAChB,QAASJ,EAAM,eACf,SAAUA,EAAM,aAChB,KAAMA,EAAM,YACZ,eAAgBA,EAAM,uBAAyB,KAC/C,WAAYA,EAAM,WAClB,SAAUA,EAAM,SAChB,KAAMA,EAAM,KACZ,QAASA,EAAM,QACf,OAAQA,EAAM,OACd,OAAS+B,GAAM7B,EAAK,OAAQ6B,CAAC,EAC7B,aAAeC,GAAO9B,EAAK,aAAc8B,CAAE,EAC3C,cAAgBC,GAAM/B,EAAK,cAAe+B,CAAC,EAC3C,WAAY,CAACD,EAAIE,IAAShC,EAAK,WAAY8B,EAAIE,CAAI,EACnD,aAAc,CAACF,EAAIG,IAAUjC,EAAK,aAAc8B,EAAIG,CAAK,EACzD,SAAWC,GAAMlC,EAAK,SAAUkC,CAAC,CAAA,CAClC,EACH,CAAC,EAEDpB,EAAAA,MACE,IAAMhB,EAAM,OACXkB,GAAW,CACNA,GAAUW,GAAUA,EAAS,UAAUX,CAAM,CACnD,CAAA,EAGFG,EAAAA,gBAAgB,IAAM,CACpBQ,GAAA,MAAAA,EAAU,UACVA,EAAW,IACb,CAAC,EAEDN,EAAa,CACX,IAAK,IAA2BM,CAAA,CACjC,wBAICL,EAAAA,mBAA0F,MAAA,SAAjF,OAAJ,IAAIpB,EAAO,2BAAyB,GAAI,MAAO,CAAA,MAAA,OAAA,OAAA,OAAA,CAAA"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/VideoEditor.vue","../src/Timeline.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Editor,\n type EditorApi,\n type Locale,\n type Ms,\n type PlaybackEngineFactory,\n type Project,\n type Theme,\n} from \"@aicut/core\";\n\n/**\n * Vue 3 wrapper around `@aicut/core`. Same shape as `@aicut/react`:\n * uncontrolled for project state, theme is reactive, API exposed via\n * `defineExpose` so a parent `ref` can call cut/seek/setProject/etc.\n */\nconst props = defineProps<{\n defaultProject?: Project;\n theme?: Theme;\n /** UI string overrides (English default). Reactive — swap to `localeZh` for Chinese. */\n locale?: Partial<Locale>;\n /**\n * Initial-only factory for a custom playback engine. Defaults to the\n * built-in `HtmlVideoEngine`. Pass `WebCodecsEngine` (v0.6+) or your\n * own engine to override. Bound at mount; later prop changes are\n * ignored.\n */\n playbackEngine?: PlaybackEngineFactory;\n /**\n * Initial-only — pixel height of each track row (default 56). Lower\n * values (~32–40) shrink the timeline for small viewports. Applied\n * process-wide at construction time.\n */\n trackHeight?: number;\n /** Initial-only — pixel height of the timeline ruler (default 24). */\n rulerHeight?: number;\n /**\n * Pixel height of the whole bottom timeline area (default 240).\n * Reactive — swap any time to recompact. The canvas inside fills\n * 100% and shows an internal scrollbar when track count overflows.\n */\n timelineHeight?: number;\n /**\n * Per-clip keyframe animation (X / Y / Scale). Reactive — set\n * `{ enabled: true }` to surface keyframe diamonds on the timeline\n * and route the canvas-based engines through the transform pipeline.\n * Data is preserved when disabled.\n */\n keyframes?: { enabled?: boolean };\n /**\n * Jump-to-clip-edge toolbar cluster (|◀ ▶|) + I/O keyboard shortcuts.\n * Reactive — set `{ enabled: true }` to surface the buttons next to\n * the keyframe diamond and bind the shortcuts. Off hides the buttons\n * entirely (no toolbar space cost).\n */\n clipEdgeNav?: { enabled?: boolean };\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\", api: EditorApi): void;\n (e: \"change\", project: Project): void;\n (e: \"export\", project: Project): void;\n (e: \"timeUpdate\", timeMs: Ms): void;\n (e: \"play\"): void;\n (e: \"pause\"): void;\n (e: \"selectionChange\", clipId: string | null): void;\n (\n e: \"keyframeSelectionChange\",\n target: { clipId: string; keyframeId: string } | null,\n ): void;\n (e: \"error\", error: Error): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet editor: Editor | null = null;\nconst offs: Array<() => void> = [];\n/** Header slot DOM nodes — set after editor mount so Vue Teleports\n * have a valid target. Library renders nothing here; named slots\n * `#headerLeft` / `#headerRight` portal whatever the host provides. */\nconst headerLeftSlot = ref<HTMLElement | null>(null);\nconst headerRightSlot = ref<HTMLElement | null>(null);\n\nonMounted(() => {\n if (!host.value) return;\n editor = Editor.create({\n container: host.value,\n project: props.defaultProject,\n theme: props.theme,\n locale: props.locale,\n playbackEngine: props.playbackEngine,\n ...(props.trackHeight != null ? { trackHeight: props.trackHeight } : {}),\n ...(props.rulerHeight != null ? { rulerHeight: props.rulerHeight } : {}),\n ...(props.timelineHeight != null\n ? { timelineHeight: props.timelineHeight }\n : {}),\n ...(props.keyframes != null ? { keyframes: props.keyframes } : {}),\n ...(props.clipEdgeNav != null ? { clipEdgeNav: props.clipEdgeNav } : {}),\n });\n\n offs.push(\n editor.on(\"change\", ({ project }) => emit(\"change\", project)),\n editor.on(\"export\", ({ project }) => emit(\"export\", project)),\n editor.on(\"time\", ({ timeMs }) => emit(\"timeUpdate\", timeMs)),\n editor.on(\"play\", () => emit(\"play\")),\n editor.on(\"pause\", () => emit(\"pause\")),\n editor.on(\"selectionChange\", ({ clipId }) =>\n emit(\"selectionChange\", clipId),\n ),\n editor.on(\"keyframeSelectionChange\", ({ target }) =>\n emit(\"keyframeSelectionChange\", target),\n ),\n editor.on(\"error\", ({ error }) => emit(\"error\", error)),\n );\n\n headerLeftSlot.value = editor.headerLeft;\n headerRightSlot.value = editor.headerRight;\n emit(\"ready\", editor);\n});\n\nwatch(\n () => props.theme,\n (theme) => {\n if (theme && editor) editor.setTheme(theme);\n },\n);\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && editor) editor.setLocale(locale);\n },\n);\n\n// Reactive — flip keyframe mode without remount. Data preserved.\nwatch(\n () => props.keyframes?.enabled,\n (enabled) => {\n if (!editor) return;\n const desired = enabled === true;\n if (editor.isKeyframesEnabled() !== desired) {\n editor.setKeyframesEnabled(desired);\n }\n },\n);\n\n// Reactive — flip clip-edge nav cluster (|◀ ▶|) + I/O shortcuts.\nwatch(\n () => props.clipEdgeNav?.enabled,\n (enabled) => {\n if (!editor) return;\n const desired = enabled === true;\n if (editor.isClipEdgeNavEnabled() !== desired) {\n editor.setClipEdgeNavEnabled(desired);\n }\n },\n);\n\n// Reactive — sets the CSS custom property directly so the timeline\n// height can be tweaked without remounting.\nwatch(\n () => props.timelineHeight,\n (timelineHeight) => {\n const root = host.value;\n if (!root) return;\n if (timelineHeight != null && timelineHeight > 0) {\n root.style.setProperty(\n \"--aicut-timeline-height\",\n `${Math.round(timelineHeight)}px`,\n );\n } else {\n root.style.removeProperty(\"--aicut-timeline-height\");\n }\n },\n);\n\nonBeforeUnmount(() => {\n for (const off of offs) off();\n offs.length = 0;\n editor?.destroy();\n editor = null;\n headerLeftSlot.value = null;\n headerRightSlot.value = null;\n});\n\ndefineExpose({\n /** Returns the underlying core API or null if not yet mounted. */\n api: (): EditorApi | null => editor,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-host=\"\">\n <Teleport v-if=\"headerLeftSlot\" :to=\"headerLeftSlot\">\n <slot name=\"headerLeft\" />\n </Teleport>\n <Teleport v-if=\"headerRightSlot\" :to=\"headerRightSlot\">\n <slot name=\"headerRight\" />\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Timeline as CoreTimeline,\n type Clip,\n type Locale,\n type Ms,\n type Project,\n} from \"@aicut/core\";\n\n/**\n * Standalone canvas Timeline wrapped for Vue 3. Same surface as the\n * React `<Timeline>`: pass `defaultProject`, drive imperatively via\n * the exposed `api()` ref.\n */\nconst props = defineProps<{\n defaultProject: Project;\n defaultScale?: number;\n defaultTime?: Ms;\n defaultSelectedClipId?: string | null;\n showHeader?: boolean;\n readOnly?: boolean;\n snap?: boolean;\n autoFit?: boolean;\n locale?: Partial<Locale>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"seek\", timeMs: Ms): void;\n (e: \"selectClip\", clipId: string | null): void;\n (e: \"scaleChange\", pxPerSec: number): void;\n (e: \"moveClip\", clipId: string, opts: { start?: Ms; trackId?: string }): void;\n (\n e: \"resizeClip\",\n clipId: string,\n edits: Partial<Pick<Clip, \"in\" | \"out\" | \"start\">>,\n ): void;\n (e: \"change\", project: Project): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet timeline: CoreTimeline | null = null;\n\nonMounted(() => {\n if (!host.value) return;\n timeline = CoreTimeline.create({\n container: host.value,\n project: props.defaultProject,\n pxPerSec: props.defaultScale,\n time: props.defaultTime,\n selectedClipId: props.defaultSelectedClipId ?? null,\n showHeader: props.showHeader,\n readOnly: props.readOnly,\n snap: props.snap,\n autoFit: props.autoFit,\n locale: props.locale,\n onSeek: (t) => emit(\"seek\", t),\n onSelectClip: (id) => emit(\"selectClip\", id),\n onScaleChange: (s) => emit(\"scaleChange\", s),\n onMoveClip: (id, opts) => emit(\"moveClip\", id, opts),\n onResizeClip: (id, edits) => emit(\"resizeClip\", id, edits),\n onChange: (p) => emit(\"change\", p),\n });\n});\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && timeline) timeline.setLocale(locale);\n },\n);\n\nonBeforeUnmount(() => {\n timeline?.destroy();\n timeline = null;\n});\n\ndefineExpose({\n api: (): CoreTimeline | null => timeline,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-timeline-host=\"\" :style=\"{ width: '100%', height: '240px' }\" />\n</template>\n"],"names":["props","__props","emit","__emit","host","ref","editor","offs","headerLeftSlot","headerRightSlot","onMounted","Editor","project","timeMs","clipId","target","error","watch","theme","locale","_a","enabled","desired","timelineHeight","root","onBeforeUnmount","off","__expose","_createElementBlock","_createBlock","_Teleport","_renderSlot","_ctx","timeline","CoreTimeline","t","id","s","opts","edits","p"],"mappings":"+cAiBA,MAAMA,EAAQC,EA0CRC,EAAOC,EAePC,EAAOC,EAAAA,IAA2B,IAAI,EAC5C,IAAIC,EAAwB,KAC5B,MAAMC,EAA0B,CAAA,EAI1BC,EAAiBH,EAAAA,IAAwB,IAAI,EAC7CI,EAAkBJ,EAAAA,IAAwB,IAAI,EAEpDK,OAAAA,EAAAA,UAAU,IAAM,CACTN,EAAK,QACVE,EAASK,EAAAA,OAAO,OAAO,CACrB,UAAWP,EAAK,MAChB,QAASJ,EAAM,eACf,MAAOA,EAAM,MACb,OAAQA,EAAM,OACd,eAAgBA,EAAM,eACtB,GAAIA,EAAM,aAAe,KAAO,CAAE,YAAaA,EAAM,WAAA,EAAgB,CAAA,EACrE,GAAIA,EAAM,aAAe,KAAO,CAAE,YAAaA,EAAM,WAAA,EAAgB,CAAA,EACrE,GAAIA,EAAM,gBAAkB,KACxB,CAAE,eAAgBA,EAAM,cAAA,EACxB,CAAA,EACJ,GAAIA,EAAM,WAAa,KAAO,CAAE,UAAWA,EAAM,SAAA,EAAc,CAAA,EAC/D,GAAIA,EAAM,aAAe,KAAO,CAAE,YAAaA,EAAM,aAAgB,CAAA,CAAC,CACvE,EAEDO,EAAK,KACHD,EAAO,GAAG,SAAU,CAAC,CAAE,QAAAM,KAAcV,EAAK,SAAUU,CAAO,CAAC,EAC5DN,EAAO,GAAG,SAAU,CAAC,CAAE,QAAAM,KAAcV,EAAK,SAAUU,CAAO,CAAC,EAC5DN,EAAO,GAAG,OAAQ,CAAC,CAAE,OAAAO,KAAaX,EAAK,aAAcW,CAAM,CAAC,EAC5DP,EAAO,GAAG,OAAQ,IAAMJ,EAAK,MAAM,CAAC,EACpCI,EAAO,GAAG,QAAS,IAAMJ,EAAK,OAAO,CAAC,EACtCI,EAAO,GAAG,kBAAmB,CAAC,CAAE,OAAAQ,CAAA,IAC9BZ,EAAK,kBAAmBY,CAAM,CAAA,EAEhCR,EAAO,GAAG,0BAA2B,CAAC,CAAE,OAAAS,CAAA,IACtCb,EAAK,0BAA2Ba,CAAM,CAAA,EAExCT,EAAO,GAAG,QAAS,CAAC,CAAE,MAAAU,KAAYd,EAAK,QAASc,CAAK,CAAC,CAAA,EAGxDR,EAAe,MAAQF,EAAO,WAC9BG,EAAgB,MAAQH,EAAO,YAC/BJ,EAAK,QAASI,CAAM,EACtB,CAAC,EAEDW,EAAAA,MACE,IAAMjB,EAAM,MACXkB,GAAU,CACLA,GAASZ,GAAQA,EAAO,SAASY,CAAK,CAC5C,CAAA,EAGFD,EAAAA,MACE,IAAMjB,EAAM,OACXmB,GAAW,CACNA,GAAUb,GAAQA,EAAO,UAAUa,CAAM,CAC/C,CAAA,EAIFF,EAAAA,MACE,IAAA,OAAM,OAAAG,EAAApB,EAAM,YAAN,YAAAoB,EAAiB,SACtBC,GAAY,CACX,GAAI,CAACf,EAAQ,OACb,MAAMgB,EAAUD,IAAY,GACxBf,EAAO,mBAAA,IAAyBgB,GAClChB,EAAO,oBAAoBgB,CAAO,CAEtC,CAAA,EAIFL,EAAAA,MACE,IAAA,OAAM,OAAAG,EAAApB,EAAM,cAAN,YAAAoB,EAAmB,SACxBC,GAAY,CACX,GAAI,CAACf,EAAQ,OACb,MAAMgB,EAAUD,IAAY,GACxBf,EAAO,qBAAA,IAA2BgB,GACpChB,EAAO,sBAAsBgB,CAAO,CAExC,CAAA,EAKFL,EAAAA,MACE,IAAMjB,EAAM,eACXuB,GAAmB,CAClB,MAAMC,EAAOpB,EAAK,MACboB,IACDD,GAAkB,MAAQA,EAAiB,EAC7CC,EAAK,MAAM,YACT,0BACA,GAAG,KAAK,MAAMD,CAAc,CAAC,IAAA,EAG/BC,EAAK,MAAM,eAAe,yBAAyB,EAEvD,CAAA,EAGFC,EAAAA,gBAAgB,IAAM,CACpB,UAAWC,KAAOnB,EAAMmB,EAAA,EACxBnB,EAAK,OAAS,EACdD,GAAA,MAAAA,EAAQ,UACRA,EAAS,KACTE,EAAe,MAAQ,KACvBC,EAAgB,MAAQ,IAC1B,CAAC,EAEDkB,EAAa,CAEX,IAAK,IAAwBrB,CAAA,CAC9B,wBAICsB,EAAAA,mBAOM,MAAA,SAPG,OAAJ,IAAIxB,EAAO,kBAAgB,EAAA,GACdI,EAAA,qBAAhBqB,EAAAA,YAEWC,EAAAA,SAAA,OAFsB,GAAItB,EAAA,KAAA,GACnCuB,aAA0BC,EAAA,OAAA,YAAA,CAAA,yCAEZvB,EAAA,qBAAhBoB,EAAAA,YAEWC,EAAAA,SAAA,OAFuB,GAAIrB,EAAA,KAAA,GACpCsB,aAA2BC,EAAA,OAAA,aAAA,CAAA,yXCtLjC,MAAMhC,EAAQC,EAYRC,EAAOC,EAaPC,EAAOC,EAAAA,IAA2B,IAAI,EAC5C,IAAI4B,EAAgC,KAEpCvB,OAAAA,EAAAA,UAAU,IAAM,CACTN,EAAK,QACV6B,EAAWC,EAAAA,SAAa,OAAO,CAC7B,UAAW9B,EAAK,MAChB,QAASJ,EAAM,eACf,SAAUA,EAAM,aAChB,KAAMA,EAAM,YACZ,eAAgBA,EAAM,uBAAyB,KAC/C,WAAYA,EAAM,WAClB,SAAUA,EAAM,SAChB,KAAMA,EAAM,KACZ,QAASA,EAAM,QACf,OAAQA,EAAM,OACd,OAASmC,GAAMjC,EAAK,OAAQiC,CAAC,EAC7B,aAAeC,GAAOlC,EAAK,aAAckC,CAAE,EAC3C,cAAgBC,GAAMnC,EAAK,cAAemC,CAAC,EAC3C,WAAY,CAACD,EAAIE,IAASpC,EAAK,WAAYkC,EAAIE,CAAI,EACnD,aAAc,CAACF,EAAIG,IAAUrC,EAAK,aAAckC,EAAIG,CAAK,EACzD,SAAWC,GAAMtC,EAAK,SAAUsC,CAAC,CAAA,CAClC,EACH,CAAC,EAEDvB,EAAAA,MACE,IAAMjB,EAAM,OACXmB,GAAW,CACNA,GAAUc,GAAUA,EAAS,UAAUd,CAAM,CACnD,CAAA,EAGFM,EAAAA,gBAAgB,IAAM,CACpBQ,GAAA,MAAAA,EAAU,UACVA,EAAW,IACb,CAAC,EAEDN,EAAa,CACX,IAAK,IAA2BM,CAAA,CACjC,wBAICL,EAAAA,mBAA0F,MAAA,SAAjF,OAAJ,IAAIxB,EAAO,2BAAyB,GAAI,MAAO,CAAA,MAAA,OAAA,OAAA,OAAA,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { default as VideoEditor } from "./VideoEditor.vue";
2
2
  export { default as Timeline } from "./Timeline.vue";
3
- export type { Project, MediaSource, Track, Clip, Ms, Theme, EditorApi, TimelineOptions, Locale, PlaybackEngine, PlaybackEngineFactory, PlaybackEngineOptions, CanvasCompositorEngineOptions, } from "@aicut/core";
4
- export { createEmptyProject, createId, localeEn, localeZh, HtmlVideoEngine, htmlVideoEngineFactory, CanvasCompositorEngine, canvasCompositorEngineFactory, TRACK_HEIGHT, RULER_HEIGHT, HEADER_WIDTH, setTimelineMetrics, } from "@aicut/core";
3
+ export type { Project, MediaSource, Track, Clip, Keyframe, Ms, Theme, EditorApi, TimelineOptions, Locale, PlaybackEngine, PlaybackEngineFactory, PlaybackEngineOptions, CanvasCompositorEngineOptions, EffectiveTransform, } from "@aicut/core";
4
+ export { createEmptyProject, createId, localeEn, localeZh, HtmlVideoEngine, htmlVideoEngineFactory, CanvasCompositorEngine, canvasCompositorEngineFactory, TRACK_HEIGHT, RULER_HEIGHT, HEADER_WIDTH, setTimelineMetrics, IDENTITY_TRANSFORM, isIdentityTransform, getEffectiveTransform, getTransformAtTimelineTime, } from "@aicut/core";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EACV,OAAO,EACP,WAAW,EACX,KAAK,EACL,IAAI,EACJ,EAAE,EACF,KAAK,EACL,SAAS,EACT,eAAe,EACf,MAAM,EACN,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EACV,OAAO,EACP,WAAW,EACX,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,EAAE,EACF,KAAK,EACL,SAAS,EACT,eAAe,EACf,MAAM,EACN,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { defineComponent as v, ref as s, onMounted as H, watch as u, onBeforeUnmount as E, openBlock as p, createElementBlock as k, createBlock as f, Teleport as g, renderSlot as y, createCommentVNode as C } from "vue";
2
- import { Editor as _, Timeline as T } from "@aicut/core";
3
- import { CanvasCompositorEngine as I, HEADER_WIDTH as F, HtmlVideoEngine as L, RULER_HEIGHT as w, TRACK_HEIGHT as V, canvasCompositorEngineFactory as M, createEmptyProject as U, createId as $, htmlVideoEngineFactory as b, localeEn as z, localeZh as O, setTimelineMetrics as A } from "@aicut/core";
4
- const B = /* @__PURE__ */ v({
1
+ import { defineComponent as C, ref as u, onMounted as v, watch as c, onBeforeUnmount as k, openBlock as p, createElementBlock as H, createBlock as f, Teleport as g, renderSlot as y, createCommentVNode as E } from "vue";
2
+ import { Editor as T, Timeline as _ } from "@aicut/core";
3
+ import { CanvasCompositorEngine as B, HEADER_WIDTH as P, HtmlVideoEngine as j, IDENTITY_TRANSFORM as F, RULER_HEIGHT as L, TRACK_HEIGHT as w, canvasCompositorEngineFactory as M, createEmptyProject as V, createId as A, getEffectiveTransform as O, getTransformAtTimelineTime as U, htmlVideoEngineFactory as $, isIdentityTransform as z, localeEn as D, localeZh as K, setTimelineMetrics as G } from "@aicut/core";
4
+ const I = /* @__PURE__ */ C({
5
5
  __name: "VideoEditor",
6
6
  props: {
7
7
  defaultProject: {},
@@ -10,80 +10,108 @@ const B = /* @__PURE__ */ v({
10
10
  playbackEngine: { type: Function },
11
11
  trackHeight: {},
12
12
  rulerHeight: {},
13
- timelineHeight: {}
13
+ timelineHeight: {},
14
+ keyframes: {},
15
+ clipEdgeNav: {}
14
16
  },
15
- emits: ["ready", "change", "export", "timeUpdate", "play", "pause", "selectionChange", "error"],
16
- setup(h, { expose: d, emit: m }) {
17
- const t = h, a = m, r = s(null);
17
+ emits: ["ready", "change", "export", "timeUpdate", "play", "pause", "selectionChange", "keyframeSelectionChange", "error"],
18
+ setup(d, { expose: h, emit: m }) {
19
+ const l = d, o = m, i = u(null);
18
20
  let e = null;
19
- const o = [], n = s(null), i = s(null);
20
- return H(() => {
21
- r.value && (e = _.create({
22
- container: r.value,
23
- project: t.defaultProject,
24
- theme: t.theme,
25
- locale: t.locale,
26
- playbackEngine: t.playbackEngine,
27
- ...t.trackHeight != null ? { trackHeight: t.trackHeight } : {},
28
- ...t.rulerHeight != null ? { rulerHeight: t.rulerHeight } : {},
29
- ...t.timelineHeight != null ? { timelineHeight: t.timelineHeight } : {}
30
- }), o.push(
31
- e.on("change", ({ project: l }) => a("change", l)),
32
- e.on("export", ({ project: l }) => a("export", l)),
33
- e.on("time", ({ timeMs: l }) => a("timeUpdate", l)),
34
- e.on("play", () => a("play")),
35
- e.on("pause", () => a("pause")),
21
+ const a = [], r = u(null), s = u(null);
22
+ return v(() => {
23
+ i.value && (e = T.create({
24
+ container: i.value,
25
+ project: l.defaultProject,
26
+ theme: l.theme,
27
+ locale: l.locale,
28
+ playbackEngine: l.playbackEngine,
29
+ ...l.trackHeight != null ? { trackHeight: l.trackHeight } : {},
30
+ ...l.rulerHeight != null ? { rulerHeight: l.rulerHeight } : {},
31
+ ...l.timelineHeight != null ? { timelineHeight: l.timelineHeight } : {},
32
+ ...l.keyframes != null ? { keyframes: l.keyframes } : {},
33
+ ...l.clipEdgeNav != null ? { clipEdgeNav: l.clipEdgeNav } : {}
34
+ }), a.push(
35
+ e.on("change", ({ project: t }) => o("change", t)),
36
+ e.on("export", ({ project: t }) => o("export", t)),
37
+ e.on("time", ({ timeMs: t }) => o("timeUpdate", t)),
38
+ e.on("play", () => o("play")),
39
+ e.on("pause", () => o("pause")),
36
40
  e.on(
37
41
  "selectionChange",
38
- ({ clipId: l }) => a("selectionChange", l)
42
+ ({ clipId: t }) => o("selectionChange", t)
39
43
  ),
40
- e.on("error", ({ error: l }) => a("error", l))
41
- ), n.value = e.headerLeft, i.value = e.headerRight, a("ready", e));
42
- }), u(
43
- () => t.theme,
44
- (l) => {
45
- l && e && e.setTheme(l);
44
+ e.on(
45
+ "keyframeSelectionChange",
46
+ ({ target: t }) => o("keyframeSelectionChange", t)
47
+ ),
48
+ e.on("error", ({ error: t }) => o("error", t))
49
+ ), r.value = e.headerLeft, s.value = e.headerRight, o("ready", e));
50
+ }), c(
51
+ () => l.theme,
52
+ (t) => {
53
+ t && e && e.setTheme(t);
54
+ }
55
+ ), c(
56
+ () => l.locale,
57
+ (t) => {
58
+ t && e && e.setLocale(t);
59
+ }
60
+ ), c(
61
+ () => {
62
+ var t;
63
+ return (t = l.keyframes) == null ? void 0 : t.enabled;
64
+ },
65
+ (t) => {
66
+ if (!e) return;
67
+ const n = t === !0;
68
+ e.isKeyframesEnabled() !== n && e.setKeyframesEnabled(n);
46
69
  }
47
- ), u(
48
- () => t.locale,
49
- (l) => {
50
- l && e && e.setLocale(l);
70
+ ), c(
71
+ () => {
72
+ var t;
73
+ return (t = l.clipEdgeNav) == null ? void 0 : t.enabled;
74
+ },
75
+ (t) => {
76
+ if (!e) return;
77
+ const n = t === !0;
78
+ e.isClipEdgeNavEnabled() !== n && e.setClipEdgeNavEnabled(n);
51
79
  }
52
- ), u(
53
- () => t.timelineHeight,
54
- (l) => {
55
- const c = r.value;
56
- c && (l != null && l > 0 ? c.style.setProperty(
80
+ ), c(
81
+ () => l.timelineHeight,
82
+ (t) => {
83
+ const n = i.value;
84
+ n && (t != null && t > 0 ? n.style.setProperty(
57
85
  "--aicut-timeline-height",
58
- `${Math.round(l)}px`
59
- ) : c.style.removeProperty("--aicut-timeline-height"));
86
+ `${Math.round(t)}px`
87
+ ) : n.style.removeProperty("--aicut-timeline-height"));
60
88
  }
61
- ), E(() => {
62
- for (const l of o) l();
63
- o.length = 0, e == null || e.destroy(), e = null, n.value = null, i.value = null;
64
- }), d({
89
+ ), k(() => {
90
+ for (const t of a) t();
91
+ a.length = 0, e == null || e.destroy(), e = null, r.value = null, s.value = null;
92
+ }), h({
65
93
  /** Returns the underlying core API or null if not yet mounted. */
66
94
  api: () => e
67
- }), (l, c) => (p(), k("div", {
95
+ }), (t, n) => (p(), H("div", {
68
96
  ref_key: "host",
69
- ref: r,
97
+ ref: i,
70
98
  "data-aicut-host": ""
71
99
  }, [
72
- n.value ? (p(), f(g, {
100
+ r.value ? (p(), f(g, {
73
101
  key: 0,
74
- to: n.value
102
+ to: r.value
75
103
  }, [
76
- y(l.$slots, "headerLeft")
77
- ], 8, ["to"])) : C("", !0),
78
- i.value ? (p(), f(g, {
104
+ y(t.$slots, "headerLeft")
105
+ ], 8, ["to"])) : E("", !0),
106
+ s.value ? (p(), f(g, {
79
107
  key: 1,
80
- to: i.value
108
+ to: s.value
81
109
  }, [
82
- y(l.$slots, "headerRight")
83
- ], 8, ["to"])) : C("", !0)
110
+ y(t.$slots, "headerRight")
111
+ ], 8, ["to"])) : E("", !0)
84
112
  ], 512));
85
113
  }
86
- }), P = /* @__PURE__ */ v({
114
+ }), N = /* @__PURE__ */ C({
87
115
  __name: "Timeline",
88
116
  props: {
89
117
  defaultProject: {},
@@ -97,59 +125,63 @@ const B = /* @__PURE__ */ v({
97
125
  locale: {}
98
126
  },
99
127
  emits: ["seek", "selectClip", "scaleChange", "moveClip", "resizeClip", "change"],
100
- setup(h, { expose: d, emit: m }) {
101
- const t = h, a = m, r = s(null);
128
+ setup(d, { expose: h, emit: m }) {
129
+ const l = d, o = m, i = u(null);
102
130
  let e = null;
103
- return H(() => {
104
- r.value && (e = T.create({
105
- container: r.value,
106
- project: t.defaultProject,
107
- pxPerSec: t.defaultScale,
108
- time: t.defaultTime,
109
- selectedClipId: t.defaultSelectedClipId ?? null,
110
- showHeader: t.showHeader,
111
- readOnly: t.readOnly,
112
- snap: t.snap,
113
- autoFit: t.autoFit,
114
- locale: t.locale,
115
- onSeek: (o) => a("seek", o),
116
- onSelectClip: (o) => a("selectClip", o),
117
- onScaleChange: (o) => a("scaleChange", o),
118
- onMoveClip: (o, n) => a("moveClip", o, n),
119
- onResizeClip: (o, n) => a("resizeClip", o, n),
120
- onChange: (o) => a("change", o)
131
+ return v(() => {
132
+ i.value && (e = _.create({
133
+ container: i.value,
134
+ project: l.defaultProject,
135
+ pxPerSec: l.defaultScale,
136
+ time: l.defaultTime,
137
+ selectedClipId: l.defaultSelectedClipId ?? null,
138
+ showHeader: l.showHeader,
139
+ readOnly: l.readOnly,
140
+ snap: l.snap,
141
+ autoFit: l.autoFit,
142
+ locale: l.locale,
143
+ onSeek: (a) => o("seek", a),
144
+ onSelectClip: (a) => o("selectClip", a),
145
+ onScaleChange: (a) => o("scaleChange", a),
146
+ onMoveClip: (a, r) => o("moveClip", a, r),
147
+ onResizeClip: (a, r) => o("resizeClip", a, r),
148
+ onChange: (a) => o("change", a)
121
149
  }));
122
- }), u(
123
- () => t.locale,
124
- (o) => {
125
- o && e && e.setLocale(o);
150
+ }), c(
151
+ () => l.locale,
152
+ (a) => {
153
+ a && e && e.setLocale(a);
126
154
  }
127
- ), E(() => {
155
+ ), k(() => {
128
156
  e == null || e.destroy(), e = null;
129
- }), d({
157
+ }), h({
130
158
  api: () => e
131
- }), (o, n) => (p(), k("div", {
159
+ }), (a, r) => (p(), H("div", {
132
160
  ref_key: "host",
133
- ref: r,
161
+ ref: i,
134
162
  "data-aicut-timeline-host": "",
135
163
  style: { width: "100%", height: "240px" }
136
164
  }, null, 512));
137
165
  }
138
166
  });
139
167
  export {
140
- I as CanvasCompositorEngine,
141
- F as HEADER_WIDTH,
142
- L as HtmlVideoEngine,
143
- w as RULER_HEIGHT,
144
- V as TRACK_HEIGHT,
145
- P as Timeline,
146
- B as VideoEditor,
168
+ B as CanvasCompositorEngine,
169
+ P as HEADER_WIDTH,
170
+ j as HtmlVideoEngine,
171
+ F as IDENTITY_TRANSFORM,
172
+ L as RULER_HEIGHT,
173
+ w as TRACK_HEIGHT,
174
+ N as Timeline,
175
+ I as VideoEditor,
147
176
  M as canvasCompositorEngineFactory,
148
- U as createEmptyProject,
149
- $ as createId,
150
- b as htmlVideoEngineFactory,
151
- z as localeEn,
152
- O as localeZh,
153
- A as setTimelineMetrics
177
+ V as createEmptyProject,
178
+ A as createId,
179
+ O as getEffectiveTransform,
180
+ U as getTransformAtTimelineTime,
181
+ $ as htmlVideoEngineFactory,
182
+ z as isIdentityTransform,
183
+ D as localeEn,
184
+ K as localeZh,
185
+ G as setTimelineMetrics
154
186
  };
155
187
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/VideoEditor.vue","../src/Timeline.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Editor,\n type EditorApi,\n type Locale,\n type Ms,\n type PlaybackEngineFactory,\n type Project,\n type Theme,\n} from \"@aicut/core\";\n\n/**\n * Vue 3 wrapper around `@aicut/core`. Same shape as `@aicut/react`:\n * uncontrolled for project state, theme is reactive, API exposed via\n * `defineExpose` so a parent `ref` can call cut/seek/setProject/etc.\n */\nconst props = defineProps<{\n defaultProject?: Project;\n theme?: Theme;\n /** UI string overrides (English default). Reactive — swap to `localeZh` for Chinese. */\n locale?: Partial<Locale>;\n /**\n * Initial-only factory for a custom playback engine. Defaults to the\n * built-in `HtmlVideoEngine`. Pass `WebCodecsEngine` (v0.6+) or your\n * own engine to override. Bound at mount; later prop changes are\n * ignored.\n */\n playbackEngine?: PlaybackEngineFactory;\n /**\n * Initial-only — pixel height of each track row (default 56). Lower\n * values (~32–40) shrink the timeline for small viewports. Applied\n * process-wide at construction time.\n */\n trackHeight?: number;\n /** Initial-only — pixel height of the timeline ruler (default 24). */\n rulerHeight?: number;\n /**\n * Pixel height of the whole bottom timeline area (default 240).\n * Reactive — swap any time to recompact. The canvas inside fills\n * 100% and shows an internal scrollbar when track count overflows.\n */\n timelineHeight?: number;\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\", api: EditorApi): void;\n (e: \"change\", project: Project): void;\n (e: \"export\", project: Project): void;\n (e: \"timeUpdate\", timeMs: Ms): void;\n (e: \"play\"): void;\n (e: \"pause\"): void;\n (e: \"selectionChange\", clipId: string | null): void;\n (e: \"error\", error: Error): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet editor: Editor | null = null;\nconst offs: Array<() => void> = [];\n/** Header slot DOM nodes — set after editor mount so Vue Teleports\n * have a valid target. Library renders nothing here; named slots\n * `#headerLeft` / `#headerRight` portal whatever the host provides. */\nconst headerLeftSlot = ref<HTMLElement | null>(null);\nconst headerRightSlot = ref<HTMLElement | null>(null);\n\nonMounted(() => {\n if (!host.value) return;\n editor = Editor.create({\n container: host.value,\n project: props.defaultProject,\n theme: props.theme,\n locale: props.locale,\n playbackEngine: props.playbackEngine,\n ...(props.trackHeight != null ? { trackHeight: props.trackHeight } : {}),\n ...(props.rulerHeight != null ? { rulerHeight: props.rulerHeight } : {}),\n ...(props.timelineHeight != null\n ? { timelineHeight: props.timelineHeight }\n : {}),\n });\n\n offs.push(\n editor.on(\"change\", ({ project }) => emit(\"change\", project)),\n editor.on(\"export\", ({ project }) => emit(\"export\", project)),\n editor.on(\"time\", ({ timeMs }) => emit(\"timeUpdate\", timeMs)),\n editor.on(\"play\", () => emit(\"play\")),\n editor.on(\"pause\", () => emit(\"pause\")),\n editor.on(\"selectionChange\", ({ clipId }) =>\n emit(\"selectionChange\", clipId),\n ),\n editor.on(\"error\", ({ error }) => emit(\"error\", error)),\n );\n\n headerLeftSlot.value = editor.headerLeft;\n headerRightSlot.value = editor.headerRight;\n emit(\"ready\", editor);\n});\n\nwatch(\n () => props.theme,\n (theme) => {\n if (theme && editor) editor.setTheme(theme);\n },\n);\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && editor) editor.setLocale(locale);\n },\n);\n\n// Reactive — sets the CSS custom property directly so the timeline\n// height can be tweaked without remounting.\nwatch(\n () => props.timelineHeight,\n (timelineHeight) => {\n const root = host.value;\n if (!root) return;\n if (timelineHeight != null && timelineHeight > 0) {\n root.style.setProperty(\n \"--aicut-timeline-height\",\n `${Math.round(timelineHeight)}px`,\n );\n } else {\n root.style.removeProperty(\"--aicut-timeline-height\");\n }\n },\n);\n\nonBeforeUnmount(() => {\n for (const off of offs) off();\n offs.length = 0;\n editor?.destroy();\n editor = null;\n headerLeftSlot.value = null;\n headerRightSlot.value = null;\n});\n\ndefineExpose({\n /** Returns the underlying core API or null if not yet mounted. */\n api: (): EditorApi | null => editor,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-host=\"\">\n <Teleport v-if=\"headerLeftSlot\" :to=\"headerLeftSlot\">\n <slot name=\"headerLeft\" />\n </Teleport>\n <Teleport v-if=\"headerRightSlot\" :to=\"headerRightSlot\">\n <slot name=\"headerRight\" />\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Timeline as CoreTimeline,\n type Clip,\n type Locale,\n type Ms,\n type Project,\n} from \"@aicut/core\";\n\n/**\n * Standalone canvas Timeline wrapped for Vue 3. Same surface as the\n * React `<Timeline>`: pass `defaultProject`, drive imperatively via\n * the exposed `api()` ref.\n */\nconst props = defineProps<{\n defaultProject: Project;\n defaultScale?: number;\n defaultTime?: Ms;\n defaultSelectedClipId?: string | null;\n showHeader?: boolean;\n readOnly?: boolean;\n snap?: boolean;\n autoFit?: boolean;\n locale?: Partial<Locale>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"seek\", timeMs: Ms): void;\n (e: \"selectClip\", clipId: string | null): void;\n (e: \"scaleChange\", pxPerSec: number): void;\n (e: \"moveClip\", clipId: string, opts: { start?: Ms; trackId?: string }): void;\n (\n e: \"resizeClip\",\n clipId: string,\n edits: Partial<Pick<Clip, \"in\" | \"out\" | \"start\">>,\n ): void;\n (e: \"change\", project: Project): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet timeline: CoreTimeline | null = null;\n\nonMounted(() => {\n if (!host.value) return;\n timeline = CoreTimeline.create({\n container: host.value,\n project: props.defaultProject,\n pxPerSec: props.defaultScale,\n time: props.defaultTime,\n selectedClipId: props.defaultSelectedClipId ?? null,\n showHeader: props.showHeader,\n readOnly: props.readOnly,\n snap: props.snap,\n autoFit: props.autoFit,\n locale: props.locale,\n onSeek: (t) => emit(\"seek\", t),\n onSelectClip: (id) => emit(\"selectClip\", id),\n onScaleChange: (s) => emit(\"scaleChange\", s),\n onMoveClip: (id, opts) => emit(\"moveClip\", id, opts),\n onResizeClip: (id, edits) => emit(\"resizeClip\", id, edits),\n onChange: (p) => emit(\"change\", p),\n });\n});\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && timeline) timeline.setLocale(locale);\n },\n);\n\nonBeforeUnmount(() => {\n timeline?.destroy();\n timeline = null;\n});\n\ndefineExpose({\n api: (): CoreTimeline | null => timeline,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-timeline-host=\"\" :style=\"{ width: '100%', height: '240px' }\" />\n</template>\n"],"names":["props","__props","emit","__emit","host","ref","editor","offs","headerLeftSlot","headerRightSlot","onMounted","Editor","project","timeMs","clipId","error","watch","theme","locale","timelineHeight","root","onBeforeUnmount","off","__expose","_createElementBlock","_createBlock","_Teleport","_renderSlot","_ctx","timeline","CoreTimeline","t","id","s","opts","edits","p"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/VideoEditor.vue","../src/Timeline.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Editor,\n type EditorApi,\n type Locale,\n type Ms,\n type PlaybackEngineFactory,\n type Project,\n type Theme,\n} from \"@aicut/core\";\n\n/**\n * Vue 3 wrapper around `@aicut/core`. Same shape as `@aicut/react`:\n * uncontrolled for project state, theme is reactive, API exposed via\n * `defineExpose` so a parent `ref` can call cut/seek/setProject/etc.\n */\nconst props = defineProps<{\n defaultProject?: Project;\n theme?: Theme;\n /** UI string overrides (English default). Reactive — swap to `localeZh` for Chinese. */\n locale?: Partial<Locale>;\n /**\n * Initial-only factory for a custom playback engine. Defaults to the\n * built-in `HtmlVideoEngine`. Pass `WebCodecsEngine` (v0.6+) or your\n * own engine to override. Bound at mount; later prop changes are\n * ignored.\n */\n playbackEngine?: PlaybackEngineFactory;\n /**\n * Initial-only — pixel height of each track row (default 56). Lower\n * values (~32–40) shrink the timeline for small viewports. Applied\n * process-wide at construction time.\n */\n trackHeight?: number;\n /** Initial-only — pixel height of the timeline ruler (default 24). */\n rulerHeight?: number;\n /**\n * Pixel height of the whole bottom timeline area (default 240).\n * Reactive — swap any time to recompact. The canvas inside fills\n * 100% and shows an internal scrollbar when track count overflows.\n */\n timelineHeight?: number;\n /**\n * Per-clip keyframe animation (X / Y / Scale). Reactive — set\n * `{ enabled: true }` to surface keyframe diamonds on the timeline\n * and route the canvas-based engines through the transform pipeline.\n * Data is preserved when disabled.\n */\n keyframes?: { enabled?: boolean };\n /**\n * Jump-to-clip-edge toolbar cluster (|◀ ▶|) + I/O keyboard shortcuts.\n * Reactive — set `{ enabled: true }` to surface the buttons next to\n * the keyframe diamond and bind the shortcuts. Off hides the buttons\n * entirely (no toolbar space cost).\n */\n clipEdgeNav?: { enabled?: boolean };\n}>();\n\nconst emit = defineEmits<{\n (e: \"ready\", api: EditorApi): void;\n (e: \"change\", project: Project): void;\n (e: \"export\", project: Project): void;\n (e: \"timeUpdate\", timeMs: Ms): void;\n (e: \"play\"): void;\n (e: \"pause\"): void;\n (e: \"selectionChange\", clipId: string | null): void;\n (\n e: \"keyframeSelectionChange\",\n target: { clipId: string; keyframeId: string } | null,\n ): void;\n (e: \"error\", error: Error): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet editor: Editor | null = null;\nconst offs: Array<() => void> = [];\n/** Header slot DOM nodes — set after editor mount so Vue Teleports\n * have a valid target. Library renders nothing here; named slots\n * `#headerLeft` / `#headerRight` portal whatever the host provides. */\nconst headerLeftSlot = ref<HTMLElement | null>(null);\nconst headerRightSlot = ref<HTMLElement | null>(null);\n\nonMounted(() => {\n if (!host.value) return;\n editor = Editor.create({\n container: host.value,\n project: props.defaultProject,\n theme: props.theme,\n locale: props.locale,\n playbackEngine: props.playbackEngine,\n ...(props.trackHeight != null ? { trackHeight: props.trackHeight } : {}),\n ...(props.rulerHeight != null ? { rulerHeight: props.rulerHeight } : {}),\n ...(props.timelineHeight != null\n ? { timelineHeight: props.timelineHeight }\n : {}),\n ...(props.keyframes != null ? { keyframes: props.keyframes } : {}),\n ...(props.clipEdgeNav != null ? { clipEdgeNav: props.clipEdgeNav } : {}),\n });\n\n offs.push(\n editor.on(\"change\", ({ project }) => emit(\"change\", project)),\n editor.on(\"export\", ({ project }) => emit(\"export\", project)),\n editor.on(\"time\", ({ timeMs }) => emit(\"timeUpdate\", timeMs)),\n editor.on(\"play\", () => emit(\"play\")),\n editor.on(\"pause\", () => emit(\"pause\")),\n editor.on(\"selectionChange\", ({ clipId }) =>\n emit(\"selectionChange\", clipId),\n ),\n editor.on(\"keyframeSelectionChange\", ({ target }) =>\n emit(\"keyframeSelectionChange\", target),\n ),\n editor.on(\"error\", ({ error }) => emit(\"error\", error)),\n );\n\n headerLeftSlot.value = editor.headerLeft;\n headerRightSlot.value = editor.headerRight;\n emit(\"ready\", editor);\n});\n\nwatch(\n () => props.theme,\n (theme) => {\n if (theme && editor) editor.setTheme(theme);\n },\n);\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && editor) editor.setLocale(locale);\n },\n);\n\n// Reactive — flip keyframe mode without remount. Data preserved.\nwatch(\n () => props.keyframes?.enabled,\n (enabled) => {\n if (!editor) return;\n const desired = enabled === true;\n if (editor.isKeyframesEnabled() !== desired) {\n editor.setKeyframesEnabled(desired);\n }\n },\n);\n\n// Reactive — flip clip-edge nav cluster (|◀ ▶|) + I/O shortcuts.\nwatch(\n () => props.clipEdgeNav?.enabled,\n (enabled) => {\n if (!editor) return;\n const desired = enabled === true;\n if (editor.isClipEdgeNavEnabled() !== desired) {\n editor.setClipEdgeNavEnabled(desired);\n }\n },\n);\n\n// Reactive — sets the CSS custom property directly so the timeline\n// height can be tweaked without remounting.\nwatch(\n () => props.timelineHeight,\n (timelineHeight) => {\n const root = host.value;\n if (!root) return;\n if (timelineHeight != null && timelineHeight > 0) {\n root.style.setProperty(\n \"--aicut-timeline-height\",\n `${Math.round(timelineHeight)}px`,\n );\n } else {\n root.style.removeProperty(\"--aicut-timeline-height\");\n }\n },\n);\n\nonBeforeUnmount(() => {\n for (const off of offs) off();\n offs.length = 0;\n editor?.destroy();\n editor = null;\n headerLeftSlot.value = null;\n headerRightSlot.value = null;\n});\n\ndefineExpose({\n /** Returns the underlying core API or null if not yet mounted. */\n api: (): EditorApi | null => editor,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-host=\"\">\n <Teleport v-if=\"headerLeftSlot\" :to=\"headerLeftSlot\">\n <slot name=\"headerLeft\" />\n </Teleport>\n <Teleport v-if=\"headerRightSlot\" :to=\"headerRightSlot\">\n <slot name=\"headerRight\" />\n </Teleport>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, onMounted, ref, watch } from \"vue\";\nimport {\n Timeline as CoreTimeline,\n type Clip,\n type Locale,\n type Ms,\n type Project,\n} from \"@aicut/core\";\n\n/**\n * Standalone canvas Timeline wrapped for Vue 3. Same surface as the\n * React `<Timeline>`: pass `defaultProject`, drive imperatively via\n * the exposed `api()` ref.\n */\nconst props = defineProps<{\n defaultProject: Project;\n defaultScale?: number;\n defaultTime?: Ms;\n defaultSelectedClipId?: string | null;\n showHeader?: boolean;\n readOnly?: boolean;\n snap?: boolean;\n autoFit?: boolean;\n locale?: Partial<Locale>;\n}>();\n\nconst emit = defineEmits<{\n (e: \"seek\", timeMs: Ms): void;\n (e: \"selectClip\", clipId: string | null): void;\n (e: \"scaleChange\", pxPerSec: number): void;\n (e: \"moveClip\", clipId: string, opts: { start?: Ms; trackId?: string }): void;\n (\n e: \"resizeClip\",\n clipId: string,\n edits: Partial<Pick<Clip, \"in\" | \"out\" | \"start\">>,\n ): void;\n (e: \"change\", project: Project): void;\n}>();\n\nconst host = ref<HTMLDivElement | null>(null);\nlet timeline: CoreTimeline | null = null;\n\nonMounted(() => {\n if (!host.value) return;\n timeline = CoreTimeline.create({\n container: host.value,\n project: props.defaultProject,\n pxPerSec: props.defaultScale,\n time: props.defaultTime,\n selectedClipId: props.defaultSelectedClipId ?? null,\n showHeader: props.showHeader,\n readOnly: props.readOnly,\n snap: props.snap,\n autoFit: props.autoFit,\n locale: props.locale,\n onSeek: (t) => emit(\"seek\", t),\n onSelectClip: (id) => emit(\"selectClip\", id),\n onScaleChange: (s) => emit(\"scaleChange\", s),\n onMoveClip: (id, opts) => emit(\"moveClip\", id, opts),\n onResizeClip: (id, edits) => emit(\"resizeClip\", id, edits),\n onChange: (p) => emit(\"change\", p),\n });\n});\n\nwatch(\n () => props.locale,\n (locale) => {\n if (locale && timeline) timeline.setLocale(locale);\n },\n);\n\nonBeforeUnmount(() => {\n timeline?.destroy();\n timeline = null;\n});\n\ndefineExpose({\n api: (): CoreTimeline | null => timeline,\n});\n</script>\n\n<template>\n <div ref=\"host\" data-aicut-timeline-host=\"\" :style=\"{ width: '100%', height: '240px' }\" />\n</template>\n"],"names":["props","__props","emit","__emit","host","ref","editor","offs","headerLeftSlot","headerRightSlot","onMounted","Editor","project","timeMs","clipId","target","error","watch","theme","locale","_a","enabled","desired","timelineHeight","root","onBeforeUnmount","off","__expose","_createElementBlock","_createBlock","_Teleport","_renderSlot","_ctx","timeline","CoreTimeline","t","id","s","opts","edits","p"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aicut/vue",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Vue 3 wrapper for the AiCut video editor + lighting picker — thin declarative shells over @aicut/core.",
5
5
  "license": "MIT",
6
6
  "author": "ziqiang <ziqiangytu@gmail.com>",
@@ -65,7 +65,7 @@
65
65
  "README.md"
66
66
  ],
67
67
  "dependencies": {
68
- "@aicut/core": "0.5.0"
68
+ "@aicut/core": "0.6.0"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "vue": "^3.4.0"