@smoove/studio 0.1.1

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.
Files changed (276) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/components/brand/brand.d.ts +9 -0
  4. package/dist/components/brand/brand.d.ts.map +1 -0
  5. package/dist/components/brand/brand.js +11 -0
  6. package/dist/components/brand/brand.js.map +1 -0
  7. package/dist/components/button/button.d.ts +21 -0
  8. package/dist/components/button/button.d.ts.map +1 -0
  9. package/dist/components/button/button.js +20 -0
  10. package/dist/components/button/button.js.map +1 -0
  11. package/dist/components/button/icon-button.d.ts +27 -0
  12. package/dist/components/button/icon-button.d.ts.map +1 -0
  13. package/dist/components/button/icon-button.js +19 -0
  14. package/dist/components/button/icon-button.js.map +1 -0
  15. package/dist/components/header/header-title.d.ts +8 -0
  16. package/dist/components/header/header-title.d.ts.map +1 -0
  17. package/dist/components/header/header-title.js +7 -0
  18. package/dist/components/header/header-title.js.map +1 -0
  19. package/dist/components/header/header.d.ts +7 -0
  20. package/dist/components/header/header.d.ts.map +1 -0
  21. package/dist/components/header/header.js +7 -0
  22. package/dist/components/header/header.js.map +1 -0
  23. package/dist/components/header/zoom.d.ts +3 -0
  24. package/dist/components/header/zoom.d.ts.map +1 -0
  25. package/dist/components/header/zoom.js +16 -0
  26. package/dist/components/header/zoom.js.map +1 -0
  27. package/dist/components/icon/icon.d.ts +11 -0
  28. package/dist/components/icon/icon.d.ts.map +1 -0
  29. package/dist/components/icon/icon.js +7 -0
  30. package/dist/components/icon/icon.js.map +1 -0
  31. package/dist/components/icon/paths.d.ts +47 -0
  32. package/dist/components/icon/paths.d.ts.map +1 -0
  33. package/dist/components/icon/paths.js +54 -0
  34. package/dist/components/icon/paths.js.map +1 -0
  35. package/dist/components/left-panel/library.d.ts +8 -0
  36. package/dist/components/left-panel/library.d.ts.map +1 -0
  37. package/dist/components/left-panel/library.js +49 -0
  38. package/dist/components/left-panel/library.js.map +1 -0
  39. package/dist/components/left-panel/sidebar-group.d.ts +12 -0
  40. package/dist/components/left-panel/sidebar-group.d.ts.map +1 -0
  41. package/dist/components/left-panel/sidebar-group.js +11 -0
  42. package/dist/components/left-panel/sidebar-group.js.map +1 -0
  43. package/dist/components/left-panel/sidebar-item.d.ts +17 -0
  44. package/dist/components/left-panel/sidebar-item.d.ts.map +1 -0
  45. package/dist/components/left-panel/sidebar-item.js +12 -0
  46. package/dist/components/left-panel/sidebar-item.js.map +1 -0
  47. package/dist/components/left-panel/sidebar.d.ts +8 -0
  48. package/dist/components/left-panel/sidebar.d.ts.map +1 -0
  49. package/dist/components/left-panel/sidebar.js +8 -0
  50. package/dist/components/left-panel/sidebar.js.map +1 -0
  51. package/dist/components/primitives/dialog.d.ts +33 -0
  52. package/dist/components/primitives/dialog.d.ts.map +1 -0
  53. package/dist/components/primitives/dialog.js +30 -0
  54. package/dist/components/primitives/dialog.js.map +1 -0
  55. package/dist/components/primitives/menu.d.ts +25 -0
  56. package/dist/components/primitives/menu.d.ts.map +1 -0
  57. package/dist/components/primitives/menu.js +31 -0
  58. package/dist/components/primitives/menu.js.map +1 -0
  59. package/dist/components/primitives/number-field.d.ts +12 -0
  60. package/dist/components/primitives/number-field.d.ts.map +1 -0
  61. package/dist/components/primitives/number-field.js +7 -0
  62. package/dist/components/primitives/number-field.js.map +1 -0
  63. package/dist/components/primitives/portal-context.d.ts +9 -0
  64. package/dist/components/primitives/portal-context.d.ts.map +1 -0
  65. package/dist/components/primitives/portal-context.js +10 -0
  66. package/dist/components/primitives/portal-context.js.map +1 -0
  67. package/dist/components/primitives/select.d.ts +14 -0
  68. package/dist/components/primitives/select.d.ts.map +1 -0
  69. package/dist/components/primitives/select.js +11 -0
  70. package/dist/components/primitives/select.js.map +1 -0
  71. package/dist/components/primitives/slider.d.ts +10 -0
  72. package/dist/components/primitives/slider.d.ts.map +1 -0
  73. package/dist/components/primitives/slider.js +7 -0
  74. package/dist/components/primitives/slider.js.map +1 -0
  75. package/dist/components/primitives/switch.d.ts +5 -0
  76. package/dist/components/primitives/switch.d.ts.map +1 -0
  77. package/dist/components/primitives/switch.js +6 -0
  78. package/dist/components/primitives/switch.js.map +1 -0
  79. package/dist/components/primitives/tabs.d.ts +23 -0
  80. package/dist/components/primitives/tabs.d.ts.map +1 -0
  81. package/dist/components/primitives/tabs.js +17 -0
  82. package/dist/components/primitives/tabs.js.map +1 -0
  83. package/dist/components/primitives/tooltip.d.ts +9 -0
  84. package/dist/components/primitives/tooltip.d.ts.map +1 -0
  85. package/dist/components/primitives/tooltip.js +11 -0
  86. package/dist/components/primitives/tooltip.js.map +1 -0
  87. package/dist/components/render/export-frame-dialog.d.ts +8 -0
  88. package/dist/components/render/export-frame-dialog.d.ts.map +1 -0
  89. package/dist/components/render/export-frame-dialog.js +60 -0
  90. package/dist/components/render/export-frame-dialog.js.map +1 -0
  91. package/dist/components/render/render-dialog.d.ts +8 -0
  92. package/dist/components/render/render-dialog.d.ts.map +1 -0
  93. package/dist/components/render/render-dialog.js +95 -0
  94. package/dist/components/render/render-dialog.js.map +1 -0
  95. package/dist/components/render/render-queue.d.ts +5 -0
  96. package/dist/components/render/render-queue.d.ts.map +1 -0
  97. package/dist/components/render/render-queue.js +40 -0
  98. package/dist/components/render/render-queue.js.map +1 -0
  99. package/dist/components/right-panel/panel-handle.d.ts +3 -0
  100. package/dist/components/right-panel/panel-handle.d.ts.map +1 -0
  101. package/dist/components/right-panel/panel-handle.js +9 -0
  102. package/dist/components/right-panel/panel-handle.js.map +1 -0
  103. package/dist/components/right-panel/panel-tabs.d.ts +3 -0
  104. package/dist/components/right-panel/panel-tabs.d.ts.map +1 -0
  105. package/dist/components/right-panel/panel-tabs.js +26 -0
  106. package/dist/components/right-panel/panel-tabs.js.map +1 -0
  107. package/dist/components/right-panel/panel.d.ts +8 -0
  108. package/dist/components/right-panel/panel.d.ts.map +1 -0
  109. package/dist/components/right-panel/panel.js +16 -0
  110. package/dist/components/right-panel/panel.js.map +1 -0
  111. package/dist/components/schema-form/field.d.ts +9 -0
  112. package/dist/components/schema-form/field.d.ts.map +1 -0
  113. package/dist/components/schema-form/field.js +102 -0
  114. package/dist/components/schema-form/field.js.map +1 -0
  115. package/dist/components/schema-form/schema-form.d.ts +3 -0
  116. package/dist/components/schema-form/schema-form.d.ts.map +1 -0
  117. package/dist/components/schema-form/schema-form.js +18 -0
  118. package/dist/components/schema-form/schema-form.js.map +1 -0
  119. package/dist/components/stage/stage.d.ts +12 -0
  120. package/dist/components/stage/stage.d.ts.map +1 -0
  121. package/dist/components/stage/stage.js +103 -0
  122. package/dist/components/stage/stage.js.map +1 -0
  123. package/dist/components/studio/features.d.ts +4 -0
  124. package/dist/components/studio/features.d.ts.map +1 -0
  125. package/dist/components/studio/features.js +18 -0
  126. package/dist/components/studio/features.js.map +1 -0
  127. package/dist/components/studio/layout.d.ts +19 -0
  128. package/dist/components/studio/layout.d.ts.map +1 -0
  129. package/dist/components/studio/layout.js +17 -0
  130. package/dist/components/studio/layout.js.map +1 -0
  131. package/dist/components/studio/studio-context.d.ts +53 -0
  132. package/dist/components/studio/studio-context.d.ts.map +1 -0
  133. package/dist/components/studio/studio-context.js +3 -0
  134. package/dist/components/studio/studio-context.js.map +1 -0
  135. package/dist/components/studio/studio.d.ts +21 -0
  136. package/dist/components/studio/studio.d.ts.map +1 -0
  137. package/dist/components/studio/studio.js +38 -0
  138. package/dist/components/studio/studio.js.map +1 -0
  139. package/dist/components/timeline/layered-body.d.ts +8 -0
  140. package/dist/components/timeline/layered-body.d.ts.map +1 -0
  141. package/dist/components/timeline/layered-body.js +75 -0
  142. package/dist/components/timeline/layered-body.js.map +1 -0
  143. package/dist/components/timeline/region-handles.d.ts +8 -0
  144. package/dist/components/timeline/region-handles.d.ts.map +1 -0
  145. package/dist/components/timeline/region-handles.js +13 -0
  146. package/dist/components/timeline/region-handles.js.map +1 -0
  147. package/dist/components/timeline/ruler.d.ts +7 -0
  148. package/dist/components/timeline/ruler.d.ts.map +1 -0
  149. package/dist/components/timeline/ruler.js +19 -0
  150. package/dist/components/timeline/ruler.js.map +1 -0
  151. package/dist/components/timeline/scrubber.d.ts +6 -0
  152. package/dist/components/timeline/scrubber.d.ts.map +1 -0
  153. package/dist/components/timeline/scrubber.js +25 -0
  154. package/dist/components/timeline/scrubber.js.map +1 -0
  155. package/dist/components/timeline/timeline-header.d.ts +3 -0
  156. package/dist/components/timeline/timeline-header.d.ts.map +1 -0
  157. package/dist/components/timeline/timeline-header.js +36 -0
  158. package/dist/components/timeline/timeline-header.js.map +1 -0
  159. package/dist/components/timeline/timeline.d.ts +5 -0
  160. package/dist/components/timeline/timeline.d.ts.map +1 -0
  161. package/dist/components/timeline/timeline.js +16 -0
  162. package/dist/components/timeline/timeline.js.map +1 -0
  163. package/dist/components/timeline/transport.d.ts +5 -0
  164. package/dist/components/timeline/transport.d.ts.map +1 -0
  165. package/dist/components/timeline/transport.js +21 -0
  166. package/dist/components/timeline/transport.js.map +1 -0
  167. package/dist/components/timeline/use-scrub-surface.d.ts +20 -0
  168. package/dist/components/timeline/use-scrub-surface.d.ts.map +1 -0
  169. package/dist/components/timeline/use-scrub-surface.js +56 -0
  170. package/dist/components/timeline/use-scrub-surface.js.map +1 -0
  171. package/dist/components/toasts/toasts.d.ts +4 -0
  172. package/dist/components/toasts/toasts.d.ts.map +1 -0
  173. package/dist/components/toasts/toasts.js +22 -0
  174. package/dist/components/toasts/toasts.js.map +1 -0
  175. package/dist/hooks/use-composition.d.ts +10 -0
  176. package/dist/hooks/use-composition.d.ts.map +1 -0
  177. package/dist/hooks/use-composition.js +13 -0
  178. package/dist/hooks/use-composition.js.map +1 -0
  179. package/dist/hooks/use-layers.d.ts +9 -0
  180. package/dist/hooks/use-layers.d.ts.map +1 -0
  181. package/dist/hooks/use-layers.js +34 -0
  182. package/dist/hooks/use-layers.js.map +1 -0
  183. package/dist/hooks/use-playback.d.ts +15 -0
  184. package/dist/hooks/use-playback.d.ts.map +1 -0
  185. package/dist/hooks/use-playback.js +38 -0
  186. package/dist/hooks/use-playback.js.map +1 -0
  187. package/dist/hooks/use-props-form.d.ts +15 -0
  188. package/dist/hooks/use-props-form.d.ts.map +1 -0
  189. package/dist/hooks/use-props-form.js +22 -0
  190. package/dist/hooks/use-props-form.js.map +1 -0
  191. package/dist/hooks/use-real-fps.d.ts +3 -0
  192. package/dist/hooks/use-real-fps.d.ts.map +1 -0
  193. package/dist/hooks/use-real-fps.js +27 -0
  194. package/dist/hooks/use-real-fps.js.map +1 -0
  195. package/dist/hooks/use-shortcuts.d.ts +7 -0
  196. package/dist/hooks/use-shortcuts.d.ts.map +1 -0
  197. package/dist/hooks/use-shortcuts.js +53 -0
  198. package/dist/hooks/use-shortcuts.js.map +1 -0
  199. package/dist/hooks/use-studio.d.ts +4 -0
  200. package/dist/hooks/use-studio.d.ts.map +1 -0
  201. package/dist/hooks/use-studio.js +10 -0
  202. package/dist/hooks/use-studio.js.map +1 -0
  203. package/dist/index.d.ts +145 -0
  204. package/dist/index.d.ts.map +1 -0
  205. package/dist/index.js +117 -0
  206. package/dist/index.js.map +1 -0
  207. package/dist/lib/cn.d.ts +3 -0
  208. package/dist/lib/cn.d.ts.map +1 -0
  209. package/dist/lib/cn.js +8 -0
  210. package/dist/lib/cn.js.map +1 -0
  211. package/dist/lib/constants.d.ts +28 -0
  212. package/dist/lib/constants.d.ts.map +1 -0
  213. package/dist/lib/constants.js +38 -0
  214. package/dist/lib/constants.js.map +1 -0
  215. package/dist/lib/cva.d.ts +25 -0
  216. package/dist/lib/cva.d.ts.map +1 -0
  217. package/dist/lib/cva.js +23 -0
  218. package/dist/lib/cva.js.map +1 -0
  219. package/dist/lib/format.d.ts +13 -0
  220. package/dist/lib/format.d.ts.map +1 -0
  221. package/dist/lib/format.js +25 -0
  222. package/dist/lib/format.js.map +1 -0
  223. package/dist/lib/ids.d.ts +3 -0
  224. package/dist/lib/ids.d.ts.map +1 -0
  225. package/dist/lib/ids.js +6 -0
  226. package/dist/lib/ids.js.map +1 -0
  227. package/dist/registry/define-registry.d.ts +8 -0
  228. package/dist/registry/define-registry.d.ts.map +1 -0
  229. package/dist/registry/define-registry.js +71 -0
  230. package/dist/registry/define-registry.js.map +1 -0
  231. package/dist/registry/props-signal.d.ts +9 -0
  232. package/dist/registry/props-signal.d.ts.map +1 -0
  233. package/dist/registry/props-signal.js +25 -0
  234. package/dist/registry/props-signal.js.map +1 -0
  235. package/dist/schema/kf.d.ts +28 -0
  236. package/dist/schema/kf.d.ts.map +1 -0
  237. package/dist/schema/kf.js +82 -0
  238. package/dist/schema/kf.js.map +1 -0
  239. package/dist/schema/types.d.ts +69 -0
  240. package/dist/schema/types.d.ts.map +1 -0
  241. package/dist/schema/types.js +4 -0
  242. package/dist/schema/types.js.map +1 -0
  243. package/dist/server/index.d.ts +6 -0
  244. package/dist/server/index.d.ts.map +1 -0
  245. package/dist/server/index.js +7 -0
  246. package/dist/server/index.js.map +1 -0
  247. package/dist/server/map.d.ts +19 -0
  248. package/dist/server/map.d.ts.map +1 -0
  249. package/dist/server/map.js +63 -0
  250. package/dist/server/map.js.map +1 -0
  251. package/dist/server/render-queue.d.ts +46 -0
  252. package/dist/server/render-queue.d.ts.map +1 -0
  253. package/dist/server/render-queue.js +147 -0
  254. package/dist/server/render-queue.js.map +1 -0
  255. package/dist/server/temp-storage.d.ts +13 -0
  256. package/dist/server/temp-storage.d.ts.map +1 -0
  257. package/dist/server/temp-storage.js +55 -0
  258. package/dist/server/temp-storage.js.map +1 -0
  259. package/dist/server/types.d.ts +57 -0
  260. package/dist/server/types.d.ts.map +1 -0
  261. package/dist/server/types.js +2 -0
  262. package/dist/server/types.js.map +1 -0
  263. package/dist/signals/signal-bridge.d.ts +18 -0
  264. package/dist/signals/signal-bridge.d.ts.map +1 -0
  265. package/dist/signals/signal-bridge.js +39 -0
  266. package/dist/signals/signal-bridge.js.map +1 -0
  267. package/dist/store/store.d.ts +74 -0
  268. package/dist/store/store.d.ts.map +1 -0
  269. package/dist/store/store.js +276 -0
  270. package/dist/store/store.js.map +1 -0
  271. package/dist/styles/studio.css +2 -0
  272. package/dist/types.d.ts +112 -0
  273. package/dist/types.d.ts.map +1 -0
  274. package/dist/types.js +2 -0
  275. package/dist/types.js.map +1 -0
  276. package/package.json +66 -0
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { usePlayback } from "../../hooks/use-playback.js";
3
+ import { useStudio } from "../../hooks/use-studio.js";
4
+ import { cn } from "../../lib/cn.js";
5
+ import { fmtTime } from "../../lib/format.js";
6
+ import { useSignalValue } from "../../signals/signal-bridge.js";
7
+ import { IconButton } from "../button/icon-button.js";
8
+ import { StSlider } from "../primitives/slider.js";
9
+ import { StTooltip } from "../primitives/tooltip.js";
10
+ /** Transport bar: play/step, volume, time, loop, fullscreen. */
11
+ export function Transport({ className }) {
12
+ const store = useStudio();
13
+ const { player, playing, loop, volume, muted, fullscreen, durSec, timeSec } = usePlayback();
14
+ const region = useSignalValue(store.region);
15
+ const regionActive = region.in != null || region.out != null;
16
+ return (_jsxs("div", { className: cn("flex items-center gap-1 px-3 h-[50px] flex-none", className), children: [_jsx(StTooltip, { content: "Restart", children: _jsx(IconButton, { size: "sm", icon: "prev", onClick: () => player?.seekTo(region.in ?? 0) }) }), _jsx(StTooltip, { content: playing ? "Pause (Space)" : "Play (Space)", children: _jsx(IconButton, { icon: playing ? "pause" : "play", iconSize: 20, className: "text-white", onClick: () => player?.toggle() }) }), _jsx(StTooltip, { content: "Step forward (\u2192)", children: _jsx(IconButton, { size: "sm", icon: "next", onClick: () => player?.stepBy(1) }) }), _jsxs("div", { className: "flex items-center group ml-1", children: [_jsx(StTooltip, { content: muted ? "Unmute" : "Mute", children: _jsx(IconButton, { size: "sm", icon: muted || volume === 0 ? "mute" : "volume", onClick: () => player?.setMuted(!muted) }) }), _jsx("div", { className: "w-0 group-hover:w-[78px] overflow-hidden transition-[width] flex items-center", children: _jsx(StSlider, { value: muted ? 0 : Math.round(volume * 100), min: 0, max: 100, className: "w-[70px] mx-1", onValueChange: (v) => {
17
+ player?.setVolume(v / 100);
18
+ player?.setMuted(v === 0);
19
+ } }) })] }), _jsxs("div", { className: "font-mono text-[12.5px] text-ink-2 ml-2 whitespace-nowrap tracking-tight tabular-nums", children: [_jsx("span", { className: "text-ink-1 inline-block text-right", style: { minWidth: "3.5ch" }, children: fmtTime(timeSec) }), _jsx("span", { className: "text-ink-3 mx-0.5", children: "/" }), fmtTime(durSec)] }), _jsx("div", { className: "flex-1" }), _jsx(StTooltip, { content: loop ? `Looping ${regionActive ? "region" : "playback"}` : "Loop off", children: _jsx(IconButton, { size: "sm", icon: "loop", active: loop, onClick: () => player?.toggleLoop(), className: "relative", children: regionActive && (_jsx("span", { className: "absolute top-1 right-1 size-1.5 rounded-full bg-accent-2 shadow-[0_0_6px_var(--color-accent-soft)]" })) }) }), _jsx(StTooltip, { content: fullscreen ? "Exit fullscreen (F)" : "Fullscreen (F)", children: _jsx(IconButton, { size: "sm", icon: fullscreen ? "fullscreenExit" : "fullscreen", onClick: () => player?.toggleFullscreen() }) })] }));
20
+ }
21
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/components/timeline/transport.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export type DragKind = "seek" | "in" | "out";
2
+ /**
3
+ * Shared pointer→frame drag handling for a scrub surface. Seeking maps the
4
+ * cursor to a frame; dragging the loop in/out grips snaps the playhead to the
5
+ * cursor too (per the design's "snap to cursor" requirement).
6
+ */
7
+ export declare function useScrubSurface(total: number): {
8
+ ref: import("react").MutableRefObject<HTMLDivElement | null>;
9
+ drag: DragKind | null;
10
+ setDrag: import("react").Dispatch<import("react").SetStateAction<DragKind | null>>;
11
+ hover: number | null;
12
+ setHover: import("react").Dispatch<import("react").SetStateAction<number | null>>;
13
+ frac: (clientX: number) => number;
14
+ frameAt: (clientX: number) => number;
15
+ seekTo: (clientX: number) => void;
16
+ inFrame: number;
17
+ outFrame: number;
18
+ den: number;
19
+ };
20
+ //# sourceMappingURL=use-scrub-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-scrub-surface.d.ts","sourceRoot":"","sources":["../../../src/components/timeline/use-scrub-surface.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,CAAC;AAE7C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM;;;;;;oBAYpB,MAAM,KAAG,MAAM;uBAKZ,MAAM,KAAG,MAAM;sBAChB,MAAM,KAAG,IAAI;;;;EA2BvC"}
@@ -0,0 +1,56 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { useStudio } from "../../hooks/use-studio.js";
3
+ import { clamp01 } from "../../lib/format.js";
4
+ import { useSignalValue } from "../../signals/signal-bridge.js";
5
+ /**
6
+ * Shared pointer→frame drag handling for a scrub surface. Seeking maps the
7
+ * cursor to a frame; dragging the loop in/out grips snaps the playhead to the
8
+ * cursor too (per the design's "snap to cursor" requirement).
9
+ */
10
+ export function useScrubSurface(total) {
11
+ const store = useStudio();
12
+ const player = useSignalValue(store.player);
13
+ const region = useSignalValue(store.region);
14
+ const ref = useRef(null);
15
+ const [drag, setDrag] = useState(null);
16
+ const [hover, setHover] = useState(null);
17
+ const den = Math.max(1, total - 1);
18
+ const inFrame = region.in ?? 0;
19
+ const outFrame = region.out ?? den;
20
+ const frac = (clientX) => {
21
+ const r = ref.current?.getBoundingClientRect();
22
+ if (!r || r.width === 0)
23
+ return 0;
24
+ return clamp01((clientX - r.left) / r.width);
25
+ };
26
+ const frameAt = (clientX) => Math.round(frac(clientX) * den);
27
+ const seekTo = (clientX) => player?.seekTo(frameAt(clientX));
28
+ // biome-ignore lint/correctness/useExhaustiveDependencies: store/player stable refs
29
+ useEffect(() => {
30
+ if (!drag)
31
+ return;
32
+ const move = (e) => {
33
+ const f = frameAt(e.clientX);
34
+ if (drag === "seek") {
35
+ player?.seekTo(f);
36
+ }
37
+ else if (drag === "in") {
38
+ store.setRegionIn(f);
39
+ player?.seekTo(f);
40
+ }
41
+ else if (drag === "out") {
42
+ store.setRegionOut(f);
43
+ player?.seekTo(f);
44
+ }
45
+ };
46
+ const up = () => setDrag(null);
47
+ window.addEventListener("mousemove", move);
48
+ window.addEventListener("mouseup", up);
49
+ return () => {
50
+ window.removeEventListener("mousemove", move);
51
+ window.removeEventListener("mouseup", up);
52
+ };
53
+ }, [drag, den, player, store]);
54
+ return { ref, drag, setDrag, hover, setHover, frac, frameAt, seekTo, inFrame, outFrame, den };
55
+ }
56
+ //# sourceMappingURL=use-scrub-surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-scrub-surface.js","sourceRoot":"","sources":["../../../src/components/timeline/use-scrub-surface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Toast viewport (Base UI Toast). Registers the store's toast sink so
2
+ store.addToast routes through the manager (auto-dismiss + a11y). */
3
+ export declare function Toasts(): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=toasts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toasts.d.ts","sourceRoot":"","sources":["../../../src/components/toasts/toasts.tsx"],"names":[],"mappings":"AASA;uEACuE;AACvE,wBAAgB,MAAM,4CAqCrB"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Toast } from "@base-ui/react/toast";
3
+ import { useEffect } from "react";
4
+ import { useStudio } from "../../hooks/use-studio.js";
5
+ import { Icon } from "../icon/icon.js";
6
+ import { usePortalContainer } from "../primitives/portal-context.js";
7
+ /** Toast viewport (Base UI Toast). Registers the store's toast sink so
8
+ store.addToast routes through the manager (auto-dismiss + a11y). */
9
+ export function Toasts() {
10
+ const store = useStudio();
11
+ const container = usePortalContainer();
12
+ const manager = Toast.useToastManager();
13
+ useEffect(() => {
14
+ store.setToastSink((title, icon) => manager.add({ title, data: { icon }, timeout: 3600 }));
15
+ return () => store.setToastSink(null);
16
+ }, [manager, store]);
17
+ return (_jsx(Toast.Portal, { container: container, children: _jsx(Toast.Viewport, { className: "fixed bottom-5 left-1/2 -translate-x-1/2 z-[60] flex flex-col gap-2 w-[320px] outline-none", children: manager.toasts.map((t) => {
18
+ const icon = t.data?.icon ?? "check";
19
+ return (_jsxs(Toast.Root, { toast: t, className: "flex items-center gap-2.5 bg-bg-1/97 backdrop-blur-xl border border-line-2 rounded-ui px-3.5 py-2.5 text-[13px] font-medium text-ink-1 shadow-[0_18px_44px_-12px_rgba(0,0,0,.7)] data-[starting-style]:opacity-0 data-[starting-style]:translate-y-3 data-[ending-style]:opacity-0 transition-all", style: { "--gap": "8px" }, children: [_jsx("span", { className: "size-[18px] grid place-items-center text-accent-2 flex-none", children: _jsx(Icon, { name: icon, size: 14 }) }), _jsx(Toast.Title, { className: "flex-1" }), _jsx(Toast.Close, { className: "text-ink-3 hover:text-ink-1", children: _jsx(Icon, { name: "close", size: 13 }) })] }, t.id));
20
+ }) }) }));
21
+ }
22
+ //# sourceMappingURL=toasts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toasts.js","sourceRoot":"","sources":["../../../src/components/toasts/toasts.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAsB,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAIrE;uEACuE;AACvE,MAAM,UAAU,MAAM;IACpB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,eAAe,EAAE,CAAC;IAExC,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,YAAY,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CACjC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAsB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAC1E,CAAC;QACF,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAErB,OAAO,CACL,KAAC,KAAK,CAAC,MAAM,IAAC,SAAS,EAAE,SAAS,YAChC,KAAC,KAAK,CAAC,QAAQ,IAAC,SAAS,EAAC,4FAA4F,YACnH,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACxB,MAAM,IAAI,GAAI,CAAC,CAAC,IAA8B,EAAE,IAAI,IAAI,OAAO,CAAC;gBAChE,OAAO,CACL,MAAC,KAAK,CAAC,IAAI,IAET,KAAK,EAAE,CAAC,EACR,SAAS,EAAC,mSAAmS,EAC7S,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAmB,aAE1C,eAAM,SAAS,EAAC,6DAA6D,YAC3E,KAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAI,GACzB,EACP,KAAC,KAAK,CAAC,KAAK,IAAC,SAAS,EAAC,QAAQ,GAAG,EAClC,KAAC,KAAK,CAAC,KAAK,IAAC,SAAS,EAAC,6BAA6B,YAClD,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,EAAE,GAAI,GACnB,KAXT,CAAC,CAAC,EAAE,CAYE,CACd,CAAC;YACJ,CAAC,CAAC,GACa,GACJ,CAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { LoadStatus } from "../store/store.js";
2
+ /** Read the active composition + its load status from the store. */
3
+ export declare function useComposition(): {
4
+ composition: import("@smoove/core").Composition<Record<string, unknown>> | null;
5
+ selectedId: string;
6
+ status: LoadStatus;
7
+ error: string | null;
8
+ entry: import("../types.js").RegistryEntry<Record<string, unknown>> | undefined;
9
+ };
10
+ //# sourceMappingURL=use-composition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-composition.d.ts","sourceRoot":"","sources":["../../src/hooks/use-composition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,oEAAoE;AACpE,wBAAgB,cAAc;;;;;;EAQ7B"}
@@ -0,0 +1,13 @@
1
+ import { useSignalValue } from "../signals/signal-bridge.js";
2
+ import { useStudio } from "./use-studio.js";
3
+ /** Read the active composition + its load status from the store. */
4
+ export function useComposition() {
5
+ const store = useStudio();
6
+ const composition = useSignalValue(store.composition);
7
+ const selectedId = useSignalValue(store.selectedId);
8
+ const status = useSignalValue(store.loadStatus)[selectedId] ?? "idle";
9
+ const error = useSignalValue(store.loadError);
10
+ const entry = store.getEntry(selectedId);
11
+ return { composition, selectedId, status, error, entry };
12
+ }
13
+ //# sourceMappingURL=use-composition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-composition.js","sourceRoot":"","sources":["../../src/hooks/use-composition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,oEAAoE;AACpE,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,MAAM,GAAe,cAAc,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC;IAClF,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACzC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type Composition, Sequence } from "@smoove/core";
2
+ import type { StudioLayer } from "../types.js";
3
+ /** Top-level `Sequence`s of a composition, in tree order. */
4
+ export declare function sequencesOf(comp: Composition): Sequence[];
5
+ /** Derive timeline tracks from a composition's top-level Sequences. */
6
+ export declare function deriveLayers(comp: Composition): StudioLayer[];
7
+ /** Apply per-layer enable/disable to the real Konva Sequences (opacity). */
8
+ export declare function applyLayerVisibility(comp: Composition, off: Set<number>): void;
9
+ //# sourceMappingURL=use-layers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-layers.d.ts","sourceRoot":"","sources":["../../src/hooks/use-layers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW/C,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,QAAQ,EAAE,CAEzD;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE,CAY7D;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAQ9E"}
@@ -0,0 +1,34 @@
1
+ import { Sequence } from "@smoove/core";
2
+ import { clamp01 } from "../lib/format.js";
3
+ const KIND_RE = /^(audio|video|group|transition|sequence):/i;
4
+ function inferKind(name) {
5
+ const m = KIND_RE.exec(name);
6
+ return m?.[1]?.toLowerCase() ?? "sequence";
7
+ }
8
+ const stripPrefix = (name) => name.replace(KIND_RE, "").trim();
9
+ /** Top-level `Sequence`s of a composition, in tree order. */
10
+ export function sequencesOf(comp) {
11
+ return comp.getChildren((n) => n instanceof Sequence);
12
+ }
13
+ /** Derive timeline tracks from a composition's top-level Sequences. */
14
+ export function deriveLayers(comp) {
15
+ const total = comp.durationInFrames.get() || 1;
16
+ return sequencesOf(comp).map((s, i) => {
17
+ const raw = s.name() || s.id() || `Layer ${i + 1}`;
18
+ return {
19
+ name: stripPrefix(raw) || `Layer ${i + 1}`,
20
+ kind: inferKind(raw),
21
+ start: clamp01(s.from / total),
22
+ end: clamp01((s.from + s.durationInFrames) / total),
23
+ };
24
+ });
25
+ }
26
+ /** Apply per-layer enable/disable to the real Konva Sequences (opacity). */
27
+ export function applyLayerVisibility(comp, off) {
28
+ const seqs = sequencesOf(comp);
29
+ seqs.forEach((s, i) => {
30
+ s.opacity(off.has(i) ? 0 : 1);
31
+ });
32
+ comp.batchDraw();
33
+ }
34
+ //# sourceMappingURL=use-layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-layers.js","sourceRoot":"","sources":["../../src/hooks/use-layers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAG3C,MAAM,OAAO,GAAG,4CAA4C,CAAC;AAE7D,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAA4B,IAAI,UAAU,CAAC;AACxE,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAE/E,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,IAAiB;IAC3C,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,QAAQ,CAAe,CAAC;AACtE,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,IAAiB;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QAEnD,OAAO;YACL,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE;YAC1C,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC;YACpB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;YAC9B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAC;SACpD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,oBAAoB,CAAC,IAAiB,EAAE,GAAgB;IACtE,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** All live playback values, sourced from the mounted player's signals. */
2
+ export declare function usePlayback(): {
3
+ player: import("@smoove/player").PlayerApi | null;
4
+ frame: number;
5
+ total: number;
6
+ playing: boolean;
7
+ loop: boolean;
8
+ volume: number;
9
+ muted: boolean;
10
+ fullscreen: boolean;
11
+ fps: number;
12
+ durSec: number;
13
+ timeSec: number;
14
+ };
15
+ //# sourceMappingURL=use-playback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-playback.d.ts","sourceRoot":"","sources":["../../src/hooks/use-playback.ts"],"names":[],"mappings":"AAcA,2EAA2E;AAC3E,wBAAgB,WAAW;;;;;;;;;;;;EAwB1B"}
@@ -0,0 +1,38 @@
1
+ import { usePlayerSignal, useSignalValue } from "../signals/signal-bridge.js";
2
+ import { useStudio } from "./use-studio.js";
3
+ const numSig = (v) => ({ get: () => v, subscribe: () => () => { } });
4
+ const boolSig = (v) => ({
5
+ get: () => v,
6
+ subscribe: () => () => { },
7
+ });
8
+ const ZERO = numSig(0);
9
+ const ONE = numSig(1);
10
+ const FALSE = boolSig(false);
11
+ const VOL = numSig(1);
12
+ /** All live playback values, sourced from the mounted player's signals. */
13
+ export function usePlayback() {
14
+ const store = useStudio();
15
+ const player = useSignalValue(store.player);
16
+ const frame = usePlayerSignal(player?.state.frame ?? ZERO);
17
+ const total = usePlayerSignal(player?.state.duration ?? ONE);
18
+ const playing = usePlayerSignal(player?.state.playing ?? FALSE);
19
+ const loop = usePlayerSignal(player?.state.loop ?? FALSE);
20
+ const volume = usePlayerSignal(player?.state.volume ?? VOL);
21
+ const muted = usePlayerSignal(player?.state.muted ?? FALSE);
22
+ const fullscreen = usePlayerSignal(player?.state.fullscreen ?? FALSE);
23
+ const fps = player?.fps || 30;
24
+ return {
25
+ player,
26
+ frame,
27
+ total,
28
+ playing,
29
+ loop,
30
+ volume,
31
+ muted,
32
+ fullscreen,
33
+ fps,
34
+ durSec: total / fps,
35
+ timeSec: frame / fps,
36
+ };
37
+ }
38
+ //# sourceMappingURL=use-playback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-playback.js","sourceRoot":"","sources":["../../src/hooks/use-playback.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,MAAM,GAAG,CAAC,CAAS,EAA0B,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC,CAAC;AACpG,MAAM,OAAO,GAAG,CAAC,CAAU,EAA2B,EAAE,CAAC,CAAC;IACxD,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACZ,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;CAC1B,CAAC,CAAC;AACH,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AACvB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAEtB,2EAA2E;AAC3E,MAAM,UAAU,WAAW;IACzB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,CAAC;IACtE,MAAM,GAAG,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;IAC9B,OAAO;QACL,MAAM;QACN,KAAK;QACL,KAAK;QACL,OAAO;QACP,IAAI;QACJ,MAAM;QACN,KAAK;QACL,UAAU;QACV,GAAG;QACH,MAAM,EAAE,KAAK,GAAG,GAAG;QACnB,OAAO,EAAE,KAAK,GAAG,GAAG;KACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { SmooveSchema } from "../schema/types.js";
2
+ export type PropsForm = {
3
+ schema?: SmooveSchema;
4
+ values: Record<string, unknown>;
5
+ setValue: (key: string, value: unknown) => void;
6
+ setValues: (next: Record<string, unknown>) => void;
7
+ reset: () => void;
8
+ };
9
+ /**
10
+ * Bridge a composition's props signal to the form: reading `values` re-renders
11
+ * on edits, writing pushes into the signal (which the studio has wired to
12
+ * `comp.refresh()`, so the preview updates with the playhead preserved).
13
+ */
14
+ export declare function usePropsForm(id: string): PropsForm;
15
+ //# sourceMappingURL=use-props-form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-props-form.d.ts","sourceRoot":"","sources":["../../src/hooks/use-props-form.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACnD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,CAYlD"}
@@ -0,0 +1,22 @@
1
+ import { resolveDefaults } from "../schema/kf.js";
2
+ import { usePlayerSignal } from "../signals/signal-bridge.js";
3
+ import { useStudio } from "./use-studio.js";
4
+ /**
5
+ * Bridge a composition's props signal to the form: reading `values` re-renders
6
+ * on edits, writing pushes into the signal (which the studio has wired to
7
+ * `comp.refresh()`, so the preview updates with the playhead preserved).
8
+ */
9
+ export function usePropsForm(id) {
10
+ const store = useStudio();
11
+ const sig = store.getPropsSignal(id);
12
+ const values = usePlayerSignal(sig);
13
+ const entry = store.getEntry(id);
14
+ return {
15
+ schema: entry?.propsSchema,
16
+ values,
17
+ setValue: (key, value) => sig.set({ ...sig.get(), [key]: value }),
18
+ setValues: (next) => sig.set(next),
19
+ reset: () => sig.set(resolveDefaults(entry?.propsSchema, entry?.defaultProps)),
20
+ };
21
+ }
22
+ //# sourceMappingURL=use-props-form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-props-form.js","sourceRoot":"","sources":["../../src/hooks/use-props-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAU5C;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjC,OAAO;QACL,MAAM,EAAE,KAAK,EAAE,WAAW;QAC1B,MAAM;QACN,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;QACjE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;QAClC,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;KAC/E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Measure realtime fps by counting how often the player's frame advances. */
2
+ export declare function useRealFps(): number;
3
+ //# sourceMappingURL=use-real-fps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-real-fps.d.ts","sourceRoot":"","sources":["../../src/hooks/use-real-fps.ts"],"names":[],"mappings":"AAIA,8EAA8E;AAC9E,wBAAgB,UAAU,IAAI,MAAM,CAoBnC"}
@@ -0,0 +1,27 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useSignalValue } from "../signals/signal-bridge.js";
3
+ import { useStudio } from "./use-studio.js";
4
+ /** Measure realtime fps by counting how often the player's frame advances. */
5
+ export function useRealFps() {
6
+ const store = useStudio();
7
+ const player = useSignalValue(store.player);
8
+ const [real, setReal] = useState(0);
9
+ useEffect(() => {
10
+ if (!player)
11
+ return;
12
+ let count = 0;
13
+ const unsub = player.state.frame.subscribe(() => {
14
+ count++;
15
+ });
16
+ const id = setInterval(() => {
17
+ setReal(count * 2);
18
+ count = 0;
19
+ }, 500);
20
+ return () => {
21
+ unsub();
22
+ clearInterval(id);
23
+ };
24
+ }, [player]);
25
+ return real;
26
+ }
27
+ //# sourceMappingURL=use-real-fps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-real-fps.js","sourceRoot":"","sources":["../../src/hooks/use-real-fps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,8EAA8E;AAC9E,MAAM,UAAU,UAAU;IACxB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;YAC9C,KAAK,EAAE,CAAC;QACV,CAAC,CAAC,CAAC;QACH,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;YAC1B,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACnB,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC,EAAE,GAAG,CAAC,CAAC;QACR,OAAO,GAAG,EAAE;YACV,KAAK,EAAE,CAAC;YACR,aAAa,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACb,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Global keyboard shortcuts. The studio owns them (the `<smoove-player>` is mounted
3
+ * with `no-keyboard`): space play/pause, ←/→ step, f fullscreen, l loop,
4
+ * i/o set loop in/out at the playhead. Ignored while typing in a field.
5
+ */
6
+ export declare function useShortcuts(): void;
7
+ //# sourceMappingURL=use-shortcuts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-shortcuts.d.ts","sourceRoot":"","sources":["../../src/hooks/use-shortcuts.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,IAAI,CA0CnC"}
@@ -0,0 +1,53 @@
1
+ import { useEffect } from "react";
2
+ import { useStudio } from "./use-studio.js";
3
+ /**
4
+ * Global keyboard shortcuts. The studio owns them (the `<smoove-player>` is mounted
5
+ * with `no-keyboard`): space play/pause, ←/→ step, f fullscreen, l loop,
6
+ * i/o set loop in/out at the playhead. Ignored while typing in a field.
7
+ */
8
+ export function useShortcuts() {
9
+ const store = useStudio();
10
+ useEffect(() => {
11
+ const onKey = (e) => {
12
+ const t = e.target;
13
+ if (t && (/^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName) || t.isContentEditable))
14
+ return;
15
+ const api = store.player.get();
16
+ if (!api)
17
+ return;
18
+ switch (e.key) {
19
+ case " ":
20
+ e.preventDefault();
21
+ api.toggle();
22
+ break;
23
+ case "ArrowRight":
24
+ e.preventDefault();
25
+ api.stepBy(1);
26
+ break;
27
+ case "ArrowLeft":
28
+ e.preventDefault();
29
+ api.stepBy(-1);
30
+ break;
31
+ case "f":
32
+ case "F":
33
+ api.toggleFullscreen();
34
+ break;
35
+ case "l":
36
+ case "L":
37
+ api.toggleLoop();
38
+ break;
39
+ case "i":
40
+ case "I":
41
+ store.setRegionIn(api.getCurrentFrame());
42
+ break;
43
+ case "o":
44
+ case "O":
45
+ store.setRegionOut(api.getCurrentFrame());
46
+ break;
47
+ }
48
+ };
49
+ window.addEventListener("keydown", onKey);
50
+ return () => window.removeEventListener("keydown", onKey);
51
+ }, [store]);
52
+ }
53
+ //# sourceMappingURL=use-shortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-shortcuts.js","sourceRoot":"","sources":["../../src/hooks/use-shortcuts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,CAAC,CAAgB,EAAE,EAAE;YACjC,MAAM,CAAC,GAAG,CAAC,CAAC,MAA4B,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,iBAAiB,CAAC;gBAAE,OAAO;YACtF,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG;gBAAE,OAAO;YACjB,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;gBACd,KAAK,GAAG;oBACN,CAAC,CAAC,cAAc,EAAE,CAAC;oBACnB,GAAG,CAAC,MAAM,EAAE,CAAC;oBACb,MAAM;gBACR,KAAK,YAAY;oBACf,CAAC,CAAC,cAAc,EAAE,CAAC;oBACnB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBACd,MAAM;gBACR,KAAK,WAAW;oBACd,CAAC,CAAC,cAAc,EAAE,CAAC;oBACnB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;oBACf,MAAM;gBACR,KAAK,GAAG,CAAC;gBACT,KAAK,GAAG;oBACN,GAAG,CAAC,gBAAgB,EAAE,CAAC;oBACvB,MAAM;gBACR,KAAK,GAAG,CAAC;gBACT,KAAK,GAAG;oBACN,GAAG,CAAC,UAAU,EAAE,CAAC;oBACjB,MAAM;gBACR,KAAK,GAAG,CAAC;gBACT,KAAK,GAAG;oBACN,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;oBACzC,MAAM;gBACR,KAAK,GAAG,CAAC;gBACT,KAAK,GAAG;oBACN,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;oBAC1C,MAAM;YACV,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { StudioStore } from "../store/store.js";
2
+ /** Read the central studio store. Must be used inside `<Studio>`. */
3
+ export declare function useStudio(): StudioStore;
4
+ //# sourceMappingURL=use-studio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-studio.d.ts","sourceRoot":"","sources":["../../src/hooks/use-studio.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,qEAAqE;AACrE,wBAAgB,SAAS,IAAI,WAAW,CAIvC"}
@@ -0,0 +1,10 @@
1
+ import { useContext } from "react";
2
+ import { StudioContext } from "../components/studio/studio-context.js";
3
+ /** Read the central studio store. Must be used inside `<Studio>`. */
4
+ export function useStudio() {
5
+ const ctx = useContext(StudioContext);
6
+ if (!ctx)
7
+ throw new Error("useStudio() must be used inside <Studio>");
8
+ return ctx;
9
+ }
10
+ //# sourceMappingURL=use-studio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-studio.js","sourceRoot":"","sources":["../../src/hooks/use-studio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAGvE,qEAAqE;AACrE,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACtE,OAAO,GAAG,CAAC;AACb,CAAC"}