@aicut/core 0.1.0 → 0.2.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 +96 -79
- package/dist/chunk-CCDON7CU.js +87 -0
- package/dist/chunk-CCDON7CU.js.map +1 -0
- package/dist/index.d.cts +3 -119
- package/dist/index.d.ts +3 -119
- package/dist/index.js +4 -85
- package/dist/index.js.map +1 -1
- package/dist/lighting/index.cjs +19373 -0
- package/dist/lighting/index.cjs.map +1 -0
- package/dist/lighting/index.d.cts +193 -0
- package/dist/lighting/index.d.ts +193 -0
- package/dist/lighting/index.js +19310 -0
- package/dist/lighting/index.js.map +1 -0
- package/dist/types-C95koNwJ.d.cts +120 -0
- package/dist/types-C95koNwJ.d.ts +120 -0
- package/package.json +47 -2
- package/styles/theme.css +312 -0
package/README.md
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
# @aicut/core
|
|
2
2
|
|
|
3
|
-
Framework-agnostic
|
|
3
|
+
> Framework-agnostic engine for the AiCut video editor — canvas timeline, plain-JSON projects, zero runtime deps.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@aicut/core)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/ziqiangai/AiCut)
|
|
8
|
+
|
|
9
|
+

|
|
4
10
|
|
|
5
11
|
For React or Vue apps, prefer **[@aicut/react](https://www.npmjs.com/package/@aicut/react)** or **[@aicut/vue](https://www.npmjs.com/package/@aicut/vue)** — they wrap this same engine.
|
|
6
12
|
|
|
13
|
+
## Install
|
|
14
|
+
|
|
7
15
|
```bash
|
|
8
16
|
pnpm add @aicut/core
|
|
9
17
|
```
|
|
@@ -21,91 +29,79 @@ const editor = Editor.create({
|
|
|
21
29
|
sources: [
|
|
22
30
|
{ id: "s1", url: "/media/a.mp4", kind: "video", name: "a.mp4" },
|
|
23
31
|
],
|
|
24
|
-
tracks: [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
],
|
|
32
|
+
tracks: [{
|
|
33
|
+
id: "t1",
|
|
34
|
+
kind: "video",
|
|
35
|
+
clips: [{ id: "c1", sourceId: "s1", in: 0, out: 5000, start: 0 }],
|
|
36
|
+
}],
|
|
31
37
|
},
|
|
32
38
|
});
|
|
33
39
|
|
|
34
|
-
editor.on("change", ({ project }) =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
headers: { "content-type": "application/json" },
|
|
38
|
-
body: JSON.stringify({ project }),
|
|
39
|
-
}));
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The editor renders into your `container`. Call methods on the returned `editor` instance to drive it imperatively.
|
|
40
|
+
editor.on("change", ({ project }) => {
|
|
41
|
+
localStorage.setItem("aicut", JSON.stringify(project));
|
|
42
|
+
});
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
editor.on("export", ({ project }) => {
|
|
45
|
+
fetch("/api/export", {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: { "content-type": "application/json" },
|
|
48
|
+
body: JSON.stringify({ project }),
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
```
|
|
45
52
|
|
|
46
|
-
|
|
53
|
+
## API at a glance
|
|
47
54
|
|
|
48
55
|
```ts
|
|
49
|
-
|
|
50
|
-
editor.
|
|
51
|
-
editor.
|
|
56
|
+
// Playback
|
|
57
|
+
editor.play(); editor.pause(); editor.togglePlay();
|
|
58
|
+
editor.seek(timeMs);
|
|
59
|
+
|
|
60
|
+
// Editing
|
|
61
|
+
editor.split(); // at playhead
|
|
62
|
+
editor.trimLeft();
|
|
52
63
|
editor.trimRight();
|
|
53
64
|
editor.removeClip(clipId);
|
|
54
65
|
editor.setClipSpeed(clipId, 2);
|
|
55
|
-
|
|
56
66
|
editor.undo(); editor.redo();
|
|
57
|
-
editor.canUndo(); editor.canRedo();
|
|
58
|
-
```
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
editor.
|
|
64
|
-
editor.setProject(p); // replace, preserves auto-fit etc.
|
|
65
|
-
editor.reset(); // empty single-track project
|
|
68
|
+
// Project state
|
|
69
|
+
editor.getProject();
|
|
70
|
+
editor.setProject(project);
|
|
71
|
+
editor.reset();
|
|
66
72
|
editor.addSource({ id, url, kind: "video" });
|
|
67
73
|
editor.addTrack("video");
|
|
68
|
-
editor.removeTrack(trackId);
|
|
69
74
|
editor.moveClip(clipId, { start, trackId, newTrack });
|
|
70
|
-
editor.resizeClip(clipId, { in, out, start });
|
|
71
|
-
```
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
// Viewport
|
|
77
|
+
editor.setScale(80); // px per second
|
|
78
|
+
editor.setSnap(false);
|
|
79
|
+
editor.setSelection(clipId);
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
editor.
|
|
77
|
-
editor.
|
|
78
|
-
editor.
|
|
79
|
-
editor.enterFullscreen(); editor.exitFullscreen();
|
|
81
|
+
// UI
|
|
82
|
+
editor.setTheme({ controlsBg: "#fff" });
|
|
83
|
+
editor.setLocale({ undo: "Annuler" });
|
|
84
|
+
editor.requestExport(); // → fires "export" event
|
|
80
85
|
```
|
|
81
86
|
|
|
82
|
-
|
|
87
|
+
## Events
|
|
83
88
|
|
|
84
89
|
```ts
|
|
85
|
-
|
|
86
|
-
editor.on("time",
|
|
87
|
-
editor.on("export",
|
|
90
|
+
editor.on("change", ({ project }) => /* … */);
|
|
91
|
+
editor.on("time", ({ timeMs }) => /* … */);
|
|
92
|
+
editor.on("export", ({ project }) => /* … */);
|
|
88
93
|
editor.on("selectionChange", ({ clipId }) => /* … */);
|
|
89
|
-
editor.on("historyChange",
|
|
90
|
-
editor.on("ready",
|
|
91
|
-
editor.on("scaleChange",
|
|
92
|
-
editor.on("snapChange",
|
|
93
|
-
editor.on("error",
|
|
94
|
-
off(); // unsubscribe
|
|
94
|
+
editor.on("historyChange", ({ canUndo, canRedo }) => /* … */);
|
|
95
|
+
editor.on("ready", ({ sourceId }) => /* … */);
|
|
96
|
+
editor.on("scaleChange", ({ pxPerSec }) => /* … */);
|
|
97
|
+
editor.on("snapChange", ({ snap }) => /* … */);
|
|
98
|
+
editor.on("error", ({ error }) => /* … */);
|
|
95
99
|
```
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
The library never calls a backend on its own — `requestExport()` fires the `export` event with the current project JSON; your handler decides what to do.
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
editor.requestExport(); // → emits "export" with project
|
|
103
|
-
```
|
|
101
|
+
Each `on` returns an unsubscribe function.
|
|
104
102
|
|
|
105
103
|
## Theming
|
|
106
104
|
|
|
107
|
-
CSS variables; pass any subset via `theme` and the rest fall back to the defaults.
|
|
108
|
-
|
|
109
105
|
```ts
|
|
110
106
|
Editor.create({
|
|
111
107
|
container,
|
|
@@ -116,16 +112,14 @@ Editor.create({
|
|
|
116
112
|
controlsBorder: "rgba(255, 255, 255, 0.08)",
|
|
117
113
|
controlsHover: "rgba(255, 255, 255, 0.08)",
|
|
118
114
|
controlsActive: "rgba(255, 255, 255, 0.12)",
|
|
119
|
-
previewBg: "#000",
|
|
115
|
+
previewBg: "#000", // letterbox colour
|
|
120
116
|
},
|
|
121
117
|
});
|
|
122
|
-
|
|
123
|
-
editor.setTheme({ controlsBg: "#f6f6f8", previewBg: "#e4e4e7" }); // runtime swap
|
|
124
118
|
```
|
|
125
119
|
|
|
126
|
-
Every
|
|
120
|
+
Every key is also a plain CSS custom property — `.aicut-root { --aicut-controls-bg: …; }` works too. Call `editor.setTheme(…)` to swap at runtime.
|
|
127
121
|
|
|
128
|
-
##
|
|
122
|
+
## i18n
|
|
129
123
|
|
|
130
124
|
English by default. Bundled `localeZh` covers the whole editor (toolbar tooltips, exit-fullscreen overlay, canvas track headers).
|
|
131
125
|
|
|
@@ -134,42 +128,65 @@ import { Editor, localeZh } from "@aicut/core";
|
|
|
134
128
|
|
|
135
129
|
Editor.create({ container, project, locale: localeZh });
|
|
136
130
|
|
|
137
|
-
|
|
138
|
-
editor.setLocale({ undo: "Annuler", redo: "Refaire" });
|
|
131
|
+
editor.setLocale({ undo: "Annuler" }); // partial override
|
|
139
132
|
```
|
|
140
133
|
|
|
141
|
-
`Locale` is exported as a type if you need to typecheck a custom pack.
|
|
142
|
-
|
|
143
134
|
## Toolbar slots
|
|
144
135
|
|
|
145
|
-
Both the editor's
|
|
136
|
+
Both the editor's toolbar and the standalone `Timeline`'s optional toolbar expose `toolbarLeft` / `toolbarRight` slot DOM elements. The library renders nothing into them — append your own buttons.
|
|
146
137
|
|
|
147
138
|
```ts
|
|
148
|
-
const editor = Editor.create({ container, project });
|
|
149
139
|
const exportBtn = document.createElement("button");
|
|
150
140
|
exportBtn.textContent = "Export";
|
|
151
141
|
exportBtn.onclick = () => editor.requestExport();
|
|
152
142
|
editor.toolbarRight.appendChild(exportBtn);
|
|
153
143
|
```
|
|
154
144
|
|
|
155
|
-
|
|
145
|
+
## Lighting picker (opt-in sub-entry)
|
|
156
146
|
|
|
157
|
-
|
|
147
|
+
A separate component for AI relighting workflows — drag a light dot around a 3D sphere wrapping a subject frame, control brightness / color / direction. Three.js is bundled only on this sub-entry, so consumers of the video editor pay zero bytes for it.
|
|
158
148
|
|
|
159
|
-
|
|
149
|
+
```ts
|
|
150
|
+
import { LightingEditor } from "@aicut/core/lighting";
|
|
151
|
+
import "@aicut/core/styles.css";
|
|
152
|
+
|
|
153
|
+
const ed = LightingEditor.create({
|
|
154
|
+
container: document.getElementById("light")!,
|
|
155
|
+
subjectImageUrl: "/frames/subject.jpg",
|
|
156
|
+
smartEnabled: true, // default; false → no slot column at all
|
|
157
|
+
smartOpen: true, // default; user can toggle via × / header pill
|
|
158
|
+
onChange: (cfg) => console.log(cfg),
|
|
159
|
+
onGenerate: (cfg) => fetch("/relight", { method: "POST", body: JSON.stringify(cfg) }),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Host appends UI into the smart slot (prompt textarea, presets, generate btn, …).
|
|
163
|
+
ed.smartSlot.appendChild(myAiUI);
|
|
164
|
+
|
|
165
|
+
// Runtime control:
|
|
166
|
+
ed.setSmartOpen(false);
|
|
167
|
+
ed.setSmartEnabled(false);
|
|
168
|
+
ed.setView("front");
|
|
169
|
+
ed.setConfig({ brightness: 0.8, color: "#ffaa3a" });
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Locale extension `LightingLocale` (separate from the video editor's `Locale`) is also exported with `lightingLocaleEn` / `lightingLocaleZh`.
|
|
173
|
+
|
|
174
|
+
## Standalone Timeline
|
|
160
175
|
|
|
161
176
|
```ts
|
|
162
177
|
import { Timeline } from "@aicut/core";
|
|
163
178
|
|
|
164
179
|
const tl = Timeline.create({
|
|
165
180
|
container: document.getElementById("strip")!,
|
|
166
|
-
project:
|
|
181
|
+
project: singleClipProject,
|
|
167
182
|
showHeader: false,
|
|
168
183
|
readOnly: true,
|
|
169
184
|
onSeek: (ms) => console.log("picked", ms),
|
|
170
185
|
});
|
|
171
186
|
```
|
|
172
187
|
|
|
188
|
+
Useful for a frame-picker, thumbnail strip, or read-only preview.
|
|
189
|
+
|
|
173
190
|
## Data model
|
|
174
191
|
|
|
175
192
|
```ts
|
|
@@ -188,14 +205,14 @@ interface Track { id: string; kind: "video" | "audio"; clips: Clip[]; }
|
|
|
188
205
|
|
|
189
206
|
interface Clip {
|
|
190
207
|
id: string; sourceId: string;
|
|
191
|
-
in: Ms; out: Ms;
|
|
192
|
-
start: Ms;
|
|
208
|
+
in: Ms; out: Ms; // window into the source (exclusive at `out`)
|
|
209
|
+
start: Ms; // position on the timeline
|
|
193
210
|
speed?: number;
|
|
194
211
|
}
|
|
195
212
|
|
|
196
|
-
type Ms = number;
|
|
213
|
+
type Ms = number; // integer milliseconds; no frame-rate coupling
|
|
197
214
|
```
|
|
198
215
|
|
|
199
|
-
|
|
216
|
+
---
|
|
200
217
|
|
|
201
|
-
|
|
218
|
+
[Full docs & demo](https://github.com/ziqiangai/AiCut) · [@aicut/react](https://www.npmjs.com/package/@aicut/react) · [@aicut/vue](https://www.npmjs.com/package/@aicut/vue)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// src/i18n.ts
|
|
2
|
+
var localeEn = {
|
|
3
|
+
undo: "Undo",
|
|
4
|
+
redo: "Redo",
|
|
5
|
+
split: "Split",
|
|
6
|
+
trimLeft: "Trim left edge",
|
|
7
|
+
trimRight: "Trim right edge",
|
|
8
|
+
speedComingSoon: "Speed (coming soon)",
|
|
9
|
+
playPause: "Play / Pause (Space)",
|
|
10
|
+
fullscreen: "Fullscreen preview",
|
|
11
|
+
snap: "Snap",
|
|
12
|
+
snapOnTitle: "Turn off snap",
|
|
13
|
+
snapOffTitle: "Turn on snap",
|
|
14
|
+
zoomOut: "Zoom out",
|
|
15
|
+
zoomIn: "Zoom in",
|
|
16
|
+
reset: "Reset edits (keep sources)",
|
|
17
|
+
exitFullscreen: "Exit fullscreen",
|
|
18
|
+
exitFullscreenTitle: "Exit fullscreen (Esc)",
|
|
19
|
+
newTrack: "+ New track",
|
|
20
|
+
videoTrackLabel: "Video {n}",
|
|
21
|
+
audioTrackLabel: "Audio {n}"
|
|
22
|
+
};
|
|
23
|
+
var localeZh = {
|
|
24
|
+
undo: "\u64A4\u9500",
|
|
25
|
+
redo: "\u91CD\u505A",
|
|
26
|
+
split: "\u5206\u5272",
|
|
27
|
+
trimLeft: "\u5411\u5DE6\u88C1\u526A",
|
|
28
|
+
trimRight: "\u5411\u53F3\u88C1\u526A",
|
|
29
|
+
speedComingSoon: "\u53D8\u901F\uFF08\u5373\u5C06\u5230\u6765\uFF09",
|
|
30
|
+
playPause: "\u64AD\u653E / \u6682\u505C (Space)",
|
|
31
|
+
fullscreen: "\u5168\u5C4F\u9884\u89C8",
|
|
32
|
+
snap: "\u5438\u9644",
|
|
33
|
+
snapOnTitle: "\u5173\u95ED\u5438\u9644",
|
|
34
|
+
snapOffTitle: "\u5F00\u542F\u5438\u9644",
|
|
35
|
+
zoomOut: "\u7F29\u5C0F",
|
|
36
|
+
zoomIn: "\u653E\u5927",
|
|
37
|
+
reset: "\u91CD\u7F6E\u7F16\u8F91\uFF08\u4FDD\u7559\u89C6\u9891\u6E90\uFF09",
|
|
38
|
+
exitFullscreen: "\u9000\u51FA\u5168\u5C4F",
|
|
39
|
+
exitFullscreenTitle: "\u9000\u51FA\u5168\u5C4F (Esc)",
|
|
40
|
+
newTrack: "+ \u65B0\u8F68\u9053",
|
|
41
|
+
videoTrackLabel: "\u89C6\u9891 {n}",
|
|
42
|
+
audioTrackLabel: "\u97F3\u9891 {n}"
|
|
43
|
+
};
|
|
44
|
+
function mergeLocale(partial) {
|
|
45
|
+
return partial ? { ...localeEn, ...partial } : localeEn;
|
|
46
|
+
}
|
|
47
|
+
function formatLabel(template, vars) {
|
|
48
|
+
return template.replace(
|
|
49
|
+
/\{(\w+)\}/g,
|
|
50
|
+
(_, k) => k in vars ? String(vars[k]) : `{${k}}`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/theme.ts
|
|
55
|
+
var THEME_VARS = {
|
|
56
|
+
brand: "--color-brand",
|
|
57
|
+
secondary: "--color-secondary",
|
|
58
|
+
surface: "--color-surface",
|
|
59
|
+
dark: "--color-dark",
|
|
60
|
+
muted: "--color-muted",
|
|
61
|
+
card: "--color-card",
|
|
62
|
+
success: "--color-success",
|
|
63
|
+
warning: "--color-warning",
|
|
64
|
+
info: "--color-info",
|
|
65
|
+
error: "--color-error",
|
|
66
|
+
controlsBg: "--aicut-controls-bg",
|
|
67
|
+
controlsBorder: "--aicut-controls-border",
|
|
68
|
+
controlsText: "--aicut-controls-text",
|
|
69
|
+
controlsHover: "--aicut-controls-hover",
|
|
70
|
+
controlsActive: "--aicut-controls-active",
|
|
71
|
+
previewBg: "--aicut-preview-bg",
|
|
72
|
+
radiusSm: "--aicut-radius-sm",
|
|
73
|
+
radiusMd: "--aicut-radius-md",
|
|
74
|
+
radiusLg: "--aicut-radius-lg"
|
|
75
|
+
};
|
|
76
|
+
function applyTheme(root, theme) {
|
|
77
|
+
if (!theme) return;
|
|
78
|
+
for (const key of Object.keys(theme)) {
|
|
79
|
+
const cssVar = THEME_VARS[key];
|
|
80
|
+
const value = theme[key];
|
|
81
|
+
if (cssVar && value) root.style.setProperty(cssVar, value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { applyTheme, formatLabel, localeEn, localeZh, mergeLocale };
|
|
86
|
+
//# sourceMappingURL=chunk-CCDON7CU.js.map
|
|
87
|
+
//# sourceMappingURL=chunk-CCDON7CU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n.ts","../src/theme.ts"],"names":[],"mappings":"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","file":"chunk-CCDON7CU.js","sourcesContent":["/**\n * UI strings the editor paints into the DOM (toolbar tooltips, the\n * fullscreen exit button) and onto the timeline canvas (phantom new-\n * track label, track header labels). Every user-visible literal in\n * `@aicut/core` flows through this interface — there are no hidden\n * hard-coded translations elsewhere in the library.\n *\n * Defaults to English. Hosts that want Chinese (or any other locale)\n * pass `locale: localeZh` to `Editor.create` / `Timeline.create`, or\n * override individual keys with `locale: { undo: \"撤销\" }`.\n */\nexport interface Locale {\n // Toolbar tooltips\n undo: string;\n redo: string;\n split: string;\n trimLeft: string;\n trimRight: string;\n speedComingSoon: string;\n playPause: string;\n fullscreen: string;\n snap: string;\n /** Title shown on the snap button when snap is ON (clicking turns OFF). */\n snapOnTitle: string;\n /** Title shown when snap is OFF (clicking turns ON). */\n snapOffTitle: string;\n zoomOut: string;\n zoomIn: string;\n reset: string;\n\n // Fullscreen exit overlay\n exitFullscreen: string;\n exitFullscreenTitle: string;\n\n // Timeline canvas labels\n /** Phantom row that appears under the last track during a drag. */\n newTrack: string;\n /** Track header — `{n}` is replaced with the 1-based track index. */\n videoTrackLabel: string;\n /** Same template format as videoTrackLabel. */\n audioTrackLabel: string;\n}\n\n/** English. The library default — chosen over Chinese as the OSS norm. */\nexport const localeEn: Locale = {\n undo: \"Undo\",\n redo: \"Redo\",\n split: \"Split\",\n trimLeft: \"Trim left edge\",\n trimRight: \"Trim right edge\",\n speedComingSoon: \"Speed (coming soon)\",\n playPause: \"Play / Pause (Space)\",\n fullscreen: \"Fullscreen preview\",\n snap: \"Snap\",\n snapOnTitle: \"Turn off snap\",\n snapOffTitle: \"Turn on snap\",\n zoomOut: \"Zoom out\",\n zoomIn: \"Zoom in\",\n reset: \"Reset edits (keep sources)\",\n exitFullscreen: \"Exit fullscreen\",\n exitFullscreenTitle: \"Exit fullscreen (Esc)\",\n newTrack: \"+ New track\",\n videoTrackLabel: \"Video {n}\",\n audioTrackLabel: \"Audio {n}\",\n};\n\n/** Simplified Chinese. */\nexport const localeZh: Locale = {\n undo: \"撤销\",\n redo: \"重做\",\n split: \"分割\",\n trimLeft: \"向左裁剪\",\n trimRight: \"向右裁剪\",\n speedComingSoon: \"变速(即将到来)\",\n playPause: \"播放 / 暂停 (Space)\",\n fullscreen: \"全屏预览\",\n snap: \"吸附\",\n snapOnTitle: \"关闭吸附\",\n snapOffTitle: \"开启吸附\",\n zoomOut: \"缩小\",\n zoomIn: \"放大\",\n reset: \"重置编辑(保留视频源)\",\n exitFullscreen: \"退出全屏\",\n exitFullscreenTitle: \"退出全屏 (Esc)\",\n newTrack: \"+ 新轨道\",\n videoTrackLabel: \"视频 {n}\",\n audioTrackLabel: \"音频 {n}\",\n};\n\n/** Spread defaults under host overrides — host can supply a partial. */\nexport function mergeLocale(partial: Partial<Locale> | undefined): Locale {\n return partial ? { ...localeEn, ...partial } : localeEn;\n}\n\n/**\n * Replace `{key}` placeholders in a template. We only need `{n}`\n * substitution today; the implementation is generic so additional\n * keys (e.g. `{name}`) won't need a second pass.\n */\nexport function formatLabel(\n template: string,\n vars: Record<string, string | number>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, k) =>\n k in vars ? String(vars[k]) : `{${k}}`,\n );\n}\n","import type { Theme } from \"./types.js\";\n\n/**\n * Map `Theme` keys to the CSS custom property they write.\n *\n * Brand/palette keys share names with iqvise's globals.css so hosts\n * that already define `--color-brand` etc. at the page level get the\n * editor in their palette for free — `theme` props ONLY needed when\n * scoping to this editor instance.\n *\n * Chrome keys keep the `--aicut-controls-*` prefix because they have\n * no analogue in the host palette.\n */\nconst THEME_VARS: Record<keyof Theme, string> = {\n brand: \"--color-brand\",\n secondary: \"--color-secondary\",\n surface: \"--color-surface\",\n dark: \"--color-dark\",\n muted: \"--color-muted\",\n card: \"--color-card\",\n success: \"--color-success\",\n warning: \"--color-warning\",\n info: \"--color-info\",\n error: \"--color-error\",\n controlsBg: \"--aicut-controls-bg\",\n controlsBorder: \"--aicut-controls-border\",\n controlsText: \"--aicut-controls-text\",\n controlsHover: \"--aicut-controls-hover\",\n controlsActive: \"--aicut-controls-active\",\n previewBg: \"--aicut-preview-bg\",\n radiusSm: \"--aicut-radius-sm\",\n radiusMd: \"--aicut-radius-md\",\n radiusLg: \"--aicut-radius-lg\",\n};\n\nexport function applyTheme(root: HTMLElement, theme: Theme | undefined): void {\n if (!theme) return;\n for (const key of Object.keys(theme) as Array<keyof Theme>) {\n const cssVar = THEME_VARS[key];\n const value = theme[key];\n if (cssVar && value) root.style.setProperty(cssVar, value);\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,121 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* fullscreen exit button) and onto the timeline canvas (phantom new-
|
|
4
|
-
* track label, track header labels). Every user-visible literal in
|
|
5
|
-
* `@aicut/core` flows through this interface — there are no hidden
|
|
6
|
-
* hard-coded translations elsewhere in the library.
|
|
7
|
-
*
|
|
8
|
-
* Defaults to English. Hosts that want Chinese (or any other locale)
|
|
9
|
-
* pass `locale: localeZh` to `Editor.create` / `Timeline.create`, or
|
|
10
|
-
* override individual keys with `locale: { undo: "撤销" }`.
|
|
11
|
-
*/
|
|
12
|
-
interface Locale {
|
|
13
|
-
undo: string;
|
|
14
|
-
redo: string;
|
|
15
|
-
split: string;
|
|
16
|
-
trimLeft: string;
|
|
17
|
-
trimRight: string;
|
|
18
|
-
speedComingSoon: string;
|
|
19
|
-
playPause: string;
|
|
20
|
-
fullscreen: string;
|
|
21
|
-
snap: string;
|
|
22
|
-
/** Title shown on the snap button when snap is ON (clicking turns OFF). */
|
|
23
|
-
snapOnTitle: string;
|
|
24
|
-
/** Title shown when snap is OFF (clicking turns ON). */
|
|
25
|
-
snapOffTitle: string;
|
|
26
|
-
zoomOut: string;
|
|
27
|
-
zoomIn: string;
|
|
28
|
-
reset: string;
|
|
29
|
-
exitFullscreen: string;
|
|
30
|
-
exitFullscreenTitle: string;
|
|
31
|
-
/** Phantom row that appears under the last track during a drag. */
|
|
32
|
-
newTrack: string;
|
|
33
|
-
/** Track header — `{n}` is replaced with the 1-based track index. */
|
|
34
|
-
videoTrackLabel: string;
|
|
35
|
-
/** Same template format as videoTrackLabel. */
|
|
36
|
-
audioTrackLabel: string;
|
|
37
|
-
}
|
|
38
|
-
/** English. The library default — chosen over Chinese as the OSS norm. */
|
|
39
|
-
declare const localeEn: Locale;
|
|
40
|
-
/** Simplified Chinese. */
|
|
41
|
-
declare const localeZh: Locale;
|
|
42
|
-
/** Spread defaults under host overrides — host can supply a partial. */
|
|
43
|
-
declare function mergeLocale(partial: Partial<Locale> | undefined): Locale;
|
|
44
|
-
/**
|
|
45
|
-
* Replace `{key}` placeholders in a template. We only need `{n}`
|
|
46
|
-
* substitution today; the implementation is generic so additional
|
|
47
|
-
* keys (e.g. `{name}`) won't need a second pass.
|
|
48
|
-
*/
|
|
49
|
-
declare function formatLabel(template: string, vars: Record<string, string | number>): string;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Milliseconds. All timing in the project is expressed as integer ms to
|
|
53
|
-
* keep JSON serialization unambiguous (no frame-rate coupling in the
|
|
54
|
-
* data model — the renderer can present time as frames if it wants).
|
|
55
|
-
*/
|
|
56
|
-
type Ms = number;
|
|
57
|
-
interface MediaSource {
|
|
58
|
-
id: string;
|
|
59
|
-
url: string;
|
|
60
|
-
kind: "video" | "audio";
|
|
61
|
-
/** Optional — probed lazily from the <video> element if absent. */
|
|
62
|
-
duration?: Ms;
|
|
63
|
-
name?: string;
|
|
64
|
-
}
|
|
65
|
-
interface Clip {
|
|
66
|
-
id: string;
|
|
67
|
-
sourceId: string;
|
|
68
|
-
/** Window into the source — `in` inclusive, `out` exclusive. */
|
|
69
|
-
in: Ms;
|
|
70
|
-
out: Ms;
|
|
71
|
-
/** Position on the timeline. */
|
|
72
|
-
start: Ms;
|
|
73
|
-
/**
|
|
74
|
-
* Playback rate. 1 = normal, 2 = 2× speed. Default 1.
|
|
75
|
-
* Persisted in the project JSON so a host can restore exactly.
|
|
76
|
-
*/
|
|
77
|
-
speed?: number;
|
|
78
|
-
}
|
|
79
|
-
interface Track {
|
|
80
|
-
id: string;
|
|
81
|
-
kind: "video" | "audio";
|
|
82
|
-
/** Clips on this track. Must be kept sorted by `start` and non-overlapping. */
|
|
83
|
-
clips: Clip[];
|
|
84
|
-
}
|
|
85
|
-
interface Project {
|
|
86
|
-
/** Schema version — bump when breaking the JSON shape. */
|
|
87
|
-
version: 1;
|
|
88
|
-
sources: MediaSource[];
|
|
89
|
-
tracks: Track[];
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Subset of CSS variables the editor honors. Pass any custom values
|
|
93
|
-
* via `Editor` options; everything is forwarded as `--aicut-*` on the
|
|
94
|
-
* editor's root container, so a host can also override via plain CSS.
|
|
95
|
-
*/
|
|
96
|
-
interface Theme {
|
|
97
|
-
brand?: string;
|
|
98
|
-
secondary?: string;
|
|
99
|
-
surface?: string;
|
|
100
|
-
dark?: string;
|
|
101
|
-
muted?: string;
|
|
102
|
-
card?: string;
|
|
103
|
-
success?: string;
|
|
104
|
-
warning?: string;
|
|
105
|
-
info?: string;
|
|
106
|
-
error?: string;
|
|
107
|
-
/** Toolbar / ruler chrome. Background of the editor frame. */
|
|
108
|
-
controlsBg?: string;
|
|
109
|
-
controlsBorder?: string;
|
|
110
|
-
controlsText?: string;
|
|
111
|
-
controlsHover?: string;
|
|
112
|
-
controlsActive?: string;
|
|
113
|
-
/** Letterbox color around the preview video. Defaults to black. */
|
|
114
|
-
previewBg?: string;
|
|
115
|
-
radiusSm?: string;
|
|
116
|
-
radiusMd?: string;
|
|
117
|
-
radiusLg?: string;
|
|
118
|
-
}
|
|
1
|
+
import { M as Ms, T as Track, C as Clip, a as MediaSource, P as Project, b as Theme, L as Locale } from './types-C95koNwJ.cjs';
|
|
2
|
+
export { f as formatLabel, l as localeEn, c as localeZh, m as mergeLocale } from './types-C95koNwJ.cjs';
|
|
119
3
|
|
|
120
4
|
interface EditorOptions {
|
|
121
5
|
/** Host element to mount the editor into. Will be wiped on init. */
|
|
@@ -637,4 +521,4 @@ declare class Timeline {
|
|
|
637
521
|
private applySnap;
|
|
638
522
|
}
|
|
639
523
|
|
|
640
|
-
export {
|
|
524
|
+
export { Clip, Editor, type EditorApi, type EditorEventMap, type EditorEventName, type EditorOptions, HEADER_WIDTH, Locale, MediaSource, Ms, Project, RULER_HEIGHT, TRACK_HEIGHT, Theme, Timeline, type TimelineOptions, Track, createEmptyProject, createId, normalizeProject };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,121 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* fullscreen exit button) and onto the timeline canvas (phantom new-
|
|
4
|
-
* track label, track header labels). Every user-visible literal in
|
|
5
|
-
* `@aicut/core` flows through this interface — there are no hidden
|
|
6
|
-
* hard-coded translations elsewhere in the library.
|
|
7
|
-
*
|
|
8
|
-
* Defaults to English. Hosts that want Chinese (or any other locale)
|
|
9
|
-
* pass `locale: localeZh` to `Editor.create` / `Timeline.create`, or
|
|
10
|
-
* override individual keys with `locale: { undo: "撤销" }`.
|
|
11
|
-
*/
|
|
12
|
-
interface Locale {
|
|
13
|
-
undo: string;
|
|
14
|
-
redo: string;
|
|
15
|
-
split: string;
|
|
16
|
-
trimLeft: string;
|
|
17
|
-
trimRight: string;
|
|
18
|
-
speedComingSoon: string;
|
|
19
|
-
playPause: string;
|
|
20
|
-
fullscreen: string;
|
|
21
|
-
snap: string;
|
|
22
|
-
/** Title shown on the snap button when snap is ON (clicking turns OFF). */
|
|
23
|
-
snapOnTitle: string;
|
|
24
|
-
/** Title shown when snap is OFF (clicking turns ON). */
|
|
25
|
-
snapOffTitle: string;
|
|
26
|
-
zoomOut: string;
|
|
27
|
-
zoomIn: string;
|
|
28
|
-
reset: string;
|
|
29
|
-
exitFullscreen: string;
|
|
30
|
-
exitFullscreenTitle: string;
|
|
31
|
-
/** Phantom row that appears under the last track during a drag. */
|
|
32
|
-
newTrack: string;
|
|
33
|
-
/** Track header — `{n}` is replaced with the 1-based track index. */
|
|
34
|
-
videoTrackLabel: string;
|
|
35
|
-
/** Same template format as videoTrackLabel. */
|
|
36
|
-
audioTrackLabel: string;
|
|
37
|
-
}
|
|
38
|
-
/** English. The library default — chosen over Chinese as the OSS norm. */
|
|
39
|
-
declare const localeEn: Locale;
|
|
40
|
-
/** Simplified Chinese. */
|
|
41
|
-
declare const localeZh: Locale;
|
|
42
|
-
/** Spread defaults under host overrides — host can supply a partial. */
|
|
43
|
-
declare function mergeLocale(partial: Partial<Locale> | undefined): Locale;
|
|
44
|
-
/**
|
|
45
|
-
* Replace `{key}` placeholders in a template. We only need `{n}`
|
|
46
|
-
* substitution today; the implementation is generic so additional
|
|
47
|
-
* keys (e.g. `{name}`) won't need a second pass.
|
|
48
|
-
*/
|
|
49
|
-
declare function formatLabel(template: string, vars: Record<string, string | number>): string;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Milliseconds. All timing in the project is expressed as integer ms to
|
|
53
|
-
* keep JSON serialization unambiguous (no frame-rate coupling in the
|
|
54
|
-
* data model — the renderer can present time as frames if it wants).
|
|
55
|
-
*/
|
|
56
|
-
type Ms = number;
|
|
57
|
-
interface MediaSource {
|
|
58
|
-
id: string;
|
|
59
|
-
url: string;
|
|
60
|
-
kind: "video" | "audio";
|
|
61
|
-
/** Optional — probed lazily from the <video> element if absent. */
|
|
62
|
-
duration?: Ms;
|
|
63
|
-
name?: string;
|
|
64
|
-
}
|
|
65
|
-
interface Clip {
|
|
66
|
-
id: string;
|
|
67
|
-
sourceId: string;
|
|
68
|
-
/** Window into the source — `in` inclusive, `out` exclusive. */
|
|
69
|
-
in: Ms;
|
|
70
|
-
out: Ms;
|
|
71
|
-
/** Position on the timeline. */
|
|
72
|
-
start: Ms;
|
|
73
|
-
/**
|
|
74
|
-
* Playback rate. 1 = normal, 2 = 2× speed. Default 1.
|
|
75
|
-
* Persisted in the project JSON so a host can restore exactly.
|
|
76
|
-
*/
|
|
77
|
-
speed?: number;
|
|
78
|
-
}
|
|
79
|
-
interface Track {
|
|
80
|
-
id: string;
|
|
81
|
-
kind: "video" | "audio";
|
|
82
|
-
/** Clips on this track. Must be kept sorted by `start` and non-overlapping. */
|
|
83
|
-
clips: Clip[];
|
|
84
|
-
}
|
|
85
|
-
interface Project {
|
|
86
|
-
/** Schema version — bump when breaking the JSON shape. */
|
|
87
|
-
version: 1;
|
|
88
|
-
sources: MediaSource[];
|
|
89
|
-
tracks: Track[];
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Subset of CSS variables the editor honors. Pass any custom values
|
|
93
|
-
* via `Editor` options; everything is forwarded as `--aicut-*` on the
|
|
94
|
-
* editor's root container, so a host can also override via plain CSS.
|
|
95
|
-
*/
|
|
96
|
-
interface Theme {
|
|
97
|
-
brand?: string;
|
|
98
|
-
secondary?: string;
|
|
99
|
-
surface?: string;
|
|
100
|
-
dark?: string;
|
|
101
|
-
muted?: string;
|
|
102
|
-
card?: string;
|
|
103
|
-
success?: string;
|
|
104
|
-
warning?: string;
|
|
105
|
-
info?: string;
|
|
106
|
-
error?: string;
|
|
107
|
-
/** Toolbar / ruler chrome. Background of the editor frame. */
|
|
108
|
-
controlsBg?: string;
|
|
109
|
-
controlsBorder?: string;
|
|
110
|
-
controlsText?: string;
|
|
111
|
-
controlsHover?: string;
|
|
112
|
-
controlsActive?: string;
|
|
113
|
-
/** Letterbox color around the preview video. Defaults to black. */
|
|
114
|
-
previewBg?: string;
|
|
115
|
-
radiusSm?: string;
|
|
116
|
-
radiusMd?: string;
|
|
117
|
-
radiusLg?: string;
|
|
118
|
-
}
|
|
1
|
+
import { M as Ms, T as Track, C as Clip, a as MediaSource, P as Project, b as Theme, L as Locale } from './types-C95koNwJ.js';
|
|
2
|
+
export { f as formatLabel, l as localeEn, c as localeZh, m as mergeLocale } from './types-C95koNwJ.js';
|
|
119
3
|
|
|
120
4
|
interface EditorOptions {
|
|
121
5
|
/** Host element to mount the editor into. Will be wiped on init. */
|
|
@@ -637,4 +521,4 @@ declare class Timeline {
|
|
|
637
521
|
private applySnap;
|
|
638
522
|
}
|
|
639
523
|
|
|
640
|
-
export {
|
|
524
|
+
export { Clip, Editor, type EditorApi, type EditorEventMap, type EditorEventName, type EditorOptions, HEADER_WIDTH, Locale, MediaSource, Ms, Project, RULER_HEIGHT, TRACK_HEIGHT, Theme, Timeline, type TimelineOptions, Track, createEmptyProject, createId, normalizeProject };
|