@aicut/vue 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -164,7 +164,14 @@ function onGenerate() {
164
164
  ref="editor"
165
165
  subject-image-url="/frames/subject.jpg"
166
166
  @change="onChange"
167
- />
167
+ >
168
+ <!-- Reset / Generate / save-preset / etc. go into the controls
169
+ column's footer slot — the only host-supplied surface the
170
+ library reserves space for. -->
171
+ <template #controlsFooter>
172
+ <button @click="editor?.api()?.reset()">Reset</button>
173
+ </template>
174
+ </LightingEditor>
168
175
  <aside>
169
176
  <textarea placeholder="Describe the mood…" />
170
177
  <button @click="onGenerate">Generate</button>
@@ -173,7 +180,11 @@ function onGenerate() {
173
180
  </template>
174
181
  ```
175
182
 
176
- Props: `subjectImageUrl`, `defaultConfig`, `defaultView`, `theme`, `locale`. Events: `ready`, `change`. The library is intentionally scoped to the picker — Smart mode UI / Generate buttons / layout live in host code.
183
+ Props: `subjectImageUrl`, `defaultConfig`, `defaultView`, `theme`, `locale`. Slots: `controlsFooter`. Events: `ready`, `change`.
184
+
185
+ Exposed API (`editor.api()`): `setConfig`, `getConfig`, `setSubjectImage`, `setView`, `setTheme`, `setLocale`, `reset`.
186
+
187
+ The library is intentionally scoped to the picker — Smart mode UI / Generate buttons / layout live in host code.
177
188
 
178
189
  ## Standalone `<Timeline>`
179
190
 
@@ -10,7 +10,13 @@ type __VLS_Props = {
10
10
  /** UI string overrides (English default). Reactive — swap to `localeZh` for Chinese. */
11
11
  locale?: Partial<Locale>;
12
12
  };
13
- declare const _default: import("vue").DefineComponent<__VLS_Props, {
13
+ declare var __VLS_5: {}, __VLS_11: {};
14
+ type __VLS_Slots = {} & {
15
+ headerLeft?: (props: typeof __VLS_5) => any;
16
+ } & {
17
+ headerRight?: (props: typeof __VLS_11) => any;
18
+ };
19
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
14
20
  /** Returns the underlying core API or null if not yet mounted. */
15
21
  api: () => EditorApi | null;
16
22
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
@@ -32,5 +38,11 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {
32
38
  onSelectionChange?: ((clipId: string | null) => any) | undefined;
33
39
  onError?: ((error: Error) => any) | undefined;
34
40
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
35
42
  export default _default;
43
+ type __VLS_WithSlots<T, S> = T & {
44
+ new (): {
45
+ $slots: S;
46
+ };
47
+ };
36
48
  //# sourceMappingURL=VideoEditor.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"VideoEditor.vue.d.ts","sourceRoot":"","sources":["../src/VideoEditor.vue"],"names":[],"mappings":"AA+FA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,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;CAC1B,CAAC;;IAiEA,kEAAkE;eACzD,SAAS,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;AAuC3B,wBAQG"}
1
+ {"version":3,"file":"VideoEditor.vue.d.ts","sourceRoot":"","sources":["../src/VideoEditor.vue"],"names":[],"mappings":"AA+GA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,MAAM,EAEX,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;CAC1B,CAAC;AA2HF,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"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("vue"),c=require("@aicut/core"),u=a.defineComponent({__name:"VideoEditor",props:{defaultProject:{},theme:{},locale:{}},emits:["ready","change","export","timeUpdate","play","pause","selectionChange","error"],setup(i,{expose:s,emit:p}){const l=i,n=p,r=a.ref(null);let e=null;const o=[];return a.onMounted(()=>{r.value&&(e=c.Editor.create({container:r.value,project:l.defaultProject,theme:l.theme,locale:l.locale}),o.push(e.on("change",({project:t})=>n("change",t)),e.on("export",({project:t})=>n("export",t)),e.on("time",({timeMs:t})=>n("timeUpdate",t)),e.on("play",()=>n("play")),e.on("pause",()=>n("pause")),e.on("selectionChange",({clipId:t})=>n("selectionChange",t)),e.on("error",({error:t})=>n("error",t))),n("ready",e))}),a.watch(()=>l.theme,t=>{t&&e&&e.setTheme(t)}),a.watch(()=>l.locale,t=>{t&&e&&e.setLocale(t)}),a.onBeforeUnmount(()=>{for(const t of o)t();o.length=0,e==null||e.destroy(),e=null}),s({api:()=>e}),(t,f)=>(a.openBlock(),a.createElementBlock("div",{ref_key:"host",ref:r,"data-aicut-host":""},null,512))}}),d=a.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(i,{expose:s,emit:p}){const l=i,n=p,r=a.ref(null);let e=null;return a.onMounted(()=>{r.value&&(e=c.Timeline.create({container:r.value,project:l.defaultProject,pxPerSec:l.defaultScale,time:l.defaultTime,selectedClipId:l.defaultSelectedClipId??null,showHeader:l.showHeader,readOnly:l.readOnly,snap:l.snap,autoFit:l.autoFit,locale:l.locale,onSeek:o=>n("seek",o),onSelectClip:o=>n("selectClip",o),onScaleChange:o=>n("scaleChange",o),onMoveClip:(o,t)=>n("moveClip",o,t),onResizeClip:(o,t)=>n("resizeClip",o,t),onChange:o=>n("change",o)}))}),a.watch(()=>l.locale,o=>{o&&e&&e.setLocale(o)}),a.onBeforeUnmount(()=>{e==null||e.destroy(),e=null}),s({api:()=>e}),(o,t)=>(a.openBlock(),a.createElementBlock("div",{ref_key:"host",ref:r,"data-aicut-timeline-host":"",style:{width:"100%",height:"240px"}},null,512))}});Object.defineProperty(exports,"createEmptyProject",{enumerable:!0,get:()=>c.createEmptyProject});Object.defineProperty(exports,"createId",{enumerable:!0,get:()=>c.createId});Object.defineProperty(exports,"localeEn",{enumerable:!0,get:()=>c.localeEn});Object.defineProperty(exports,"localeZh",{enumerable:!0,get:()=>c.localeZh});exports.Timeline=d;exports.VideoEditor=u;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue"),i=require("@aicut/core"),h=t.defineComponent({__name:"VideoEditor",props:{defaultProject:{},theme:{},locale:{}},emits:["ready","change","export","timeUpdate","play","pause","selectionChange","error"],setup(s,{expose:p,emit:d}){const a=s,n=d,c=t.ref(null);let e=null;const l=[],r=t.ref(null),u=t.ref(null);return t.onMounted(()=>{c.value&&(e=i.Editor.create({container:c.value,project:a.defaultProject,theme:a.theme,locale:a.locale}),l.push(e.on("change",({project:o})=>n("change",o)),e.on("export",({project:o})=>n("export",o)),e.on("time",({timeMs:o})=>n("timeUpdate",o)),e.on("play",()=>n("play")),e.on("pause",()=>n("pause")),e.on("selectionChange",({clipId:o})=>n("selectionChange",o)),e.on("error",({error:o})=>n("error",o))),r.value=e.headerLeft,u.value=e.headerRight,n("ready",e))}),t.watch(()=>a.theme,o=>{o&&e&&e.setTheme(o)}),t.watch(()=>a.locale,o=>{o&&e&&e.setLocale(o)}),t.onBeforeUnmount(()=>{for(const o of l)o();l.length=0,e==null||e.destroy(),e=null,r.value=null,u.value=null}),p({api:()=>e}),(o,m)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"host",ref:c,"data-aicut-host":""},[r.value?(t.openBlock(),t.createBlock(t.Teleport,{key:0,to:r.value},[t.renderSlot(o.$slots,"headerLeft")],8,["to"])):t.createCommentVNode("",!0),u.value?(t.openBlock(),t.createBlock(t.Teleport,{key:1,to:u.value},[t.renderSlot(o.$slots,"headerRight")],8,["to"])):t.createCommentVNode("",!0)],512))}}),f=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(s,{expose:p,emit:d}){const a=s,n=d,c=t.ref(null);let e=null;return t.onMounted(()=>{c.value&&(e=i.Timeline.create({container:c.value,project:a.defaultProject,pxPerSec:a.defaultScale,time:a.defaultTime,selectedClipId:a.defaultSelectedClipId??null,showHeader:a.showHeader,readOnly:a.readOnly,snap:a.snap,autoFit:a.autoFit,locale:a.locale,onSeek:l=>n("seek",l),onSelectClip:l=>n("selectClip",l),onScaleChange:l=>n("scaleChange",l),onMoveClip:(l,r)=>n("moveClip",l,r),onResizeClip:(l,r)=>n("resizeClip",l,r),onChange:l=>n("change",l)}))}),t.watch(()=>a.locale,l=>{l&&e&&e.setLocale(l)}),t.onBeforeUnmount(()=>{e==null||e.destroy(),e=null}),p({api:()=>e}),(l,r)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"host",ref:c,"data-aicut-timeline-host":"",style:{width:"100%",height:"240px"}},null,512))}});Object.defineProperty(exports,"createEmptyProject",{enumerable:!0,get:()=>i.createEmptyProject});Object.defineProperty(exports,"createId",{enumerable:!0,get:()=>i.createId});Object.defineProperty(exports,"localeEn",{enumerable:!0,get:()=>i.localeEn});Object.defineProperty(exports,"localeZh",{enumerable:!0,get:()=>i.localeZh});exports.Timeline=f;exports.VideoEditor=h;
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 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\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\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 });\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 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\nonBeforeUnmount(() => {\n for (const off of offs) off();\n offs.length = 0;\n editor?.destroy();\n editor = 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</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","onMounted","Editor","project","timeMs","clipId","error","watch","theme","locale","onBeforeUnmount","off","__expose","_createElementBlock","timeline","CoreTimeline","t","id","s","opts","edits","p"],"mappings":"0UAgBA,MAAMA,EAAQC,EAORC,EAAOC,EAWPC,EAAOC,EAAAA,IAA2B,IAAI,EAC5C,IAAIC,EAAwB,KAC5B,MAAMC,EAA0B,CAAA,EAEhCC,OAAAA,EAAAA,UAAU,IAAM,CACTJ,EAAK,QACVE,EAASG,EAAAA,OAAO,OAAO,CACrB,UAAWL,EAAK,MAChB,QAASJ,EAAM,eACf,MAAOA,EAAM,MACb,OAAQA,EAAM,MAAA,CACf,EAEDO,EAAK,KACHD,EAAO,GAAG,SAAU,CAAC,CAAE,QAAAI,KAAcR,EAAK,SAAUQ,CAAO,CAAC,EAC5DJ,EAAO,GAAG,SAAU,CAAC,CAAE,QAAAI,KAAcR,EAAK,SAAUQ,CAAO,CAAC,EAC5DJ,EAAO,GAAG,OAAQ,CAAC,CAAE,OAAAK,KAAaT,EAAK,aAAcS,CAAM,CAAC,EAC5DL,EAAO,GAAG,OAAQ,IAAMJ,EAAK,MAAM,CAAC,EACpCI,EAAO,GAAG,QAAS,IAAMJ,EAAK,OAAO,CAAC,EACtCI,EAAO,GAAG,kBAAmB,CAAC,CAAE,OAAAM,CAAA,IAC9BV,EAAK,kBAAmBU,CAAM,CAAA,EAEhCN,EAAO,GAAG,QAAS,CAAC,CAAE,MAAAO,KAAYX,EAAK,QAASW,CAAK,CAAC,CAAA,EAGxDX,EAAK,QAASI,CAAM,EACtB,CAAC,EAEDQ,EAAAA,MACE,IAAMd,EAAM,MACXe,GAAU,CACLA,GAAST,GAAQA,EAAO,SAASS,CAAK,CAC5C,CAAA,EAGFD,EAAAA,MACE,IAAMd,EAAM,OACXgB,GAAW,CACNA,GAAUV,GAAQA,EAAO,UAAUU,CAAM,CAC/C,CAAA,EAGFC,EAAAA,gBAAgB,IAAM,CACpB,UAAWC,KAAOX,EAAMW,EAAA,EACxBX,EAAK,OAAS,EACdD,GAAA,MAAAA,EAAQ,UACRA,EAAS,IACX,CAAC,EAEDa,EAAa,CAEX,IAAK,IAAwBb,CAAA,CAC9B,wBAICc,EAAAA,mBAAqC,MAAA,SAA5B,OAAJ,IAAIhB,EAAO,kBAAgB,EAAA,sVC3ElC,MAAMJ,EAAQC,EAYRC,EAAOC,EAaPC,EAAOC,EAAAA,IAA2B,IAAI,EAC5C,IAAIgB,EAAgC,KAEpCb,OAAAA,EAAAA,UAAU,IAAM,CACTJ,EAAK,QACViB,EAAWC,EAAAA,SAAa,OAAO,CAC7B,UAAWlB,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,OAASuB,GAAMrB,EAAK,OAAQqB,CAAC,EAC7B,aAAeC,GAAOtB,EAAK,aAAcsB,CAAE,EAC3C,cAAgBC,GAAMvB,EAAK,cAAeuB,CAAC,EAC3C,WAAY,CAACD,EAAIE,IAASxB,EAAK,WAAYsB,EAAIE,CAAI,EACnD,aAAc,CAACF,EAAIG,IAAUzB,EAAK,aAAcsB,EAAIG,CAAK,EACzD,SAAWC,GAAM1B,EAAK,SAAU0B,CAAC,CAAA,CAClC,EACH,CAAC,EAEDd,EAAAA,MACE,IAAMd,EAAM,OACXgB,GAAW,CACNA,GAAUK,GAAUA,EAAS,UAAUL,CAAM,CACnD,CAAA,EAGFC,EAAAA,gBAAgB,IAAM,CACpBI,GAAA,MAAAA,EAAU,UACVA,EAAW,IACb,CAAC,EAEDF,EAAa,CACX,IAAK,IAA2BE,CAAA,CACjC,wBAICD,EAAAA,mBAA0F,MAAA,SAAjF,OAAJ,IAAIhB,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 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\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 });\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\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","onBeforeUnmount","off","__expose","_createElementBlock","_createBlock","_Teleport","_renderSlot","_ctx","timeline","CoreTimeline","t","id","s","opts","edits","p"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { defineComponent as p, ref as u, onMounted as d, watch as s, onBeforeUnmount as h, openBlock as m, createElementBlock as f } from "vue";
2
- import { Editor as C, Timeline as y } from "@aicut/core";
3
- import { createEmptyProject as B, createId as E, localeEn as P, localeZh as T } from "@aicut/core";
4
- const v = /* @__PURE__ */ p({
1
+ import { defineComponent as g, ref as i, onMounted as v, watch as h, onBeforeUnmount as _, openBlock as s, createElementBlock as S, createBlock as f, Teleport as m, renderSlot as C, createCommentVNode as y } from "vue";
2
+ import { Editor as k, Timeline as x } from "@aicut/core";
3
+ import { createEmptyProject as I, createId as R, localeEn as z, localeZh as F } from "@aicut/core";
4
+ const E = /* @__PURE__ */ g({
5
5
  __name: "VideoEditor",
6
6
  props: {
7
7
  defaultProject: {},
@@ -9,13 +9,13 @@ const v = /* @__PURE__ */ p({
9
9
  locale: {}
10
10
  },
11
11
  emits: ["ready", "change", "export", "timeUpdate", "play", "pause", "selectionChange", "error"],
12
- setup(r, { expose: c, emit: i }) {
13
- const l = r, a = i, n = u(null);
12
+ setup(p, { expose: u, emit: d }) {
13
+ const l = p, a = d, r = i(null);
14
14
  let e = null;
15
- const o = [];
16
- return d(() => {
17
- n.value && (e = C.create({
18
- container: n.value,
15
+ const o = [], n = i(null), c = i(null);
16
+ return v(() => {
17
+ r.value && (e = k.create({
18
+ container: r.value,
19
19
  project: l.defaultProject,
20
20
  theme: l.theme,
21
21
  locale: l.locale
@@ -30,30 +30,43 @@ const v = /* @__PURE__ */ p({
30
30
  ({ clipId: t }) => a("selectionChange", t)
31
31
  ),
32
32
  e.on("error", ({ error: t }) => a("error", t))
33
- ), a("ready", e));
34
- }), s(
33
+ ), n.value = e.headerLeft, c.value = e.headerRight, a("ready", e));
34
+ }), h(
35
35
  () => l.theme,
36
36
  (t) => {
37
37
  t && e && e.setTheme(t);
38
38
  }
39
- ), s(
39
+ ), h(
40
40
  () => l.locale,
41
41
  (t) => {
42
42
  t && e && e.setLocale(t);
43
43
  }
44
- ), h(() => {
44
+ ), _(() => {
45
45
  for (const t of o) t();
46
- o.length = 0, e == null || e.destroy(), e = null;
47
- }), c({
46
+ o.length = 0, e == null || e.destroy(), e = null, n.value = null, c.value = null;
47
+ }), u({
48
48
  /** Returns the underlying core API or null if not yet mounted. */
49
49
  api: () => e
50
- }), (t, g) => (m(), f("div", {
50
+ }), (t, B) => (s(), S("div", {
51
51
  ref_key: "host",
52
- ref: n,
52
+ ref: r,
53
53
  "data-aicut-host": ""
54
- }, null, 512));
54
+ }, [
55
+ n.value ? (s(), f(m, {
56
+ key: 0,
57
+ to: n.value
58
+ }, [
59
+ C(t.$slots, "headerLeft")
60
+ ], 8, ["to"])) : y("", !0),
61
+ c.value ? (s(), f(m, {
62
+ key: 1,
63
+ to: c.value
64
+ }, [
65
+ C(t.$slots, "headerRight")
66
+ ], 8, ["to"])) : y("", !0)
67
+ ], 512));
55
68
  }
56
- }), S = /* @__PURE__ */ p({
69
+ }), P = /* @__PURE__ */ g({
57
70
  __name: "Timeline",
58
71
  props: {
59
72
  defaultProject: {},
@@ -67,12 +80,12 @@ const v = /* @__PURE__ */ p({
67
80
  locale: {}
68
81
  },
69
82
  emits: ["seek", "selectClip", "scaleChange", "moveClip", "resizeClip", "change"],
70
- setup(r, { expose: c, emit: i }) {
71
- const l = r, a = i, n = u(null);
83
+ setup(p, { expose: u, emit: d }) {
84
+ const l = p, a = d, r = i(null);
72
85
  let e = null;
73
- return d(() => {
74
- n.value && (e = y.create({
75
- container: n.value,
86
+ return v(() => {
87
+ r.value && (e = x.create({
88
+ container: r.value,
76
89
  project: l.defaultProject,
77
90
  pxPerSec: l.defaultScale,
78
91
  time: l.defaultTime,
@@ -85,33 +98,33 @@ const v = /* @__PURE__ */ p({
85
98
  onSeek: (o) => a("seek", o),
86
99
  onSelectClip: (o) => a("selectClip", o),
87
100
  onScaleChange: (o) => a("scaleChange", o),
88
- onMoveClip: (o, t) => a("moveClip", o, t),
89
- onResizeClip: (o, t) => a("resizeClip", o, t),
101
+ onMoveClip: (o, n) => a("moveClip", o, n),
102
+ onResizeClip: (o, n) => a("resizeClip", o, n),
90
103
  onChange: (o) => a("change", o)
91
104
  }));
92
- }), s(
105
+ }), h(
93
106
  () => l.locale,
94
107
  (o) => {
95
108
  o && e && e.setLocale(o);
96
109
  }
97
- ), h(() => {
110
+ ), _(() => {
98
111
  e == null || e.destroy(), e = null;
99
- }), c({
112
+ }), u({
100
113
  api: () => e
101
- }), (o, t) => (m(), f("div", {
114
+ }), (o, n) => (s(), S("div", {
102
115
  ref_key: "host",
103
- ref: n,
116
+ ref: r,
104
117
  "data-aicut-timeline-host": "",
105
118
  style: { width: "100%", height: "240px" }
106
119
  }, null, 512));
107
120
  }
108
121
  });
109
122
  export {
110
- S as Timeline,
111
- v as VideoEditor,
112
- B as createEmptyProject,
113
- E as createId,
114
- P as localeEn,
115
- T as localeZh
123
+ P as Timeline,
124
+ E as VideoEditor,
125
+ I as createEmptyProject,
126
+ R as createId,
127
+ z as localeEn,
128
+ F as localeZh
116
129
  };
117
130
  //# 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 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\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\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 });\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 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\nonBeforeUnmount(() => {\n for (const off of offs) off();\n offs.length = 0;\n editor?.destroy();\n editor = 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</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","onMounted","Editor","project","timeMs","clipId","error","watch","theme","locale","onBeforeUnmount","off","__expose","_createElementBlock","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 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\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 });\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\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","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.4.0",
3
+ "version": "0.4.2",
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>",
@@ -60,7 +60,7 @@
60
60
  "README.md"
61
61
  ],
62
62
  "dependencies": {
63
- "@aicut/core": "0.4.0"
63
+ "@aicut/core": "0.4.2"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "vue": "^3.4.0"