@hypit/hypit 0.1.4 → 0.1.6

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 (462) hide show
  1. package/README.md +4 -2
  2. package/dist/public/caption.d.ts +206 -183
  3. package/dist/public/composition.d.ts +25 -3
  4. package/dist/public/endpoint-kit.d.ts +24 -2
  5. package/dist/public/generation.d.ts +5 -1
  6. package/dist/public/hyperframes.d.ts +19 -1
  7. package/dist/public/narrative.d.ts +17 -3
  8. package/dist/public/performance.d.ts +1590 -0
  9. package/dist/public/program-space.d.ts +179 -32
  10. package/dist/public/runtime-kit.d.ts +21 -8
  11. package/dist/public/sound.d.ts +822 -0
  12. package/dist/public/speech.d.ts +41 -0
  13. package/dist/public/studio-adapter.d.ts +77 -15
  14. package/dist/public/temporal-markup.d.ts +9 -44
  15. package/dist/public/temporal.d.ts +37 -28
  16. package/dist/public/{semantic-track.d.ts → timeline.d.ts} +62 -49
  17. package/examples/README.md +18 -10
  18. package/examples/minimal-author-package/packages/example-component/preview/preview.svml +19 -12
  19. package/examples/minimal-author-package/packages/example-component/src/component.ts +5 -5
  20. package/examples/minimal-author-package/packages/example-component/src/fragment.ts +3 -5
  21. package/examples/minimal-author-package/packages/example-component/src/manifest.ts +8 -10
  22. package/examples/minimal-author-package/packages/example-component/src/surface.ts +2 -2
  23. package/examples/provider-package/README.md +78 -0
  24. package/examples/provider-package/hypit.runtime.json +12 -0
  25. package/examples/provider-package/packages/provider-images/package.json +11 -0
  26. package/examples/provider-package/packages/provider-images/src/activation.ts +24 -0
  27. package/examples/provider-package/packages/provider-images/src/provider.ts +122 -0
  28. package/examples/provider-package/packages/provider-images/tsconfig.json +9 -0
  29. package/examples/semantic-composition/README.md +8 -1
  30. package/examples/semantic-composition/chat.svml +6 -5
  31. package/examples/semantic-composition/hypit.runtime.json +1 -1
  32. package/examples/semantic-composition/packages/chat-scene/README.md +3 -3
  33. package/examples/semantic-composition/packages/chat-scene/src/activation.ts +18 -21
  34. package/examples/semantic-composition/packages/chat-scene/src/render.ts +4 -4
  35. package/examples/semantic-composition/packages/performance-styles/README.md +42 -0
  36. package/examples/semantic-composition/packages/performance-styles/package.json +25 -0
  37. package/examples/semantic-composition/packages/performance-styles/src/activation.ts +57 -0
  38. package/examples/semantic-composition/packages/performance-styles/src/render.ts +54 -0
  39. package/examples/semantic-composition/packages/performance-styles/src/studio.ts +28 -0
  40. package/examples/semantic-composition/packages/performance-styles/tsconfig.json +18 -0
  41. package/examples/semantic-composition/packages/responsive-explainer/README.md +16 -9
  42. package/examples/semantic-composition/packages/responsive-explainer/src/activation.ts +12 -12
  43. package/examples/semantic-composition/packages/responsive-explainer/src/render.ts +5 -5
  44. package/examples/semantic-composition/packages/sound-styles/README.md +36 -0
  45. package/examples/semantic-composition/packages/sound-styles/package.json +25 -0
  46. package/examples/semantic-composition/packages/sound-styles/src/activation.ts +53 -0
  47. package/examples/semantic-composition/packages/sound-styles/src/render.ts +14 -0
  48. package/examples/semantic-composition/packages/sound-styles/tsconfig.json +18 -0
  49. package/package.json +35 -15
  50. package/packages/audio-track/README.md +20 -13
  51. package/packages/audio-track/package.json +1 -1
  52. package/packages/audio-track/src/component.ts +4 -4
  53. package/packages/audio-track/src/fragment.ts +6 -5
  54. package/packages/audio-track/src/index.ts +1 -1
  55. package/packages/audio-track/src/manifest.ts +17 -16
  56. package/packages/audio-track/src/program.ts +21 -25
  57. package/packages/audio-track/src/surface.ts +19 -18
  58. package/packages/audio-track-studio/README.md +23 -0
  59. package/packages/audio-track-studio/src/index.ts +28 -17
  60. package/packages/author-kit/README.md +1 -1
  61. package/packages/background-removal/README.md +4 -7
  62. package/packages/browser-capture/package.json +1 -1
  63. package/packages/build-result/README.md +11 -0
  64. package/packages/build-result/src/decode.ts +2 -0
  65. package/packages/build-result/src/execution-log.ts +17 -0
  66. package/packages/build-result/src/index.ts +1 -0
  67. package/packages/build-result/src/store.ts +14 -1
  68. package/packages/build-result/src/types.ts +3 -0
  69. package/packages/build-result-s3/src/repository.ts +4 -0
  70. package/packages/caption/README.md +61 -73
  71. package/packages/caption/package.json +3 -2
  72. package/packages/caption/src/activation.ts +2 -2
  73. package/packages/caption/src/component.ts +20 -5
  74. package/packages/caption/src/display.ts +3 -18
  75. package/packages/caption/src/fragment.ts +3 -7
  76. package/packages/caption/src/index.ts +6 -5
  77. package/packages/caption/src/manifest.ts +29 -46
  78. package/packages/caption/src/style.ts +24 -135
  79. package/packages/caption/src/surface.ts +12 -92
  80. package/packages/caption/src/temporalize.ts +18 -53
  81. package/packages/caption/src/types.ts +8 -35
  82. package/packages/caption/src/visibility.ts +23 -0
  83. package/packages/caption-fine/README.md +21 -9
  84. package/packages/caption-fine/package.json +4 -2
  85. package/packages/caption-fine/src/component.ts +3 -3
  86. package/packages/caption-fine/src/fragment.ts +7 -19
  87. package/packages/caption-fine/src/index.ts +2 -0
  88. package/packages/caption-fine/src/manifest.ts +26 -17
  89. package/packages/caption-fine/src/recipe.ts +7 -0
  90. package/packages/caption-fine/src/render.ts +14 -13
  91. package/packages/caption-fine/src/schedule.ts +39 -35
  92. package/packages/caption-fine/src/style.ts +10 -9
  93. package/packages/caption-fine/src/surface.ts +62 -35
  94. package/packages/caption-fine/src/types.ts +2 -0
  95. package/packages/caption-fine-studio/README.md +24 -2
  96. package/packages/caption-fine-studio/package.json +3 -1
  97. package/packages/caption-fine-studio/src/activation.ts +3 -3
  98. package/packages/caption-fine-studio/src/index.ts +54 -42
  99. package/packages/cli/README.md +57 -4
  100. package/packages/cli/package.json +1 -0
  101. package/packages/cli/src/arguments.ts +25 -6
  102. package/packages/cli/src/build-planning.ts +3 -2
  103. package/packages/cli/src/command.ts +6 -0
  104. package/packages/cli/src/commands/environment.ts +28 -18
  105. package/packages/cli/src/commands/execution.ts +81 -26
  106. package/packages/cli/src/commands/results.ts +7 -11
  107. package/packages/cli/src/index.ts +2 -2
  108. package/packages/cli/src/machine-view.ts +3 -2
  109. package/packages/cli/src/main.ts +34 -42
  110. package/packages/cli/src/observation.ts +7 -1
  111. package/packages/cli/src/output.ts +65 -23
  112. package/packages/cli/src/view.ts +66 -19
  113. package/packages/comment-sticker/README.md +3 -3
  114. package/packages/comment-sticker/package.json +1 -1
  115. package/packages/comment-sticker/src/component.ts +4 -4
  116. package/packages/comment-sticker/src/fragment.ts +5 -4
  117. package/packages/comment-sticker/src/manifest.ts +7 -6
  118. package/packages/comment-sticker/src/program.ts +9 -9
  119. package/packages/comment-sticker/src/surface.ts +6 -7
  120. package/packages/composition/README.md +21 -0
  121. package/packages/composition/src/audio-presentation.ts +44 -0
  122. package/packages/composition/src/index.ts +3 -0
  123. package/packages/composition/src/schema.ts +8 -3
  124. package/packages/composition/src/track.ts +15 -1
  125. package/packages/credential-store-env/README.md +1 -1
  126. package/packages/deck-track/README.md +3 -3
  127. package/packages/deck-track/package.json +1 -1
  128. package/packages/deck-track/src/component.ts +5 -5
  129. package/packages/deck-track/src/fragment.ts +6 -5
  130. package/packages/deck-track/src/lower.ts +12 -12
  131. package/packages/deck-track/src/manifest.ts +8 -7
  132. package/packages/deck-track/src/program.ts +13 -16
  133. package/packages/deck-track/src/surface.ts +9 -10
  134. package/packages/driver-node/src/driver.ts +41 -3
  135. package/packages/elevenlabs-speech/README.md +27 -0
  136. package/packages/{provider-xiaomi-mimo → elevenlabs-speech}/package.json +5 -8
  137. package/packages/elevenlabs-speech/src/activation.ts +26 -0
  138. package/packages/elevenlabs-speech/src/fragment.ts +11 -0
  139. package/packages/elevenlabs-speech/src/index.ts +111 -0
  140. package/packages/elevenlabs-speech/src/surface.ts +167 -0
  141. package/packages/endpoint-kit/README.md +24 -0
  142. package/packages/endpoint-kit/src/index.ts +7 -1
  143. package/packages/film/README.md +12 -7
  144. package/packages/film/package.json +1 -1
  145. package/packages/film/src/component.ts +4 -4
  146. package/packages/film/src/fragment.ts +6 -5
  147. package/packages/film/src/manifest.ts +11 -10
  148. package/packages/film/src/program.ts +5 -5
  149. package/packages/film/src/recipe.ts +2 -1
  150. package/packages/film/src/surface.ts +10 -7
  151. package/packages/film-studio/package.json +1 -1
  152. package/packages/film-studio/src/index.ts +2 -2
  153. package/packages/fishaudio-speech/README.md +33 -0
  154. package/packages/fishaudio-speech/package.json +21 -0
  155. package/packages/fishaudio-speech/src/activation.ts +32 -0
  156. package/packages/fishaudio-speech/src/fragment.ts +11 -0
  157. package/packages/fishaudio-speech/src/index.ts +156 -0
  158. package/packages/fishaudio-speech/src/surface.ts +192 -0
  159. package/packages/generation/README.md +11 -1
  160. package/packages/generation/src/mapping.ts +28 -30
  161. package/packages/gpt-image/README.md +1 -2
  162. package/packages/grok-imagine/README.md +1 -2
  163. package/packages/hyperframes/README.md +7 -3
  164. package/packages/hyperframes/src/browser-program.ts +11 -2
  165. package/packages/hyperframes/src/document.ts +15 -2
  166. package/packages/interview-emoji-reveal/README.md +4 -4
  167. package/packages/interview-emoji-reveal/package.json +1 -1
  168. package/packages/interview-emoji-reveal/src/component.ts +4 -4
  169. package/packages/interview-emoji-reveal/src/fragment.ts +6 -5
  170. package/packages/interview-emoji-reveal/src/manifest.ts +9 -8
  171. package/packages/interview-emoji-reveal/src/program.ts +14 -14
  172. package/packages/interview-emoji-reveal/src/surface.ts +8 -9
  173. package/packages/media-execution/README.md +7 -3
  174. package/packages/media-execution/src/audio-presentation.ts +23 -0
  175. package/packages/media-execution/src/execute.ts +2 -0
  176. package/packages/media-pipeline/README.md +7 -3
  177. package/packages/media-pipeline/src/audio-plan.ts +4 -1
  178. package/packages/media-pipeline/src/component.ts +16 -2
  179. package/packages/media-pipeline/src/manifest.ts +3 -1
  180. package/packages/media-pipeline/src/types.ts +2 -1
  181. package/packages/media-track/README.md +14 -47
  182. package/packages/media-track/package.json +1 -1
  183. package/packages/media-track/preview/preview.svml +5 -5
  184. package/packages/media-track/src/author.ts +12 -6
  185. package/packages/media-track/src/component.ts +10 -16
  186. package/packages/media-track/src/fragment.ts +8 -7
  187. package/packages/media-track/src/index.ts +3 -1
  188. package/packages/media-track/src/lower.ts +7 -7
  189. package/packages/media-track/src/manifest.ts +16 -38
  190. package/packages/media-track/src/program.ts +62 -67
  191. package/packages/media-track/src/sampling.ts +6 -6
  192. package/packages/media-track/src/sequence.ts +8 -8
  193. package/packages/media-track/src/surface.ts +25 -43
  194. package/packages/media-track-studio/README.md +9 -0
  195. package/packages/media-track-studio/src/index.ts +16 -11
  196. package/packages/mimo-speech/README.md +1 -1
  197. package/packages/minimax-h3/README.md +1 -1
  198. package/packages/nano-banana/README.md +1 -1
  199. package/packages/narrative/README.md +23 -1
  200. package/packages/narrative/src/identity.ts +11 -0
  201. package/packages/narrative/src/index.ts +3 -0
  202. package/packages/narrative/src/schema.ts +28 -27
  203. package/packages/narrative/src/selection.ts +52 -0
  204. package/packages/narrative/src/types.ts +2 -0
  205. package/packages/package-loader-node/README.md +30 -0
  206. package/packages/package-loader-node/package.json +5 -2
  207. package/packages/package-loader-node/src/distribution-resolution.ts +10 -3
  208. package/packages/package-loader-node/src/index.ts +1 -0
  209. package/packages/package-loader-node/src/loader.ts +12 -15
  210. package/packages/package-loader-node/src/location.ts +27 -1
  211. package/packages/package-loader-node/src/module-scope.ts +183 -0
  212. package/packages/package-loader-node/src/types.ts +4 -0
  213. package/packages/performance/README.md +83 -0
  214. package/packages/performance/package.json +30 -0
  215. package/packages/performance/src/activation.ts +11 -0
  216. package/packages/performance/src/component.ts +46 -0
  217. package/packages/performance/src/index.ts +6 -0
  218. package/packages/performance/src/manifest.ts +53 -0
  219. package/packages/{media-track/src/performance.ts → performance/src/media.ts} +9 -10
  220. package/packages/performance/src/program.ts +51 -0
  221. package/packages/performance/src/style.ts +35 -0
  222. package/packages/performance/src/surface.ts +99 -0
  223. package/packages/performance-studio/README.md +25 -0
  224. package/packages/performance-studio/package.json +21 -0
  225. package/packages/performance-studio/src/activation.ts +6 -0
  226. package/packages/performance-studio/src/index.ts +84 -0
  227. package/packages/program-space/README.md +9 -18
  228. package/packages/program-space/src/activation.ts +1 -5
  229. package/packages/program-space/src/index.ts +2 -11
  230. package/packages/program-space/src/surface.ts +1 -20
  231. package/packages/project-context-node/README.md +20 -0
  232. package/packages/project-context-node/package.json +10 -0
  233. package/packages/project-context-node/src/index.ts +3 -0
  234. package/packages/{cli → project-context-node}/src/runtime-selection.ts +7 -2
  235. package/packages/provider-hyperframes-local/README.md +43 -15
  236. package/packages/provider-hyperframes-local/src/activation.ts +4 -3
  237. package/packages/provider-hyperframes-local/src/capture-process.ts +26 -4
  238. package/packages/provider-hyperframes-local/src/capture.ts +96 -26
  239. package/packages/provider-hyperframes-local/src/concurrency.ts +86 -0
  240. package/packages/provider-hyperframes-local/src/opaque-capture.ts +92 -0
  241. package/packages/provider-hyperframes-local/src/options.ts +2 -0
  242. package/packages/provider-hyperframes-local/src/program.ts +6 -3
  243. package/packages/provider-hyperframes-local/src/progress.ts +53 -0
  244. package/packages/provider-hyperframes-local/src/provider.ts +18 -5
  245. package/packages/provider-hyperframes-local/src/render.ts +48 -7
  246. package/packages/provider-hypihub/README.md +48 -17
  247. package/packages/provider-hypihub/package.json +2 -0
  248. package/packages/provider-hypihub/src/mapping.ts +31 -7
  249. package/packages/provider-hypihub/src/oauth.ts +6 -0
  250. package/packages/provider-hypihub/src/provider.ts +25 -13
  251. package/packages/provider-hypihub/src/routes.ts +1 -2
  252. package/packages/provider-hypihub/src/upload.ts +2 -0
  253. package/packages/provider-media-local/README.md +3 -4
  254. package/packages/provider-whisperx-local/src/program.ts +1 -0
  255. package/packages/provider-whisperx-local/src/provider.ts +3 -0
  256. package/packages/ranking/README.md +8 -6
  257. package/packages/ranking/package.json +1 -1
  258. package/packages/ranking/src/component.ts +6 -6
  259. package/packages/ranking/src/fragment.ts +11 -7
  260. package/packages/ranking/src/manifest.ts +21 -14
  261. package/packages/ranking/src/render.ts +22 -26
  262. package/packages/ranking/src/schedule.ts +16 -19
  263. package/packages/ranking/src/surface.ts +12 -13
  264. package/packages/ranking-studio/README.md +18 -0
  265. package/packages/ranking-studio/src/index.ts +61 -9
  266. package/packages/render-hyperframes/README.md +7 -7
  267. package/packages/render-hyperframes/package.json +1 -1
  268. package/packages/render-hyperframes/src/component.ts +11 -1
  269. package/packages/render-hyperframes/src/fragment.ts +7 -4
  270. package/packages/render-hyperframes/src/manifest.ts +4 -4
  271. package/packages/render-hyperframes/src/surface.ts +6 -6
  272. package/packages/runtime/README.md +8 -1
  273. package/packages/runtime/src/execution.ts +15 -4
  274. package/packages/runtime/src/index.ts +2 -1
  275. package/packages/runtime/src/log.ts +51 -0
  276. package/packages/runtime/src/types.ts +5 -8
  277. package/packages/runtime-host-node/README.md +30 -0
  278. package/packages/runtime-host-node/package.json +1 -0
  279. package/packages/runtime-host-node/src/index.ts +24 -9
  280. package/packages/runtime-host-node/src/packages.ts +47 -50
  281. package/packages/runtime-kit/README.md +5 -0
  282. package/packages/runtime-kit/src/index.ts +3 -1
  283. package/packages/runtime-local/README.md +109 -4
  284. package/packages/runtime-local/src/config.ts +202 -56
  285. package/packages/runtime-local/src/control.ts +9 -1
  286. package/packages/runtime-local/src/executor.ts +66 -0
  287. package/packages/runtime-local/src/host.ts +37 -17
  288. package/packages/runtime-local/src/log.ts +48 -0
  289. package/packages/runtime-local/src/programs.ts +2 -1
  290. package/packages/runtime-local/src/result-writer.ts +2 -0
  291. package/packages/runtime-local/src/runtime.ts +8 -6
  292. package/packages/runtime-local/src/supervisor.ts +142 -0
  293. package/packages/runtime-local/src/types.ts +9 -2
  294. package/packages/runtime-local/src/worker-process.ts +7 -24
  295. package/packages/runtime-local/src/worker.ts +55 -83
  296. package/packages/screen-overlay/README.md +3 -3
  297. package/packages/screen-overlay/package.json +1 -1
  298. package/packages/screen-overlay/src/component.ts +3 -3
  299. package/packages/screen-overlay/src/fragment.ts +5 -4
  300. package/packages/screen-overlay/src/manifest.ts +7 -6
  301. package/packages/screen-overlay/src/program.ts +9 -9
  302. package/packages/screen-overlay/src/surface.ts +6 -7
  303. package/packages/script/README.md +30 -5
  304. package/packages/script/src/manifest.ts +4 -3
  305. package/packages/script/src/narrative.ts +1 -0
  306. package/packages/script/src/parser.ts +45 -6
  307. package/packages/script/src/surface.ts +4 -3
  308. package/packages/script/src/types.ts +1 -1
  309. package/packages/script-studio/package.json +9 -3
  310. package/packages/script-studio/src/index.ts +2 -0
  311. package/packages/script-studio/src/projection.ts +105 -0
  312. package/packages/seedance/README.md +30 -1
  313. package/packages/seedance/src/index.ts +18 -7
  314. package/packages/seedance/src/surface.ts +17 -4
  315. package/packages/seedance-kits/README.md +7 -1
  316. package/packages/seedream/README.md +1 -1
  317. package/packages/sound/README.md +81 -0
  318. package/packages/sound/package.json +25 -0
  319. package/packages/sound/src/activation.ts +11 -0
  320. package/packages/sound/src/component.ts +28 -0
  321. package/packages/sound/src/index.ts +5 -0
  322. package/packages/sound/src/manifest.ts +47 -0
  323. package/packages/sound/src/program.ts +84 -0
  324. package/packages/sound/src/style.ts +34 -0
  325. package/packages/sound/src/surface.ts +90 -0
  326. package/packages/sound-studio/README.md +22 -0
  327. package/packages/sound-studio/package.json +20 -0
  328. package/packages/sound-studio/src/activation.ts +6 -0
  329. package/packages/sound-studio/src/index.ts +74 -0
  330. package/packages/speech/README.md +2 -2
  331. package/packages/speech-alignment/src/local.ts +8 -0
  332. package/packages/speech-alignment/src/locate.ts +1 -1
  333. package/packages/store-sqlite/README.md +7 -0
  334. package/packages/store-sqlite/src/store.ts +84 -83
  335. package/packages/studio/INSPECTOR.md +15 -2
  336. package/packages/studio/LOCALIZATION.md +98 -0
  337. package/packages/studio/README.md +101 -14
  338. package/packages/studio/locales/en.json +197 -0
  339. package/packages/studio/locales/zh-CN.json +191 -0
  340. package/packages/studio/package.json +8 -7
  341. package/packages/studio/src/companion-assembly.ts +1 -0
  342. package/packages/studio/src/domain.ts +1 -1
  343. package/packages/studio/src/fallback-companions.ts +3 -3
  344. package/packages/studio/src/feedback-server.ts +51 -0
  345. package/packages/studio/src/feedback-store.ts +66 -0
  346. package/packages/studio/src/feedback.ts +60 -0
  347. package/packages/studio/src/localization-node.ts +46 -0
  348. package/packages/studio/src/localization.ts +85 -0
  349. package/packages/studio/src/parameter-values.ts +43 -1
  350. package/packages/studio/src/parameters.ts +114 -24
  351. package/packages/studio/src/preview/render.ts +5 -1
  352. package/packages/studio/src/preview/runtime-shim.ts +49 -3
  353. package/packages/studio/src/programme.ts +14 -30
  354. package/packages/studio/src/server.ts +10 -6
  355. package/packages/studio/src/shared.ts +4 -2
  356. package/packages/studio/src/snapshot.ts +21 -132
  357. package/packages/studio/src/studio-preflight.ts +3 -3
  358. package/packages/studio/src/studio-registry.ts +50 -6
  359. package/packages/studio/src/style.css +223 -50
  360. package/packages/studio/src/ui/artifact-name.ts +8 -6
  361. package/packages/studio/src/ui/artifact-preview.ts +5 -4
  362. package/packages/studio/src/ui/code.ts +17 -16
  363. package/packages/studio/src/ui/comments.ts +234 -0
  364. package/packages/studio/src/ui/dropdown.ts +68 -0
  365. package/packages/studio/src/ui/i18n.ts +109 -0
  366. package/packages/studio/src/ui/icons.ts +6 -0
  367. package/packages/studio/src/ui/library.ts +76 -65
  368. package/packages/studio/src/ui/main.ts +223 -211
  369. package/packages/studio/src/ui/overlay.ts +12 -8
  370. package/packages/studio/src/ui/scrub-preview.ts +110 -0
  371. package/packages/studio/src/ui/stage.ts +93 -29
  372. package/packages/studio/src/ui/timeline.ts +190 -118
  373. package/packages/studio/start.ts +41 -22
  374. package/packages/studio-adapter/README.md +130 -11
  375. package/packages/studio-adapter/src/index.ts +100 -13
  376. package/packages/temporal/README.md +6 -6
  377. package/packages/temporal/package.json +1 -1
  378. package/packages/temporal/src/component.ts +5 -6
  379. package/packages/temporal/src/index.ts +8 -6
  380. package/packages/temporal/src/location.ts +11 -11
  381. package/packages/temporal/src/projection.ts +19 -19
  382. package/packages/temporal/src/rational.ts +4 -4
  383. package/packages/temporal-markup/EDITING.md +2 -2
  384. package/packages/temporal-markup/README.md +27 -11
  385. package/packages/temporal-markup/package.json +1 -1
  386. package/packages/temporal-markup/src/index.ts +20 -25
  387. package/packages/temporal-markup/src/space.ts +10 -41
  388. package/packages/timeline/README.md +31 -0
  389. package/packages/{semantic-track → timeline}/package.json +1 -1
  390. package/packages/timeline/src/activation.ts +8 -0
  391. package/packages/timeline/src/component.ts +24 -0
  392. package/packages/timeline/src/identity.ts +60 -0
  393. package/packages/timeline/src/index.ts +6 -0
  394. package/packages/{semantic-track → timeline}/src/location.ts +20 -20
  395. package/packages/timeline/src/manifest.ts +39 -0
  396. package/packages/{semantic-track → timeline}/src/projection.ts +14 -14
  397. package/packages/timeline/src/types.ts +24 -0
  398. package/packages/timeline-author/README.md +68 -0
  399. package/packages/{speech-track → timeline-author}/package.json +6 -4
  400. package/packages/timeline-author/src/activation.ts +22 -0
  401. package/packages/{speech-track → timeline-author}/src/component.ts +15 -13
  402. package/packages/{speech-track → timeline-author}/src/fragment.ts +14 -23
  403. package/packages/timeline-author/src/index.ts +7 -0
  404. package/packages/timeline-author/src/manifest.ts +78 -0
  405. package/packages/timeline-author/src/program.ts +107 -0
  406. package/packages/timeline-author/src/surface.ts +46 -0
  407. package/packages/timeline-author/src/types.ts +6 -0
  408. package/packages/typography-track/README.md +4 -4
  409. package/packages/typography-track/package.json +1 -1
  410. package/packages/typography-track/src/component.ts +4 -4
  411. package/packages/typography-track/src/fragment.ts +4 -3
  412. package/packages/typography-track/src/manifest.ts +11 -9
  413. package/packages/typography-track/src/program.ts +15 -15
  414. package/packages/typography-track/src/surface.ts +17 -18
  415. package/packages/video-cli/README.md +4 -1
  416. package/packages/video-cli/package.json +2 -1
  417. package/packages/video-cli/src/creation.ts +14 -4
  418. package/packages/video-cli/src/index.ts +1 -1
  419. package/packages/video-cli/src/studio-distribution.ts +2 -1
  420. package/packages/volcengine-matting/README.md +3 -3
  421. package/packages/whisperx/README.md +1 -1
  422. package/services/whisperx/README.md +14 -0
  423. package/services/whisperx/pyproject.toml +2 -0
  424. package/services/whisperx/uv.lock +20 -20
  425. package/packages/provider-hyperframes-aws-lambda/README.md +0 -30
  426. package/packages/provider-hyperframes-aws-lambda/package.json +0 -30
  427. package/packages/provider-hyperframes-aws-lambda/src/activation.ts +0 -97
  428. package/packages/provider-hyperframes-aws-lambda/src/client.ts +0 -114
  429. package/packages/provider-hyperframes-aws-lambda/src/index.ts +0 -21
  430. package/packages/provider-hyperframes-aws-lambda/src/provider.ts +0 -522
  431. package/packages/provider-kie/README.md +0 -134
  432. package/packages/provider-kie/package.json +0 -43
  433. package/packages/provider-kie/src/activation.ts +0 -71
  434. package/packages/provider-kie/src/index.ts +0 -10
  435. package/packages/provider-kie/src/mapping.ts +0 -182
  436. package/packages/provider-kie/src/provider.ts +0 -657
  437. package/packages/provider-kie/src/routes.ts +0 -150
  438. package/packages/provider-xiaomi-mimo/README.md +0 -32
  439. package/packages/provider-xiaomi-mimo/src/activation.ts +0 -57
  440. package/packages/provider-xiaomi-mimo/src/index.ts +0 -5
  441. package/packages/provider-xiaomi-mimo/src/provider.ts +0 -214
  442. package/packages/runtime/src/environment.ts +0 -6
  443. package/packages/semantic-track/README.md +0 -21
  444. package/packages/semantic-track/src/activation.ts +0 -8
  445. package/packages/semantic-track/src/component.ts +0 -24
  446. package/packages/semantic-track/src/identity.ts +0 -58
  447. package/packages/semantic-track/src/index.ts +0 -6
  448. package/packages/semantic-track/src/manifest.ts +0 -38
  449. package/packages/semantic-track/src/types.ts +0 -26
  450. package/packages/speech-track/README.md +0 -51
  451. package/packages/speech-track/src/activation.ts +0 -19
  452. package/packages/speech-track/src/index.ts +0 -7
  453. package/packages/speech-track/src/manifest.ts +0 -73
  454. package/packages/speech-track/src/program.ts +0 -64
  455. package/packages/speech-track/src/surface.ts +0 -35
  456. package/packages/speech-track/src/types.ts +0 -6
  457. package/packages/speech-track-studio/README.md +0 -3
  458. package/packages/speech-track-studio/package.json +0 -14
  459. package/packages/speech-track-studio/src/activation.ts +0 -7
  460. package/packages/speech-track-studio/src/index.ts +0 -40
  461. /package/packages/{cli → project-context-node}/src/project-context.ts +0 -0
  462. /package/packages/{speech-track → timeline-author}/preview/Track.png +0 -0
