Skip to content

Commit 8beb451

Browse files
committed
feat(studio): add animation inspector alpha
1 parent b07b888 commit 8beb451

76 files changed

Lines changed: 11860 additions & 1527 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bun.lock

Lines changed: 14 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/scripts/build-copy.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async function main() {
6868
copyDir(join(CLI_ROOT, "src", "templates", tmpl), join(DIST, "templates", tmpl));
6969
}
7070

71-
for (const skill of ["hyperframes", "hyperframes-cli", "gsap"]) {
71+
for (const skill of ["hyperframes", "hyperframes-cli", "gsap", "hf-motion"]) {
7272
copyDir(join(REPO_ROOT, "skills", skill), join(DIST, "skills", skill));
7373
}
7474

packages/cli/src/server/fileWatcher.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ export interface ProjectWatcher {
99
}
1010

1111
const WATCHED_EXTENSIONS = new Set([".html", ".css", ".js", ".json"]);
12+
const IGNORED_SEGMENTS = new Set([
13+
".git",
14+
".hyperframes",
15+
".thumbnails",
16+
"node_modules",
17+
"renders",
18+
]);
1219
const DEBOUNCE_MS = 300;
1320

1421
export function createProjectWatcher(projectDir: string): ProjectWatcher {
@@ -19,6 +26,8 @@ export function createProjectWatcher(projectDir: string): ProjectWatcher {
1926
try {
2027
watcher = watch(projectDir, { recursive: true }, (_event, filename) => {
2128
if (!filename) return;
29+
const segments = filename.split(/[\\/]/).filter(Boolean);
30+
if (segments.some((segment) => IGNORED_SEGMENTS.has(segment))) return;
2231
const ext = "." + filename.split(".").pop()?.toLowerCase();
2332
if (!WATCHED_EXTENSIONS.has(ext)) return;
2433

packages/cli/src/server/studioServer.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,30 @@ export function createStudioServer(options: StudioServerOptions): StudioServer {
341341
return serve();
342342
});
343343

344+
const api = createStudioApi(adapter);
345+
let recentApiWriteAt = 0;
346+
347+
watcher.addListener((relativePath) => {
348+
if (Date.now() - recentApiWriteAt < 3000) return;
349+
void api
350+
.fetch(
351+
new Request(
352+
`http://studio/projects/${encodeURIComponent(project.id)}/history/adopt-external`,
353+
{
354+
method: "POST",
355+
headers: { "Content-Type": "application/json" },
356+
body: JSON.stringify({
357+
paths: [relativePath],
358+
actor: { type: "external" },
359+
}),
360+
},
361+
),
362+
)
363+
.catch((error) => {
364+
console.warn("[studio] Failed to adopt external file edit:", error);
365+
});
366+
});
367+
344368
app.get("/api/events", (c) => {
345369
return streamSSE(c, async (stream) => {
346370
const listener = () => {
@@ -356,10 +380,12 @@ export function createStudioServer(options: StudioServerOptions): StudioServer {
356380
// Mount the shared studio API at /api.
357381
// Use fetch() forwarding (not .route()) so the sub-app sees paths without
358382
// the /api prefix — the shared module's path extraction uses c.req.path.
359-
const api = createStudioApi(adapter);
360383
app.all("/api/*", async (c) => {
361384
const url = new URL(c.req.url);
362385
url.pathname = url.pathname.slice(4); // Strip "/api" prefix
386+
if (/^\/projects\/[^/]+\/(?:edits|history\/(?:undo|redo|record-applied))/.test(url.pathname)) {
387+
recentApiWriteAt = Date.now();
388+
}
363389
const forwardReq = new Request(url.toString(), {
364390
method: c.req.method,
365391
headers: c.req.raw.headers,

packages/core/package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,18 @@
3030
"types": "./src/compiler/index.ts"
3131
},
3232
"./runtime": "./dist/hyperframe.runtime.iife.js",
33+
"./runtime/lottie-readiness": {
34+
"import": "./src/runtime/adapters/lottieReadiness.ts",
35+
"types": "./src/runtime/adapters/lottieReadiness.ts"
36+
},
3337
"./studio-api": {
3438
"import": "./src/studio-api/index.ts",
3539
"types": "./src/studio-api/index.ts"
3640
},
41+
"./studio-history": {
42+
"import": "./src/studio-api/history/editHistory.ts",
43+
"types": "./src/studio-api/history/editHistory.ts"
44+
},
3745
"./text": {
3846
"import": "./src/text/index.ts",
3947
"types": "./src/text/index.ts"
@@ -61,10 +69,18 @@
6169
"types": "./dist/compiler/index.d.ts"
6270
},
6371
"./runtime": "./dist/hyperframe.runtime.iife.js",
72+
"./runtime/lottie-readiness": {
73+
"import": "./dist/runtime/adapters/lottieReadiness.js",
74+
"types": "./dist/runtime/adapters/lottieReadiness.d.ts"
75+
},
6476
"./studio-api": {
6577
"import": "./dist/studio-api/index.js",
6678
"types": "./dist/studio-api/index.d.ts"
6779
},
80+
"./studio-history": {
81+
"import": "./dist/studio-api/history/editHistory.js",
82+
"types": "./dist/studio-api/history/editHistory.d.ts"
83+
},
6884
"./text": {
6985
"import": "./dist/text/index.js",
7086
"types": "./dist/text/index.d.ts"

0 commit comments

Comments
 (0)