@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.
- package/README.md +4 -2
- package/dist/public/caption.d.ts +206 -183
- package/dist/public/composition.d.ts +25 -3
- package/dist/public/endpoint-kit.d.ts +24 -2
- package/dist/public/generation.d.ts +5 -1
- package/dist/public/hyperframes.d.ts +19 -1
- package/dist/public/narrative.d.ts +17 -3
- package/dist/public/performance.d.ts +1590 -0
- package/dist/public/program-space.d.ts +179 -32
- package/dist/public/runtime-kit.d.ts +21 -8
- package/dist/public/sound.d.ts +822 -0
- package/dist/public/speech.d.ts +41 -0
- package/dist/public/studio-adapter.d.ts +77 -15
- package/dist/public/temporal-markup.d.ts +9 -44
- package/dist/public/temporal.d.ts +37 -28
- package/dist/public/{semantic-track.d.ts → timeline.d.ts} +62 -49
- package/examples/README.md +18 -10
- package/examples/minimal-author-package/packages/example-component/preview/preview.svml +19 -12
- package/examples/minimal-author-package/packages/example-component/src/component.ts +5 -5
- package/examples/minimal-author-package/packages/example-component/src/fragment.ts +3 -5
- package/examples/minimal-author-package/packages/example-component/src/manifest.ts +8 -10
- package/examples/minimal-author-package/packages/example-component/src/surface.ts +2 -2
- package/examples/provider-package/README.md +78 -0
- package/examples/provider-package/hypit.runtime.json +12 -0
- package/examples/provider-package/packages/provider-images/package.json +11 -0
- package/examples/provider-package/packages/provider-images/src/activation.ts +24 -0
- package/examples/provider-package/packages/provider-images/src/provider.ts +122 -0
- package/examples/provider-package/packages/provider-images/tsconfig.json +9 -0
- package/examples/semantic-composition/README.md +8 -1
- package/examples/semantic-composition/chat.svml +6 -5
- package/examples/semantic-composition/hypit.runtime.json +1 -1
- package/examples/semantic-composition/packages/chat-scene/README.md +3 -3
- package/examples/semantic-composition/packages/chat-scene/src/activation.ts +18 -21
- package/examples/semantic-composition/packages/chat-scene/src/render.ts +4 -4
- package/examples/semantic-composition/packages/performance-styles/README.md +42 -0
- package/examples/semantic-composition/packages/performance-styles/package.json +25 -0
- package/examples/semantic-composition/packages/performance-styles/src/activation.ts +57 -0
- package/examples/semantic-composition/packages/performance-styles/src/render.ts +54 -0
- package/examples/semantic-composition/packages/performance-styles/src/studio.ts +28 -0
- package/examples/semantic-composition/packages/performance-styles/tsconfig.json +18 -0
- package/examples/semantic-composition/packages/responsive-explainer/README.md +16 -9
- package/examples/semantic-composition/packages/responsive-explainer/src/activation.ts +12 -12
- package/examples/semantic-composition/packages/responsive-explainer/src/render.ts +5 -5
- package/examples/semantic-composition/packages/sound-styles/README.md +36 -0
- package/examples/semantic-composition/packages/sound-styles/package.json +25 -0
- package/examples/semantic-composition/packages/sound-styles/src/activation.ts +53 -0
- package/examples/semantic-composition/packages/sound-styles/src/render.ts +14 -0
- package/examples/semantic-composition/packages/sound-styles/tsconfig.json +18 -0
- package/package.json +35 -15
- package/packages/audio-track/README.md +20 -13
- package/packages/audio-track/package.json +1 -1
- package/packages/audio-track/src/component.ts +4 -4
- package/packages/audio-track/src/fragment.ts +6 -5
- package/packages/audio-track/src/index.ts +1 -1
- package/packages/audio-track/src/manifest.ts +17 -16
- package/packages/audio-track/src/program.ts +21 -25
- package/packages/audio-track/src/surface.ts +19 -18
- package/packages/audio-track-studio/README.md +23 -0
- package/packages/audio-track-studio/src/index.ts +28 -17
- package/packages/author-kit/README.md +1 -1
- package/packages/background-removal/README.md +4 -7
- package/packages/browser-capture/package.json +1 -1
- package/packages/build-result/README.md +11 -0
- package/packages/build-result/src/decode.ts +2 -0
- package/packages/build-result/src/execution-log.ts +17 -0
- package/packages/build-result/src/index.ts +1 -0
- package/packages/build-result/src/store.ts +14 -1
- package/packages/build-result/src/types.ts +3 -0
- package/packages/build-result-s3/src/repository.ts +4 -0
- package/packages/caption/README.md +61 -73
- package/packages/caption/package.json +3 -2
- package/packages/caption/src/activation.ts +2 -2
- package/packages/caption/src/component.ts +20 -5
- package/packages/caption/src/display.ts +3 -18
- package/packages/caption/src/fragment.ts +3 -7
- package/packages/caption/src/index.ts +6 -5
- package/packages/caption/src/manifest.ts +29 -46
- package/packages/caption/src/style.ts +24 -135
- package/packages/caption/src/surface.ts +12 -92
- package/packages/caption/src/temporalize.ts +18 -53
- package/packages/caption/src/types.ts +8 -35
- package/packages/caption/src/visibility.ts +23 -0
- package/packages/caption-fine/README.md +21 -9
- package/packages/caption-fine/package.json +4 -2
- package/packages/caption-fine/src/component.ts +3 -3
- package/packages/caption-fine/src/fragment.ts +7 -19
- package/packages/caption-fine/src/index.ts +2 -0
- package/packages/caption-fine/src/manifest.ts +26 -17
- package/packages/caption-fine/src/recipe.ts +7 -0
- package/packages/caption-fine/src/render.ts +14 -13
- package/packages/caption-fine/src/schedule.ts +39 -35
- package/packages/caption-fine/src/style.ts +10 -9
- package/packages/caption-fine/src/surface.ts +62 -35
- package/packages/caption-fine/src/types.ts +2 -0
- package/packages/caption-fine-studio/README.md +24 -2
- package/packages/caption-fine-studio/package.json +3 -1
- package/packages/caption-fine-studio/src/activation.ts +3 -3
- package/packages/caption-fine-studio/src/index.ts +54 -42
- package/packages/cli/README.md +57 -4
- package/packages/cli/package.json +1 -0
- package/packages/cli/src/arguments.ts +25 -6
- package/packages/cli/src/build-planning.ts +3 -2
- package/packages/cli/src/command.ts +6 -0
- package/packages/cli/src/commands/environment.ts +28 -18
- package/packages/cli/src/commands/execution.ts +81 -26
- package/packages/cli/src/commands/results.ts +7 -11
- package/packages/cli/src/index.ts +2 -2
- package/packages/cli/src/machine-view.ts +3 -2
- package/packages/cli/src/main.ts +34 -42
- package/packages/cli/src/observation.ts +7 -1
- package/packages/cli/src/output.ts +65 -23
- package/packages/cli/src/view.ts +66 -19
- package/packages/comment-sticker/README.md +3 -3
- package/packages/comment-sticker/package.json +1 -1
- package/packages/comment-sticker/src/component.ts +4 -4
- package/packages/comment-sticker/src/fragment.ts +5 -4
- package/packages/comment-sticker/src/manifest.ts +7 -6
- package/packages/comment-sticker/src/program.ts +9 -9
- package/packages/comment-sticker/src/surface.ts +6 -7
- package/packages/composition/README.md +21 -0
- package/packages/composition/src/audio-presentation.ts +44 -0
- package/packages/composition/src/index.ts +3 -0
- package/packages/composition/src/schema.ts +8 -3
- package/packages/composition/src/track.ts +15 -1
- package/packages/credential-store-env/README.md +1 -1
- package/packages/deck-track/README.md +3 -3
- package/packages/deck-track/package.json +1 -1
- package/packages/deck-track/src/component.ts +5 -5
- package/packages/deck-track/src/fragment.ts +6 -5
- package/packages/deck-track/src/lower.ts +12 -12
- package/packages/deck-track/src/manifest.ts +8 -7
- package/packages/deck-track/src/program.ts +13 -16
- package/packages/deck-track/src/surface.ts +9 -10
- package/packages/driver-node/src/driver.ts +41 -3
- package/packages/elevenlabs-speech/README.md +27 -0
- package/packages/{provider-xiaomi-mimo → elevenlabs-speech}/package.json +5 -8
- package/packages/elevenlabs-speech/src/activation.ts +26 -0
- package/packages/elevenlabs-speech/src/fragment.ts +11 -0
- package/packages/elevenlabs-speech/src/index.ts +111 -0
- package/packages/elevenlabs-speech/src/surface.ts +167 -0
- package/packages/endpoint-kit/README.md +24 -0
- package/packages/endpoint-kit/src/index.ts +7 -1
- package/packages/film/README.md +12 -7
- package/packages/film/package.json +1 -1
- package/packages/film/src/component.ts +4 -4
- package/packages/film/src/fragment.ts +6 -5
- package/packages/film/src/manifest.ts +11 -10
- package/packages/film/src/program.ts +5 -5
- package/packages/film/src/recipe.ts +2 -1
- package/packages/film/src/surface.ts +10 -7
- package/packages/film-studio/package.json +1 -1
- package/packages/film-studio/src/index.ts +2 -2
- package/packages/fishaudio-speech/README.md +33 -0
- package/packages/fishaudio-speech/package.json +21 -0
- package/packages/fishaudio-speech/src/activation.ts +32 -0
- package/packages/fishaudio-speech/src/fragment.ts +11 -0
- package/packages/fishaudio-speech/src/index.ts +156 -0
- package/packages/fishaudio-speech/src/surface.ts +192 -0
- package/packages/generation/README.md +11 -1
- package/packages/generation/src/mapping.ts +28 -30
- package/packages/gpt-image/README.md +1 -2
- package/packages/grok-imagine/README.md +1 -2
- package/packages/hyperframes/README.md +7 -3
- package/packages/hyperframes/src/browser-program.ts +11 -2
- package/packages/hyperframes/src/document.ts +15 -2
- package/packages/interview-emoji-reveal/README.md +4 -4
- package/packages/interview-emoji-reveal/package.json +1 -1
- package/packages/interview-emoji-reveal/src/component.ts +4 -4
- package/packages/interview-emoji-reveal/src/fragment.ts +6 -5
- package/packages/interview-emoji-reveal/src/manifest.ts +9 -8
- package/packages/interview-emoji-reveal/src/program.ts +14 -14
- package/packages/interview-emoji-reveal/src/surface.ts +8 -9
- package/packages/media-execution/README.md +7 -3
- package/packages/media-execution/src/audio-presentation.ts +23 -0
- package/packages/media-execution/src/execute.ts +2 -0
- package/packages/media-pipeline/README.md +7 -3
- package/packages/media-pipeline/src/audio-plan.ts +4 -1
- package/packages/media-pipeline/src/component.ts +16 -2
- package/packages/media-pipeline/src/manifest.ts +3 -1
- package/packages/media-pipeline/src/types.ts +2 -1
- package/packages/media-track/README.md +14 -47
- package/packages/media-track/package.json +1 -1
- package/packages/media-track/preview/preview.svml +5 -5
- package/packages/media-track/src/author.ts +12 -6
- package/packages/media-track/src/component.ts +10 -16
- package/packages/media-track/src/fragment.ts +8 -7
- package/packages/media-track/src/index.ts +3 -1
- package/packages/media-track/src/lower.ts +7 -7
- package/packages/media-track/src/manifest.ts +16 -38
- package/packages/media-track/src/program.ts +62 -67
- package/packages/media-track/src/sampling.ts +6 -6
- package/packages/media-track/src/sequence.ts +8 -8
- package/packages/media-track/src/surface.ts +25 -43
- package/packages/media-track-studio/README.md +9 -0
- package/packages/media-track-studio/src/index.ts +16 -11
- package/packages/mimo-speech/README.md +1 -1
- package/packages/minimax-h3/README.md +1 -1
- package/packages/nano-banana/README.md +1 -1
- package/packages/narrative/README.md +23 -1
- package/packages/narrative/src/identity.ts +11 -0
- package/packages/narrative/src/index.ts +3 -0
- package/packages/narrative/src/schema.ts +28 -27
- package/packages/narrative/src/selection.ts +52 -0
- package/packages/narrative/src/types.ts +2 -0
- package/packages/package-loader-node/README.md +30 -0
- package/packages/package-loader-node/package.json +5 -2
- package/packages/package-loader-node/src/distribution-resolution.ts +10 -3
- package/packages/package-loader-node/src/index.ts +1 -0
- package/packages/package-loader-node/src/loader.ts +12 -15
- package/packages/package-loader-node/src/location.ts +27 -1
- package/packages/package-loader-node/src/module-scope.ts +183 -0
- package/packages/package-loader-node/src/types.ts +4 -0
- package/packages/performance/README.md +83 -0
- package/packages/performance/package.json +30 -0
- package/packages/performance/src/activation.ts +11 -0
- package/packages/performance/src/component.ts +46 -0
- package/packages/performance/src/index.ts +6 -0
- package/packages/performance/src/manifest.ts +53 -0
- package/packages/{media-track/src/performance.ts → performance/src/media.ts} +9 -10
- package/packages/performance/src/program.ts +51 -0
- package/packages/performance/src/style.ts +35 -0
- package/packages/performance/src/surface.ts +99 -0
- package/packages/performance-studio/README.md +25 -0
- package/packages/performance-studio/package.json +21 -0
- package/packages/performance-studio/src/activation.ts +6 -0
- package/packages/performance-studio/src/index.ts +84 -0
- package/packages/program-space/README.md +9 -18
- package/packages/program-space/src/activation.ts +1 -5
- package/packages/program-space/src/index.ts +2 -11
- package/packages/program-space/src/surface.ts +1 -20
- package/packages/project-context-node/README.md +20 -0
- package/packages/project-context-node/package.json +10 -0
- package/packages/project-context-node/src/index.ts +3 -0
- package/packages/{cli → project-context-node}/src/runtime-selection.ts +7 -2
- package/packages/provider-hyperframes-local/README.md +43 -15
- package/packages/provider-hyperframes-local/src/activation.ts +4 -3
- package/packages/provider-hyperframes-local/src/capture-process.ts +26 -4
- package/packages/provider-hyperframes-local/src/capture.ts +96 -26
- package/packages/provider-hyperframes-local/src/concurrency.ts +86 -0
- package/packages/provider-hyperframes-local/src/opaque-capture.ts +92 -0
- package/packages/provider-hyperframes-local/src/options.ts +2 -0
- package/packages/provider-hyperframes-local/src/program.ts +6 -3
- package/packages/provider-hyperframes-local/src/progress.ts +53 -0
- package/packages/provider-hyperframes-local/src/provider.ts +18 -5
- package/packages/provider-hyperframes-local/src/render.ts +48 -7
- package/packages/provider-hypihub/README.md +48 -17
- package/packages/provider-hypihub/package.json +2 -0
- package/packages/provider-hypihub/src/mapping.ts +31 -7
- package/packages/provider-hypihub/src/oauth.ts +6 -0
- package/packages/provider-hypihub/src/provider.ts +25 -13
- package/packages/provider-hypihub/src/routes.ts +1 -2
- package/packages/provider-hypihub/src/upload.ts +2 -0
- package/packages/provider-media-local/README.md +3 -4
- package/packages/provider-whisperx-local/src/program.ts +1 -0
- package/packages/provider-whisperx-local/src/provider.ts +3 -0
- package/packages/ranking/README.md +8 -6
- package/packages/ranking/package.json +1 -1
- package/packages/ranking/src/component.ts +6 -6
- package/packages/ranking/src/fragment.ts +11 -7
- package/packages/ranking/src/manifest.ts +21 -14
- package/packages/ranking/src/render.ts +22 -26
- package/packages/ranking/src/schedule.ts +16 -19
- package/packages/ranking/src/surface.ts +12 -13
- package/packages/ranking-studio/README.md +18 -0
- package/packages/ranking-studio/src/index.ts +61 -9
- package/packages/render-hyperframes/README.md +7 -7
- package/packages/render-hyperframes/package.json +1 -1
- package/packages/render-hyperframes/src/component.ts +11 -1
- package/packages/render-hyperframes/src/fragment.ts +7 -4
- package/packages/render-hyperframes/src/manifest.ts +4 -4
- package/packages/render-hyperframes/src/surface.ts +6 -6
- package/packages/runtime/README.md +8 -1
- package/packages/runtime/src/execution.ts +15 -4
- package/packages/runtime/src/index.ts +2 -1
- package/packages/runtime/src/log.ts +51 -0
- package/packages/runtime/src/types.ts +5 -8
- package/packages/runtime-host-node/README.md +30 -0
- package/packages/runtime-host-node/package.json +1 -0
- package/packages/runtime-host-node/src/index.ts +24 -9
- package/packages/runtime-host-node/src/packages.ts +47 -50
- package/packages/runtime-kit/README.md +5 -0
- package/packages/runtime-kit/src/index.ts +3 -1
- package/packages/runtime-local/README.md +109 -4
- package/packages/runtime-local/src/config.ts +202 -56
- package/packages/runtime-local/src/control.ts +9 -1
- package/packages/runtime-local/src/executor.ts +66 -0
- package/packages/runtime-local/src/host.ts +37 -17
- package/packages/runtime-local/src/log.ts +48 -0
- package/packages/runtime-local/src/programs.ts +2 -1
- package/packages/runtime-local/src/result-writer.ts +2 -0
- package/packages/runtime-local/src/runtime.ts +8 -6
- package/packages/runtime-local/src/supervisor.ts +142 -0
- package/packages/runtime-local/src/types.ts +9 -2
- package/packages/runtime-local/src/worker-process.ts +7 -24
- package/packages/runtime-local/src/worker.ts +55 -83
- package/packages/screen-overlay/README.md +3 -3
- package/packages/screen-overlay/package.json +1 -1
- package/packages/screen-overlay/src/component.ts +3 -3
- package/packages/screen-overlay/src/fragment.ts +5 -4
- package/packages/screen-overlay/src/manifest.ts +7 -6
- package/packages/screen-overlay/src/program.ts +9 -9
- package/packages/screen-overlay/src/surface.ts +6 -7
- package/packages/script/README.md +30 -5
- package/packages/script/src/manifest.ts +4 -3
- package/packages/script/src/narrative.ts +1 -0
- package/packages/script/src/parser.ts +45 -6
- package/packages/script/src/surface.ts +4 -3
- package/packages/script/src/types.ts +1 -1
- package/packages/script-studio/package.json +9 -3
- package/packages/script-studio/src/index.ts +2 -0
- package/packages/script-studio/src/projection.ts +105 -0
- package/packages/seedance/README.md +30 -1
- package/packages/seedance/src/index.ts +18 -7
- package/packages/seedance/src/surface.ts +17 -4
- package/packages/seedance-kits/README.md +7 -1
- package/packages/seedream/README.md +1 -1
- package/packages/sound/README.md +81 -0
- package/packages/sound/package.json +25 -0
- package/packages/sound/src/activation.ts +11 -0
- package/packages/sound/src/component.ts +28 -0
- package/packages/sound/src/index.ts +5 -0
- package/packages/sound/src/manifest.ts +47 -0
- package/packages/sound/src/program.ts +84 -0
- package/packages/sound/src/style.ts +34 -0
- package/packages/sound/src/surface.ts +90 -0
- package/packages/sound-studio/README.md +22 -0
- package/packages/sound-studio/package.json +20 -0
- package/packages/sound-studio/src/activation.ts +6 -0
- package/packages/sound-studio/src/index.ts +74 -0
- package/packages/speech/README.md +2 -2
- package/packages/speech-alignment/src/local.ts +8 -0
- package/packages/speech-alignment/src/locate.ts +1 -1
- package/packages/store-sqlite/README.md +7 -0
- package/packages/store-sqlite/src/store.ts +84 -83
- package/packages/studio/INSPECTOR.md +15 -2
- package/packages/studio/LOCALIZATION.md +98 -0
- package/packages/studio/README.md +101 -14
- package/packages/studio/locales/en.json +197 -0
- package/packages/studio/locales/zh-CN.json +191 -0
- package/packages/studio/package.json +8 -7
- package/packages/studio/src/companion-assembly.ts +1 -0
- package/packages/studio/src/domain.ts +1 -1
- package/packages/studio/src/fallback-companions.ts +3 -3
- package/packages/studio/src/feedback-server.ts +51 -0
- package/packages/studio/src/feedback-store.ts +66 -0
- package/packages/studio/src/feedback.ts +60 -0
- package/packages/studio/src/localization-node.ts +46 -0
- package/packages/studio/src/localization.ts +85 -0
- package/packages/studio/src/parameter-values.ts +43 -1
- package/packages/studio/src/parameters.ts +114 -24
- package/packages/studio/src/preview/render.ts +5 -1
- package/packages/studio/src/preview/runtime-shim.ts +49 -3
- package/packages/studio/src/programme.ts +14 -30
- package/packages/studio/src/server.ts +10 -6
- package/packages/studio/src/shared.ts +4 -2
- package/packages/studio/src/snapshot.ts +21 -132
- package/packages/studio/src/studio-preflight.ts +3 -3
- package/packages/studio/src/studio-registry.ts +50 -6
- package/packages/studio/src/style.css +223 -50
- package/packages/studio/src/ui/artifact-name.ts +8 -6
- package/packages/studio/src/ui/artifact-preview.ts +5 -4
- package/packages/studio/src/ui/code.ts +17 -16
- package/packages/studio/src/ui/comments.ts +234 -0
- package/packages/studio/src/ui/dropdown.ts +68 -0
- package/packages/studio/src/ui/i18n.ts +109 -0
- package/packages/studio/src/ui/icons.ts +6 -0
- package/packages/studio/src/ui/library.ts +76 -65
- package/packages/studio/src/ui/main.ts +223 -211
- package/packages/studio/src/ui/overlay.ts +12 -8
- package/packages/studio/src/ui/scrub-preview.ts +110 -0
- package/packages/studio/src/ui/stage.ts +93 -29
- package/packages/studio/src/ui/timeline.ts +190 -118
- package/packages/studio/start.ts +41 -22
- package/packages/studio-adapter/README.md +130 -11
- package/packages/studio-adapter/src/index.ts +100 -13
- package/packages/temporal/README.md +6 -6
- package/packages/temporal/package.json +1 -1
- package/packages/temporal/src/component.ts +5 -6
- package/packages/temporal/src/index.ts +8 -6
- package/packages/temporal/src/location.ts +11 -11
- package/packages/temporal/src/projection.ts +19 -19
- package/packages/temporal/src/rational.ts +4 -4
- package/packages/temporal-markup/EDITING.md +2 -2
- package/packages/temporal-markup/README.md +27 -11
- package/packages/temporal-markup/package.json +1 -1
- package/packages/temporal-markup/src/index.ts +20 -25
- package/packages/temporal-markup/src/space.ts +10 -41
- package/packages/timeline/README.md +31 -0
- package/packages/{semantic-track → timeline}/package.json +1 -1
- package/packages/timeline/src/activation.ts +8 -0
- package/packages/timeline/src/component.ts +24 -0
- package/packages/timeline/src/identity.ts +60 -0
- package/packages/timeline/src/index.ts +6 -0
- package/packages/{semantic-track → timeline}/src/location.ts +20 -20
- package/packages/timeline/src/manifest.ts +39 -0
- package/packages/{semantic-track → timeline}/src/projection.ts +14 -14
- package/packages/timeline/src/types.ts +24 -0
- package/packages/timeline-author/README.md +68 -0
- package/packages/{speech-track → timeline-author}/package.json +6 -4
- package/packages/timeline-author/src/activation.ts +22 -0
- package/packages/{speech-track → timeline-author}/src/component.ts +15 -13
- package/packages/{speech-track → timeline-author}/src/fragment.ts +14 -23
- package/packages/timeline-author/src/index.ts +7 -0
- package/packages/timeline-author/src/manifest.ts +78 -0
- package/packages/timeline-author/src/program.ts +107 -0
- package/packages/timeline-author/src/surface.ts +46 -0
- package/packages/timeline-author/src/types.ts +6 -0
- package/packages/typography-track/README.md +4 -4
- package/packages/typography-track/package.json +1 -1
- package/packages/typography-track/src/component.ts +4 -4
- package/packages/typography-track/src/fragment.ts +4 -3
- package/packages/typography-track/src/manifest.ts +11 -9
- package/packages/typography-track/src/program.ts +15 -15
- package/packages/typography-track/src/surface.ts +17 -18
- package/packages/video-cli/README.md +4 -1
- package/packages/video-cli/package.json +2 -1
- package/packages/video-cli/src/creation.ts +14 -4
- package/packages/video-cli/src/index.ts +1 -1
- package/packages/video-cli/src/studio-distribution.ts +2 -1
- package/packages/volcengine-matting/README.md +3 -3
- package/packages/whisperx/README.md +1 -1
- package/services/whisperx/README.md +14 -0
- package/services/whisperx/pyproject.toml +2 -0
- package/services/whisperx/uv.lock +20 -20
- package/packages/provider-hyperframes-aws-lambda/README.md +0 -30
- package/packages/provider-hyperframes-aws-lambda/package.json +0 -30
- package/packages/provider-hyperframes-aws-lambda/src/activation.ts +0 -97
- package/packages/provider-hyperframes-aws-lambda/src/client.ts +0 -114
- package/packages/provider-hyperframes-aws-lambda/src/index.ts +0 -21
- package/packages/provider-hyperframes-aws-lambda/src/provider.ts +0 -522
- package/packages/provider-kie/README.md +0 -134
- package/packages/provider-kie/package.json +0 -43
- package/packages/provider-kie/src/activation.ts +0 -71
- package/packages/provider-kie/src/index.ts +0 -10
- package/packages/provider-kie/src/mapping.ts +0 -182
- package/packages/provider-kie/src/provider.ts +0 -657
- package/packages/provider-kie/src/routes.ts +0 -150
- package/packages/provider-xiaomi-mimo/README.md +0 -32
- package/packages/provider-xiaomi-mimo/src/activation.ts +0 -57
- package/packages/provider-xiaomi-mimo/src/index.ts +0 -5
- package/packages/provider-xiaomi-mimo/src/provider.ts +0 -214
- package/packages/runtime/src/environment.ts +0 -6
- package/packages/semantic-track/README.md +0 -21
- package/packages/semantic-track/src/activation.ts +0 -8
- package/packages/semantic-track/src/component.ts +0 -24
- package/packages/semantic-track/src/identity.ts +0 -58
- package/packages/semantic-track/src/index.ts +0 -6
- package/packages/semantic-track/src/manifest.ts +0 -38
- package/packages/semantic-track/src/types.ts +0 -26
- package/packages/speech-track/README.md +0 -51
- package/packages/speech-track/src/activation.ts +0 -19
- package/packages/speech-track/src/index.ts +0 -7
- package/packages/speech-track/src/manifest.ts +0 -73
- package/packages/speech-track/src/program.ts +0 -64
- package/packages/speech-track/src/surface.ts +0 -35
- package/packages/speech-track/src/types.ts +0 -6
- package/packages/speech-track-studio/README.md +0 -3
- package/packages/speech-track-studio/package.json +0 -14
- package/packages/speech-track-studio/src/activation.ts +0 -7
- package/packages/speech-track-studio/src/index.ts +0 -40
- /package/packages/{cli → project-context-node}/src/project-context.ts +0 -0
- /package/packages/{speech-track → timeline-author}/preview/Track.png +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { bindDropdown } from "./dropdown.js";
|
|
2
|
+
import { uiLabel, uiAttribute, uiText, uiAttr, userText, languageMenu, initializeI18n, type Message } from "./i18n.js";
|
|
1
3
|
import type { Clip, StudioFailure, StudioInspectorDomain, StudioSnapshot } from "../shared.js";
|
|
2
4
|
import type { CanonicalValue, ValueSchema } from "@hypit/protocol";
|
|
3
|
-
import { parameterAuthorValue, parameterNumber, parameterOption, validateParameterValue } from "../parameter-values.js";
|
|
5
|
+
import { parameterAuthorValue, parameterControlForSchema, parameterNumber, parameterOption, parameterRecordSchema, parameterRecordVariants, validateParameterValue } from "../parameter-values.js";
|
|
4
6
|
import { createCodePane } from "./code.js";
|
|
5
7
|
import { icon } from "./icons.js";
|
|
6
8
|
import { createLibraryPane } from "./library.js";
|
|
@@ -13,8 +15,11 @@ import { semanticGestureSpan } from "../temporal-edit.js";
|
|
|
13
15
|
import type { SemanticTarget } from "../temporal-edit.js";
|
|
14
16
|
import { applyStudioMutation } from "./writeback.js";
|
|
15
17
|
import { createTimeline } from "./timeline.js";
|
|
18
|
+
import { createComments } from "./comments.js";
|
|
16
19
|
import "../style.css";
|
|
17
20
|
|
|
21
|
+
await initializeI18n();
|
|
22
|
+
|
|
18
23
|
const app = document.querySelector<HTMLElement>("#app")!;
|
|
19
24
|
app.innerHTML = `
|
|
20
25
|
<header class="topbar">
|
|
@@ -39,6 +44,11 @@ app.innerHTML = `
|
|
|
39
44
|
<div class="topbar-right">
|
|
40
45
|
<div class="meta" data-meta></div>
|
|
41
46
|
<div class="status" data-status></div>
|
|
47
|
+
<div data-language-menu></div>
|
|
48
|
+
<div class="view-tabs" role="tablist" ${uiAttribute("aria-label", "app.studio-view")}>
|
|
49
|
+
<button type="button" role="tab" data-view="studio" aria-selected="true">${icon("studio")}${uiLabel("app.studio")}</button>
|
|
50
|
+
<button type="button" role="tab" data-view="comments" aria-selected="false">${icon("comments")}${uiLabel("app.comments")}</button>
|
|
51
|
+
</div>
|
|
42
52
|
</div>
|
|
43
53
|
</header>
|
|
44
54
|
<main class="studio-shell">
|
|
@@ -47,7 +57,7 @@ app.innerHTML = `
|
|
|
47
57
|
<div class="preview-panel" data-stage></div>
|
|
48
58
|
<aside class="workspace-panel">
|
|
49
59
|
<div class="pane-heading workspace-heading" data-workspace-heading>
|
|
50
|
-
<div class="pane-title">${icon("tune")}<h2
|
|
60
|
+
<div class="pane-title">${icon("tune")}<h2>${uiLabel("inspector.properties")}</h2></div>
|
|
51
61
|
</div>
|
|
52
62
|
<div class="workspace-scroll">
|
|
53
63
|
<section class="workspace-section">
|
|
@@ -60,11 +70,14 @@ app.innerHTML = `
|
|
|
60
70
|
</main>
|
|
61
71
|
<pre class="failure" data-failure></pre>`;
|
|
62
72
|
|
|
73
|
+
app.querySelector("[data-language-menu]")!.replaceWith(languageMenu());
|
|
74
|
+
|
|
63
75
|
const store = createStore();
|
|
64
76
|
const code = createCodePane();
|
|
65
77
|
const stage = createStage(store, (id) => library.selectArtifact(id));
|
|
66
78
|
const library = createLibraryPane(code, (artifact) => stage.openArtifact(artifact), (artifact) => stage.renameArtifact(artifact));
|
|
67
79
|
const timeline = createTimeline(store);
|
|
80
|
+
const comments = createComments(store, stage);
|
|
68
81
|
app.querySelector<HTMLElement>("[data-library]")!.append(library.element);
|
|
69
82
|
app.querySelector<HTMLElement>("[data-timeline]")!.append(timeline.element);
|
|
70
83
|
app.querySelector<HTMLElement>("[data-stage]")!.append(stage.element);
|
|
@@ -91,6 +104,14 @@ const workspaceHandle = createHandle({
|
|
|
91
104
|
});
|
|
92
105
|
workspaceHandle.classList.add("workspace-handle");
|
|
93
106
|
upperShell.insertBefore(workspaceHandle, workspacePanel);
|
|
107
|
+
const commentsHandle = createHandle({
|
|
108
|
+
axis: "column", initial: 360, minimum: 280, invert: true,
|
|
109
|
+
maximum: () => Math.max(280, upperShell.clientWidth - 360),
|
|
110
|
+
apply: (size) => { upperShell.style.setProperty("--comments-width", `${size}px`); },
|
|
111
|
+
remember: "hypit-studio.comments-width",
|
|
112
|
+
});
|
|
113
|
+
commentsHandle.classList.add("comments-handle");
|
|
114
|
+
upperShell.append(commentsHandle, comments.element);
|
|
94
115
|
shell.insertBefore(createHandle({
|
|
95
116
|
axis: "row", initial: Math.round(window.innerHeight * 0.45), minimum: 220, invert: true,
|
|
96
117
|
maximum: () => Math.max(260, shell.clientHeight - 260),
|
|
@@ -104,10 +125,33 @@ const project = app.querySelector<HTMLElement>("[data-project]")!;
|
|
|
104
125
|
const status = app.querySelector<HTMLElement>("[data-status]")!;
|
|
105
126
|
const failureView = app.querySelector<HTMLElement>("[data-failure]")!;
|
|
106
127
|
|
|
128
|
+
const changeView = (): void => {
|
|
129
|
+
const current = window.location.hash === "#comments" ? "comments" : "studio";
|
|
130
|
+
shell.dataset.view = current;
|
|
131
|
+
app.querySelectorAll<HTMLButtonElement>(".view-tabs [data-view]").forEach((button) => {
|
|
132
|
+
const selected = button.dataset.view === current;
|
|
133
|
+
button.setAttribute("aria-selected", String(selected)); button.tabIndex = selected ? 0 : -1;
|
|
134
|
+
});
|
|
135
|
+
comments.activate(current === "comments");
|
|
136
|
+
};
|
|
137
|
+
app.querySelectorAll<HTMLButtonElement>(".view-tabs [data-view]").forEach((button) => {
|
|
138
|
+
button.addEventListener("click", () => { window.location.hash = button.dataset.view!; });
|
|
139
|
+
button.addEventListener("keydown", (event) => {
|
|
140
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
event.stopPropagation();
|
|
143
|
+
const next = button.dataset.view === "studio" ? "comments" : "studio";
|
|
144
|
+
window.location.hash = next;
|
|
145
|
+
app.querySelector<HTMLButtonElement>(`.view-tabs [data-view="${next}"]`)!.focus();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
window.addEventListener("hashchange", changeView);
|
|
149
|
+
changeView();
|
|
150
|
+
|
|
107
151
|
timeline.element.addEventListener("studio:write", (event) => {
|
|
108
152
|
const state = (event as CustomEvent<{ readonly state?: string }>).detail.state;
|
|
109
153
|
status.className = state === "error" ? "status error" : state === "saved" ? "status saved" : "status saving";
|
|
110
|
-
status
|
|
154
|
+
uiText(status, state === "error" ? "common.save-failed" : state === "saved" ? "common.saved" : "common.saving");
|
|
111
155
|
});
|
|
112
156
|
|
|
113
157
|
// Program-level facts never change while a Source is being read, so they live in
|
|
@@ -117,14 +161,14 @@ function renderMeta(snapshot: StudioSnapshot): void {
|
|
|
117
161
|
project.title = snapshot.source.path;
|
|
118
162
|
// Sequence facts belong to the project/inspector, not the application chrome.
|
|
119
163
|
// The timeline transport is the single persistent time readout.
|
|
120
|
-
meta
|
|
164
|
+
userText(meta, "");
|
|
121
165
|
}
|
|
122
166
|
|
|
123
|
-
function property(label:
|
|
167
|
+
function property(label: Message, value: string, tone?: string): HTMLElement {
|
|
124
168
|
const node = document.createElement("div");
|
|
125
169
|
node.className = `property${tone === undefined ? "" : ` ${tone}`}`;
|
|
126
170
|
node.innerHTML = "<span></span><strong></strong>";
|
|
127
|
-
node.querySelector("span")
|
|
171
|
+
uiText(node.querySelector("span")!, label);
|
|
128
172
|
node.querySelector("strong")!.textContent = value;
|
|
129
173
|
node.querySelector("strong")!.title = value;
|
|
130
174
|
return node;
|
|
@@ -142,6 +186,12 @@ function group(label: string, items: readonly HTMLElement[], className = ""): HT
|
|
|
142
186
|
return node;
|
|
143
187
|
}
|
|
144
188
|
|
|
189
|
+
function uiGroup(label: Message, items: readonly HTMLElement[]): HTMLElement {
|
|
190
|
+
const node = group(label, items);
|
|
191
|
+
uiText(node.querySelector("h3")!, label);
|
|
192
|
+
return node;
|
|
193
|
+
}
|
|
194
|
+
|
|
145
195
|
function aspectRatio(width: number, height: number): string {
|
|
146
196
|
let a = width;
|
|
147
197
|
let b = height;
|
|
@@ -149,18 +199,18 @@ function aspectRatio(width: number, height: number): string {
|
|
|
149
199
|
return `${width / a}:${height / a}`;
|
|
150
200
|
}
|
|
151
201
|
|
|
152
|
-
const domainPresentation: Readonly<Record<StudioInspectorDomain, { readonly label:
|
|
153
|
-
where: { label: "
|
|
154
|
-
how: { label: "
|
|
155
|
-
when: { label: "
|
|
202
|
+
const domainPresentation: Readonly<Record<StudioInspectorDomain, { readonly label: Message; readonly icon: string }>> = {
|
|
203
|
+
where: { label: "inspector.where", icon: "where" },
|
|
204
|
+
how: { label: "inspector.how", icon: "how" },
|
|
205
|
+
when: { label: "inspector.when", icon: "when" },
|
|
156
206
|
};
|
|
157
|
-
const domainOrder: readonly StudioInspectorDomain[] = ["where", "
|
|
207
|
+
const domainOrder: readonly StudioInspectorDomain[] = ["where", "when", "how"];
|
|
158
208
|
const inspectorDomainByEntity = new Map<string, StudioInspectorDomain>();
|
|
159
209
|
const inspectorPageByEntity = new Map<string, string>();
|
|
160
210
|
|
|
161
211
|
function defaultWorkspaceHeading(): void {
|
|
162
212
|
workspaceHeading.className = "pane-heading workspace-heading";
|
|
163
|
-
workspaceHeading.innerHTML = `<div class="pane-title">${icon("tune")}<h2
|
|
213
|
+
workspaceHeading.innerHTML = `<div class="pane-title">${icon("tune")}<h2>${uiLabel("inspector.properties")}</h2></div>`;
|
|
164
214
|
}
|
|
165
215
|
|
|
166
216
|
function inspectorHeading(
|
|
@@ -176,7 +226,7 @@ function inspectorHeading(
|
|
|
176
226
|
button.type = "button";
|
|
177
227
|
button.className = `inspector-domain-tab${domain === active ? " active" : ""}`;
|
|
178
228
|
button.dataset.domain = domain;
|
|
179
|
-
button.innerHTML = `${icon(presentation.icon)}<strong>${presentation.label}</strong>`;
|
|
229
|
+
button.innerHTML = `${icon(presentation.icon)}<strong>${uiLabel(presentation.label)}</strong>`;
|
|
180
230
|
button.setAttribute("aria-pressed", String(domain === active));
|
|
181
231
|
button.addEventListener("click", () => {
|
|
182
232
|
inspectorDomainByEntity.set(entityId, domain);
|
|
@@ -207,7 +257,7 @@ function commitControl(entityId: string, parameter: Clip["inspector"][number], r
|
|
|
207
257
|
void writeParameter(entityId, parameter, replacement);
|
|
208
258
|
} catch (error) {
|
|
209
259
|
restoreParameterControls(entityId);
|
|
210
|
-
status
|
|
260
|
+
uiText(status, "common.invalid-value"); status.className = "status error";
|
|
211
261
|
status.title = error instanceof Error ? error.message : String(error);
|
|
212
262
|
}
|
|
213
263
|
}
|
|
@@ -230,8 +280,8 @@ document.addEventListener("keydown", (event) => {
|
|
|
230
280
|
}, true);
|
|
231
281
|
|
|
232
282
|
function selectControl(
|
|
233
|
-
entityId: string,
|
|
234
283
|
parameter: Clip["inspector"][number],
|
|
284
|
+
change: (value: CanonicalValue) => void,
|
|
235
285
|
): HTMLElement {
|
|
236
286
|
const control = document.createElement("div");
|
|
237
287
|
control.className = "parameter-select parameter-control";
|
|
@@ -286,76 +336,13 @@ function selectControl(
|
|
|
286
336
|
}
|
|
287
337
|
close(false);
|
|
288
338
|
trigger.focus();
|
|
289
|
-
|
|
339
|
+
change(option.value);
|
|
290
340
|
});
|
|
291
341
|
return item;
|
|
292
342
|
});
|
|
293
343
|
menu.append(...options);
|
|
294
344
|
|
|
295
|
-
const close = (
|
|
296
|
-
control.classList.remove("open", "open-up");
|
|
297
|
-
trigger.setAttribute("aria-expanded", "false");
|
|
298
|
-
menu.hidden = true;
|
|
299
|
-
if (restoreFocus) trigger.focus();
|
|
300
|
-
};
|
|
301
|
-
const open = (focus: "selected" | "first" | "last" = "selected"): void => {
|
|
302
|
-
control.classList.add("open");
|
|
303
|
-
trigger.setAttribute("aria-expanded", "true");
|
|
304
|
-
menu.hidden = false;
|
|
305
|
-
control.classList.remove("open-up");
|
|
306
|
-
const scroll = control.closest<HTMLElement>(".workspace-scroll");
|
|
307
|
-
if (scroll !== null) {
|
|
308
|
-
const menuBox = menu.getBoundingClientRect();
|
|
309
|
-
const scrollBox = scroll.getBoundingClientRect();
|
|
310
|
-
if (menuBox.bottom > scrollBox.bottom && trigger.getBoundingClientRect().top - menuBox.height >= scrollBox.top) {
|
|
311
|
-
control.classList.add("open-up");
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
const target = focus === "first" ? options[0]
|
|
315
|
-
: focus === "last" ? options.at(-1)
|
|
316
|
-
: options.find((option) => option.classList.contains("active")) ?? options[0];
|
|
317
|
-
target?.focus();
|
|
318
|
-
};
|
|
319
|
-
const moveOptionFocus = (offset: number): void => {
|
|
320
|
-
const current = options.indexOf(document.activeElement as HTMLButtonElement);
|
|
321
|
-
const next = current < 0 ? 0 : (current + offset + options.length) % options.length;
|
|
322
|
-
options[next]?.focus();
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
trigger.addEventListener("click", () => {
|
|
326
|
-
if (control.classList.contains("open")) close(false);
|
|
327
|
-
else open();
|
|
328
|
-
});
|
|
329
|
-
trigger.addEventListener("keydown", (event) => {
|
|
330
|
-
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
331
|
-
event.preventDefault();
|
|
332
|
-
event.stopPropagation();
|
|
333
|
-
open(event.key === "ArrowDown" ? "first" : "last");
|
|
334
|
-
} else if (event.key === "Escape" && control.classList.contains("open")) {
|
|
335
|
-
event.preventDefault();
|
|
336
|
-
event.stopPropagation();
|
|
337
|
-
close(false);
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
menu.addEventListener("keydown", (event) => {
|
|
341
|
-
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
342
|
-
event.preventDefault();
|
|
343
|
-
event.stopPropagation();
|
|
344
|
-
moveOptionFocus(event.key === "ArrowDown" ? 1 : -1);
|
|
345
|
-
} else if (event.key === "Home" || event.key === "End") {
|
|
346
|
-
event.preventDefault();
|
|
347
|
-
event.stopPropagation();
|
|
348
|
-
options[event.key === "Home" ? 0 : options.length - 1]?.focus();
|
|
349
|
-
} else if (event.key === "Escape") {
|
|
350
|
-
event.preventDefault();
|
|
351
|
-
event.stopPropagation();
|
|
352
|
-
close(true);
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
control.addEventListener("focusout", (event) => {
|
|
356
|
-
if (event.relatedTarget instanceof Node && control.contains(event.relatedTarget)) return;
|
|
357
|
-
close(false);
|
|
358
|
-
});
|
|
345
|
+
const { close } = bindDropdown(control, trigger, menu, options);
|
|
359
346
|
control.append(trigger, menu);
|
|
360
347
|
return control;
|
|
361
348
|
}
|
|
@@ -376,7 +363,7 @@ function colorValueControl(
|
|
|
376
363
|
const picker = document.createElement("input");
|
|
377
364
|
picker.type = "color";
|
|
378
365
|
picker.className = "parameter-color-native";
|
|
379
|
-
picker
|
|
366
|
+
uiAttr(picker, "aria-label", "inspector.color-picker", { label });
|
|
380
367
|
picker.title = label;
|
|
381
368
|
const exact = /^#[0-9a-f]{6}(?:[0-9a-f]{2})?$/iu.test(initial);
|
|
382
369
|
picker.value = exact ? initial.slice(0, 7) : "#000000";
|
|
@@ -437,7 +424,8 @@ function fieldLabel(name: string): string {
|
|
|
437
424
|
|
|
438
425
|
function blankValue(schema: ValueSchema): CanonicalValue {
|
|
439
426
|
if (schema.kind === "string") return "";
|
|
440
|
-
if (schema.kind === "
|
|
427
|
+
if (schema.kind === "literal") return schema.value;
|
|
428
|
+
if (schema.kind === "number" || schema.kind === "null" || schema.kind === "oneOf") return null;
|
|
441
429
|
if (schema.kind === "boolean") return false;
|
|
442
430
|
if (schema.kind === "array") return [];
|
|
443
431
|
if (schema.kind === "object") return Object.fromEntries(Object.entries(schema.fields)
|
|
@@ -452,31 +440,12 @@ function scalarDraftControl(
|
|
|
452
440
|
held: CanonicalValue | undefined,
|
|
453
441
|
change: (value: CanonicalValue) => void,
|
|
454
442
|
): HTMLElement {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
input.spellcheck = false;
|
|
462
|
-
if (schema.kind === "boolean") {
|
|
463
|
-
input.type = "checkbox";
|
|
464
|
-
input.checked = held === true;
|
|
465
|
-
input.addEventListener("change", () => change(input.checked));
|
|
466
|
-
return input;
|
|
467
|
-
}
|
|
468
|
-
input.type = "text";
|
|
469
|
-
if (schema.kind === "number") input.inputMode = "decimal";
|
|
470
|
-
input.value = held === undefined || held === null ? "" : textValue(held);
|
|
471
|
-
input.addEventListener("input", () => {
|
|
472
|
-
if (schema.kind === "number") {
|
|
473
|
-
const number = Number(input.value);
|
|
474
|
-
change(input.value.trim().length === 0 || !Number.isFinite(number) ? null : number);
|
|
475
|
-
} else {
|
|
476
|
-
change(input.value);
|
|
477
|
-
}
|
|
478
|
-
});
|
|
479
|
-
return input;
|
|
443
|
+
return parameterControl("", {
|
|
444
|
+
id: label, label, domain: "how", section: { id: "record", label: "" },
|
|
445
|
+
control: parameterControlForSchema(schema) ?? "text",
|
|
446
|
+
...(schema.kind === "string" && schema.enum !== undefined ? { options: schema.enum } : {}),
|
|
447
|
+
schema, value: held ?? null,
|
|
448
|
+
}, change);
|
|
480
449
|
}
|
|
481
450
|
|
|
482
451
|
function recordDraftControl(
|
|
@@ -490,30 +459,34 @@ function recordDraftControl(
|
|
|
490
459
|
const fields = document.createElement("div");
|
|
491
460
|
fields.className = "parameter-record-fields";
|
|
492
461
|
for (const [name, field] of Object.entries(schema.fields)) {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
const copy = document.createElement("span");
|
|
496
|
-
copy.textContent = fieldLabel(name);
|
|
497
|
-
row.append(copy, scalarDraftControl(fieldLabel(name), field.schema, record[name], (next) => {
|
|
462
|
+
if (field.schema.kind === "literal") continue;
|
|
463
|
+
fields.append(scalarDraftControl(fieldLabel(name), field.schema, record[name], (next) => {
|
|
498
464
|
record = { ...record, [name]: next };
|
|
499
465
|
change(record);
|
|
500
466
|
}));
|
|
501
|
-
fields.append(row);
|
|
502
467
|
}
|
|
503
468
|
return fields;
|
|
504
469
|
}
|
|
505
470
|
|
|
506
|
-
function structuredControl(entityId: string, parameter: Clip["inspector"][number]): HTMLElement {
|
|
507
|
-
const
|
|
471
|
+
function structuredControl(entityId: string, parameter: Clip["inspector"][number], change: (value: CanonicalValue) => void): HTMLElement {
|
|
472
|
+
const declaredSchema = parameter.schema;
|
|
508
473
|
const shell = document.createElement("div");
|
|
509
474
|
shell.className = "parameter-structured";
|
|
510
|
-
if (
|
|
475
|
+
if (declaredSchema === undefined || (declaredSchema.kind !== "array" && declaredSchema.kind !== "object" && !parameterRecordVariants(declaredSchema).length)) return shell;
|
|
511
476
|
let draft = structuredClone(parameter.value);
|
|
512
|
-
|
|
477
|
+
const notice = document.createElement("div");
|
|
478
|
+
notice.className = "parameter-structured-notice";
|
|
479
|
+
notice.setAttribute("role", "status");
|
|
480
|
+
const save = (): void => {
|
|
481
|
+
const changed = !sameValue(draft, parameter.value);
|
|
482
|
+
notice.hidden = !changed || valid();
|
|
483
|
+
uiText(notice, "inspector.invalid-fields");
|
|
484
|
+
if (changed && valid()) change(draft);
|
|
485
|
+
};
|
|
513
486
|
|
|
514
487
|
const valid = (): boolean => {
|
|
515
488
|
try {
|
|
516
|
-
validateParameterValue(draft,
|
|
489
|
+
validateParameterValue(draft, declaredSchema, parameter.label);
|
|
517
490
|
return true;
|
|
518
491
|
} catch {
|
|
519
492
|
return false;
|
|
@@ -522,14 +495,28 @@ function structuredControl(entityId: string, parameter: Clip["inspector"][number
|
|
|
522
495
|
|
|
523
496
|
const render = (): void => {
|
|
524
497
|
shell.replaceChildren();
|
|
498
|
+
const variants = parameterRecordVariants(declaredSchema);
|
|
499
|
+
const schema = declaredSchema.kind === "array" ? declaredSchema : parameterRecordSchema(declaredSchema, draft);
|
|
500
|
+
if (schema === undefined) return;
|
|
501
|
+
if (variants.length) {
|
|
502
|
+
const active = variants.find(variant => variant.schema === schema)!;
|
|
503
|
+
shell.append(parameterControl(entityId, {
|
|
504
|
+
...parameter, control: "select", value: variants.indexOf(active),
|
|
505
|
+
options: variants.map((variant, index) => ({ value: index, label: textValue(variant.value) })),
|
|
506
|
+
}, (next) => {
|
|
507
|
+
if (next === variants.indexOf(active)) return;
|
|
508
|
+
draft = blankValue(variants[Number(next)]!.schema);
|
|
509
|
+
render();
|
|
510
|
+
save();
|
|
511
|
+
}));
|
|
512
|
+
}
|
|
525
513
|
const summary = document.createElement("div");
|
|
526
514
|
summary.className = "parameter-structured-summary";
|
|
527
515
|
const count = document.createElement("span");
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
: "Structured value";
|
|
516
|
+
if (schema.kind === "array" && Array.isArray(draft)) uiText(count, "inspector.item-count", { count: draft.length });
|
|
517
|
+
else uiText(count, "inspector.structured-value");
|
|
531
518
|
summary.append(count);
|
|
532
|
-
shell.append(summary);
|
|
519
|
+
if (schema.kind === "array") shell.append(summary);
|
|
533
520
|
|
|
534
521
|
if (schema.kind === "array") {
|
|
535
522
|
const list = Array.isArray(draft) ? draft : [];
|
|
@@ -542,12 +529,12 @@ function structuredControl(entityId: string, parameter: Clip["inspector"][number
|
|
|
542
529
|
? recordDraftControl(schema.items, item, (next) => {
|
|
543
530
|
const current = Array.isArray(draft) ? draft : [];
|
|
544
531
|
draft = current.map((candidate, heldIndex) => heldIndex === index ? next : candidate);
|
|
545
|
-
|
|
532
|
+
save();
|
|
546
533
|
})
|
|
547
534
|
: scalarDraftControl(`${parameter.label} ${index + 1}`, schema.items, item, (next) => {
|
|
548
535
|
const current = Array.isArray(draft) ? draft : [];
|
|
549
536
|
draft = current.map((candidate, heldIndex) => heldIndex === index ? next : candidate);
|
|
550
|
-
|
|
537
|
+
save();
|
|
551
538
|
});
|
|
552
539
|
const actions = document.createElement("span");
|
|
553
540
|
actions.className = "parameter-list-actions";
|
|
@@ -557,28 +544,30 @@ function structuredControl(entityId: string, parameter: Clip["inspector"][number
|
|
|
557
544
|
reordered.splice(index + offset, 0, moving!);
|
|
558
545
|
draft = reordered;
|
|
559
546
|
render();
|
|
547
|
+
save();
|
|
560
548
|
};
|
|
561
549
|
const up = document.createElement("button");
|
|
562
550
|
up.type = "button";
|
|
563
551
|
up.textContent = "↑";
|
|
564
|
-
up
|
|
552
|
+
uiAttr(up, "title", "inspector.move-up");
|
|
565
553
|
up.disabled = index === 0;
|
|
566
554
|
up.addEventListener("click", () => move(-1));
|
|
567
555
|
const down = document.createElement("button");
|
|
568
556
|
down.type = "button";
|
|
569
557
|
down.textContent = "↓";
|
|
570
|
-
down
|
|
558
|
+
uiAttr(down, "title", "inspector.move-down");
|
|
571
559
|
down.disabled = index === list.length - 1;
|
|
572
560
|
down.addEventListener("click", () => move(1));
|
|
573
561
|
const remove = document.createElement("button");
|
|
574
562
|
remove.type = "button";
|
|
575
563
|
remove.innerHTML = icon("minus");
|
|
576
|
-
remove
|
|
564
|
+
uiAttr(remove, "title", "inspector.remove-item");
|
|
577
565
|
remove.disabled = schema.minItems !== undefined && list.length <= schema.minItems;
|
|
578
566
|
remove.addEventListener("click", () => {
|
|
579
567
|
const current = Array.isArray(draft) ? draft : [];
|
|
580
568
|
draft = current.filter((_, heldIndex) => heldIndex !== index);
|
|
581
569
|
render();
|
|
570
|
+
save();
|
|
582
571
|
});
|
|
583
572
|
actions.append(up, down, remove);
|
|
584
573
|
row.append(editor, actions);
|
|
@@ -588,7 +577,7 @@ function structuredControl(entityId: string, parameter: Clip["inspector"][number
|
|
|
588
577
|
} else {
|
|
589
578
|
shell.append(recordDraftControl(schema, draft, (next) => {
|
|
590
579
|
draft = next;
|
|
591
|
-
|
|
580
|
+
save();
|
|
592
581
|
}));
|
|
593
582
|
}
|
|
594
583
|
|
|
@@ -599,75 +588,87 @@ function structuredControl(entityId: string, parameter: Clip["inspector"][number
|
|
|
599
588
|
const add = document.createElement("button");
|
|
600
589
|
add.type = "button";
|
|
601
590
|
add.className = "parameter-structured-add";
|
|
602
|
-
add.innerHTML = `${icon("plus")}
|
|
591
|
+
add.innerHTML = `${icon("plus")}${uiLabel(schema.items.kind === "string" && schema.items.format === "color" ? "inspector.add-color" : "inspector.add-item")}`;
|
|
603
592
|
add.disabled = schema.maxItems !== undefined && list.length >= schema.maxItems;
|
|
604
593
|
add.addEventListener("click", () => {
|
|
605
594
|
const current = Array.isArray(draft) ? draft : [];
|
|
606
595
|
draft = [...current, blankValue(schema.items)];
|
|
607
596
|
render();
|
|
597
|
+
save();
|
|
608
598
|
});
|
|
609
599
|
footer.append(add);
|
|
610
600
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
reset.type = "button";
|
|
615
|
-
reset.textContent = "Reset";
|
|
616
|
-
reset.disabled = sameValue(draft, parameter.value);
|
|
617
|
-
reset.addEventListener("click", () => {
|
|
618
|
-
draft = structuredClone(parameter.value);
|
|
619
|
-
render();
|
|
620
|
-
});
|
|
621
|
-
const apply = document.createElement("button");
|
|
622
|
-
apply.type = "button";
|
|
623
|
-
apply.className = "primary";
|
|
624
|
-
apply.textContent = "Apply";
|
|
625
|
-
apply.addEventListener("click", () => commitControl(entityId, parameter, draft));
|
|
626
|
-
refreshDecisions = () => {
|
|
627
|
-
reset.disabled = sameValue(draft, parameter.value);
|
|
628
|
-
apply.disabled = reset.disabled || !valid();
|
|
629
|
-
};
|
|
630
|
-
refreshDecisions();
|
|
631
|
-
decisions.append(reset, apply);
|
|
632
|
-
footer.append(decisions);
|
|
633
|
-
shell.append(footer);
|
|
601
|
+
if (schema.kind === "array") shell.append(footer);
|
|
602
|
+
notice.hidden = sameValue(draft, parameter.value) || valid();
|
|
603
|
+
shell.append(notice);
|
|
634
604
|
};
|
|
635
605
|
render();
|
|
636
606
|
return shell;
|
|
637
607
|
}
|
|
638
608
|
|
|
639
|
-
function parameterControl(
|
|
609
|
+
function parameterControl(
|
|
610
|
+
entityId: string,
|
|
611
|
+
parameter: Clip["inspector"][number],
|
|
612
|
+
change?: (value: CanonicalValue) => void,
|
|
613
|
+
): HTMLElement {
|
|
614
|
+
const editable = parameter.edit !== undefined || change !== undefined;
|
|
615
|
+
const commit = change ?? ((value: CanonicalValue) => commitControl(entityId, parameter, value));
|
|
616
|
+
if (editable && parameter.control === "record" && parameter.schema !== undefined && parameterRecordVariants(parameter.schema).length) {
|
|
617
|
+
return structuredControl(entityId, parameter, commit);
|
|
618
|
+
}
|
|
640
619
|
const row = document.createElement("div");
|
|
641
|
-
row.className = `parameter-row parameter-editable control-${parameter.control}`;
|
|
620
|
+
row.className = `parameter-row ${!editable ? "parameter-readonly" : "parameter-editable"} control-${parameter.control}`;
|
|
642
621
|
const name = document.createElement("span");
|
|
643
622
|
name.className = "parameter-label";
|
|
644
623
|
name.textContent = parameter.label;
|
|
645
624
|
name.title = parameter.summary ?? parameter.label;
|
|
646
625
|
const right = document.createElement("span");
|
|
647
626
|
right.className = "parameter-right parameter-control";
|
|
627
|
+
if (!editable) {
|
|
628
|
+
const value = document.createElement("span");
|
|
629
|
+
value.className = "parameter-display";
|
|
630
|
+
let displayValue = textValue(parameter.value);
|
|
631
|
+
let unitLabel = parameter.unit;
|
|
632
|
+
if (parameter.control === "number") {
|
|
633
|
+
try {
|
|
634
|
+
const numeric = parameterNumber(change && parameter.value === null ? 0 : parameter.value, parameter.number);
|
|
635
|
+
displayValue = String(numeric.value);
|
|
636
|
+
unitLabel = numeric.suffix || parameter.unit;
|
|
637
|
+
} catch { /* Keep the actual value visible when it is not a scalar. */ }
|
|
638
|
+
} else if (parameter.control === "select") {
|
|
639
|
+
displayValue = parameter.options?.map(parameterOption).find(option => option.value === parameter.value)?.label ?? displayValue;
|
|
640
|
+
}
|
|
641
|
+
value.textContent = displayValue;
|
|
642
|
+
right.append(value);
|
|
643
|
+
if (unitLabel !== undefined) {
|
|
644
|
+
const unit = document.createElement("small"); unit.textContent = unitLabel; right.append(unit);
|
|
645
|
+
}
|
|
646
|
+
row.append(name, right);
|
|
647
|
+
return row;
|
|
648
|
+
}
|
|
648
649
|
let unitLabel = parameter.unit;
|
|
649
650
|
if (parameter.control === "select") {
|
|
650
|
-
right.append(selectControl(
|
|
651
|
+
right.append(selectControl(parameter, commit));
|
|
651
652
|
} else if (parameter.control === "color") {
|
|
652
653
|
right.append(colorValueControl(parameter.label, textValue(parameter.value), (next) => {
|
|
653
|
-
|
|
654
|
+
commit(next);
|
|
654
655
|
}));
|
|
655
656
|
if (parameter.swatches?.length) {
|
|
656
657
|
const palette = document.createElement("span"); palette.className = "parameter-swatches";
|
|
657
658
|
for (const color of parameter.swatches) {
|
|
658
659
|
const swatch = document.createElement("button"); swatch.type = "button";
|
|
659
|
-
swatch.style.backgroundColor = color; swatch.title = color; swatch
|
|
660
|
-
swatch.addEventListener("click", () =>
|
|
660
|
+
swatch.style.backgroundColor = color; swatch.title = color; uiAttr(swatch, "aria-label", "inspector.use-color", { color });
|
|
661
|
+
swatch.addEventListener("click", () => commit(color)); palette.append(swatch);
|
|
661
662
|
}
|
|
662
663
|
right.append(palette);
|
|
663
664
|
}
|
|
664
665
|
} else if (parameter.control === "list" || parameter.control === "record") {
|
|
665
|
-
right.append(structuredControl(entityId, parameter));
|
|
666
|
+
right.append(structuredControl(entityId, parameter, commit));
|
|
666
667
|
} else {
|
|
667
668
|
if (parameter.multiline && parameter.control === "text") {
|
|
668
669
|
const value = document.createElement("textarea"); value.className = "parameter-value parameter-multiline";
|
|
669
670
|
value.value = textValue(parameter.value); value.setAttribute("aria-label", parameter.label);
|
|
670
|
-
value.addEventListener("change", () =>
|
|
671
|
+
value.addEventListener("change", () => commit(value.value)); right.append(value);
|
|
671
672
|
row.append(name, right); return row;
|
|
672
673
|
}
|
|
673
674
|
const value = document.createElement("input");
|
|
@@ -678,8 +679,8 @@ function parameterControl(entityId: string, parameter: Clip["inspector"][number]
|
|
|
678
679
|
if (value.type === "checkbox") value.checked = parameter.value === true || parameter.value === "true";
|
|
679
680
|
else if (parameter.control === "number") {
|
|
680
681
|
try {
|
|
681
|
-
const numeric = parameterNumber(parameter.value, parameter.number);
|
|
682
|
-
value.type = "number"; value.inputMode = "decimal"; value.value = String(numeric.value);
|
|
682
|
+
const numeric = parameterNumber(change && parameter.value === null ? 0 : parameter.value, parameter.number);
|
|
683
|
+
value.type = "number"; value.inputMode = "decimal"; value.value = change && parameter.value === null ? "" : String(numeric.value);
|
|
683
684
|
const schema = parameter.schema?.kind === "number" ? parameter.schema : undefined;
|
|
684
685
|
const scale = parameter.number?.scale ?? 1;
|
|
685
686
|
const minimum = parameter.number?.minimum ?? (schema?.minimum === undefined ? undefined : schema.minimum * scale);
|
|
@@ -698,11 +699,12 @@ function parameterControl(entityId: string, parameter: Clip["inspector"][number]
|
|
|
698
699
|
if (!value.title) value.title = parameter.summary ?? parameter.label;
|
|
699
700
|
value.addEventListener("change", () => {
|
|
700
701
|
if (value.type === "checkbox") {
|
|
701
|
-
|
|
702
|
+
commit(value.checked);
|
|
702
703
|
} else if (parameter.control === "number") {
|
|
703
|
-
if (value.
|
|
704
|
+
if (change) commit(Number.isFinite(value.valueAsNumber) ? value.valueAsNumber : null);
|
|
705
|
+
else if (value.reportValidity()) commit(value.valueAsNumber);
|
|
704
706
|
} else {
|
|
705
|
-
|
|
707
|
+
commit(value.value);
|
|
706
708
|
}
|
|
707
709
|
});
|
|
708
710
|
right.append(value);
|
|
@@ -731,13 +733,13 @@ function parameterGroups(entityId: string, fields: readonly Clip["inspector"][nu
|
|
|
731
733
|
});
|
|
732
734
|
}
|
|
733
735
|
|
|
734
|
-
let parameterWriteState: "" | "
|
|
736
|
+
let parameterWriteState: "" | "common.saving" | "common.saved" | "common.failed" = "";
|
|
735
737
|
async function writeParameter(entityId: string, parameter: Clip["inspector"][number], replacement: CanonicalValue): Promise<void> {
|
|
736
738
|
const state = store.current();
|
|
737
739
|
if (state === undefined) return;
|
|
738
|
-
parameterWriteState = "
|
|
740
|
+
parameterWriteState = "common.saving";
|
|
739
741
|
status.title = "";
|
|
740
|
-
status
|
|
742
|
+
uiText(status, parameterWriteState);
|
|
741
743
|
status.className = "status saving";
|
|
742
744
|
try {
|
|
743
745
|
await applyStudioMutation({
|
|
@@ -747,15 +749,15 @@ async function writeParameter(entityId: string, parameter: Clip["inspector"][num
|
|
|
747
749
|
parameterId: parameter.id,
|
|
748
750
|
value: replacement,
|
|
749
751
|
});
|
|
750
|
-
parameterWriteState = "
|
|
751
|
-
status
|
|
752
|
+
parameterWriteState = "common.saved";
|
|
753
|
+
uiText(status, parameterWriteState);
|
|
752
754
|
status.className = "status saved";
|
|
753
755
|
} catch (error) {
|
|
754
756
|
// Validation and stale-revision rejections do not publish a new snapshot.
|
|
755
757
|
// Restore the accepted value just as a rejected compilation does.
|
|
756
758
|
restoreParameterControls(entityId);
|
|
757
|
-
parameterWriteState = "
|
|
758
|
-
status
|
|
759
|
+
parameterWriteState = "common.failed";
|
|
760
|
+
uiText(status, error instanceof Error ? "common.save-failed" : parameterWriteState);
|
|
759
761
|
status.className = "status error";
|
|
760
762
|
status.title = error instanceof Error ? error.message : String(error);
|
|
761
763
|
}
|
|
@@ -773,26 +775,26 @@ function renderInspector(snapshot: StudioSnapshot, clipId: string | undefined):
|
|
|
773
775
|
defaultWorkspaceHeading();
|
|
774
776
|
const fps = snapshot.space.frameRate.numerator / snapshot.space.frameRate.denominator;
|
|
775
777
|
inspector.replaceChildren(
|
|
776
|
-
|
|
777
|
-
property("
|
|
778
|
-
property("
|
|
779
|
-
property("
|
|
780
|
-
property("
|
|
778
|
+
uiGroup("inspector.project", [
|
|
779
|
+
property("inspector.author", snapshot.source.path, "property-code"),
|
|
780
|
+
property("inspector.run", snapshot.run.path, "property-code"),
|
|
781
|
+
property("inspector.sources", String(snapshot.source.files.length)),
|
|
782
|
+
property("inspector.tracks", String(snapshot.tracks.length), "property-number"),
|
|
781
783
|
]),
|
|
782
|
-
|
|
783
|
-
property("
|
|
784
|
-
property("
|
|
784
|
+
uiGroup("inspector.canvas", [
|
|
785
|
+
property("inspector.resolution", `${snapshot.space.canvasWidth} × ${snapshot.space.canvasHeight}`, "property-number"),
|
|
786
|
+
property("inspector.aspect-ratio", aspectRatio(snapshot.space.canvasWidth, snapshot.space.canvasHeight), "property-number"),
|
|
785
787
|
]),
|
|
786
|
-
|
|
787
|
-
property("
|
|
788
|
-
property("
|
|
789
|
-
property("
|
|
788
|
+
uiGroup("inspector.timeline", [
|
|
789
|
+
property("inspector.duration", `${snapshot.space.durationSec.toFixed(2)} s`, "property-number"),
|
|
790
|
+
property("inspector.frame-rate", `${fps.toFixed(Number.isInteger(fps) ? 0 : 2)} fps`, "property-number"),
|
|
791
|
+
property("inspector.frames", String(snapshot.space.frameCount), "property-number"),
|
|
790
792
|
]),
|
|
791
|
-
|
|
792
|
-
property("
|
|
793
|
+
uiGroup("inspector.build", [
|
|
794
|
+
property("inspector.targets", snapshot.run.targets
|
|
793
795
|
.map((target) => target.split("::output::").at(-1) ?? target)
|
|
794
796
|
.join(", ") || "—", "property-code"),
|
|
795
|
-
property("
|
|
797
|
+
property("inspector.candidates", String(snapshot.run.satisfactions.length), "property-number"),
|
|
796
798
|
]),
|
|
797
799
|
);
|
|
798
800
|
return;
|
|
@@ -802,7 +804,7 @@ function renderInspector(snapshot: StudioSnapshot, clipId: string | undefined):
|
|
|
802
804
|
defaultWorkspaceHeading();
|
|
803
805
|
const empty = document.createElement("div");
|
|
804
806
|
empty.className = "inspector-empty";
|
|
805
|
-
empty
|
|
807
|
+
uiText(empty, "inspector.empty");
|
|
806
808
|
inspector.replaceChildren(empty);
|
|
807
809
|
return;
|
|
808
810
|
}
|
|
@@ -813,17 +815,22 @@ function renderInspector(snapshot: StudioSnapshot, clipId: string | undefined):
|
|
|
813
815
|
|
|
814
816
|
const domainFields = clip.inspector.filter((field) => field.domain === activeDomain);
|
|
815
817
|
const pages = new Map<string, { readonly label: string; readonly fields: typeof domainFields }>();
|
|
816
|
-
|
|
817
|
-
|
|
818
|
+
const commonFields = domainFields.filter(field => field.page === undefined);
|
|
819
|
+
for (const field of domainFields.filter(field => field.page !== undefined)) {
|
|
820
|
+
const id = field.page!.id;
|
|
818
821
|
const page = pages.get(id) ?? { label: field.page?.label ?? "", fields: [] };
|
|
819
822
|
pages.set(id, { ...page, fields: [...page.fields, field] });
|
|
820
823
|
}
|
|
821
824
|
const pageIds = [...pages.keys()];
|
|
825
|
+
if (pageIds.length === 0) {
|
|
826
|
+
inspector.replaceChildren(...parameterGroups(clip.id, commonFields));
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
822
829
|
const memoryKey = `${clip.id}:${activeDomain}`;
|
|
823
830
|
const rememberedPage = inspectorPageByEntity.get(memoryKey);
|
|
824
831
|
const activePage = rememberedPage !== undefined && pages.has(rememberedPage) ? rememberedPage : pageIds[0]!;
|
|
825
832
|
inspectorPageByEntity.set(memoryKey, activePage);
|
|
826
|
-
const page = pages.get(activePage)
|
|
833
|
+
const page = pages.get(activePage);
|
|
827
834
|
const subtabs = document.createElement("div");
|
|
828
835
|
subtabs.className = "inspector-subtabs";
|
|
829
836
|
if (pageIds.length > 1) {
|
|
@@ -841,7 +848,7 @@ function renderInspector(snapshot: StudioSnapshot, clipId: string | undefined):
|
|
|
841
848
|
return button;
|
|
842
849
|
}));
|
|
843
850
|
}
|
|
844
|
-
inspector.replaceChildren(...(pageIds.length > 1 ? [subtabs] : []), ...parameterGroups(clip.id, page
|
|
851
|
+
inspector.replaceChildren(...(pageIds.length > 1 ? [subtabs] : []), ...parameterGroups(clip.id, [...commonFields, ...(page?.fields ?? [])]));
|
|
845
852
|
}
|
|
846
853
|
|
|
847
854
|
function renderSemanticInspector(snapshot: StudioSnapshot, segmentId: string): void {
|
|
@@ -850,7 +857,7 @@ function renderSemanticInspector(snapshot: StudioSnapshot, segmentId: string): v
|
|
|
850
857
|
defaultWorkspaceHeading();
|
|
851
858
|
const empty = document.createElement("div");
|
|
852
859
|
empty.className = "inspector-empty";
|
|
853
|
-
empty
|
|
860
|
+
uiText(empty, "inspector.empty");
|
|
854
861
|
inspector.replaceChildren(empty);
|
|
855
862
|
}
|
|
856
863
|
|
|
@@ -862,32 +869,36 @@ function semanticAnchorInspector(snapshot: StudioSnapshot, kind: "selection" | "
|
|
|
862
869
|
.map((handle) => ({ clip, handle })));
|
|
863
870
|
const current = kind === "selection" ? semantic?.selections.find((item) => item.id === id)
|
|
864
871
|
: semantic?.moments.find((item) => item.id === id);
|
|
865
|
-
if (!semantic || !current) return
|
|
866
|
-
const endpoints = "anchorId" in current ? [["
|
|
867
|
-
: [["
|
|
868
|
-
return
|
|
872
|
+
if (!semantic || !current) return uiGroup("inspector.timing", []);
|
|
873
|
+
const endpoints: readonly (readonly [Message, string])[] = "anchorId" in current ? [["inspector.moment", current.anchorId]]
|
|
874
|
+
: [["inspector.start", current.startAnchorId], ["inspector.end", current.endAnchorId]];
|
|
875
|
+
return uiGroup("inspector.semantic-anchors", endpoints.map(([label, anchorId]) => {
|
|
869
876
|
const anchor = semantic.anchors.find((item) => item.id === anchorId)!;
|
|
870
|
-
const describe = (item: typeof anchor) => {
|
|
877
|
+
const describe = (node: Element, item: typeof anchor) => {
|
|
871
878
|
const word = semantic.tokens.find((token) => token.id === item.tokenId)?.text;
|
|
872
|
-
|
|
879
|
+
uiText(node, `inspector.anchor.${item.kind}`, { detail: `${word ? ` · ${word}` : ""}${item.segmentId ? ` · ${item.segmentId}` : ""}` });
|
|
873
880
|
};
|
|
874
881
|
const candidates = semantic.anchors.filter((item) => item.frame === anchor.frame).flatMap((item) => {
|
|
875
882
|
const target: SemanticTarget = "anchorId" in current ? { kind: "moment", anchorId: item.id }
|
|
876
|
-
: { kind: "selection", startAnchorId: label === "
|
|
877
|
-
endAnchorId: label === "
|
|
883
|
+
: { kind: "selection", startAnchorId: label === "inspector.start" ? item.id : current.startAnchorId,
|
|
884
|
+
endAnchorId: label === "inspector.end" ? item.id : current.endAnchorId };
|
|
878
885
|
const owner = consumers.find(({ handle }) => semanticGestureSpan(semantic.anchors, handle, target) !== undefined);
|
|
879
886
|
return owner ? [{ item, target, ...owner }] : [];
|
|
880
887
|
});
|
|
881
|
-
if (candidates.length < 2)
|
|
888
|
+
if (candidates.length < 2) {
|
|
889
|
+
const row = property(label!, "");
|
|
890
|
+
describe(row.querySelector("strong")!, anchor);
|
|
891
|
+
return row;
|
|
892
|
+
}
|
|
882
893
|
const row = document.createElement("label");
|
|
883
894
|
row.className = "property";
|
|
884
895
|
const name = document.createElement("span");
|
|
885
|
-
name
|
|
896
|
+
uiText(name, label!);
|
|
886
897
|
const control = document.createElement("select");
|
|
887
898
|
control.className = "parameter-value";
|
|
888
|
-
control
|
|
899
|
+
uiAttr(control, "aria-label", label === "inspector.start" ? "inspector.start-anchor" : label === "inspector.end" ? "inspector.end-anchor" : "inspector.moment-anchor");
|
|
889
900
|
for (const { item } of candidates) {
|
|
890
|
-
const option = document.createElement("option"); option.value = item.id; option
|
|
901
|
+
const option = document.createElement("option"); option.value = item.id; describe(option, item);
|
|
891
902
|
control.append(option);
|
|
892
903
|
}
|
|
893
904
|
control.value = anchorId!;
|
|
@@ -896,14 +907,14 @@ function semanticAnchorInspector(snapshot: StudioSnapshot, kind: "selection" | "
|
|
|
896
907
|
const span = semanticGestureSpan(semantic.anchors, choice.handle, choice.target)!;
|
|
897
908
|
const temporal = choice.handle.temporal!;
|
|
898
909
|
control.disabled = true;
|
|
899
|
-
status
|
|
910
|
+
uiText(status, "common.saving"); status.className = "status saving";
|
|
900
911
|
void applyStudioMutation({ type: "timeline.adjust", revision: snapshot.revision,
|
|
901
912
|
entityId: choice.clip.id, gesture: choice.handle.gesture,
|
|
902
913
|
target: temporal.kind === "instant" ? { kind: "instant", frame: span.startFrame, semantic: choice.target }
|
|
903
914
|
: { kind: "window", ...span, semantic: choice.target },
|
|
904
|
-
}).then(() => { status
|
|
915
|
+
}).then(() => { uiText(status, "common.saved"); status.className = "status saved"; })
|
|
905
916
|
.catch((error: unknown) => {
|
|
906
|
-
control.value = anchorId!; status
|
|
917
|
+
control.value = anchorId!; uiText(status, "common.save-failed"); status.className = "status error";
|
|
907
918
|
status.title = error instanceof Error ? error.message : String(error);
|
|
908
919
|
}).finally(() => { control.disabled = false; });
|
|
909
920
|
});
|
|
@@ -1060,6 +1071,7 @@ window.addEventListener("keydown", (event) => {
|
|
|
1060
1071
|
event.preventDefault();
|
|
1061
1072
|
return;
|
|
1062
1073
|
}
|
|
1074
|
+
if (shell.dataset.view === "comments" && ["-", "_", "=", "+", "\\", "f", "F"].includes(event.key)) return;
|
|
1063
1075
|
if (event.key === "-" || event.key === "_") {
|
|
1064
1076
|
timeline.zoomOut();
|
|
1065
1077
|
event.preventDefault();
|
|
@@ -1086,10 +1098,10 @@ window.addEventListener("keydown", (event) => {
|
|
|
1086
1098
|
});
|
|
1087
1099
|
|
|
1088
1100
|
function applySnapshot(snapshot: StudioSnapshot): void {
|
|
1089
|
-
failureView
|
|
1101
|
+
userText(failureView, "");
|
|
1090
1102
|
status.className = "status";
|
|
1091
1103
|
status.title = "";
|
|
1092
|
-
status
|
|
1104
|
+
userText(status, "");
|
|
1093
1105
|
renderMeta(snapshot);
|
|
1094
1106
|
library.show(snapshot);
|
|
1095
1107
|
store.load(snapshot);
|
|
@@ -1097,7 +1109,7 @@ function applySnapshot(snapshot: StudioSnapshot): void {
|
|
|
1097
1109
|
|
|
1098
1110
|
function applyFailure(failure: StudioFailure): void {
|
|
1099
1111
|
status.className = "status error";
|
|
1100
|
-
status
|
|
1112
|
+
uiText(status, "common.compile-failed");
|
|
1101
1113
|
failureView.textContent = failure.error;
|
|
1102
1114
|
if (failure.range !== undefined) code.highlight([{ range: failure.range, tone: "element" }], true);
|
|
1103
1115
|
// A parameter control changes immediately in the browser, but the source
|