@@ -0,0 +1,234 @@
1
+ import { t, uiLabel, uiAttribute, uiText, uiAttr, type Message } from "./i18n.js";
2
+ import { feedbackClock } from "../feedback.js";
3
+ import type { FeedbackComment, FeedbackMutation, FeedbackView } from "../feedback.js";
4
+ import { icon } from "./icons.js";
5
+ import type { Store } from "./selection.js";
6
+ import type { Stage } from "./stage.js";
7
+
8
+ type Anchor = Pick<FeedbackComment, "at">;
9
+
10
+ export function createComments(store: Store, stage: Stage) {
11
+ const element = document.createElement("aside");
12
+ element.className = "comments-panel";
13
+ element.innerHTML = `
14
+ <div class="pane-heading comments-heading">
15
+ <div class="pane-title">${icon("comments")}<h2>${uiLabel("app.comments")}</h2><span data-count></span></div>
16
+ <button type="button" class="comments-icon" data-refresh ${uiAttribute("aria-label", "comments.refresh-comments")} ${uiAttribute("title", "comments.refresh-comments")}>${icon("refresh")}</button>
17
+ </div>
18
+ <div class="comments-filters" role="group" ${uiAttribute("aria-label", "comments.filter-comments")}>
19
+ <button type="button" data-filter="all" aria-pressed="true">${uiLabel("comments.all")}</button>
20
+ <button type="button" data-filter="open" aria-pressed="false">${uiLabel("comments.open")}</button>
21
+ <button type="button" data-filter="done" aria-pressed="false">${uiLabel("comments.done")}</button>
22
+ </div>
23
+ <div class="comments-error" role="status" aria-live="polite" hidden></div>
24
+ <div class="comments-list" ${uiAttribute("aria-label", "app.comments")}></div>
25
+ <form class="comment-composer">
26
+ <div class="comment-anchor">
27
+ <button type="button" class="comment-time" data-current-time ${uiAttribute("title", "comments.use-current-frame")} ${uiAttribute("aria-label", "comments.use-current-frame")}>${icon("when")}<span>00:00.00</span></button>
28
+ </div>
29
+ <div class="comment-input">
30
+ <textarea rows="3" ${uiAttribute("aria-label", "comments.write-a-comment")} ${uiAttribute("placeholder", "comments.placeholder")} spellcheck="true" enterkeyhint="send"></textarea>
31
+ <div class="comment-input-actions">
32
+ <div class="comment-tools">
33
+ <button type="button" class="comments-icon" ${uiAttribute("aria-label", "comments.emoji-soon")} ${uiAttribute("title", "comments.emoji-soon")} disabled>${icon("smile")}</button>
34
+ <button type="button" class="comments-icon" ${uiAttribute("aria-label", "comments.draw-soon")} ${uiAttribute("title", "comments.draw-soon")} disabled>${icon("edit")}</button>
35
+ </div>
36
+ <button class="comment-submit" type="submit" ${uiAttribute("aria-label", "comments.send-comment")} ${uiAttribute("title", "comments.send-shortcut")} disabled>${icon("send")}</button>
37
+ </div>
38
+ </div>
39
+ </form>`;
40
+ const list = element.querySelector<HTMLElement>(".comments-list")!;
41
+ const form = element.querySelector<HTMLFormElement>("form")!;
42
+ const input = form.querySelector<HTMLTextAreaElement>("textarea")!;
43
+ const submit = form.querySelector<HTMLButtonElement>(".comment-submit")!;
44
+ const counter = element.querySelector<HTMLElement>("[data-count]")!;
45
+ const timeLabel = form.querySelector<HTMLElement>("[data-current-time] span")!;
46
+ const errorView = element.querySelector<HTMLElement>(".comments-error")!;
47
+ let view: FeedbackView | undefined;
48
+ let filter = "all";
49
+ let selected: string | undefined;
50
+ let anchor: Anchor | undefined;
51
+ let busy = false;
52
+ let active = false;
53
+ let fetchId = 0;
54
+ let editing: { id: string; before: FeedbackComment; text: string } | undefined;
55
+
56
+ const showError = (error?: unknown): void => {
57
+ errorView.hidden = error === undefined;
58
+ errorView.textContent = error === undefined ? "" : error instanceof Error ? error.message : String(error);
59
+ };
60
+ const currentAnchor = (): Anchor | undefined => {
61
+ const state = store.current();
62
+ if (state === undefined) return undefined;
63
+ return {
64
+ at: state.playhead.frame * state.snapshot.space.frameRate.denominator / state.snapshot.space.frameRate.numerator,
65
+ };
66
+ };
67
+ const renderAnchor = (): void => {
68
+ timeLabel.textContent = feedbackClock(anchor?.at ?? 0);
69
+ submit.disabled = busy || view === undefined || anchor === undefined || input.value.trim().length === 0;
70
+ };
71
+ const capture = (): void => { stage.pause(); anchor = currentAnchor(); renderAnchor(); };
72
+ const button = (name: string, label: Message, action: () => void): HTMLButtonElement => {
73
+ const node = document.createElement("button");
74
+ node.type = "button"; node.className = "comments-icon";
75
+ node.innerHTML = icon(name); uiAttr(node, "title", label); uiAttr(node, "aria-label", label);
76
+ node.disabled = busy;
77
+ node.addEventListener("click", (event) => { event.stopPropagation(); action(); });
78
+ return node;
79
+ };
80
+ const locate = (comment: FeedbackComment): void => {
81
+ stage.pause(); stage.showComposition();
82
+ const state = store.current();
83
+ if (state === undefined) return;
84
+ const frame = Math.round(comment.at * state.snapshot.space.frameRate.numerator / state.snapshot.space.frameRate.denominator);
85
+ store.seek(frame, "video");
86
+ selected = comment.id;
87
+ render();
88
+ };
89
+ const render = (): void => {
90
+ const focusedEdit = list.querySelector<HTMLTextAreaElement>(".comment-edit textarea");
91
+ const cursor = focusedEdit === document.activeElement && focusedEdit !== null
92
+ ? { start: focusedEdit.selectionStart, end: focusedEdit.selectionEnd } : undefined;
93
+ counter.textContent = view === undefined ? "" : String(view.comments.length);
94
+ // Notes are appended to the file in submission order. Number that order;
95
+ // time sorting and filters only change where a note is displayed.
96
+ const comments = [...view?.comments ?? []]
97
+ .map((comment, index) => ({ comment, number: index + 1 }))
98
+ .sort((a, b) => a.comment.at - b.comment.at)
99
+ .filter(({ comment }) => filter === "all" || (filter === "done") === (comment.resolved === true));
100
+ list.replaceChildren();
101
+ if (comments.length === 0) {
102
+ const empty = document.createElement("div");
103
+ empty.className = "comments-empty";
104
+ empty.innerHTML = `${icon(filter === "done" ? "check" : "comments")}<strong></strong><p></p>`;
105
+ uiText(empty.querySelector("strong")!, view === undefined ? "comments.loading-comments" : filter === "done" ? "comments.no-completed-comments" : filter === "open" ? "comments.caught-up" : "comments.empty");
106
+ uiText(empty.querySelector("p")!, filter === "all" ? "comments.empty-hint" : "comments.filter-hint");
107
+ list.append(empty);
108
+ }
109
+ for (const { comment, number } of comments) {
110
+ const row = document.createElement("article");
111
+ row.className = `comment-card${comment.resolved ? " resolved" : ""}${comment.id === selected ? " selected" : ""}`;
112
+ row.dataset.commentId = comment.id;
113
+ const head = document.createElement("div"); head.className = "comment-card-head";
114
+ const location = document.createElement("button"); location.type = "button"; location.className = "comment-location";
115
+ const label = document.createElement("span"); label.className = "comment-number"; label.textContent = `#${number}`;
116
+ const time = document.createElement("span"); time.className = "comment-time"; time.textContent = feedbackClock(comment.at);
117
+ location.append(time);
118
+ uiAttr(location, "title", "comments.go-to-this-frame"); location.addEventListener("click", () => locate(comment));
119
+ row.addEventListener("click", (event) => {
120
+ if ((event.target as Element).closest("button, form") !== null || window.getSelection()?.isCollapsed === false) return;
121
+ locate(comment);
122
+ });
123
+ const actions = document.createElement("div"); actions.className = "comment-actions";
124
+ const resolve = button("check", comment.resolved ? "comments.reopen-comment" : "comments.mark-complete", () => {
125
+ void mutate({ type: "replace", before: comment, comment: { ...comment, resolved: !comment.resolved } });
126
+ });
127
+ resolve.classList.toggle("is-done", comment.resolved === true);
128
+ resolve.setAttribute("aria-pressed", String(comment.resolved === true));
129
+ actions.append(label, resolve, button("edit", "comments.edit-comment", () => {
130
+ editing = { id: comment.id, before: comment, text: comment.text }; selected = comment.id; render();
131
+ list.querySelector<HTMLTextAreaElement>(".comment-edit textarea")?.focus();
132
+ }), button("trash", "comments.delete-comment", () => { void mutate({ type: "delete", before: comment }); }));
133
+ head.append(location, actions); row.append(head);
134
+ if (editing?.id === comment.id) {
135
+ const edit = document.createElement("form"); edit.className = "comment-edit";
136
+ const text = document.createElement("textarea"); text.rows = 3; text.value = editing.text;
137
+ uiAttr(text, "aria-label", "comments.edit-comment-text");
138
+ text.addEventListener("input", () => { if (editing !== undefined) editing.text = text.value; });
139
+ const controls = document.createElement("div"); controls.className = "comment-edit-actions";
140
+ const cancel = document.createElement("button"); cancel.type = "button"; uiText(cancel, "common.cancel");
141
+ cancel.addEventListener("click", () => { editing = undefined; render(); });
142
+ const save = document.createElement("button"); save.type = "submit"; uiText(save, "common.save"); save.disabled = busy;
143
+ controls.append(cancel, save); edit.append(text, controls);
144
+ edit.addEventListener("submit", (event) => {
145
+ event.preventDefault();
146
+ if (editing === undefined || text.value.trim().length === 0) return;
147
+ void mutate({ type: "replace", before: editing.before, comment: { ...editing.before, text: text.value.trim() } }, () => { editing = undefined; });
148
+ }); row.append(edit);
149
+ } else {
150
+ const text = document.createElement("p"); text.className = "comment-text"; text.textContent = comment.text;
151
+ row.append(text);
152
+ }
153
+ list.append(row);
154
+ }
155
+ if (cursor !== undefined) {
156
+ const next = list.querySelector<HTMLTextAreaElement>(".comment-edit textarea");
157
+ next?.focus({ preventScroll: true }); next?.setSelectionRange(cursor.start, cursor.end);
158
+ }
159
+ };
160
+ const refresh = async (): Promise<void> => {
161
+ const request = ++fetchId;
162
+ try {
163
+ const response = await fetch("/__studio/feedback");
164
+ const data = await response.json() as FeedbackView & { error?: string };
165
+ if (!response.ok) throw new Error(data.error ?? t("comments.read-failed"));
166
+ if (request !== fetchId) return;
167
+ if (JSON.stringify(view) !== JSON.stringify(data)) { view = data; render(); }
168
+ showError(); renderAnchor();
169
+ } catch (error) { if (request === fetchId) showError(error); }
170
+ };
171
+ const mutate = async (mutation: FeedbackMutation, saved?: () => void): Promise<void> => {
172
+ if (busy) return;
173
+ busy = true; showError(); renderAnchor();
174
+ try {
175
+ const response = await fetch("/__studio/feedback", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(mutation) });
176
+ const data = await response.json() as FeedbackView & { error?: string };
177
+ if (!response.ok) throw new Error(data.error ?? t("comments.save-failed"));
178
+ ++fetchId; view = data; busy = false; saved?.();
179
+ if (mutation.type === "delete" && selected === mutation.before.id) selected = undefined;
180
+ if (mutation.type === "delete" && editing?.id === mutation.before.id) editing = undefined;
181
+ render();
182
+ } catch (error) { showError(error); }
183
+ finally { busy = false; renderAnchor(); }
184
+ };
185
+ form.addEventListener("submit", (event) => {
186
+ event.preventDefault();
187
+ if (view === undefined || anchor === undefined || input.value.trim().length === 0) return;
188
+ const comment: FeedbackComment = { id: `c-${crypto.randomUUID()}`, run: view.run, ...anchor, text: input.value.trim() };
189
+ void mutate({ type: "add", comment }, () => {
190
+ input.value = ""; input.style.height = ""; selected = comment.id; anchor = currentAnchor();
191
+ });
192
+ });
193
+ input.addEventListener("focus", () => { if (input.value.length === 0) capture(); else stage.pause(); });
194
+ input.addEventListener("input", () => {
195
+ input.style.height = "auto"; input.style.height = `${Math.min(180, input.scrollHeight)}px`; renderAnchor();
196
+ });
197
+ element.addEventListener("keydown", (event) => {
198
+ if (!(event.target instanceof HTMLTextAreaElement) || event.key !== "Enter") return;
199
+ // Some IMEs report the confirming Enter as keyCode 229 after compositionend.
200
+ if (event.isComposing || event.keyCode === 229 || event.shiftKey || event.altKey) return;
201
+ event.preventDefault();
202
+ event.stopPropagation();
203
+ if (!event.repeat) event.target.form?.requestSubmit();
204
+ });
205
+ document.addEventListener("pointerdown", (event) => {
206
+ if (!active || selected === undefined) return;
207
+ const row = event.target instanceof Element ? event.target.closest(".comment-card") : null;
208
+ if (row?.getAttribute("data-comment-id") === selected) return;
209
+ selected = undefined;
210
+ // Keep the clicked control and any unsaved editor mounted through pointerup.
211
+ list.querySelector(".comment-card.selected")?.classList.remove("selected");
212
+ });
213
+ form.querySelector("[data-current-time]")!.addEventListener("click", capture);
214
+ element.querySelector("[data-refresh]")!.addEventListener("click", () => { void refresh(); });
215
+ element.querySelectorAll<HTMLButtonElement>("[data-filter]").forEach((button) => button.addEventListener("click", () => {
216
+ filter = button.dataset.filter!;
217
+ element.querySelectorAll<HTMLButtonElement>("[data-filter]").forEach((item) => item.setAttribute("aria-pressed", String(item === button)));
218
+ render();
219
+ }));
220
+ store.subscribe(() => {
221
+ if (input.value.length === 0) { anchor = currentAnchor(); renderAnchor(); }
222
+ });
223
+ type Hot = { on(event: string, listener: () => void): void };
224
+ (import.meta as ImportMeta & { hot?: Hot }).hot?.on("studio:feedback-changed", () => { if (active) void refresh(); });
225
+ render();
226
+ return {
227
+ element,
228
+ activate(value: boolean) {
229
+ active = value;
230
+ stage.setReviewMode(value);
231
+ if (active) { stage.showComposition(); anchor ??= currentAnchor(); renderAnchor(); void refresh(); }
232
+ },
233
+ };
234
+ }
@@ -0,0 +1,68 @@
1
+ /** Shared listbox interaction for Studio controls. Callers own the options and values. */
2
+ export function bindDropdown(control: HTMLElement, trigger: HTMLButtonElement, menu: HTMLElement, options: readonly HTMLButtonElement[]) {
3
+ const close = (restoreFocus = false): void => {
4
+ control.classList.remove("open", "open-up");
5
+ trigger.setAttribute("aria-expanded", "false");
6
+ menu.hidden = true;
7
+ if (restoreFocus) trigger.focus();
8
+ };
9
+ const open = (focus: "selected" | "first" | "last" = "selected"): void => {
10
+ control.classList.add("open");
11
+ trigger.setAttribute("aria-expanded", "true");
12
+ menu.hidden = false;
13
+ control.classList.remove("open-up");
14
+ const scroll = control.closest<HTMLElement>(".workspace-scroll");
15
+ if (scroll !== null) {
16
+ const menuBox = menu.getBoundingClientRect();
17
+ const scrollBox = scroll.getBoundingClientRect();
18
+ if (menuBox.bottom > scrollBox.bottom && trigger.getBoundingClientRect().top - menuBox.height >= scrollBox.top) {
19
+ control.classList.add("open-up");
20
+ }
21
+ }
22
+ const target = focus === "first" ? options[0]
23
+ : focus === "last" ? options.at(-1)
24
+ : options.find((option) => option.classList.contains("active")) ?? options[0];
25
+ target?.focus();
26
+ };
27
+ const moveOptionFocus = (offset: number): void => {
28
+ const current = options.indexOf(document.activeElement as HTMLButtonElement);
29
+ const next = current < 0 ? 0 : (current + offset + options.length) % options.length;
30
+ options[next]?.focus();
31
+ };
32
+
33
+ trigger.addEventListener("click", () => {
34
+ if (control.classList.contains("open")) close(false);
35
+ else open();
36
+ });
37
+ trigger.addEventListener("keydown", (event) => {
38
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
39
+ event.preventDefault();
40
+ event.stopPropagation();
41
+ open(event.key === "ArrowDown" ? "first" : "last");
42
+ } else if (event.key === "Escape" && control.classList.contains("open")) {
43
+ event.preventDefault();
44
+ event.stopPropagation();
45
+ close(false);
46
+ }
47
+ });
48
+ menu.addEventListener("keydown", (event) => {
49
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
50
+ event.preventDefault();
51
+ event.stopPropagation();
52
+ moveOptionFocus(event.key === "ArrowDown" ? 1 : -1);
53
+ } else if (event.key === "Home" || event.key === "End") {
54
+ event.preventDefault();
55
+ event.stopPropagation();
56
+ options[event.key === "Home" ? 0 : options.length - 1]?.focus();
57
+ } else if (event.key === "Escape") {
58
+ event.preventDefault();
59
+ event.stopPropagation();
60
+ close(true);
61
+ }
62
+ });
63
+ control.addEventListener("focusout", (event) => {
64
+ if (event.relatedTarget instanceof Node && control.contains(event.relatedTarget)) return;
65
+ close(false);
66
+ });
67
+ return { close };
68
+ }
@@ -0,0 +1,109 @@
1
+ import { builtinLanguages, chooseLanguage, formatMessage, readLanguagePack } from "../localization.js";
2
+ import type { LanguagePack, Message, MessageValues } from "../localization.js";
3
+ import { bindDropdown } from "./dropdown.js";
4
+ import { icon } from "./icons.js";
5
+ export type { Message } from "../localization.js";
6
+
7
+ type Attribute = "title" | "aria-label" | "placeholder" | "alt";
8
+ const attributes: readonly Attribute[] = ["title", "aria-label", "placeholder", "alt"];
9
+ const storageKey = "hypit-studio.language";
10
+ let languages = builtinLanguages;
11
+ let language = chooseLanguage(languages, navigator.languages);
12
+
13
+ export async function initializeI18n(): Promise<void> {
14
+ const response = await fetch("/__studio/locales");
15
+ if (!response.ok) throw new Error(`Could not load Studio languages (${response.status}).`);
16
+ languages = (await response.json() as unknown[]).map(readLanguagePack);
17
+ let saved: string | null = null;
18
+ try { saved = localStorage.getItem(storageKey); } catch { /* Browser storage may be disabled. */ }
19
+ language = chooseLanguage(languages, [...(saved ? [saved] : []), ...navigator.languages]);
20
+ document.documentElement.lang = language.locale;
21
+ }
22
+
23
+ export function t(message: Message, values: MessageValues = {}): string {
24
+ return formatMessage(language, message, values);
25
+ }
26
+ function escape(value: string): string {
27
+ return value.replace(/[&<>"']/gu, char => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[char]!);
28
+ }
29
+ export function uiLabel(message: Message): string {
30
+ return `<span data-ui-text="${message}" dir="${language.direction}">${escape(t(message))}</span>`;
31
+ }
32
+ export function uiAttribute(attribute: Attribute, message: Message): string {
33
+ return `${attribute}="${escape(t(message))}" data-ui-${attribute}="${message}"`;
34
+ }
35
+ export function uiText(node: Element, message: Message, values: MessageValues = {}): void {
36
+ node.setAttribute("data-ui-text", message);
37
+ node.setAttribute("data-ui-values", JSON.stringify(values));
38
+ node.setAttribute("dir", language.direction);
39
+ node.textContent = t(message, values);
40
+ }
41
+ /** Use when a node changes from UI text into a user-provided name or an empty value. */
42
+ export function userText(node: Element, value: string): void {
43
+ node.removeAttribute("data-ui-text");
44
+ node.removeAttribute("data-ui-values");
45
+ node.setAttribute("dir", "auto");
46
+ node.textContent = value;
47
+ }
48
+ export function uiAttr(node: Element, attribute: Attribute, message: Message, values: MessageValues = {}): void {
49
+ node.setAttribute(`data-ui-${attribute}`, message);
50
+ node.setAttribute(`data-ui-${attribute}-values`, JSON.stringify(values));
51
+ node.setAttribute(attribute, t(message, values));
52
+ }
53
+ export function uiDate(node: Element, timestamp: number): void {
54
+ node.setAttribute("data-ui-date", String(timestamp));
55
+ node.textContent = new Intl.DateTimeFormat(language.locale, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }).format(timestamp);
56
+ }
57
+
58
+ function selectLanguage(pack: LanguagePack): void {
59
+ language = pack;
60
+ try { localStorage.setItem(storageKey, pack.locale); } catch { /* Tab-local choice still applies. */ }
61
+ document.documentElement.lang = pack.locale;
62
+ // Update explicitly marked chrome in place, without rebuilding editors or the player.
63
+ for (const node of Array.from(document.querySelectorAll("[data-ui-text]"))) {
64
+ uiText(node, node.getAttribute("data-ui-text") as Message, JSON.parse(node.getAttribute("data-ui-values") ?? "{}") as MessageValues);
65
+ }
66
+ for (const attribute of attributes) {
67
+ for (const node of Array.from(document.querySelectorAll(`[data-ui-${attribute}]`))) {
68
+ uiAttr(node, attribute, node.getAttribute(`data-ui-${attribute}`) as Message, JSON.parse(node.getAttribute(`data-ui-${attribute}-values`) ?? "{}") as MessageValues);
69
+ }
70
+ }
71
+ for (const node of Array.from(document.querySelectorAll("[data-ui-date]"))) uiDate(node, Number(node.getAttribute("data-ui-date")));
72
+ }
73
+
74
+ export function languageMenu(): HTMLElement {
75
+ const control = document.createElement("div");
76
+ control.className = "parameter-select language-select";
77
+ const trigger = document.createElement("button");
78
+ trigger.type = "button"; trigger.className = "parameter-select-trigger language-toggle";
79
+ trigger.dataset.language = "";
80
+ trigger.innerHTML = icon("globe");
81
+ uiAttr(trigger, "title", "app.language"); uiAttr(trigger, "aria-label", "app.language");
82
+ trigger.setAttribute("aria-haspopup", "listbox"); trigger.setAttribute("aria-expanded", "false");
83
+ const menu = document.createElement("div");
84
+ menu.className = "parameter-select-menu"; menu.id = "studio-languages"; menu.hidden = true;
85
+ menu.setAttribute("role", "listbox"); uiAttr(menu, "aria-label", "app.language");
86
+ trigger.setAttribute("aria-controls", menu.id);
87
+ const options = languages.map(pack => {
88
+ const item = document.createElement("button");
89
+ item.type = "button"; item.className = "parameter-select-option";
90
+ item.lang = pack.locale; item.dir = pack.direction;
91
+ item.textContent = pack.name;
92
+ item.dataset.locale = pack.locale;
93
+ item.setAttribute("role", "option");
94
+ item.addEventListener("click", () => {
95
+ selectLanguage(pack); renderSelection(); close(true);
96
+ });
97
+ return item;
98
+ });
99
+ const renderSelection = (): void => {
100
+ for (const item of options) {
101
+ const selected = item.dataset.locale === language.locale;
102
+ item.classList.toggle("active", selected); item.setAttribute("aria-selected", String(selected));
103
+ }
104
+ };
105
+ menu.append(...options); control.append(trigger, menu);
106
+ const { close } = bindDropdown(control, trigger, menu, options);
107
+ renderSelection();
108
+ return control;
109
+ }
@@ -1,7 +1,13 @@
1
1
  const paths: Readonly<Record<string, string>> = {
2
2
  brand: '<g transform="translate(0 1.282) scale(.091603) translate(-50 -180)"><path fill="currentColor" stroke="none" d="M303.78,277.82c-5.98-8.63-15.83-13.77-26.32-13.77h-93.41c-12.28,0-24.92,7.44-29.6,18.8l-28.26,75.82c-4.6,11.25-4.54,24.05,2.22,34.16,6.79,10.15,19.36,16.15,31.57,16.15h85.98c14.12,0,26.9-8.88,31.84-22.1l29.69-79.57c3.67-9.84,2.29-20.86-3.69-29.48v-.02h-.02ZM252.02,377.25c-.94,2.52-3.39,4.22-6.08,4.22h-83.45c-4.34,0-6.68-2.8-7.49-3.99s-2.5-4.43-.84-8.44l23.85-66.24c2.29-6.35,8.08-10.87,14.82-11.22.33-.02.67-.02,1.02-.02h75.41s12.51,1.42,9.29,14.61l-26.53,71.09h0ZM106.85,361.73s-22.36-11.59-17.66-32.66l29.67-82.23c4.78-13.25,17.36-22.09,31.45-22.09h95.02c6.25,0,12.1,3.03,15.71,8.14l13.89,19.68h-112.97c-8.7,0-16.49,5.41-19.52,13.57l-35.59,95.6h0ZM73.3,323.27s-22.37-11.59-17.66-32.66l29.67-82.23c4.79-13.25,17.37-22.09,31.45-22.09h89.91c6.25,0,12.1,3.03,15.71,8.14l13.89,19.68h-107.84c-8.7,0-16.49,5.41-19.52,13.57l-35.59,95.6h-.02Z"/></g>',
3
+ globe: '<circle cx="12" cy="12" r="9"/><ellipse cx="12" cy="12" rx="4" ry="9"/><path d="M3 12h18"/>',
3
4
  code: '<path d="M9 7 4 12l5 5M15 7l5 5-5 5M13 4l-2 16"/>',
4
5
  edit: '<path d="m4 16-.8 4 4-.8L18.5 8.9 15.1 5.5 4 16Z"/><path d="m13.8 6.8 3.4 3.4"/>',
6
+ studio: '<rect x="3" y="4" width="18" height="16" rx="1.5"/><path d="M3 14h18M8 4v10M15 14v6"/>',
7
+ comments: '<path d="M6 17H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-8l-5 4v-4Z"/><path d="M7 8h10M7 12h7"/>',
8
+ trash: '<path d="M3 6h18M9 6V3h6v3M6 6l1 15h10l1-15M10 10v7M14 10v7"/>',
9
+ send: '<path d="M12 20V4m-6 6 6-6 6 6"/>',
10
+ smile: '<circle cx="12" cy="12" r="9"/><path d="M8 14a4.5 4.5 0 0 0 8 0M8.5 9h.01M15.5 9h.01"/>',
5
11
  eye: '<path d="M2.5 12s3.5-6 9.5-6 9.5 6 9.5 6-3.5 6-9.5 6-9.5-6-9.5-6Z"/><circle cx="12" cy="12" r="2.5"/>',
6
12
  preview: '<rect x="3" y="4" width="18" height="14" rx="2"/><path d="m10 8 5 3.5-5 3.5V8ZM8 21h8"/>',
7
13
  tune: '<path d="M4 7h10M18 7h2M4 17h2M10 17h10"/><circle cx="16" cy="7" r="2"/><circle cx="8" cy="17" r="2"/>',