reframe-video 0.1.0 → 0.1.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/assets/sfx/LICENSE.md +5 -0
- package/assets/sfx/bgm-song21.mp3 +0 -0
- package/assets/sfx/pop.wav +0 -0
- package/assets/sfx/rise.wav +0 -0
- package/assets/sfx/shimmer.wav +0 -0
- package/assets/sfx/thud.wav +0 -0
- package/assets/sfx/tick.wav +0 -0
- package/assets/sfx/whoosh.wav +0 -0
- package/dist/analyze.js +44 -1
- package/dist/bin.js +371 -35
- package/dist/browserEntry.js +311 -8
- package/dist/cli.js +305 -21
- package/dist/index.js +566 -16
- package/dist/renderer-canvas.js +58 -3
- package/dist/trace-cli.js +677 -0
- package/dist/types/assets.d.ts +9 -0
- package/dist/types/compile.d.ts +15 -1
- package/dist/types/compose.d.ts +12 -2
- package/dist/types/dsl.d.ts +30 -1
- package/dist/types/evaluate.d.ts +17 -0
- package/dist/types/index.d.ts +5 -1
- package/dist/types/ir.d.ts +82 -1
- package/dist/types/motion.d.ts +54 -0
- package/dist/types/path.d.ts +15 -0
- package/dist/types/presets.d.ts +41 -0
- package/guides/edsl-guide.md +24 -0
- package/package.json +1 -1
- package/preview/src/main.ts +111 -6
- package/preview/src/panel.ts +37 -3
- package/preview/src/store.ts +28 -2
- package/preview/src/virtual.d.ts +9 -1
- package/preview/vite.config.ts +3 -2
package/preview/src/panel.ts
CHANGED
|
@@ -200,6 +200,39 @@ export function buildPanel(store: EditorStore, root: HTMLElement) {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
// --- beats (semantic groups) ---
|
|
204
|
+
const beats: Extract<TimelineIR, { kind: "beat" }>[] = [];
|
|
205
|
+
const beatOf = new Map<string, string>();
|
|
206
|
+
const walkBeats = (tl: TimelineIR, owner?: string) => {
|
|
207
|
+
if (tl.kind === "beat") {
|
|
208
|
+
beats.push(tl);
|
|
209
|
+
tl.children.forEach((c) => walkBeats(c, tl.name));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if ("label" in tl && tl.label !== undefined && owner) beatOf.set(tl.label, owner);
|
|
213
|
+
if ("children" in tl) tl.children.forEach((c) => walkBeats(c, owner));
|
|
214
|
+
};
|
|
215
|
+
if (ir.timeline) walkBeats(ir.timeline);
|
|
216
|
+
if (beats.length > 0) {
|
|
217
|
+
root.append(el("h3", {}, "Beats"));
|
|
218
|
+
for (const b of beats) {
|
|
219
|
+
const card = el("div", { class: "step-card beat-card" },
|
|
220
|
+
el("div", {}, `${b.name} `, el("span", { class: "kind" }, "(beat)")),
|
|
221
|
+
);
|
|
222
|
+
const gapRow = makeControl("gap", b.gap ?? 0, store.hasTimelineEdit(b.name, "gap"),
|
|
223
|
+
(v) => store.setTimelineParam(b.name, "gap", Number(v)),
|
|
224
|
+
() => store.unsetTimelineParam(b.name, "gap"));
|
|
225
|
+
gapRow.prepend(el("label", {}, "gap"));
|
|
226
|
+
card.append(gapRow);
|
|
227
|
+
const scaleRow = makeControl("scale", b.scale ?? 1, store.hasTimelineEdit(b.name, "scale"),
|
|
228
|
+
(v) => store.setTimelineParam(b.name, "scale", Number(v)),
|
|
229
|
+
() => store.unsetTimelineParam(b.name, "scale"));
|
|
230
|
+
scaleRow.prepend(el("label", {}, "scale"));
|
|
231
|
+
card.append(scaleRow);
|
|
232
|
+
root.append(card);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
203
236
|
// --- labeled timeline steps ---
|
|
204
237
|
const steps: Extract<TimelineIR, { label?: string }>[] = [];
|
|
205
238
|
const walkTl = (tl: TimelineIR) => {
|
|
@@ -211,9 +244,10 @@ export function buildPanel(store: EditorStore, root: HTMLElement) {
|
|
|
211
244
|
root.append(el("h3", {}, "Timeline"));
|
|
212
245
|
for (const step of steps) {
|
|
213
246
|
const label = step.label!;
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
);
|
|
247
|
+
const beatName = beatOf.get(label);
|
|
248
|
+
const head = el("div", {}, `${label} `, el("span", { class: "kind" }, `(${step.kind})`));
|
|
249
|
+
if (beatName) head.append(el("span", { class: "badge" }, ` ↳ ${beatName}`));
|
|
250
|
+
const card = el("div", { class: "step-card" }, head);
|
|
217
251
|
const durRow = makeControl(
|
|
218
252
|
"duration",
|
|
219
253
|
"duration" in step ? (step.duration ?? 0.5) : 0.5,
|
package/preview/src/store.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type OverlayDoc,
|
|
16
16
|
type PropValue,
|
|
17
17
|
type SceneIR,
|
|
18
|
+
type TimelineIR,
|
|
18
19
|
} from "@reframe/core";
|
|
19
20
|
|
|
20
21
|
export type ChangeKind = "value" | "structure";
|
|
@@ -91,12 +92,37 @@ export class EditorStore {
|
|
|
91
92
|
this.recompose("structure");
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
setTimelineParam(
|
|
95
|
+
setTimelineParam(
|
|
96
|
+
label: string,
|
|
97
|
+
key: "duration" | "ease" | "stagger" | "at" | "gap" | "scale" | "order",
|
|
98
|
+
value: number | string,
|
|
99
|
+
) {
|
|
95
100
|
((this.draft.timeline ??= {})[label] ??= {})[key] = value as never;
|
|
96
101
|
this.recompose("value");
|
|
97
102
|
}
|
|
98
103
|
|
|
99
|
-
|
|
104
|
+
/** Labeled motionPath steps with their (possibly overlay-edited) waypoints —
|
|
105
|
+
* drives the preview's draggable handles and is exposed on window.__store. */
|
|
106
|
+
motionPaths(): { label: string; points: [number, number][] }[] {
|
|
107
|
+
const out: { label: string; points: [number, number][] }[] = [];
|
|
108
|
+
const walk = (tl: TimelineIR) => {
|
|
109
|
+
if (tl.kind === "motionPath" && tl.label) out.push({ label: tl.label, points: tl.points });
|
|
110
|
+
if ("children" in tl) tl.children.forEach(walk);
|
|
111
|
+
};
|
|
112
|
+
if (this.compiled.ir.timeline) walk(this.compiled.ir.timeline);
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** A dragged waypoint writes the whole points array as a timeline patch. */
|
|
117
|
+
setMotionPathPoints(label: string, points: [number, number][]) {
|
|
118
|
+
((this.draft.timeline ??= {})[label] ??= {}).points = points;
|
|
119
|
+
this.recompose("value");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
unsetTimelineParam(
|
|
123
|
+
label: string,
|
|
124
|
+
key: "duration" | "ease" | "stagger" | "at" | "gap" | "scale" | "order",
|
|
125
|
+
) {
|
|
100
126
|
delete this.draft.timeline?.[label]?.[key];
|
|
101
127
|
this.prune();
|
|
102
128
|
this.recompose("structure");
|
package/preview/src/virtual.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
declare module "virtual:reframe-user-scenes" {
|
|
2
2
|
import type { SceneIR } from "@reframe/core";
|
|
3
|
-
export const userScenes: {
|
|
3
|
+
export const userScenes: {
|
|
4
|
+
name: string;
|
|
5
|
+
/** Absolute directory containing the scene file. */
|
|
6
|
+
dir: string;
|
|
7
|
+
load: () => Promise<{ default: SceneIR }>;
|
|
8
|
+
}[];
|
|
4
9
|
}
|
|
10
|
+
|
|
11
|
+
/** Absolute path of examples/scenes (injected by vite define; "" when packaged). */
|
|
12
|
+
declare const __REFRAME_EXAMPLES_DIR__: string;
|
package/preview/vite.config.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
-
import { basename, join, resolve } from "node:path";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { defineConfig, type Plugin } from "vite";
|
|
4
4
|
|
|
5
5
|
const PKG_ROOT = resolve(__dirname, "..");
|
|
@@ -31,7 +31,7 @@ const userScenesPlugin: Plugin = {
|
|
|
31
31
|
if (id !== "\0reframe-user-scenes") return undefined;
|
|
32
32
|
const entries = userScenes().map(
|
|
33
33
|
(s) =>
|
|
34
|
-
` { name: ${JSON.stringify(s.name)}, load: () => import(${JSON.stringify(`/@fs${s.path}`)}) },`,
|
|
34
|
+
` { name: ${JSON.stringify(s.name)}, dir: ${JSON.stringify(dirname(s.path))}, load: () => import(${JSON.stringify(`/@fs${s.path}`)}) },`,
|
|
35
35
|
);
|
|
36
36
|
return `export const userScenes = [\n${entries.join("\n")}\n];\n`;
|
|
37
37
|
},
|
|
@@ -39,6 +39,7 @@ const userScenesPlugin: Plugin = {
|
|
|
39
39
|
|
|
40
40
|
export default defineConfig({
|
|
41
41
|
plugins: [userScenesPlugin],
|
|
42
|
+
define: { __REFRAME_EXAMPLES_DIR__: '""' }, // packaged preview ships no examples
|
|
42
43
|
resolve: {
|
|
43
44
|
alias: {
|
|
44
45
|
"@reframe/core": resolve(PKG_ROOT, "dist", "index.js"),
|