@odori/cli 0.0.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/LICENSE +22 -0
- package/bin/odori.mjs +39 -0
- package/dist/chunk-7XJL2BYO.js +3552 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.js +10 -0
- package/dist/index.d.ts +622 -0
- package/dist/index.js +156 -0
- package/dist/registry-snapshot-NIH2JMQ6.js +3559 -0
- package/package.json +50 -0
- package/src/audio-mix.ts +133 -0
- package/src/binaries.ts +241 -0
- package/src/brand-file.ts +94 -0
- package/src/chunk-cache.ts +85 -0
- package/src/chunks.ts +78 -0
- package/src/cli.ts +319 -0
- package/src/commands/add.ts +151 -0
- package/src/commands/dev.ts +160 -0
- package/src/commands/doctor.ts +162 -0
- package/src/commands/exportVideo.ts +198 -0
- package/src/commands/init.ts +56 -0
- package/src/commands/inspect.ts +72 -0
- package/src/commands/list.ts +22 -0
- package/src/commands/new.ts +126 -0
- package/src/commands/shared.ts +96 -0
- package/src/commands/still.ts +40 -0
- package/src/commands/test.ts +265 -0
- package/src/commands/update.ts +183 -0
- package/src/config.ts +84 -0
- package/src/contracts.ts +159 -0
- package/src/cues.ts +141 -0
- package/src/determinism.ts +82 -0
- package/src/diff.ts +71 -0
- package/src/discovery.ts +216 -0
- package/src/formats.ts +119 -0
- package/src/index.ts +58 -0
- package/src/integrity.ts +101 -0
- package/src/jobs.ts +151 -0
- package/src/log.ts +17 -0
- package/src/open.ts +32 -0
- package/src/paths.ts +12 -0
- package/src/prepare-cache.ts +58 -0
- package/src/project.ts +196 -0
- package/src/registry-snapshot.json +3431 -0
- package/src/registry-source.ts +269 -0
- package/src/render.ts +627 -0
- package/src/server.ts +307 -0
- package/studio/index.html +41 -0
- package/studio/src/Studio.tsx +192 -0
- package/studio/src/components/AudioClip.tsx +64 -0
- package/studio/src/components/CanvasStage.tsx +79 -0
- package/studio/src/components/CommandPalette.tsx +129 -0
- package/studio/src/components/Diagnostics.tsx +93 -0
- package/studio/src/components/ExportPanel.tsx +234 -0
- package/studio/src/components/InputControls.tsx +110 -0
- package/studio/src/components/Thumbnail.tsx +71 -0
- package/studio/src/components/Transport.tsx +237 -0
- package/studio/src/components/Waveform.tsx +114 -0
- package/studio/src/components/Wordmark.tsx +449 -0
- package/studio/src/components/ui.tsx +138 -0
- package/studio/src/lib/mix-loudness.ts +52 -0
- package/studio/src/main.tsx +34 -0
- package/studio/src/shortcuts.ts +27 -0
- package/studio/src/studio.css +1232 -0
- package/studio/src/theme.ts +61 -0
- package/studio/src/views/AssetsView.tsx +111 -0
- package/studio/src/views/BrandsView.tsx +139 -0
- package/studio/src/views/ComponentsView.tsx +285 -0
- package/studio/src/views/HomeView.tsx +122 -0
- package/studio/src/views/VideosView.tsx +343 -0
- package/studio/src/virtual.d.ts +25 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {StrictMode} from "react";
|
|
2
|
+
import {createRoot} from "react-dom/client";
|
|
3
|
+
import {RenderSurface} from "odori";
|
|
4
|
+
import {Studio} from "./Studio";
|
|
5
|
+
import {project, videos} from "virtual:odori-project";
|
|
6
|
+
import "./studio.css";
|
|
7
|
+
|
|
8
|
+
const query = new URLSearchParams(window.location.search);
|
|
9
|
+
const renderMode = query.get("render") === "1";
|
|
10
|
+
const root = createRoot(document.getElementById("root")!);
|
|
11
|
+
|
|
12
|
+
if (renderMode) {
|
|
13
|
+
const requested = query.get("video");
|
|
14
|
+
const entry = videos.find((video) => video.metadata.id === requested) ?? videos[0];
|
|
15
|
+
if (!entry) throw new Error("No videos discovered. Create videos/<name>/video.tsx first.");
|
|
16
|
+
const input = query.get("input") ? (JSON.parse(atob(query.get("input")!)) as Record<string, unknown>) : undefined;
|
|
17
|
+
const prepared = query.get("prepared") ? JSON.parse(atob(query.get("prepared")!)) : undefined;
|
|
18
|
+
document.body.classList.add("render-mode");
|
|
19
|
+
root.render(
|
|
20
|
+
<RenderSurface
|
|
21
|
+
entry={entry}
|
|
22
|
+
initialFrame={Number(query.get("frame") ?? 0)}
|
|
23
|
+
input={input}
|
|
24
|
+
prepared={prepared}
|
|
25
|
+
assets={project.assets}
|
|
26
|
+
/>,
|
|
27
|
+
);
|
|
28
|
+
} else {
|
|
29
|
+
root.render(
|
|
30
|
+
<StrictMode>
|
|
31
|
+
<Studio />
|
|
32
|
+
</StrictMode>,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {useEffect, useRef} from "react";
|
|
2
|
+
|
|
3
|
+
export type ShortcutMap = Record<string, (event: KeyboardEvent) => void>;
|
|
4
|
+
|
|
5
|
+
const isTyping = (target: EventTarget | null) => {
|
|
6
|
+
const element = target as HTMLElement | null;
|
|
7
|
+
if (!element) return false;
|
|
8
|
+
return ["INPUT", "TEXTAREA", "SELECT"].includes(element.tagName) || element.isContentEditable;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Editor-style shortcuts that stay out of the way while typing in a control. */
|
|
12
|
+
export const useShortcuts = (map: ShortcutMap) => {
|
|
13
|
+
const latest = useRef(map);
|
|
14
|
+
latest.current = map;
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const onKeyDown = (event: KeyboardEvent) => {
|
|
18
|
+
if (isTyping(event.target) || event.metaKey || event.ctrlKey) return;
|
|
19
|
+
const handler = latest.current[event.key];
|
|
20
|
+
if (!handler) return;
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
handler(event);
|
|
23
|
+
};
|
|
24
|
+
window.addEventListener("keydown", onKeyDown);
|
|
25
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
26
|
+
}, []);
|
|
27
|
+
};
|